source: trunk/GSASIIstrIO.py @ 1820

Last change on this file since 1820 was 1820, checked in by vondreele, 8 years ago

fix issues in reading powder peak lists (since TOF added)
force reload of data after Refine
add Move Peaks to Background menu - moves fitted background peaks to Peak List for possible indexing
increase number of possible peaks in background to 30!
fix bug in LS output for Pawley refinements
reformat background peak output from Refine

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 133.3 KB
Line 
1# -*- coding: utf-8 -*-
2########### SVN repository information ###################
3# $Date: 2015-04-29 19:04:05 +0000 (Wed, 29 Apr 2015) $
4# $Author: vondreele $
5# $Revision: 1820 $
6# $URL: trunk/GSASIIstrIO.py $
7# $Id: GSASIIstrIO.py 1820 2015-04-29 19:04:05Z vondreele $
8########### SVN repository information ###################
9'''
10*GSASIIstrIO: structure I/O routines*
11-------------------------------------
12
13'''
14import sys
15import os
16import os.path as ospath
17import time
18import math
19import copy
20import random
21import cPickle
22import numpy as np
23import numpy.ma as ma
24import numpy.linalg as nl
25import scipy.optimize as so
26import GSASIIpath
27GSASIIpath.SetVersionNumber("$Revision: 1820 $")
28import GSASIIElem as G2el
29import GSASIIgrid as G2gd
30import GSASIIlattice as G2lat
31import GSASIIspc as G2spc
32import GSASIIobj as G2obj
33import GSASIImapvars as G2mv
34import GSASIImath as G2mth
35
36sind = lambda x: np.sin(x*np.pi/180.)
37cosd = lambda x: np.cos(x*np.pi/180.)
38tand = lambda x: np.tan(x*np.pi/180.)
39asind = lambda x: 180.*np.arcsin(x)/np.pi
40acosd = lambda x: 180.*np.arccos(x)/np.pi
41atan2d = lambda y,x: 180.*np.arctan2(y,x)/np.pi
42   
43ateln2 = 8.0*math.log(2.0)
44
45def GetControls(GPXfile):
46    ''' Returns dictionary of control items found in GSASII gpx file
47
48    :param str GPXfile: full .gpx file name
49    :return: dictionary of control items
50    '''
51    Controls = copy.copy(G2obj.DefaultControls)
52    fl = open(GPXfile,'rb')
53    while True:
54        try:
55            data = cPickle.load(fl)
56        except EOFError:
57            break
58        datum = data[0]
59        if datum[0] == 'Controls':
60            Controls.update(datum[1])
61    fl.close()
62    return Controls
63   
64def GetConstraints(GPXfile):
65    '''Read the constraints from the GPX file and interpret them
66
67    called in :func:`ReadCheckConstraints`, :func:`GSASIIstrMain.Refine`
68    and :func:`GSASIIstrMain.SeqRefine`.
69    '''
70    fl = open(GPXfile,'rb')
71    while True:
72        try:
73            data = cPickle.load(fl)
74        except EOFError:
75            break
76        datum = data[0]
77        if datum[0] == 'Constraints':
78            constList = []
79            for item in datum[1]:
80                if item.startswith('_'): continue
81                constList += datum[1][item]
82            fl.close()
83            constDict,fixedList,ignored = ProcessConstraints(constList)
84            if ignored:
85                print ignored,'Constraints were rejected. Was a constrained phase, histogram or atom deleted?'
86            return constDict,fixedList
87    fl.close()
88    raise Exception,"No constraints in GPX file"
89   
90def ProcessConstraints(constList):
91    """Interpret the constraints in the constList input into a dictionary, etc.
92    All :class:`GSASIIobj.G2VarObj` objects are mapped to the appropriate
93    phase/hist/atoms based on the object internals (random Ids). If this can't be
94    done (if a phase has been deleted, etc.), the variable is ignored.
95    If the constraint cannot be used due to too many dropped variables,
96    it is counted as ignored.
97   
98    :param list constList: a list of lists where each item in the outer list
99      specifies a constraint of some form, as described in the :mod:`GSASIIobj`
100      :ref:`Constraint definition <Constraint_definitions_table>`.
101
102    :returns:  a tuple of (constDict,fixedList,ignored) where:
103     
104      * constDict (list of dicts) contains the constraint relationships
105      * fixedList (list) contains the fixed values for each type
106        of constraint.
107      * ignored (int) counts the number of invalid constraint items
108        (should always be zero!)
109    """
110    constDict = []
111    fixedList = []
112    ignored = 0
113    for item in constList:
114        if item[-1] == 'h':
115            # process a hold
116            fixedList.append('0')
117            var = str(item[0][1])
118            if '?' not in var:
119                constDict.append({var:0.0})
120            else:
121                ignored += 1
122        elif item[-1] == 'f':
123            # process a new variable
124            fixedList.append(None)
125            D = {}
126            varyFlag = item[-2]
127            varname = item[-3]
128            for term in item[:-3]:
129                var = str(term[1])
130                if '?' not in var:
131                    D[var] = term[0]
132            if len(D) > 1:
133                # add extra dict terms for input variable name and vary flag
134                if varname is not None:                   
135                    if varname.startswith('::'):
136                        varname = varname[2:].replace(':',';')
137                    else:
138                        varname = varname.replace(':',';')
139                    D['_name'] = '::' + varname
140                D['_vary'] = varyFlag == True # force to bool
141                constDict.append(D)
142            else:
143                ignored += 1
144            #constFlag[-1] = ['Vary']
145        elif item[-1] == 'c': 
146            # process a contraint relationship
147            D = {}
148            for term in item[:-3]:
149                var = str(term[1])
150                if '?' not in var:
151                    D[var] = term[0]
152            if len(D) >= 1:
153                fixedList.append(str(item[-3]))
154                constDict.append(D)
155            else:
156                ignored += 1
157        elif item[-1] == 'e':
158            # process an equivalence
159            firstmult = None
160            eqlist = []
161            for term in item[:-3]:
162                if term[0] == 0: term[0] = 1.0
163                var = str(term[1])
164                if '?' in var: continue
165                if firstmult is None:
166                    firstmult = term[0]
167                    firstvar = var
168                else:
169                    eqlist.append([var,firstmult/term[0]])
170            if len(eqlist) > 0:
171                G2mv.StoreEquivalence(firstvar,eqlist)
172            else:
173                ignored += 1
174        else:
175            ignored += 1
176    return constDict,fixedList,ignored
177
178def ReadCheckConstraints(GPXfile):
179    '''Load constraints and related info and return any error or warning messages'''
180    # init constraints
181    G2mv.InitVars()   
182    # get variables
183    Histograms,Phases = GetUsedHistogramsAndPhases(GPXfile)
184    if not Phases:
185        return 'Error: No Phases!',''
186    if not Histograms:
187        return 'Error: no diffraction data',''
188    constrDict,fixedList = GetConstraints(GPXfile) # load user constraints before internally generated ones
189    rigidbodyDict = GetRigidBodies(GPXfile)
190    rbIds = rigidbodyDict.get('RBIds',{'Vector':[],'Residue':[]})
191    rbVary,rbDict = GetRigidBodyModels(rigidbodyDict,Print=False)
192    Natoms,atomIndx,phaseVary,phaseDict,pawleyLookup,FFtables,BLtables,maxSSwave = GetPhaseData(Phases,RestraintDict=None,rbIds=rbIds,Print=False) # generates atom symmetry constraints
193    hapVary,hapDict,controlDict = GetHistogramPhaseData(Phases,Histograms,Print=False)
194    histVary,histDict,controlDict = GetHistogramData(Histograms,Print=False)
195    varyList = rbVary+phaseVary+hapVary+histVary
196    errmsg, warnmsg = G2mv.CheckConstraints(varyList,constrDict,fixedList)
197    if errmsg:
198        # print some diagnostic info on the constraints
199        print('Error in constraints:\n'+errmsg+
200              '\nRefinement not possible due to conflict in constraints, see below:\n')
201        print G2mv.VarRemapShow(varyList,True)
202    return errmsg, warnmsg
203def GetRestraints(GPXfile):
204    '''Read the restraints from the GPX file.
205    Throws an exception if not found in the .GPX file
206    '''
207    fl = open(GPXfile,'rb')
208    while True:
209        try:
210            data = cPickle.load(fl)
211        except EOFError:
212            break
213        datum = data[0]
214        if datum[0] == 'Restraints':
215            restraintDict = datum[1]
216    fl.close()
217    return restraintDict
218   
219def GetRigidBodies(GPXfile):
220    '''Read the rigid body models from the GPX file
221    '''
222    fl = open(GPXfile,'rb')
223    while True:
224        try:
225            data = cPickle.load(fl)
226        except EOFError:
227            break
228        datum = data[0]
229        if datum[0] == 'Rigid bodies':
230            rigidbodyDict = datum[1]
231    fl.close()
232    return rigidbodyDict
233       
234def GetFprime(controlDict,Histograms):
235    'Needs a doc string'
236    FFtables = controlDict['FFtables']
237    if not FFtables:
238        return
239    histoList = Histograms.keys()
240    histoList.sort()
241    for histogram in histoList:
242        if histogram[:4] in ['PWDR','HKLF']:
243            Histogram = Histograms[histogram]
244            hId = Histogram['hId']
245            hfx = ':%d:'%(hId)
246            if 'X' in controlDict[hfx+'histType']:
247                keV = controlDict[hfx+'keV']
248                for El in FFtables:
249                    Orbs = G2el.GetXsectionCoeff(El.split('+')[0].split('-')[0])
250                    FP,FPP,Mu = G2el.FPcalc(Orbs, keV)
251                    FFtables[El][hfx+'FP'] = FP
252                    FFtables[El][hfx+'FPP'] = FPP               
253           
254def GetPhaseNames(GPXfile):
255    ''' Returns a list of phase names found under 'Phases' in GSASII gpx file
256
257    :param str GPXfile: full .gpx file name
258    :return: list of phase names
259    '''
260    fl = open(GPXfile,'rb')
261    PhaseNames = []
262    while True:
263        try:
264            data = cPickle.load(fl)
265        except EOFError:
266            break
267        datum = data[0]
268        if 'Phases' == datum[0]:
269            for datus in data[1:]:
270                PhaseNames.append(datus[0])
271    fl.close()
272    return PhaseNames
273
274def GetAllPhaseData(GPXfile,PhaseName):
275    ''' Returns the entire dictionary for PhaseName from GSASII gpx file
276
277    :param str GPXfile: full .gpx file name
278    :param str PhaseName: phase name
279    :return: phase dictionary
280    '''       
281    fl = open(GPXfile,'rb')
282    General = {}
283    Atoms = []
284    while True:
285        try:
286            data = cPickle.load(fl)
287        except EOFError:
288            break
289        datum = data[0]
290        if 'Phases' == datum[0]:
291            for datus in data[1:]:
292                if datus[0] == PhaseName:
293                    break
294    fl.close()
295    return datus[1]
296   
297def GetHistograms(GPXfile,hNames):
298    """ Returns a dictionary of histograms found in GSASII gpx file
299
300    :param str GPXfile: full .gpx file name
301    :param str hNames: list of histogram names
302    :return: dictionary of histograms (types = PWDR & HKLF)
303
304    """
305    fl = open(GPXfile,'rb')
306    Histograms = {}
307    while True:
308        try:
309            data = cPickle.load(fl)
310        except EOFError:
311            break
312        datum = data[0]
313        hist = datum[0]
314        if hist in hNames:
315            if 'PWDR' in hist[:4]:
316                PWDRdata = {}
317                PWDRdata.update(datum[1][0])        #weight factor
318                PWDRdata['Data'] = ma.array(ma.getdata(datum[1][1]))          #masked powder data arrays/clear previous masks
319                PWDRdata[data[2][0]] = data[2][1]       #Limits & excluded regions (if any)
320                PWDRdata[data[3][0]] = data[3][1]       #Background
321                PWDRdata[data[4][0]] = data[4][1]       #Instrument parameters
322                PWDRdata[data[5][0]] = data[5][1]       #Sample parameters
323                try:
324                    PWDRdata[data[9][0]] = data[9][1]       #Reflection lists might be missing
325                except IndexError:
326                    PWDRdata['Reflection Lists'] = {}
327                PWDRdata['Residuals'] = {}
328   
329                Histograms[hist] = PWDRdata
330            elif 'HKLF' in hist[:4]:
331                HKLFdata = {}
332                HKLFdata.update(datum[1][0])        #weight factor
333#patch
334                if 'list' in str(type(datum[1][1])):
335                #if isinstance(datum[1][1],list):
336                    RefData = {'RefList':[],'FF':{}}
337                    for ref in datum[1][1]:
338                        RefData['RefList'].append(ref[:11]+[ref[13],])
339                    RefData['RefList'] = np.array(RefData['RefList'])
340                    datum[1][1] = RefData
341#end patch
342                datum[1][1]['FF'] = {}
343                HKLFdata['Data'] = datum[1][1]
344                HKLFdata[data[1][0]] = data[1][1]       #Instrument parameters
345                HKLFdata['Reflection Lists'] = None
346                HKLFdata['Residuals'] = {}
347                Histograms[hist] = HKLFdata           
348    fl.close()
349    return Histograms
350   
351def GetHistogramNames(GPXfile,hType):
352    """ Returns a list of histogram names found in GSASII gpx file
353
354    :param str GPXfile: full .gpx file name
355    :param str hType: list of histogram types
356    :return: list of histogram names (types = PWDR & HKLF)
357
358    """
359    fl = open(GPXfile,'rb')
360    HistogramNames = []
361    while True:
362        try:
363            data = cPickle.load(fl)
364        except EOFError:
365            break
366        datum = data[0]
367        if datum[0][:4] in hType:
368            HistogramNames.append(datum[0])
369    fl.close()
370    return HistogramNames
371   
372def GetUsedHistogramsAndPhases(GPXfile):
373    ''' Returns all histograms that are found in any phase
374    and any phase that uses a histogram. This also
375    assigns numbers to used phases and histograms by the
376    order they appear in the file.
377
378    :param str GPXfile: full .gpx file name
379    :returns: (Histograms,Phases)
380
381     * Histograms = dictionary of histograms as {name:data,...}
382     * Phases = dictionary of phases that use histograms
383
384    '''
385    phaseNames = GetPhaseNames(GPXfile)
386    histoList = GetHistogramNames(GPXfile,['PWDR','HKLF'])
387    allHistograms = GetHistograms(GPXfile,histoList)
388    phaseData = {}
389    for name in phaseNames: 
390        phaseData[name] =  GetAllPhaseData(GPXfile,name)
391    Histograms = {}
392    Phases = {}
393    for phase in phaseData:
394        Phase = phaseData[phase]
395        if Phase['Histograms']:
396            if phase not in Phases:
397                pId = phaseNames.index(phase)
398                Phase['pId'] = pId
399                Phases[phase] = Phase
400            for hist in Phase['Histograms']:
401                if 'Use' not in Phase['Histograms'][hist]:      #patch
402                    Phase['Histograms'][hist]['Use'] = True         
403                if hist not in Histograms and Phase['Histograms'][hist]['Use']:
404                    try:
405                        Histograms[hist] = allHistograms[hist]
406                        hId = histoList.index(hist)
407                        Histograms[hist]['hId'] = hId
408                    except KeyError: # would happen if a referenced histogram were
409                        # renamed or deleted
410                        print('For phase "'+str(phase)+
411                              '" unresolved reference to histogram "'+str(hist)+'"')
412    G2obj.IndexAllIds(Histograms=Histograms,Phases=Phases)
413    return Histograms,Phases
414   
415def getBackupName(GPXfile,makeBack):
416    '''
417    Get the name for the backup .gpx file name
418   
419    :param str GPXfile: full .gpx file name
420    :param bool makeBack: if True the name of a new file is returned, if
421      False the name of the last file that exists is returned
422    :returns: the name of a backup file
423   
424    '''
425    GPXpath,GPXname = ospath.split(GPXfile)
426    if GPXpath == '': GPXpath = '.'
427    Name = ospath.splitext(GPXname)[0]
428    files = os.listdir(GPXpath)
429    last = 0
430    for name in files:
431        name = name.split('.')
432        if len(name) == 3 and name[0] == Name and 'bak' in name[1]:
433            if makeBack:
434                last = max(last,int(name[1].strip('bak'))+1)
435            else:
436                last = max(last,int(name[1].strip('bak')))
437    GPXback = ospath.join(GPXpath,ospath.splitext(GPXname)[0]+'.bak'+str(last)+'.gpx')
438    return GPXback   
439       
440def GPXBackup(GPXfile,makeBack=True):
441    '''
442    makes a backup of the current .gpx file (?)
443   
444    :param str GPXfile: full .gpx file name
445    :param bool makeBack: if True (default), the backup is written to
446      a new file; if False, the last backup is overwritten
447    :returns: the name of the backup file that was written
448    '''
449    import distutils.file_util as dfu
450    GPXback = getBackupName(GPXfile,makeBack)
451    dfu.copy_file(GPXfile,GPXback)
452    return GPXback
453
454def SetUsedHistogramsAndPhases(GPXfile,Histograms,Phases,RigidBodies,CovData,makeBack=True):
455    ''' Updates gpxfile from all histograms that are found in any phase
456    and any phase that used a histogram. Also updates rigid body definitions.
457
458
459    :param str GPXfile: full .gpx file name
460    :param dict Histograms: dictionary of histograms as {name:data,...}
461    :param dict Phases: dictionary of phases that use histograms
462    :param dict RigidBodies: dictionary of rigid bodies
463    :param dict CovData: dictionary of refined variables, varyList, & covariance matrix
464    :param bool makeBack: True if new backup of .gpx file is to be made; else use the last one made
465
466    '''
467                       
468    import distutils.file_util as dfu
469    GPXback = GPXBackup(GPXfile,makeBack)
470    print 'Read from file:',GPXback
471    print 'Save to file  :',GPXfile
472    infile = open(GPXback,'rb')
473    outfile = open(GPXfile,'wb')
474    while True:
475        try:
476            data = cPickle.load(infile)
477        except EOFError:
478            break
479        datum = data[0]
480#        print 'read: ',datum[0]
481        if datum[0] == 'Phases':
482            for iphase in range(len(data)):
483                if data[iphase][0] in Phases:
484                    phaseName = data[iphase][0]
485                    data[iphase][1].update(Phases[phaseName])
486        elif datum[0] == 'Covariance':
487            data[0][1] = CovData
488        elif datum[0] == 'Rigid bodies':
489            data[0][1] = RigidBodies
490        try:
491            histogram = Histograms[datum[0]]
492#            print 'found ',datum[0]
493            data[0][1][1] = histogram['Data']
494            data[0][1][0].update(histogram['Residuals'])
495            for datus in data[1:]:
496#                print '    read: ',datus[0]
497                if datus[0] in ['Background','Instrument Parameters','Sample Parameters','Reflection Lists']:
498                    datus[1] = histogram[datus[0]]
499        except KeyError:
500            pass
501        try:                       
502            cPickle.dump(data,outfile,1)
503        except AttributeError:
504            print 'ERROR - bad data in least squares result'
505            infile.close()
506            outfile.close()
507            dfu.copy_file(GPXback,GPXfile)
508            print 'GPX file save failed - old version retained'
509            return
510           
511    print 'GPX file save successful'
512   
513def SetSeqResult(GPXfile,Histograms,SeqResult):
514    '''
515    Needs doc string
516   
517    :param str GPXfile: full .gpx file name
518    '''
519    GPXback = GPXBackup(GPXfile)
520    print 'Read from file:',GPXback
521    print 'Save to file  :',GPXfile
522    infile = open(GPXback,'rb')
523    outfile = open(GPXfile,'wb')
524    while True:
525        try:
526            data = cPickle.load(infile)
527        except EOFError:
528            break
529        datum = data[0]
530        if datum[0] == 'Sequential results':
531            data[0][1] = SeqResult
532        # reset the Copy Next flag, since it should not be needed twice in a row
533        if datum[0] == 'Controls':
534            data[0][1]['Copy2Next'] = False
535        try:
536            histogram = Histograms[datum[0]]
537            data[0][1][1] = list(histogram['Data'])
538            for datus in data[1:]:
539                if datus[0] in ['Background','Instrument Parameters','Sample Parameters','Reflection Lists']:
540                    datus[1] = histogram[datus[0]]
541        except KeyError:
542            pass
543                               
544        cPickle.dump(data,outfile,1)
545    infile.close()
546    outfile.close()
547    print 'GPX file save successful'
548                       
549def ShowBanner(pFile=None):
550    'Print authorship, copyright and citation notice'
551    print >>pFile,80*'*'
552    print >>pFile,'   General Structure Analysis System-II Crystal Structure Refinement'
553    print >>pFile,'              by Robert B. Von Dreele & Brian H. Toby'
554    print >>pFile,'                Argonne National Laboratory(C), 2010'
555    print >>pFile,' This product includes software developed by the UChicago Argonne, LLC,' 
556    print >>pFile,'            as Operator of Argonne National Laboratory.'
557    print >>pFile,'                          Please cite:'
558    print >>pFile,'   B.H. Toby & R.B. Von Dreele, J. Appl. Cryst. 46, 544-549 (2013)'
559
560    print >>pFile,80*'*','\n'
561
562def ShowControls(Controls,pFile=None,SeqRef=False):
563    'Print controls information'
564    print >>pFile,' Least squares controls:'
565    print >>pFile,' Refinement type: ',Controls['deriv type']
566    if 'Hessian' in Controls['deriv type']:
567        print >>pFile,' Maximum number of cycles:',Controls['max cyc']
568    else:
569        print >>pFile,' Minimum delta-M/M for convergence: ','%.2g'%(Controls['min dM/M'])
570    print >>pFile,' Initial shift factor: ','%.3f'%(Controls['shift factor'])
571    if SeqRef:
572        print >>pFile,' Sequential refinement controls:'
573        print >>pFile,' Copy of histogram results to next: ',Controls['Copy2Next']
574        print >>pFile,' Process histograms in reverse order: ',Controls['Reverse Seq']
575   
576def GetPawleyConstr(SGLaue,PawleyRef,im,pawleyVary):
577    'needs a doc string'
578#    if SGLaue in ['-1','2/m','mmm']:
579#        return                      #no Pawley symmetry required constraints
580    eqvDict = {}
581    for i,varyI in enumerate(pawleyVary):
582        eqvDict[varyI] = []
583        refI = int(varyI.split(':')[-1])
584        ih,ik,il = PawleyRef[refI][:3]
585        dspI = PawleyRef[refI][4+im]
586        for varyJ in pawleyVary[i+1:]:
587            refJ = int(varyJ.split(':')[-1])
588            jh,jk,jl = PawleyRef[refJ][:3]
589            dspJ = PawleyRef[refJ][4+im]
590            if SGLaue in ['4/m','4/mmm']:
591                isum = ih**2+ik**2
592                jsum = jh**2+jk**2
593                if abs(il) == abs(jl) and isum == jsum:
594                    eqvDict[varyI].append(varyJ) 
595            elif SGLaue in ['3R','3mR']:
596                isum = ih**2+ik**2+il**2
597                jsum = jh**2+jk**2+jl**2
598                isum2 = ih*ik+ih*il+ik*il
599                jsum2 = jh*jk+jh*jl+jk*jl
600                if isum == jsum and isum2 == jsum2:
601                    eqvDict[varyI].append(varyJ) 
602            elif SGLaue in ['3','3m1','31m','6/m','6/mmm']:
603                isum = ih**2+ik**2+ih*ik
604                jsum = jh**2+jk**2+jh*jk
605                if abs(il) == abs(jl) and isum == jsum:
606                    eqvDict[varyI].append(varyJ) 
607            elif SGLaue in ['m3','m3m']:
608                isum = ih**2+ik**2+il**2
609                jsum = jh**2+jk**2+jl**2
610                if isum == jsum:
611                    eqvDict[varyI].append(varyJ)
612            elif abs(dspI-dspJ)/dspI < 1.e-4:
613                eqvDict[varyI].append(varyJ) 
614    for item in pawleyVary:
615        if eqvDict[item]:
616            for item2 in pawleyVary:
617                if item2 in eqvDict[item]:
618                    eqvDict[item2] = []
619            G2mv.StoreEquivalence(item,eqvDict[item])
620                   
621def cellVary(pfx,SGData): 
622    'needs a doc string'
623    if SGData['SGLaue'] in ['-1',]:
624        return [pfx+'A0',pfx+'A1',pfx+'A2',pfx+'A3',pfx+'A4',pfx+'A5']
625    elif SGData['SGLaue'] in ['2/m',]:
626        if SGData['SGUniq'] == 'a':
627            return [pfx+'A0',pfx+'A1',pfx+'A2',pfx+'A5']
628        elif SGData['SGUniq'] == 'b':
629            return [pfx+'A0',pfx+'A1',pfx+'A2',pfx+'A4']
630        else:
631            return [pfx+'A0',pfx+'A1',pfx+'A2',pfx+'A3']
632    elif SGData['SGLaue'] in ['mmm',]:
633        return [pfx+'A0',pfx+'A1',pfx+'A2']
634    elif SGData['SGLaue'] in ['4/m','4/mmm']:
635        G2mv.StoreEquivalence(pfx+'A0',(pfx+'A1',))
636        return [pfx+'A0',pfx+'A1',pfx+'A2']
637    elif SGData['SGLaue'] in ['6/m','6/mmm','3m1', '31m', '3']:
638        G2mv.StoreEquivalence(pfx+'A0',(pfx+'A1',pfx+'A3',))
639        return [pfx+'A0',pfx+'A1',pfx+'A2',pfx+'A3']
640    elif SGData['SGLaue'] in ['3R', '3mR']:
641        G2mv.StoreEquivalence(pfx+'A0',(pfx+'A1',pfx+'A2',))
642        G2mv.StoreEquivalence(pfx+'A3',(pfx+'A4',pfx+'A5',))
643        return [pfx+'A0',pfx+'A1',pfx+'A2',pfx+'A3',pfx+'A4',pfx+'A5']                       
644    elif SGData['SGLaue'] in ['m3m','m3']:
645        G2mv.StoreEquivalence(pfx+'A0',(pfx+'A1',pfx+'A2',))
646        return [pfx+'A0',pfx+'A1',pfx+'A2']
647       
648def modVary(pfx,SSGData):
649    vary = []
650    for i,item in enumerate(SSGData['modSymb']):
651        if item in ['a','b','g']:
652            vary.append(pfx+'mV%d'%(i))
653    return vary
654       
655################################################################################
656##### Rigid Body Models and not General.get('doPawley')
657################################################################################
658       
659def GetRigidBodyModels(rigidbodyDict,Print=True,pFile=None):
660    'needs a doc string'
661   
662    def PrintResRBModel(RBModel):
663        atNames = RBModel['atNames']
664        rbRef = RBModel['rbRef']
665        rbSeq = RBModel['rbSeq']
666        print >>pFile,'Residue RB name: ',RBModel['RBname'],' no.atoms: ',len(RBModel['rbTypes']), \
667            'No. times used: ',RBModel['useCount']
668        print >>pFile,'    At name       x          y          z'
669        for name,xyz in zip(atNames,RBModel['rbXYZ']):
670            print >>pFile,%8s %10.4f %10.4f %10.4f'%(name,xyz[0],xyz[1],xyz[2])
671        print >>pFile,'Orientation defined by:',atNames[rbRef[0]],' -> ',atNames[rbRef[1]], \
672            ' & ',atNames[rbRef[0]],' -> ',atNames[rbRef[2]]
673        if rbSeq:
674            for i,rbseq in enumerate(rbSeq):
675                print >>pFile,'Torsion sequence ',i,' Bond: '+atNames[rbseq[0]],' - ', \
676                    atNames[rbseq[1]],' riding: ',[atNames[i] for i in rbseq[3]]
677       
678    def PrintVecRBModel(RBModel):
679        rbRef = RBModel['rbRef']
680        atTypes = RBModel['rbTypes']
681        print >>pFile,'Vector RB name: ',RBModel['RBname'],' no.atoms: ',len(RBModel['rbTypes']), \
682            'No. times used: ',RBModel['useCount']
683        for i in range(len(RBModel['VectMag'])):
684            print >>pFile,'Vector no.: ',i,' Magnitude: ', \
685                '%8.4f'%(RBModel['VectMag'][i]),' Refine? ',RBModel['VectRef'][i]
686            print >>pFile,'  No. Type     vx         vy         vz'
687            for j,[name,xyz] in enumerate(zip(atTypes,RBModel['rbVect'][i])):
688                print >>pFile,%d   %2s %10.4f %10.4f %10.4f'%(j,name,xyz[0],xyz[1],xyz[2])
689        print >>pFile,'  No. Type      x          y          z'
690        for i,[name,xyz] in enumerate(zip(atTypes,RBModel['rbXYZ'])):
691            print >>pFile,%d   %2s %10.4f %10.4f %10.4f'%(i,name,xyz[0],xyz[1],xyz[2])
692        print >>pFile,'Orientation defined by: atom ',rbRef[0],' -> atom ',rbRef[1], \
693            ' & atom ',rbRef[0],' -> atom ',rbRef[2]
694    rbVary = []
695    rbDict = {}
696    rbIds = rigidbodyDict.get('RBIds',{'Vector':[],'Residue':[]})
697    if len(rbIds['Vector']):
698        for irb,item in enumerate(rbIds['Vector']):
699            if rigidbodyDict['Vector'][item]['useCount']:
700                RBmags = rigidbodyDict['Vector'][item]['VectMag']
701                RBrefs = rigidbodyDict['Vector'][item]['VectRef']
702                for i,[mag,ref] in enumerate(zip(RBmags,RBrefs)):
703                    pid = '::RBV;'+str(i)+':'+str(irb)
704                    rbDict[pid] = mag
705                    if ref:
706                        rbVary.append(pid)
707                if Print:
708                    print >>pFile,'\nVector rigid body model:'
709                    PrintVecRBModel(rigidbodyDict['Vector'][item])
710    if len(rbIds['Residue']):
711        for item in rbIds['Residue']:
712            if rigidbodyDict['Residue'][item]['useCount']:
713                if Print:
714                    print >>pFile,'\nResidue rigid body model:'
715                    PrintResRBModel(rigidbodyDict['Residue'][item])
716    return rbVary,rbDict
717   
718def SetRigidBodyModels(parmDict,sigDict,rigidbodyDict,pFile=None):
719    'needs a doc string'
720   
721    def PrintRBVectandSig(VectRB,VectSig):
722        print >>pFile,'\n Rigid body vector magnitudes for '+VectRB['RBname']+':'
723        namstr = '  names :'
724        valstr = '  values:'
725        sigstr = '  esds  :'
726        for i,[val,sig] in enumerate(zip(VectRB['VectMag'],VectSig)):
727            namstr += '%12s'%('Vect '+str(i))
728            valstr += '%12.4f'%(val)
729            if sig:
730                sigstr += '%12.4f'%(sig)
731            else:
732                sigstr += 12*' '
733        print >>pFile,namstr
734        print >>pFile,valstr
735        print >>pFile,sigstr       
736       
737    RBIds = rigidbodyDict.get('RBIds',{'Vector':[],'Residue':[]})  #these are lists of rbIds
738    if not RBIds['Vector']:
739        return
740    for irb,item in enumerate(RBIds['Vector']):
741        if rigidbodyDict['Vector'][item]['useCount']:
742            VectSig = []
743            RBmags = rigidbodyDict['Vector'][item]['VectMag']
744            for i,mag in enumerate(RBmags):
745                name = '::RBV;'+str(i)+':'+str(irb)
746                mag = parmDict[name]
747                if name in sigDict:
748                    VectSig.append(sigDict[name])
749            PrintRBVectandSig(rigidbodyDict['Vector'][item],VectSig)   
750       
751################################################################################
752##### Phase data
753################################################################################       
754                   
755def GetPhaseData(PhaseData,RestraintDict={},rbIds={},Print=True,pFile=None):
756    'needs a doc string'
757           
758    def PrintFFtable(FFtable):
759        print >>pFile,'\n X-ray scattering factors:'
760        print >>pFile,'   Symbol     fa                                      fb                                      fc'
761        print >>pFile,99*'-'
762        for Ename in FFtable:
763            ffdata = FFtable[Ename]
764            fa = ffdata['fa']
765            fb = ffdata['fb']
766            print >>pFile,' %8s %9.5f %9.5f %9.5f %9.5f %9.5f %9.5f %9.5f %9.5f %9.5f' %  \
767                (Ename.ljust(8),fa[0],fa[1],fa[2],fa[3],fb[0],fb[1],fb[2],fb[3],ffdata['fc'])
768               
769    def PrintBLtable(BLtable):
770        print >>pFile,'\n Neutron scattering factors:'
771        print >>pFile,'   Symbol   isotope       mass       b       resonant terms'
772        print >>pFile,99*'-'
773        for Ename in BLtable:
774            bldata = BLtable[Ename]
775            isotope = bldata[0]
776            mass = bldata[1]['Mass']
777            if 'SL' in bldata[1]:
778                blen = bldata[1]['SL'][0]
779                bres = []
780            else:
781                blen = 0
782                bres = bldata[1]['BW-LS']
783            line = ' %8s%11s %10.3f %8.3f'%(Ename.ljust(8),isotope.center(11),mass,blen)
784            for item in bres:
785                line += '%10.5g'%(item)
786            print >>pFile,line
787           
788    def PrintRBObjects(resRBData,vecRBData):
789       
790        def PrintRBThermals():
791            tlstr = ['11','22','33','12','13','23']
792            sstr = ['12','13','21','23','31','32','AA','BB']
793            TLS = RB['ThermalMotion'][1]
794            TLSvar = RB['ThermalMotion'][2]
795            if 'T' in RB['ThermalMotion'][0]:
796                print >>pFile,'TLS data'
797                text = ''
798                for i in range(6):
799                    text += 'T'+tlstr[i]+' %8.4f %s '%(TLS[i],str(TLSvar[i])[0])
800                print >>pFile,text
801                if 'L' in RB['ThermalMotion'][0]: 
802                    text = ''
803                    for i in range(6,12):
804                        text += 'L'+tlstr[i-6]+' %8.2f %s '%(TLS[i],str(TLSvar[i])[0])
805                    print >>pFile,text
806                if 'S' in RB['ThermalMotion'][0]:
807                    text = ''
808                    for i in range(12,20):
809                        text += 'S'+sstr[i-12]+' %8.3f %s '%(TLS[i],str(TLSvar[i])[0])
810                    print >>pFile,text
811            if 'U' in RB['ThermalMotion'][0]:
812                print >>pFile,'Uiso data'
813                text = 'Uiso'+' %10.3f %s'%(TLS[0],str(TLSvar[0])[0])           
814           
815        if len(resRBData):
816            for RB in resRBData:
817                Oxyz = RB['Orig'][0]
818                Qrijk = RB['Orient'][0]
819                Angle = 2.0*acosd(Qrijk[0])
820                print >>pFile,'\nRBObject ',RB['RBname'],' at ',      \
821                    '%10.4f %10.4f %10.4f'%(Oxyz[0],Oxyz[1],Oxyz[2]),' Refine?',RB['Orig'][1]
822                print >>pFile,'Orientation angle,vector:',      \
823                    '%10.3f %10.4f %10.4f %10.4f'%(Angle,Qrijk[1],Qrijk[2],Qrijk[3]),' Refine? ',RB['Orient'][1]
824                Torsions = RB['Torsions']
825                if len(Torsions):
826                    text = 'Torsions: '
827                    for torsion in Torsions:
828                        text += '%10.4f Refine? %s'%(torsion[0],torsion[1])
829                    print >>pFile,text
830                PrintRBThermals()
831        if len(vecRBData):
832            for RB in vecRBData:
833                Oxyz = RB['Orig'][0]
834                Qrijk = RB['Orient'][0]
835                Angle = 2.0*acosd(Qrijk[0])
836                print >>pFile,'\nRBObject ',RB['RBname'],' at ',      \
837                    '%10.4f %10.4f %10.4f'%(Oxyz[0],Oxyz[1],Oxyz[2]),' Refine?',RB['Orig'][1]           
838                print >>pFile,'Orientation angle,vector:',      \
839                    '%10.3f %10.4f %10.4f %10.4f'%(Angle,Qrijk[1],Qrijk[2],Qrijk[3]),' Refine? ',RB['Orient'][1]
840                PrintRBThermals()
841               
842    def PrintAtoms(General,Atoms):
843        cx,ct,cs,cia = General['AtomPtrs']
844        print >>pFile,'\n Atoms:'
845        line = '   name    type  refine?   x         y         z    '+ \
846            '  frac site sym  mult I/A   Uiso     U11     U22     U33     U12     U13     U23'
847        if General['Type'] == 'macromolecular':
848            line = ' res no residue chain'+line
849        print >>pFile,line
850        if General['Type'] in ['nuclear','modulated','magnetic']:
851            print >>pFile,135*'-'
852            for i,at in enumerate(Atoms):
853                line = '%7s'%(at[ct-1])+'%7s'%(at[ct])+'%7s'%(at[ct+1])+'%10.5f'%(at[cx])+'%10.5f'%(at[cx+1])+ \
854                    '%10.5f'%(at[cx+2])+'%8.3f'%(at[cx+3])+'%7s'%(at[cs])+'%5d'%(at[cs+1])+'%5s'%(at[cia])
855                if at[cia] == 'I':
856                    line += '%8.5f'%(at[cia+1])+48*' '
857                else:
858                    line += 8*' '
859                    for j in range(6):
860                        line += '%8.5f'%(at[cia+2+j])
861                print >>pFile,line
862        elif General['Type'] == 'macromolecular':
863            print >>pFile,135*'-'           
864            for i,at in enumerate(Atoms):
865                line = '%7s'%(at[0])+'%7s'%(at[1])+'%7s'%(at[2])+'%7s'%(at[ct-1])+'%7s'%(at[ct])+'%7s'%(at[ct+1])+'%10.5f'%(at[cx])+'%10.5f'%(at[cx+1])+ \
866                    '%10.5f'%(at[cx+2])+'%8.3f'%(at[cx+3])+'%7s'%(at[cs])+'%5d'%(at[cs+1])+'%5s'%(at[cia])
867                if at[cia] == 'I':
868                    line += '%8.4f'%(at[cia+1])+48*' '
869                else:
870                    line += 8*' '
871                    for j in range(6):
872                        line += '%8.4f'%(at[cia+2+j])
873                print >>pFile,line
874               
875    def PrintWaves(General,Atoms):
876        cx,ct,cs,cia = General['AtomPtrs']
877        print >>pFile,'\n Modulation waves'
878        names = {'Sfrac':['Fsin','Fcos','Fzero','Fwid'],'Spos':['Xsin','Ysin','Zsin','Xcos','Ycos','Zcos','Tzero','Xslope','Yslope','Zslope'],
879            'Sadp':['U11sin','U22sin','U33sin','U12sin','U13sin','U23sin','U11cos','U22cos',
880            'U33cos','U12cos','U13cos','U23cos'],'Smag':['MXsin','MYsin','MZsin','MXcos','MYcos','MZcos']}
881        print >>pFile,135*'-'
882        for i,at in enumerate(Atoms):
883            AtomSS = at[-1]['SS1']
884            for Stype in ['Sfrac','Spos','Sadp','Smag']:
885                Waves = AtomSS[Stype]
886                if len(Waves):
887                    print >>pFile,' atom: %s, site sym: %s, type: %s wave type: %s:'    \
888                        %(at[ct-1],at[cs],Stype,AtomSS['waveType'])
889                    line = ''
890                    for item in names[Stype]:
891                        line += '%8s '%(item)
892                    print >>pFile,line
893                for wave in Waves:                   
894                    line = ''
895                    for item in wave[0]:
896                        line += '%8.4f '%(item)
897                    line += ' Refine? '+str(wave[1])
898                    print >>pFile,line
899       
900    def PrintTexture(textureData):
901        topstr = '\n Spherical harmonics texture: Order:' + \
902            str(textureData['Order'])
903        if textureData['Order']:
904            print >>pFile,topstr+' Refine? '+str(textureData['SH Coeff'][0])
905        else:
906            print >>pFile,topstr
907            return
908        names = ['omega','chi','phi']
909        line = '\n'
910        for name in names:
911            line += ' SH '+name+':'+'%12.4f'%(textureData['Sample '+name][1])+' Refine? '+str(textureData['Sample '+name][0])
912        print >>pFile,line
913        print >>pFile,'\n Texture coefficients:'
914        SHcoeff = textureData['SH Coeff'][1]
915        SHkeys = SHcoeff.keys()
916        nCoeff = len(SHcoeff)
917        nBlock = nCoeff/10+1
918        iBeg = 0
919        iFin = min(iBeg+10,nCoeff)
920        for block in range(nBlock):
921            ptlbls = ' names :'
922            ptstr =  ' values:'
923            for item in SHkeys[iBeg:iFin]:
924                ptlbls += '%12s'%(item)
925                ptstr += '%12.4f'%(SHcoeff[item]) 
926            print >>pFile,ptlbls
927            print >>pFile,ptstr
928            iBeg += 10
929            iFin = min(iBeg+10,nCoeff)
930       
931    def MakeRBParms(rbKey,phaseVary,phaseDict):
932        rbid = str(rbids.index(RB['RBId']))
933        pfxRB = pfx+'RB'+rbKey+'P'
934        pstr = ['x','y','z']
935        ostr = ['a','i','j','k']
936        for i in range(3):
937            name = pfxRB+pstr[i]+':'+str(iRB)+':'+rbid
938            phaseDict[name] = RB['Orig'][0][i]
939            if RB['Orig'][1]:
940                phaseVary += [name,]
941        pfxRB = pfx+'RB'+rbKey+'O'
942        for i in range(4):
943            name = pfxRB+ostr[i]+':'+str(iRB)+':'+rbid
944            phaseDict[name] = RB['Orient'][0][i]
945            if RB['Orient'][1] == 'AV' and i:
946                phaseVary += [name,]
947            elif RB['Orient'][1] == 'A' and not i:
948                phaseVary += [name,]
949           
950    def MakeRBThermals(rbKey,phaseVary,phaseDict):
951        rbid = str(rbids.index(RB['RBId']))
952        tlstr = ['11','22','33','12','13','23']
953        sstr = ['12','13','21','23','31','32','AA','BB']
954        if 'T' in RB['ThermalMotion'][0]:
955            pfxRB = pfx+'RB'+rbKey+'T'
956            for i in range(6):
957                name = pfxRB+tlstr[i]+':'+str(iRB)+':'+rbid
958                phaseDict[name] = RB['ThermalMotion'][1][i]
959                if RB['ThermalMotion'][2][i]:
960                    phaseVary += [name,]
961        if 'L' in RB['ThermalMotion'][0]:
962            pfxRB = pfx+'RB'+rbKey+'L'
963            for i in range(6):
964                name = pfxRB+tlstr[i]+':'+str(iRB)+':'+rbid
965                phaseDict[name] = RB['ThermalMotion'][1][i+6]
966                if RB['ThermalMotion'][2][i+6]:
967                    phaseVary += [name,]
968        if 'S' in RB['ThermalMotion'][0]:
969            pfxRB = pfx+'RB'+rbKey+'S'
970            for i in range(8):
971                name = pfxRB+sstr[i]+':'+str(iRB)+':'+rbid
972                phaseDict[name] = RB['ThermalMotion'][1][i+12]
973                if RB['ThermalMotion'][2][i+12]:
974                    phaseVary += [name,]
975        if 'U' in RB['ThermalMotion'][0]:
976            name = pfx+'RB'+rbKey+'U:'+str(iRB)+':'+rbid
977            phaseDict[name] = RB['ThermalMotion'][1][0]
978            if RB['ThermalMotion'][2][0]:
979                phaseVary += [name,]
980               
981    def MakeRBTorsions(rbKey,phaseVary,phaseDict):
982        rbid = str(rbids.index(RB['RBId']))
983        pfxRB = pfx+'RB'+rbKey+'Tr;'
984        for i,torsion in enumerate(RB['Torsions']):
985            name = pfxRB+str(i)+':'+str(iRB)+':'+rbid
986            phaseDict[name] = torsion[0]
987            if torsion[1]:
988                phaseVary += [name,]
989                   
990    if Print:
991        print  >>pFile,'\n Phases:'
992    phaseVary = []
993    phaseDict = {}
994    phaseConstr = {}
995    pawleyLookup = {}
996    FFtables = {}                   #scattering factors - xrays
997    BLtables = {}                   # neutrons
998    Natoms = {}
999    AtMults = {}
1000    AtIA = {}
1001    maxSSwave = {}
1002    shModels = ['cylindrical','none','shear - 2/m','rolling - mmm']
1003    SamSym = dict(zip(shModels,['0','-1','2/m','mmm']))
1004    atomIndx = {}
1005    for name in PhaseData:
1006        General = PhaseData[name]['General']
1007        pId = PhaseData[name]['pId']
1008        pfx = str(pId)+'::'
1009        FFtable = G2el.GetFFtable(General['AtomTypes'])
1010        BLtable = G2el.GetBLtable(General)
1011        FFtables.update(FFtable)
1012        BLtables.update(BLtable)
1013        Atoms = PhaseData[name]['Atoms']
1014        if Atoms and not General.get('doPawley'):
1015            cx,ct,cs,cia = General['AtomPtrs']
1016            AtLookup = G2mth.FillAtomLookUp(Atoms,cia+8)
1017        PawleyRef = PhaseData[name].get('Pawley ref',[])
1018        SGData = General['SGData']
1019        SGtext,SGtable = G2spc.SGPrint(SGData)
1020        cell = General['Cell']
1021        A = G2lat.cell2A(cell[1:7])
1022        phaseDict.update({pfx+'A0':A[0],pfx+'A1':A[1],pfx+'A2':A[2],
1023            pfx+'A3':A[3],pfx+'A4':A[4],pfx+'A5':A[5],pfx+'Vol':G2lat.calc_V(A)})
1024        if cell[0]:
1025            phaseVary += cellVary(pfx,SGData)       #also fills in symmetry required constraints
1026        SSGtext = []    #no superstructure
1027        im = 0
1028        if General['Type'] in ['modulated','magnetic']:
1029            im = 1      #refl offset
1030            Vec,vRef,maxH = General['SuperVec']
1031            phaseDict.update({pfx+'mV0':Vec[0],pfx+'mV1':Vec[1],pfx+'mV2':Vec[2]})
1032            SSGData = General['SSGData']
1033            SSGtext,SSGtable = G2spc.SSGPrint(SGData,SSGData)
1034            if vRef:
1035                phaseVary += modVary(pfx,SSGData)       
1036        resRBData = PhaseData[name]['RBModels'].get('Residue',[])
1037        if resRBData:
1038            rbids = rbIds['Residue']    #NB: used in the MakeRB routines
1039            for iRB,RB in enumerate(resRBData):
1040                MakeRBParms('R',phaseVary,phaseDict)
1041                MakeRBThermals('R',phaseVary,phaseDict)
1042                MakeRBTorsions('R',phaseVary,phaseDict)
1043       
1044        vecRBData = PhaseData[name]['RBModels'].get('Vector',[])
1045        if vecRBData:
1046            rbids = rbIds['Vector']    #NB: used in the MakeRB routines
1047            for iRB,RB in enumerate(vecRBData):
1048                MakeRBParms('V',phaseVary,phaseDict)
1049                MakeRBThermals('V',phaseVary,phaseDict)
1050                   
1051        Natoms[pfx] = 0
1052        maxSSwave[pfx] = {'Sfrac':0,'Spos':0,'Sadp':0,'Smag':0}
1053        if Atoms and not General.get('doPawley'):
1054            cx,ct,cs,cia = General['AtomPtrs']
1055            Natoms[pfx] = len(Atoms)
1056            for i,at in enumerate(Atoms):
1057                atomIndx[at[cia+8]] = [pfx,i]      #lookup table for restraints
1058                phaseDict.update({pfx+'Atype:'+str(i):at[ct],pfx+'Afrac:'+str(i):at[cx+3],pfx+'Amul:'+str(i):at[cs+1],
1059                    pfx+'Ax:'+str(i):at[cx],pfx+'Ay:'+str(i):at[cx+1],pfx+'Az:'+str(i):at[cx+2],
1060                    pfx+'dAx:'+str(i):0.,pfx+'dAy:'+str(i):0.,pfx+'dAz:'+str(i):0.,         #refined shifts for x,y,z
1061                    pfx+'AI/A:'+str(i):at[cia],})
1062                if at[cia] == 'I':
1063                    phaseDict[pfx+'AUiso:'+str(i)] = at[cia+1]
1064                else:
1065                    phaseDict.update({pfx+'AU11:'+str(i):at[cia+2],pfx+'AU22:'+str(i):at[cia+3],pfx+'AU33:'+str(i):at[cia+4],
1066                        pfx+'AU12:'+str(i):at[cia+5],pfx+'AU13:'+str(i):at[cia+6],pfx+'AU23:'+str(i):at[cia+7]})
1067                if 'F' in at[ct+1]:
1068                    phaseVary.append(pfx+'Afrac:'+str(i))
1069                if 'X' in at[ct+1]:
1070                    try:    #patch for sytsym name changes
1071                        xId,xCoef = G2spc.GetCSxinel(at[cs])
1072                    except KeyError:
1073                        Sytsym = G2spc.SytSym(at[cx:cx+3],SGData)[0]
1074                        at[cs] = Sytsym
1075                        xId,xCoef = G2spc.GetCSxinel(at[cs])
1076                    xId,xCoef = G2spc.GetCSxinel(at[cs])
1077                    names = [pfx+'dAx:'+str(i),pfx+'dAy:'+str(i),pfx+'dAz:'+str(i)]
1078                    equivs = [[],[],[]]
1079                    for j in range(3):
1080                        if xId[j] > 0:                               
1081                            phaseVary.append(names[j])
1082                            equivs[xId[j]-1].append([names[j],xCoef[j]])
1083                    for equiv in equivs:
1084                        if len(equiv) > 1:
1085                            name = equiv[0][0]
1086                            coef = equiv[0][1]
1087                            for eqv in equiv[1:]:
1088                                eqv[1] /= coef
1089                                G2mv.StoreEquivalence(name,(eqv,))
1090                if 'U' in at[ct+1]:
1091                    if at[cia] == 'I':
1092                        phaseVary.append(pfx+'AUiso:'+str(i))
1093                    else:
1094                        try:    #patch for sytsym name changes
1095                            uId,uCoef = G2spc.GetCSuinel(at[cs])[:2]
1096                        except KeyError:
1097                            Sytsym = G2spc.SytSym(at[cx:cx+3],SGData)[0]
1098                            at[cs] = Sytsym
1099                            uId,uCoef = G2spc.GetCSuinel(at[cs])[:2]
1100                        uId,uCoef = G2spc.GetCSuinel(at[cs])[:2]
1101                        names = [pfx+'AU11:'+str(i),pfx+'AU22:'+str(i),pfx+'AU33:'+str(i),
1102                            pfx+'AU12:'+str(i),pfx+'AU13:'+str(i),pfx+'AU23:'+str(i)]
1103                        equivs = [[],[],[],[],[],[]]
1104                        for j in range(6):
1105                            if uId[j] > 0:                               
1106                                phaseVary.append(names[j])
1107                                equivs[uId[j]-1].append([names[j],uCoef[j]])
1108                        for equiv in equivs:
1109                            if len(equiv) > 1:
1110                                name = equiv[0][0]
1111                                coef = equiv[0][1]
1112                                for eqv in equiv[1:]:
1113                                    eqv[1] /= coef
1114                                G2mv.StoreEquivalence(name,equiv[1:])
1115                if General['Type'] in ['modulated','magnetic']:
1116                    AtomSS = at[-1]['SS1']
1117                    waveType = AtomSS['waveType']
1118                    phaseDict[pfx+'waveType:'+str(i)] = waveType   
1119                    for Stype in ['Sfrac','Spos','Sadp','Smag']:
1120                        Waves = AtomSS[Stype]
1121                        uId,uCoef = CSI[Stype]
1122                        for iw,wave in enumerate(Waves):
1123                            if not iw:
1124                                CSI = G2spc.GetSSfxuinel(waveType,at[cx:cx+3],SGData,SSGData)
1125                            else:
1126                                CSI = G2spc.GetSSfxuinel('Fourier',at[cx:cx+3],SGData,SSGData)
1127                            stiw = str(i)+':'+str(iw)
1128                            if Stype == 'Spos':
1129                                if waveType in ['ZigZag','Sawtooth'] and not iw:
1130                                    names = [pfx+'Tzero:'+stiw,pfx+'Xslope:'+stiw,pfx+'Yslope:'+stiw,pfx+'Zslope:'+stiw]
1131                                    equivs = [[], [],[],[]]
1132                                else:
1133                                    names = [pfx+'Xsin:'+stiw,pfx+'Ysin:'+stiw,pfx+'Zsin:'+stiw,
1134                                        pfx+'Xcos:'+stiw,pfx+'Ycos:'+stiw,pfx+'Zcos:'+stiw]
1135                                    equivs = [[],[],[], [],[],[]]
1136                            elif Stype == 'Sadp':
1137                                names = [pfx+'U11sin:'+stiw,pfx+'U22sin:'+stiw,pfx+'U33sin:'+stiw,
1138                                    pfx+'U12sin:'+stiw,pfx+'U13sin:'+stiw,pfx+'U23sin:'+stiw,
1139                                    pfx+'U11cos:'+stiw,pfx+'U22cos:'+stiw,pfx+'U33cos:'+stiw,
1140                                    pfx+'U12cos:'+stiw,pfx+'U13cos:'+stiw,pfx+'U23cos:'+stiw]
1141                                equivs = [[],[],[],[],[],[], [],[],[],[],[],[]]
1142                            elif Stype == 'Sfrac':
1143                                equivs = [[],[]]
1144                                if 'Crenel' in waveType and not iw:
1145                                    names = [pfx+'Fzero:'+stiw,pfx+'Fwid:'+stiw]
1146                                else:
1147                                    names = [pfx+'Fsin:'+stiw,pfx+'Fcos:'+stiw]
1148                            elif Stype == 'Smag':
1149                                equivs = [[],[],[], [],[],[]]
1150                                names = [pfx+'MXsin:'+stiw,pfx+'MYsin:'+stiw,pfx+'MZsin:'+stiw,
1151                                    pfx+'MXcos:'+stiw,pfx+'MYcos:'+stiw,pfx+'MZcos:'+stiw]
1152                            phaseDict.update(dict(zip(names,wave[0])))
1153                            if wave[1]:
1154                                for j in range(len(equivs)):
1155                                    if uId[j] > 0:                               
1156                                        phaseVary.append(names[j])
1157                                        equivs[uId[j]-1].append([names[j],uCoef[j]])
1158                                for equiv in equivs:
1159                                    if len(equiv) > 1:
1160                                        name = equiv[0][0]
1161                                        coef = equiv[0][1]
1162                                        for eqv in equiv[1:]:
1163                                            eqv[1] /= coef
1164                                        G2mv.StoreEquivalence(name,equiv[1:])
1165                            maxSSwave[pfx][Stype] = max(maxSSwave[pfx][Stype],iw+1)
1166            textureData = General['SH Texture']
1167            if textureData['Order']:
1168                phaseDict[pfx+'SHorder'] = textureData['Order']
1169                phaseDict[pfx+'SHmodel'] = SamSym[textureData['Model']]
1170                for item in ['omega','chi','phi']:
1171                    phaseDict[pfx+'SH '+item] = textureData['Sample '+item][1]
1172                    if textureData['Sample '+item][0]:
1173                        phaseVary.append(pfx+'SH '+item)
1174                for item in textureData['SH Coeff'][1]:
1175                    phaseDict[pfx+item] = textureData['SH Coeff'][1][item]
1176                    if textureData['SH Coeff'][0]:
1177                        phaseVary.append(pfx+item)
1178               
1179            if Print:
1180                print >>pFile,'\n Phase name: ',General['Name']
1181                print >>pFile,135*'-'
1182                PrintFFtable(FFtable)
1183                PrintBLtable(BLtable)
1184                print >>pFile,''
1185                if len(SSGtext):    #if superstructure
1186                    for line in SSGtext: print >>pFile,line
1187                    if len(SSGtable):
1188                        for item in SSGtable:
1189                            line = ' %s '%(item)
1190                            print >>pFile,line   
1191                    else:
1192                        print >>pFile,' ( 1)    %s'%(SSGtable[0])
1193                else:
1194                    for line in SGtext: print >>pFile,line
1195                    if len(SGtable):
1196                        for item in SGtable:
1197                            line = ' %s '%(item)
1198                            print >>pFile,line   
1199                    else:
1200                        print >>pFile,' ( 1)    %s'%(SGtable[0])
1201                PrintRBObjects(resRBData,vecRBData)
1202                PrintAtoms(General,Atoms)
1203                if General['Type'] in ['modulated','magnetic']:
1204                    PrintWaves(General,Atoms)
1205                print >>pFile,'\n Unit cell: a = %.5f'%(cell[1]),' b = %.5f'%(cell[2]),' c = %.5f'%(cell[3]), \
1206                    ' alpha = %.3f'%(cell[4]),' beta = %.3f'%(cell[5]),' gamma = %.3f'%(cell[6]), \
1207                    ' volume = %.3f'%(cell[7]),' Refine?',cell[0]
1208                if len(SSGtext):    #if superstructure
1209                    print >>pFile,'\n Modulation vector: mV0 = %.4f'%(Vec[0]),' mV1 = %.4f'%(Vec[1]),   \
1210                        ' mV2 = %.4f'%(Vec[2]),' max mod. index = %d'%(maxH),' Refine?',vRef
1211                PrintTexture(textureData)
1212                if name in RestraintDict:
1213                    PrintRestraints(cell[1:7],SGData,General['AtomPtrs'],Atoms,AtLookup,
1214                        textureData,RestraintDict[name],pFile)
1215                   
1216        elif PawleyRef:
1217            if Print:
1218                print >>pFile,'\n Phase name: ',General['Name']
1219                print >>pFile,135*'-'
1220                print >>pFile,''
1221                if len(SSGtext):    #if superstructure
1222                    for line in SSGtext: print >>pFile,line
1223                    if len(SSGtable):
1224                        for item in SSGtable:
1225                            line = ' %s '%(item)
1226                            print >>pFile,line   
1227                    else:
1228                        print >>pFile,' ( 1)    %s'%(SSGtable[0])
1229                else:
1230                    for line in SGtext: print >>pFile,line
1231                    if len(SGtable):
1232                        for item in SGtable:
1233                            line = ' %s '%(item)
1234                            print >>pFile,line   
1235                    else:
1236                        print >>pFile,' ( 1)    %s'%(SGtable[0])
1237                print >>pFile,'\n Unit cell: a = %.5f'%(cell[1]),' b = %.5f'%(cell[2]),' c = %.5f'%(cell[3]), \
1238                    ' alpha = %.3f'%(cell[4]),' beta = %.3f'%(cell[5]),' gamma = %.3f'%(cell[6]), \
1239                    ' volume = %.3f'%(cell[7]),' Refine?',cell[0]
1240                if len(SSGtext):    #if superstructure
1241                    print >>pFile,'\n Modulation vector: mV0 = %.4f'%(Vec[0]),' mV1 = %.4f'%(Vec[1]),   \
1242                        ' mV2 = %.4f'%(Vec[2]),' max mod. index = %d'%(maxH),' Refine?',vRef
1243            pawleyVary = []
1244            for i,refl in enumerate(PawleyRef):
1245                phaseDict[pfx+'PWLref:'+str(i)] = refl[6+im]
1246                if im:
1247                    pawleyLookup[pfx+'%d,%d,%d,%d'%(refl[0],refl[1],refl[2],refl[3])] = i
1248                else:
1249                    pawleyLookup[pfx+'%d,%d,%d'%(refl[0],refl[1],refl[2])] = i
1250                if refl[5+im]:
1251                    pawleyVary.append(pfx+'PWLref:'+str(i))
1252            GetPawleyConstr(SGData['SGLaue'],PawleyRef,im,pawleyVary)      #does G2mv.StoreEquivalence
1253            phaseVary += pawleyVary
1254               
1255    return Natoms,atomIndx,phaseVary,phaseDict,pawleyLookup,FFtables,BLtables,maxSSwave
1256   
1257def cellFill(pfx,SGData,parmDict,sigDict): 
1258    '''Returns the filled-out reciprocal cell (A) terms and their uncertainties
1259    from the parameter and sig dictionaries.
1260
1261    :param str pfx: parameter prefix ("n::", where n is a phase number)
1262    :param dict SGdata: a symmetry object
1263    :param dict parmDict: a dictionary of parameters
1264    :param dict sigDict:  a dictionary of uncertainties on parameters
1265
1266    :returns: A,sigA where each is a list of six terms with the A terms
1267    '''
1268    if SGData['SGLaue'] in ['-1',]:
1269        A = [parmDict[pfx+'A0'],parmDict[pfx+'A1'],parmDict[pfx+'A2'],
1270            parmDict[pfx+'A3'],parmDict[pfx+'A4'],parmDict[pfx+'A5']]
1271    elif SGData['SGLaue'] in ['2/m',]:
1272        if SGData['SGUniq'] == 'a':
1273            A = [parmDict[pfx+'A0'],parmDict[pfx+'A1'],parmDict[pfx+'A2'],
1274                0,0,parmDict[pfx+'A5']]
1275        elif SGData['SGUniq'] == 'b':
1276            A = [parmDict[pfx+'A0'],parmDict[pfx+'A1'],parmDict[pfx+'A2'],
1277                0,parmDict[pfx+'A4'],0]
1278        else:
1279            A = [parmDict[pfx+'A0'],parmDict[pfx+'A1'],parmDict[pfx+'A2'],
1280                parmDict[pfx+'A3'],0,0]
1281    elif SGData['SGLaue'] in ['mmm',]:
1282        A = [parmDict[pfx+'A0'],parmDict[pfx+'A1'],parmDict[pfx+'A2'],0,0,0]
1283    elif SGData['SGLaue'] in ['4/m','4/mmm']:
1284        A = [parmDict[pfx+'A0'],parmDict[pfx+'A0'],parmDict[pfx+'A2'],0,0,0]
1285    elif SGData['SGLaue'] in ['6/m','6/mmm','3m1', '31m', '3']:
1286        A = [parmDict[pfx+'A0'],parmDict[pfx+'A0'],parmDict[pfx+'A2'],
1287            parmDict[pfx+'A0'],0,0]
1288    elif SGData['SGLaue'] in ['3R', '3mR']:
1289        A = [parmDict[pfx+'A0'],parmDict[pfx+'A0'],parmDict[pfx+'A0'],
1290            parmDict[pfx+'A3'],parmDict[pfx+'A3'],parmDict[pfx+'A3']]
1291    elif SGData['SGLaue'] in ['m3m','m3']:
1292        A = [parmDict[pfx+'A0'],parmDict[pfx+'A0'],parmDict[pfx+'A0'],0,0,0]
1293
1294    try:
1295        if SGData['SGLaue'] in ['-1',]:
1296            sigA = [sigDict[pfx+'A0'],sigDict[pfx+'A1'],sigDict[pfx+'A2'],
1297                sigDict[pfx+'A3'],sigDict[pfx+'A4'],sigDict[pfx+'A5']]
1298        elif SGData['SGLaue'] in ['2/m',]:
1299            if SGData['SGUniq'] == 'a':
1300                sigA = [sigDict[pfx+'A0'],sigDict[pfx+'A1'],sigDict[pfx+'A2'],
1301                    0,0,sigDict[pfx+'A5']]
1302            elif SGData['SGUniq'] == 'b':
1303                sigA = [sigDict[pfx+'A0'],sigDict[pfx+'A1'],sigDict[pfx+'A2'],
1304                    0,sigDict[pfx+'A4'],0]
1305            else:
1306                sigA = [sigDict[pfx+'A0'],sigDict[pfx+'A1'],sigDict[pfx+'A2'],
1307                    sigDict[pfx+'A3'],0,0]
1308        elif SGData['SGLaue'] in ['mmm',]:
1309            sigA = [sigDict[pfx+'A0'],sigDict[pfx+'A1'],sigDict[pfx+'A2'],0,0,0]
1310        elif SGData['SGLaue'] in ['4/m','4/mmm']:
1311            sigA = [sigDict[pfx+'A0'],0,sigDict[pfx+'A2'],0,0,0]
1312        elif SGData['SGLaue'] in ['6/m','6/mmm','3m1', '31m', '3']:
1313            sigA = [sigDict[pfx+'A0'],0,sigDict[pfx+'A2'],0,0,0]
1314        elif SGData['SGLaue'] in ['3R', '3mR']:
1315            sigA = [sigDict[pfx+'A0'],0,0,sigDict[pfx+'A3'],0,0]
1316        elif SGData['SGLaue'] in ['m3m','m3']:
1317            sigA = [sigDict[pfx+'A0'],0,0,0,0,0]
1318    except KeyError:
1319        sigA = [0,0,0,0,0,0]
1320    return A,sigA
1321       
1322def PrintRestraints(cell,SGData,AtPtrs,Atoms,AtLookup,textureData,phaseRest,pFile):
1323    'needs a doc string'
1324    if phaseRest:
1325        Amat = G2lat.cell2AB(cell)[0]
1326        cx,ct,cs = AtPtrs[:3]
1327        names = [['Bond','Bonds'],['Angle','Angles'],['Plane','Planes'],
1328            ['Chiral','Volumes'],['Torsion','Torsions'],['Rama','Ramas'],
1329            ['ChemComp','Sites'],['Texture','HKLs']]
1330        for name,rest in names:
1331            itemRest = phaseRest[name]
1332            if itemRest[rest] and itemRest['Use']:
1333                print >>pFile,'\n  %s %10.3f Use: %s'%(name+' restraint weight factor',itemRest['wtFactor'],str(itemRest['Use']))
1334                if name in ['Bond','Angle','Plane','Chiral']:
1335                    print >>pFile,'     calc       obs      sig   delt/sig  atoms(symOp): '
1336                    for indx,ops,obs,esd in itemRest[rest]:
1337                        try:
1338                            AtNames = G2mth.GetAtomItemsById(Atoms,AtLookup,indx,ct-1)
1339                            AtName = ''
1340                            for i,Aname in enumerate(AtNames):
1341                                AtName += Aname
1342                                if ops[i] == '1':
1343                                    AtName += '-'
1344                                else:
1345                                    AtName += '+('+ops[i]+')-'
1346                            XYZ = np.array(G2mth.GetAtomItemsById(Atoms,AtLookup,indx,cx,3))
1347                            XYZ = G2mth.getSyXYZ(XYZ,ops,SGData)
1348                            if name == 'Bond':
1349                                calc = G2mth.getRestDist(XYZ,Amat)
1350                            elif name == 'Angle':
1351                                calc = G2mth.getRestAngle(XYZ,Amat)
1352                            elif name == 'Plane':
1353                                calc = G2mth.getRestPlane(XYZ,Amat)
1354                            elif name == 'Chiral':
1355                                calc = G2mth.getRestChiral(XYZ,Amat)
1356                            print >>pFile,' %9.3f %9.3f %8.3f %8.3f   %s'%(calc,obs,esd,(obs-calc)/esd,AtName[:-1])
1357                        except KeyError:
1358                            del itemRest[rest]
1359                elif name in ['Torsion','Rama']:
1360                    print >>pFile,'  atoms(symOp)  calc  obs  sig  delt/sig  torsions: '
1361                    coeffDict = itemRest['Coeff']
1362                    for indx,ops,cofName,esd in itemRest[rest]:
1363                        AtNames = G2mth.GetAtomItemsById(Atoms,AtLookup,indx,ct-1)
1364                        AtName = ''
1365                        for i,Aname in enumerate(AtNames):
1366                            AtName += Aname+'+('+ops[i]+')-'
1367                        XYZ = np.array(G2mth.GetAtomItemsById(Atoms,AtLookup,indx,cx,3))
1368                        XYZ = G2mth.getSyXYZ(XYZ,ops,SGData)
1369                        if name == 'Torsion':
1370                            tor = G2mth.getRestTorsion(XYZ,Amat)
1371                            restr,calc = G2mth.calcTorsionEnergy(tor,coeffDict[cofName])
1372                            print >>pFile,' %8.3f %8.3f %.3f %8.3f %8.3f %s'%(calc,obs,esd,(obs-calc)/esd,tor,AtName[:-1])
1373                        else:
1374                            phi,psi = G2mth.getRestRama(XYZ,Amat)
1375                            restr,calc = G2mth.calcRamaEnergy(phi,psi,coeffDict[cofName])                               
1376                            print >>pFile,' %8.3f %8.3f %8.3f %8.3f %8.3f %8.3f %s'%(calc,obs,esd,(obs-calc)/esd,phi,psi,AtName[:-1])
1377                elif name == 'ChemComp':
1378                    print >>pFile,'     atoms   mul*frac  factor     prod'
1379                    for indx,factors,obs,esd in itemRest[rest]:
1380                        try:
1381                            atoms = G2mth.GetAtomItemsById(Atoms,AtLookup,indx,ct-1)
1382                            mul = np.array(G2mth.GetAtomItemsById(Atoms,AtLookup,indx,cs+1))
1383                            frac = np.array(G2mth.GetAtomItemsById(Atoms,AtLookup,indx,cs-1))
1384                            mulfrac = mul*frac
1385                            calcs = mul*frac*factors
1386                            for iatm,[atom,mf,fr,clc] in enumerate(zip(atoms,mulfrac,factors,calcs)):
1387                                print >>pFile,' %10s %8.3f %8.3f %8.3f'%(atom,mf,fr,clc)
1388                            print >>pFile,' Sum:                   calc: %8.3f obs: %8.3f esd: %8.3f'%(np.sum(calcs),obs,esd)
1389                        except KeyError:
1390                            del itemRest[rest]
1391                elif name == 'Texture' and textureData['Order']:
1392                    Start = False
1393                    SHCoef = textureData['SH Coeff'][1]
1394                    shModels = ['cylindrical','none','shear - 2/m','rolling - mmm']
1395                    SamSym = dict(zip(shModels,['0','-1','2/m','mmm']))
1396                    print '    HKL  grid  neg esd  sum neg  num neg use unit?  unit esd  '
1397                    for hkl,grid,esd1,ifesd2,esd2 in itemRest[rest]:
1398                        PH = np.array(hkl)
1399                        phi,beta = G2lat.CrsAng(np.array(hkl),cell,SGData)
1400                        ODFln = G2lat.Flnh(Start,SHCoef,phi,beta,SGData)
1401                        R,P,Z = G2mth.getRestPolefig(ODFln,SamSym[textureData['Model']],grid)
1402                        Z = ma.masked_greater(Z,0.0)
1403                        num = ma.count(Z)
1404                        sum = 0
1405                        if num:
1406                            sum = np.sum(Z)
1407                        print '   %d %d %d  %d %8.3f %8.3f %8d   %s    %8.3f'%(hkl[0],hkl[1],hkl[2],grid,esd1,sum,num,str(ifesd2),esd2)
1408       
1409def getCellEsd(pfx,SGData,A,covData):
1410    'needs a doc string'
1411    dpr = 180./np.pi
1412    rVsq = G2lat.calc_rVsq(A)
1413    G,g = G2lat.A2Gmat(A)       #get recip. & real metric tensors
1414    cell = np.array(G2lat.Gmat2cell(g))   #real cell
1415    cellst = np.array(G2lat.Gmat2cell(G)) #recip. cell
1416    scos = cosd(cellst[3:6])
1417    ssin = sind(cellst[3:6])
1418    scot = scos/ssin
1419    rcos = cosd(cell[3:6])
1420    rsin = sind(cell[3:6])
1421    rcot = rcos/rsin
1422    RMnames = [pfx+'A0',pfx+'A1',pfx+'A2',pfx+'A3',pfx+'A4',pfx+'A5']
1423    varyList = covData['varyList']
1424    covMatrix = covData['covMatrix']
1425    vcov = G2mth.getVCov(RMnames,varyList,covMatrix)
1426    Ax = np.array(A)
1427    Ax[3:] /= 2.
1428    drVdA = np.array([Ax[1]*Ax[2]-Ax[5]**2,Ax[0]*Ax[2]-Ax[4]**2,Ax[0]*Ax[1]-Ax[3]**2,
1429        Ax[4]*Ax[5]-Ax[2]*Ax[3],Ax[3]*Ax[5]-Ax[1]*Ax[4],Ax[3]*Ax[4]-Ax[0]*Ax[5]])
1430    srcvlsq = np.inner(drVdA,np.inner(vcov,drVdA.T))
1431    Vol = 1/np.sqrt(rVsq)
1432    sigVol = Vol**3*np.sqrt(srcvlsq)/2.
1433    R123 = Ax[0]*Ax[1]*Ax[2]
1434    dsasdg = np.zeros((3,6))
1435    dadg = np.zeros((6,6))
1436    for i0 in range(3):         #0  1   2
1437        i1 = (i0+1)%3           #1  2   0
1438        i2 = (i1+1)%3           #2  0   1
1439        i3 = 5-i2               #3  5   4
1440        i4 = 5-i1               #4  3   5
1441        i5 = 5-i0               #5  4   3
1442        dsasdg[i0][i1] = 0.5*scot[i0]*scos[i0]/Ax[i1]
1443        dsasdg[i0][i2] = 0.5*scot[i0]*scos[i0]/Ax[i2]
1444        dsasdg[i0][i5] = -scot[i0]/np.sqrt(Ax[i1]*Ax[i2])
1445        denmsq = Ax[i0]*(R123-Ax[i1]*Ax[i4]**2-Ax[i2]*Ax[i3]**2+(Ax[i4]*Ax[i3])**2)
1446        denom = np.sqrt(denmsq)
1447        dadg[i5][i0] = -Ax[i5]/denom-rcos[i0]/denmsq*(R123-0.5*Ax[i1]*Ax[i4]**2-0.5*Ax[i2]*Ax[i3]**2)
1448        dadg[i5][i1] = -0.5*rcos[i0]/denmsq*(Ax[i0]**2*Ax[i2]-Ax[i0]*Ax[i4]**2)
1449        dadg[i5][i2] = -0.5*rcos[i0]/denmsq*(Ax[i0]**2*Ax[i1]-Ax[i0]*Ax[i3]**2)
1450        dadg[i5][i3] = Ax[i4]/denom+rcos[i0]/denmsq*(Ax[i0]*Ax[i2]*Ax[i3]-Ax[i3]*Ax[i4]**2)
1451        dadg[i5][i4] = Ax[i3]/denom+rcos[i0]/denmsq*(Ax[i0]*Ax[i1]*Ax[i4]-Ax[i3]**2*Ax[i4])
1452        dadg[i5][i5] = -Ax[i0]/denom
1453    for i0 in range(3):
1454        i1 = (i0+1)%3
1455        i2 = (i1+1)%3
1456        i3 = 5-i2
1457        for ij in range(6):
1458            dadg[i0][ij] = cell[i0]*(rcot[i2]*dadg[i3][ij]/rsin[i2]-dsasdg[i1][ij]/ssin[i1])
1459            if ij == i0:
1460                dadg[i0][ij] = dadg[i0][ij]-0.5*cell[i0]/Ax[i0]
1461            dadg[i3][ij] = -dadg[i3][ij]*rsin[2-i0]*dpr
1462    sigMat = np.inner(dadg,np.inner(vcov,dadg.T))
1463    var = np.diag(sigMat)
1464    CS = np.where(var>0.,np.sqrt(var),0.)
1465    return [CS[0],CS[1],CS[2],CS[5],CS[4],CS[3],sigVol]
1466   
1467def SetPhaseData(parmDict,sigDict,Phases,RBIds,covData,RestraintDict=None,pFile=None):
1468    'needs a doc string'
1469   
1470    def PrintAtomsAndSig(General,Atoms,atomsSig):
1471        print >>pFile,'\n Atoms:'
1472        line = '   name      x         y         z      frac   Uiso     U11     U22     U33     U12     U13     U23'
1473        if General['Type'] == 'magnetic':
1474            line += '   Mx     My     Mz'
1475        elif General['Type'] == 'macromolecular':
1476            line = ' res no residue chain '+line
1477        cx,ct,cs,cia = General['AtomPtrs']
1478        print >>pFile,line
1479        print >>pFile,135*'-'
1480        fmt = {0:'%7s',ct:'%7s',cx:'%10.5f',cx+1:'%10.5f',cx+2:'%10.5f',cx+3:'%8.3f',cia+1:'%8.5f',
1481            cia+2:'%8.5f',cia+3:'%8.5f',cia+4:'%8.5f',cia+5:'%8.5f',cia+6:'%8.5f',cia+7:'%8.5f'}
1482        noFXsig = {cx:[10*' ','%10s'],cx+1:[10*' ','%10s'],cx+2:[10*' ','%10s'],cx+3:[8*' ','%8s']}
1483        for atyp in General['AtomTypes']:       #zero composition
1484            General['NoAtoms'][atyp] = 0.
1485        for i,at in enumerate(Atoms):
1486            General['NoAtoms'][at[ct]] += at[cx+3]*float(at[cx+5])     #new composition
1487            if General['Type'] == 'macromolecular':
1488                name = ' %s %s %s %s:'%(at[0],at[1],at[2],at[3])
1489                valstr = ' values:          '
1490                sigstr = ' sig   :          '
1491            else:
1492                name = fmt[0]%(at[ct-1])+fmt[1]%(at[ct])+':'
1493                valstr = ' values:'
1494                sigstr = ' sig   :'
1495            for ind in range(cx,cx+4):
1496                sigind = str(i)+':'+str(ind)
1497                valstr += fmt[ind]%(at[ind])                   
1498                if sigind in atomsSig:
1499                    sigstr += fmt[ind]%(atomsSig[sigind])
1500                else:
1501                    sigstr += noFXsig[ind][1]%(noFXsig[ind][0])
1502            if at[cia] == 'I':
1503                valstr += fmt[cia+1]%(at[cia+1])
1504                if '%d:%d'%(i,cia+1) in atomsSig:
1505                    sigstr += fmt[cia+1]%(atomsSig['%d:%d'%(i,cia+1)])
1506                else:
1507                    sigstr += 8*' '
1508            else:
1509                valstr += 8*' '
1510                sigstr += 8*' '
1511                for ind in range(cia+2,cia+8):
1512                    sigind = str(i)+':'+str(ind)
1513                    valstr += fmt[ind]%(at[ind])
1514                    if sigind in atomsSig:                       
1515                        sigstr += fmt[ind]%(atomsSig[sigind])
1516                    else:
1517                        sigstr += 8*' '
1518            print >>pFile,name
1519            print >>pFile,valstr
1520            print >>pFile,sigstr
1521           
1522    def PrintWavesAndSig(General,Atoms,wavesSig):
1523        cx,ct,cs,cia = General['AtomPtrs']
1524        print >>pFile,'\n Modulation waves'
1525        names = {'Sfrac':['Fsin','Fcos','Fzero','Fwid'],'Spos':['Xsin','Ysin','Zsin','Xcos','Ycos','Zcos','Tzero','Xslope','Yslope','Zslope'],
1526            'Sadp':['U11sin','U22sin','U33sin','U12sin','U13sin','U23sin','U11cos','U22cos',
1527            'U33cos','U12cos','U13cos','U23cos'],'Smag':['MXsin','MYsin','MZsin','MXcos','MYcos','MZcos']}
1528        print >>pFile,135*'-'
1529        for i,at in enumerate(Atoms):
1530            AtomSS = at[-1]['SS1']
1531            waveType = AtomSS['waveType']
1532            for Stype in ['Sfrac','Spos','Sadp','Smag']:
1533                Waves = AtomSS[Stype]
1534                if len(Waves):
1535                    print >>pFile,' atom: %s, site sym: %s, type: %s wave type: %s:'    \
1536                        %(at[ct-1],at[cs],Stype,waveType)
1537                    line = ''
1538                    for iw,wave in enumerate(Waves):
1539                        stiw = ':'+str(i)+':'+str(iw)
1540                        namstr = '  names :'
1541                        valstr = '  values:'
1542                        sigstr = '  esds  :'
1543                        if Stype == 'Spos':
1544                            nt = 6
1545                            ot = 0
1546                            if waveType in ['Sawtooth','ZigZag'] and not iw:
1547                                nt = 4
1548                                ot = 6
1549                            for j in range(nt):
1550                                name = names['Spos'][j+ot]
1551                                namstr += '%12s'%(name)
1552                                valstr += '%12.4f'%(wave[0][j])
1553                                if name+stiw in wavesSig:
1554                                    sigstr += '%12.4f'%(wavesSig[name+stiw])
1555                                else:
1556                                    sigstr += 12*' '
1557                        elif Stype == 'Sfrac':
1558                            ot = 0
1559                            if 'Crenel' in waveType and not iw:
1560                                ot = 2
1561                            for j in range(2):
1562                                name = names['Sfrac'][j+ot]
1563                                namstr += '%12s'%(names['Sfrac'][j+ot])
1564                                valstr += '%12.4f'%(wave[0][j])
1565                                if name+stiw in wavesSig:
1566                                    sigstr += '%12.4f'%(wavesSig[name+stiw])
1567                                else:
1568                                    sigstr += 12*' '
1569                        elif Stype == 'Sadp':
1570                            for j in range(12):
1571                                name = names['Sadp'][j]
1572                                namstr += '%10s'%(names['Sadp'][j])
1573                                valstr += '%10.6f'%(wave[0][j])
1574                                if name+stiw in wavesSig:
1575                                    sigstr += '%10.6f'%(wavesSig[name+stiw])
1576                                else:
1577                                    sigstr += 10*' '
1578                        elif Stype == 'Smag':
1579                            for j in range(6):
1580                                name = names['Smag'][j]
1581                                namstr += '%12s'%(names['Smag'][j])
1582                                valstr += '%12.4f'%(wave[0][j])
1583                                if name+stiw in wavesSig:
1584                                    sigstr += '%12.4f'%(wavesSig[name+stiw])
1585                                else:
1586                                    sigstr += 12*' '
1587                               
1588                    print >>pFile,namstr
1589                    print >>pFile,valstr
1590                    print >>pFile,sigstr
1591       
1592               
1593    def PrintRBObjPOAndSig(rbfx,rbsx):
1594        namstr = '  names :'
1595        valstr = '  values:'
1596        sigstr = '  esds  :'
1597        for i,px in enumerate(['Px:','Py:','Pz:']):
1598            name = pfx+rbfx+px+rbsx
1599            namstr += '%12s'%('Pos '+px[1])
1600            valstr += '%12.5f'%(parmDict[name])
1601            if name in sigDict:
1602                sigstr += '%12.5f'%(sigDict[name])
1603            else:
1604                sigstr += 12*' '
1605        for i,po in enumerate(['Oa:','Oi:','Oj:','Ok:']):
1606            name = pfx+rbfx+po+rbsx
1607            namstr += '%12s'%('Ori '+po[1])
1608            valstr += '%12.5f'%(parmDict[name])
1609            if name in sigDict:
1610                sigstr += '%12.5f'%(sigDict[name])
1611            else:
1612                sigstr += 12*' '
1613        print >>pFile,namstr
1614        print >>pFile,valstr
1615        print >>pFile,sigstr
1616       
1617    def PrintRBObjTLSAndSig(rbfx,rbsx,TLS):
1618        namstr = '  names :'
1619        valstr = '  values:'
1620        sigstr = '  esds  :'
1621        if 'N' not in TLS:
1622            print >>pFile,' Thermal motion:'
1623        if 'T' in TLS:
1624            for i,pt in enumerate(['T11:','T22:','T33:','T12:','T13:','T23:']):
1625                name = pfx+rbfx+pt+rbsx
1626                namstr += '%12s'%(pt[:3])
1627                valstr += '%12.5f'%(parmDict[name])
1628                if name in sigDict:
1629                    sigstr += '%12.5f'%(sigDict[name])
1630                else:
1631                    sigstr += 12*' '
1632            print >>pFile,namstr
1633            print >>pFile,valstr
1634            print >>pFile,sigstr
1635        if 'L' in TLS:
1636            namstr = '  names :'
1637            valstr = '  values:'
1638            sigstr = '  esds  :'
1639            for i,pt in enumerate(['L11:','L22:','L33:','L12:','L13:','L23:']):
1640                name = pfx+rbfx+pt+rbsx
1641                namstr += '%12s'%(pt[:3])
1642                valstr += '%12.3f'%(parmDict[name])
1643                if name in sigDict:
1644                    sigstr += '%12.3f'%(sigDict[name])
1645                else:
1646                    sigstr += 12*' '
1647            print >>pFile,namstr
1648            print >>pFile,valstr
1649            print >>pFile,sigstr
1650        if 'S' in TLS:
1651            namstr = '  names :'
1652            valstr = '  values:'
1653            sigstr = '  esds  :'
1654            for i,pt in enumerate(['S12:','S13:','S21:','S23:','S31:','S32:','SAA:','SBB:']):
1655                name = pfx+rbfx+pt+rbsx
1656                namstr += '%12s'%(pt[:3])
1657                valstr += '%12.4f'%(parmDict[name])
1658                if name in sigDict:
1659                    sigstr += '%12.4f'%(sigDict[name])
1660                else:
1661                    sigstr += 12*' '
1662            print >>pFile,namstr
1663            print >>pFile,valstr
1664            print >>pFile,sigstr
1665        if 'U' in TLS:
1666            name = pfx+rbfx+'U:'+rbsx
1667            namstr = '  names :'+'%12s'%('Uiso')
1668            valstr = '  values:'+'%12.5f'%(parmDict[name])
1669            if name in sigDict:
1670                sigstr = '  esds  :'+'%12.5f'%(sigDict[name])
1671            else:
1672                sigstr = '  esds  :'+12*' '
1673            print >>pFile,namstr
1674            print >>pFile,valstr
1675            print >>pFile,sigstr
1676       
1677    def PrintRBObjTorAndSig(rbsx):
1678        namstr = '  names :'
1679        valstr = '  values:'
1680        sigstr = '  esds  :'
1681        nTors = len(RBObj['Torsions'])
1682        if nTors:
1683            print >>pFile,' Torsions:'
1684            for it in range(nTors):
1685                name = pfx+'RBRTr;'+str(it)+':'+rbsx
1686                namstr += '%12s'%('Tor'+str(it))
1687                valstr += '%12.4f'%(parmDict[name])
1688                if name in sigDict:
1689                    sigstr += '%12.4f'%(sigDict[name])
1690            print >>pFile,namstr
1691            print >>pFile,valstr
1692            print >>pFile,sigstr
1693               
1694    def PrintSHtextureAndSig(textureData,SHtextureSig):
1695        print >>pFile,'\n Spherical harmonics texture: Order:' + str(textureData['Order'])
1696        names = ['omega','chi','phi']
1697        namstr = '  names :'
1698        ptstr =  '  values:'
1699        sigstr = '  esds  :'
1700        for name in names:
1701            namstr += '%12s'%(name)
1702            ptstr += '%12.3f'%(textureData['Sample '+name][1])
1703            if 'Sample '+name in SHtextureSig:
1704                sigstr += '%12.3f'%(SHtextureSig['Sample '+name])
1705            else:
1706                sigstr += 12*' '
1707        print >>pFile,namstr
1708        print >>pFile,ptstr
1709        print >>pFile,sigstr
1710        print >>pFile,'\n Texture coefficients:'
1711        SHcoeff = textureData['SH Coeff'][1]
1712        SHkeys = SHcoeff.keys()
1713        nCoeff = len(SHcoeff)
1714        nBlock = nCoeff/10+1
1715        iBeg = 0
1716        iFin = min(iBeg+10,nCoeff)
1717        for block in range(nBlock):
1718            namstr = '  names :'
1719            ptstr =  '  values:'
1720            sigstr = '  esds  :'
1721            for name in SHkeys[iBeg:iFin]:
1722                namstr += '%12s'%(name)
1723                ptstr += '%12.3f'%(SHcoeff[name])
1724                if name in SHtextureSig:
1725                    sigstr += '%12.3f'%(SHtextureSig[name])
1726                else:
1727                    sigstr += 12*' '
1728            print >>pFile,namstr
1729            print >>pFile,ptstr
1730            print >>pFile,sigstr
1731            iBeg += 10
1732            iFin = min(iBeg+10,nCoeff)
1733           
1734    print >>pFile,'\n Phases:'
1735    for phase in Phases:
1736        print >>pFile,' Result for phase: ',phase
1737        Phase = Phases[phase]
1738        General = Phase['General']
1739        SGData = General['SGData']
1740        Atoms = Phase['Atoms']
1741        if Atoms and not General.get('doPawley'):
1742            cx,ct,cs,cia = General['AtomPtrs']
1743            AtLookup = G2mth.FillAtomLookUp(Atoms,cia+8)
1744        cell = General['Cell']
1745        pId = Phase['pId']
1746        pfx = str(pId)+'::'
1747        if cell[0]:
1748            A,sigA = cellFill(pfx,SGData,parmDict,sigDict)
1749            cellSig = getCellEsd(pfx,SGData,A,covData)  #includes sigVol
1750            print >>pFile,' Reciprocal metric tensor: '
1751            ptfmt = "%15.9f"
1752            names = ['A11','A22','A33','A12','A13','A23']
1753            namstr = '  names :'
1754            ptstr =  '  values:'
1755            sigstr = '  esds  :'
1756            for name,a,siga in zip(names,A,sigA):
1757                namstr += '%15s'%(name)
1758                ptstr += ptfmt%(a)
1759                if siga:
1760                    sigstr += ptfmt%(siga)
1761                else:
1762                    sigstr += 15*' '
1763            print >>pFile,namstr
1764            print >>pFile,ptstr
1765            print >>pFile,sigstr
1766            cell[1:7] = G2lat.A2cell(A)
1767            cell[7] = G2lat.calc_V(A)
1768            print >>pFile,' New unit cell:'
1769            ptfmt = ["%12.6f","%12.6f","%12.6f","%12.4f","%12.4f","%12.4f","%12.3f"]
1770            names = ['a','b','c','alpha','beta','gamma','Volume']
1771            namstr = '  names :'
1772            ptstr =  '  values:'
1773            sigstr = '  esds  :'
1774            for name,fmt,a,siga in zip(names,ptfmt,cell[1:8],cellSig):
1775                namstr += '%12s'%(name)
1776                ptstr += fmt%(a)
1777                if siga:
1778                    sigstr += fmt%(siga)
1779                else:
1780                    sigstr += 12*' '
1781            print >>pFile,namstr
1782            print >>pFile,ptstr
1783            print >>pFile,sigstr
1784        ik = 6  #for Pawley stuff below
1785        if General['Type'] in ['modulated','magnetic']:
1786            ik = 7
1787            Vec,vRef,maxH = General['SuperVec']
1788            if vRef:
1789                print >>pFile,' New modulation vector:'
1790                namstr = '  names :'
1791                ptstr =  '  values:'
1792                sigstr = '  esds  :'
1793                for var in ['mV0','mV1','mV2']:
1794                    namstr += '%12s'%(pfx+var)
1795                    ptstr += '%12.6f'%(parmDict[pfx+var])
1796                    if pfx+var in sigDict:
1797                        sigstr += '%12.6f'%(sigDict[pfx+var])
1798                    else:
1799                        sigstr += 12*' '
1800                print >>pFile,namstr
1801                print >>pFile,ptstr
1802                print >>pFile,sigstr
1803           
1804        General['Mass'] = 0.
1805        if Phase['General'].get('doPawley'):
1806            pawleyRef = Phase['Pawley ref']
1807            for i,refl in enumerate(pawleyRef):
1808                key = pfx+'PWLref:'+str(i)
1809                refl[ik] = parmDict[key]
1810                if key in sigDict:
1811                    refl[ik+1] = sigDict[key]
1812                else:
1813                    refl[ik+1] = 0
1814        else:
1815            VRBIds = RBIds['Vector']
1816            RRBIds = RBIds['Residue']
1817            RBModels = Phase['RBModels']
1818            for irb,RBObj in enumerate(RBModels.get('Vector',[])):
1819                jrb = VRBIds.index(RBObj['RBId'])
1820                rbsx = str(irb)+':'+str(jrb)
1821                print >>pFile,' Vector rigid body parameters:'
1822                PrintRBObjPOAndSig('RBV',rbsx)
1823                PrintRBObjTLSAndSig('RBV',rbsx,RBObj['ThermalMotion'][0])
1824            for irb,RBObj in enumerate(RBModels.get('Residue',[])):
1825                jrb = RRBIds.index(RBObj['RBId'])
1826                rbsx = str(irb)+':'+str(jrb)
1827                print >>pFile,' Residue rigid body parameters:'
1828                PrintRBObjPOAndSig('RBR',rbsx)
1829                PrintRBObjTLSAndSig('RBR',rbsx,RBObj['ThermalMotion'][0])
1830                PrintRBObjTorAndSig(rbsx)
1831            atomsSig = {}
1832            wavesSig = {}
1833            cx,ct,cs,cia = General['AtomPtrs']
1834            for i,at in enumerate(Atoms):
1835                names = {cx:pfx+'Ax:'+str(i),cx+1:pfx+'Ay:'+str(i),cx+2:pfx+'Az:'+str(i),cx+3:pfx+'Afrac:'+str(i),
1836                    cia+1:pfx+'AUiso:'+str(i),cia+2:pfx+'AU11:'+str(i),cia+3:pfx+'AU22:'+str(i),cia+4:pfx+'AU33:'+str(i),
1837                    cia+5:pfx+'AU12:'+str(i),cia+6:pfx+'AU13:'+str(i),cia+7:pfx+'AU23:'+str(i)}
1838                for ind in range(cx,cx+4):
1839                    at[ind] = parmDict[names[ind]]
1840                    if ind in range(cx,cx+3):
1841                        name = names[ind].replace('A','dA')
1842                    else:
1843                        name = names[ind]
1844                    if name in sigDict:
1845                        atomsSig[str(i)+':'+str(ind)] = sigDict[name]
1846                if at[cia] == 'I':
1847                    at[cia+1] = parmDict[names[cia+1]]
1848                    if names[cia+1] in sigDict:
1849                        atomsSig['%d:%d'%(i,cia+1)] = sigDict[names[cia+1]]
1850                else:
1851                    for ind in range(cia+2,cia+8):
1852                        at[ind] = parmDict[names[ind]]
1853                        if names[ind] in sigDict:
1854                            atomsSig[str(i)+':'+str(ind)] = sigDict[names[ind]]
1855                ind = General['AtomTypes'].index(at[ct])
1856                General['Mass'] += General['AtomMass'][ind]*at[cx+3]*at[cx+5]
1857                if General['Type'] in ['modulated','magnetic']:
1858                    AtomSS = at[-1]['SS1']
1859                    waveType = AtomSS['waveType']
1860                    for Stype in ['Sfrac','Spos','Sadp','Smag']:
1861                        Waves = AtomSS[Stype]
1862                        for iw,wave in enumerate(Waves):
1863                            stiw = str(i)+':'+str(iw)
1864                            if Stype == 'Spos':
1865                                if waveType in ['ZigZag','Sawtooth'] and not iw:
1866                                    names = ['Tzero:'+stiw,'Xslope:'+stiw,'Yslope:'+stiw,'Zslope:'+stiw]
1867                                else:
1868                                    names = ['Xsin:'+stiw,'Ysin:'+stiw,'Zsin:'+stiw,
1869                                        'Xcos:'+stiw,'Ycos:'+stiw,'Zcos:'+stiw]
1870                            elif Stype == 'Sadp':
1871                                names = ['U11sin:'+stiw,'U22sin:'+stiw,'U33sin:'+stiw,
1872                                    'U12sin:'+stiw,'U13sin:'+stiw,'U23sin:'+stiw,
1873                                    'U11cos:'+stiw,'U22cos:'+stiw,'U33cos:'+stiw,
1874                                    'U12cos:'+stiw,'U13cos:'+stiw,'U23cos:'+stiw]
1875                            elif Stype == 'Sfrac':
1876                                if 'Crenel' in waveType and not iw:
1877                                    names = ['Fzero:'+stiw,'Fwid:'+stiw]
1878                                else:
1879                                    names = ['Fsin:'+stiw,'Fcos:'+stiw]
1880                            elif Stype == 'Smag':
1881                                names = ['MXsin:'+stiw,'MYsin:'+stiw,'MZsin:'+stiw,
1882                                    'MXcos:'+stiw,'MYcos:'+stiw,'MZcos:'+stiw]
1883                            for iname,name in enumerate(names):
1884                                AtomSS[Stype][iw][0][iname] = parmDict[pfx+name]
1885                                if pfx+name in sigDict:
1886                                    wavesSig[name] = sigDict[pfx+name]
1887                   
1888            PrintAtomsAndSig(General,Atoms,atomsSig)
1889            if General['Type'] in ['modulated','magnetic']:
1890                PrintWavesAndSig(General,Atoms,wavesSig)
1891           
1892       
1893        textureData = General['SH Texture']   
1894        if textureData['Order']:
1895            SHtextureSig = {}
1896            for name in ['omega','chi','phi']:
1897                aname = pfx+'SH '+name
1898                textureData['Sample '+name][1] = parmDict[aname]
1899                if aname in sigDict:
1900                    SHtextureSig['Sample '+name] = sigDict[aname]
1901            for name in textureData['SH Coeff'][1]:
1902                aname = pfx+name
1903                textureData['SH Coeff'][1][name] = parmDict[aname]
1904                if aname in sigDict:
1905                    SHtextureSig[name] = sigDict[aname]
1906            PrintSHtextureAndSig(textureData,SHtextureSig)
1907        if phase in RestraintDict and not Phase['General'].get('doPawley'):
1908            PrintRestraints(cell[1:7],SGData,General['AtomPtrs'],Atoms,AtLookup,
1909                textureData,RestraintDict[phase],pFile)
1910                   
1911################################################################################
1912##### Histogram & Phase data
1913################################################################################       
1914                   
1915def GetHistogramPhaseData(Phases,Histograms,Print=True,pFile=None,resetRefList=True):
1916    '''Loads the HAP histogram/phase information into dicts
1917
1918    :param dict Phases: phase information
1919    :param dict Histograms: Histogram information
1920    :param bool Print: prints information as it is read
1921    :param file pFile: file object to print to (the default, None causes printing to the console)
1922    :param bool resetRefList: Should the contents of the Reflection List be initialized
1923      on loading. The default, True, initializes the Reflection List as it is loaded.
1924
1925    :returns: (hapVary,hapDict,controlDict)
1926      * hapVary: list of refined variables
1927      * hapDict: dict with refined variables and their values
1928      * controlDict: dict with computation controls (?)
1929    '''
1930   
1931    def PrintSize(hapData):
1932        if hapData[0] in ['isotropic','uniaxial']:
1933            line = '\n Size model    : %9s'%(hapData[0])
1934            line += ' equatorial:'+'%12.5f'%(hapData[1][0])+' Refine? '+str(hapData[2][0])
1935            if hapData[0] == 'uniaxial':
1936                line += ' axial:'+'%12.5f'%(hapData[1][1])+' Refine? '+str(hapData[2][1])
1937            line += '\n\t LG mixing coeff.: %12.4f'%(hapData[1][2])+' Refine? '+str(hapData[2][2])
1938            print >>pFile,line
1939        else:
1940            print >>pFile,'\n Size model    : %s'%(hapData[0])+ \
1941                '\n\t LG mixing coeff.:%12.4f'%(hapData[1][2])+' Refine? '+str(hapData[2][2])
1942            Snames = ['S11','S22','S33','S12','S13','S23']
1943            ptlbls = ' names :'
1944            ptstr =  ' values:'
1945            varstr = ' refine:'
1946            for i,name in enumerate(Snames):
1947                ptlbls += '%12s' % (name)
1948                ptstr += '%12.6f' % (hapData[4][i])
1949                varstr += '%12s' % (str(hapData[5][i]))
1950            print >>pFile,ptlbls
1951            print >>pFile,ptstr
1952            print >>pFile,varstr
1953       
1954    def PrintMuStrain(hapData,SGData):
1955        if hapData[0] in ['isotropic','uniaxial']:
1956            line = '\n Mustrain model: %9s'%(hapData[0])
1957            line += ' equatorial:'+'%12.1f'%(hapData[1][0])+' Refine? '+str(hapData[2][0])
1958            if hapData[0] == 'uniaxial':
1959                line += ' axial:'+'%12.1f'%(hapData[1][1])+' Refine? '+str(hapData[2][1])
1960            line +='\n\t LG mixing coeff.:%12.4f'%(hapData[1][2])+' Refine? '+str(hapData[2][2])
1961            print >>pFile,line
1962        else:
1963            print >>pFile,'\n Mustrain model: %s'%(hapData[0])+ \
1964                '\n\t LG mixing coeff.:%12.4f'%(hapData[1][2])+' Refine? '+str(hapData[2][2])
1965            Snames = G2spc.MustrainNames(SGData)
1966            ptlbls = ' names :'
1967            ptstr =  ' values:'
1968            varstr = ' refine:'
1969            for i,name in enumerate(Snames):
1970                ptlbls += '%12s' % (name)
1971                ptstr += '%12.6f' % (hapData[4][i])
1972                varstr += '%12s' % (str(hapData[5][i]))
1973            print >>pFile,ptlbls
1974            print >>pFile,ptstr
1975            print >>pFile,varstr
1976
1977    def PrintHStrain(hapData,SGData):
1978        print >>pFile,'\n Hydrostatic/elastic strain: '
1979        Hsnames = G2spc.HStrainNames(SGData)
1980        ptlbls = ' names :'
1981        ptstr =  ' values:'
1982        varstr = ' refine:'
1983        for i,name in enumerate(Hsnames):
1984            ptlbls += '%12s' % (name)
1985            ptstr += '%12.4g' % (hapData[0][i])
1986            varstr += '%12s' % (str(hapData[1][i]))
1987        print >>pFile,ptlbls
1988        print >>pFile,ptstr
1989        print >>pFile,varstr
1990
1991    def PrintSHPO(hapData):
1992        print >>pFile,'\n Spherical harmonics preferred orientation: Order:' + \
1993            str(hapData[4])+' Refine? '+str(hapData[2])
1994        ptlbls = ' names :'
1995        ptstr =  ' values:'
1996        for item in hapData[5]:
1997            ptlbls += '%12s'%(item)
1998            ptstr += '%12.3f'%(hapData[5][item]) 
1999        print >>pFile,ptlbls
2000        print >>pFile,ptstr
2001   
2002    def PrintBabinet(hapData):
2003        print >>pFile,'\n Babinet form factor modification: '
2004        ptlbls = ' names :'
2005        ptstr =  ' values:'
2006        varstr = ' refine:'
2007        for name in ['BabA','BabU']:
2008            ptlbls += '%12s' % (name)
2009            ptstr += '%12.6f' % (hapData[name][0])
2010            varstr += '%12s' % (str(hapData[name][1]))
2011        print >>pFile,ptlbls
2012        print >>pFile,ptstr
2013        print >>pFile,varstr
2014       
2015   
2016    hapDict = {}
2017    hapVary = []
2018    controlDict = {}
2019    poType = {}
2020    poAxes = {}
2021    spAxes = {}
2022    spType = {}
2023   
2024    for phase in Phases:
2025        HistoPhase = Phases[phase]['Histograms']
2026        SGData = Phases[phase]['General']['SGData']
2027        cell = Phases[phase]['General']['Cell'][1:7]
2028        A = G2lat.cell2A(cell)
2029        if Phases[phase]['General']['Type'] in ['modulated','magnetic']:
2030            SSGData = Phases[phase]['General']['SSGData']
2031            Vec,x,maxH = Phases[phase]['General']['SuperVec']
2032        pId = Phases[phase]['pId']
2033        histoList = HistoPhase.keys()
2034        histoList.sort()
2035        for histogram in histoList:
2036            try:
2037                Histogram = Histograms[histogram]
2038            except KeyError:                       
2039                #skip if histogram not included e.g. in a sequential refinement
2040                continue
2041            hapData = HistoPhase[histogram]
2042            hId = Histogram['hId']
2043            if 'PWDR' in histogram:
2044                limits = Histogram['Limits'][1]
2045                inst = Histogram['Instrument Parameters'][0]
2046                Zero = inst['Zero'][0]
2047                if 'C' in inst['Type'][1]:
2048                    try:
2049                        wave = inst['Lam'][1]
2050                    except KeyError:
2051                        wave = inst['Lam1'][1]
2052                    dmin = wave/(2.0*sind(limits[1]/2.0))
2053                elif 'T' in inst['Type'][0]:
2054                    dmin = limits[0]/inst['difC'][1]
2055                pfx = str(pId)+':'+str(hId)+':'
2056                for item in ['Scale','Extinction']:
2057                    hapDict[pfx+item] = hapData[item][0]
2058                    if hapData[item][1]:
2059                        hapVary.append(pfx+item)
2060                names = G2spc.HStrainNames(SGData)
2061                HSvals = []
2062                for i,name in enumerate(names):
2063                    hapDict[pfx+name] = hapData['HStrain'][0][i]
2064                    HSvals.append(hapDict[pfx+name])
2065                    if hapData['HStrain'][1][i]:
2066                        hapVary.append(pfx+name)
2067                DIJS = G2spc.HStrainVals(HSvals,SGData)
2068                controlDict[pfx+'poType'] = hapData['Pref.Ori.'][0]
2069                if hapData['Pref.Ori.'][0] == 'MD':
2070                    hapDict[pfx+'MD'] = hapData['Pref.Ori.'][1]
2071                    controlDict[pfx+'MDAxis'] = hapData['Pref.Ori.'][3]
2072                    if hapData['Pref.Ori.'][2]:
2073                        hapVary.append(pfx+'MD')
2074                else:                           #'SH' spherical harmonics
2075                    controlDict[pfx+'SHord'] = hapData['Pref.Ori.'][4]
2076                    controlDict[pfx+'SHncof'] = len(hapData['Pref.Ori.'][5])
2077                    controlDict[pfx+'SHnames'] = G2lat.GenSHCoeff(SGData['SGLaue'],'0',controlDict[pfx+'SHord'],False)
2078                    controlDict[pfx+'SHhkl'] = []
2079                    try: #patch for old Pref.Ori. items
2080                        controlDict[pfx+'SHtoler'] = 0.1
2081                        if hapData['Pref.Ori.'][6][0] != '':
2082                            controlDict[pfx+'SHhkl'] = [eval(a.replace(' ',',')) for a in hapData['Pref.Ori.'][6]]
2083                        controlDict[pfx+'SHtoler'] = hapData['Pref.Ori.'][7]
2084                    except IndexError:
2085                        pass
2086                    for item in hapData['Pref.Ori.'][5]:
2087                        hapDict[pfx+item] = hapData['Pref.Ori.'][5][item]
2088                        if hapData['Pref.Ori.'][2]:
2089                            hapVary.append(pfx+item)
2090                for item in ['Mustrain','Size']:
2091                    controlDict[pfx+item+'Type'] = hapData[item][0]
2092                    hapDict[pfx+item+';mx'] = hapData[item][1][2]
2093                    if hapData[item][2][2]:
2094                        hapVary.append(pfx+item+';mx')
2095                    if hapData[item][0] in ['isotropic','uniaxial']:
2096                        hapDict[pfx+item+';i'] = hapData[item][1][0]
2097                        if hapData[item][2][0]:
2098                            hapVary.append(pfx+item+';i')
2099                        if hapData[item][0] == 'uniaxial':
2100                            controlDict[pfx+item+'Axis'] = hapData[item][3]
2101                            hapDict[pfx+item+';a'] = hapData[item][1][1]
2102                            if hapData[item][2][1]:
2103                                hapVary.append(pfx+item+';a')
2104                    else:       #generalized for mustrain or ellipsoidal for size
2105                        Nterms = len(hapData[item][4])
2106                        if item == 'Mustrain':
2107                            names = G2spc.MustrainNames(SGData)
2108                            pwrs = []
2109                            for name in names:
2110                                h,k,l = name[1:]
2111                                pwrs.append([int(h),int(k),int(l)])
2112                            controlDict[pfx+'MuPwrs'] = pwrs
2113                        for i in range(Nterms):
2114                            sfx = ':'+str(i)
2115                            hapDict[pfx+item+sfx] = hapData[item][4][i]
2116                            if hapData[item][5][i]:
2117                                hapVary.append(pfx+item+sfx)
2118                for bab in ['BabA','BabU']:
2119                    hapDict[pfx+bab] = hapData['Babinet'][bab][0]
2120                    if hapData['Babinet'][bab][1]:
2121                        hapVary.append(pfx+bab)
2122                               
2123                if Print: 
2124                    print >>pFile,'\n Phase: ',phase,' in histogram: ',histogram
2125                    print >>pFile,135*'-'
2126                    print >>pFile,' Phase fraction  : %10.4f'%(hapData['Scale'][0]),' Refine?',hapData['Scale'][1]
2127                    print >>pFile,' Extinction coeff: %10.4f'%(hapData['Extinction'][0]),' Refine?',hapData['Extinction'][1]
2128                    if hapData['Pref.Ori.'][0] == 'MD':
2129                        Ax = hapData['Pref.Ori.'][3]
2130                        print >>pFile,' March-Dollase PO: %10.4f'%(hapData['Pref.Ori.'][1]),' Refine?',hapData['Pref.Ori.'][2], \
2131                            ' Axis: %d %d %d'%(Ax[0],Ax[1],Ax[2])
2132                    else: #'SH' for spherical harmonics
2133                        PrintSHPO(hapData['Pref.Ori.'])
2134                        print >>pFile,' Penalty hkl list: '+str(controlDict[pfx+'SHhkl'])+' tolerance: %.2f'%(controlDict[pfx+'SHtoler'])
2135                    PrintSize(hapData['Size'])
2136                    PrintMuStrain(hapData['Mustrain'],SGData)
2137                    PrintHStrain(hapData['HStrain'],SGData)
2138                    if hapData['Babinet']['BabA'][0]:
2139                        PrintBabinet(hapData['Babinet'])                       
2140                if resetRefList:
2141                    refList = []
2142                    Uniq = []
2143                    Phi = []
2144                    if Phases[phase]['General']['Type'] in ['modulated','magnetic']:
2145                        ifSuper = True
2146                        HKLd = np.array(G2lat.GenSSHLaue(dmin,SGData,SSGData,Vec,maxH,A))
2147                        HKLd = G2mth.sortArray(HKLd,4,reverse=True)
2148                        for h,k,l,m,d in HKLd:
2149                            ext,mul,uniq,phi = G2spc.GenHKLf([h,k,l],SGData)    #is this right for SS refl.??
2150                            mul *= 2      # for powder overlap of Friedel pairs
2151                            if m or not ext:
2152                                if 'C' in inst['Type'][0]:
2153                                    pos = G2lat.Dsp2pos(inst,d)
2154                                    if limits[0] < pos < limits[1]:
2155                                        refList.append([h,k,l,m,mul,d, pos,0.0,0.0,0.0,0.0, 0.0,0.0,1.0,1.0,1.0])
2156                                        #... sig,gam,fotsq,fctsq, phase,icorr,prfo,abs,ext
2157                                        Uniq.append(uniq)
2158                                        Phi.append(phi)
2159                                elif 'T' in inst['Type'][0]:
2160                                    pos = G2lat.Dsp2pos(inst,d)
2161                                    if limits[0] < pos < limits[1]:
2162                                        wave = inst['difC'][1]*d/(252.816*inst['fltPath'][0])
2163                                        refList.append([h,k,l,m,mul,d, pos,0.0,0.0,0.0,0.0, 0.0,0.0,0.0,0.0,wave, 1.0,1.0,1.0])
2164                                        # ... sig,gam,fotsq,fctsq, phase,icorr,alp,bet,wave, prfo,abs,ext
2165                                        Uniq.append(uniq)
2166                                        Phi.append(phi)
2167                    else:
2168                        ifSuper = False
2169                        HKLd = np.array(G2lat.GenHLaue(dmin,SGData,A))
2170                        HKLd = G2mth.sortArray(HKLd,3,reverse=True)
2171                        for h,k,l,d in HKLd:
2172                            ext,mul,uniq,phi = G2spc.GenHKLf([h,k,l],SGData)
2173                            mul *= 2      # for powder overlap of Friedel pairs
2174                            if ext:
2175                                continue
2176                            if 'C' in inst['Type'][0]:
2177                                pos = G2lat.Dsp2pos(inst,d)
2178                                if limits[0] < pos < limits[1]:
2179                                    refList.append([h,k,l,mul,d, pos,0.0,0.0,0.0,0.0, 0.0,0.0,1.0,1.0,1.0])
2180                                    #... sig,gam,fotsq,fctsq, phase,icorr,prfo,abs,ext
2181                                    Uniq.append(uniq)
2182                                    Phi.append(phi)
2183                            elif 'T' in inst['Type'][0]:
2184                                pos = G2lat.Dsp2pos(inst,d)
2185                                if limits[0] < pos < limits[1]:
2186                                    wave = inst['difC'][1]*d/(252.816*inst['fltPath'][0])
2187                                    refList.append([h,k,l,mul,d, pos,0.0,0.0,0.0,0.0, 0.0,0.0,0.0,0.0,wave, 1.0,1.0,1.0])
2188                                    # ... sig,gam,fotsq,fctsq, phase,icorr,alp,bet,wave, prfo,abs,ext
2189                                    Uniq.append(uniq)
2190                                    Phi.append(phi)
2191                    Histogram['Reflection Lists'][phase] = {'RefList':np.array(refList),'FF':{},'Type':inst['Type'][0],'Super':ifSuper}
2192            elif 'HKLF' in histogram:
2193                inst = Histogram['Instrument Parameters'][0]
2194                hId = Histogram['hId']
2195                hfx = ':%d:'%(hId)
2196                for item in inst:
2197                    if type(inst) is not list and item != 'Type': continue # skip over non-refined items (such as InstName)
2198                    hapDict[hfx+item] = inst[item][1]
2199                pfx = str(pId)+':'+str(hId)+':'
2200                hapDict[pfx+'Scale'] = hapData['Scale'][0]
2201                if hapData['Scale'][1]:
2202                    hapVary.append(pfx+'Scale')
2203                               
2204                extApprox,extType,extParms = hapData['Extinction']
2205                controlDict[pfx+'EType'] = extType
2206                controlDict[pfx+'EApprox'] = extApprox
2207                if 'C' in inst['Type'][0]:
2208                    controlDict[pfx+'Tbar'] = extParms['Tbar']
2209                    controlDict[pfx+'Cos2TM'] = extParms['Cos2TM']
2210                if 'Primary' in extType:
2211                    Ekey = ['Ep',]
2212                elif 'I & II' in extType:
2213                    Ekey = ['Eg','Es']
2214                elif 'Secondary Type II' == extType:
2215                    Ekey = ['Es',]
2216                elif 'Secondary Type I' == extType:
2217                    Ekey = ['Eg',]
2218                else:   #'None'
2219                    Ekey = []
2220                for eKey in Ekey:
2221                    hapDict[pfx+eKey] = extParms[eKey][0]
2222                    if extParms[eKey][1]:
2223                        hapVary.append(pfx+eKey)
2224                for bab in ['BabA','BabU']:
2225                    hapDict[pfx+bab] = hapData['Babinet'][bab][0]
2226                    if hapData['Babinet'][bab][1]:
2227                        hapVary.append(pfx+bab)
2228                if Print: 
2229                    print >>pFile,'\n Phase: ',phase,' in histogram: ',histogram
2230                    print >>pFile,135*'-'
2231                    print >>pFile,' Scale factor     : %10.4f'%(hapData['Scale'][0]),' Refine?',hapData['Scale'][1]
2232                    if extType != 'None':
2233                        print >>pFile,' Extinction  Type: %15s'%(extType),' approx: %10s'%(extApprox)
2234                        text = ' Parameters       :'
2235                        for eKey in Ekey:
2236                            text += ' %4s : %10.3e Refine? '%(eKey,extParms[eKey][0])+str(extParms[eKey][1])
2237                        print >>pFile,text
2238                    if hapData['Babinet']['BabA'][0]:
2239                        PrintBabinet(hapData['Babinet'])
2240                Histogram['Reflection Lists'] = phase       
2241               
2242    return hapVary,hapDict,controlDict
2243   
2244def SetHistogramPhaseData(parmDict,sigDict,Phases,Histograms,Print=True,pFile=None):
2245    'needs a doc string'
2246   
2247    def PrintSizeAndSig(hapData,sizeSig):
2248        line = '\n Size model:     %9s'%(hapData[0])
2249        refine = False
2250        if hapData[0] in ['isotropic','uniaxial']:
2251            line += ' equatorial:%12.5f'%(hapData[1][0])
2252            if sizeSig[0][0]:
2253                line += ', sig:%8.4f'%(sizeSig[0][0])
2254                refine = True
2255            if hapData[0] == 'uniaxial':
2256                line += ' axial:%12.4f'%(hapData[1][1])
2257                if sizeSig[0][1]:
2258                    refine = True
2259                    line += ', sig:%8.4f'%(sizeSig[0][1])
2260            line += ' LG mix coeff.:%12.4f'%(hapData[1][2])
2261            if sizeSig[0][2]:
2262                refine = True
2263                line += ', sig:%8.4f'%(sizeSig[0][2])
2264            if refine:
2265                print >>pFile,line
2266        else:
2267            line += ' LG mix coeff.:%12.4f'%(hapData[1][2])
2268            if sizeSig[0][2]:
2269                refine = True
2270                line += ', sig:%8.4f'%(sizeSig[0][2])
2271            Snames = ['S11','S22','S33','S12','S13','S23']
2272            ptlbls = ' name  :'
2273            ptstr =  ' value :'
2274            sigstr = ' sig   :'
2275            for i,name in enumerate(Snames):
2276                ptlbls += '%12s' % (name)
2277                ptstr += '%12.6f' % (hapData[4][i])
2278                if sizeSig[1][i]:
2279                    refine = True
2280                    sigstr += '%12.6f' % (sizeSig[1][i])
2281                else:
2282                    sigstr += 12*' '
2283            if refine:
2284                print >>pFile,line
2285                print >>pFile,ptlbls
2286                print >>pFile,ptstr
2287                print >>pFile,sigstr
2288       
2289    def PrintMuStrainAndSig(hapData,mustrainSig,SGData):
2290        line = '\n Mustrain model: %9s'%(hapData[0])
2291        refine = False
2292        if hapData[0] in ['isotropic','uniaxial']:
2293            line += ' equatorial:%12.1f'%(hapData[1][0])
2294            if mustrainSig[0][0]:
2295                line += ', sig:%8.1f'%(mustrainSig[0][0])
2296                refine = True
2297            if hapData[0] == 'uniaxial':
2298                line += ' axial:%12.1f'%(hapData[1][1])
2299                if mustrainSig[0][1]:
2300                     line += ', sig:%8.1f'%(mustrainSig[0][1])
2301            line += ' LG mix coeff.:%12.4f'%(hapData[1][2])
2302            if mustrainSig[0][2]:
2303                refine = True
2304                line += ', sig:%8.3f'%(mustrainSig[0][2])
2305            if refine:
2306                print >>pFile,line
2307        else:
2308            line += ' LG mix coeff.:%12.4f'%(hapData[1][2])
2309            if mustrainSig[0][2]:
2310                refine = True
2311                line += ', sig:%8.3f'%(mustrainSig[0][2])
2312            Snames = G2spc.MustrainNames(SGData)
2313            ptlbls = ' name  :'
2314            ptstr =  ' value :'
2315            sigstr = ' sig   :'
2316            for i,name in enumerate(Snames):
2317                ptlbls += '%12s' % (name)
2318                ptstr += '%12.6f' % (hapData[4][i])
2319                if mustrainSig[1][i]:
2320                    refine = True
2321                    sigstr += '%12.6f' % (mustrainSig[1][i])
2322                else:
2323                    sigstr += 12*' '
2324            if refine:
2325                print >>pFile,line
2326                print >>pFile,ptlbls
2327                print >>pFile,ptstr
2328                print >>pFile,sigstr
2329           
2330    def PrintHStrainAndSig(hapData,strainSig,SGData):
2331        Hsnames = G2spc.HStrainNames(SGData)
2332        ptlbls = ' name  :'
2333        ptstr =  ' value :'
2334        sigstr = ' sig   :'
2335        refine = False
2336        for i,name in enumerate(Hsnames):
2337            ptlbls += '%12s' % (name)
2338            ptstr += '%12.4g' % (hapData[0][i])
2339            if name in strainSig:
2340                refine = True
2341                sigstr += '%12.4g' % (strainSig[name])
2342            else:
2343                sigstr += 12*' '
2344        if refine:
2345            print >>pFile,'\n Hydrostatic/elastic strain: '
2346            print >>pFile,ptlbls
2347            print >>pFile,ptstr
2348            print >>pFile,sigstr
2349       
2350    def PrintSHPOAndSig(pfx,hapData,POsig):
2351        print >>pFile,'\n Spherical harmonics preferred orientation: Order:'+str(hapData[4])
2352        ptlbls = ' names :'
2353        ptstr =  ' values:'
2354        sigstr = ' sig   :'
2355        for item in hapData[5]:
2356            ptlbls += '%12s'%(item)
2357            ptstr += '%12.3f'%(hapData[5][item])
2358            if pfx+item in POsig:
2359                sigstr += '%12.3f'%(POsig[pfx+item])
2360            else:
2361                sigstr += 12*' ' 
2362        print >>pFile,ptlbls
2363        print >>pFile,ptstr
2364        print >>pFile,sigstr
2365       
2366    def PrintExtAndSig(pfx,hapData,ScalExtSig):
2367        print >>pFile,'\n Single crystal extinction: Type: ',hapData[0],' Approx: ',hapData[1]
2368        text = ''
2369        for item in hapData[2]:
2370            if pfx+item in ScalExtSig:
2371                text += '       %s: '%(item)
2372                text += '%12.2e'%(hapData[2][item][0])
2373                if pfx+item in ScalExtSig:
2374                    text += ' sig: %12.2e'%(ScalExtSig[pfx+item])
2375        print >>pFile,text       
2376       
2377    def PrintBabinetAndSig(pfx,hapData,BabSig):
2378        print >>pFile,'\n Babinet form factor modification: '
2379        ptlbls = ' names :'
2380        ptstr =  ' values:'
2381        sigstr = ' sig   :'
2382        for item in hapData:
2383            ptlbls += '%12s'%(item)
2384            ptstr += '%12.3f'%(hapData[item][0])
2385            if pfx+item in BabSig:
2386                sigstr += '%12.3f'%(BabSig[pfx+item])
2387            else:
2388                sigstr += 12*' ' 
2389        print >>pFile,ptlbls
2390        print >>pFile,ptstr
2391        print >>pFile,sigstr
2392   
2393    PhFrExtPOSig = {}
2394    SizeMuStrSig = {}
2395    ScalExtSig = {}
2396    BabSig = {}
2397    wtFrSum = {}
2398    for phase in Phases:
2399        HistoPhase = Phases[phase]['Histograms']
2400        General = Phases[phase]['General']
2401        SGData = General['SGData']
2402        pId = Phases[phase]['pId']
2403        histoList = HistoPhase.keys()
2404        histoList.sort()
2405        for histogram in histoList:
2406            try:
2407                Histogram = Histograms[histogram]
2408            except KeyError:                       
2409                #skip if histogram not included e.g. in a sequential refinement
2410                continue
2411            hapData = HistoPhase[histogram]
2412            hId = Histogram['hId']
2413            pfx = str(pId)+':'+str(hId)+':'
2414            if hId not in wtFrSum:
2415                wtFrSum[hId] = 0.
2416            if 'PWDR' in histogram:
2417                for item in ['Scale','Extinction']:
2418                    hapData[item][0] = parmDict[pfx+item]
2419                    if pfx+item in sigDict:
2420                        PhFrExtPOSig.update({pfx+item:sigDict[pfx+item],})
2421                wtFrSum[hId] += hapData['Scale'][0]*General['Mass']
2422                if hapData['Pref.Ori.'][0] == 'MD':
2423                    hapData['Pref.Ori.'][1] = parmDict[pfx+'MD']
2424                    if pfx+'MD' in sigDict:
2425                        PhFrExtPOSig.update({pfx+'MD':sigDict[pfx+'MD'],})
2426                else:                           #'SH' spherical harmonics
2427                    for item in hapData['Pref.Ori.'][5]:
2428                        hapData['Pref.Ori.'][5][item] = parmDict[pfx+item]
2429                        if pfx+item in sigDict:
2430                            PhFrExtPOSig.update({pfx+item:sigDict[pfx+item],})
2431                SizeMuStrSig.update({pfx+'Mustrain':[[0,0,0],[0 for i in range(len(hapData['Mustrain'][4]))]],
2432                    pfx+'Size':[[0,0,0],[0 for i in range(len(hapData['Size'][4]))]],
2433                    pfx+'HStrain':{}})                 
2434                for item in ['Mustrain','Size']:
2435                    hapData[item][1][2] = parmDict[pfx+item+';mx']
2436                    hapData[item][1][2] = min(1.,max(0.,hapData[item][1][2]))
2437                    if pfx+item+';mx' in sigDict:
2438                        SizeMuStrSig[pfx+item][0][2] = sigDict[pfx+item+';mx']
2439                    if hapData[item][0] in ['isotropic','uniaxial']:                   
2440                        hapData[item][1][0] = parmDict[pfx+item+';i']
2441                        if item == 'Size':
2442                            hapData[item][1][0] = min(10.,max(0.001,hapData[item][1][0]))
2443                        if pfx+item+';i' in sigDict: 
2444                            SizeMuStrSig[pfx+item][0][0] = sigDict[pfx+item+';i']
2445                        if hapData[item][0] == 'uniaxial':
2446                            hapData[item][1][1] = parmDict[pfx+item+';a']
2447                            if item == 'Size':
2448                                hapData[item][1][1] = min(10.,max(0.001,hapData[item][1][1]))                       
2449                            if pfx+item+';a' in sigDict:
2450                                SizeMuStrSig[pfx+item][0][1] = sigDict[pfx+item+';a']
2451                    else:       #generalized for mustrain or ellipsoidal for size
2452                        Nterms = len(hapData[item][4])
2453                        for i in range(Nterms):
2454                            sfx = ':'+str(i)
2455                            hapData[item][4][i] = parmDict[pfx+item+sfx]
2456                            if pfx+item+sfx in sigDict:
2457                                SizeMuStrSig[pfx+item][1][i] = sigDict[pfx+item+sfx]
2458                names = G2spc.HStrainNames(SGData)
2459                for i,name in enumerate(names):
2460                    hapData['HStrain'][0][i] = parmDict[pfx+name]
2461                    if pfx+name in sigDict:
2462                        SizeMuStrSig[pfx+'HStrain'][name] = sigDict[pfx+name]
2463                for name in ['BabA','BabU']:
2464                    hapData['Babinet'][name][0] = parmDict[pfx+name]
2465                    if pfx+name in sigDict:
2466                        BabSig[pfx+name] = sigDict[pfx+name]               
2467               
2468            elif 'HKLF' in histogram:
2469                for item in ['Scale',]:
2470                    if parmDict.get(pfx+item):
2471                        hapData[item][0] = parmDict[pfx+item]
2472                        if pfx+item in sigDict:
2473                            ScalExtSig[pfx+item] = sigDict[pfx+item]
2474                for item in ['Ep','Eg','Es']:
2475                    if parmDict.get(pfx+item):
2476                        hapData['Extinction'][2][item][0] = parmDict[pfx+item]
2477                        if pfx+item in sigDict:
2478                            ScalExtSig[pfx+item] = sigDict[pfx+item]
2479                for name in ['BabA','BabU']:
2480                    hapData['Babinet'][name][0] = parmDict[pfx+name]
2481                    if pfx+name in sigDict:
2482                        BabSig[pfx+name] = sigDict[pfx+name]               
2483
2484    if Print:
2485        for phase in Phases:
2486            HistoPhase = Phases[phase]['Histograms']
2487            General = Phases[phase]['General']
2488            SGData = General['SGData']
2489            pId = Phases[phase]['pId']
2490            histoList = HistoPhase.keys()
2491            histoList.sort()
2492            for histogram in histoList:
2493                try:
2494                    Histogram = Histograms[histogram]
2495                except KeyError:                       
2496                    #skip if histogram not included e.g. in a sequential refinement
2497                    continue
2498                print >>pFile,'\n Phase: ',phase,' in histogram: ',histogram
2499                print >>pFile,130*'-'
2500                hapData = HistoPhase[histogram]
2501                hId = Histogram['hId']
2502                Histogram['Residuals'][str(pId)+'::Name'] = phase
2503                pfx = str(pId)+':'+str(hId)+':'
2504                if 'PWDR' in histogram:
2505                    print >>pFile,' Final refinement RF, RF^2 = %.2f%%, %.2f%% on %d reflections'   \
2506                        %(Histogram['Residuals'][pfx+'Rf'],Histogram['Residuals'][pfx+'Rf^2'],Histogram['Residuals'][pfx+'Nref'])
2507                    print >>pFile,' Bragg intensity sum = %.3g'%(Histogram['Residuals'][pfx+'sumInt'])
2508               
2509                    if pfx+'Scale' in PhFrExtPOSig:
2510                        wtFr = hapData['Scale'][0]*General['Mass']/wtFrSum[hId]
2511                        sigwtFr = PhFrExtPOSig[pfx+'Scale']*wtFr/hapData['Scale'][0]
2512                        print >>pFile,' Phase fraction  : %10.5f, sig %10.5f Weight fraction  : %8.5f, sig %10.5f' \
2513                            %(hapData['Scale'][0],PhFrExtPOSig[pfx+'Scale'],wtFr,sigwtFr)
2514                    if pfx+'Extinction' in PhFrExtPOSig:
2515                        print >>pFile,' Extinction coeff: %10.4f, sig %10.4f'%(hapData['Extinction'][0],PhFrExtPOSig[pfx+'Extinction'])
2516                    if hapData['Pref.Ori.'][0] == 'MD':
2517                        if pfx+'MD' in PhFrExtPOSig:
2518                            print >>pFile,' March-Dollase PO: %10.4f, sig %10.4f'%(hapData['Pref.Ori.'][1],PhFrExtPOSig[pfx+'MD'])
2519                    else:
2520                        PrintSHPOAndSig(pfx,hapData['Pref.Ori.'],PhFrExtPOSig)
2521                    PrintSizeAndSig(hapData['Size'],SizeMuStrSig[pfx+'Size'])
2522                    PrintMuStrainAndSig(hapData['Mustrain'],SizeMuStrSig[pfx+'Mustrain'],SGData)
2523                    PrintHStrainAndSig(hapData['HStrain'],SizeMuStrSig[pfx+'HStrain'],SGData)
2524                    if len(BabSig):
2525                        PrintBabinetAndSig(pfx,hapData['Babinet'],BabSig)
2526                   
2527                elif 'HKLF' in histogram:
2528                    print >>pFile,' Final refinement RF, RF^2 = %.2f%%, %.2f%% on %d reflections (%d user rejected, %d sp.gp.extinct)'   \
2529                        %(Histogram['Residuals'][pfx+'Rf'],Histogram['Residuals'][pfx+'Rf^2'],Histogram['Residuals'][pfx+'Nref'],
2530                        Histogram['Residuals'][pfx+'Nrej'],Histogram['Residuals'][pfx+'Next'])
2531                    print >>pFile,' HKLF histogram weight factor = ','%.3f'%(Histogram['wtFactor'])
2532                    if pfx+'Scale' in ScalExtSig:
2533                        print >>pFile,' Scale factor : %10.4f, sig %10.4f'%(hapData['Scale'][0],ScalExtSig[pfx+'Scale'])
2534                    if hapData['Extinction'][0] != 'None':
2535                        PrintExtAndSig(pfx,hapData['Extinction'],ScalExtSig)
2536                    if len(BabSig):
2537                        PrintBabinetAndSig(pfx,hapData['Babinet'],BabSig)
2538
2539################################################################################
2540##### Histogram data
2541################################################################################       
2542                   
2543def GetHistogramData(Histograms,Print=True,pFile=None):
2544    'needs a doc string'
2545   
2546    def GetBackgroundParms(hId,Background):
2547        Back = Background[0]
2548        DebyePeaks = Background[1]
2549        bakType,bakFlag = Back[:2]
2550        backVals = Back[3:]
2551        backNames = [':'+str(hId)+':Back;'+str(i) for i in range(len(backVals))]
2552        backDict = dict(zip(backNames,backVals))
2553        backVary = []
2554        if bakFlag:
2555            backVary = backNames
2556        backDict[':'+str(hId)+':nDebye'] = DebyePeaks['nDebye']
2557        backDict[':'+str(hId)+':nPeaks'] = DebyePeaks['nPeaks']
2558        debyeDict = {}
2559        debyeList = []
2560        for i in range(DebyePeaks['nDebye']):
2561            debyeNames = [':'+str(hId)+':DebyeA;'+str(i),':'+str(hId)+':DebyeR;'+str(i),':'+str(hId)+':DebyeU;'+str(i)]
2562            debyeDict.update(dict(zip(debyeNames,DebyePeaks['debyeTerms'][i][::2])))
2563            debyeList += zip(debyeNames,DebyePeaks['debyeTerms'][i][1::2])
2564        debyeVary = []
2565        for item in debyeList:
2566            if item[1]:
2567                debyeVary.append(item[0])
2568        backDict.update(debyeDict)
2569        backVary += debyeVary
2570        peakDict = {}
2571        peakList = []
2572        for i in range(DebyePeaks['nPeaks']):
2573            peakNames = [':'+str(hId)+':BkPkpos;'+str(i),':'+str(hId)+ \
2574                ':BkPkint;'+str(i),':'+str(hId)+':BkPksig;'+str(i),':'+str(hId)+':BkPkgam;'+str(i)]
2575            peakDict.update(dict(zip(peakNames,DebyePeaks['peaksList'][i][::2])))
2576            peakList += zip(peakNames,DebyePeaks['peaksList'][i][1::2])
2577        peakVary = []
2578        for item in peakList:
2579            if item[1]:
2580                peakVary.append(item[0])
2581        backDict.update(peakDict)
2582        backVary += peakVary
2583        return bakType,backDict,backVary           
2584       
2585    def GetInstParms(hId,Inst):     
2586        dataType = Inst['Type'][0]
2587        instDict = {}
2588        insVary = []
2589        pfx = ':'+str(hId)+':'
2590        insKeys = Inst.keys()
2591        insKeys.sort()
2592        for item in insKeys:
2593            insName = pfx+item
2594            instDict[insName] = Inst[item][1]
2595            if len(Inst[item]) > 2 and Inst[item][2]:
2596                insVary.append(insName)
2597        if 'C' in dataType:
2598            instDict[pfx+'SH/L'] = max(instDict[pfx+'SH/L'],0.0005)
2599        return dataType,instDict,insVary
2600       
2601    def GetSampleParms(hId,Sample):
2602        sampVary = []
2603        hfx = ':'+str(hId)+':'       
2604        sampDict = {hfx+'Gonio. radius':Sample['Gonio. radius'],hfx+'Omega':Sample['Omega'],
2605            hfx+'Chi':Sample['Chi'],hfx+'Phi':Sample['Phi']}
2606        for key in ('Temperature','Pressure','FreePrm1','FreePrm2','FreePrm3'):
2607            if key in Sample:
2608                sampDict[hfx+key] = Sample[key]
2609        Type = Sample['Type']
2610        if 'Bragg' in Type:             #Bragg-Brentano
2611            for item in ['Scale','Shift','Transparency','SurfRoughA','SurfRoughB']:
2612                sampDict[hfx+item] = Sample[item][0]
2613                if Sample[item][1]:
2614                    sampVary.append(hfx+item)
2615        elif 'Debye' in Type:        #Debye-Scherrer
2616            for item in ['Scale','Absorption','DisplaceX','DisplaceY']:
2617                sampDict[hfx+item] = Sample[item][0]
2618                if Sample[item][1]:
2619                    sampVary.append(hfx+item)
2620        return Type,sampDict,sampVary
2621       
2622    def PrintBackground(Background):
2623        Back = Background[0]
2624        DebyePeaks = Background[1]
2625        print >>pFile,'\n Background function: ',Back[0],' Refine?',bool(Back[1])
2626        line = ' Coefficients: '
2627        for i,back in enumerate(Back[3:]):
2628            line += '%10.3f'%(back)
2629            if i and not i%10:
2630                line += '\n'+15*' '
2631        print >>pFile,line
2632        if DebyePeaks['nDebye']:
2633            print >>pFile,'\n Debye diffuse scattering coefficients'
2634            parms = ['DebyeA','DebyeR','DebyeU']
2635            line = ' names :  '
2636            for parm in parms:
2637                line += '%8s refine?'%(parm)
2638            print >>pFile,line
2639            for j,term in enumerate(DebyePeaks['debyeTerms']):
2640                line = ' term'+'%2d'%(j)+':'
2641                for i in range(3):
2642                    line += '%10.3f %5s'%(term[2*i],bool(term[2*i+1]))                   
2643                print >>pFile,line
2644        if DebyePeaks['nPeaks']:
2645            print >>pFile,'\n Single peak coefficients'
2646            parms =    ['BkPkpos','BkPkint','BkPksig','BkPkgam']
2647            line = ' names :  '
2648            for parm in parms:
2649                line += '%8s refine?'%(parm)
2650            print >>pFile,line
2651            for j,term in enumerate(DebyePeaks['peaksList']):
2652                line = ' peak'+'%2d'%(j)+':'
2653                for i in range(4):
2654                    line += '%12.3f %5s'%(term[2*i],bool(term[2*i+1]))                   
2655                print >>pFile,line
2656       
2657    def PrintInstParms(Inst):
2658        print >>pFile,'\n Instrument Parameters:'
2659        insKeys = Inst.keys()
2660        insKeys.sort()
2661        iBeg = 0
2662        Ok = True
2663        while Ok:
2664            ptlbls = ' name  :'
2665            ptstr =  ' value :'
2666            varstr = ' refine:'
2667            iFin = min(iBeg+9,len(insKeys))
2668            for item in insKeys[iBeg:iFin]:
2669                if item not in ['Type','Source']:
2670                    ptlbls += '%12s' % (item)
2671                    ptstr += '%12.6f' % (Inst[item][1])
2672                    if item in ['Lam1','Lam2','Azimuth','fltPath','2-theta',]:
2673                        varstr += 12*' '
2674                    else:
2675                        varstr += '%12s' % (str(bool(Inst[item][2])))
2676            print >>pFile,ptlbls
2677            print >>pFile,ptstr
2678            print >>pFile,varstr
2679            iBeg = iFin
2680            if iBeg == len(insKeys):
2681                Ok = False
2682            else:
2683                print >>pFile,'\n'
2684       
2685    def PrintSampleParms(Sample):
2686        print >>pFile,'\n Sample Parameters:'
2687        print >>pFile,' Goniometer omega = %.2f, chi = %.2f, phi = %.2f'% \
2688            (Sample['Omega'],Sample['Chi'],Sample['Phi'])
2689        ptlbls = ' name  :'
2690        ptstr =  ' value :'
2691        varstr = ' refine:'
2692        if 'Bragg' in Sample['Type']:
2693            for item in ['Scale','Shift','Transparency','SurfRoughA','SurfRoughB']:
2694                ptlbls += '%14s'%(item)
2695                ptstr += '%14.4f'%(Sample[item][0])
2696                varstr += '%14s'%(str(bool(Sample[item][1])))
2697           
2698        elif 'Debye' in Type:        #Debye-Scherrer
2699            for item in ['Scale','Absorption','DisplaceX','DisplaceY']:
2700                ptlbls += '%14s'%(item)
2701                ptstr += '%14.4f'%(Sample[item][0])
2702                varstr += '%14s'%(str(bool(Sample[item][1])))
2703
2704        print >>pFile,ptlbls
2705        print >>pFile,ptstr
2706        print >>pFile,varstr
2707       
2708    histDict = {}
2709    histVary = []
2710    controlDict = {}
2711    histoList = Histograms.keys()
2712    histoList.sort()
2713    for histogram in histoList:
2714        if 'PWDR' in histogram:
2715            Histogram = Histograms[histogram]
2716            hId = Histogram['hId']
2717            pfx = ':'+str(hId)+':'
2718            controlDict[pfx+'wtFactor'] = Histogram['wtFactor']
2719            controlDict[pfx+'Limits'] = Histogram['Limits'][1]
2720            controlDict[pfx+'Exclude'] = Histogram['Limits'][2:]
2721            for excl in controlDict[pfx+'Exclude']:
2722                Histogram['Data'][0] = ma.masked_inside(Histogram['Data'][0],excl[0],excl[1])
2723            if controlDict[pfx+'Exclude']:
2724                ma.mask_rows(Histogram['Data'])
2725            Background = Histogram['Background']
2726            Type,bakDict,bakVary = GetBackgroundParms(hId,Background)
2727            controlDict[pfx+'bakType'] = Type
2728            histDict.update(bakDict)
2729            histVary += bakVary
2730           
2731            Inst = Histogram['Instrument Parameters'][0]
2732            Type,instDict,insVary = GetInstParms(hId,Inst)
2733            controlDict[pfx+'histType'] = Type
2734            if 'XC' in Type:
2735                if pfx+'Lam1' in instDict:
2736                    controlDict[pfx+'keV'] = 12.397639/instDict[pfx+'Lam1']
2737                else:
2738                    controlDict[pfx+'keV'] = 12.397639/instDict[pfx+'Lam']           
2739            histDict.update(instDict)
2740            histVary += insVary
2741           
2742            Sample = Histogram['Sample Parameters']
2743            Type,sampDict,sampVary = GetSampleParms(hId,Sample)
2744            controlDict[pfx+'instType'] = Type
2745            histDict.update(sampDict)
2746            histVary += sampVary
2747           
2748   
2749            if Print: 
2750                print >>pFile,'\n Histogram: ',histogram,' histogram Id: ',hId
2751                print >>pFile,135*'-'
2752                Units = {'C':' deg','T':' msec'}
2753                units = Units[controlDict[pfx+'histType'][2]]
2754                Limits = controlDict[pfx+'Limits']
2755                print >>pFile,' Instrument type: ',Sample['Type']
2756                print >>pFile,' Histogram limits: %8.2f%s to %8.2f%s'%(Limits[0],units,Limits[1],units)
2757                if len(controlDict[pfx+'Exclude']):
2758                    excls = controlDict[pfx+'Exclude']
2759                    for excl in excls:
2760                        print >>pFile,' Excluded region:  %8.2f%s to %8.2f%s'%(excl[0],units,excl[1],units)   
2761                PrintSampleParms(Sample)
2762                PrintInstParms(Inst)
2763                PrintBackground(Background)
2764        elif 'HKLF' in histogram:
2765            Histogram = Histograms[histogram]
2766            hId = Histogram['hId']
2767            pfx = ':'+str(hId)+':'
2768            controlDict[pfx+'wtFactor'] = Histogram['wtFactor']
2769            Inst = Histogram['Instrument Parameters'][0]
2770            controlDict[pfx+'histType'] = Inst['Type'][0]
2771            if 'X' in Inst['Type'][0]:
2772                histDict[pfx+'Lam'] = Inst['Lam'][1]
2773                controlDict[pfx+'keV'] = 12.397639/histDict[pfx+'Lam']                   
2774    return histVary,histDict,controlDict
2775   
2776def SetHistogramData(parmDict,sigDict,Histograms,Print=True,pFile=None):
2777    'needs a doc string'
2778   
2779    def SetBackgroundParms(pfx,Background,parmDict,sigDict):
2780        Back = Background[0]
2781        DebyePeaks = Background[1]
2782        lenBack = len(Back[3:])
2783        backSig = [0 for i in range(lenBack+3*DebyePeaks['nDebye']+4*DebyePeaks['nPeaks'])]
2784        for i in range(lenBack):
2785            Back[3+i] = parmDict[pfx+'Back;'+str(i)]
2786            if pfx+'Back;'+str(i) in sigDict:
2787                backSig[i] = sigDict[pfx+'Back;'+str(i)]
2788        if DebyePeaks['nDebye']:
2789            for i in range(DebyePeaks['nDebye']):
2790                names = [pfx+'DebyeA:'+str(i),pfx+'DebyeR:'+str(i),pfx+'DebyeU:'+str(i)]
2791                for j,name in enumerate(names):
2792                    DebyePeaks['debyeTerms'][i][2*j] = parmDict[name]
2793                    if name in sigDict:
2794                        backSig[lenBack+3*i+j] = sigDict[name]           
2795        if DebyePeaks['nPeaks']:
2796            for i in range(DebyePeaks['nPeaks']):
2797                names = [pfx+'BkPkpos;'+str(i),pfx+'BkPkint;'+str(i),
2798                    pfx+'BkPksig;'+str(i),pfx+'BkPkgam;'+str(i)]
2799                for j,name in enumerate(names):
2800                    DebyePeaks['peaksList'][i][2*j] = parmDict[name]
2801                    if name in sigDict:
2802                        backSig[lenBack+3*DebyePeaks['nDebye']+4*i+j] = sigDict[name]
2803        return backSig
2804       
2805    def SetInstParms(pfx,Inst,parmDict,sigDict):
2806        instSig = {}
2807        insKeys = Inst.keys()
2808        insKeys.sort()
2809        for item in insKeys:
2810            insName = pfx+item
2811            Inst[item][1] = parmDict[insName]
2812            if insName in sigDict:
2813                instSig[item] = sigDict[insName]
2814            else:
2815                instSig[item] = 0
2816        return instSig
2817       
2818    def SetSampleParms(pfx,Sample,parmDict,sigDict):
2819        if 'Bragg' in Sample['Type']:             #Bragg-Brentano
2820            sampSig = [0 for i in range(5)]
2821            for i,item in enumerate(['Scale','Shift','Transparency','SurfRoughA','SurfRoughB']):
2822                Sample[item][0] = parmDict[pfx+item]
2823                if pfx+item in sigDict:
2824                    sampSig[i] = sigDict[pfx+item]
2825        elif 'Debye' in Sample['Type']:        #Debye-Scherrer
2826            sampSig = [0 for i in range(4)]
2827            for i,item in enumerate(['Scale','Absorption','DisplaceX','DisplaceY']):
2828                Sample[item][0] = parmDict[pfx+item]
2829                if pfx+item in sigDict:
2830                    sampSig[i] = sigDict[pfx+item]
2831        return sampSig
2832       
2833    def PrintBackgroundSig(Background,backSig):
2834        Back = Background[0]
2835        DebyePeaks = Background[1]
2836        lenBack = len(Back[3:])
2837        valstr = ' value : '
2838        sigstr = ' sig   : '
2839        refine = False
2840        for i,back in enumerate(Back[3:]):
2841            valstr += '%10.4g'%(back)
2842            if Back[1]:
2843                refine = True
2844                sigstr += '%10.4g'%(backSig[i])
2845            else:
2846                sigstr += 10*' '
2847        if refine:
2848            print >>pFile,'\n Background function: ',Back[0]
2849            print >>pFile,valstr
2850            print >>pFile,sigstr
2851        if DebyePeaks['nDebye']:
2852            ifAny = False
2853            ptfmt = "%12.3f"
2854            names =  ' names :'
2855            ptstr =  ' values:'
2856            sigstr = ' esds  :'
2857            for item in sigDict:
2858                if 'Debye' in item:
2859                    ifAny = True
2860                    names += '%12s'%(item)
2861                    ptstr += ptfmt%(parmDict[item])
2862                    sigstr += ptfmt%(sigDict[item])
2863            if ifAny:
2864                print >>pFile,'\n Debye diffuse scattering coefficients'
2865                print >>pFile,names
2866                print >>pFile,ptstr
2867                print >>pFile,sigstr
2868        if DebyePeaks['nPeaks']:
2869            print >>pFile,'\n Single peak coefficients:'
2870            parms =    ['BkPkpos','BkPkint','BkPksig','BkPkgam']
2871            line = ' peak no. '
2872            for parm in parms:
2873                line += '%14s%12s'%(parm.center(14),'esd'.center(12))
2874            print >>pFile,line
2875            for ip in range(DebyePeaks['nPeaks']):
2876                ptstr = ' %4d '%(ip)
2877                for parm in parms:
2878                    fmt = '%14.3f'
2879                    efmt = '%12.3f'
2880                    if parm == 'BkPkpos':
2881                        fmt = '%14.4f'
2882                        efmt = '%12.4f'
2883                    name = pfx+parm+';%d'%(ip)
2884                    ptstr += fmt%(parmDict[name])
2885                    if name in sigDict:
2886                        ptstr += efmt%(sigDict[name])
2887                    else:
2888                        ptstr += 12*' '
2889                print >>pFile,ptstr
2890        sumBk = np.array(Histogram['sumBk'])
2891        print >>pFile,' Background sums: empirical %.3g, Debye %.3g, peaks %.3g, Total %.3g'    \
2892            %(sumBk[0],sumBk[1],sumBk[2],np.sum(sumBk))
2893       
2894    def PrintInstParmsSig(Inst,instSig):
2895        refine = False
2896        insKeys = instSig.keys()
2897        insKeys.sort()
2898        iBeg = 0
2899        Ok = True
2900        while Ok:
2901            ptlbls = ' names :'
2902            ptstr =  ' value :'
2903            sigstr = ' sig   :'
2904            iFin = min(iBeg+9,len(insKeys))
2905            for name in insKeys[iBeg:iFin]:
2906                if name not in  ['Type','Lam1','Lam2','Azimuth','Source','fltPath']:
2907                    ptlbls += '%12s' % (name)
2908                    ptstr += '%12.6f' % (Inst[name][1])
2909                    if instSig[name]:
2910                        refine = True
2911                        sigstr += '%12.6f' % (instSig[name])
2912                    else:
2913                        sigstr += 12*' '
2914            if refine:
2915                print >>pFile,'\n Instrument Parameters:'
2916                print >>pFile,ptlbls
2917                print >>pFile,ptstr
2918                print >>pFile,sigstr
2919            iBeg = iFin
2920            if iBeg == len(insKeys):
2921                Ok = False
2922       
2923    def PrintSampleParmsSig(Sample,sampleSig):
2924        ptlbls = ' names :'
2925        ptstr =  ' values:'
2926        sigstr = ' sig   :'
2927        refine = False
2928        if 'Bragg' in Sample['Type']:
2929            for i,item in enumerate(['Scale','Shift','Transparency','SurfRoughA','SurfRoughB']):
2930                ptlbls += '%14s'%(item)
2931                ptstr += '%14.4f'%(Sample[item][0])
2932                if sampleSig[i]:
2933                    refine = True
2934                    sigstr += '%14.4f'%(sampleSig[i])
2935                else:
2936                    sigstr += 14*' '
2937           
2938        elif 'Debye' in Sample['Type']:        #Debye-Scherrer
2939            for i,item in enumerate(['Scale','Absorption','DisplaceX','DisplaceY']):
2940                ptlbls += '%14s'%(item)
2941                ptstr += '%14.4f'%(Sample[item][0])
2942                if sampleSig[i]:
2943                    refine = True
2944                    sigstr += '%14.4f'%(sampleSig[i])
2945                else:
2946                    sigstr += 14*' '
2947
2948        if refine:
2949            print >>pFile,'\n Sample Parameters:'
2950            print >>pFile,ptlbls
2951            print >>pFile,ptstr
2952            print >>pFile,sigstr
2953       
2954    histoList = Histograms.keys()
2955    histoList.sort()
2956    for histogram in histoList:
2957        if 'PWDR' in histogram:
2958            Histogram = Histograms[histogram]
2959            hId = Histogram['hId']
2960            pfx = ':'+str(hId)+':'
2961            Background = Histogram['Background']
2962            backSig = SetBackgroundParms(pfx,Background,parmDict,sigDict)
2963           
2964            Inst = Histogram['Instrument Parameters'][0]
2965            instSig = SetInstParms(pfx,Inst,parmDict,sigDict)
2966       
2967            Sample = Histogram['Sample Parameters']
2968            sampSig = SetSampleParms(pfx,Sample,parmDict,sigDict)
2969
2970            print >>pFile,'\n Histogram: ',histogram,' histogram Id: ',hId
2971            print >>pFile,135*'-'
2972            print >>pFile,' PWDR histogram weight factor = '+'%.3f'%(Histogram['wtFactor'])
2973            print >>pFile,' Final refinement wR = %.2f%% on %d observations in this histogram'%(Histogram['Residuals']['wR'],Histogram['Residuals']['Nobs'])
2974            print >>pFile,' Other residuals: R = %.2f%%, Rb = %.2f%%, wRb = %.2f%% wRmin = %.2f%%'% \
2975                (Histogram['Residuals']['R'],Histogram['Residuals']['Rb'],Histogram['Residuals']['wRb'],Histogram['Residuals']['wRmin'])
2976            if Print:
2977                print >>pFile,' Instrument type: ',Sample['Type']
2978                PrintSampleParmsSig(Sample,sampSig)
2979                PrintInstParmsSig(Inst,instSig)
2980                PrintBackgroundSig(Background,backSig)
2981               
Note: See TracBrowser for help on using the repository browser.