Changeset 175


Ignore:
Timestamp:
May 7, 2010 11:28:17 PM (14 years ago)
Author:
jemian
Message:

rebuilt the 2D processing - now works successfully on all test files

File:
1 edited

Legend:

Unmodified
Added
Removed
  • dc2mda/src/pythonlib/dc2mda.py

    r174 r175  
    1717import struct
    1818import sys
    19 import mda
     19import traceback
    2020import data_types   # EPICS & IDL data types
     21import mda          # read/write support for MDA files
    2122
    2223
     
    217218        elif rank == 1:
    218219            # 1-D array
    219             myDict['count'] = count = s1
     220            myDict['count'] = s1
    220221            myDict['type'] = type = s2
    221222            myDict['nx'] = nx = s3
     
    225226            myDict['ny'] = ny = s2
    226227            myDict['type'] = type = s3
    227             myDict['count'] = count = s4  # total number of values
     228            myDict['count'] = s4  # total number of values
    228229        else:
    229230            msg = offsetHex + ": "
     
    245246                data = []
    246247                self.read_LONG(fp)  # another string length DWORD
    247                 for i in range(ny):
     248                for __i__ in range(ny):
    248249                    row = ""
    249                     for j in range(nx):
     250                    for __j__ in range(nx):
    250251                        c = fp.read(1)
    251252                        if ord(c) > 0:
     
    255256            else:
    256257                data = []
    257                 for i in range(nx):
     258                for __i__ in range(nx):
    258259                    data.append(self.read_BYTE(fp))
    259260        elif type == 2:          # INT
    260261            data = []
    261262            if rank == 2:
    262                 for i in range(ny):
     263                for __i__ in range(ny):
    263264                    row = []
    264                     for j in range(nx):
     265                    for __j__ in range(nx):
    265266                        if isIndexFile:
    266267                            row.append(self.read_INT(fp))
     
    269270                    data.append(row)
    270271            else:
    271                 for i in range(nx):
     272                for __i__ in range(nx):
    272273                    if isIndexFile:
    273274                        data.append(self.read_INT(fp))
     
    278279            data = []
    279280            if rank == 2:
    280                 for i in range(ny):
     281                for __i__ in range(ny):
    281282                    row = []
    282                     for j in range(nx):
     283                    for __j__ in range(nx):
    283284                        row.append(self.read_LONG(fp))
    284285                    data.append(row)
    285286            else:
    286                 for i in range(nx):
     287                for __i__ in range(nx):
    287288                    data.append(self.read_LONG(fp))
    288289        elif type == 4:          # FLOAT
    289290            data = []
    290291            if rank == 2:
    291                 for i in range(ny):
     292                for __i__ in range(ny):
    292293                    row = []
    293                     for j in range(nx):
     294                    for __j__ in range(nx):
    294295                        row.append(self.read_FLOAT(fp))
    295296                    data.append(row)
    296297            else:
    297                 for i in range(nx):
     298                for __i__ in range(nx):
    298299                    data.append(self.read_FLOAT(fp))
    299300        elif type == 5:          # DOUBLE
    300301            data = []
    301302            if rank == 2:
    302                 for i in range(ny):
     303                for __i__ in range(ny):
    303304                    row = []
    304                     for j in range(nx):
     305                    for __j__ in range(nx):
    305306                        row.append(self.read_DOUBLE(fp))
    306307                    data.append(row)
    307308            else:
    308                 for i in range(nx):
     309                for __i__ in range(nx):
    309310                    data.append(self.read_DOUBLE(fp))
    310311        elif type == 6:          # COMPLEX
     
    320321            elif rank == 1:
    321322                data = []
    322                 for i in range(nx):
     323                for __i__ in range(nx):
    323324                    data.append(self.read_STRING(fp,
    324325                         numChars=s4, strip=True, indexFile=isIndexFile))
     
    527528            name = records[i * 5 + 0]
    528529            qno = records[i * 5 + 1]
    529             keyList = ['x', 'y', 'image']
    530             for j in range(len(keyList)):
    531                 dict[keyList[j]] = records[i * 5 + 2 + j]['data']
    532530            keyList = ['PV inner scan', 'PV outer scan', 'file 1D data',
    533531                       'PV 1D scan positioner 1', 'PV 2D scan positioner 1',
     
    540538                dict[keyList[j]] = qno['data'][j]
    541539            #print 'DEBUG:', dict['2D scanno'], dict['1D scanno']
     540            #pprint.pprint(dict)
     541            keyList = ['x', 'y', 'image']
     542            for j in range(len(keyList)):
     543                dict[keyList[j]] = records[i * 5 + 2 + j]['data']
    542544            images.append(dict)
    543545        return images
     
    587589            dict['Scan data file name'] = strings[3]
    588590            dict['time'] = strings[4].split(".")[0].strip()
    589             dict['userID'] = strings[4].split(".")[1].strip()
     591            dict['userID'] = strings[4].split(".")[1].replace("User Name:", "", 1).strip()
    590592            dict['comment'] = strings[5]
    591593            seqno = records[recNum]['data']; recNum += 1
     
    650652        header['ourKeys'].append('time')
    651653        header['time'] = scan['time']
    652         for entry in scan['env']:
    653             header[entry['pv']] = (entry['description'], '', entry['value'], 0, 1)
     654        header.update( self.buildEnvMetadata(scan) )
    654655        # add metadata from the catcher file as "environment" data
    655         EPICS_datatype = 0
    656         envKeys = ['userID', 'version', 'comment', 'time']
    657         for i in range(len(envKeys)):
    658             key = envKeys[i]
    659             value = scan[key]
    660             pv = self.keyToPv(key)
    661             header[pv] =  (key, '', value, EPICS_datatype, 1)
     656        header.update(
     657            self.buildPvMetadata(
     658                'DBR_STRING',
     659                ['userID', 'version', 'comment', 'time'],
     660                scan)
     661        )
    662662        # strings
    663         envKeys = ['Plot title', 'Plot x label', 'Plot y label', 'Scan data file name', 'pv', 'filename']
    664         for i in range(len(envKeys)):
    665             key = envKeys[i]
    666             value = scan[key]
    667             pv = self.keyToPv(key)
    668             header[pv] =  (key, '', value, EPICS_datatype, 1)
    669         header['filename_short'] =  ('short file name', '', scan['filename'], EPICS_datatype, 1)
     663        header.update(
     664            self.buildPvMetadata(
     665                'DBR_STRING',
     666                ['Plot title', 'Plot x label', 'Plot y label',
     667                 'Scan data file name', 'pv', 'filename'],
     668                scan)
     669        )
     670        header['filename_short'] = (
     671            'short file name', '', scan['filename'], 0, 1)
    670672        # floats
    671         EPICS_datatype = data_types.EPICS_types_dict_REVERSE['DBR_CTRL_DOUBLE']
    672         envKeys = ['Y positioner value at given 2D scan number']
    673         for i in range(len(envKeys)):
    674             key = envKeys[i]
    675             value = scan[key]
    676             pv = self.keyToPv(key)
    677             header[pv] =  (key, '', [value], EPICS_datatype, 1)
     673        header.update(
     674            self.buildPvMetadata(
     675                'DBR_CTRL_DOUBLE',
     676                ['Y positioner value at given 2D scan number'],
     677                scan)
     678        )
    678679        # ints
    679         EPICS_datatype = data_types.EPICS_types_dict_REVERSE['DBR_CTRL_LONG']
    680         envKeys = [
    681             '1D scan number, zero based',
    682             '1D scan starting reference case number',
    683             '2D scanning sequence number, Y loop index number',
    684             '2D scan number, zero based',
    685             '2D scanning indicator',
    686             '2D scan requested number of data points',
    687             '2D scan current acquired number'
    688         ]
    689         for i in range(len(envKeys)):
    690             key = envKeys[i]
    691             value = scan[key]
    692             pv = self.keyToPv(key)
    693             header[pv] =  (key, '', [value], EPICS_datatype, 1)
     680        header.update(
     681            self.buildPvMetadata(
     682                'DBR_CTRL_LONG',
     683                [
     684                    '1D scan number, zero based',
     685                    '1D scan starting reference case number',
     686                    '2D scanning sequence number, Y loop index number',
     687                    '2D scan number, zero based',
     688                    '2D scanning indicator',
     689                    '2D scan requested number of data points',
     690                    '2D scan current acquired number'
     691                ],
     692                scan)
     693        )
    694694        #------------ 1-D scan data_1D
    695695        data_1D = mda.scanDim()
     
    751751        print
    752752
    753     def collateFrameSets(self, images):
    754         '''
    755             Gather the frame sets from the acquired images
    756             @param images: entries from records in data.file.image.
    757             Determine how many different 2-D scans (frameSets) we have.
    758             That is the number of MDA files we will create.
    759             @return: list frameSet dictionaries
     753    def collateFrameSets(self, dcFile, scans, index, images):
     754        '''
     755            Used by 2D processing to identify sets of images 
     756            (different detectors with the same 2D scan number)
     757            @return: dictionary of image frameSets
     758            @note: one MDA file will be written for each frameSet
    760759        '''
    761760        frameSets = {}
    762         for image_index in range(len(images)):
    763             image = images[image_index]
    764             # index of 1st 1D scan (X data)
    765             n1D = image['1D scanno'] - image['ny']
    766             n2D = image['2D scanno']        # one-based
    767             if not n2D in frameSets.keys():
    768                 frameSets[n2D] = {
    769                         'first 1D scan num': n1D,
    770                         '2D scan num': n2D,
    771                         'detector pv list': [],
    772                         '1D scan list' : range(n1D, image['1D scanno']),
    773                         'image frame list': []
    774                     }
    775             detPv1 = image['PV Detector 1']
    776             frameSets[n2D]['detector pv list'].append(detPv1)
    777             frameSets[n2D]['image frame list'].append(image_index)
    778         if DC2MDA_DEBUG: pprint.pprint(frameSets)
     761        for imageNum in range(len(images)):
     762            image = images[imageNum]
     763            #len_inner = len(image['image'][0])
     764            len_outer = len(image['image'])
     765            if len_outer > 1:
     766                scan2DNum = image['2D scanno']
     767                if not scan2DNum in frameSets.keys():
     768                    scan1DNum = image['1D scanno'] - image['ny']
     769                    if (scan1DNum >= 0) and (scan1DNum < len(scans)):
     770                        frame = frameSets[scan2DNum] = {}
     771                        frame['2D scan number'] = scan2DNum
     772                        frame['x'] = image['x']
     773                        frame['y'] = image['y']
     774                        frame['imageList'] = [imageNum]
     775                        frame['image1'] = imageNum
     776                        frame['scan1'] = scan1DNum
     777                else:
     778                    frame = frameSets[scan2DNum]
     779                    if (frame['x'] == image['x']) and (frame['y'] == image['y']):
     780                        frame['imageList'].append(imageNum)
    779781        return frameSets
     782   
     783    def buildEnvMetadata(self, scan):
     784        '''
     785            build a dictionary of metadata for
     786            the MDA file from the scan environment
     787        '''
     788        result = {}
     789        for entry in scan['env']:  # env variables from first 1-D scan
     790            result[entry['pv']] = (entry['description'], '', entry['value'], 0, 1)
     791        return result
     792
     793    def buildPvMetadata(self, EPICS_type_str, keyList, db):
     794        '''
     795            build a dictionary of metadata for the MDA file
     796            by harvesting specific additional items
     797        '''
     798        EPICS_datatype = data_types.EPICS_types_dict_REVERSE[EPICS_type_str]
     799        result = {}
     800        for i in range(len(keyList)):
     801            key = keyList[i]
     802            if EPICS_type_str == 'DBR_STRING':
     803                value = db[key]
     804            else:
     805                value = [db[key]]   # anything not a string must be in a list
     806            pv = self.keyToPv(key)
     807            result[pv] =  (key, '', value, EPICS_datatype, 1)
     808        return result
     809
    780810
    781811    def translateMDA_2D(self, dcFile, indexFile, imageFile):
     
    796826        images = self.parseImageRecords(self.readFileRecords(imageFile))
    797827   
    798         # Determine how many different 2-D scans (frameSets) we have.
    799         # That is the number of MDA files we will create.
    800         frameSets = self.collateFrameSets(images)
    801    
     828        # group images by same 2D scan number
     829        frameSets = self.collateFrameSets(dcFile, scans, index, images)
     830
    802831        for frameNum in frameSets:
    803             frameSet = frameSets[frameNum]
     832            frame = frameSets[frameNum]
    804833            outputMdaFileName = self.FILE_TEMPLATE_2D % (dcFile, frameNum)
    805             scan1Num = frameSet['1D scan list'][0]
    806             if (scan1Num < 0) or (scan1Num >= len(scans)):
    807                 fmt = "(%d: Requested data from missing 1D scan #%d)"
    808                 msg = fmt % (frameNum, scan1Num)
    809                 print msg,
    810                 continue
    811             scan1 = scans[scan1Num]
    812             image1Num = frameSet['image frame list'][0]
    813             image1 = images[image1Num]
     834            scan1 = scans[frame['scan1']]
     835            image1 = images[frame['image1']]
     836            scanLen_inner = len(frame['x'])
     837            scanLen_outer = len(frame['y'])
    814838            #-------------------------- MDA header ------------------------
    815839            header = {
     
    820844            header['version'] = MDA_VERSION_FOR_MDAEXPLORER   # float
    821845            header['rank'] = 2
    822             header['scan_number'] = frameSet['2D scan num']   # one-based
    823             scan1_len = image1['nx']
    824             scan2_len = image1['ny']
    825             header['dimensions'] = [scan2_len, scan1_len]
     846            header['scan_number'] = frame['2D scan number']   # one-based
     847            header['dimensions'] = [scanLen_outer, scanLen_inner]
    826848            header['isRegular'] = 1       # What else could it be but regular?
    827849            header['ourKeys'] = ['sampleEntry', 'filename', 'version', 'scan_number',
     
    830852            header['time'] = scan1['time']
    831853            #----- environment data
    832             for entry in scan1['env']:  # env variables from first 1-D scan
    833                 header[entry['pv']] = (entry['description'], '', entry['value'], 0, 1)
     854            header.update( self.buildEnvMetadata(scan1) )
    834855            # add metadata from the catcher files as "environment" data
    835             envKeys = ['userID', 'version', 'comment', 'time']
    836             for i in range(len(envKeys)):
    837                 key = envKeys[i]
    838                 value = scan1[key]
    839                 pv = self.keyToPv(key)
    840                 header[pv] =  (key, '', value, 0, 1)
    841             envKeys = ['nx', 'ny']
    842             for i in range(len(envKeys)):
    843                 key = envKeys[i]
    844                 value = [image1[key]]   # integers must be in lists
    845                 pv = self.keyToPv(key)
    846                 header[pv] =  (key, '', value, data_types.EPICS_types_dict_REVERSE['DBR_CTRL_LONG'], 1)
    847             del pv, key, value, i, envKeys
    848             header['filename_short'] =  ('short file name', '', scan1['Scan data file name'], 0, 1)
    849             header['filename_long'] =  ('long file name', '', index['filename'], 0, 1)
     856            header.update(
     857                self.buildPvMetadata(
     858                    'DBR_STRING',
     859                    ['userID', 'version', 'comment', 'time'],
     860                    scan1)
     861            )
     862            header.update(
     863                self.buildPvMetadata('DBR_CTRL_LONG', ['nx', 'ny'], image1)
     864            )
     865
     866            items = [
     867                 ['filename_short', 'short file name', 'Scan data file name'],
     868                 ['filename_long', 'long file name','filename'],
     869                 ['filename_1D_data', '1-D data file name', 'file 1D data'],
     870                 ['PV_outer_scan', 'outer scan record PV', 'PV outer scan'],
     871                 ['PV_inner_scan', 'inner scan record PV', 'PV inner scan'],
     872                 ['PV_detector_1', 'detector 1 PV', 'PV Detector 1'],
     873                 ['PV_pos_1_inner', 'positioner 1 PV, inner scan', 'PV 2D scan positioner 1'],
     874                 ['PV_pos_1_outer', 'positioner 1 PV, outer scan','PV 1D scan positioner 1']
     875            ]
     876            for row in items:
     877                key, desc, value = row
     878                header[key] = (desc, '', value, 0, 1)
     879
    850880            header['filename_current'] =  ('current file name', '', dcFile, 0, 1)
    851             header['filename_1D_data'] =  ('1-D data file name', '', image1['file 1D data'], 0, 1)
    852881            header['filename_2D_data'] =  ('2-D data file name', '', imageFile, 0, 1)
    853             header['PV_outer_scan'] =  ('outer scan record PV', '', image1['PV outer scan'], 0, 1)
    854             header['PV_inner_scan'] =  ('inner scan record PV', '', image1['PV inner scan'], 0, 1)
    855             header['PV_detector_1'] =  ('detector 1 PV', '', image1['PV Detector 1'], 0, 1)
    856             header['PV_pos_1_inner'] =  ('positioner 1 PV, inner scan', '', image1['PV 2D scan positioner 1'], 0, 1)
    857             header['PV_pos_1_outer'] =  ('positioner 1 PV, outer scan', '', image1['PV 1D scan positioner 1'], 0, 1)
    858882            #-------------------------- MDA outer scan ------------------------
    859883            outer = mda.scanDim()
     
    861885            outer.dim = 1
    862886            outer.name = image1['PV outer scan']
    863             outer.npts = scan2_len              # requested
    864             outer.curr_pt = len(image1['y'])    # actual number of points
    865             if outer.curr_pt > outer.npts:
    866                 outer.npts = outer.curr_pt
     887            outer.npts = len(image1['image'])          # physical size
     888            outer.curr_pt = len(image1['y'])    # actual number of points (same)
    867889            outer.time = scan1['time']
    868890            # .........
     
    875897            pos.unit = ''
    876898            pos.step_mode = "LINEAR"
    877             pos.data = image1['y']
     899            pos.data = frame['y']
     900            for __i__ in xrange(len(frame['y']), outer.npts):
     901                pos.data.append(0.0)
    878902            outer.p.append(pos)
    879903            # ..........
    880             outer.d = []
     904            outer.d = []    # no detector data in outer scan
    881905            # ..........
    882906            outer.np = len(outer.p)
     
    887911            inner.dim = 2
    888912            inner.name = image1['PV inner scan']
    889             inner.npts = scan1_len        # requested
     913            inner.npts = len(image1['image'][0])          # physical size        # requested
     914            inner.curr_pt = len(frame['x'])    # actual number of points
    890915            inner.time = scan1['time']
    891             inner.curr_pt = len(image1['x'])    # actual number of points
    892             interruptedScanLength = None                  # for interrupted scans
    893             if inner.curr_pt > inner.npts:
    894                 inner.npts = inner.curr_pt
    895916            # ..........
    896             for posNum in range(len(scan1['pos'])):
    897                 if scan1['pos'][posNum]['defined'] == 1:
    898                     pos = mda.scanPositioner()
    899                     pos.number = posNum
    900                     pos.fieldName = mda.posName(posNum)  # scan-record field (e.g., 'P1') 
    901                     pos.name = scan1['pos'][posNum]['pv']
    902                     pos.desc = scan1['pos'][posNum]['description']
    903                     pos.unit = scan1['pos'][posNum]['units']
    904                     pos.step_mode = "LINEAR"
    905                     pos.data = []
    906                     # Why not use the image data instead?
    907                     for scanNum in frameSet['1D scan list']:
    908                         # what about array length on inner scans?
    909                         #fmt = "scan1Num: %d"
    910                         #fmt += "  posNum: %d"
    911                         #fmt += "  scan1Num: %d"
    912                         #fmt += "  inner.npts: %d"
    913                         #fmt += "  inner.curr_pt: %d"
    914                         #fmt += "  len(posData): %d"
    915                         posData = scans[scanNum]['pos'][posNum]['data']
    916                         #print "scanNum:", scanNum, "  posNum:", posNum,  "  len(posData):", len(posData)
    917                         if len(posData) < inner.curr_pt:
    918                             if (interruptedScanLength == None) or (len(posData) < interruptedScanLength):
    919                                 interruptedScanLength = len(posData)
    920                             # must pad the data array, use zeroes
    921                             padLength = inner.curr_pt - len(posData)
    922                             moreData = [0]*padLength
    923                             posData.extend(moreData)
    924                         #print fmt % (scan1Num, posNum, scan1Num, inner.npts, inner.curr_pt, len(posData))
    925                         pos.data.append(posData)
    926                         #print "len(posData):", len(posData), "  len(pos.data):", len(pos.data)
    927                     inner.p.append(pos)
    928                     del pos
     917            # only 1 positioner in inner scan is saved in catcher image file
     918            pos = mda.scanPositioner()
     919            pos.number = 0
     920            pos.fieldName = 'P1'  # scan-record field (e.g., 'P1') 
     921            pos.name = image1['PV 1D scan positioner 1']
     922            pos.desc = pos.name
     923            pos.unit = ''
     924            pos.step_mode = "LINEAR"
     925            pos.data = []
     926            for __i__ in range(outer.npts):   # need copies of the same thing
     927                pos.data.append(frame['x'])
     928            inner.p.append(pos)
    929929            # ..........
    930             for detNum in range(len(scan1['det'])):
    931                 if scan1['det'][detNum]['defined'] == 1:
    932                     det = mda.scanDetector()
    933                     det.number = detNum
    934                     det.fieldName = mda.detName(detNum)  # scan-record field (e.g., 'D01')
    935                     det.name = scan1['det'][detNum]['pv']
    936                     det.desc = scan1['det'][detNum]['description']
    937                     det.unit = scan1['det'][detNum]['units']
    938                     det.data = []
    939                     for scanNum in frameSet['1D scan list']:
    940                         detData = scans[scanNum]['det'][detNum]['data']
    941                         if len(detData) < inner.curr_pt:
    942                             # must pad the data array, use zeroes
    943                             padLength = inner.curr_pt - len(detData)
    944                             moreData = [0]*padLength
    945                             detData.extend(moreData)
    946                         det.data.append(detData)
    947                     inner.d.append(det)
     930            for imgNum in frame['imageList']:
     931                image = images[imgNum]
     932                det = mda.scanDetector()
     933                det.number = image['2D detector number']
     934                det.fieldName = mda.detName(det.number)  # such as 'D01'
     935                det.name = scan1['det'][det.number]['pv']
     936                det.desc = scan1['det'][det.number]['description']
     937                det.unit = scan1['det'][det.number]['units']
     938                det.data = image['image']
     939                for __i__ in xrange(len(det.data), outer.npts):
     940                    det.data.append([0]*inner.npts)
     941                inner.d.append(det)
    948942            # ..........
    949943            inner.np = len(inner.p)
     
    957951                print frameNum,
    958952            except:
    959                 type, value, traceback = sys.exc_info()
    960                 print "Error with frame %d in call mda.writeMDA()\n%s\n%s\n%s" % (frameNum, type, value, traceback)
     953                print traceback.print_exc()
     954                #type, value, traceback = sys.exc_info()
     955                #fmt = "Error with frame %d in call mda.writeMDA()\n%s\n%s\n%s"
     956                #print fmt % (frameNum, type, value, traceback)
    961957        pass
    962958
     
    988984
    989985if __name__ == '__main__':
    990     print SVN_ID
    991986    file = TEST_1D_DC_FILE    # for code development
    992987    file = TEST_2D_DC_FILE    # for code development
    993988    if len(sys.argv) == 2:
    994         file = sys.argv[1]
     989        file = sys.argv[1].strip()
    995990    elif not os.path.exists(file):
    996991        print "usage: ", sys.argv[0], " path/to/data_catcher_file"
Note: See TracChangeset for help on using the changeset viewer.