source: trunk/GSASIIIO.py @ 947

Last change on this file since 947 was 944, checked in by vondreele, 12 years ago

fix l/r u/d issues in some images (MAR mostly)

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