source: trunk/GSASIIIO.py @ 649

Last change on this file since 649 was 649, checked in by vondreele, 10 years ago

read Joel Bernier's tiff images - not done yet
finish negative Pawley reflection issues - now works fine.

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