xzos / PyZDDE

Zemax/ OpticStudio Extension using Python
MIT License
154 stars 64 forks source link

zTiltDecenterElements() function returns `ValueError` when a thickness solve is present in the last surface #59

Closed indranilsinharoy closed 8 years ago

indranilsinharoy commented 8 years ago

The following ValueError is produced when there is a thickness solve present in the last surface:

[...]
In [3]: ln.zTiltDecenterElements(2, 24)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)

----> 1 ln.zTiltDecenterElements(2, 24)

C:\...\...\pyzdde\zdde.py in zTiltDecenterElements(self, firstSurf, lastSurf, xdec, ydec, xtilt, ytilt, ztilt, order, cbComment1, cbComment2, dummySemiDiaToZero)
[...]
> 10172         self.zSetSolve(dummy, self.SOLVE_SPAR_THICK, *solve)
[...]

C:\...\...\pyzdde\zdde.py in zSetSolve(self, surfNum, code, *solveData)
   5793                 elif solveData[0] == self.SOLVE_THICK_PICKUP: # (P)
   5794                     data = ('{:d},{:1.20g},{:1.20g},{:d}'
-> 5795                     .format(solveData[1], solveData[2], solveData[3], solveData[4])) # surface, scale-factor, offset, column
[...]

ValueError: Unknown format code 'd' for object of type 'float'
indranilsinharoy commented 8 years ago

There were two problems with the following line whose purpose was to transfer any solve (if present) in the thickness parameter of the last surface to the dummy surface after the second coordinate break:

self.zSetSolve(dummy, self.SOLVE_SPAR_THICK, *solve)

The root cause of both the problems (listed below) was the overly simplistic way the solve was being transferred above. The splattered sequence *solve consists of solvetype, param1, param2, param3, param4.

  1. Since param1 can take both integer and floating point values, Zemax formats it as a float even when param could represent a surface number (e.g. for pickup solvetype) which must be formatted as an integer when setting the solve on the dummy surface.
  2. When param1 represents a surface number, we need to check if the corresponding surface number would increase or remain same after inserting the first CB surface. If the param1 value is greater than the surface number of the first CB (whose value is value of the argument firstSurf), then we need to increment param1 by one because of the insertion of the first CB surface befor it.

The following code should fix it:

if solve[0] in {5, 7, 8, 9}: # param1 is a integer surface number
    param1 = int(solve[1]) if solve[1] < cb1 else int(solve[1]) + 1
else: # param1 is a floating value, or macro name
    param1 = solve[1]
self.zSetSolve(dummy, self.SOLVE_SPAR_THICK, solve[0], param1, solve[2],  solve[3], solve[4])
indranilsinharoy commented 8 years ago

Fixed in https://github.com/indranilsinharoy/PyZDDE/commit/5e52846bd8e89045068eaf883e6a18b8b0771d2e