source: trunk/GSASIIIO.py @ 923

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

more doc updates

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