source: trunk/GSASIIIO.py @ 824

Last change on this file since 824 was 824, checked in by vondreele, 9 years ago

added read of edf (European data file) image files
more work on texture restraints - no derivatives yet

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