Changeset 2817 for trunk/GSASIIIO.py


Ignore:
Timestamp:
May 2, 2017 10:03:41 AM (8 years ago)
Author:
vondreele
Message:

major revision - move all importers to GSASIIobj & make them independent of wx so they can be used in a scripting environment.
Still to move are PhaseSelector?, and 3 BlockSelector? dialogs

File:
1 edited

Legend:

Unmodified
Added
Removed
  • TabularUnified trunk/GSASIIIO.py

    r2777 r2817  
    223223    mainsizer = wx.BoxSizer(wx.VERTICAL)
    224224    h,w = Image.shape[:2]
    225     mainsizer.Add(wx.StaticText(dlg,wx.ID_ANY,
    226                                 'File '+str(filename)+'\nImage size: '+str(h)+' x '+str(w)),
    227                   0,wx.ALIGN_LEFT|wx.ALL, 2)
     225    mainsizer.Add(wx.StaticText(dlg,wx.ID_ANY,'File '+str(filename)+'\nImage size: '+str(h)+' x '+str(w)),
     226        0,wx.ALIGN_LEFT|wx.ALL, 2)
    228227   
    229228    vsizer = wx.BoxSizer(wx.HORIZONTAL)
    230229    vsizer.Add(wx.StaticText(dlg,wx.ID_ANY,u'Wavelength (\xC5) '),
    231                0,wx.ALIGN_LEFT|wx.ALL, 2)
     230        0,wx.ALIGN_LEFT|wx.ALL, 2)
    232231    wdgt = G2G.ValidatedTxtCtrl(dlg,Data,'wavelength')
    233232    vsizer.Add(wdgt)
     
    236235    vsizer = wx.BoxSizer(wx.HORIZONTAL)
    237236    vsizer.Add(wx.StaticText(dlg,wx.ID_ANY,u'Pixel size (\xb5m). Width '),
    238                0,wx.ALIGN_LEFT|wx.ALL, 2)
     237        0,wx.ALIGN_LEFT|wx.ALL, 2)
    239238    wdgt = G2G.ValidatedTxtCtrl(dlg,Data['pixelSize'],0,
    240239                                 size=(50,-1))
    241240    vsizer.Add(wdgt)
    242     vsizer.Add(wx.StaticText(dlg,wx.ID_ANY,u'  Height '),
    243                wx.ALIGN_LEFT|wx.ALL, 2)
    244     wdgt = G2G.ValidatedTxtCtrl(dlg,Data['pixelSize'],1,
    245                                  size=(50,-1))
     241    vsizer.Add(wx.StaticText(dlg,wx.ID_ANY,u'  Height '),wx.ALIGN_LEFT|wx.ALL, 2)
     242    wdgt = G2G.ValidatedTxtCtrl(dlg,Data['pixelSize'],1,size=(50,-1))
    246243    vsizer.Add(wdgt)
    247244    mainsizer.Add(vsizer,0,wx.ALIGN_LEFT|wx.ALL, 2)
     
    249246    vsizer = wx.BoxSizer(wx.HORIZONTAL)
    250247    vsizer.Add(wx.StaticText(dlg,wx.ID_ANY,u'Sample to detector (mm) '),
    251                0,wx.ALIGN_LEFT|wx.ALL, 2)
     248        0,wx.ALIGN_LEFT|wx.ALL, 2)
    252249    wdgt = G2G.ValidatedTxtCtrl(dlg,Data,'distance')
    253250    vsizer.Add(wdgt)
     
    256253    vsizer = wx.BoxSizer(wx.HORIZONTAL)
    257254    vsizer.Add(wx.StaticText(dlg,wx.ID_ANY,u'Beam center (pixels). X = '),
    258                0,wx.ALIGN_LEFT|wx.ALL, 2)
    259     wdgt = G2G.ValidatedTxtCtrl(dlg,Data['center'],0,
    260                                  size=(75,-1))
     255        0,wx.ALIGN_LEFT|wx.ALL, 2)
     256    wdgt = G2G.ValidatedTxtCtrl(dlg,Data['center'],0,size=(75,-1))
    261257    vsizer.Add(wdgt)
    262     vsizer.Add(wx.StaticText(dlg,wx.ID_ANY,u'  Y = '),
    263                wx.ALIGN_LEFT|wx.ALL, 2)
    264     wdgt = G2G.ValidatedTxtCtrl(dlg,Data['center'],1,
    265                                  size=(75,-1))
     258    vsizer.Add(wx.StaticText(dlg,wx.ID_ANY,u'  Y = '),wx.ALIGN_LEFT|wx.ALL, 2)
     259    wdgt = G2G.ValidatedTxtCtrl(dlg,Data['center'],1,size=(75,-1))
    266260    vsizer.Add(wdgt)
    267261    mainsizer.Add(vsizer,0,wx.ALIGN_LEFT|wx.ALL, 2)
     
    269263    vsizer = wx.BoxSizer(wx.HORIZONTAL)
    270264    vsizer.Add(wx.StaticText(dlg,wx.ID_ANY,u'Comments '),
    271                0,wx.ALIGN_LEFT|wx.ALL, 2)
     265        0,wx.ALIGN_LEFT|wx.ALL, 2)
    272266    wdgt = G2G.ValidatedTxtCtrl(dlg,Comments,0,size=(250,-1))
    273267    vsizer.Add(wdgt)
     
    549543    return
    550544   
    551 # should get moved to importer when ready to test
    552 def GetEdfData(filename,imageOnly=False):   
    553     'Read European detector data edf file'
    554     if not imageOnly:
    555         print 'Read European detector data edf file: ',filename
    556     File = open(filename,'rb')
    557     fileSize = os.stat(filename).st_size
    558     head = File.read(3072)
    559     lines = head.split('\n')
    560     sizexy = [0,0]
    561     pixSize = [154,154]     #Pixium4700?
    562     cent = [0,0]
    563     wave = 1.54187  #default <CuKa>
    564     dist = 1000.
    565     head = ['European detector data',]
    566     for line in lines:
    567         line = line.replace(';',' ').strip()
    568         fields = line.split()
    569         if 'Dim_1' in line:
    570             sizexy[0] = int(fields[2])
    571         elif 'Dim_2' in line:
    572             sizexy[1] = int(fields[2])
    573         elif 'DataType' in line:
    574             dType = fields[2]
    575         elif 'wavelength' in line:
    576             wave = float(fields[2])
    577         elif 'Size' in line:
    578             imSize = int(fields[2])
    579 #        elif 'DataType' in lines:
    580 #            dType = fields[2]
    581         elif 'pixel_size_x' in line:
    582             pixSize[0] = float(fields[2])
    583         elif 'pixel_size_y' in line:
    584             pixSize[1] = float(fields[2])
    585         elif 'beam_center_x' in line:
    586             cent[0] = float(fields[2])
    587         elif 'beam_center_y' in line:
    588             cent[1] = float(fields[2])
    589         elif 'refined_distance' in line:
    590             dist = float(fields[2])
    591         if line:
    592             head.append(line)
    593         else:   #blank line at end of header
    594             break 
    595     File.seek(fileSize-imSize)
    596     if dType == 'UnsignedShort':       
    597         image = np.array(np.frombuffer(File.read(imSize),dtype=np.int16),dtype=np.int32)
    598     else:
    599         image = np.array(np.frombuffer(File.read(imSize),dtype=np.int32),dtype=np.int32)
    600     image = np.reshape(image,(sizexy[1],sizexy[0]))
    601     data = {'pixelSize':pixSize,'wavelength':wave,'distance':dist,'center':cent,'size':sizexy}
    602     Npix = sizexy[0]*sizexy[1]
    603     File.close()   
    604     if imageOnly:
    605         return image
    606     else:
    607         return head,data,Npix,image
    608        
    609 # should get moved to importer when ready to test
    610 def GetRigaku(filename,imageOnly=False):
    611     'Read Rigaku R-Axis IV image file'
    612     import array as ar
    613     if not imageOnly:
    614         print 'Read Rigaku R-Axis IV file: ',filename   
    615     File = open(filename,'rb')
    616     fileSize = os.stat(filename).st_size
    617     Npix = (fileSize-6000)/2
    618     File.read(6000)
    619     head = ['Rigaku R-Axis IV detector data',]
    620     image = np.array(ar.array('H',File.read(fileSize-6000)),dtype=np.int32)
    621     print fileSize,image.shape
    622     print head
    623     if Npix == 9000000:
    624         sizexy = [3000,3000]
    625         pixSize = [100.,100.]       
    626     elif Npix == 2250000:
    627         sizexy = [1500,1500]
    628         pixSize = [200.,200.]
    629     else:
    630         sizexy = [6000,6000]
    631         pixSize = [50.,50.]
    632     image = np.reshape(image,(sizexy[1],sizexy[0]))       
    633     data = {'pixelSize':pixSize,'wavelength':1.5428,'distance':250.0,'center':[150.,150.],'size':sizexy} 
    634     File.close()   
    635     if imageOnly:
    636         return image
    637     else:
    638         return head,data,Npix,image
    639    
    640 # should get moved to importer when ready to test       
    641 def GetImgData(filename,imageOnly=False):
    642     'Read an ADSC image file'
    643     import array as ar
    644     if not imageOnly:
    645         print 'Read ADSC img file: ',filename
    646     File = open(filename,'rb')
    647     head = File.read(511)
    648     lines = head.split('\n')
    649     head = []
    650     center = [0,0]
    651     for line in lines[1:-2]:
    652         line = line.strip()[:-1]
    653         if line:
    654             if 'SIZE1' in line:
    655                 size = int(line.split('=')[1])
    656                 Npix = size*size
    657             elif 'WAVELENGTH' in line:
    658                 wave = float(line.split('=')[1])
    659             elif 'BIN' in line:
    660                 if line.split('=')[1] == '2x2':
    661                     pixel=(102,102)
    662                 else:
    663                     pixel = (51,51)
    664             elif 'DISTANCE' in line:
    665                 distance = float(line.split('=')[1])
    666             elif 'CENTER_X' in line:
    667                 center[0] = float(line.split('=')[1])
    668             elif 'CENTER_Y' in line:
    669                 center[1] = float(line.split('=')[1])
    670             head.append(line)
    671     data = {'pixelSize':pixel,'wavelength':wave,'distance':distance,'center':center,'size':[size,size]}
    672     image = []
    673     pos = 512
    674     File.seek(pos)
    675     image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
    676     image = np.reshape(image,(size,size))
    677 #    image = np.zeros(shape=(size,size),dtype=np.int32)   
    678 #    while row < size:
    679 #        File.seek(pos)
    680 #        line = ar.array('H',File.read(2*size))
    681 #        image[row] = np.asarray(line)
    682 #        row += 1
    683 #        pos += 2*size
    684     File.close()
    685     if imageOnly:
    686         return image
    687     else:
    688         return lines[1:-2],data,Npix,image
    689        
    690 # should get moved to importer when ready to test
    691 def GetMAR345Data(filename,imageOnly=False):
    692     'Read a MAR-345 image plate image'
    693     try:
    694         import pack_f as pf
    695     except:
    696         msg = wx.MessageDialog(None, message="Unable to load the GSAS MAR image decompression, pack_f",
    697                                caption="Import Error",
    698                                style=wx.ICON_ERROR | wx.OK | wx.STAY_ON_TOP)
    699         msg.ShowModal()
    700         return None,None,None,None
    701 
    702     if not imageOnly:
    703         print 'Read Mar345 file: ',filename
    704     File = open(filename,'rb')
    705     head = File.read(4095)
    706     lines = head[128:].split('\n')
    707     head = []
    708     for line in lines:
    709         line = line.strip()
    710         if 'PIXEL' in line:
    711             values = line.split()
    712             pixel = (int(values[2]),int(values[4]))     #in microns
    713         elif 'WAVELENGTH' in line:
    714             wave = float(line.split()[1])
    715         elif 'DISTANCE' in line:
    716             distance = float(line.split()[1])           #in mm
    717             if not distance:
    718                 distance = 500.
    719         elif 'CENTER' in line:
    720             values = line.split()
    721             center = [float(values[2])/10.,float(values[4])/10.]    #make in mm from pixels
    722         if line:
    723             head.append(line)
    724     data = {'pixelSize':pixel,'wavelength':wave,'distance':distance,'center':center}
    725     for line in head:
    726         if 'FORMAT' in line[0:6]:
    727             items = line.split()
    728             sizex = int(items[1])
    729             Npix = int(items[3])
    730             sizey = int(Npix/sizex)
    731     pos = 4096
    732     data['size'] = [sizex,sizey]
    733     File.seek(pos)
    734     line = File.read(8)
    735     while 'CCP4' not in line:       #get past overflow list for now
    736         line = File.read(8)
    737         pos += 8
    738     pos += 37
    739     File.seek(pos)
    740     raw = File.read()
    741     File.close()
    742     image = np.zeros(shape=(sizex,sizey),dtype=np.int32)
    743    
    744     image = np.flipud(pf.pack_f(len(raw),raw,sizex,sizey,image).T)  #transpose to get it right way around & flip
    745     if imageOnly:
    746         return image
    747     else:
    748         return head,data,Npix,image
    749        
    750545def ProjFileOpen(G2frame,showProvenance=True):
    751546    'Read a GSAS-II project file and load into the G2 data tree'
     
    913708            if nOcc:
    914709                Aname += '(%d)'%(nOcc)
    915         Sample = G2pdG.SetDefaultSample()       #set as Debye-Scherrer
     710        Sample = G2obj.SetDefaultSample()       #set as Debye-Scherrer
    916711        Sample['Gonio. radius'] = data['distance']
    917712        Sample['Omega'] = data['GonioAngles'][0]
     
    1116911            grfile.close()
    1117912            print ' G(R) saved to: ',grfilename
    1118            
    1119            
    1120            
    1121913   
    1122914def PeakListSave(G2frame,file,peaks):
     
    1155947    print 'index peak list saved'
    1156948   
    1157 def SetNewPhase(Name='New Phase',SGData=None,cell=None,Super=None):
    1158     '''Create a new phase dict with default values for various parameters
    1159 
    1160     :param str Name: Name for new Phase
    1161 
    1162     :param dict SGData: space group data from :func:`GSASIIspc:SpcGroup`;
    1163       defaults to data for P 1
    1164 
    1165     :param list cell: unit cell parameter list; defaults to
    1166       [1.0,1.0,1.0,90.,90,90.,1.]
    1167 
    1168     '''
    1169     if SGData is None: SGData = G2spc.SpcGroup('P 1')[1]
    1170     if cell is None: cell=[1.0,1.0,1.0,90.,90,90.,1.]
    1171     phaseData = {
    1172         'ranId':ran.randint(0,sys.maxint),
    1173         'General':{
    1174             'Name':Name,
    1175             'Type':'nuclear',
    1176             'Modulated':False,
    1177             'AtomPtrs':[3,1,7,9],
    1178             'SGData':SGData,
    1179             'Cell':[False,]+cell,
    1180             'Pawley dmin':1.0,
    1181             'Data plot type':'None',
    1182             'SH Texture':{
    1183                 'Order':0,
    1184                 'Model':'cylindrical',
    1185                 'Sample omega':[False,0.0],
    1186                 'Sample chi':[False,0.0],
    1187                 'Sample phi':[False,0.0],
    1188                 'SH Coeff':[False,{}],
    1189                 'SHShow':False,
    1190                 'PFhkl':[0,0,1],
    1191                 'PFxyz':[0,0,1],
    1192                 'PlotType':'Pole figure',
    1193                 'Penalty':[['',],0.1,False,1.0]}},
    1194         'Atoms':[],
    1195         'Drawing':{},
    1196         'Histograms':{},
    1197         'Pawley ref':[],
    1198         'RBModels':{},
    1199         }
    1200     if Super and Super.get('Use',False):
    1201         phaseData['General'].update({'Modulated':True,'Super':True,'SuperSg':Super['ssSymb']})
    1202         phaseData['General']['SSGData'] = G2spc.SSpcGroup(SGData,Super['ssSymb'])
    1203         phaseData['General']['SuperVec'] = [Super['ModVec'],False,Super['maxH']]
    1204 
    1205     return phaseData
    1206        
    1207949class MultipleChoicesDialog(wx.Dialog):
    1208950    '''A dialog that offers a series of choices, each with a
     
    13951137#   not used directly, only by subclassing
    13961138######################################################################
    1397 try:
    1398     E,SGData = G2spc.SpcGroup('P 1') # data structure for default space group
    1399 except: # errors on doc build
    1400     SGData = None
    1401 P1SGData = SGData
    1402 ######################################################################
    1403 class ImportBaseclass(object):
    1404     '''Defines a base class for the reading of input files (diffraction
    1405     data, coordinates,...). See :ref:`Writing a Import Routine<Import_routines>`
    1406     for an explanation on how to use a subclass of this class.
     1139def BlockSelector(ChoiceList, ParentFrame=None,title='Select a block',
     1140    size=None, header='Block Selector',useCancel=True):
     1141    ''' Provide a wx dialog to select a block if the file contains more
     1142    than one set of data and one must be selected
    14071143    '''
    1408     class ImportException(Exception):
    1409         '''Defines an Exception that is used when an import routine hits an expected error,
    1410         usually in .Reader.
    1411 
    1412         Good practice is that the Reader should define a value in self.errors that
    1413         tells the user some information about what is wrong with their file.         
    1414         '''
    1415         pass
     1144    if useCancel:
     1145        dlg = wx.SingleChoiceDialog(
     1146            ParentFrame,title, header,ChoiceList)
     1147    else:
     1148        dlg = wx.SingleChoiceDialog(
     1149            ParentFrame,title, header,ChoiceList,
     1150            style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER|wx.OK|wx.CENTRE)
     1151    if size: dlg.SetSize(size)
     1152    dlg.CenterOnParent()
     1153    if dlg.ShowModal() == wx.ID_OK:
     1154        sel = dlg.GetSelection()
     1155        return sel
     1156    else:
     1157        return None
     1158    dlg.Destroy()
     1159
     1160def MultipleBlockSelector(ChoiceList, ParentFrame=None,
     1161    title='Select a block',size=None, header='Block Selector'):
     1162    '''Provide a wx dialog to select a block of data if the
     1163    file contains more than one set of data and one must be
     1164    selected.
     1165
     1166    :returns: a list of the selected blocks
     1167    '''
     1168    dlg = wx.MultiChoiceDialog(ParentFrame,title, header,ChoiceList+['Select all'],
     1169        wx.CHOICEDLG_STYLE)
     1170    dlg.CenterOnScreen()
     1171    if size: dlg.SetSize(size)
     1172    if dlg.ShowModal() == wx.ID_OK:
     1173        sel = dlg.GetSelections()
     1174    else:
     1175        return []
     1176    dlg.Destroy()
     1177    selected = []
     1178    if len(ChoiceList) in sel:
     1179        return range(len(ChoiceList))
     1180    else:
     1181        return sel
     1182    return selected
     1183
     1184def MultipleChoicesSelector(choicelist, headinglist, ParentFrame=None, **kwargs):
     1185    '''A modal dialog that offers a series of choices, each with a title and a wx.Choice
     1186    widget. Typical input:
    14161187   
    1417     UseReader = True  # in __init__ set value of self.UseReader to False to skip use of current importer
    1418     def __init__(self,formatName,longFormatName=None,
    1419                  extensionlist=[],strictExtension=False,):
    1420         self.formatName = formatName # short string naming file type
    1421         if longFormatName: # longer string naming file type
    1422             self.longFormatName = longFormatName
    1423         else:
    1424             self.longFormatName = formatName
    1425         # define extensions that are allowed for the file type
    1426         # for windows, remove any extensions that are duplicate, as case is ignored
    1427         if sys.platform == 'windows' and extensionlist:
    1428             extensionlist = list(set([s.lower() for s in extensionlist]))
    1429         self.extensionlist = extensionlist
    1430         # If strictExtension is True, the file will not be read, unless
    1431         # the extension matches one in the extensionlist
    1432         self.strictExtension = strictExtension
    1433         self.errors = ''
    1434         self.warnings = ''
    1435         # used for readers that will use multiple passes to read
    1436         # more than one data block
    1437         self.repeat = False
    1438         self.selections = []
    1439         self.repeatcount = 0
    1440         self.readfilename = '?'
    1441         #print 'created',self.__class__
    1442 
    1443     def ReInitialize(self):
    1444         'Reinitialize the Reader to initial settings'
    1445         self.errors = ''
    1446         self.warnings = ''
    1447         self.repeat = False
    1448         self.repeatcount = 0
    1449         self.readfilename = '?'
    1450 
    1451     def BlockSelector(self, ChoiceList, ParentFrame=None,title='Select a block',
    1452         size=None, header='Block Selector',useCancel=True):
    1453         ''' Provide a wx dialog to select a block if the file contains more
    1454         than one set of data and one must be selected
    1455         '''
    1456         if useCancel:
    1457             dlg = wx.SingleChoiceDialog(
    1458                 ParentFrame,title, header,ChoiceList)
    1459         else:
    1460             dlg = wx.SingleChoiceDialog(
    1461                 ParentFrame,title, header,ChoiceList,
    1462                 style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER|wx.OK|wx.CENTRE)
    1463         if size: dlg.SetSize(size)
    1464         dlg.CenterOnParent()
    1465         if dlg.ShowModal() == wx.ID_OK:
    1466             sel = dlg.GetSelection()
    1467             return sel
    1468         else:
    1469             return None
    1470         dlg.Destroy()
    1471 
    1472     def MultipleBlockSelector(self, ChoiceList, ParentFrame=None,
    1473         title='Select a block',size=None, header='Block Selector'):
    1474         '''Provide a wx dialog to select a block of data if the
    1475         file contains more than one set of data and one must be
    1476         selected.
    1477 
    1478         :returns: a list of the selected blocks
    1479         '''
    1480         dlg = wx.MultiChoiceDialog(ParentFrame,title, header,ChoiceList+['Select all'],
    1481             wx.CHOICEDLG_STYLE)
    1482         dlg.CenterOnScreen()
    1483         if size: dlg.SetSize(size)
    1484         if dlg.ShowModal() == wx.ID_OK:
    1485             sel = dlg.GetSelections()
    1486         else:
    1487             return []
    1488         dlg.Destroy()
    1489         selected = []
    1490         if len(ChoiceList) in sel:
    1491             return range(len(ChoiceList))
    1492         else:
    1493             return sel
    1494         return selected
    1495 
    1496     def MultipleChoicesDialog(self, choicelist, headinglist, ParentFrame=None, **kwargs):
    1497         '''A modal dialog that offers a series of choices, each with a title and a wx.Choice
    1498         widget. Typical input:
    1499        
    1500            * choicelist=[ ('a','b','c'), ('test1','test2'),('no choice',)]
    1501            
    1502            * headinglist = [ 'select a, b or c', 'select 1 of 2', 'No option here']
    1503            
    1504         optional keyword parameters are: head (window title) and title
    1505         returns a list of selected indicies for each choice (or None)
    1506         '''
    1507         result = None
    1508         dlg = MultipleChoicesDialog(choicelist,headinglist,
    1509             parent=ParentFrame, **kwargs)         
    1510         dlg.CenterOnParent()
    1511         if dlg.ShowModal() == wx.ID_OK:
    1512             result = dlg.chosen
    1513         dlg.Destroy()
    1514         return result
    1515 
    1516     def ShowBusy(self):
    1517         wx.BeginBusyCursor()
     1188       * choicelist=[ ('a','b','c'), ('test1','test2'),('no choice',)]
     1189       
     1190       * headinglist = [ 'select a, b or c', 'select 1 of 2', 'No option here']
     1191       
     1192    optional keyword parameters are: head (window title) and title
     1193    returns a list of selected indicies for each choice (or None)
     1194    '''
     1195    result = None
     1196    dlg = MultipleChoicesDialog(choicelist,headinglist,
     1197        parent=ParentFrame, **kwargs)         
     1198    dlg.CenterOnParent()
     1199    if dlg.ShowModal() == wx.ID_OK:
     1200        result = dlg.chosen
     1201    dlg.Destroy()
     1202    return result
     1203
     1204def PhaseSelector(self, ChoiceList, ParentFrame=None,
     1205    title='Select a phase', size=None,header='Phase Selector'):
     1206    ''' Provide a wx dialog to select a phase if the file contains more
     1207    than one phase
     1208    '''
     1209    return BlockSelector(ChoiceList,ParentFrame,title,
     1210        size,header)
     1211
     1212def ShowBusy():
     1213    wx.BeginBusyCursor()
    15181214#        wx.Yield() # make it happen now!
    15191215
    1520     def DoneBusy(self):
    1521         wx.EndBusyCursor()
    1522         wx.Yield() # make it happen now!
    1523        
    1524 #    def Reader(self, filename, filepointer, ParentFrame=None, **unused):
    1525 #        '''This method must be supplied in the child class to read the file.
    1526 #        if the read fails either return False or raise an Exception
    1527 #        preferably of type ImportException.
    1528 #        '''
    1529 #        #start reading
    1530 #        raise ImportException("Error occurred while...")
    1531 #        self.errors += "Hint for user on why the error occur
    1532 #        return False # if an error occurs
    1533 #        return True # if read OK
    1534 
    1535     def ExtensionValidator(self, filename):
    1536         '''This methods checks if the file has the correct extension
    1537         Return False if this filename will not be supported by this reader
    1538         Return True if the extension matches the list supplied by the reader
    1539         Return None if the reader allows un-registered extensions
    1540         '''
    1541         if filename:
    1542             ext = os.path.splitext(filename)[1]
    1543             if sys.platform == 'windows': ext = ext.lower()
    1544             if ext in self.extensionlist: return True
    1545             if self.strictExtension: return False
    1546         return None
    1547 
    1548     def ContentsValidator(self, filepointer):
    1549         '''This routine will attempt to determine if the file can be read
    1550         with the current format.
    1551         This will typically be overridden with a method that
    1552         takes a quick scan of [some of]
    1553         the file contents to do a "sanity" check if the file
    1554         appears to match the selected format.
    1555         Expected to be called via self.Validator()
    1556         '''
    1557         #filepointer.seek(0) # rewind the file pointer
    1558         return True
    1559 
    1560     def CIFValidator(self, filepointer):
    1561         '''A :meth:`ContentsValidator` for use to validate CIF files.
    1562         '''
    1563         for i,l in enumerate(filepointer):
    1564             if i >= 1000: return True
    1565             '''Encountered only blank lines or comments in first 1000
    1566             lines. This is unlikely, but assume it is CIF anyway, since we are
    1567             even less likely to find a file with nothing but hashes and
    1568             blank lines'''
    1569             line = l.strip()
    1570             if len(line) == 0: # ignore blank lines
    1571                 continue
    1572             elif line.startswith('#'): # ignore comments
    1573                 continue
    1574             elif line.startswith('data_'): # on the right track, accept this file
    1575                 return True
    1576             else: # found something invalid
    1577                 self.errors = 'line '+str(i+1)+' contains unexpected data:\n'
    1578                 if all([ord(c) < 128 and ord(c) != 0 for c in str(l)]): # show only if ASCII
    1579                     self.errors += '  '+str(l)
    1580                 else:
    1581                     self.errors += '  (binary)'
    1582                 self.errors += '\n  Note: a CIF should only have blank lines or comments before'
    1583                 self.errors += '\n        a data_ statement begins a block.'
    1584                 return False
    1585 
    1586 ######################################################################
    1587 class ImportPhase(ImportBaseclass):
    1588     '''Defines a base class for the reading of files with coordinates
    1589 
    1590     Objects constructed that subclass this (in import/G2phase_*.py etc.) will be used
    1591     in :meth:`GSASII.GSASII.OnImportPhase`.
    1592     See :ref:`Writing a Import Routine<Import_Routines>`
    1593     for an explanation on how to use this class.
    1594 
    1595     '''
    1596     def __init__(self,formatName,longFormatName=None,extensionlist=[],
    1597         strictExtension=False,):
    1598         # call parent __init__
    1599         ImportBaseclass.__init__(self,formatName,longFormatName,
    1600             extensionlist,strictExtension)
    1601         self.Phase = None # a phase must be created with G2IO.SetNewPhase in the Reader
    1602         self.Constraints = None
    1603 
    1604     def PhaseSelector(self, ChoiceList, ParentFrame=None,
    1605         title='Select a phase', size=None,header='Phase Selector'):
    1606         ''' Provide a wx dialog to select a phase if the file contains more
    1607         than one phase
    1608         '''
    1609         return self.BlockSelector(ChoiceList,ParentFrame,title,
    1610             size,header)
    1611 
    1612 ######################################################################
    1613 class ImportStructFactor(ImportBaseclass):
    1614     '''Defines a base class for the reading of files with tables
    1615     of structure factors.
    1616 
    1617     Structure factors are read with a call to :meth:`GSASII.GSASII.OnImportSfact`
    1618     which in turn calls :meth:`GSASII.GSASII.OnImportGeneric`, which calls
    1619     methods :meth:`ExtensionValidator`, :meth:`ContentsValidator` and
    1620     :meth:`Reader`.
    1621 
    1622     See :ref:`Writing a Import Routine<Import_Routines>`
    1623     for an explanation on how to use import classes in general. The specifics
    1624     for reading a structure factor histogram require that
    1625     the ``Reader()`` routine in the import
    1626     class need to do only a few things: It
    1627     should load :attr:`RefDict` item ``'RefList'`` with the reflection list,
    1628     and set :attr:`Parameters` with the instrument parameters
    1629     (initialized with :meth:`InitParameters` and set with :meth:`UpdateParameters`).
    1630     '''
    1631     def __init__(self,formatName,longFormatName=None,extensionlist=[],
    1632         strictExtension=False,):
    1633         ImportBaseclass.__init__(self,formatName,longFormatName,
    1634             extensionlist,strictExtension)
    1635 
    1636         # define contents of Structure Factor entry
    1637         self.Parameters = []
    1638         'self.Parameters is a list with two dicts for data parameter settings'
    1639         self.InitParameters()
    1640         self.RefDict = {'RefList':[],'FF':{},'Super':0}
    1641         self.Banks = []             #for multi bank data (usually TOF)
    1642         '''self.RefDict is a dict containing the reflection information, as read from the file.
    1643         Item 'RefList' contains the reflection information. See the
    1644         :ref:`Single Crystal Reflection Data Structure<XtalRefl_table>`
    1645         for the contents of each row. Dict element 'FF'
    1646         contains the form factor values for each element type; if this entry
    1647         is left as initialized (an empty list) it will be initialized as needed later.
    1648         '''
    1649     def ReInitialize(self):
    1650         'Reinitialize the Reader to initial settings'
    1651         ImportBaseclass.ReInitialize(self)
    1652         self.InitParameters()
    1653         self.Banks = []             #for multi bank data (usually TOF)
    1654         self.RefDict = {'RefList':[],'FF':{},'Super':0}
    1655        
    1656     def InitParameters(self):
    1657         'initialize the instrument parameters structure'
    1658         Lambda = 0.70926
    1659         HistType = 'SXC'
    1660         self.Parameters = [{'Type':[HistType,HistType], # create the structure
    1661                             'Lam':[Lambda,Lambda]
    1662                             }, {}]
    1663         'Parameters is a list with two dicts for data parameter settings'
    1664 
    1665     def UpdateParameters(self,Type=None,Wave=None):
    1666         'Revise the instrument parameters'
    1667         if Type is not None:
    1668             self.Parameters[0]['Type'] = [Type,Type]
    1669         if Wave is not None:
    1670             self.Parameters[0]['Lam'] = [Wave,Wave]           
    1671                        
    1672 ######################################################################
    1673 class ImportPowderData(ImportBaseclass):
    1674     '''Defines a base class for the reading of files with powder data.
    1675 
    1676     Objects constructed that subclass this (in import/G2pwd_*.py etc.) will be used
    1677     in :meth:`GSASII.GSASII.OnImportPowder`.
    1678     See :ref:`Writing a Import Routine<Import_Routines>`
    1679     for an explanation on how to use this class.
    1680     '''
    1681     def __init__(self,formatName,longFormatName=None,
    1682         extensionlist=[],strictExtension=False,):
    1683         ImportBaseclass.__init__(self,formatName,longFormatName,
    1684             extensionlist,strictExtension)
    1685         self.clockWd = None  # used in TOF
    1686         self.ReInitialize()
    1687        
    1688     def ReInitialize(self):
    1689         'Reinitialize the Reader to initial settings'
    1690         ImportBaseclass.ReInitialize(self)
    1691         self.powderentry = ['',None,None] #  (filename,Pos,Bank)
    1692         self.powderdata = [] # Powder dataset
    1693         '''A powder data set is a list with items [x,y,w,yc,yb,yd]:
    1694                 np.array(x), # x-axis values
    1695                 np.array(y), # powder pattern intensities
    1696                 np.array(w), # 1/sig(intensity)^2 values (weights)
    1697                 np.array(yc), # calc. intensities (zero)
    1698                 np.array(yb), # calc. background (zero)
    1699                 np.array(yd), # obs-calc profiles
    1700         '''                           
    1701         self.comments = []
    1702         self.idstring = ''
    1703         self.Sample = G2pdG.SetDefaultSample() # default sample parameters
    1704         self.Controls = {}  # items to be placed in top-level Controls
    1705         self.GSAS = None     # used in TOF
    1706         self.repeat_instparm = True # Should a parm file be
    1707         #                             used for multiple histograms?
    1708         self.instparm = None # name hint from file of instparm to use
    1709         self.instfile = '' # full path name to instrument parameter file
    1710         self.instbank = '' # inst parm bank number
    1711         self.instmsg = ''  # a label that gets printed to show
    1712                            # where instrument parameters are from
    1713         self.numbanks = 1
    1714         self.instdict = {} # place items here that will be transferred to the instrument parameters
    1715         self.pwdparms = {} # place parameters that are transferred directly to the tree
    1716                            # here (typically from an existing GPX file)
    1717 ######################################################################
    1718 class ImportSmallAngleData(ImportBaseclass):
    1719     '''Defines a base class for the reading of files with small angle data.
    1720     See :ref:`Writing a Import Routine<Import_Routines>`
    1721     for an explanation on how to use this class.
    1722     '''
    1723     def __init__(self,formatName,longFormatName=None,extensionlist=[],
    1724         strictExtension=False,):
    1725            
    1726         ImportBaseclass.__init__(self,formatName,longFormatName,extensionlist,
    1727             strictExtension)
    1728         self.ReInitialize()
    1729        
    1730     def ReInitialize(self):
    1731         'Reinitialize the Reader to initial settings'
    1732         ImportBaseclass.ReInitialize(self)
    1733         self.smallangleentry = ['',None,None] #  (filename,Pos,Bank)
    1734         self.smallangledata = [] # SASD dataset
    1735         '''A small angle data set is a list with items [x,y,w,yc,yd]:
    1736                 np.array(x), # x-axis values
    1737                 np.array(y), # powder pattern intensities
    1738                 np.array(w), # 1/sig(intensity)^2 values (weights)
    1739                 np.array(yc), # calc. intensities (zero)
    1740                 np.array(yd), # obs-calc profiles
    1741                 np.array(yb), # preset bkg
    1742         '''                           
    1743         self.comments = []
    1744         self.idstring = ''
    1745         self.Sample = G2pdG.SetDefaultSample()
    1746         self.GSAS = None     # used in TOF
    1747         self.clockWd = None  # used in TOF
    1748         self.numbanks = 1
    1749         self.instdict = {} # place items here that will be transferred to the instrument parameters
    1750 
    1751 ######################################################################
    1752 class ImportReflectometryData(ImportBaseclass):
    1753     '''Defines a base class for the reading of files with reflectometry data.
    1754     See :ref:`Writing a Import Routine<Import_Routines>`
    1755     for an explanation on how to use this class.
    1756     '''
    1757     def __init__(self,formatName,longFormatName=None,extensionlist=[],
    1758         strictExtension=False,):
    1759            
    1760         ImportBaseclass.__init__(self,formatName,longFormatName,extensionlist,
    1761             strictExtension)
    1762         self.ReInitialize()
    1763        
    1764     def ReInitialize(self):
    1765         'Reinitialize the Reader to initial settings'
    1766         ImportBaseclass.ReInitialize(self)
    1767         self.reflectometryentry = ['',None,None] #  (filename,Pos,Bank)
    1768         self.reflectometrydata = [] # SASD dataset
    1769         '''A small angle data set is a list with items [x,y,w,yc,yd]:
    1770                 np.array(x), # x-axis values
    1771                 np.array(y), # powder pattern intensities
    1772                 np.array(w), # 1/sig(intensity)^2 values (weights)
    1773                 np.array(yc), # calc. intensities (zero)
    1774                 np.array(yd), # obs-calc profiles
    1775                 np.array(yb), # preset bkg
    1776         '''                           
    1777         self.comments = []
    1778         self.idstring = ''
    1779         self.Sample = G2pdG.SetDefaultSample()
    1780         self.GSAS = None     # used in TOF
    1781         self.clockWd = None  # used in TOF
    1782         self.numbanks = 1
    1783         self.instdict = {} # place items here that will be transferred to the instrument parameters
    1784 
    1785 ######################################################################
    1786 class ImportPDFData(ImportBaseclass):
    1787     '''Defines a base class for the reading of files with PDF G(R) data.
    1788     See :ref:`Writing a Import Routine<Import_Routines>`
    1789     for an explanation on how to use this class.
    1790     '''
    1791     def __init__(self,formatName,longFormatName=None,extensionlist=[],
    1792         strictExtension=False,):
    1793            
    1794         ImportBaseclass.__init__(self,formatName,longFormatName,extensionlist,
    1795             strictExtension)
    1796         self.ReInitialize()
    1797        
    1798     def ReInitialize(self):
    1799         'Reinitialize the Reader to initial settings'
    1800         ImportBaseclass.ReInitialize(self)
    1801         self.pdfentry = ['',None,None] #  (filename,Pos,Bank)
    1802         self.pdfdata = [] # PDF G(R) dataset
    1803         '''A pdf g(r) data set is a list with items [x,y]:
    1804                 np.array(x), # r-axis values
    1805                 np.array(y), # pdf g(r)
    1806         '''                           
    1807         self.comments = []
    1808         self.idstring = ''
    1809         self.numbanks = 1
    1810 
    1811 ######################################################################
    1812 class ImportImage(ImportBaseclass):
    1813     '''Defines a base class for the reading of images
    1814 
    1815     Images are read in only these places:
    1816    
    1817       * Initial reading is typically done from a menu item
    1818         with a call to :meth:`GSASII.GSASII.OnImportImage`
    1819         which in turn calls :meth:`GSASII.GSASII.OnImportGeneric`. That calls
    1820         methods :meth:`ExtensionValidator`, :meth:`ContentsValidator` and
    1821         :meth:`Reader`. This returns a list of reader objects for each read image.
    1822 
    1823       * Images are read alternatively in :func:`GSASIIIO.ReadImages`, which puts image info
    1824         directly into the data tree.
    1825 
    1826       * Images are reloaded with :func:`GSASIIIO.GetImageData`.
    1827 
    1828     .. _Image_import_routines:
    1829 
    1830     When reading an image, the ``Reader()`` routine in the ImportImage class
    1831     should set:
    1832    
    1833       * :attr:`Comments`: a list of strings (str),
    1834       * :attr:`Npix`: the number of pixels in the image (int),
    1835       * :attr:`Image`: the actual image as a numpy array (np.array)
    1836       * :attr:`Data`: a dict defining image parameters (dict). Within this dict the following
    1837         data items are needed:
    1838        
    1839          * 'pixelSize': size of each pixel in microns (such as ``[200,200]``.
    1840          * 'wavelength': wavelength in Angstoms.
    1841          * 'distance': distance of detector from sample in cm.
    1842          * 'center': uncalibrated center of beam on detector (such as ``[204.8,204.8]``.
    1843          * 'size': size of image (such as ``[2048,2048]``).
    1844          * 'ImageTag': image number or other keyword used to retrieve image from
    1845            a multi-image data file (defaults to ``1`` if not specified).
    1846          * 'sumfile': holds sum image file name if a sum was produced from a multi image file
    1847 
    1848     optional data items:
    1849    
    1850       * :attr:`repeat`: set to True if there are additional images to
    1851         read in the file, False otherwise
    1852       * :attr:`repeatcount`: set to the number of the image.
    1853      
    1854     Note that the above is initialized with :meth:`InitParameters`.
    1855     (Also see :ref:`Writing a Import Routine<Import_Routines>`
    1856     for an explanation on how to use import classes in general.)
    1857     '''
    1858     def __init__(self,formatName,longFormatName=None,extensionlist=[],
    1859         strictExtension=False,):
    1860         ImportBaseclass.__init__(self,formatName,longFormatName,
    1861             extensionlist,strictExtension)
    1862         self.InitParameters()
    1863        
    1864     def ReInitialize(self):
    1865         'Reinitialize the Reader to initial settings -- not used at present'
    1866         ImportBaseclass.ReInitialize(self)
    1867         self.InitParameters()
    1868        
    1869     def InitParameters(self):
    1870         'initialize the instrument parameters structure'
    1871         self.Comments = ['No comments']
    1872         self.Data = {}
    1873         self.Npix = 0
    1874         self.Image = None
    1875         self.repeat = False
    1876         self.repeatcount = 1
    1877         self.sumfile = ''
    1878 
    1879     def LoadImage(self,ParentFrame,imagefile,imagetag=None):
    1880         '''Optionally, call this after reading in an image to load it into the tree.
    1881         This saves time by preventing a reread of the same information.
    1882         '''
    1883         if ParentFrame:
    1884             ParentFrame.ImageZ = self.Image   # store the image for plotting
    1885             ParentFrame.oldImagefile = imagefile # save the name of the last image file read
    1886             ParentFrame.oldImageTag = imagetag   # save the tag of the last image file read           
    1887 
     1216def DoneBusy():
     1217    wx.EndBusyCursor()
     1218    wx.Yield() # make it happen now!
    18881219######################################################################
    18891220def striphist(var,insChar=''):
     
    27872118    return Layer
    27882119
    2789 def ReadCIF(URLorFile):
    2790     '''Open a CIF, which may be specified as a file name or as a URL using PyCifRW
    2791     (from James Hester).
    2792     The open routine gets confused with DOS names that begin with a letter and colon
    2793     "C:\dir\" so this routine will try to open the passed name as a file and if that
    2794     fails, try it as a URL
    2795 
    2796     :param str URLorFile: string containing a URL or a file name. Code will try first
    2797       to open it as a file and then as a URL.
    2798 
    2799     :returns: a PyCifRW CIF object.
    2800     '''
    2801     import CifFile as cif # PyCifRW from James Hester
    2802 
    2803     # alternate approach:
    2804     #import urllib
    2805     #ciffile = 'file:'+urllib.pathname2url(filename)
    2806    
    2807     try:
    2808         fp = open(URLorFile,'r')
    2809         cf = cif.ReadCif(fp)
    2810         fp.close()
    2811         return cf
    2812     except IOError:
    2813         return cif.ReadCif(URLorFile)
    2814 
    28152120if __name__ == '__main__':
    28162121    import GSASII
Note: See TracChangeset for help on using the changeset viewer.