source: branch/2frame/GSASIIscriptable.py @ 2967

Last change on this file since 2967 was 2967, checked in by toby, 6 years ago

misc changes for sphinx docs

File size: 50.3 KB
Line 
1# -*- coding: utf-8 -*-
2########### SVN repository information ###################
3# $Date: 2017-04-12 15:12:45 -0500 (Wed, 12 Apr 2017) $
4# $Author: vondreele $
5# $Revision: 2777 $
6# $URL: https://subversion.xray.aps.anl.gov/pyGSAS/trunk/GSASIIscriptable.py $
7# $Id: GSASIIIO.py 2777 2017-04-12 20:12:45Z vondreele $
8########### SVN repository information ###################
9"""
10*GSASIIscriptable: Scripting Tools*
11-----------------------------------
12
13Routines for reading, writing, modifying and creating GSAS-II project (.gpx) files.
14
15"""
16from __future__ import division, print_function # needed?
17import os.path as ospath
18import sys
19import cPickle
20import imp
21import copy
22import platform
23import os
24import random as ran
25import json
26
27import numpy.ma as ma
28import scipy.interpolate as si
29import numpy as np
30import scipy as sp
31import matplotlib as mpl
32
33import GSASIIpath
34GSASIIpath.SetBinaryPath() # would rather have this in __name__ == '__main__' stanza
35import GSASIIIO as G2IO
36import GSASIIfiles as G2fil
37import GSASIIobj as G2obj
38import GSASIIpwd as G2pwd
39import GSASIIstrIO as G2strIO
40import GSASIIspc as G2spc
41import GSASIIstrMain as G2strMain
42import GSASIImath as G2mth
43import GSASIIElem as G2elem
44
45def LoadDictFromProjFile(ProjFile):
46    '''Read a GSAS-II project file and load items to dictionary
47    :param str ProjFile: GSAS-II project (name.gpx) full file name
48    :returns: Project,nameList, where
49   
50      * Project (dict) is a representation of gpx file following the GSAS-II tree struture
51        for each item: key = tree name (e.g. 'Controls','Restraints',etc.), data is dict
52        data dict = {'data':item data whch may be list, dict or None,'subitems':subdata (if any)}
53      * nameList (list) has names of main tree entries & subentries used to reconstruct project file
54
55    Example for fap.gpx::
56   
57      Project = {                 #NB:dict order is not tree order
58        u'Phases':{'data':None,'fap':{phase dict}},
59        u'PWDR FAP.XRA Bank 1':{'data':[histogram data list],'Comments':comments,'Limits':limits, etc},
60        u'Rigid bodies':{'data': {rigid body dict}},
61        u'Covariance':{'data':{covariance data dict}},
62        u'Controls':{'data':{controls data dict}},
63        u'Notebook':{'data':[notebook list]},
64        u'Restraints':{'data':{restraint data dict}},
65        u'Constraints':{'data':{constraint data dict}}]
66        }
67      nameList = [                #NB: reproduces tree order
68        [u'Notebook',],
69        [u'Controls',],
70        [u'Covariance',],
71        [u'Constraints',],
72        [u'Restraints',],
73        [u'Rigid bodies',],
74        [u'PWDR FAP.XRA Bank 1',
75             u'Comments',
76             u'Limits',
77             u'Background',
78             u'Instrument Parameters',
79             u'Sample Parameters',
80             u'Peak List',
81             u'Index Peak List',
82             u'Unit Cells List',
83             u'Reflection Lists'],
84        [u'Phases', u'fap']
85        ]
86       
87    '''
88    if not ospath.exists(ProjFile):
89        print ('\n*** Error attempt to open project file that does not exist:\n   '+
90            str(ProjFile))
91        return
92    file = open(ProjFile,'rb')
93    print('loading from file: {}'.format(ProjFile))
94    Project = {}
95    nameList = []
96    try:
97        while True:
98            try:
99                data = cPickle.load(file)
100            except EOFError:
101                break
102            datum = data[0]
103            Project[datum[0]] = {'data':datum[1]}
104            nameList.append([datum[0],])
105            for datus in data[1:]:
106                Project[datum[0]][datus[0]] = datus[1]
107                nameList[-1].append(datus[0])
108        file.close()
109        print('project load successful')
110    except:
111        print("Error reading file "+str(ProjFile)+". This is not a GSAS-II .gpx file")
112        return None
113    return Project,nameList
114   
115def SaveDictToProjFile(Project,nameList,ProjFile):
116    '''Save a GSAS-II project file from dictionary/nameList created by LoadDictFromProjFile
117   
118    :param dict Project: representation of gpx file following the GSAS-II
119      tree structure as described for LoadDictFromProjFile
120    :param list nameList: names of main tree entries & subentries used to reconstruct project file
121    :param str ProjFile: full file name for output project.gpx file (including extension)
122   
123    '''
124    file = open(ProjFile,'wb')
125    print('save to file: {}'.format(ProjFile))
126    for name in nameList:
127        data = []
128        item = Project[name[0]]
129        data.append([name[0],item['data']])
130        for item2 in name[1:]:
131            data.append([item2,item[item2]])
132        cPickle.dump(data,file,1)
133    file.close()
134    print('project save successful')
135   
136def ImportPowder(reader,filename):
137    '''Use a reader to import a powder diffraction data file
138   
139    :param str reader: a scriptable reader
140    :param str filename: full name of powder data file; can be "multi-Bank" data
141   
142    :returns: list rdlist: list of rrader objects containing powder data, one for each
143      "Bank" of data encountered in file. Items in reader object of interest are:
144     
145        * rd.comments: list of str: comments found on powder file
146        * rd.dnames: list of str: data nammes suitable for use in GSASII data tree NB: duplicated in all rd entries in rdlist
147        * rd.powderdata: list of numpy arrays: pos,int,wt,zeros,zeros,zeros as needed for a PWDR entry in  GSASII data tree.
148             
149    '''
150    rdfile,rdpath,descr = imp.find_module(reader)
151    rdclass = imp.load_module(reader,rdfile,rdpath,descr)
152    rd = rdclass.GSAS_ReaderClass()   
153    if not rd.scriptable:
154        print(u'**** ERROR: '+reader+u' is not a scriptable reader')
155        return None
156    fl = open(filename,'rb')
157    rdlist = []
158    if rd.ContentsValidator(fl):
159        fl.seek(0)
160        repeat = True
161        rdbuffer = {} # create temporary storage for file reader
162        block = 0
163        while repeat: # loop if the reader asks for another pass on the file
164            block += 1
165            repeat = False
166            rd.objname = ospath.basename(filename)
167            flag = rd.Reader(filename,fl,None,buffer=rdbuffer,blocknum=block,)
168            if flag:
169                rdlist.append(copy.deepcopy(rd)) # save the result before it is written over
170                if rd.repeat:
171                    repeat = True
172        return rdlist
173    print(rd.errors)
174    return None
175   
176def SetDefaultDData(dType,histoName,NShkl=0,NDij=0):
177    '''Create an initial Histogram dictionary
178   
179    Author: Jackson O'Donnell jacksonhodonnell@gmail.com
180    '''
181    if dType in ['SXC','SNC']:
182        return {'Histogram':histoName,'Show':False,'Scale':[1.0,True],
183            'Babinet':{'BabA':[0.0,False],'BabU':[0.0,False]},
184            'Extinction':['Lorentzian','None', {'Tbar':0.1,'Cos2TM':0.955,
185            'Eg':[1.e-10,False],'Es':[1.e-10,False],'Ep':[1.e-10,False]}],
186            'Flack':[0.0,False]}
187    elif dType == 'SNT':
188        return {'Histogram':histoName,'Show':False,'Scale':[1.0,True],
189            'Babinet':{'BabA':[0.0,False],'BabU':[0.0,False]},
190            'Extinction':['Lorentzian','None', {
191            'Eg':[1.e-10,False],'Es':[1.e-10,False],'Ep':[1.e-10,False]}]}
192    elif 'P' in dType:
193        return {'Histogram':histoName,'Show':False,'Scale':[1.0,False],
194            'Pref.Ori.':['MD',1.0,False,[0,0,1],0,{},[],0.1],
195            'Size':['isotropic',[1.,1.,1.],[False,False,False],[0,0,1],
196                [1.,1.,1.,0.,0.,0.],6*[False,]],
197            'Mustrain':['isotropic',[1000.0,1000.0,1.0],[False,False,False],[0,0,1],
198                NShkl*[0.01,],NShkl*[False,]],
199            'HStrain':[NDij*[0.0,],NDij*[False,]],
200            'Extinction':[0.0,False],'Babinet':{'BabA':[0.0,False],'BabU':[0.0,False]}}
201
202
203def PreSetup(data):
204    '''Create part of an initial (empty) phase dictionary
205   
206    from GSASIIphsGUI.py, near end of UpdatePhaseData
207    Author: Jackson O'Donnell jacksonhodonnell@gmail.com
208    '''
209    if 'RBModels' not in data:
210        data['RBModels'] = {}
211    if 'MCSA' not in data:
212        data['MCSA'] = {'Models':[{'Type':'MD','Coef':[1.0,False,[.8,1.2],],'axis':[0,0,1]}],'Results':[],'AtInfo':{}}
213    if 'dict' in str(type(data['MCSA']['Results'])):
214        data['MCSA']['Results'] = []
215    if 'Modulated' not in data['General']:
216        data['General']['Modulated'] = False
217    if 'modulated' in data['General']['Type']:
218        data['General']['Modulated'] = True
219        data['General']['Type'] = 'nuclear'
220
221
222def SetupGeneral(data, dirname):
223    """Helps initialize phase data.
224
225    From GSASIIphsGui.py, function of the same name. Minor changes for imports etc.
226    Author: Jackson O'Donnell jacksonhodonnell@gmail.com
227    """
228    mapDefault = {'MapType':'','RefList':'','Resolution':0.5,'Show bonds':True,
229                'rho':[],'rhoMax':0.,'mapSize':10.0,'cutOff':50.,'Flip':False}
230    generalData = data['General']
231    atomData = data['Atoms']
232    generalData['AtomTypes'] = []
233    generalData['Isotopes'] = {}
234
235    if 'Isotope' not in generalData:
236        generalData['Isotope'] = {}
237    if 'Data plot type' not in generalData:
238        generalData['Data plot type'] = 'Mustrain'
239    if 'POhkl' not in generalData:
240        generalData['POhkl'] = [0,0,1]
241    if 'Map' not in generalData:
242        generalData['Map'] = mapDefault.copy()
243    if 'Flip' not in generalData:
244        generalData['Flip'] = {'RefList':'','Resolution':0.5,'Norm element':'None',
245            'k-factor':0.1,'k-Max':20.,}
246    if 'testHKL' not in generalData['Flip']:
247        generalData['Flip']['testHKL'] = [[0,0,2],[2,0,0],[1,1,1],[0,2,0],[1,2,3]]
248    if 'doPawley' not in generalData:
249        generalData['doPawley'] = False     #ToDo: change to ''
250    if 'Pawley dmin' not in generalData:
251        generalData['Pawley dmin'] = 1.0
252    if 'Pawley neg wt' not in generalData:
253        generalData['Pawley neg wt'] = 0.0
254    if 'Algolrithm' in generalData.get('MCSA controls',{}) or \
255        'MCSA controls' not in generalData:
256        generalData['MCSA controls'] = {'Data source':'','Annealing':[50.,0.001,50],
257        'dmin':2.0,'Algorithm':'log','Jump coeff':[0.95,0.5],'boltzmann':1.0,
258        'fast parms':[1.0,1.0,1.0],'log slope':0.9,'Cycles':1,'Results':[],'newDmin':True}
259    if 'AtomPtrs' not in generalData:
260        generalData['AtomPtrs'] = [3,1,7,9]
261        if generalData['Type'] == 'macromolecular':
262            generalData['AtomPtrs'] = [6,4,10,12]
263        elif generalData['Type'] == 'magnetic':
264            generalData['AtomPtrs'] = [3,1,10,12]
265    if generalData['Type'] in ['modulated',]:
266        generalData['Modulated'] = True
267        generalData['Type'] = 'nuclear'
268        if 'Super' not in generalData:
269            generalData['Super'] = 1
270            generalData['SuperVec'] = [[0,0,.1],False,4]
271            generalData['SSGData'] = {}
272        if '4DmapData' not in generalData:
273            generalData['4DmapData'] = mapDefault.copy()
274            generalData['4DmapData'].update({'MapType':'Fobs'})
275    if 'Modulated' not in generalData:
276        generalData['Modulated'] = False
277    if 'HydIds' not in generalData:
278        generalData['HydIds'] = {}
279    cx,ct,cs,cia = generalData['AtomPtrs']
280    generalData['NoAtoms'] = {}
281    generalData['BondRadii'] = []
282    generalData['AngleRadii'] = []
283    generalData['vdWRadii'] = []
284    generalData['AtomMass'] = []
285    generalData['Color'] = []
286    if generalData['Type'] == 'magnetic':
287        generalData['MagDmin'] = generalData.get('MagDmin',1.0)
288        landeg = generalData.get('Lande g',[])
289    generalData['Mydir'] = dirname
290    badList = {}
291    for iat,atom in enumerate(atomData):
292        atom[ct] = atom[ct].lower().capitalize()              #force to standard form
293        if generalData['AtomTypes'].count(atom[ct]):
294            generalData['NoAtoms'][atom[ct]] += atom[cx+3]*float(atom[cs+1])
295        elif atom[ct] != 'UNK':
296            Info = G2elem.GetAtomInfo(atom[ct])
297            if not Info:
298                if atom[ct] not in badList:
299                    badList[atom[ct]] = 0
300                badList[atom[ct]] += 1
301                atom[ct] = 'UNK'
302                continue
303            atom[ct] = Info['Symbol'] # N.B. symbol might be changed by GetAtomInfo
304            generalData['AtomTypes'].append(atom[ct])
305            generalData['Z'] = Info['Z']
306            generalData['Isotopes'][atom[ct]] = Info['Isotopes']
307            generalData['BondRadii'].append(Info['Drad'])
308            generalData['AngleRadii'].append(Info['Arad'])
309            generalData['vdWRadii'].append(Info['Vdrad'])
310            if atom[ct] in generalData['Isotope']:
311                if generalData['Isotope'][atom[ct]] not in generalData['Isotopes'][atom[ct]]:
312                    isotope = generalData['Isotopes'][atom[ct]].keys()[-1]
313                    generalData['Isotope'][atom[ct]] = isotope
314                generalData['AtomMass'].append(Info['Isotopes'][generalData['Isotope'][atom[ct]]]['Mass'])
315            else:
316                generalData['Isotope'][atom[ct]] = 'Nat. Abund.'
317                if 'Nat. Abund.' not in generalData['Isotopes'][atom[ct]]:
318                    isotope = generalData['Isotopes'][atom[ct]].keys()[-1]
319                    generalData['Isotope'][atom[ct]] = isotope
320                generalData['AtomMass'].append(Info['Mass'])
321            generalData['NoAtoms'][atom[ct]] = atom[cx+3]*float(atom[cs+1])
322            generalData['Color'].append(Info['Color'])
323            if generalData['Type'] == 'magnetic':
324                if len(landeg) < len(generalData['AtomTypes']):
325                    landeg.append(2.0)
326    if generalData['Type'] == 'magnetic':
327        generalData['Lande g'] = landeg[:len(generalData['AtomTypes'])]
328
329    if badList:
330        msg = 'Warning: element symbol(s) not found:'
331        for key in badList:
332            msg += '\n\t' + key
333            if badList[key] > 1:
334                msg += ' (' + str(badList[key]) + ' times)'
335        raise Exception("Phase error:\n" + msg)
336        # wx.MessageBox(msg,caption='Element symbol error')
337    F000X = 0.
338    F000N = 0.
339    for i,elem in enumerate(generalData['AtomTypes']):
340        F000X += generalData['NoAtoms'][elem]*generalData['Z']
341        isotope = generalData['Isotope'][elem]
342        F000N += generalData['NoAtoms'][elem]*generalData['Isotopes'][elem][isotope]['SL'][0]
343    generalData['F000X'] = F000X
344    generalData['F000N'] = F000N
345    generalData['Mass'] = G2mth.getMass(generalData)
346
347def make_empty_project(author=None, filename=None):
348    """Creates an dictionary in the style of GSASIIscriptable, for an empty
349    project.
350
351    If no author name or filename is supplied, 'no name' and
352    <current dir>/test_output.gpx are used , respectively.
353
354    Returns: project dictionary, name list
355    Author: Jackson O'Donnell jacksonhodonnell@gmail.com
356    """
357    if not filename:
358        filename = os.path.join(os.getcwd(), 'test_output.gpx')
359    else:
360        filename = os.path.abspath(filename)
361    gsasii_version = str(GSASIIpath.GetVersionNumber())
362    python_library_versions = G2fil.get_python_versions([mpl, np, sp])
363
364    controls_data = dict(G2obj.DefaultControls)
365    controls_data['LastSavedAs'] = unicode(filename)
366    controls_data['LastSavedUsing'] = gsasii_version
367    controls_data['PythonVersions'] = python_library_versions
368    if author:
369        controls_data['Author'] = author
370
371    output = {'Constraints': {'data': {'HAP': [], 'Hist': [], 'Phase': [],
372                                       'Global': []}},
373              'Controls': {'data': controls_data},
374              u'Covariance': {'data': {}},
375              u'Notebook': {'data': ['']},
376              u'Restraints': {'data': {}},
377              u'Rigid bodies': {'data': {'RBIds': {'Residue': [], 'Vector': []},
378                                'Residue': {'AtInfo': {}},
379                                'Vector':  {'AtInfo': {}}}}}
380
381    names = [[u'Notebook'], [u'Controls'], [u'Covariance'],
382             [u'Constraints'], [u'Restraints'], [u'Rigid bodies']]
383
384    return output, names
385
386
387class G2ImportException(Exception):
388    pass
389
390
391def import_generic(filename, readerlist):
392    """Attempt to import a filename, using a list of reader objects.
393
394    Returns the first reader object which worked."""
395    # Translated from OnImportGeneric method in GSASII.py
396    primaryReaders, secondaryReaders = [], []
397    for reader in readerlist:
398        flag = reader.ExtensionValidator(filename)
399        if flag is None:
400            secondaryReaders.append(reader)
401        elif flag:
402            primaryReaders.append(reader)
403    if not secondaryReaders and not primaryReaders:
404        raise G2ImportException("Could not read file: ", filename)
405
406    with open(filename, 'Ur') as fp:
407        rd_list = []
408
409        for rd in primaryReaders + secondaryReaders:
410            # Initialize reader
411            rd.selections = []
412            rd.dnames = []
413            rd.ReInitialize()
414            # Rewind file
415            fp.seek(0)
416            rd.errors = ""
417            if not rd.ContentsValidator(fp):
418                # Report error
419                pass
420            if len(rd.selections) > 1:
421                # Select data?
422                # GSASII.py:543
423                raise G2ImportException("Not sure what data to select")
424
425            block = 0
426            rdbuffer = {}
427            fp.seek(0)
428            repeat = True
429            while repeat:
430                repeat = False
431                block += 1
432                rd.objname = os.path.basename(filename)
433                flag = rd.Reader(filename, fp, buffer=rdbuffer, blocknum=block)
434                if flag:
435                    # Omitting image loading special cases
436                    rd.readfilename = filename
437                    rd_list.append(copy.deepcopy(rd))
438                    repeat = rd.repeat
439                else:
440                    raise G2ImportException("{}.Reader() returned:".format(rd),
441                                            flag)
442
443            if rd_list:
444                if rd.warnings:
445                    print("Read warning by", rd.formatName, "reader:",
446                          rd.warnings, file=sys.stderr)
447                return rd_list
448    raise G2ImportException("No reader could read file: " + filename)
449
450
451def load_iprms(instfile, reader):
452    """Loads instrument parameters from a file, and edits the
453    given reader.
454
455    Returns a 2-tuple of (Iparm1, Iparm2) parameters
456    """
457    ext = os.path.splitext(instfile)[1]
458
459    if ext.lower() == '.instprm':
460        # New GSAS File, load appropriately
461        with open(instfile) as f:
462            lines = f.readlines()
463        bank = reader.powderentry[2]
464        numbanks = reader.numbanks
465        iparms = G2fil.ReadPowderInstprm(lines, bank, numbanks, reader)
466
467        reader.instfile = instfile
468        reader.instmsg = 'GSAS-II file' + instfile
469        return iparms
470    elif ext.lower() not in ('.prm', '.inst', '.ins'):
471        raise ValueError('Expected .prm file, found: ', instfile)
472
473    # It's an old GSAS file, load appropriately
474    Iparm = {}
475    with open(instfile, 'Ur') as fp:
476        for line in fp:
477            if '#' in line:
478                continue
479            Iparm[line[:12]] = line[12:-1]
480    ibanks = int(Iparm.get('INS   BANK  ', '1').strip())
481    if ibanks == 1:
482        reader.instbank = 1
483        reader.powderentry[2] = 1
484        reader.instfile = instfile
485        reader.instmsg = instfile + ' bank ' + str(reader.instbank)
486        return G2fil.SetPowderInstParms(Iparm, reader)
487    # TODO handle >1 banks
488    raise NotImplementedError("Check GSASIIfiles.py: ReadPowderInstprm")
489
490def load_pwd_from_reader(reader, instprm, existingnames=[]):
491    """Loads powder data from a reader object, and assembles it into a GSASII data tree.
492
493    Returns: (name, tree) - 2-tuple of the histogram name (str), and data
494    Author: Jackson O'Donnell jacksonhodonnell@gmail.com
495    """
496    HistName = 'PWDR ' + G2obj.StripUnicode(reader.idstring, '_')
497    HistName = unicode(G2obj.MakeUniqueLabel(HistName, existingnames))
498
499    try:
500        Iparm1, Iparm2 = instprm
501    except ValueError:
502        # TODO load_iprms
503        Iparm1, Iparm2 = load_iprms(instprm, reader)
504
505    Ymin = np.min(reader.powderdata[1])
506    Ymax = np.max(reader.powderdata[1])
507    valuesdict = {'wtFactor': 1.0,
508                  'Dummy': False,
509                  'ranId': ran.randint(0, sys.maxint),
510                  'Offset': [0.0, 0.0], 'delOffset': 0.02*Ymax,
511                  'refOffset': -0.1*Ymax, 'refDelt': 0.1*Ymax,
512                  'qPlot': False, 'dPlot': False, 'sqrtPlot': False,
513                  'Yminmax': [Ymin, Ymax]}
514    reader.Sample['ranId'] = valuesdict['ranId']
515
516    # Ending keys:
517    # [u'Reflection Lists',
518    #  u'Limits',
519    #  'data',
520    #  u'Index Peak List',
521    #  u'Comments',
522    #  u'Unit Cells List',
523    #  u'Sample Parameters',
524    #  u'Peak List',
525    #  u'Background',
526    #  u'Instrument Parameters']
527    Tmin = np.min(reader.powderdata[0])
528    Tmax = np.max(reader.powderdata[0])
529
530    default_background = [['chebyschev', False, 3, 1.0, 0.0, 0.0],
531                          {'nDebye': 0, 'debyeTerms': [], 'nPeaks': 0, 'peaksList': []}]
532
533    output_dict = {u'Reflection Lists': {},
534                   u'Limits': reader.pwdparms.get('Limits', [(Tmin, Tmax), [Tmin, Tmax]]),
535                   u'data': [valuesdict, reader.powderdata, HistName],
536                   u'Index Peak List': [[], []],
537                   u'Comments': reader.comments,
538                   u'Unit Cells List': [],
539                   u'Sample Parameters': reader.Sample,
540                   u'Peak List': {'peaks': [], 'sigDict': {}},
541                   u'Background': reader.pwdparms.get('Background', default_background),
542                   u'Instrument Parameters': [Iparm1, Iparm2],
543                   }
544
545    names = [u'Comments',
546             u'Limits',
547             u'Background',
548             u'Instrument Parameters',
549             u'Sample Parameters',
550             u'Peak List',
551             u'Index Peak List',
552             u'Unit Cells List',
553             u'Reflection Lists']
554
555    # TODO controls?? GSASII.py:1664-7
556
557    return HistName, [HistName] + names, output_dict
558
559
560def _deep_copy_into(from_, into):
561    """Helper function for reloading .gpx file. See G2Project.reload()
562    Author: Jackson O'Donnell jacksonhodonnell@gmail.com
563    """
564    if isinstance(from_, dict) and isinstance(into, dict):
565        combined_keys = set(from_.keys()).union(into.keys())
566        for key in combined_keys:
567            if key in from_ and key in into:
568                both_dicts = (isinstance(from_[key], dict)
569                              and isinstance(into[key], dict))
570                both_lists = (isinstance(from_[key], list)
571                              and isinstance(into[key], list))
572                if both_dicts or both_lists:
573                    _deep_copy_into(from_[key], into[key])
574                else:
575                    into[key] = from_[key]
576            elif key in from_:
577                into[key] = from_[key]
578            else:  # key in into
579                del into[key]
580    elif isinstance(from_, list) and isinstance(into, list):
581        if len(from_) == len(into):
582            for i in xrange(len(from_)):
583                both_dicts = (isinstance(from_[i], dict)
584                              and isinstance(into[i], dict))
585                both_lists = (isinstance(from_[i], list)
586                              and isinstance(into[i], list))
587                if both_dicts or both_lists:
588                    _deep_copy_into(from_[i], into[i])
589                else:
590                    into[i] = from_[i]
591        else:
592            into[:] = from_
593
594
595class G2ObjectWrapper(object):
596    """Base class for all GSAS-II object wrappers
597    Author: Jackson O'Donnell jacksonhodonnell@gmail.com
598    """
599    def __init__(self, datadict):
600        self.data = datadict
601
602    def __getitem__(self, key):
603        return self.data[key]
604
605    def __setitem__(self, key, value):
606        self.data[key] = value
607
608    def __contains__(self, key):
609        return key in self.data
610
611    def get(self, k, d=None):
612        return self.data.get(k, d)
613
614    def keys(self):
615        return self.data.keys()
616
617    def values(self):
618        return self.data.values()
619
620    def items(self):
621        return self.data.items()
622
623
624class G2Project(G2ObjectWrapper):
625    def __init__(self, gpxfile=None, author=None, filename=None):
626        """Loads a GSAS-II project from a specified filename.
627
628        :param str gpxfile: Existing .gpx file to be loaded. If nonexistent,
629        creates an empty project.
630        :param str author: Author's name. Optional.
631        :param str filename: The filename the project should be saved to in
632        the future. If both filename and gpxfile are present, the project is
633        loaded from the gpxfile, then set to  save to filename in the future"""
634        if gpxfile is None:
635            self.filename = filename
636            self.data, self.names = make_empty_project(author=author, filename=filename)
637        elif isinstance(gpxfile, str):
638            # TODO set author, filename
639            self.filename = gpxfile
640            self.data, self.names = LoadDictFromProjFile(gpxfile)
641            self.index_ids()
642        else:
643            raise ValueError("Not sure what to do with gpxfile")
644
645    @classmethod
646    def from_dict_and_names(cls, gpxdict, names, filename=None):
647        out = cls()
648        if filename:
649            out.filename = filename
650            gpxdict['Controls']['data']['LastSavedAs'] = filename
651        else:
652            try:
653                out.filename = gpxdict['Controls']['data']['LastSavedAs']
654            except KeyError:
655                out.filename = None
656        out.data = gpxdict
657        out.names = names
658
659    def save(self, filename=None):
660        """Saves the project, either to the current filename, or to a new file.
661
662        Updates self.filename if a new filename provided"""
663        # TODO update LastSavedUsing ?
664        if filename:
665            self.data['Controls']['data']['LastSavedAs'] = filename
666            self.filename = filename
667        elif not self.filename:
668            raise AttributeError("No file name to save to")
669        SaveDictToProjFile(self.data, self.names, self.filename)
670
671    def add_powder_histogram(self, datafile, iparams):
672        """Loads a powder data histogram into the project.
673
674        Automatically checks for an instrument parameter file, or one can be
675        provided."""
676        pwdrreaders = import_generic(datafile, PwdrDataReaders)
677        histname, new_names, pwdrdata = load_pwd_from_reader(
678                                          pwdrreaders[0], iparams,
679                                          list(self.histogram_names()))
680        if histname in self.data:
681            print("Warning - redefining histogram", histname)
682        else:
683            if self.names[-1][0] == 'Phases':
684                self.names.insert(-1, new_names)
685            else:
686                self.names.append(new_names)
687        self.data[histname] = pwdrdata
688        return self.histogram(histname)
689
690    def add_phase(self, phasefile, phasename=None, histograms=[]):
691        """Loads a phase into the project from a .cif file
692
693        :returns: A :class:`gpx_manipulations.G2Phase` object representing the
694        new phase."""
695        # TODO handle multiple phases in a file
696        phasereaders = import_generic(phasefile, PhaseReaders)
697        phasereader = phasereaders[0]
698
699        phasename = phasename or phasereader.Phase['General']['Name']
700        phaseNameList = list(self.phase_names())
701        phasename = G2obj.MakeUniqueLabel(phasename, phaseNameList)
702        phasereader.Phase['General']['Name'] = phasename
703
704        if 'Phases' not in self.data:
705            self.data[u'Phases'] = { 'data': None }
706        assert phasename not in self.data['Phases'], "phase names should be unique"
707        self.data['Phases'][phasename] = phasereader.Phase
708
709        if phasereader.Constraints:
710            Constraints = self.data['Constraints']
711            for i in phasereader.Constraints:
712                if isinstance(i, dict):
713                    if '_Explain' not in Constraints:
714                        Constraints['_Explain'] = {}
715                    Constraints['_Explain'].update(i)
716                else:
717                    Constraints['Phase'].append(i)
718
719        data = self.data['Phases'][phasename]
720        generalData = data['General']
721        SGData = generalData['SGData']
722        NShkl = len(G2spc.MustrainNames(SGData))
723        NDij = len(G2spc.HStrainNames(SGData))
724        Super = generalData.get('Super', 0)
725        if Super:
726            SuperVec = np.array(generalData['SuperVec'][0])
727        else:
728            SuperVec = []
729        UseList = data['Histograms']
730
731        for histname in histograms:
732            if histname.startswith('HKLF '):
733                raise NotImplementedError("Does not support HKLF yet")
734            elif histname.startswith('PWDR '):
735                hist = self.histogram(histname)
736                hist['Reflection Lists'][generalData['Name']] = {}
737                UseList[histname] = SetDefaultDData('PWDR', histname, NShkl=NShkl, NDij=NDij)
738                for key, val in [('Use', True), ('LeBail', False),
739                                 ('newLeBail', True),
740                                 ('Babinet', {'BabA': [0.0, False],
741                                              'BabU': [0.0, False]})]:
742                    if key not in UseList[histname]:
743                        UseList[histname][key] = val
744            else:
745                raise NotImplementedError("Unexpected histogram" + histname)
746
747        for obj in self.names:
748            if obj[0] == 'Phases':
749                phasenames = obj
750                break
751        else:
752            phasenames = [u'Phases']
753            self.names.append(phasenames)
754        phasenames.append(unicode(phasename))
755
756        # TODO should it be self.filename, not phasefile?
757        SetupGeneral(data, os.path.dirname(phasefile))
758        self.index_ids()
759
760        return self.phase(phasename)
761
762    def reload(self):
763        """Reload self from self.filename"""
764        data, names = LoadDictFromProjFile(self.filename)
765        self.names = names
766        # Need to deep copy the new data file data into the current tree,
767        # so that any existing G2Phase, or G2PwdrData objects will still be
768        # valid
769        _deep_copy_into(from_=data, into=self.data)
770
771    def refine(self, newfile=None, printFile=None):
772        # index_ids will automatically save the project
773        self.index_ids()
774        # TODO G2strMain does not properly use printFile
775        G2strMain.Refine(self.filename)
776        # Reload yourself
777        self.reload()
778
779    def histogram_names(self):
780        """Gives an iterator of the names of each histogram in the project."""
781        for obj in self.names:
782            if len(obj) > 1 and obj[0] != u'Phases':
783                yield obj[0]
784
785    def histogram(self, histname):
786        """Returns the histogram named histname, or None if it does not exist."""
787        if histname in self.data:
788            return G2PwdrData(self.data[histname])
789        return None
790
791    def histograms(self):
792        """Return a list of all histograms, as
793        :class:`gpx_manipulations.G2PwdrData` objects"""
794        return [self.histogram(name) for name in self.histogram_names()]
795
796    def phase_names(self):
797        """Gives an iterator of the names of each phase in the project."""
798        for obj in self.names:
799            if obj[0] == 'Phases':
800                for name in obj[1:]:
801                    yield name
802                break
803
804    def phase(self, phasename):
805        return G2Phase(self.data['Phases'][phasename])
806
807    def phases(self):
808        return [self.phase(name) for name in self.phase_names()]
809
810    def do_refinements(self, refinements, histogram='all', phase='all',
811                       outputnames=None):
812        """Conducts a series of refinements."""
813        if outputnames:
814            if len(refinements) != len(outputnames):
815                raise ValueError("Should have same number of outuputs to"
816                                 "refinements")
817        else:
818            outputnames = [None for r in refinements]
819
820        for output, refinement in zip(outputnames, refinements):
821            self.set_refinement(refinement, histogram)
822            # Handle 'once' args - refinements that are disabled after this
823            # refinement
824            if 'once' in refinement:
825                temp = {'set': refinement['once']}
826                self.set_refinement(temp, histogram, phase)
827
828            if output:
829                self.save(output)
830
831            self.refine()  # newFile=output)
832
833            # Handle 'once' args - refinements that are disabled after this
834            # refinement
835            if 'once' in refinement:
836                temp = {'clear': refinement['once']}
837                self.set_refinement(temp, histogram, phase)
838
839    def set_refinement(self, refinement, histogram='all', phase='all'):
840        """Apply specified refinements to a given histogram(s) or phase(s).
841
842        :param dict refinement: The refinements to be conducted
843        :param histogram: Either a name of a histogram (str), a list of
844        histogram names, or 'all' (default)
845        :param phase: Either a name of a phase (str), a list of phase names, or
846        'all' (default)"""
847        if histogram == 'all':
848            hists = [self.histogram(name)
849                     for name in self.histogram_names()]
850        elif isinstance(histogram, str):
851            hists = [self.histogram(histogram)]
852        else:
853            hists = [self.histogram(name) for name in histogram]
854
855        if phase == 'all':
856            phases = [self.phase(name) for name in self.phase_names()]
857        elif isinstance(phase, str):
858            phases = [self.phase(phase)]
859        else:
860            phases = [self.phase(name) for name in phase]
861
862        for key, val in refinement.get('set', {}).items():
863            # Apply refinement options
864            if G2PwdrData.is_valid_refinement_key(key):
865                for hist in hists:
866                    hist.set_refinement(key, val)
867            elif G2Phase.is_valid_refinement_key(key):
868                for phase in phases:
869                    phase.set_refinement(key, val)
870            else:
871                print("Unknown refinement key:", key)
872
873        for key, val in refinement.get('clear', {}).items():
874            # Clear refinement options
875            if G2PwdrData.is_valid_refinement_key(key):
876                for hist in hists:
877                    hist.clear_refinement(key, val)
878            elif G2Phase.is_valid_refinement_key(key):
879                for phase in phases:
880                    phase.clear_refinement(key, val)
881            else:
882                print("Unknown refinement key:", key)
883
884    def index_ids(self):
885        self.save()
886        return G2strIO.GetUsedHistogramsAndPhases(self.filename)
887
888    def add_constraint_raw(self, cons_scope, constr):
889        """Adds a constraint of type consType to the project.
890        cons_scope should be one of "Hist", "Phase", "HAP", or "Global".
891
892        WARNING it does not check the constraint is well-constructed"""
893        constrs = self['Constraints']['data']
894        if 'Global' not in constrs:
895            constrs['Global'] = []
896        constrs[cons_scope].append(constr)
897
898    def hold_many(self, vars, type):
899        """Apply holds for all the variables in vars, for constraint of a given type.
900
901        type is passed directly to add_constraint_raw as consType
902
903        :param list vars: A list of variables to hold. Either G2obj.G2VarObj objects,
904        string variable specifiers, or arguments for :meth:`make_var_obj`
905        :param str type: A string constraint type specifier. See
906        :meth:`add_constraint_raw`"""
907        for var in vars:
908            if isinstance(var, str):
909                var = self.make_var_obj(var)
910            elif not isinstance(var, G2obj.G2VarObj):
911                var = self.make_var_obj(*var)
912            self.add_constraint_raw(type, [[1.0, var], None, None, 'h'])
913
914    def make_var_obj(self, phase=None, hist=None, varname=None, atomId=None,
915                     reloadIdx=True):
916        """Wrapper to create a G2VarObj. Takes either a string representaiton ("p:h:name:a")
917        or individual names of phase, histogram, varname, and atomId.
918
919        Automatically converts string phase, hist, or atom names into the ID required
920        by G2VarObj."""
921        if reloadIdx:
922            self.index_ids()
923
924        # If string representation, short circuit
925        if hist is None and varname is None and atomId is None:
926            if isinstance(phase, str) and ':' in phase:
927                return G2obj.G2VarObj(phase)
928
929        # Get phase index
930        phaseObj = None
931        if isinstance(phase, G2Phase):
932            phaseObj = phase
933            phase = G2obj.PhaseRanIdLookup[phase.ranId]
934        elif phase in self['Phases']:
935            phaseObj = self.phase(phase)
936            phaseRanId = phaseObj.ranId
937            phase = G2obj.PhaseRanIdLookup[phaseRanId]
938
939        # Get histogram index
940        if isinstance(hist, G2PwdrData):
941            hist = G2obj.HistRanIdLookup[hist.ranId]
942        elif hist in self.data:
943            histRanId = self.histogram(hist).ranId
944            hist = G2obj.HistRanIdLookup[histRanId]
945
946        # Get atom index (if any)
947        if isinstance(atomId, G2AtomRecord):
948            atomId = G2obj.AtomRanIdLookup[phase][atomId.ranId]
949        elif phaseObj:
950            atomObj = phaseObj.atom(atomId)
951            if atomObj:
952                atomRanId = atomObj.ranId
953                atomId = G2obj.AtomRanIdLookup[phase][atomRanId]
954
955        return G2obj.G2VarObj(phase, hist, varname, atomId)
956
957
958class G2AtomRecord(G2ObjectWrapper):
959    """Wrapper for an atom record
960    Author: Jackson O'Donnell jacksonhodonnell@gmail.com
961    """
962    def __init__(self, data, indices):
963        self.data = data
964        self.cx, self.ct, self.cs, self.cia = indices
965
966    @property
967    def label(self):
968        return self.data[self.ct-1]
969
970    @property
971    def type(self):
972        return self.data[self.ct]
973
974    @property
975    def refinement_flags(self):
976        return self.data[self.ct+1]
977
978    @refinement_flags.setter
979    def set_refinement(self, other):
980        for c in other:
981            if c not in ' FXU':
982                raise ValueError("Invalid atom refinement: ", other)
983        self.data[self.ct+1] = unicode(other)
984
985    @property
986    def coordinates(self):
987        return tuple(self.data[self.cx:self.cx+3])
988
989    @property
990    def ranId(self):
991        return self.data[self.cia+8]
992
993    @property
994    def adp_flag(self):
995        # Either 'I' or 'A'
996        return self.data[self.cia]
997
998    @property
999    def uiso(self):
1000        if self.adp_flag == 'I':
1001            return self.data[self.cia+1]
1002        else:
1003            return self.data[self.cia+2:self.cia+8]
1004
1005
1006class G2PwdrData(G2ObjectWrapper):
1007    """Wraps a Poweder Data Histogram.
1008    Author: Jackson O'Donnell jacksonhodonnell@gmail.com
1009    """
1010    @staticmethod
1011    def is_valid_refinement_key(key):
1012        valid_keys = ['Limits', 'Sample Parameters', 'Background',
1013                      'Instrument Parameters']
1014        return key in valid_keys
1015
1016    @property
1017    def name(self):
1018        return self['data'][-1]
1019
1020    @property
1021    def ranId(self):
1022        return self['data'][0]['ranId']
1023
1024    def fit_fixed_points(self):
1025        """Attempts to apply a background fit to the fixed points currently specified."""
1026
1027        def SetInstParms(Inst):
1028            dataType = Inst['Type'][0]
1029            insVary = []
1030            insNames = []
1031            insVals = []
1032            for parm in Inst:
1033                insNames.append(parm)
1034                insVals.append(Inst[parm][1])
1035                if parm in ['U','V','W','X','Y','SH/L','I(L2)/I(L1)','alpha',
1036                    'beta-0','beta-1','beta-q','sig-0','sig-1','sig-2','sig-q',] and Inst[parm][2]:
1037                        Inst[parm][2] = False
1038            instDict = dict(zip(insNames, insVals))
1039            instDict['X'] = max(instDict['X'], 0.01)
1040            instDict['Y'] = max(instDict['Y'], 0.01)
1041            if 'SH/L' in instDict:
1042                instDict['SH/L'] = max(instDict['SH/L'], 0.002)
1043            return dataType, instDict, insVary
1044
1045        bgrnd = self['Background']
1046
1047        # Need our fixed points in order
1048        bgrnd[1]['FixedPoints'].sort(key=lambda pair: pair[0])
1049        X = [x for x, y in bgrnd[1]['FixedPoints']]
1050        Y = [y for x, y in bgrnd[1]['FixedPoints']]
1051
1052        # Some simple lookups
1053        limits = self['Limits']
1054        inst, inst2 = self['Instrument Parameters']
1055        pwddata = self['data'][1]
1056
1057        # Construct the data for background fitting
1058        xBeg = np.searchsorted(pwddata[0], limits[0])
1059        xFin = np.searchsorted(pwddata[0], limits[1])
1060        xdata = pwddata[0][xBeg:xFin]
1061        ydata = si.interp1d(X,Y)(ma.getdata(xdata))
1062
1063        W = [1]*len(xdata)
1064        Z = [0]*len(xdata)
1065
1066        dataType, insDict, insVary = SetInstParms(inst)
1067        bakType, bakDict, bakVary = G2pwd.SetBackgroundParms(bgrnd)
1068
1069        # Do the fit
1070        # TODO get controls from root
1071        data = np.array([xdata, ydata, W, Z, Z, Z])
1072        G2pwd.DoPeakFit('LSQ', [], bgrnd, limits, inst, inst2, data,
1073                        preVaryList=bakVary, controls={})
1074
1075        # Post-fit
1076        parmDict = {}
1077        bakType, bakDict, bakVary = G2pwd.SetBackgroundParms(bgrnd)
1078        parmDict.update(bakDict)
1079        parmDict.update(insDict)
1080        pwddata[3][xBeg:xFin] *= 0
1081        pwddata[5][xBeg:xFin] *= 0
1082        pwddata[4][xBeg:xFin] = G2pwd.getBackground('', parmDict, bakType, dataType, xdata)[0]
1083
1084        # TODO adjust pwddata? GSASIIpwdGUI.py:1041
1085
1086    def y_calc(self):
1087        return self['data'][1][3]
1088
1089    def set_refinement(self, key, value):
1090        """Sets the refinement parameter 'key' to the specification 'value'"""
1091        if key == 'Limits':
1092            old_limits = self.data['Limits'][1]
1093            new_limits = value
1094            if isinstance(new_limits, dict):
1095                if 'low' in new_limits:
1096                    old_limits[0] = new_limits['low']
1097                if 'high' in new_limits:
1098                    old_limits[1] = new_limits['high']
1099            else:
1100                old_limits[0], old_limits[1] = new_limits
1101        elif key == 'Sample Parameters':
1102            sample = self.data['Sample Parameters']
1103            for sparam in value:
1104                sample[sparam][1] = True
1105        elif key == 'Background':
1106            bkg, peaks = self.data['Background']
1107
1108            # If True or False, just set the refine parameter
1109            if value in (True, False):
1110                bkg[1] = value
1111                return
1112
1113            if 'type' in value:
1114                bkg[0] = value['type']
1115            if 'refine' in value:
1116                bkg[1] = value['refine']
1117            if 'no. coeffs' in value:
1118                cur_coeffs = bkg[2]
1119                n_coeffs = value['no. coeffs']
1120                if n_coeffs > cur_coeffs:
1121                    for x in range(n_coeffs - cur_coeffs):
1122                        bkg.append(0.0)
1123                else:
1124                    for _ in range(cur_coeffs - n_coeffs):
1125                        bkg.pop()
1126                bkg[2] = n_coeffs
1127            if 'coeffs' in value:
1128                bkg[3:] = value['coeffs']
1129            if 'FixedPoints' in value:
1130                peaks['FixedPoints'] = value
1131            if value.get('fit fixed points', False):
1132                self.fit_fixed_points()
1133
1134        elif key == 'Instrument Parameters':
1135            instrument, secondary = self.data['Instrument Parameters']
1136            for iparam in value:
1137                try:
1138                    instrument[iparam][2] = True
1139                except IndexError:
1140                    raise ValueError("Invalid key:", iparam)
1141        else:
1142            raise ValueError("Unknown key:", key)
1143
1144    def clear_refinement(self, key, value):
1145        """Clears the refinement parameter 'key' and its associated value."""
1146        if key == 'Limits':
1147            old_limits, cur_limits = self.data['Limits']
1148            cur_limits[0], cur_limits[1] = old_limits
1149        elif key == 'Sample Parameters':
1150            sample = self.data['Sample Parameters']
1151            for sparam in value:
1152                sample[sparam][1] = False
1153        elif key == 'Background':
1154            bkg, peaks = self.data['Background']
1155
1156            # If True or False, just set the refine parameter
1157            if value in (True, False):
1158                bkg[1] = False
1159                return
1160
1161            bkg[1] = False
1162            if 'FixedPoints' in value:
1163                if 'FixedPoints' in peaks:
1164                    del peaks['FixedPoints']
1165        elif key == 'Instrument Parameters':
1166            instrument, secondary = self.data['Instrument Parameters']
1167            for iparam in value:
1168                instrument[iparam][2] = False
1169        else:
1170            raise ValueError("Unknown key:", key)
1171
1172
1173class G2Phase(G2ObjectWrapper):
1174    """A wrapper object around a given phase.
1175    Author: Jackson O'Donnell jacksonhodonnell@gmail.com
1176    """
1177    @staticmethod
1178    def is_valid_refinement_key(key):
1179        valid_keys = ["Cell", "Atoms", "LeBail"]
1180        return key in valid_keys
1181
1182    def atom(self, atomlabel):
1183        """Returns the atom specified by atomlabel, or None if it does not
1184        exist."""
1185        # Consult GSASIIobj.py for the meaning of this
1186        cx, ct, cs, cia = self.data['General']['AtomPtrs']
1187        ptrs = [cx, ct, cs, cia]
1188        atoms = self.data['Atoms']
1189        for atom in atoms:
1190            if atom[ct-1] == atomlabel:
1191                return G2AtomRecord(atom, ptrs)
1192
1193    def atoms(self):
1194        """Returns a list of atoms present in the phase."""
1195        ptrs = self.data['General']['AtomPtrs']
1196        output = []
1197        atoms = self.data['Atoms']
1198        for atom in atoms:
1199            output.append(G2AtomRecord(atom, ptrs))
1200        return output
1201
1202    @property
1203    def ranId(self):
1204        return self.data['ranId']
1205
1206    def cell_dict(self):
1207        cell = self['General']['Cell']
1208        return {'a': cell[1], 'b': cell[2], 'c': cell[3],
1209                'alpha': cell[4], 'beta': cell[5], 'gamma': cell[6],
1210                'vol': cell[6]}
1211
1212    def set_refinement(self, key, value):
1213        if key == "Cell":
1214            self.data['General']['Cell'][0] = True
1215        elif key == "Atoms":
1216            cx, ct, cs, cia = self.data['General']['AtomPtrs']
1217
1218            for atomlabel, atomrefinement in value.items():
1219                atom = self.atom(atomlabel)
1220                atom.refinement_flags = atomrefinement
1221        elif key == "LeBail":
1222            hists = self.data['Histograms']
1223            for hname, hoptions in hists.items():
1224                if 'LeBail' not in hoptions:
1225                    hoptions['newLeBail'] = True
1226                hoptions['LeBail'] = bool(value)
1227        else:
1228            raise ValueError("Unknown key:", key)
1229
1230    def clear_refinement(self, key, value):
1231        if key == "Cell":
1232            self.data['General']['Cell'][0] = False
1233        elif key == "Atoms":
1234            cx, ct, cs, cia = self.data['General']['AtomPtrs']
1235
1236            for atomlabel in value:
1237                atom = self.atom(atomlabel)
1238                # Set refinement to none
1239                atom.refinement_flags = ' '
1240        elif key == "LeBail":
1241            hists = self.data['Histograms']
1242            for hname, hoptions in hists.items():
1243                if 'LeBail' not in hoptions:
1244                    hoptions['newLeBail'] = True
1245                hoptions['LeBail'] = False
1246        else:
1247            raise ValueError("Unknown key:", key)
1248
1249def main():
1250    '''TODO: the command-line options need some thought
1251    '''
1252    arg = sys.argv
1253    print(arg)
1254    if len(arg) > 1:
1255        GPXfile = arg[1]
1256        if not ospath.exists(GPXfile):
1257            print(u'ERROR - '+GPXfile+u" doesn't exist!")
1258            exit()
1259        Project,nameList = LoadDictFromProjFile(GPXfile)
1260        SaveDictToProjFile(Project,nameList,'testout.gpx')
1261    else:
1262        print('ERROR - missing filename')
1263        exit()
1264    print("Done")
1265         
1266if __name__ == '__main__':
1267    PwdrDataReaders = G2fil.LoadImportRoutines("pwd", "Powder_Data")
1268    PhaseReaders = G2fil.LoadImportRoutines("phase", "Phase")
1269    main()
1270
1271    # from gpx_manipulatons.py
1272    # try:
1273    #     filename, authorname = sys.argv[1:3]
1274    #     proj, names = make_empty_project(authorname, filename)
1275    #     SaveDictToProjFile(proj, names, os.path.abspath(filename))
1276    # except ValueError:
1277    #     print("Usage: {} <filename> <author>".format(sys.argv[0]))
1278    #     sys.exit(-1)
1279
1280
1281    # from refinements.py
1282#      USAGE = """USAGE: {} datafile instparams phasefile projectname refinements
1283
1284# datafile:    Input powder data
1285# intparams:   Corresponding instrument parameter file
1286# phasefile:   Phase to refine against data
1287# projectname: Project file to be created, should end in .gpx
1288# refinements: JSON file of refinements to be executed
1289# """
1290#     try:
1291#         datafile, instprm, phasefile, projectname, refinements = sys.argv[1:]
1292#     except ValueError:
1293#         print(USAGE.format(sys.argv[0]))
1294#         sys.exit(-1)
1295
1296#     try:
1297#         with open(refinements) as f:
1298#             refinements = json.load(f)
1299#     except IOError:
1300#         print("No such refinements file: {}".format(refinements))
1301
1302#     print("Creating project file \"{}\"...".format(projectname))
1303#     proj = G2Project(filename=projectname)
1304#     # Add the histogram
1305#     hist = proj.add_powder_histogram(datafile, instprm)
1306#     # Add the phase, and associate it with the histogram
1307#     proj.add_phase(phasefile, histograms=[hist.name])
1308
1309#     proj.do_refinements(refinements['refinements'])
1310#     proj.save()
1311
1312
1313    # from gpx_dumper
1314    # import IPython.lib.pretty as pretty
1315    # proj, nameList = LoadDictFromProjFile(sys.argv[1])
1316    # print("names:", nameList)
1317    # for key, val in proj.items():
1318    #     print(key, ":", sep='')
1319    #     pretty.pprint(val)
1320   
Note: See TracBrowser for help on using the repository browser.