source: trunk/GSASIIstrIO.py @ 1781

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

fix bug from old Pref.Ori. not having penalty items
Implement colors for bad items in Reflection Lists; Prfo < 0 for PWDR
red Fc for abs(Fo-Fc)/sig > 10 & yellow if > 3.
Implement user selected rejection scheme for HKLF; set mul < 0. Get calculated but not used in least squares

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