source: trunk/GSASIIIO.py @ 938

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

Add instrument name support; add export menu & CIF testing

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 72.0 KB
Line 
1# -*- coding: utf-8 -*-
2########### SVN repository information ###################
3# $Date: 2013-05-31 23:14:01 +0000 (Fri, 31 May 2013) $
4# $Author: toby $
5# $Revision: 938 $
6# $URL: trunk/GSASIIIO.py $
7# $Id: GSASIIIO.py 938 2013-05-31 23:14:01Z 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: 938 $")
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=None,cell=None):
949    '''Create a new phase with default values for various parameters
950
951    :param str Name: Name for new Phase
952
953    :param dict SGData: space group data from :func:`GSASIIspc:SpcGroup`;
954      defaults to data for P 1
955
956    :param list cell: unit cell parameter list; defaults to
957      [1.0,1.0,1.0,90.,90,90.,1.]
958
959    '''
960    if SGData is None: SGData = G2spc.SpcGroup('P 1')[1]
961    if cell is None: cell=[1.0,1.0,1.0,90.,90,90.,1.]
962    phaseData = {
963        'ranId':ran.randint(0,sys.maxint),
964        'General':{
965            'Name':Name,
966            'Type':'nuclear',
967            'SGData':SGData,
968            'Cell':[False,]+cell,
969            'Pawley dmin':1.0,
970            'Data plot type':'None',
971            'SH Texture':{
972                'Order':0,
973                'Model':'cylindrical',
974                'Sample omega':[False,0.0],
975                'Sample chi':[False,0.0],
976                'Sample phi':[False,0.0],
977                'SH Coeff':[False,{}],
978                'SHShow':False,
979                'PFhkl':[0,0,1],
980                'PFxyz':[0,0,1],
981                'PlotType':'Pole figure'}},
982        'Atoms':[],
983        'Drawing':{},
984        'Histograms':{},
985        'Pawley ref':[],
986        'RBModels':{},
987        }
988    return phaseData
989   
990def ReadEXPPhase(G2frame,filename):
991    '''Read a phase from a GSAS .EXP file.
992    Called in the GSAS phase import routine (see imports/G2phase.py)
993    '''
994    shModels = ['cylindrical','none','shear - 2/m','rolling - mmm']
995    textureData = {'Order':0,'Model':'cylindrical','Sample omega':[False,0.0],
996        'Sample chi':[False,0.0],'Sample phi':[False,0.0],'SH Coeff':[False,{}],
997        'SHShow':False,'PFhkl':[0,0,1],'PFxyz':[0,0,1],'PlotType':'Pole figure'}
998    shNcof = 0
999    file = open(filename, 'Ur')
1000    S = 1
1001    Expr = [{},{},{},{},{},{},{},{},{}]
1002    while S:
1003        S = file.readline()
1004        if 'EXPR NPHAS' in S[:12]:
1005            Num = S[12:-1].count('0')
1006            NPhas = S[12:-1].split()
1007        if 'CRS' in S[:3]:
1008            N = int(S[3:4])-1
1009            Expr[N][S[:12]] = S[12:-1]
1010    file.close()
1011    PNames = []
1012    for n,N in enumerate(NPhas):
1013        if N != '0':
1014            result = n
1015            key = 'CRS'+str(n+1)+'    PNAM'
1016            PNames.append(Expr[n][key])
1017    if Num < 8:
1018        dlg = wx.SingleChoiceDialog(G2frame, 'Which phase to read?', 'Read phase data', PNames, wx.CHOICEDLG_STYLE)
1019        try:
1020            if dlg.ShowModal() == wx.ID_OK:
1021                result = dlg.GetSelection()
1022        finally:
1023            dlg.Destroy()       
1024    EXPphase = Expr[result]
1025    keyList = EXPphase.keys()
1026    keyList.sort()
1027    SGData = {}
1028    if NPhas[result] == '1':
1029        Ptype = 'nuclear'
1030    elif NPhas[result] in ['2','3']:
1031        Ptype = 'magnetic'
1032    elif NPhas[result] == '4':
1033        Ptype = 'macromolecular'
1034    elif NPhas[result] == '10':
1035        Ptype = 'Pawley'
1036    for key in keyList:
1037        if 'PNAM' in key:
1038           PhaseName = EXPphase[key].strip()
1039        elif 'ABC   ' in key:
1040            abc = [float(EXPphase[key][:10]),float(EXPphase[key][10:20]),float(EXPphase[key][20:30])]                       
1041        elif 'ANGLES' in key:
1042            angles = [float(EXPphase[key][:10]),float(EXPphase[key][10:20]),float(EXPphase[key][20:30])]                                               
1043        elif 'SG SYM' in key:
1044            SpGrp = EXPphase[key][:15].strip()
1045            E,SGData = G2spc.SpcGroup(SpGrp)
1046            if E:
1047                E,SGData = G2spc.SpcGroup('P 1') # unlikely to need this
1048        elif 'OD    ' in key:
1049            SHdata = EXPphase[key].split() # may not have all 9 values
1050            SHvals = 9*[0]
1051            for i in range(9):
1052                try:
1053                    float(SHdata[i])
1054                    SHvals[i] = SHdata[i]
1055                except:
1056                    pass
1057            textureData['Order'] = int(SHvals[0])
1058            textureData['Model'] = shModels[int(SHvals[2])]
1059            textureData['Sample omega'] = [False,float(SHvals[6])]
1060            textureData['Sample chi'] = [False,float(SHvals[7])]
1061            textureData['Sample phi'] = [False,float(SHvals[8])]
1062            shNcof = int(SHvals[1])
1063    Atoms = []
1064    if Ptype == 'nuclear':
1065        for key in keyList:
1066            if 'AT' in key:
1067                if key[11:] == 'A':
1068                    S = EXPphase[key]
1069                elif key[11:] == 'B':
1070                    S += EXPphase[key]
1071                    Atom = [S[50:58].strip(),S[:10].strip(),'',
1072                        float(S[10:20]),float(S[20:30]),float(S[30:40]),
1073                        float(S[40:50]),'',int(S[60:62]),S[130:131]]
1074                    if Atom[9] == 'I':
1075                        Atom += [float(S[68:78]),0.,0.,0.,0.,0.,0.]
1076                    elif Atom[9] == 'A':
1077                        Atom += [0.0,float(S[68:78]),float(S[78:88]),
1078                            float(S[88:98]),float(S[98:108]),
1079                            float(S[108:118]),float(S[118:128])]
1080                    XYZ = Atom[3:6]
1081                    Atom[7],Atom[8] = G2spc.SytSym(XYZ,SGData)
1082                    Atom.append(ran.randint(0,sys.maxint))
1083                    Atoms.append(Atom)
1084    elif Ptype == 'macromolecular':
1085        for key in keyList:
1086            if 'AT' in key[6:8]:
1087                S = EXPphase[key]
1088                Atom = [S[56:60],S[50:54].strip().upper(),S[54:56],
1089                    S[46:51].strip(),S[:8].strip(),'',
1090                    float(S[16:24]),float(S[24:32]),float(S[32:40]),
1091                    float(S[8:16]),'1',1,'I',float(S[40:46]),0,0,0,0,0,0]
1092                XYZ = Atom[6:9]
1093                Atom[10],Atom[11] = G2spc.SytSym(XYZ,SGData)
1094                Atom.append(ran.randint(0,sys.maxint))
1095                Atoms.append(Atom)
1096    Volume = G2lat.calc_V(G2lat.cell2A(abc+angles))
1097    if shNcof:
1098        shCoef = {}
1099        nRec = [i+1 for i in range((shNcof-1)/6+1)]
1100        for irec in nRec:
1101            ODkey = keyList[0][:6]+'OD'+'%3dA'%(irec)
1102            indx = EXPphase[ODkey].split()
1103            ODkey = ODkey[:-1]+'B'
1104            vals = EXPphase[ODkey].split()
1105            for i,val in enumerate(vals):
1106                key = 'C(%s,%s,%s)'%(indx[3*i],indx[3*i+1],indx[3*i+2])
1107                shCoef[key] = float(val)
1108        textureData['SH Coeff'] = [False,shCoef]
1109       
1110    Phase = SetNewPhase(Name=PhaseName,SGData=SGData,cell=abc+angles+[Volume,])
1111    general = Phase['General']
1112    general['Type'] = Ptype
1113    general['SH Texture'] = textureData
1114    Phase['Atoms'] = Atoms
1115    return Phase
1116       
1117def ReadPDBPhase(filename):
1118    '''Read a phase from a PDB file.
1119    Called in the PDB phase import routine (see imports/G2phase.py)
1120    '''
1121    EightPiSq = 8.*math.pi**2
1122    file = open(filename, 'Ur')
1123    Phase = {}
1124    Title = ''
1125    Compnd = ''
1126    Atoms = []
1127    A = np.zeros(shape=(3,3))
1128    S = file.readline()
1129    while S:
1130        Atom = []
1131        if 'TITLE' in S[:5]:
1132            Title = S[10:72].strip()
1133            S = file.readline()
1134        elif 'COMPND    ' in S[:10]:
1135            Compnd = S[10:72].strip()
1136            S = file.readline()
1137        elif 'CRYST' in S[:5]:
1138            abc = S[7:34].split()
1139            angles = S[34:55].split()
1140            cell=[float(abc[0]),float(abc[1]),float(abc[2]),
1141                float(angles[0]),float(angles[1]),float(angles[2])]
1142            Volume = G2lat.calc_V(G2lat.cell2A(cell))
1143            AA,AB = G2lat.cell2AB(cell)
1144            SpGrp = S[55:65]
1145            E,SGData = G2spc.SpcGroup(SpGrp)
1146            # space group processing failed, try to look up name in table
1147            if E:
1148                SpGrpNorm = G2spc.StandardizeSpcName(SpGrp)
1149                if SpGrpNorm:
1150                    E,SGData = G2spc.SpcGroup(SpGrpNorm)
1151            while E:
1152                print G2spc.SGErrors(E)
1153                dlg = wx.TextEntryDialog(None,
1154                    SpGrp[:-1]+' is invalid \nN.B.: make sure spaces separate axial fields in symbol',
1155                    'ERROR in space group symbol','',style=wx.OK)
1156                if dlg.ShowModal() == wx.ID_OK:
1157                    SpGrp = dlg.GetValue()
1158                    E,SGData = G2spc.SpcGroup(SpGrp)
1159                else:
1160                    return None
1161                dlg.Destroy()               
1162            SGlines = G2spc.SGPrint(SGData)
1163            for line in SGlines: print line
1164            S = file.readline()
1165        elif 'SCALE' in S[:5]:
1166            V = (S[10:41].split())
1167            A[int(S[5])-1] = [float(V[0]),float(V[1]),float(V[2])]
1168            S = file.readline()
1169        elif 'ATOM' in S[:4] or 'HETATM' in S[:6]:
1170            XYZ = [float(S[31:39]),float(S[39:47]),float(S[47:55])]
1171            XYZ = np.inner(AB,XYZ)
1172            XYZ = np.where(abs(XYZ)<0.00001,0,XYZ)
1173            SytSym,Mult = G2spc.SytSym(XYZ,SGData)
1174            Uiso = float(S[61:67])/EightPiSq
1175            Type = S[12:14].upper()
1176            if Type[0] in '123456789':
1177                Type = Type[1:]
1178            Atom = [S[22:27].strip(),S[17:20].upper(),S[20:22],
1179                S[12:17].strip(),Type.strip(),'',XYZ[0],XYZ[1],XYZ[2],
1180                float(S[55:61]),SytSym,Mult,'I',Uiso,0,0,0,0,0,0]
1181            S = file.readline()
1182            if 'ANISOU' in S[:6]:
1183                Uij = S[30:72].split()
1184                Uij = [float(Uij[0])/10000.,float(Uij[1])/10000.,float(Uij[2])/10000.,
1185                    float(Uij[3])/10000.,float(Uij[4])/10000.,float(Uij[5])/10000.]
1186                Atom = Atom[:14]+Uij
1187                Atom[12] = 'A'
1188                S = file.readline()
1189            Atom.append(ran.randint(0,sys.maxint))
1190            Atoms.append(Atom)
1191        else:           
1192            S = file.readline()
1193    file.close()
1194    if Title:
1195        PhaseName = Title
1196    elif Compnd:
1197        PhaseName = Compnd
1198    else:
1199        PhaseName = 'None'
1200    Phase = SetNewPhase(Name=PhaseName,SGData=SGData,cell=cell+[Volume,])
1201    Phase['General']['Type'] = 'macromolecular'
1202    Phase['Atoms'] = Atoms
1203   
1204    return Phase
1205
1206class MultipleChoicesDialog(wx.Dialog):
1207    '''A dialog that offers a series of choices, each with a
1208    title and a wx.Choice widget. Intended to be used Modally.
1209    typical input:
1210
1211        *  choicelist=[ ('a','b','c'), ('test1','test2'),('no choice',)]
1212        *  headinglist = [ 'select a, b or c', 'select 1 of 2', 'No option here']
1213       
1214    selections are placed in self.chosen when OK is pressed
1215    '''
1216    def __init__(self,choicelist,headinglist,
1217                 head='Select options',
1218                 title='Please select from options below',
1219                 parent=None):
1220        self.chosen = []
1221        wx.Dialog.__init__(
1222            self,parent,wx.ID_ANY,head, 
1223            pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE)
1224        panel = wx.Panel(self)
1225        mainSizer = wx.BoxSizer(wx.VERTICAL)
1226        mainSizer.Add((10,10),1)
1227        topLabl = wx.StaticText(panel,wx.ID_ANY,title)
1228        mainSizer.Add(topLabl,0,wx.ALIGN_CENTER_VERTICAL|wx.CENTER,10)
1229        self.ChItems = []
1230        for choice,lbl in zip(choicelist,headinglist):
1231            mainSizer.Add((10,10),1)
1232            self.chosen.append(0)
1233            topLabl = wx.StaticText(panel,wx.ID_ANY,' '+lbl)
1234            mainSizer.Add(topLabl,0,wx.ALIGN_LEFT,10)
1235            self.ChItems.append(wx.Choice(self, wx.ID_ANY, (100, 50), choices = choice))
1236            mainSizer.Add(self.ChItems[-1],0,wx.ALIGN_CENTER,10)
1237
1238        OkBtn = wx.Button(panel,-1,"Ok")
1239        OkBtn.Bind(wx.EVT_BUTTON, self.OnOk)
1240        cancelBtn = wx.Button(panel,-1,"Cancel")
1241        cancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel)
1242        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
1243        btnSizer.Add((20,20),1)
1244        btnSizer.Add(OkBtn)
1245        btnSizer.Add((20,20),1)
1246        btnSizer.Add(cancelBtn)
1247        btnSizer.Add((20,20),1)
1248        mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
1249        panel.SetSizer(mainSizer)
1250        panel.Fit()
1251        self.Fit()
1252       
1253    def OnOk(self,event):
1254        parent = self.GetParent()
1255        if parent is not None: parent.Raise()
1256        # save the results from the choice widgets
1257        self.chosen = []
1258        for w in self.ChItems:
1259            self.chosen.append(w.GetSelection())
1260        self.EndModal(wx.ID_OK)             
1261           
1262    def OnCancel(self,event):
1263        parent = self.GetParent()
1264        if parent is not None: parent.Raise()
1265        self.chosen = []
1266        self.EndModal(wx.ID_CANCEL)             
1267           
1268def ExtractFileFromZip(filename, selection=None, confirmread=True,
1269                       confirmoverwrite=True, parent=None,
1270                       multipleselect=False):
1271    '''If the filename is a zip file, extract a file from that
1272    archive.
1273
1274    :param list Selection: used to predefine the name of the file
1275      to be extracted. Filename case and zip directory name are
1276      ignored in selection; the first matching file is used.
1277
1278    :param bool confirmread: if True asks the user to confirm before expanding
1279      the only file in a zip
1280
1281    :param bool confirmoverwrite: if True asks the user to confirm
1282      before overwriting if the extracted file already exists
1283
1284    :param bool multipleselect: if True allows more than one zip
1285      file to be extracted, a list of file(s) is returned.
1286      If only one file is present, do not ask which one, otherwise
1287      offer a list of choices (unless selection is used).
1288   
1289    :returns: the name of the file that has been created or a
1290      list of files (see multipleselect)
1291
1292    If the file is not a zipfile, return the name of the input file.
1293    If the zipfile is empty or no file has been selected, return None
1294    '''
1295    import zipfile # do this now, since we can save startup time by doing this only on need
1296    import shutil
1297    zloc = os.path.split(filename)[0]
1298    if not zipfile.is_zipfile(filename):
1299        #print("not zip")
1300        return filename
1301
1302    z = zipfile.ZipFile(filename,'r')
1303    zinfo = z.infolist()
1304
1305    if len(zinfo) == 0:
1306        #print('Zip has no files!')
1307        zlist = [-1]
1308    if selection:
1309        choices = [os.path.split(i.filename)[1].lower() for i in zinfo]
1310        if selection.lower() in choices:
1311            zlist = [choices.index(selection.lower())]
1312        else:
1313            print('debug: file '+str(selection)+' was not found in '+str(filename))
1314            zlist = [-1]
1315    elif len(zinfo) == 1 and confirmread:
1316        result = wx.ID_NO
1317        dlg = wx.MessageDialog(
1318            parent,
1319            'Is file '+str(zinfo[0].filename)+
1320            ' what you want to extract from '+
1321            str(os.path.split(filename)[1])+'?',
1322            'Confirm file', 
1323            wx.YES_NO | wx.ICON_QUESTION)
1324        try:
1325            result = dlg.ShowModal()
1326        finally:
1327            dlg.Destroy()
1328        if result == wx.ID_NO:
1329            zlist = [-1]
1330        else:
1331            zlist = [0]
1332    elif len(zinfo) == 1:
1333        zlist = [0]
1334    elif multipleselect:
1335        # select one or more from a from list
1336        choices = [i.filename for i in zinfo]
1337        dlg = wx.MultiChoiceDialog(parent,'Select file(s) to extract from zip file'+str(filename),
1338            'Choose file(s)',choices,wx.CHOICEDLG_STYLE,)
1339        if dlg.ShowModal() == wx.ID_OK:
1340            zlist = dlg.GetSelections()
1341        else:
1342            zlist = []
1343        dlg.Destroy()
1344    else:
1345        # select one from a from list
1346        choices = [i.filename for i in zinfo]
1347        dlg = wx.SingleChoiceDialog(parent,
1348            'Select file to extract from zip file'+str(filename),'Choose file',
1349            choices,)
1350        if dlg.ShowModal() == wx.ID_OK:
1351            zlist = [dlg.GetSelection()]
1352        else:
1353            zlist = [-1]
1354        dlg.Destroy()
1355       
1356    outlist = []
1357    for zindex in zlist:
1358        if zindex >= 0:
1359            efil = os.path.join(zloc, os.path.split(zinfo[zindex].filename)[1])
1360            if os.path.exists(efil) and confirmoverwrite:
1361                result = wx.ID_NO
1362                dlg = wx.MessageDialog(parent,
1363                    'File '+str(efil)+' already exists. OK to overwrite it?',
1364                    'Confirm overwrite',wx.YES_NO | wx.ICON_QUESTION)
1365                try:
1366                    result = dlg.ShowModal()
1367                finally:
1368                    dlg.Destroy()
1369                if result == wx.ID_NO:
1370                    zindex = -1
1371        if zindex >= 0:
1372            # extract the file to the current directory, regardless of it's original path
1373            #z.extract(zinfo[zindex],zloc)
1374            eloc,efil = os.path.split(zinfo[zindex].filename)
1375            outfile = os.path.join(zloc, efil)
1376            fpin = z.open(zinfo[zindex])
1377            fpout = file(outfile, "wb")
1378            shutil.copyfileobj(fpin, fpout)
1379            fpin.close()
1380            fpout.close()
1381            outlist.append(outfile)
1382    z.close()
1383    if multipleselect and len(outlist) >= 1:
1384        return outlist
1385    elif len(outlist) == 1:
1386        return outlist[0]
1387    else:
1388        return None
1389
1390######################################################################
1391# base classes for reading various types of data files
1392#   not used directly, only by subclassing
1393######################################################################
1394E,SGData = G2spc.SpcGroup('P 1') # data structure for default space group
1395class ImportBaseclass(object):
1396    '''Defines a base class for the importing of data files (diffraction
1397    data, coordinates,...
1398    '''
1399    def __init__(self,
1400                 formatName,
1401                 longFormatName=None,
1402                 extensionlist=[],
1403                 strictExtension=False,
1404                 ):
1405        self.formatName = formatName # short string naming file type
1406        if longFormatName: # longer string naming file type
1407            self.longFormatName = longFormatName
1408        else:
1409            self.longFormatName = formatName
1410        # define extensions that are allowed for the file type
1411        # for windows, remove any extensions that are duplicate, as case is ignored
1412        if sys.platform == 'windows' and extensionlist:
1413            extensionlist = list(set([s.lower() for s in extensionlist]))
1414        self.extensionlist = extensionlist
1415        # If strictExtension is True, the file will not be read, unless
1416        # the extension matches one in the extensionlist
1417        self.strictExtension = strictExtension
1418        self.warnings = ''
1419        # used for readers that will use multiple passes to read
1420        # more than one data block
1421        self.repeat = False
1422        self.repeatcount = 0
1423        #print 'created',self.__class__
1424
1425    def BlockSelector(self, ChoiceList, ParentFrame=None,
1426                      title='Select a block',
1427                      size=None, header='Block Selector',
1428                      useCancel=True):
1429        ''' Provide a wx dialog to select a block if the file contains more
1430        than one set of data and one must be selected
1431        '''
1432        if useCancel:
1433            dlg = wx.SingleChoiceDialog(
1434                ParentFrame,title, header,ChoiceList)
1435        else:
1436            dlg = wx.SingleChoiceDialog(
1437                ParentFrame,title, header,ChoiceList,
1438                style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER|wx.OK|wx.CENTRE)
1439        if size: dlg.SetSize(size)
1440        if dlg.ShowModal() == wx.ID_OK:
1441            sel = dlg.GetSelection()
1442            return sel
1443        else:
1444            return None
1445        dlg.Destroy()
1446
1447    def MultipleBlockSelector(self, ChoiceList, ParentFrame=None,
1448        title='Select a block',size=None, header='Block Selector'):
1449        '''Provide a wx dialog to select a block of data if the
1450        file contains more than one set of data and one must be
1451        selected.
1452
1453        :returns: a list of the selected blocks
1454        '''
1455        dlg = wx.MultiChoiceDialog(ParentFrame,title, header,ChoiceList+['Select all'],
1456            wx.CHOICEDLG_STYLE)
1457        if size: dlg.SetSize(size)
1458        if dlg.ShowModal() == wx.ID_OK:
1459            sel = dlg.GetSelections()
1460        else:
1461            return []
1462        dlg.Destroy()
1463        selected = []
1464        if len(ChoiceList) in sel:
1465            return range(len(ChoiceList))
1466        else:
1467            return sel
1468        return selected
1469
1470    def MultipleChoicesDialog(self, choicelist, headinglist, ParentFrame=None, **kwargs):
1471        '''A modal dialog that offers a series of choices, each with a title and a wx.Choice
1472        widget. Typical input:
1473       
1474           * choicelist=[ ('a','b','c'), ('test1','test2'),('no choice',)]
1475           
1476           * headinglist = [ 'select a, b or c', 'select 1 of 2', 'No option here']
1477           
1478        optional keyword parameters are: head (window title) and title
1479        returns a list of selected indicies for each choice (or None)
1480        '''
1481        result = None
1482        dlg = MultipleChoicesDialog(choicelist,headinglist,
1483            parent=ParentFrame, **kwargs)         
1484        if dlg.ShowModal() == wx.ID_OK:
1485            result = dlg.chosen
1486        dlg.Destroy()
1487        return result
1488
1489    def ShowBusy(self):
1490        wx.BeginBusyCursor()
1491
1492    def DoneBusy(self):
1493        wx.EndBusyCursor()
1494       
1495#    def Reader(self, filename, filepointer, ParentFrame=None, **unused):
1496#        '''This method must be supplied in the child class
1497#        it will read the file
1498#        '''
1499#        return True # if read OK
1500#        return False # if an error occurs
1501
1502    def ExtensionValidator(self, filename):
1503        '''This methods checks if the file has the correct extension
1504        Return False if this filename will not be supported by this reader
1505        Return True if the extension matches the list supplied by the reader
1506        Return None if the reader allows un-registered extensions
1507        '''
1508        if filename:
1509            ext = os.path.splitext(filename)[1]
1510            if sys.platform == 'windows': ext = ext.lower()
1511            if ext in self.extensionlist: return True
1512            if self.strictExtension: return False
1513        return None
1514
1515    def ContentsValidator(self, filepointer):
1516        '''This routine will attempt to determine if the file can be read
1517        with the current format.
1518        This will typically be overridden with a method that
1519        takes a quick scan of [some of]
1520        the file contents to do a "sanity" check if the file
1521        appears to match the selected format.
1522        Expected to be called via self.Validator()
1523        '''
1524        #filepointer.seek(0) # rewind the file pointer
1525        return True
1526
1527class ImportPhase(ImportBaseclass):
1528    '''Defines a base class for the reading of files with coordinates
1529    '''
1530    def __init__(self,formatName,longFormatName=None,extensionlist=[],
1531        strictExtension=False,):
1532        # call parent __init__
1533        ImportBaseclass.__init__(self,formatName,longFormatName,
1534            extensionlist,strictExtension)
1535        # define a default Phase structure
1536        self.Phase = SetNewPhase(Name='new phase',SGData=SGData)
1537
1538    def PhaseSelector(self, ChoiceList, ParentFrame=None,
1539        title='Select a phase', size=None,header='Phase Selector'):
1540        ''' Provide a wx dialog to select a phase if the file contains more
1541        than one phase
1542        '''
1543        return self.BlockSelector(ChoiceList,ParentFrame,title,
1544            size,header)
1545
1546######################################################################
1547class ExportBaseclass(object):
1548    '''Defines a base class for the exporting of GSAS-II results
1549    '''
1550    def __init__(self,
1551                 G2frame,
1552                 formatName,
1553                 longFormatName=None,
1554                 ):
1555        self.G2frame = G2frame
1556        self.formatName = formatName # short string naming file type
1557        if longFormatName: # longer string naming file type
1558            self.longFormatName = longFormatName
1559        else:
1560            self.longFormatName = formatName
1561        self.OverallParms = {}
1562        self.GroupedParms = {}
1563    def loadTree(self):
1564        '''Load the contents of the data tree into a pair of dicts.
1565       
1566        The childrenless data tree items are overall parameters/controls for the
1567        entire project and are placed in self.OverallParms
1568
1569        The data tree items with children are either Phase items or are
1570        data of some sort. Date entries begin with a key, such as
1571        PWDR, IMG, HKLF,... that identifies the data type.
1572        * Phase items are placed in self.GroupedParms["Phases"][item]
1573        * Data items are placed in self.GroupedParms["Phases"][key][item]
1574
1575          Note that there is no overall phase information, only information
1576          stored for each phase, but there is overall information for each
1577          data item. The overall data information is stored in
1578          self.GroupedParms["Phases"][key][None]
1579       
1580        '''
1581        self.OverallParms = {}
1582        self.GroupedParms = {}
1583        G2frame = self.G2frame
1584        if G2frame.PatternTree.IsEmpty(): return # nothing to do
1585        item, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
1586        while item:
1587            name = G2frame.PatternTree.GetItemText(item)
1588            item2, cookie2 = G2frame.PatternTree.GetFirstChild(item)
1589            if item2: 
1590                key = name.split()[0]
1591                if name == "Phases":
1592                    self.GroupedParms[name] = {}
1593                    d = self.GroupedParms[name]
1594                else:
1595                    if self.GroupedParms.get(key) is None:
1596                        self.GroupedParms[key] = {}
1597                    self.GroupedParms[key][name] = {}
1598                    self.GroupedParms[key][name][None] = G2frame.PatternTree.GetItemPyData(item)
1599                    d = self.GroupedParms[key][name]
1600                while item2:
1601                    name = G2frame.PatternTree.GetItemText(item2)
1602                    d[name] = G2frame.PatternTree.GetItemPyData(item2)
1603                    item2, cookie2 = G2frame.PatternTree.GetNextChild(item, cookie2)                           
1604            else:
1605                self.OverallParms[name] = G2frame.PatternTree.GetItemPyData(item)
1606            item, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
1607
1608    def dumpTree(self,mode='type'):
1609        '''Print out information on the data tree dicts loaded in loadTree
1610        '''
1611        print '\nOverall'
1612        if mode == 'type':
1613            def Show(arg): return type(arg)
1614        else:
1615            def Show(arg): return arg
1616        for key in self.OverallParms:
1617            print '  ',key,Show(self.OverallParms[key])
1618        print '\nGrouped'
1619        for key in self.GroupedParms:
1620            if key == "Phases":
1621                print '  Phases'
1622                for key1 in self.GroupedParms[key]:
1623                    print '    ',key1,Show(self.GroupedParms[key][key1])
1624            else:
1625                print '  ',key,Show(self.GroupedParms[key])
1626                for key1 in self.GroupedParms[key]:
1627                    print '    ',key1,Show(self.GroupedParms[key][key1][None])
1628                    for key2 in self.GroupedParms[key][key1]:
1629                        print '      ',key2,Show(self.GroupedParms[key][key1][key2])
1630
1631######################################################################
1632class ImportStructFactor(ImportBaseclass):
1633    '''Defines a base class for the reading of files with tables
1634    of structure factors
1635    '''
1636    def __init__(self,formatName,longFormatName=None,extensionlist=[],
1637        strictExtension=False,):
1638        ImportBaseclass.__init__(self,formatName,longFormatName,
1639            extensionlist,strictExtension)
1640
1641        # define contents of Structure Factor entry
1642        self.Controls = { # dictionary with plotting controls
1643            'Type' : 'Fosq',
1644            'ifFc' : False,    #
1645            'HKLmax' : [None,None,None],
1646            'HKLmin' : [None,None,None],
1647            'FoMax' : None,   # maximum observed structure factor as Fo
1648            'Zone' : '001',
1649            'Layer' : 0,
1650            'Scale' : 1.0,
1651            'log-lin' : 'lin',
1652            }
1653        self.Parameters = [ # list with data collection parameters
1654            ('SXC',0.70926),
1655            ['SXC',0.70926],
1656            ['Type','Lam']
1657            ]
1658        self.RefList = []
1659
1660    def UpdateParameters(self,Type=None,Wave=None):
1661        HistType = self.Parameters[0][0]
1662        HistWave = self.Parameters[0][1]
1663        if Type is not None:
1664            HistType = Type
1665        if Wave is not None:
1666            HistWave = Wave
1667        self.Parameters = [{'Type':[HistType,HistType],'Lam':[HistWave,HistWave]},{}]  # overwrite entire list
1668           
1669    def UpdateControls(self,Type='Fosq',FcalcPresent=False):
1670        '''Scan through the reflections to update the Controls dictionary
1671        '''
1672        self.Controls['Type'] = Type
1673        self.Controls['ifFc'] = FcalcPresent
1674        HKLmax = [None,None,None]
1675        HKLmin = [None,None,None]
1676        Fo2max = None
1677        for refl in self.RefList:
1678            HKL = refl[:3]
1679            if Fo2max is None:
1680                Fo2max = refl[8]
1681            else:
1682                Fo2max = max(Fo2max,refl[8])
1683            for i,hkl in enumerate(HKL):
1684                if HKLmax[i] is None:
1685                    HKLmax[i] = hkl
1686                    HKLmin[i] = hkl
1687                else:
1688                    HKLmax[i] = max(HKLmax[i],hkl)
1689                    HKLmin[i] = min(HKLmin[i],hkl)
1690        self.Controls['HKLmax'] = HKLmax
1691        self.Controls['HKLmin'] = HKLmin
1692        if Type ==  'Fosq':
1693            self.Controls['FoMax'] = np.sqrt(Fo2max)
1694        elif Type ==  'Fo':
1695            self.Controls['FoMax'] = Fo2max
1696        else:
1697            print "Unsupported Struct Fact type in ImportStructFactor.UpdateControls"
1698            raise Exception,"Unsupported Struct Fact type in ImportStructFactor.UpdateControls"
1699
1700######################################################################
1701class ImportPowderData(ImportBaseclass):
1702    '''Defines a base class for the reading of files with powder data
1703    '''
1704    # define some default instrument parameter files
1705    # just like GSAS, sigh
1706    defaultIparm_lbl = []
1707    defaultIparms = []
1708    defaultIparm_lbl.append('CuKa lab data')
1709    defaultIparms.append({
1710        'INS   HTYPE ':'PXC ',
1711        'INS  1 ICONS':'  1.540500  1.544300       0.0         0       0.7    0       0.5   ',
1712        'INS  1PRCF1 ':'    3    8      0.01                                                ',
1713        'INS  1PRCF11':'   2.000000E+00  -2.000000E+00   5.000000E+00   0.000000E+00        ',
1714        'INS  1PRCF12':'   0.000000E+00   0.000000E+00   0.150000E-01   0.150000E-01        ',
1715        })
1716    defaultIparm_lbl.append('0.6A synch')
1717    defaultIparms.append({
1718        'INS   HTYPE ':'PXC ',
1719        'INS  1 ICONS':'  0.600000  0.000000       0.0         0      0.99    0       0.5   ',
1720        'INS  1PRCF1 ':'    3    8      0.01                                                ',
1721        'INS  1PRCF11':'   1.000000E+00  -1.000000E+00   0.300000E+00   0.000000E+00        ',
1722        'INS  1PRCF12':'   0.000000E+00   0.000000E+00   0.100000E-01   0.100000E-01        ',
1723        })
1724    defaultIparm_lbl.append('1.5A CW neutron data')
1725    defaultIparms.append({
1726        'INS   HTYPE ':'PNC',
1727        'INS  1 ICONS':'   1.54020   0.00000   0.04000         0',
1728        'INS  1PRCF1 ':'    3    8     0.005',
1729        'INS  1PRCF11':'   0.239700E+03  -0.298200E+03   0.180800E+03   0.000000E+00',
1730        'INS  1PRCF12':'   0.000000E+00   0.000000E+00   0.400000E-01   0.300000E-01',
1731        })
1732    defaultIparm_lbl.append('10m TOF backscattering bank')
1733    defaultIparms.append({
1734        'INS   HTYPE ':'PNT',
1735        'INS  1 ICONS':'   5000.00      0.00      0.00',
1736        'INS  1BNKPAR':'    1.0000   150.000',       
1737        'INS  1PRCF1 ':'    1    8   0.01000',
1738        'INS  1PRCF11':'   0.000000E+00   5.000000E+00   3.000000E-02   1.000000E-03',
1739        'INS  1PRCF12':'   0.000000E+00   4.000000E+01   0.000000E+00   0.000000E+00',       
1740        })
1741    defaultIparm_lbl.append('10m TOF 90deg bank')
1742    defaultIparms.append({
1743        'INS   HTYPE ':'PNT',
1744        'INS  1 ICONS':'   3500.00      0.00      0.00',
1745        'INS  1BNKPAR':'    1.0000    90.000',       
1746        'INS  1PRCF1 ':'    1    8   0.01000',
1747        'INS  1PRCF11':'   0.000000E+00   5.000000E+00   3.000000E-02   4.000000E-03',
1748        'INS  1PRCF12':'   0.000000E+00   8.000000E+01   0.000000E+00   0.000000E+00',       
1749        })
1750    defaultIparm_lbl.append('63m POWGEN 90deg bank')
1751    defaultIparms.append({
1752        'INS   HTYPE ':'PNT',
1753        'INS  1 ICONS':'  22585.80      0.00      0.00',
1754        'INS  1BNKPAR':'    1.0000    90.000',       
1755        'INS  1PRCF1 ':'    1    8   0.01000',
1756        'INS  1PRCF11':'   0.000000E+00   1.000000E+00   3.000000E-02   4.000000E-03',
1757        'INS  1PRCF12':'   0.000000E+00   8.000000E+01   0.000000E+00   0.000000E+00',       
1758        })
1759    def __init__(self,
1760                 formatName,
1761                 longFormatName=None,
1762                 extensionlist=[],
1763                 strictExtension=False,
1764                 ):
1765        ImportBaseclass.__init__(self,formatName,
1766                                            longFormatName,
1767                                            extensionlist,
1768                                            strictExtension)
1769        self.powderentry = ['',None,None] #  (filename,Pos,Bank)
1770        self.powderdata = [] # Powder dataset
1771        '''A powder data set is a list with items [x,y,w,yc,yb,yd]:
1772                np.array(x), # x-axis values
1773                np.array(y), # powder pattern intensities
1774                np.array(w), # 1/sig(intensity)^2 values (weights)
1775                np.array(yc), # calc. intensities (zero)
1776                np.array(yb), # calc. background (zero)
1777                np.array(yd), # obs-calc profiles
1778        '''                           
1779        self.comments = []
1780        self.idstring = ''
1781        self.Sample = G2pdG.SetDefaultSample()
1782        self.GSAS = None     # used in TOF
1783        self.clockWd = None  # used in TOF
1784        self.repeat_instparm = True # Should a parm file be
1785        #                             used for multiple histograms?
1786        self.instparm = None # name hint
1787        self.instfile = '' # full path name to instrument parameter file
1788        self.instbank = '' # inst parm bank number
1789        self.instmsg = ''  # a label that gets printed to show
1790                           # where instrument parameters are from
1791        self.numbanks = 1
1792        self.instdict = {} # place items here that will be transferred to the instrument parameters
1793
1794if __name__ == '__main__':
1795    app = wx.PySimpleApp()
1796    frm = wx.Frame(None) # create a frame
1797    frm.Show(True)
1798    filename = '/tmp/notzip.zip'
1799    filename = '/tmp/all.zip'
1800    #filename = '/tmp/11bmb_7652.zip'
1801   
1802    #selection=None, confirmoverwrite=True, parent=None
1803    #print ExtractFileFromZip(filename, selection='11bmb_7652.fxye',parent=frm)
1804    print ExtractFileFromZip(filename,multipleselect=True)
1805                             #confirmread=False, confirmoverwrite=False)
1806
1807    # choicelist=[ ('a','b','c'),
1808    #              ('test1','test2'),('no choice',)]
1809    # titles = [ 'a, b or c', 'tests', 'No option here']
1810    # dlg = MultipleChoicesDialog(
1811    #     choicelist,titles,
1812    #     parent=frm)
1813    # if dlg.ShowModal() == wx.ID_OK:
1814    #     print 'Got OK'
Note: See TracBrowser for help on using the repository browser.