source: trunk/GSASIIIO.py @ 670

Last change on this file since 670 was 670, checked in by toby, 10 years ago

add .GPX file name to window title

  • Property svn:keywords set to Date Author Revision URL Id
File size: 55.7 KB
Line 
1# -*- coding: utf-8 -*-
2"""GSASIIIO: functions for IO of data
3   Copyright: 2008, Robert B. Von Dreele (Argonne National Laboratory)
4"""
5########### SVN repository information ###################
6# $Date: 2012-07-01 01:38:38 +0000 (Sun, 01 Jul 2012) $
7# $Author: toby $
8# $Revision: 670 $
9# $URL: trunk/GSASIIIO.py $
10# $Id: GSASIIIO.py 670 2012-07-01 01:38:38Z toby $
11########### SVN repository information ###################
12import wx
13import math
14import numpy as np
15import cPickle
16import sys
17import random as ran
18import GSASIIpath
19GSASIIpath.SetVersionNumber("$Revision: 670 $")
20import GSASIIgrid as G2gd
21import GSASIIspc as G2spc
22import GSASIIlattice as G2lat
23import GSASIIpwdGUI as G2pdG
24import GSASIIElem as G2el
25import os
26import os.path as ospath
27
28def sfloat(S):
29    if S.strip():
30        return float(S)
31    else:
32        return 0.0
33
34def sint(S):
35    if S.strip():
36        return int(S)
37    else:
38        return 0
39
40def FileDlgFixExt(dlg,file):
41    #this is needed to fix a problem in linux wx.FileDialog
42    ext = dlg.GetWildcard().split('|')[2*dlg.GetFilterIndex()+1].strip('*')
43    if ext not in file:
44        file += ext
45    return file
46       
47def GetPowderPeaks(fileName):
48    sind = lambda x: math.sin(x*math.pi/180.)
49    asind = lambda x: 180.*math.asin(x)/math.pi
50    Cuka = 1.54052
51    File = open(fileName,'Ur')
52    Comments = []
53    peaks = []
54    S = File.readline()
55    while S:
56        if S[:1] == '#':
57            Comments.append(S[:-1])
58        else:
59            item = S.split()
60            if len(item) == 1:
61                peaks.append([float(item[0]),1.0])
62            elif len(item) > 1:
63                peaks.append([float(item[0]),float(item[0])])
64        S = File.readline()
65    File.close()
66    if Comments:
67       print 'Comments on file:'
68       for Comment in Comments: print Comment
69    Peaks = []
70    if peaks[0][0] > peaks[-1][0]:          # d-spacings - assume CuKa
71        for peak in peaks:
72            dsp = peak[0]
73            sth = Cuka/(2.0*dsp)
74            if sth < 1.0:
75                tth = 2.0*asind(sth)
76            else:
77                break
78            Peaks.append([tth,peak[1],True,False,0,0,0,dsp,0.0])
79    else:                                   #2-thetas - assume Cuka (for now)
80        for peak in peaks:
81            tth = peak[0]
82            dsp = Cuka/(2.0*sind(tth/2.0))
83            Peaks.append([tth,peak[1],True,False,0,0,0,dsp,0.0])
84    return Comments,Peaks
85
86def CheckImageFile(G2frame,imagefile):
87    if not ospath.exists(imagefile):
88        dlg = wx.FileDialog(G2frame, 'Bad image file name; choose name', '.', '',\
89        'Any image file (*.tif;*.tiff;*.mar*;*.avg;*.sum;*.img)\
90        |*.tif;*.tiff;*.mar*;*.avg;*.sum;*.img|\
91        Any detector tif (*.tif;*.tiff)|*.tif;*.tiff|\
92        MAR file (*.mar*)|*.mar*|\
93        GE Image (*.avg;*.sum)|*.avg;*.sum|\
94        ADSC Image (*.img)|*.img|\
95        All files (*.*)|*.*',wx.OPEN|wx.CHANGE_DIR)
96        try:
97            dlg.SetFilename(''+ospath.split(imagefile)[1])
98            if dlg.ShowModal() == wx.ID_OK:
99                imagefile = dlg.GetPath()
100            else:
101                imagefile = False
102        finally:
103            dlg.Destroy()
104    return imagefile
105       
106def GetImageData(G2frame,imagefile,imageOnly=False):       
107    ext = ospath.splitext(imagefile)[1]
108    Comments = []
109    if ext == '.tif' or ext == '.tiff':
110        Comments,Data,Npix,Image = GetTifData(imagefile)
111    elif ext == '.img':
112        Comments,Data,Npix,Image = GetImgData(imagefile)
113        Image[0][0] = 0
114    elif ext == '.mar3450' or ext == '.mar2300':
115        Comments,Data,Npix,Image = GetMAR345Data(imagefile)
116    elif ext in ['.sum','.avg','']:
117        Comments,Data,Npix,Image = GetGEsumData(imagefile)
118    elif ext == '.G2img':
119        Comments,Data,Npix,Image = GetG2Image(imagefile)
120    if imageOnly:
121        return Image
122    else:
123        return Comments,Data,Npix,Image
124       
125def PutG2Image(filename,Comments,Data,Npix,image):
126    File = open(filename,'wb')
127    cPickle.dump([Comments,Data,Npix,image],File,1)
128    File.close()
129    return
130   
131def GetG2Image(filename):
132    File = open(filename,'rb')
133    Comments,Data,Npix,image = cPickle.load(File)
134    File.close()
135    return Comments,Data,Npix,image
136   
137def GetGEsumData(filename,imageOnly=False):
138    import struct as st
139    import array as ar
140    if not imageOnly:
141        print 'Read GE sum file: ',filename   
142    File = open(filename,'rb')
143    if '.sum' in filename:
144        head = ['GE detector sum data from APS 1-ID',]
145        sizexy = [2048,2048]
146    elif '.avg' in filename:
147        head = ['GE detector avg data from APS 1-ID',]
148        sizexy = [2048,2048]
149    else:
150        head = ['GE detector raw data from APS 1-ID',]
151        File.seek(18)
152        size,nframes = st.unpack('<ih',File.read(6))
153        sizexy = [2048,2048]
154        pos = 8192
155        File.seek(pos)
156    Npix = sizexy[0]*sizexy[1]
157    if '.sum' in filename:
158        image = np.array(ar.array('f',File.read(4*Npix)),dtype=np.int32)
159    elif '.avg' in filename:
160        image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
161    else:
162        image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
163        while nframes > 1:
164            image += np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
165            nframes -= 1
166    image = np.reshape(image,(sizexy[1],sizexy[0]))
167    data = {'pixelSize':(200,200),'wavelength':0.15,'distance':250.0,'center':[204.8,204.8],'size':sizexy} 
168    File.close()   
169    if imageOnly:
170        return image
171    else:
172        return head,data,Npix,image
173       
174def GetImgData(filename,imageOnly=False):
175    import struct as st
176    import array as ar
177    if not imageOnly:
178        print 'Read ADSC img file: ',filename
179    File = open(filename,'rb')
180    head = File.read(511)
181    lines = head.split('\n')
182    head = []
183    center = [0,0]
184    for line in lines[1:-2]:
185        line = line.strip()[:-1]
186        if line:
187            if 'SIZE1' in line:
188                size = int(line.split('=')[1])
189                Npix = size*size
190            elif 'WAVELENGTH' in line:
191                wave = float(line.split('=')[1])
192            elif 'BIN' in line:
193                if line.split('=')[1] == '2x2':
194                    pixel=(102,102)
195                else:
196                    pixel = (51,51)
197            elif 'DISTANCE' in line:
198                distance = float(line.split('=')[1])
199            elif 'CENTER_X' in line:
200                center[0] = float(line.split('=')[1])
201            elif 'CENTER_Y' in line:
202                center[1] = float(line.split('=')[1])
203            head.append(line)
204    data = {'pixelSize':pixel,'wavelength':wave,'distance':distance,'center':center,'size':[size,size]}
205    image = []
206    row = 0
207    pos = 512
208    File.seek(pos)
209    image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
210    image = np.reshape(image,(sizexy[1],sizexy[0]))
211#    image = np.zeros(shape=(size,size),dtype=np.int32)   
212#    while row < size:
213#        File.seek(pos)
214#        line = ar.array('H',File.read(2*size))
215#        image[row] = np.asarray(line)
216#        row += 1
217#        pos += 2*size
218    File.close()
219    if imageOnly:
220        return image
221    else:
222        return lines[1:-2],data,Npix,image
223       
224def GetMAR345Data(filename,imageOnly=False):
225    import array as ar
226    import struct as st
227    try:
228        import pack_f as pf
229    except:
230        msg = wx.MessageDialog(None, message="Unable to load the GSAS MAR image decompression, pack_f",
231                               caption="Import Error",
232                               style=wx.ICON_ERROR | wx.OK | wx.STAY_ON_TOP)
233        msg.ShowModal()
234        return None,None,None,None
235
236    if not imageOnly:
237        print 'Read Mar345 file: ',filename
238    File = open(filename,'rb')
239    head = File.read(4095)
240    numbers = st.unpack('<iiiiiiiiii',head[:40])
241    lines = head[128:].split('\n')
242    head = []
243    for line in lines:
244        line = line.strip()
245        if 'PIXEL' in line:
246            values = line.split()
247            pixel = (int(values[2]),int(values[4]))     #in microns
248        elif 'WAVELENGTH' in line:
249            wave = float(line.split()[1])
250        elif 'DISTANCE' in line:
251            distance = float(line.split()[1])           #in mm
252        elif 'CENTER' in line:
253            values = line.split()
254            center = [float(values[2])/10.,float(values[4])/10.]    #make in mm from pixels
255        if line: 
256            head.append(line)
257    data = {'pixelSize':pixel,'wavelength':wave,'distance':distance,'center':center}
258    for line in head:
259        if 'FORMAT' in line[0:6]:
260            items = line.split()
261            size = int(items[1])
262            Npix = size*size
263    pos = 4096
264    data['size'] = [size,size]
265    File.seek(pos)
266    line = File.read(8)
267    while 'CCP4' not in line:       #get past overflow list for now
268        line = File.read(8)
269        pos += 8
270    pos += 37
271    File.seek(pos)
272    raw = File.read()
273    File.close()
274    image = np.zeros(shape=(size,size),dtype=np.int32)
275    image = pf.pack_f(len(raw),raw,size,image)
276    if imageOnly:
277        return image.T              #transpose to get it right way around
278    else:
279        return head,data,Npix,image.T
280       
281def GetTifData(filename,imageOnly=False):
282    import struct as st
283    import array as ar
284    File = open(filename,'rb')
285    dataType = 5
286    try:
287        Meta = open(filename+'.metadata','Ur')
288        head = Meta.readlines()
289        for line in head:
290            line = line.strip()
291            if 'dataType=' in line:
292                dataType = int(line.split('=')[1])
293        Meta.close()
294    except IOError:
295        print 'no metadata file found - will try to read file anyway'
296        head = ['no metadata file found',]
297       
298    tag = File.read(2)
299    byteOrd = '<'
300    if tag == 'II' and int(st.unpack('<h',File.read(2))[0]) == 42:     #little endian
301        IFD = int(st.unpack(byteOrd+'i',File.read(4))[0])
302    elif tag == 'MM' and int(st.unpack('>h',File.read(2))[0]) == 42:   #big endian
303        byteOrd = '>'
304        IFD = int(st.unpack(byteOrd+'i',File.read(4))[0])       
305    else:
306        lines = ['not a detector tiff file',]
307        return lines,0,0,0
308    File.seek(IFD)                                                  #get number of directory entries
309    NED = int(st.unpack(byteOrd+'h',File.read(2))[0])
310    IFD = {}
311    for ied in range(NED):
312        Tag,Type = st.unpack(byteOrd+'Hh',File.read(4))
313        nVal = st.unpack(byteOrd+'i',File.read(4))[0]
314        if Type == 1:
315            Value = st.unpack(byteOrd+nVal*'b',File.read(nVal))
316        elif Type == 2:
317            Value = st.unpack(byteOrd+'i',File.read(4))
318        elif Type == 3:
319            Value = st.unpack(byteOrd+nVal*'h',File.read(nVal*2))
320            x = st.unpack(byteOrd+nVal*'h',File.read(nVal*2))
321        elif Type == 4:
322            Value = st.unpack(byteOrd+nVal*'i',File.read(nVal*4))
323        elif Type == 5:
324            Value = st.unpack(byteOrd+nVal*'i',File.read(nVal*4))
325        elif Type == 11:
326            Value = st.unpack(byteOrd+nVal*'f',File.read(nVal*4))
327        IFD[Tag] = [Type,nVal,Value]
328#    for key in IFD:
329#        print key,IFD[key]
330    sizexy = [IFD[256][2][0],IFD[257][2][0]]
331    [nx,ny] = sizexy
332    Npix = nx*ny
333    if 272 in IFD:
334        ifd = IFD[272]
335        File.seek(ifd[2][0])
336        S = File.read(ifd[1])
337        if 'PILATUS' in S:
338            tifType = 'Pilatus'
339            dataType = 0
340            pixy = (172,172)
341            File.seek(4096)
342            if not imageOnly:
343                print 'Read Pilatus tiff file: ',filename
344            image = ar.array('L',File.read(4*Npix))
345            image = np.array(np.asarray(image),dtype=np.int32)
346    elif 262 in IFD and IFD[262][2][0] > 4:
347        tifType = 'DND'
348        pixy = (158,158)
349        File.seek(512)
350        if not imageOnly:
351            print 'Read DND SAX/WAX-detector tiff file: ',filename
352        image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
353    elif sizexy == [1536,1536]:
354        tifType = 'APS Gold'
355        pixy = (150,150)
356        File.seek(64)
357        if not imageOnly:
358            print 'Read Gold tiff file:',filename
359        image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
360    elif sizexy == [2048,2048] or sizexy == [1024,1024]:
361        if IFD[273][2][0] == 8:
362            if IFD[258][2][0] == 32:
363                tifType = 'PE'
364                pixy = (200,200)
365                File.seek(8)
366                if not imageOnly:
367                    print 'Read APS PE-detector tiff file: ',filename
368                if dataType == 5:
369                    image = np.array(ar.array('f',File.read(4*Npix)),dtype=np.float32)
370                else:
371                    image = np.array(ar.array('I',File.read(4*Npix)),dtype=np.int32)
372        elif IFD[273][2][0] == 4096:
373            tifType = 'MAR'
374            pixy = (158,158)
375            File.seek(4096)
376            if not imageOnly:
377                print 'Read MAR CCD tiff file: ',filename
378            image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
379    elif sizexy == [4096,4096]:
380        if IFD[273][2][0] == 8:
381            if IFD[258][2][0] == 16:
382                tifType = 'scanCCD'
383                pixy = (9,9)
384                File.seek(8)
385                if not imageOnly:
386                    print 'Read APS scanCCD tiff file: ',filename
387                image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
388        elif IFD[273][2][0] == 4096:
389            tifType = 'Rayonix'
390            pixy = (73.242,73.242)
391            File.seek(4096)
392            if not imageOnly:
393                print 'Read Rayonix MX300HE tiff file: ',filename
394            image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
395#    elif sizexy == [960,960]:
396#        tiftype = 'PE-BE'
397#        pixy = (200,200)
398#        File.seek(8)
399#        if not imageOnly:
400#            print 'Read Gold tiff file:',filename
401#        image = np.array(ar.array('H',File.read(2*Npix)),dtype=np.int32)
402           
403    else:
404        lines = ['not a known detector tiff file',]
405        return lines,0,0,0
406       
407    image = np.reshape(image,(sizexy[1],sizexy[0]))
408    center = [pixy[0]*sizexy[0]/2000,pixy[1]*sizexy[1]/2000]
409    data = {'pixelSize':pixy,'wavelength':0.10,'distance':100.0,'center':center,'size':sizexy}
410    File.close()   
411    if imageOnly:
412        return image
413    else:
414        return head,data,Npix,image
415   
416def ProjFileOpen(G2frame):
417    file = open(G2frame.GSASprojectfile,'rb')
418    print 'load from file: ',G2frame.GSASprojectfile
419    G2frame.SetTitle("GSAS-II data tree: "+
420                     os.path.split(G2frame.GSASprojectfile)[1])
421    wx.BeginBusyCursor()
422    try:
423        while True:
424            try:
425                data = cPickle.load(file)
426            except EOFError:
427                break
428            datum = data[0]
429           
430            Id = G2frame.PatternTree.AppendItem(parent=G2frame.root,text=datum[0])
431            if 'PWDR' in datum[0]:               
432                G2frame.PatternTree.SetItemPyData(Id,datum[1][:3])     #temp. trim off junk
433            else:
434                G2frame.PatternTree.SetItemPyData(Id,datum[1])
435            for datus in data[1:]:
436                sub = G2frame.PatternTree.AppendItem(Id,datus[0])
437                G2frame.PatternTree.SetItemPyData(sub,datus[1])
438            if 'IMG' in datum[0]:                   #retrieve image default flag & data if set
439                Data = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Image Controls'))
440                if Data['setDefault']:
441                    G2frame.imageDefault = Data               
442        file.close()
443       
444    finally:
445        wx.EndBusyCursor()
446    print 'project load successful'
447    G2frame.NewPlot = True
448   
449def ProjFileSave(G2frame):
450    if not G2frame.PatternTree.IsEmpty():
451        file = open(G2frame.GSASprojectfile,'wb')
452        print 'save to file: ',G2frame.GSASprojectfile
453        wx.BeginBusyCursor()
454        try:
455            item, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
456            while item:
457                data = []
458                name = G2frame.PatternTree.GetItemText(item)
459                data.append([name,G2frame.PatternTree.GetItemPyData(item)])
460                item2, cookie2 = G2frame.PatternTree.GetFirstChild(item)
461                while item2:
462                    name = G2frame.PatternTree.GetItemText(item2)
463                    data.append([name,G2frame.PatternTree.GetItemPyData(item2)])
464                    item2, cookie2 = G2frame.PatternTree.GetNextChild(item, cookie2)                           
465                item, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)                           
466                cPickle.dump(data,file,1)
467            file.close()
468        finally:
469            wx.EndBusyCursor()
470        print 'project save successful'
471
472def SaveIntegration(G2frame,PickId,data):
473    azms = G2frame.Integrate[1]
474    X = G2frame.Integrate[2][:-1]
475    Xminmax = [X[0],X[-1]]
476    N = len(X)
477    Id = G2frame.PatternTree.GetItemParent(PickId)
478    name = G2frame.PatternTree.GetItemText(Id)
479    name = name.replace('IMG ','PWDR ')
480    Comments = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Comments'))
481    names = ['Type','Lam','Zero','Polariz.','U','V','W','X','Y','SH/L','Azimuth'] 
482    codes = [0 for i in range(11)]
483    LRazm = data['LRazimuth']
484    Azms = []
485    if data['fullIntegrate'] and data['outAzimuths'] == 1:
486        Azms = [45.0,]                              #a poor man's average?
487    else:
488        for i,azm in enumerate(azms[:-1]):
489            Azms.append((azms[i+1]+azm)/2.)
490    for i,azm in enumerate(azms[:-1]):
491        item, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
492        Id = 0
493        while item:
494            Name = G2frame.PatternTree.GetItemText(item)
495            if name == Name:
496                Id = item
497            item, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
498        parms = ['PXC',data['wavelength'],0.0,0.99,1.0,-0.10,0.4,0.30,1.0,0.0001,Azms[i]]    #set polarization for synchrotron radiation!
499        Y = G2frame.Integrate[0][i]
500        W = 1./Y                    #probably not true
501        Sample = G2pdG.SetDefaultSample()
502        if Id:
503            G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id, 'Comments'),Comments)                   
504            G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Limits'),[tuple(Xminmax),Xminmax])
505            G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Background'),[['chebyschev',1,3,1.0,0.0,0.0],
506                            {'nDebye':0,'debyeTerms':[],'nPeaks':0,'peaksList':[]}])
507            G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Instrument Parameters'),[tuple(parms),parms[:],codes,names])
508            G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Peak List'),[])
509            G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Index Peak List'),[])
510            G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Unit Cells List'),[])             
511            G2frame.PatternTree.SetItemPyData(G2gd.GetPatternTreeItemId(G2frame,Id,'Reflection Lists'),{})             
512        else:
513            Id = G2frame.PatternTree.AppendItem(parent=G2frame.root,text=name+" Azm= %.2f"%(Azms[i]))
514            G2frame.PatternTree.SetItemPyData(G2frame.PatternTree.AppendItem(Id,text='Comments'),Comments)                   
515            G2frame.PatternTree.SetItemPyData(G2frame.PatternTree.AppendItem(Id,text='Limits'),[tuple(Xminmax),Xminmax])
516            G2frame.PatternTree.SetItemPyData(G2frame.PatternTree.AppendItem(Id,text='Background'),[['chebyschev',1,3,1.0,0.0,0.0],
517                            {'nDebye':0,'debyeTerms':[],'nPeaks':0,'peaksList':[]}])
518            G2frame.PatternTree.SetItemPyData(G2frame.PatternTree.AppendItem(Id,text='Instrument Parameters'),[tuple(parms),parms[:],codes,names])
519            G2frame.PatternTree.SetItemPyData(G2frame.PatternTree.AppendItem(Id,text='Sample Parameters'),Sample)
520            G2frame.PatternTree.SetItemPyData(G2frame.PatternTree.AppendItem(Id,text='Peak List'),[])
521            G2frame.PatternTree.SetItemPyData(G2frame.PatternTree.AppendItem(Id,text='Index Peak List'),[])
522            G2frame.PatternTree.SetItemPyData(G2frame.PatternTree.AppendItem(Id,text='Unit Cells List'),[])
523            G2frame.PatternTree.SetItemPyData(G2frame.PatternTree.AppendItem(Id,text='Reflection Lists'),{})             
524        G2frame.PatternTree.SetItemPyData(Id,[[''],[np.array(X),np.array(Y),np.array(W),np.zeros(N),np.zeros(N),np.zeros(N)]])
525    G2frame.PatternTree.SelectItem(Id)
526    G2frame.PatternTree.Expand(Id)
527    G2frame.PatternId = Id
528           
529def powderFxyeSave(G2frame,exports,powderfile):
530    head,tail = ospath.split(powderfile)
531    name,ext = tail.split('.')
532    for i,export in enumerate(exports):
533        filename = ospath.join(head,name+'-%03d.'%(i)+ext)
534        prmname = filename.strip(ext)+'prm'
535        prm = open(prmname,'w')      #old style GSAS parm file
536        PickId = G2gd.GetPatternTreeItemId(G2frame, G2frame.root, export)
537        Values,Names = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame, \
538            PickId, 'Instrument Parameters'))[1::2]     #get values & names
539        Inst = dict(zip(Names,Values))
540        print Inst['Type']
541        prm.write( '            123456789012345678901234567890123456789012345678901234567890        '+'\n')
542        prm.write( 'INS   BANK      1                                                               '+'\n')
543        prm.write(('INS   HTYPE   %sR                                                              '+'\n')%(Inst['Type']))
544        if 'Lam1' in Inst:              #Ka1 & Ka2
545            prm.write(('INS  1 ICONS%10.7f%10.7f    0.0000               0.990    0     0.500   '+'\n')%(Inst['Lam1'],Inst['Lam2']))
546        elif 'Lam' in Inst:             #single wavelength
547            prm.write(('INS  1 ICONS%10.7f%10.7f    0.0000               0.990    0     0.500   '+'\n')%(Inst['Lam'],0.0))
548        prm.write( 'INS  1 IRAD     0                                                               '+'\n')
549        prm.write( 'INS  1I HEAD                                                                    '+'\n')
550        prm.write( 'INS  1I ITYP    0    0.0000  180.0000         1                                 '+'\n')
551        prm.write(('INS  1DETAZM%10.3f                                                          '+'\n')%(Inst['Azimuth']))
552        prm.write( 'INS  1PRCF1     3    8   0.00100                                                '+'\n')
553        prm.write(('INS  1PRCF11     %15.6g%15.6g%15.6g%15.6g   '+'\n')%(Inst['U'],Inst['V'],Inst['W'],0.0))
554        prm.write(('INS  1PRCF12     %15.6g%15.6g%15.6g%15.6g   '+'\n')%(Inst['X'],Inst['Y'],Inst['SH/L']/2.,Inst['SH/L']/2.))
555        prm.close()
556        file = open(filename,'w')
557        print 'save powder pattern to file: ',filename
558        x,y,w,yc,yb,yd = G2frame.PatternTree.GetItemPyData(PickId)[1]
559        file.write(powderfile+'\n')
560        file.write('Instrument parameter file:'+ospath.split(prmname)[1]+'\n')
561        file.write('BANK 1 %d %d CONS %.2f %.2f 0 0 FXYE\n'%(len(x),len(x),\
562            100.*x[0],100.*(x[1]-x[0])))
563        s = list(np.sqrt(1./np.array(w)))       
564        XYW = zip(x,y,s)
565        for X,Y,S in XYW:
566            file.write("%15.6g %15.6g %15.6g\n" % (100.*X,Y,max(S,1.0)))
567        file.close()
568        print 'powder pattern file '+filename+' written'
569       
570def powderXyeSave(G2frame,exports,powderfile):
571    head,tail = ospath.split(powderfile)
572    name,ext = tail.split('.')
573    for i,export in enumerate(exports):
574        filename = ospath.join(head,name+'-%03d.'%(i)+ext)
575        PickId = G2gd.GetPatternTreeItemId(G2frame, G2frame.root, export)
576        file = open(filename,'w')
577        file.write('#%s\n'%(export))
578        print 'save powder pattern to file: ',filename
579        x,y,w,yc,yb,yd = G2frame.PatternTree.GetItemPyData(PickId)[1]
580        s = list(np.sqrt(1./np.array(w)))       
581        XYW = zip(x,y,s)
582        for X,Y,W in XYW:
583            file.write("%15.6g %15.6g %15.6g\n" % (X,Y,W))
584        file.close()
585        print 'powder pattern file '+filename+' written'
586       
587def PDFSave(G2frame,exports):   
588    for export in exports:
589        PickId = G2gd.GetPatternTreeItemId(G2frame, G2frame.root, export)
590        SQname = 'S(Q)'+export[4:]
591        GRname = 'G(R)'+export[4:]
592        sqfilename = ospath.join(G2frame.dirname,export.replace(' ','_')[5:]+'.sq')
593        grfilename = ospath.join(G2frame.dirname,export.replace(' ','_')[5:]+'.gr')
594        sqId = G2gd.GetPatternTreeItemId(G2frame, PickId, SQname)
595        grId = G2gd.GetPatternTreeItemId(G2frame, PickId, GRname)
596        sqdata = np.array(G2frame.PatternTree.GetItemPyData(sqId)[1][:2]).T
597        grdata = np.array(G2frame.PatternTree.GetItemPyData(grId)[1][:2]).T
598        sqfile = open(sqfilename,'w')
599        grfile = open(grfilename,'w')
600        sqfile.write('#T S(Q) %s\n'%(export))
601        grfile.write('#T G(R) %s\n'%(export))
602        sqfile.write('#L Q     S(Q)\n')
603        grfile.write('#L R     G(R)\n')
604        for q,sq in sqdata:
605            sqfile.write("%15.6g %15.6g\n" % (q,sq))
606        sqfile.close()
607        for r,gr in grdata:
608            grfile.write("%15.6g %15.6g\n" % (r,gr))
609        grfile.close()
610   
611def PeakListSave(G2frame,file,peaks):
612    print 'save peak list to file: ',G2frame.peaklistfile
613    if not peaks:
614        dlg = wx.MessageDialog(G2frame, 'No peaks!', 'Nothing to save!', wx.OK)
615        try:
616            result = dlg.ShowModal()
617        finally:
618            dlg.Destroy()
619        return
620    for peak in peaks:
621        file.write("%10.4f %12.2f %10.3f %10.3f \n" % \
622            (peak[0],peak[2],peak[4],peak[6]))
623    print 'peak list saved'
624             
625def IndexPeakListSave(G2frame,peaks):
626    file = open(G2frame.peaklistfile,'wa')
627    print 'save index peak list to file: ',G2frame.peaklistfile
628    wx.BeginBusyCursor()
629    try:
630        if not peaks:
631            dlg = wx.MessageDialog(G2frame, 'No peaks!', 'Nothing to save!', wx.OK)
632            try:
633                result = dlg.ShowModal()
634            finally:
635                dlg.Destroy()
636            return
637        for peak in peaks:
638            file.write("%12.6f\n" % (peak[7]))
639        file.close()
640    finally:
641        wx.EndBusyCursor()
642    print 'index peak list saved'
643   
644def SetNewPhase(Name='New Phase',SGData=G2spc.SpcGroup('P 1')[1],cell=[1.0,1.0,1.0,90.,90,90.,1.]):
645    phaseData = {
646        'General':{
647            'Name':Name,
648            'Type':'nuclear',
649            'SGData':SGData,
650            'Cell':[False,]+cell,
651            'Pawley dmin':1.0,
652            'Data plot type':'None',
653            'SH Texture':{
654                'Order':0,
655                'Model':'cylindrical',
656                'Sample omega':[False,0.0],
657                'Sample chi':[False,0.0],
658                'Sample phi':[False,0.0],
659                'SH Coeff':[False,{}],
660                'SHShow':False,
661                'PFhkl':[0,0,1],
662                'PFxyz':[0,0,1],
663                'PlotType':'Pole figure'}},
664        'Atoms':[],
665        'Drawing':{},
666        'Histograms':{},
667        'Pawley ref':[],
668        'Models':{},
669        }
670    return phaseData
671   
672def ReadEXPPhase(G2frame,filename):
673    shModels = ['cylindrical','none','shear - 2/m','rolling - mmm']
674    textureData = {'Order':0,'Model':'cylindrical','Sample omega':[False,0.0],
675        'Sample chi':[False,0.0],'Sample phi':[False,0.0],'SH Coeff':[False,{}],
676        'SHShow':False,'PFhkl':[0,0,1],'PFxyz':[0,0,1],'PlotType':'Pole figure'}
677    shNcof = 0
678    file = open(filename, 'Ur')
679    S = 1
680    Expr = [{},{},{},{},{},{},{},{},{}]
681    while S:
682        S = file.readline()
683        if 'EXPR NPHAS' in S[:12]:
684            Num = S[12:-1].count('0')
685            NPhas = S[12:-1].split()
686        if 'CRS' in S[:3]:
687            N = int(S[3:4])-1
688            Expr[N][S[:12]] = S[12:-1]
689    file.close()
690    PNames = []
691    for n,N in enumerate(NPhas):
692        if N != '0':
693            result = n
694            key = 'CRS'+str(n+1)+'    PNAM'
695            PNames.append(Expr[n][key])
696    if Num < 8:
697        dlg = wx.SingleChoiceDialog(G2frame, 'Which phase to read?', 'Read phase data', PNames, wx.CHOICEDLG_STYLE)
698        try:
699            if dlg.ShowModal() == wx.ID_OK:
700                result = dlg.GetSelection()
701        finally:
702            dlg.Destroy()       
703    EXPphase = Expr[result]
704    keyList = EXPphase.keys()
705    keyList.sort()
706    SGData = {}
707    if NPhas[result] == '1':
708        Ptype = 'nuclear'
709    elif NPhas[result] in ['2','3']:
710        Ptype = 'magnetic'
711    elif NPhas[result] == '4':
712        Ptype = 'macromolecular'
713    elif NPhas[result] == '10':
714        Ptype = 'Pawley'
715    for key in keyList:
716        if 'PNAM' in key:
717           PhaseName = EXPphase[key].strip()
718        elif 'ABC   ' in key:
719            abc = [float(EXPphase[key][:10]),float(EXPphase[key][10:20]),float(EXPphase[key][20:30])]                       
720        elif 'ANGLES' in key:
721            angles = [float(EXPphase[key][:10]),float(EXPphase[key][10:20]),float(EXPphase[key][20:30])]                                               
722        elif 'SG SYM' in key:
723            SpGrp = EXPphase[key][:15].strip()
724            E,SGData = G2spc.SpcGroup(SpGrp)
725        elif 'OD    ' in key:
726            SHdata = EXPphase[key].split() # may not have all 9 values
727            SHvals = 9*[0]
728            for i in range(9):
729                try:
730                    float(SHdata[i])
731                    SHvals[i] = SHdata[i]
732                except:
733                    pass
734            textureData['Order'] = int(SHvals[0])
735            textureData['Model'] = shModels[int(SHvals[2])]
736            textureData['Sample omega'] = [False,float(SHvals[6])]
737            textureData['Sample chi'] = [False,float(SHvals[7])]
738            textureData['Sample phi'] = [False,float(SHvals[8])]
739            shNcof = int(SHvals[1])
740    Atoms = []
741    if Ptype == 'nuclear':
742        for key in keyList:
743            if 'AT' in key:
744                if key[11:] == 'A':
745                    S = EXPphase[key]
746                elif key[11:] == 'B':
747                    S += EXPphase[key]
748                    Atom = [S[50:58].strip(),S[:10].strip(),'',
749                        float(S[10:20]),float(S[20:30]),float(S[30:40]),
750                        float(S[40:50]),'',int(S[60:62]),S[130:131]]
751                    if Atom[9] == 'I':
752                        Atom += [float(S[68:78]),0.,0.,0.,0.,0.,0.]
753                    elif Atom[9] == 'A':
754                        Atom += [0.0,float(S[68:78]),float(S[78:88]),
755                            float(S[88:98]),float(S[98:108]),
756                            float(S[108:118]),float(S[118:128])]
757                    XYZ = Atom[3:6]
758                    Atom[7],Atom[8] = G2spc.SytSym(XYZ,SGData)
759                    Atom.append(ran.randint(0,sys.maxint))
760                    Atoms.append(Atom)
761    elif Ptype == 'macromolecular':
762        for key in keyList:
763            if 'AT' in key[6:8]:
764                S = EXPphase[key]
765                Atom = [S[56:60],S[50:54].strip().upper(),S[54:56],
766                    S[46:51].strip(),S[:8].strip(),'',
767                    float(S[16:24]),float(S[24:32]),float(S[32:40]),
768                    float(S[8:16]),'1',1,'I',float(S[40:46]),0,0,0,0,0,0]
769                XYZ = Atom[6:9]
770                Atom[10],Atom[11] = G2spc.SytSym(XYZ,SGData)
771                Atom.append(ran.randint(0,sys.maxint))
772                Atoms.append(Atom)
773    Volume = G2lat.calc_V(G2lat.cell2A(abc+angles))
774    if shNcof:
775        shCoef = {}
776        nRec = [i+1 for i in range((shNcof-1)/6+1)]
777        for irec in nRec:
778            ODkey = keyList[0][:6]+'OD'+'%3dA'%(irec)
779            indx = EXPphase[ODkey].split()
780            ODkey = ODkey[:-1]+'B'
781            vals = EXPphase[ODkey].split()
782            for i,val in enumerate(vals):
783                key = 'C(%s,%s,%s)'%(indx[3*i],indx[3*i+1],indx[3*i+2])
784                shCoef[key] = float(val)
785        textureData['SH Coeff'] = [False,shCoef]
786       
787    Phase = SetNewPhase(Name=PhaseName,SGData=SGData,cell=abc+angles+[Volume,])
788    general = Phase['General']
789    general['Type'] = Ptype
790    general['SH Texture'] = textureData
791    Phase['Atoms'] = Atoms
792    return Phase
793       
794def ReadPDBPhase(filename):
795    EightPiSq = 8.*math.pi**2
796    file = open(filename, 'Ur')
797    Phase = {}
798    Title = ''
799    Compnd = ''
800    Atoms = []
801    A = np.zeros(shape=(3,3))
802    S = file.readline()
803    while S:
804        Atom = []
805        if 'TITLE' in S[:5]:
806            Title = S[10:72].strip()
807            S = file.readline()
808        elif 'COMPND    ' in S[:10]:
809            Compnd = S[10:72].strip()
810            S = file.readline()
811        elif 'CRYST' in S[:5]:
812            abc = S[7:34].split()
813            angles = S[34:55].split()
814            cell=[float(abc[0]),float(abc[1]),float(abc[2]),
815                float(angles[0]),float(angles[1]),float(angles[2])]
816            Volume = G2lat.calc_V(G2lat.cell2A(cell))
817            AA,AB = G2lat.cell2AB(cell)
818            SpGrp = S[55:65]
819            E,SGData = G2spc.SpcGroup(SpGrp)
820            while E:
821                print G2spc.SGErrors(E)
822                dlg = wx.TextEntryDialog(None,
823                    SpGrp[:-1]+' is invalid \nN.B.: make sure spaces separate axial fields in symbol',
824                    'ERROR in space group symbol','',style=wx.OK)
825                if dlg.ShowModal() == wx.ID_OK:
826                    SpGrp = dlg.GetValue()
827                    E,SGData = G2spc.SpcGroup(SpGrp)
828                else:
829                    return None
830                dlg.Destroy()               
831            SGlines = G2spc.SGPrint(SGData)
832            for line in SGlines: print line
833            S = file.readline()
834        elif 'SCALE' in S[:5]:
835            V = (S[10:41].split())
836            A[int(S[5])-1] = [float(V[0]),float(V[1]),float(V[2])]
837            S = file.readline()
838        elif 'ATOM' in S[:4] or 'HETATM' in S[:6]:
839            XYZ = [float(S[31:39]),float(S[39:47]),float(S[47:55])]
840            XYZ = np.inner(AB,XYZ)
841            XYZ = np.where(abs(XYZ)<0.00001,0,XYZ)
842            SytSym,Mult = G2spc.SytSym(XYZ,SGData)
843            Uiso = float(S[61:67])/EightPiSq
844            Type = S[12:14].upper()
845            if Type[0] in '123456789':
846                Type = Type[1:]
847            Atom = [S[22:27].strip(),S[17:20].upper(),S[20:22],
848                S[12:17].strip(),Type.strip(),'',XYZ[0],XYZ[1],XYZ[2],
849                float(S[55:61]),SytSym,Mult,'I',Uiso,0,0,0,0,0,0]
850            S = file.readline()
851            if 'ANISOU' in S[:6]:
852                Uij = S[30:72].split()
853                Uij = [float(Uij[0])/10000.,float(Uij[1])/10000.,float(Uij[2])/10000.,
854                    float(Uij[3])/10000.,float(Uij[4])/10000.,float(Uij[5])/10000.]
855                Atom = Atom[:14]+Uij
856                Atom[12] = 'A'
857                S = file.readline()
858            Atom.append(ran.randint(0,sys.maxint))
859            Atoms.append(Atom)
860        else:           
861            S = file.readline()
862    file.close()
863    if Title:
864        PhaseName = Title
865    elif Compnd:
866        PhaseName = Compnd
867    else:
868        PhaseName = 'None'
869    Phase = SetNewPhase(Name=PhaseName,SGData=SGData,cell=cell+[Volume,])
870    Phase['General']['Type'] = 'macromolecular'
871    Phase['Atoms'] = Atoms
872   
873    return Phase
874
875class MultipleChoicesDialog(wx.Dialog):
876    '''A dialog that offers a series of choices, each with a title and a wx.Choice
877    widget. Intended to be used Modally.
878    typical input:
879          choicelist=[ ('a','b','c'), ('test1','test2'),('no choice',)]
880          headinglist = [ 'select a, b or c', 'select 1 of 2', 'No option here']
881    selections are placed in self.chosen when OK is pressed
882    '''
883    def __init__(self,choicelist,headinglist,
884                 head='Select options',
885                 title='Please select from options below',
886                 parent=None):
887        self.chosen = []
888        wx.Dialog.__init__(
889            self,parent,wx.ID_ANY,head, 
890            pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE)
891        panel = wx.Panel(self)
892        mainSizer = wx.BoxSizer(wx.VERTICAL)
893        mainSizer.Add((10,10),1)
894        topLabl = wx.StaticText(panel,wx.ID_ANY,title)
895        mainSizer.Add(topLabl,0,wx.ALIGN_CENTER_VERTICAL|wx.CENTER,10)
896        self.ChItems = []
897        for choice,lbl in zip(choicelist,headinglist):
898            mainSizer.Add((10,10),1)
899            self.chosen.append(0)
900            topLabl = wx.StaticText(panel,wx.ID_ANY,' '+lbl)
901            mainSizer.Add(topLabl,0,wx.ALIGN_LEFT,10)
902            self.ChItems.append(wx.Choice(self, wx.ID_ANY, (100, 50), choices = choice))
903            mainSizer.Add(self.ChItems[-1],0,wx.ALIGN_CENTER,10)
904
905        OkBtn = wx.Button(panel,-1,"Ok")
906        OkBtn.Bind(wx.EVT_BUTTON, self.OnOk)
907        cancelBtn = wx.Button(panel,-1,"Cancel")
908        cancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel)
909        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
910        btnSizer.Add((20,20),1)
911        btnSizer.Add(OkBtn)
912        btnSizer.Add((20,20),1)
913        btnSizer.Add(cancelBtn)
914        btnSizer.Add((20,20),1)
915        mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
916        panel.SetSizer(mainSizer)
917        panel.Fit()
918        self.Fit()
919       
920    def OnOk(self,event):
921        parent = self.GetParent()
922        if parent is not None: parent.Raise()
923        # save the results from the choice widgets
924        self.chosen = []
925        for w in self.ChItems:
926            self.chosen.append(w.GetSelection())
927        self.EndModal(wx.ID_OK)             
928           
929    def OnCancel(self,event):
930        parent = self.GetParent()
931        if parent is not None: parent.Raise()
932        self.chosen = []
933        self.EndModal(wx.ID_CANCEL)             
934           
935def ExtractFileFromZip(filename, selection=None, confirmread=True,
936                       confirmoverwrite=True, parent=None,
937                       multipleselect=False):
938    '''If the filename is a zip file, extract a file from that archive.
939      selection is used to predefine the name of the file to be extracted
940         filename case and zip directory name are ignored in selection;
941         the first matching file is used
942      confirmread if True asks the user to confirm before expanding
943         the only file in a zip
944      confirmoverwrite if True asks the user to confirm before
945        overwriting if the extracted file already exists
946      multipleselect if True allows more than one zip file to be extracted,
947        a list of file(s) is returned
948    If only one file is present, do not ask which one, otherwise offer a
949       list of choices (unless selection is used)
950    Return the name of the file that has been created or a list of files (see multipleselect)
951      If the file is not a zipfile, return the name of the input file.
952      If the zipfile is empty or no file has been selected, return None
953    '''
954    import zipfile # do this now, since we can save startup time by doing this only on need
955    import shutil
956    zloc = os.path.split(filename)[0]
957    if not zipfile.is_zipfile(filename):
958        #print("not zip")
959        return filename
960
961    z = zipfile.ZipFile(filename,'r')
962    zinfo = z.infolist()
963
964    if len(zinfo) == 0:
965        #print('Zip has no files!')
966        zlist = [-1]
967    if selection:
968        choices = [os.path.split(i.filename)[1].lower() for i in zinfo]
969        if selection.lower() in choices:
970            zlist = [choices.index(selection.lower())]
971        else:
972            print('debug: file '+str(selection)+' was not found in '+str(filename))
973            zlist = [-1]
974    elif len(zinfo) == 1 and confirmread:
975        result = wx.ID_NO
976        dlg = wx.MessageDialog(
977            parent,
978            'Is file '+str(zinfo[0].filename)+
979            ' what you want to extract from '+
980            str(os.path.split(filename)[1])+'?',
981            'Confirm file', 
982            wx.YES_NO | wx.ICON_QUESTION)
983        try:
984            result = dlg.ShowModal()
985        finally:
986            dlg.Destroy()
987        if result == wx.ID_NO:
988            zlist = [-1]
989        else:
990            zlist = [0]
991    elif len(zinfo) == 1:
992        zlist = [0]
993    elif multipleselect:
994        # select one or more from a from list
995        choices = [i.filename for i in zinfo]
996        dlg = wx.MultiChoiceDialog(
997            parent,
998            'Select file(s) to extract from zip file'+str(filename),
999            'Choose file(s)',
1000            choices,
1001            wx.CHOICEDLG_STYLE,
1002            )
1003        if dlg.ShowModal() == wx.ID_OK:
1004            zlist = dlg.GetSelections()
1005            dlg.Destroy()
1006        else:
1007            dlg.Destroy()
1008            zlist = []
1009    else:
1010        # select one from a from list
1011        choices = [i.filename for i in zinfo]
1012        dlg = wx.SingleChoiceDialog(
1013            parent,
1014            'Select file to extract from zip file'+str(filename),
1015            'Choose file',
1016            choices,
1017            )
1018        if dlg.ShowModal() == wx.ID_OK:
1019            zlist = [dlg.GetSelection()]
1020            dlg.Destroy()
1021        else:
1022            dlg.Destroy()
1023            zlist = [-1]
1024       
1025    outlist = []
1026    for zindex in zlist:
1027        if zindex >= 0:
1028            efil = os.path.join(zloc, os.path.split(zinfo[zindex].filename)[1])
1029            if os.path.exists(efil) and confirmoverwrite:
1030                result = wx.ID_NO
1031                dlg = wx.MessageDialog(
1032                    parent,
1033                    'File '+str(efil)+' already exists. OK to overwrite it?',
1034                    'Confirm overwrite', 
1035                    wx.YES_NO | wx.ICON_QUESTION)
1036                try:
1037                    result = dlg.ShowModal()
1038                finally:
1039                    dlg.Destroy()
1040                if result == wx.ID_NO:
1041                    zindex = -1
1042        if zindex >= 0:
1043            # extract the file to the current directory, regardless of it's original path
1044            #z.extract(zinfo[zindex],zloc)
1045            eloc,efil = os.path.split(zinfo[zindex].filename)
1046            outfile = os.path.join(zloc, efil)
1047            fpin = z.open(zinfo[zindex])
1048            fpout = file(outfile, "wb")
1049            shutil.copyfileobj(fpin, fpout)
1050            fpin.close()
1051            fpout.close()
1052            outlist.append(outfile)
1053    z.close()
1054    if multipleselect and len(outlist) >= 1:
1055        return outlist
1056    elif len(outlist) == 1:
1057        return outlist[0]
1058    else:
1059        return None
1060
1061######################################################################
1062# base classes for reading various types of data files
1063#   not used directly, only by subclassing
1064######################################################################
1065E,SGData = G2spc.SpcGroup('P 1') # data structure for default space group
1066class ImportBaseclass(object):
1067    '''Defines a base class for the importing of data files (diffraction
1068    data, coordinates,...
1069    '''
1070    def __init__(self,
1071                 formatName,
1072                 longFormatName=None,
1073                 extensionlist=[],
1074                 strictExtension=False,
1075                 ):
1076        self.formatName = formatName # short string naming file type
1077        if longFormatName: # longer string naming file type
1078            self.longFormatName = longFormatName
1079        else:
1080            self.longFormatName = formatName
1081        # define extensions that are allowed for the file type
1082        # for windows, remove any extensions that are duplicate, as case is ignored
1083        if sys.platform == 'windows' and extensionlist:
1084            extensionlist = list(set([s.lower() for s in extensionlist]))
1085        self.extensionlist = extensionlist
1086        # If strictExtension is True, the file will not be read, unless
1087        # the extension matches one in the extensionlist
1088        self.strictExtension = strictExtension
1089        self.warnings = ''
1090        self.errors = ''
1091        # used for readers that will use multiple passes to read
1092        # more than one data block
1093        self.repeat = False
1094        self.repeatcount = 0
1095        #print 'created',self.__class__
1096
1097    def BlockSelector(self, ChoiceList, ParentFrame=None,
1098                      title='Select a block',
1099                      size=None, header='Block Selector'):
1100        ''' Provide a wx dialog to select a block if the file contains more
1101        than one set of data and one must be selected
1102        '''
1103        dlg = wx.SingleChoiceDialog(
1104            ParentFrame,
1105            title, header,
1106            ChoiceList,
1107            )
1108        if size: dlg.SetSize(size)
1109        if dlg.ShowModal() == wx.ID_OK:
1110            sel = dlg.GetSelection()
1111            dlg.Destroy()
1112            return sel
1113        else:
1114            dlg.Destroy()
1115            return None
1116
1117    def MultipleBlockSelector(self, ChoiceList, ParentFrame=None,
1118                      title='Select a block',
1119                      size=None, header='Block Selector'):
1120        ''' Provide a wx dialog to select a block of data if the file contains more
1121        than one set of data and one must be selected.
1122        Returns a list of the selected blocks
1123        '''
1124        dlg = wx.MultiChoiceDialog(
1125            ParentFrame,
1126            title, header,
1127            ChoiceList+['Select all'],
1128            wx.CHOICEDLG_STYLE
1129            )
1130        if size: dlg.SetSize(size)
1131        if dlg.ShowModal() == wx.ID_OK:
1132            sel = dlg.GetSelections()
1133            dlg.Destroy()
1134        else:
1135            dlg.Destroy()
1136            return []
1137        selected = []
1138        if len(ChoiceList) in sel:
1139            return range(len(ChoiceList))
1140        else:
1141            return sel
1142        return selected
1143
1144    def MultipleChoicesDialog(self, choicelist, headinglist, ParentFrame=None, **kwargs):
1145        '''A modal dialog that offers a series of choices, each with a title and a wx.Choice
1146        widget.
1147        typical input:
1148           choicelist=[ ('a','b','c'), ('test1','test2'),('no choice',)]
1149           headinglist = [ 'select a, b or c', 'select 1 of 2', 'No option here']
1150        optional keyword parameters are: head (window title) and title
1151        returns a list of selected indicies for each choice (or None)
1152        '''
1153        result = None
1154        dlg = MultipleChoicesDialog(choicelist,headinglist,
1155                                    parent=ParentFrame, **kwargs)         
1156        if dlg.ShowModal() == wx.ID_OK:
1157            result = dlg.chosen
1158        dlg.Destroy()
1159        return result
1160
1161    def ShowBusy(self):
1162        wx.BeginBusyCursor()
1163
1164    def DoneBusy(self):
1165        wx.EndBusyCursor()
1166       
1167#    def Reader(self, filename, filepointer, ParentFrame=None, **unused):
1168#        '''This method must be supplied in the child class
1169#        it will read the file
1170#        '''
1171#        return True # if read OK
1172#        return False # if an error occurs
1173
1174    def ExtensionValidator(self, filename):
1175        '''This methods checks if the file has the correct extension
1176        Return False if this filename will not be supported by this reader
1177        Return True if the extension matches the list supplied by the reader
1178        Return None if the reader allows un-registered extensions
1179        '''
1180        if filename:
1181            ext = os.path.splitext(filename)[1]
1182            if sys.platform == 'windows': ext = ext.lower()
1183            if ext in self.extensionlist: return True
1184            if self.strictExtension: return False
1185        return None
1186
1187    def ContentsValidator(self, filepointer):
1188        '''This routine will attempt to determine if the file can be read
1189        with the current format.
1190        This will typically be overridden with a method that
1191        takes a quick scan of [some of]
1192        the file contents to do a "sanity" check if the file
1193        appears to match the selected format.
1194        Expected to be called via self.Validator()
1195        '''
1196        #filepointer.seek(0) # rewind the file pointer
1197        return True
1198
1199class ImportPhase(ImportBaseclass):
1200    '''Defines a base class for the reading of files with coordinates
1201    '''
1202    def __init__(self,formatName,longFormatName=None,extensionlist=[],
1203        strictExtension=False,):
1204        # call parent __init__
1205        ImportBaseclass.__init__(self,formatName,longFormatName,
1206            extensionlist,strictExtension)
1207        # define a default Phase structure
1208        self.Phase = SetNewPhase(Name='new phase',SGData=SGData)
1209
1210    def PhaseSelector(self, ChoiceList, ParentFrame=None,
1211        title='Select a phase', size=None,header='Phase Selector'):
1212        ''' Provide a wx dialog to select a phase if the file contains more
1213        than one phase
1214        '''
1215        return self.BlockSelector(ChoiceList,ParentFrame,title,
1216            size,header)
1217
1218######################################################################
1219class ImportStructFactor(ImportBaseclass):
1220    '''Defines a base class for the reading of files with tables
1221    of structure factors
1222    '''
1223    def __init__(self,formatName,longFormatName=None,extensionlist=[],
1224        strictExtension=False,):
1225        ImportBaseclass.__init__(self,formatName,longFormatName,
1226            extensionlist,strictExtension)
1227
1228        # define contents of Structure Factor entry
1229        self.Controls = { # dictionary with plotting controls
1230            'Type' : 'Fosq',
1231            'ifFc' : False,    #
1232            'HKLmax' : [None,None,None],
1233            'HKLmin' : [None,None,None],
1234            'FoMax' : None,   # maximum observed structure factor as Fo
1235            'Zone' : '001',
1236            'Layer' : 0,
1237            'Scale' : 1.0,
1238            'log-lin' : 'lin',
1239            }
1240        self.Parameters = [ # list with data collection parameters
1241            ('SXC',0.70926),
1242            ['SXC',0.70926],
1243            ['Type','Lam']
1244            ]
1245        self.RefList = []
1246
1247    def UpdateParameters(self,Type=None,Wave=None):
1248        HistType = self.Parameters[0][0]
1249        HistWave = self.Parameters[0][1]
1250        if Type is not None:
1251            HistType = Type
1252        if Wave is not None:
1253            HistWave = Wave
1254        self.Parameters = [(HistType,HistWave),[HistType,HistWave],  # overwrite entire list
1255            ['Type','Lam']]
1256           
1257    def UpdateControls(self,Type='Fosq',FcalcPresent=False):
1258        '''Scan through the reflections to update the Controls dictionary
1259        '''
1260        self.Controls['Type'] = Type
1261        self.Controls['ifFc'] = FcalcPresent
1262        HKLmax = [None,None,None]
1263        HKLmin = [None,None,None]
1264        Fo2max = None
1265        for refl in self.RefList:
1266            HKL = refl[:3]
1267            if Fo2max is None:
1268                Fo2max = refl[8]
1269            else:
1270                Fo2max = max(Fo2max,refl[8])
1271            for i,hkl in enumerate(HKL):
1272                if HKLmax[i] is None:
1273                    HKLmax[i] = hkl
1274                    HKLmin[i] = hkl
1275                else:
1276                    HKLmax[i] = max(HKLmax[i],hkl)
1277                    HKLmin[i] = min(HKLmin[i],hkl)
1278        self.Controls['HKLmax'] = HKLmax
1279        self.Controls['HKLmin'] = HKLmin
1280        if Type ==  'Fosq':
1281            self.Controls['FoMax'] = np.sqrt(Fo2max)
1282        elif Type ==  'Fo':
1283            self.Controls['FoMax'] = Fo2max
1284        else:
1285            print "Unsupported Struct Fact type in ImportStructFactor.UpdateControls"
1286            raise Exception,"Unsupported Struct Fact type in ImportStructFactor.UpdateControls"
1287
1288######################################################################
1289class ImportPowderData(ImportBaseclass):
1290    '''Defines a base class for the reading of files with powder data
1291    '''
1292    # define some default instrument parameter files
1293    # just like GSAS, sigh
1294    defaultIparm_lbl = []
1295    defaultIparms = []
1296    defaultIparm_lbl.append('CuKa lab data')
1297    defaultIparms.append({
1298        'INS   HTYPE ':'PXC ',
1299        'INS  1 ICONS':'  1.540500  1.544300       0.0         0       0.7    0       0.5   ',
1300        'INS  1PRCF1 ':'    3    8      0.01                                                ',
1301        'INS  1PRCF11':'   2.000000E+00  -2.000000E+00   5.000000E+00   0.000000E+00        ',
1302        'INS  1PRCF12':'   0.000000E+00   0.000000E+00   0.150000E-01   0.150000E-01        ',
1303        })
1304    defaultIparm_lbl.append('0.6A synch')
1305    defaultIparms.append({
1306        'INS   HTYPE ':'PXC ',
1307        'INS  1 ICONS':'  0.600000  0.000000       0.0         0      0.99    0       0.5   ',
1308        'INS  1PRCF1 ':'    3    8      0.01                                                ',
1309        'INS  1PRCF11':'   1.000000E+00  -1.000000E+00   0.300000E+00   0.000000E+00        ',
1310        'INS  1PRCF12':'   0.000000E+00   0.000000E+00   0.100000E-01   0.100000E-01        ',
1311        })
1312    defaultIparm_lbl.append('1.5A CW neutron data')
1313    defaultIparms.append({
1314        'INS   HTYPE ':'PNC',
1315        'INS  1 ICONS':'   1.54020   0.00000   0.04000         0',
1316        'INS  1PRCF1 ':'    3    8      0.01                                                ',
1317        'INS  1PRCF1 ':'    3    8     0.005',
1318        'INS  1PRCF11':'   0.239700E+03  -0.298200E+03   0.180800E+03   0.000000E+00',
1319        'INS  1PRCF12':'   0.000000E+00   0.000000E+00   0.400000E-01   0.300000E-01',
1320        })
1321    def __init__(self,
1322                 formatName,
1323                 longFormatName=None,
1324                 extensionlist=[],
1325                 strictExtension=False,
1326                 ):
1327        ImportBaseclass.__init__(self,formatName,
1328                                            longFormatName,
1329                                            extensionlist,
1330                                            strictExtension)
1331        self.powderentry = ['',None,None] #  (filename,Pos,Bank)
1332        self.powderdata = [] # Powder dataset
1333        '''A powder data set is a list with items [x,y,w,yc,yb,yd]:
1334                np.array(x), # x-axis values
1335                np.array(y), # powder pattern intensities
1336                np.array(w), # 1/sig(intensity)^2 values (weights)
1337                np.array(yc), # calc. intensities (zero)
1338                np.array(yb), # calc. background (zero)
1339                np.array(yd), # obs-calc profiles
1340        '''                           
1341        self.comments = []
1342        self.idstring = ''
1343        self.Sample = G2pdG.SetDefaultSample()
1344        self.instparm = None # name hint
1345        self.instfile = '' # full path name to instrument parameter file
1346        self.instbank = '' # inst parm bank number
1347        self.instmsg = ''  # a label that gets printed to show
1348                           # where instrument parameters are from
1349        self.numbanks = 1
1350        self.instdict = {} # place items here that will be transferred to the instrument parameters
1351
1352if __name__ == '__main__':
1353    app = wx.PySimpleApp()
1354    frm = wx.Frame(None) # create a frame
1355    frm.Show(True)
1356    filename = '/tmp/notzip.zip'
1357    filename = '/tmp/all.zip'
1358    #filename = '/tmp/11bmb_7652.zip'
1359   
1360    #selection=None, confirmoverwrite=True, parent=None
1361    #print ExtractFileFromZip(filename, selection='11bmb_7652.fxye',parent=frm)
1362    print ExtractFileFromZip(filename,multipleselect=True)
1363                             #confirmread=False, confirmoverwrite=False)
1364
1365    # choicelist=[ ('a','b','c'),
1366    #              ('test1','test2'),('no choice',)]
1367    # titles = [ 'a, b or c', 'tests', 'No option here']
1368    # dlg = MultipleChoicesDialog(
1369    #     choicelist,titles,
1370    #     parent=frm)
1371    # if dlg.ShowModal() == wx.ID_OK:
1372    #     print 'Got OK'
Note: See TracBrowser for help on using the repository browser.