xzos / PyZDDE

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

zGetDetectorViewer not reading ZRD files or filter strings #78

Open crubster opened 6 years ago

crubster commented 6 years ago

zGetDetector Viewer returns ValueError: could not convert string to float: W2 (where W2 is a filter string from the detector .CFG file.

Looking through readDetectorViewerTextFile in zfileutils (around line 678) it looks like the function doesn't account for the fact that the text file outputted by the detector is changed when a ray database and a filter string are included in the detector config (see attached files after the "Smoothing" line, meaning that it attempts to read the filter string as the detector X position, causing the value error.

Edit: I'm using Zemax 13 in case you need a version number

detectorViewerFile.txt detectorViewerFile with ZRD and dfilter.txt

indranilsinharoy commented 6 years ago

Dear @crubster ,

I feel sorry to say that right now I'm not in a position to help as I don't have a Zemax key anymore. I'm trying to get one, but I don't know for sure when I will get. Without the ability to run tests with Zemax, I'm really uncomfortable to change the code. I'm really sorry.

crubster commented 6 years ago

Hi @indranilsinharoy ,

No worries, I made some quick and dirty changes myself that seems to have fixed it. Sorry to hear about the loss of your access to zemax- hope you get it back soon because pyZDDE is a great tool!

indranilsinharoy commented 6 years ago

Hi @crubster, Great to hear that you have fixed the issue you are facing, and thank you very much for your kind words. If possible, and if you desire, you could share your fix in these comments (or) send a pull request so that others facing similar issues could use your solution. (Please not that I'll not be able to actually honor the pull request till I'm able to test with Zemax). Thank you very much, again. Have a great day.

crubster commented 6 years ago

Hi @indranilsinharoy

I went into zfileutils and modified readDetectorViewerTextFile. I'm pretty new to github so I'll submit a pull request after I'm a bit clearer about what's going on but for now I'll just paste the modified function here (docstring removed for readability):

`

def readDetectorViewerTextFile(pyz, textFileName, displayData=False):

line_list = pyz._readLinesFromFile(pyz._openFile(textFileName))
# Meta data
detNumSurfNumPat = r'Detector\s*\d{1,4}\s*,\s*NSCG\sSurface\s*\d{1,4}'
detNumSurfNum = line_list[pyz._getFirstLineOfInterest(line_list, detNumSurfNumPat)]
detNum = int(pyz._re.search(r'\d{1,4}', detNumSurfNum.split(',')[0]).group())
nscgSurfNum = int(pyz._re.search(r'\d{1,4}', detNumSurfNum.split(',')[1]).group())
sizePixelsHitsPat = r'Size[0-9a-zA-Z\s\,\.]*Pixels[0-9a-zA-Z\s\,\.]*Total\sHits'
sizePixelsHits = line_list[pyz._getFirstLineOfInterest(line_list, sizePixelsHitsPat)]
sizeinfo, pixelsinfo , hitsinfo =  sizePixelsHits.split(',')
#note: width<-->rows<-->xPix;; height<-->cols<-->yPix 
width, height = [float(each) for each in pyz._re.findall(r'\d{1,4}\.\d{1,8}', sizeinfo)]
xPix, yPix =  [int(each) for each in pyz._re.findall(r'\d{1,6}', pixelsinfo)]
totHits = int(pyz._re.search(r'\d{1,10}', hitsinfo).group())

#peak irradiance and total power. only present for irradiance types
peakIrr, totPow = None, None 
peakIrrLineNum = pyz._getFirstLineOfInterest(line_list, 'Peak\sIrradiance')
if peakIrrLineNum:
    peakIrr = float(pyz._re.search(r'\d{1,4}\.\d{3,8}[Ee][-\+]\d{3}', 
                                   line_list[peakIrrLineNum]).group())
    totPow = float(pyz._re.search(r'\d{1,4}\.\d{3,8}[Ee][-\+]\d{3}', 
                                  line_list[peakIrrLineNum + 1]).group())

# section of text starting with 'Smoothing' (common to all)
smoothLineNum = pyz._getFirstLineOfInterest(line_list, 'Smoothing')
smooth = line_list[smoothLineNum].split(':')[1].strip()
smooth = 0 if smooth == 'None' else int(smooth)

# ray database and filter string
rayDB,dfilter = None,None
zrdLineNum = pyz._getFirstLineOfInterest(line_list, 'Ray\sDatabase')
if zrdLineNum:
    smoothLineNum+=1
    rayDB = line_list[smoothLineNum].split(':')[1].strip()
dfilterLineNum = pyz._getFirstLineOfInterest(line_list, 'Filter')
if dfilterLineNum:
    smoothLineNum+=1
    dfilter = line_list[smoothLineNum].split(':')[1].strip()

dType = line_list[smoothLineNum + 1].split(':')[1].strip()
posX = float(line_list[smoothLineNum + 2].split(':')[1].strip()) # 'Detector X'
posY = float(line_list[smoothLineNum + 3].split(':')[1].strip()) # 'Detector Y'
posZ = float(line_list[smoothLineNum + 4].split(':')[1].strip()) # 'Detector Z'
tiltX = float(line_list[smoothLineNum + 5].split(':')[1].strip())
tiltY = float(line_list[smoothLineNum + 6].split(':')[1].strip())
tiltZ = float(line_list[smoothLineNum + 7].split(':')[1].strip())
posUnits = line_list[smoothLineNum + 8].split(':')[1].strip()
units =  line_list[smoothLineNum + 9].split(':')[1].strip()

# determine "showAs" type 
rowPat = r'Row\s[0-9A-Za-z]*,\s*Y'
colPat = r'Column\s[0-9A-Za-z]*,\s*X'
rowColPat = '|'.join([rowPat, colPat])
showAsRowCol = pyz._getFirstLineOfInterest(line_list, rowColPat)

if showAsRowCol:
    # exatract specific meta data
    rowOrColPosLine = line_list[showAsRowCol]
    rowOrColIndicator = rowOrColPosLine.split(' ', 2)[0]
    assert rowOrColIndicator in ('Row', 'Column'), 'Error: Unable to determine '
    '"Row" or "Column" type for the cross section plot'
    rowOrCol = 'row' if rowOrColIndicator == 'Row' else 'col' 
    #rowColNum = line_list[showAsRowCol].split(' ', 2)[1]
    rowColNum = pyz._re.search(r'\d{1,4}|Center', rowOrColPosLine).group()
    rowColNum = 0 if rowColNum=='Center' else int(rowColNum)
    rowColVal = pyz._re.search(r'-?\d{1,4}\.\d{3,8}[Ee][-\+]\d{3}', 
                               rowOrColPosLine).group()
    rowColVal = float(rowColVal)

    if displayData:
        dataPat = (r'\s*(-?\d{1,4}\.\d{3,8}[Ee][-\+]\d{3}\s*)' + r'{{{num}}}'
                   .format(num=2)) # coordinate, value
        start_line = pyz._getFirstLineOfInterest(line_list, dataPat)
        data_mat = pyz._get2DList(line_list, start_line, yPix)
        data_matT = pyz._transpose2Dlist(data_mat)
        coordinate = data_matT[0]
        value = data_matT[1]
else:
    # note: it is still possible to 1d data here if `showAsRowCol` was corrupted
    rowOrCol, rowColNum, rowColVal = None, None, None # meta-data not available for 2D data
    if displayData:
        dataPat = (r'\s*\d{1,4}\s*(-?\d{1,4}\.\d{3,8}([Ee][-\+]\d{3,8})*\s*)' 
                   + r'{{{num}}}'.format(num=xPix))
        start_line = pyz._getFirstLineOfInterest(line_list, dataPat)
        gridData = pyz._get2DList(line_list, start_line, yPix, startCol=1)

deti = _co.namedtuple('dvwInfo', ['surfNum', 'detNum', 'width', 'height',
                                  'xPix', 'yPix', 'totHits', 'peakIrr',
                                  'totPow', 'smooth', 'rayDB','dfilter','dType', 'x', 'y', 
                                  'z', 'tiltX', 'tiltY', 'tiltZ', 'posUnits', 
                                  'units', 'rowOrCol', 'rowColNum', 'rowColVal'])
detInfo = deti(nscgSurfNum, detNum, width, height, xPix, yPix, totHits,
               peakIrr, totPow, smooth, rayDB, dfilter,dType, posX, posY, posZ, tiltX, 
               tiltY, tiltZ, posUnits, units, rowOrCol, rowColNum, rowColVal)

if displayData:
    if showAsRowCol:
        return (detInfo, coordinate, value)
    else:
        return (detInfo, gridData)
else:
    return detInfo

`

indranilsinharoy commented 6 years ago

@crubster Thanks a lot.