source: trunk/GSASIIstrIO.py @ 1775

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

fix to SH texture stuff

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 132.2 KB
Line 
1# -*- coding: utf-8 -*-
2########### SVN repository information ###################
3# $Date: 2015-04-02 20:43:31 +0000 (Thu, 02 Apr 2015) $
4# $Author: vondreele $
5# $Revision: 1775 $
6# $URL: trunk/GSASIIstrIO.py $
7# $Id: GSASIIstrIO.py 1775 2015-04-02 20:43:31Z 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: 1775 $")
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+'SHhkl'] = []
2074                    if hapData['Pref.Ori.'][6][0] != '':
2075                        controlDict[pfx+'SHhkl'] = [eval(a.replace(' ',',')) for a in hapData['Pref.Ori.'][6]]
2076                    controlDict[pfx+'SHtoler'] = hapData['Pref.Ori.'][7]
2077                    for item in hapData['Pref.Ori.'][5]:
2078                        hapDict[pfx+item] = hapData['Pref.Ori.'][5][item]
2079                        if hapData['Pref.Ori.'][2]:
2080                            hapVary.append(pfx+item)
2081                for item in ['Mustrain','Size']:
2082                    controlDict[pfx+item+'Type'] = hapData[item][0]
2083                    hapDict[pfx+item+';mx'] = hapData[item][1][2]
2084                    if hapData[item][2][2]:
2085                        hapVary.append(pfx+item+';mx')
2086                    if hapData[item][0] in ['isotropic','uniaxial']:
2087                        hapDict[pfx+item+';i'] = hapData[item][1][0]
2088                        if hapData[item][2][0]:
2089                            hapVary.append(pfx+item+';i')
2090                        if hapData[item][0] == 'uniaxial':
2091                            controlDict[pfx+item+'Axis'] = hapData[item][3]
2092                            hapDict[pfx+item+';a'] = hapData[item][1][1]
2093                            if hapData[item][2][1]:
2094                                hapVary.append(pfx+item+';a')
2095                    else:       #generalized for mustrain or ellipsoidal for size
2096                        Nterms = len(hapData[item][4])
2097                        if item == 'Mustrain':
2098                            names = G2spc.MustrainNames(SGData)
2099                            pwrs = []
2100                            for name in names:
2101                                h,k,l = name[1:]
2102                                pwrs.append([int(h),int(k),int(l)])
2103                            controlDict[pfx+'MuPwrs'] = pwrs
2104                        for i in range(Nterms):
2105                            sfx = ':'+str(i)
2106                            hapDict[pfx+item+sfx] = hapData[item][4][i]
2107                            if hapData[item][5][i]:
2108                                hapVary.append(pfx+item+sfx)
2109                for bab in ['BabA','BabU']:
2110                    hapDict[pfx+bab] = hapData['Babinet'][bab][0]
2111                    if hapData['Babinet'][bab][1]:
2112                        hapVary.append(pfx+bab)
2113                               
2114                if Print: 
2115                    print >>pFile,'\n Phase: ',phase,' in histogram: ',histogram
2116                    print >>pFile,135*'-'
2117                    print >>pFile,' Phase fraction  : %10.4f'%(hapData['Scale'][0]),' Refine?',hapData['Scale'][1]
2118                    print >>pFile,' Extinction coeff: %10.4f'%(hapData['Extinction'][0]),' Refine?',hapData['Extinction'][1]
2119                    if hapData['Pref.Ori.'][0] == 'MD':
2120                        Ax = hapData['Pref.Ori.'][3]
2121                        print >>pFile,' March-Dollase PO: %10.4f'%(hapData['Pref.Ori.'][1]),' Refine?',hapData['Pref.Ori.'][2], \
2122                            ' Axis: %d %d %d'%(Ax[0],Ax[1],Ax[2])
2123                    else: #'SH' for spherical harmonics
2124                        PrintSHPO(hapData['Pref.Ori.'])
2125                        print >>pFile,' Penalty hkl list: '+str(controlDict[pfx+'SHhkl'])+' tolerance: %.2f'%(controlDict[pfx+'SHtoler'])
2126                    PrintSize(hapData['Size'])
2127                    PrintMuStrain(hapData['Mustrain'],SGData)
2128                    PrintHStrain(hapData['HStrain'],SGData)
2129                    if hapData['Babinet']['BabA'][0]:
2130                        PrintBabinet(hapData['Babinet'])                       
2131                if resetRefList:
2132                    refList = []
2133                    Uniq = []
2134                    Phi = []
2135                    if Phases[phase]['General']['Type'] in ['modulated','magnetic']:
2136                        ifSuper = True
2137                        HKLd = np.array(G2lat.GenSSHLaue(dmin,SGData,SSGData,Vec,maxH,A))
2138                        HKLd = G2mth.sortArray(HKLd,4,reverse=True)
2139                        for h,k,l,m,d in HKLd:
2140                            ext,mul,uniq,phi = G2spc.GenHKLf([h,k,l],SGData)    #is this right for SS refl.??
2141                            mul *= 2      # for powder overlap of Friedel pairs
2142                            if m or not ext:
2143                                if 'C' in inst['Type'][0]:
2144                                    pos = G2lat.Dsp2pos(inst,d)
2145                                    if limits[0] < pos < limits[1]:
2146                                        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])
2147                                        #... sig,gam,fotsq,fctsq, phase,icorr,prfo,abs,ext
2148                                        Uniq.append(uniq)
2149                                        Phi.append(phi)
2150                                elif 'T' in inst['Type'][0]:
2151                                    pos = G2lat.Dsp2pos(inst,d)
2152                                    if limits[0] < pos < limits[1]:
2153                                        wave = inst['difC'][1]*d/(252.816*inst['fltPath'][0])
2154                                        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])
2155                                        # ... sig,gam,fotsq,fctsq, phase,icorr,alp,bet,wave, prfo,abs,ext
2156                                        Uniq.append(uniq)
2157                                        Phi.append(phi)
2158                    else:
2159                        ifSuper = False
2160                        HKLd = np.array(G2lat.GenHLaue(dmin,SGData,A))
2161                        HKLd = G2mth.sortArray(HKLd,3,reverse=True)
2162                        for h,k,l,d in HKLd:
2163                            ext,mul,uniq,phi = G2spc.GenHKLf([h,k,l],SGData)
2164                            mul *= 2      # for powder overlap of Friedel pairs
2165                            if ext:
2166                                continue
2167                            if 'C' in inst['Type'][0]:
2168                                pos = G2lat.Dsp2pos(inst,d)
2169                                if limits[0] < pos < limits[1]:
2170                                    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])
2171                                    #... sig,gam,fotsq,fctsq, phase,icorr,prfo,abs,ext
2172                                    Uniq.append(uniq)
2173                                    Phi.append(phi)
2174                            elif 'T' in inst['Type'][0]:
2175                                pos = G2lat.Dsp2pos(inst,d)
2176                                if limits[0] < pos < limits[1]:
2177                                    wave = inst['difC'][1]*d/(252.816*inst['fltPath'][0])
2178                                    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])
2179                                    # ... sig,gam,fotsq,fctsq, phase,icorr,alp,bet,wave, prfo,abs,ext
2180                                    Uniq.append(uniq)
2181                                    Phi.append(phi)
2182                    Histogram['Reflection Lists'][phase] = {'RefList':np.array(refList),'FF':{},'Type':inst['Type'][0],'Super':ifSuper}
2183            elif 'HKLF' in histogram:
2184                inst = Histogram['Instrument Parameters'][0]
2185                hId = Histogram['hId']
2186                hfx = ':%d:'%(hId)
2187                for item in inst:
2188                    if type(inst) is not list and item != 'Type': continue # skip over non-refined items (such as InstName)
2189                    hapDict[hfx+item] = inst[item][1]
2190                pfx = str(pId)+':'+str(hId)+':'
2191                hapDict[pfx+'Scale'] = hapData['Scale'][0]
2192                if hapData['Scale'][1]:
2193                    hapVary.append(pfx+'Scale')
2194                               
2195                extApprox,extType,extParms = hapData['Extinction']
2196                controlDict[pfx+'EType'] = extType
2197                controlDict[pfx+'EApprox'] = extApprox
2198                if 'C' in inst['Type'][0]:
2199                    controlDict[pfx+'Tbar'] = extParms['Tbar']
2200                    controlDict[pfx+'Cos2TM'] = extParms['Cos2TM']
2201                if 'Primary' in extType:
2202                    Ekey = ['Ep',]
2203                elif 'I & II' in extType:
2204                    Ekey = ['Eg','Es']
2205                elif 'Secondary Type II' == extType:
2206                    Ekey = ['Es',]
2207                elif 'Secondary Type I' == extType:
2208                    Ekey = ['Eg',]
2209                else:   #'None'
2210                    Ekey = []
2211                for eKey in Ekey:
2212                    hapDict[pfx+eKey] = extParms[eKey][0]
2213                    if extParms[eKey][1]:
2214                        hapVary.append(pfx+eKey)
2215                for bab in ['BabA','BabU']:
2216                    hapDict[pfx+bab] = hapData['Babinet'][bab][0]
2217                    if hapData['Babinet'][bab][1]:
2218                        hapVary.append(pfx+bab)
2219                if Print: 
2220                    print >>pFile,'\n Phase: ',phase,' in histogram: ',histogram
2221                    print >>pFile,135*'-'
2222                    print >>pFile,' Scale factor     : %10.4f'%(hapData['Scale'][0]),' Refine?',hapData['Scale'][1]
2223                    if extType != 'None':
2224                        print >>pFile,' Extinction  Type: %15s'%(extType),' approx: %10s'%(extApprox)
2225                        text = ' Parameters       :'
2226                        for eKey in Ekey:
2227                            text += ' %4s : %10.3e Refine? '%(eKey,extParms[eKey][0])+str(extParms[eKey][1])
2228                        print >>pFile,text
2229                    if hapData['Babinet']['BabA'][0]:
2230                        PrintBabinet(hapData['Babinet'])
2231                Histogram['Reflection Lists'] = phase       
2232               
2233    return hapVary,hapDict,controlDict
2234   
2235def SetHistogramPhaseData(parmDict,sigDict,Phases,Histograms,Print=True,pFile=None):
2236    'needs a doc string'
2237   
2238    def PrintSizeAndSig(hapData,sizeSig):
2239        line = '\n Size model:     %9s'%(hapData[0])
2240        refine = False
2241        if hapData[0] in ['isotropic','uniaxial']:
2242            line += ' equatorial:%12.5f'%(hapData[1][0])
2243            if sizeSig[0][0]:
2244                line += ', sig:%8.4f'%(sizeSig[0][0])
2245                refine = True
2246            if hapData[0] == 'uniaxial':
2247                line += ' axial:%12.4f'%(hapData[1][1])
2248                if sizeSig[0][1]:
2249                    refine = True
2250                    line += ', sig:%8.4f'%(sizeSig[0][1])
2251            line += ' LG mix coeff.:%12.4f'%(hapData[1][2])
2252            if sizeSig[0][2]:
2253                refine = True
2254                line += ', sig:%8.4f'%(sizeSig[0][2])
2255            if refine:
2256                print >>pFile,line
2257        else:
2258            line += ' LG mix coeff.:%12.4f'%(hapData[1][2])
2259            if sizeSig[0][2]:
2260                refine = True
2261                line += ', sig:%8.4f'%(sizeSig[0][2])
2262            Snames = ['S11','S22','S33','S12','S13','S23']
2263            ptlbls = ' name  :'
2264            ptstr =  ' value :'
2265            sigstr = ' sig   :'
2266            for i,name in enumerate(Snames):
2267                ptlbls += '%12s' % (name)
2268                ptstr += '%12.6f' % (hapData[4][i])
2269                if sizeSig[1][i]:
2270                    refine = True
2271                    sigstr += '%12.6f' % (sizeSig[1][i])
2272                else:
2273                    sigstr += 12*' '
2274            if refine:
2275                print >>pFile,line
2276                print >>pFile,ptlbls
2277                print >>pFile,ptstr
2278                print >>pFile,sigstr
2279       
2280    def PrintMuStrainAndSig(hapData,mustrainSig,SGData):
2281        line = '\n Mustrain model: %9s'%(hapData[0])
2282        refine = False
2283        if hapData[0] in ['isotropic','uniaxial']:
2284            line += ' equatorial:%12.1f'%(hapData[1][0])
2285            if mustrainSig[0][0]:
2286                line += ', sig:%8.1f'%(mustrainSig[0][0])
2287                refine = True
2288            if hapData[0] == 'uniaxial':
2289                line += ' axial:%12.1f'%(hapData[1][1])
2290                if mustrainSig[0][1]:
2291                     line += ', sig:%8.1f'%(mustrainSig[0][1])
2292            line += ' LG mix coeff.:%12.4f'%(hapData[1][2])
2293            if mustrainSig[0][2]:
2294                refine = True
2295                line += ', sig:%8.3f'%(mustrainSig[0][2])
2296            if refine:
2297                print >>pFile,line
2298        else:
2299            line += ' LG mix coeff.:%12.4f'%(hapData[1][2])
2300            if mustrainSig[0][2]:
2301                refine = True
2302                line += ', sig:%8.3f'%(mustrainSig[0][2])
2303            Snames = G2spc.MustrainNames(SGData)
2304            ptlbls = ' name  :'
2305            ptstr =  ' value :'
2306            sigstr = ' sig   :'
2307            for i,name in enumerate(Snames):
2308                ptlbls += '%12s' % (name)
2309                ptstr += '%12.6f' % (hapData[4][i])
2310                if mustrainSig[1][i]:
2311                    refine = True
2312                    sigstr += '%12.6f' % (mustrainSig[1][i])
2313                else:
2314                    sigstr += 12*' '
2315            if refine:
2316                print >>pFile,line
2317                print >>pFile,ptlbls
2318                print >>pFile,ptstr
2319                print >>pFile,sigstr
2320           
2321    def PrintHStrainAndSig(hapData,strainSig,SGData):
2322        Hsnames = G2spc.HStrainNames(SGData)
2323        ptlbls = ' name  :'
2324        ptstr =  ' value :'
2325        sigstr = ' sig   :'
2326        refine = False
2327        for i,name in enumerate(Hsnames):
2328            ptlbls += '%12s' % (name)
2329            ptstr += '%12.4g' % (hapData[0][i])
2330            if name in strainSig:
2331                refine = True
2332                sigstr += '%12.4g' % (strainSig[name])
2333            else:
2334                sigstr += 12*' '
2335        if refine:
2336            print >>pFile,'\n Hydrostatic/elastic strain: '
2337            print >>pFile,ptlbls
2338            print >>pFile,ptstr
2339            print >>pFile,sigstr
2340       
2341    def PrintSHPOAndSig(pfx,hapData,POsig):
2342        print >>pFile,'\n Spherical harmonics preferred orientation: Order:'+str(hapData[4])
2343        ptlbls = ' names :'
2344        ptstr =  ' values:'
2345        sigstr = ' sig   :'
2346        for item in hapData[5]:
2347            ptlbls += '%12s'%(item)
2348            ptstr += '%12.3f'%(hapData[5][item])
2349            if pfx+item in POsig:
2350                sigstr += '%12.3f'%(POsig[pfx+item])
2351            else:
2352                sigstr += 12*' ' 
2353        print >>pFile,ptlbls
2354        print >>pFile,ptstr
2355        print >>pFile,sigstr
2356       
2357    def PrintExtAndSig(pfx,hapData,ScalExtSig):
2358        print >>pFile,'\n Single crystal extinction: Type: ',hapData[0],' Approx: ',hapData[1]
2359        text = ''
2360        for item in hapData[2]:
2361            if pfx+item in ScalExtSig:
2362                text += '       %s: '%(item)
2363                text += '%12.2e'%(hapData[2][item][0])
2364                if pfx+item in ScalExtSig:
2365                    text += ' sig: %12.2e'%(ScalExtSig[pfx+item])
2366        print >>pFile,text       
2367       
2368    def PrintBabinetAndSig(pfx,hapData,BabSig):
2369        print >>pFile,'\n Babinet form factor modification: '
2370        ptlbls = ' names :'
2371        ptstr =  ' values:'
2372        sigstr = ' sig   :'
2373        for item in hapData:
2374            ptlbls += '%12s'%(item)
2375            ptstr += '%12.3f'%(hapData[item][0])
2376            if pfx+item in BabSig:
2377                sigstr += '%12.3f'%(BabSig[pfx+item])
2378            else:
2379                sigstr += 12*' ' 
2380        print >>pFile,ptlbls
2381        print >>pFile,ptstr
2382        print >>pFile,sigstr
2383   
2384    PhFrExtPOSig = {}
2385    SizeMuStrSig = {}
2386    ScalExtSig = {}
2387    BabSig = {}
2388    wtFrSum = {}
2389    for phase in Phases:
2390        HistoPhase = Phases[phase]['Histograms']
2391        General = Phases[phase]['General']
2392        SGData = General['SGData']
2393        pId = Phases[phase]['pId']
2394        histoList = HistoPhase.keys()
2395        histoList.sort()
2396        for histogram in histoList:
2397            try:
2398                Histogram = Histograms[histogram]
2399            except KeyError:                       
2400                #skip if histogram not included e.g. in a sequential refinement
2401                continue
2402            hapData = HistoPhase[histogram]
2403            hId = Histogram['hId']
2404            pfx = str(pId)+':'+str(hId)+':'
2405            if hId not in wtFrSum:
2406                wtFrSum[hId] = 0.
2407            if 'PWDR' in histogram:
2408                for item in ['Scale','Extinction']:
2409                    hapData[item][0] = parmDict[pfx+item]
2410                    if pfx+item in sigDict:
2411                        PhFrExtPOSig.update({pfx+item:sigDict[pfx+item],})
2412                wtFrSum[hId] += hapData['Scale'][0]*General['Mass']
2413                if hapData['Pref.Ori.'][0] == 'MD':
2414                    hapData['Pref.Ori.'][1] = parmDict[pfx+'MD']
2415                    if pfx+'MD' in sigDict:
2416                        PhFrExtPOSig.update({pfx+'MD':sigDict[pfx+'MD'],})
2417                else:                           #'SH' spherical harmonics
2418                    for item in hapData['Pref.Ori.'][5]:
2419                        hapData['Pref.Ori.'][5][item] = parmDict[pfx+item]
2420                        if pfx+item in sigDict:
2421                            PhFrExtPOSig.update({pfx+item:sigDict[pfx+item],})
2422                SizeMuStrSig.update({pfx+'Mustrain':[[0,0,0],[0 for i in range(len(hapData['Mustrain'][4]))]],
2423                    pfx+'Size':[[0,0,0],[0 for i in range(len(hapData['Size'][4]))]],
2424                    pfx+'HStrain':{}})                 
2425                for item in ['Mustrain','Size']:
2426                    hapData[item][1][2] = parmDict[pfx+item+';mx']
2427                    hapData[item][1][2] = min(1.,max(0.,hapData[item][1][2]))
2428                    if pfx+item+';mx' in sigDict:
2429                        SizeMuStrSig[pfx+item][0][2] = sigDict[pfx+item+';mx']
2430                    if hapData[item][0] in ['isotropic','uniaxial']:                   
2431                        hapData[item][1][0] = parmDict[pfx+item+';i']
2432                        if item == 'Size':
2433                            hapData[item][1][0] = min(10.,max(0.001,hapData[item][1][0]))
2434                        if pfx+item+';i' in sigDict: 
2435                            SizeMuStrSig[pfx+item][0][0] = sigDict[pfx+item+';i']
2436                        if hapData[item][0] == 'uniaxial':
2437                            hapData[item][1][1] = parmDict[pfx+item+';a']
2438                            if item == 'Size':
2439                                hapData[item][1][1] = min(10.,max(0.001,hapData[item][1][1]))                       
2440                            if pfx+item+';a' in sigDict:
2441                                SizeMuStrSig[pfx+item][0][1] = sigDict[pfx+item+';a']
2442                    else:       #generalized for mustrain or ellipsoidal for size
2443                        Nterms = len(hapData[item][4])
2444                        for i in range(Nterms):
2445                            sfx = ':'+str(i)
2446                            hapData[item][4][i] = parmDict[pfx+item+sfx]
2447                            if pfx+item+sfx in sigDict:
2448                                SizeMuStrSig[pfx+item][1][i] = sigDict[pfx+item+sfx]
2449                names = G2spc.HStrainNames(SGData)
2450                for i,name in enumerate(names):
2451                    hapData['HStrain'][0][i] = parmDict[pfx+name]
2452                    if pfx+name in sigDict:
2453                        SizeMuStrSig[pfx+'HStrain'][name] = sigDict[pfx+name]
2454                for name in ['BabA','BabU']:
2455                    hapData['Babinet'][name][0] = parmDict[pfx+name]
2456                    if pfx+name in sigDict:
2457                        BabSig[pfx+name] = sigDict[pfx+name]               
2458               
2459            elif 'HKLF' in histogram:
2460                for item in ['Scale',]:
2461                    if parmDict.get(pfx+item):
2462                        hapData[item][0] = parmDict[pfx+item]
2463                        if pfx+item in sigDict:
2464                            ScalExtSig[pfx+item] = sigDict[pfx+item]
2465                for item in ['Ep','Eg','Es']:
2466                    if parmDict.get(pfx+item):
2467                        hapData['Extinction'][2][item][0] = parmDict[pfx+item]
2468                        if pfx+item in sigDict:
2469                            ScalExtSig[pfx+item] = sigDict[pfx+item]
2470                for name in ['BabA','BabU']:
2471                    hapData['Babinet'][name][0] = parmDict[pfx+name]
2472                    if pfx+name in sigDict:
2473                        BabSig[pfx+name] = sigDict[pfx+name]               
2474
2475    if Print:
2476        for phase in Phases:
2477            HistoPhase = Phases[phase]['Histograms']
2478            General = Phases[phase]['General']
2479            SGData = General['SGData']
2480            pId = Phases[phase]['pId']
2481            histoList = HistoPhase.keys()
2482            histoList.sort()
2483            for histogram in histoList:
2484                try:
2485                    Histogram = Histograms[histogram]
2486                except KeyError:                       
2487                    #skip if histogram not included e.g. in a sequential refinement
2488                    continue
2489                print >>pFile,'\n Phase: ',phase,' in histogram: ',histogram
2490                print >>pFile,130*'-'
2491                hapData = HistoPhase[histogram]
2492                hId = Histogram['hId']
2493                Histogram['Residuals'][str(pId)+'::Name'] = phase
2494                pfx = str(pId)+':'+str(hId)+':'
2495                if 'PWDR' in histogram:
2496                    print >>pFile,' Final refinement RF, RF^2 = %.2f%%, %.2f%% on %d reflections'   \
2497                        %(Histogram['Residuals'][pfx+'Rf'],Histogram['Residuals'][pfx+'Rf^2'],Histogram['Residuals'][pfx+'Nref'])
2498                    print >>pFile,' Bragg intensity sum = %.3g'%(Histogram['Residuals'][pfx+'sumInt'])
2499               
2500                    if pfx+'Scale' in PhFrExtPOSig:
2501                        wtFr = hapData['Scale'][0]*General['Mass']/wtFrSum[hId]
2502                        sigwtFr = PhFrExtPOSig[pfx+'Scale']*wtFr/hapData['Scale'][0]
2503                        print >>pFile,' Phase fraction  : %10.5f, sig %10.5f Weight fraction  : %8.5f, sig %10.5f' \
2504                            %(hapData['Scale'][0],PhFrExtPOSig[pfx+'Scale'],wtFr,sigwtFr)
2505                    if pfx+'Extinction' in PhFrExtPOSig:
2506                        print >>pFile,' Extinction coeff: %10.4f, sig %10.4f'%(hapData['Extinction'][0],PhFrExtPOSig[pfx+'Extinction'])
2507                    if hapData['Pref.Ori.'][0] == 'MD':
2508                        if pfx+'MD' in PhFrExtPOSig:
2509                            print >>pFile,' March-Dollase PO: %10.4f, sig %10.4f'%(hapData['Pref.Ori.'][1],PhFrExtPOSig[pfx+'MD'])
2510                    else:
2511                        PrintSHPOAndSig(pfx,hapData['Pref.Ori.'],PhFrExtPOSig)
2512                    PrintSizeAndSig(hapData['Size'],SizeMuStrSig[pfx+'Size'])
2513                    PrintMuStrainAndSig(hapData['Mustrain'],SizeMuStrSig[pfx+'Mustrain'],SGData)
2514                    PrintHStrainAndSig(hapData['HStrain'],SizeMuStrSig[pfx+'HStrain'],SGData)
2515                    if len(BabSig):
2516                        PrintBabinetAndSig(pfx,hapData['Babinet'],BabSig)
2517                   
2518                elif 'HKLF' in histogram:
2519                    print >>pFile,' Final refinement RF, RF^2 = %.2f%%, %.2f%% on %d reflections'   \
2520                        %(Histogram['Residuals'][pfx+'Rf'],Histogram['Residuals'][pfx+'Rf^2'],Histogram['Residuals'][pfx+'Nref'])
2521                    print >>pFile,' HKLF histogram weight factor = ','%.3f'%(Histogram['wtFactor'])
2522                    if pfx+'Scale' in ScalExtSig:
2523                        print >>pFile,' Scale factor : %10.4f, sig %10.4f'%(hapData['Scale'][0],ScalExtSig[pfx+'Scale'])
2524                    if hapData['Extinction'][0] != 'None':
2525                        PrintExtAndSig(pfx,hapData['Extinction'],ScalExtSig)
2526                    if len(BabSig):
2527                        PrintBabinetAndSig(pfx,hapData['Babinet'],BabSig)
2528
2529################################################################################
2530##### Histogram data
2531################################################################################       
2532                   
2533def GetHistogramData(Histograms,Print=True,pFile=None):
2534    'needs a doc string'
2535   
2536    def GetBackgroundParms(hId,Background):
2537        Back = Background[0]
2538        DebyePeaks = Background[1]
2539        bakType,bakFlag = Back[:2]
2540        backVals = Back[3:]
2541        backNames = [':'+str(hId)+':Back;'+str(i) for i in range(len(backVals))]
2542        backDict = dict(zip(backNames,backVals))
2543        backVary = []
2544        if bakFlag:
2545            backVary = backNames
2546        backDict[':'+str(hId)+':nDebye'] = DebyePeaks['nDebye']
2547        backDict[':'+str(hId)+':nPeaks'] = DebyePeaks['nPeaks']
2548        debyeDict = {}
2549        debyeList = []
2550        for i in range(DebyePeaks['nDebye']):
2551            debyeNames = [':'+str(hId)+':DebyeA;'+str(i),':'+str(hId)+':DebyeR;'+str(i),':'+str(hId)+':DebyeU;'+str(i)]
2552            debyeDict.update(dict(zip(debyeNames,DebyePeaks['debyeTerms'][i][::2])))
2553            debyeList += zip(debyeNames,DebyePeaks['debyeTerms'][i][1::2])
2554        debyeVary = []
2555        for item in debyeList:
2556            if item[1]:
2557                debyeVary.append(item[0])
2558        backDict.update(debyeDict)
2559        backVary += debyeVary
2560        peakDict = {}
2561        peakList = []
2562        for i in range(DebyePeaks['nPeaks']):
2563            peakNames = [':'+str(hId)+':BkPkpos;'+str(i),':'+str(hId)+ \
2564                ':BkPkint;'+str(i),':'+str(hId)+':BkPksig;'+str(i),':'+str(hId)+':BkPkgam;'+str(i)]
2565            peakDict.update(dict(zip(peakNames,DebyePeaks['peaksList'][i][::2])))
2566            peakList += zip(peakNames,DebyePeaks['peaksList'][i][1::2])
2567        peakVary = []
2568        for item in peakList:
2569            if item[1]:
2570                peakVary.append(item[0])
2571        backDict.update(peakDict)
2572        backVary += peakVary
2573        return bakType,backDict,backVary           
2574       
2575    def GetInstParms(hId,Inst):     
2576        dataType = Inst['Type'][0]
2577        instDict = {}
2578        insVary = []
2579        pfx = ':'+str(hId)+':'
2580        insKeys = Inst.keys()
2581        insKeys.sort()
2582        for item in insKeys:
2583            insName = pfx+item
2584            instDict[insName] = Inst[item][1]
2585            if len(Inst[item]) > 2 and Inst[item][2]:
2586                insVary.append(insName)
2587        if 'C' in dataType:
2588            instDict[pfx+'SH/L'] = max(instDict[pfx+'SH/L'],0.0005)
2589        return dataType,instDict,insVary
2590       
2591    def GetSampleParms(hId,Sample):
2592        sampVary = []
2593        hfx = ':'+str(hId)+':'       
2594        sampDict = {hfx+'Gonio. radius':Sample['Gonio. radius'],hfx+'Omega':Sample['Omega'],
2595            hfx+'Chi':Sample['Chi'],hfx+'Phi':Sample['Phi']}
2596        for key in ('Temperature','Pressure','FreePrm1','FreePrm2','FreePrm3'):
2597            if key in Sample:
2598                sampDict[hfx+key] = Sample[key]
2599        Type = Sample['Type']
2600        if 'Bragg' in Type:             #Bragg-Brentano
2601            for item in ['Scale','Shift','Transparency','SurfRoughA','SurfRoughB']:
2602                sampDict[hfx+item] = Sample[item][0]
2603                if Sample[item][1]:
2604                    sampVary.append(hfx+item)
2605        elif 'Debye' in Type:        #Debye-Scherrer
2606            for item in ['Scale','Absorption','DisplaceX','DisplaceY']:
2607                sampDict[hfx+item] = Sample[item][0]
2608                if Sample[item][1]:
2609                    sampVary.append(hfx+item)
2610        return Type,sampDict,sampVary
2611       
2612    def PrintBackground(Background):
2613        Back = Background[0]
2614        DebyePeaks = Background[1]
2615        print >>pFile,'\n Background function: ',Back[0],' Refine?',bool(Back[1])
2616        line = ' Coefficients: '
2617        for i,back in enumerate(Back[3:]):
2618            line += '%10.3f'%(back)
2619            if i and not i%10:
2620                line += '\n'+15*' '
2621        print >>pFile,line
2622        if DebyePeaks['nDebye']:
2623            print >>pFile,'\n Debye diffuse scattering coefficients'
2624            parms = ['DebyeA','DebyeR','DebyeU']
2625            line = ' names :  '
2626            for parm in parms:
2627                line += '%8s refine?'%(parm)
2628            print >>pFile,line
2629            for j,term in enumerate(DebyePeaks['debyeTerms']):
2630                line = ' term'+'%2d'%(j)+':'
2631                for i in range(3):
2632                    line += '%10.3f %5s'%(term[2*i],bool(term[2*i+1]))                   
2633                print >>pFile,line
2634        if DebyePeaks['nPeaks']:
2635            print >>pFile,'\n Single peak coefficients'
2636            parms =    ['BkPkpos','BkPkint','BkPksig','BkPkgam']
2637            line = ' names :  '
2638            for parm in parms:
2639                line += '%8s refine?'%(parm)
2640            print >>pFile,line
2641            for j,term in enumerate(DebyePeaks['peaksList']):
2642                line = ' peak'+'%2d'%(j)+':'
2643                for i in range(4):
2644                    line += '%10.3f %5s'%(term[2*i],bool(term[2*i+1]))                   
2645                print >>pFile,line
2646       
2647    def PrintInstParms(Inst):
2648        print >>pFile,'\n Instrument Parameters:'
2649        insKeys = Inst.keys()
2650        insKeys.sort()
2651        iBeg = 0
2652        Ok = True
2653        while Ok:
2654            ptlbls = ' name  :'
2655            ptstr =  ' value :'
2656            varstr = ' refine:'
2657            iFin = min(iBeg+9,len(insKeys))
2658            for item in insKeys[iBeg:iFin]:
2659                if item not in ['Type','Source']:
2660                    ptlbls += '%12s' % (item)
2661                    ptstr += '%12.6f' % (Inst[item][1])
2662                    if item in ['Lam1','Lam2','Azimuth','fltPath','2-theta',]:
2663                        varstr += 12*' '
2664                    else:
2665                        varstr += '%12s' % (str(bool(Inst[item][2])))
2666            print >>pFile,ptlbls
2667            print >>pFile,ptstr
2668            print >>pFile,varstr
2669            iBeg = iFin
2670            if iBeg == len(insKeys):
2671                Ok = False
2672            else:
2673                print >>pFile,'\n'
2674       
2675    def PrintSampleParms(Sample):
2676        print >>pFile,'\n Sample Parameters:'
2677        print >>pFile,' Goniometer omega = %.2f, chi = %.2f, phi = %.2f'% \
2678            (Sample['Omega'],Sample['Chi'],Sample['Phi'])
2679        ptlbls = ' name  :'
2680        ptstr =  ' value :'
2681        varstr = ' refine:'
2682        if 'Bragg' in Sample['Type']:
2683            for item in ['Scale','Shift','Transparency','SurfRoughA','SurfRoughB']:
2684                ptlbls += '%14s'%(item)
2685                ptstr += '%14.4f'%(Sample[item][0])
2686                varstr += '%14s'%(str(bool(Sample[item][1])))
2687           
2688        elif 'Debye' in Type:        #Debye-Scherrer
2689            for item in ['Scale','Absorption','DisplaceX','DisplaceY']:
2690                ptlbls += '%14s'%(item)
2691                ptstr += '%14.4f'%(Sample[item][0])
2692                varstr += '%14s'%(str(bool(Sample[item][1])))
2693
2694        print >>pFile,ptlbls
2695        print >>pFile,ptstr
2696        print >>pFile,varstr
2697       
2698    histDict = {}
2699    histVary = []
2700    controlDict = {}
2701    histoList = Histograms.keys()
2702    histoList.sort()
2703    for histogram in histoList:
2704        if 'PWDR' in histogram:
2705            Histogram = Histograms[histogram]
2706            hId = Histogram['hId']
2707            pfx = ':'+str(hId)+':'
2708            controlDict[pfx+'wtFactor'] = Histogram['wtFactor']
2709            controlDict[pfx+'Limits'] = Histogram['Limits'][1]
2710            controlDict[pfx+'Exclude'] = Histogram['Limits'][2:]
2711            for excl in controlDict[pfx+'Exclude']:
2712                Histogram['Data'][0] = ma.masked_inside(Histogram['Data'][0],excl[0],excl[1])
2713            if controlDict[pfx+'Exclude']:
2714                ma.mask_rows(Histogram['Data'])
2715            Background = Histogram['Background']
2716            Type,bakDict,bakVary = GetBackgroundParms(hId,Background)
2717            controlDict[pfx+'bakType'] = Type
2718            histDict.update(bakDict)
2719            histVary += bakVary
2720           
2721            Inst = Histogram['Instrument Parameters'][0]
2722            Type,instDict,insVary = GetInstParms(hId,Inst)
2723            controlDict[pfx+'histType'] = Type
2724            if 'XC' in Type:
2725                if pfx+'Lam1' in instDict:
2726                    controlDict[pfx+'keV'] = 12.397639/instDict[pfx+'Lam1']
2727                else:
2728                    controlDict[pfx+'keV'] = 12.397639/instDict[pfx+'Lam']           
2729            histDict.update(instDict)
2730            histVary += insVary
2731           
2732            Sample = Histogram['Sample Parameters']
2733            Type,sampDict,sampVary = GetSampleParms(hId,Sample)
2734            controlDict[pfx+'instType'] = Type
2735            histDict.update(sampDict)
2736            histVary += sampVary
2737           
2738   
2739            if Print: 
2740                print >>pFile,'\n Histogram: ',histogram,' histogram Id: ',hId
2741                print >>pFile,135*'-'
2742                Units = {'C':' deg','T':' msec'}
2743                units = Units[controlDict[pfx+'histType'][2]]
2744                Limits = controlDict[pfx+'Limits']
2745                print >>pFile,' Instrument type: ',Sample['Type']
2746                print >>pFile,' Histogram limits: %8.2f%s to %8.2f%s'%(Limits[0],units,Limits[1],units)
2747                if len(controlDict[pfx+'Exclude']):
2748                    excls = controlDict[pfx+'Exclude']
2749                    for excl in excls:
2750                        print >>pFile,' Excluded region:  %8.2f%s to %8.2f%s'%(excl[0],units,excl[1],units)   
2751                PrintSampleParms(Sample)
2752                PrintInstParms(Inst)
2753                PrintBackground(Background)
2754        elif 'HKLF' in histogram:
2755            Histogram = Histograms[histogram]
2756            hId = Histogram['hId']
2757            pfx = ':'+str(hId)+':'
2758            controlDict[pfx+'wtFactor'] = Histogram['wtFactor']
2759            Inst = Histogram['Instrument Parameters'][0]
2760            controlDict[pfx+'histType'] = Inst['Type'][0]
2761            if 'X' in Inst['Type'][0]:
2762                histDict[pfx+'Lam'] = Inst['Lam'][1]
2763                controlDict[pfx+'keV'] = 12.397639/histDict[pfx+'Lam']                   
2764    return histVary,histDict,controlDict
2765   
2766def SetHistogramData(parmDict,sigDict,Histograms,Print=True,pFile=None):
2767    'needs a doc string'
2768   
2769    def SetBackgroundParms(pfx,Background,parmDict,sigDict):
2770        Back = Background[0]
2771        DebyePeaks = Background[1]
2772        lenBack = len(Back[3:])
2773        backSig = [0 for i in range(lenBack+3*DebyePeaks['nDebye']+4*DebyePeaks['nPeaks'])]
2774        for i in range(lenBack):
2775            Back[3+i] = parmDict[pfx+'Back;'+str(i)]
2776            if pfx+'Back;'+str(i) in sigDict:
2777                backSig[i] = sigDict[pfx+'Back;'+str(i)]
2778        if DebyePeaks['nDebye']:
2779            for i in range(DebyePeaks['nDebye']):
2780                names = [pfx+'DebyeA:'+str(i),pfx+'DebyeR:'+str(i),pfx+'DebyeU:'+str(i)]
2781                for j,name in enumerate(names):
2782                    DebyePeaks['debyeTerms'][i][2*j] = parmDict[name]
2783                    if name in sigDict:
2784                        backSig[lenBack+3*i+j] = sigDict[name]           
2785        if DebyePeaks['nPeaks']:
2786            for i in range(DebyePeaks['nPeaks']):
2787                names = [pfx+'BkPkpos;'+str(i),pfx+'BkPkint;'+str(i),
2788                    pfx+'BkPksig;'+str(i),pfx+'BkPkgam;'+str(i)]
2789                for j,name in enumerate(names):
2790                    DebyePeaks['peaksList'][i][2*j] = parmDict[name]
2791                    if name in sigDict:
2792                        backSig[lenBack+3*DebyePeaks['nDebye']+4*i+j] = sigDict[name]
2793        return backSig
2794       
2795    def SetInstParms(pfx,Inst,parmDict,sigDict):
2796        instSig = {}
2797        insKeys = Inst.keys()
2798        insKeys.sort()
2799        for item in insKeys:
2800            insName = pfx+item
2801            Inst[item][1] = parmDict[insName]
2802            if insName in sigDict:
2803                instSig[item] = sigDict[insName]
2804            else:
2805                instSig[item] = 0
2806        return instSig
2807       
2808    def SetSampleParms(pfx,Sample,parmDict,sigDict):
2809        if 'Bragg' in Sample['Type']:             #Bragg-Brentano
2810            sampSig = [0 for i in range(5)]
2811            for i,item in enumerate(['Scale','Shift','Transparency','SurfRoughA','SurfRoughB']):
2812                Sample[item][0] = parmDict[pfx+item]
2813                if pfx+item in sigDict:
2814                    sampSig[i] = sigDict[pfx+item]
2815        elif 'Debye' in Sample['Type']:        #Debye-Scherrer
2816            sampSig = [0 for i in range(4)]
2817            for i,item in enumerate(['Scale','Absorption','DisplaceX','DisplaceY']):
2818                Sample[item][0] = parmDict[pfx+item]
2819                if pfx+item in sigDict:
2820                    sampSig[i] = sigDict[pfx+item]
2821        return sampSig
2822       
2823    def PrintBackgroundSig(Background,backSig):
2824        Back = Background[0]
2825        DebyePeaks = Background[1]
2826        lenBack = len(Back[3:])
2827        valstr = ' value : '
2828        sigstr = ' sig   : '
2829        refine = False
2830        for i,back in enumerate(Back[3:]):
2831            valstr += '%10.4g'%(back)
2832            if Back[1]:
2833                refine = True
2834                sigstr += '%10.4g'%(backSig[i])
2835            else:
2836                sigstr += 10*' '
2837        if refine:
2838            print >>pFile,'\n Background function: ',Back[0]
2839            print >>pFile,valstr
2840            print >>pFile,sigstr
2841        if DebyePeaks['nDebye']:
2842            ifAny = False
2843            ptfmt = "%12.3f"
2844            names =  ' names :'
2845            ptstr =  ' values:'
2846            sigstr = ' esds  :'
2847            for item in sigDict:
2848                if 'Debye' in item:
2849                    ifAny = True
2850                    names += '%12s'%(item)
2851                    ptstr += ptfmt%(parmDict[item])
2852                    sigstr += ptfmt%(sigDict[item])
2853            if ifAny:
2854                print >>pFile,'\n Debye diffuse scattering coefficients'
2855                print >>pFile,names
2856                print >>pFile,ptstr
2857                print >>pFile,sigstr
2858        if DebyePeaks['nPeaks']:
2859            ifAny = False
2860            ptfmt = "%14.3f"
2861            names =  ' names :'
2862            ptstr =  ' values:'
2863            sigstr = ' esds  :'
2864            for item in sigDict:
2865                if 'BkPk' in item:
2866                    ifAny = True
2867                    names += '%14s'%(item)
2868                    ptstr += ptfmt%(parmDict[item])
2869                    sigstr += ptfmt%(sigDict[item])
2870            if ifAny:
2871                print >>pFile,'\n Single peak coefficients'
2872                print >>pFile,names
2873                print >>pFile,ptstr
2874                print >>pFile,sigstr
2875        sumBk = np.array(Histogram['sumBk'])
2876        print >>pFile,' Background sums: empirical %.3g, Debye %.3g, peaks %.3g, Total %.3g'    \
2877            %(sumBk[0],sumBk[1],sumBk[2],np.sum(sumBk))
2878       
2879    def PrintInstParmsSig(Inst,instSig):
2880        refine = False
2881        insKeys = instSig.keys()
2882        insKeys.sort()
2883        iBeg = 0
2884        Ok = True
2885        while Ok:
2886            ptlbls = ' names :'
2887            ptstr =  ' value :'
2888            sigstr = ' sig   :'
2889            iFin = min(iBeg+9,len(insKeys))
2890            for name in insKeys[iBeg:iFin]:
2891                if name not in  ['Type','Lam1','Lam2','Azimuth','Source','fltPath']:
2892                    ptlbls += '%12s' % (name)
2893                    ptstr += '%12.6f' % (Inst[name][1])
2894                    if instSig[name]:
2895                        refine = True
2896                        sigstr += '%12.6f' % (instSig[name])
2897                    else:
2898                        sigstr += 12*' '
2899            if refine:
2900                print >>pFile,'\n Instrument Parameters:'
2901                print >>pFile,ptlbls
2902                print >>pFile,ptstr
2903                print >>pFile,sigstr
2904            iBeg = iFin
2905            if iBeg == len(insKeys):
2906                Ok = False
2907       
2908    def PrintSampleParmsSig(Sample,sampleSig):
2909        ptlbls = ' names :'
2910        ptstr =  ' values:'
2911        sigstr = ' sig   :'
2912        refine = False
2913        if 'Bragg' in Sample['Type']:
2914            for i,item in enumerate(['Scale','Shift','Transparency','SurfRoughA','SurfRoughB']):
2915                ptlbls += '%14s'%(item)
2916                ptstr += '%14.4f'%(Sample[item][0])
2917                if sampleSig[i]:
2918                    refine = True
2919                    sigstr += '%14.4f'%(sampleSig[i])
2920                else:
2921                    sigstr += 14*' '
2922           
2923        elif 'Debye' in Sample['Type']:        #Debye-Scherrer
2924            for i,item in enumerate(['Scale','Absorption','DisplaceX','DisplaceY']):
2925                ptlbls += '%14s'%(item)
2926                ptstr += '%14.4f'%(Sample[item][0])
2927                if sampleSig[i]:
2928                    refine = True
2929                    sigstr += '%14.4f'%(sampleSig[i])
2930                else:
2931                    sigstr += 14*' '
2932
2933        if refine:
2934            print >>pFile,'\n Sample Parameters:'
2935            print >>pFile,ptlbls
2936            print >>pFile,ptstr
2937            print >>pFile,sigstr
2938       
2939    histoList = Histograms.keys()
2940    histoList.sort()
2941    for histogram in histoList:
2942        if 'PWDR' in histogram:
2943            Histogram = Histograms[histogram]
2944            hId = Histogram['hId']
2945            pfx = ':'+str(hId)+':'
2946            Background = Histogram['Background']
2947            backSig = SetBackgroundParms(pfx,Background,parmDict,sigDict)
2948           
2949            Inst = Histogram['Instrument Parameters'][0]
2950            instSig = SetInstParms(pfx,Inst,parmDict,sigDict)
2951       
2952            Sample = Histogram['Sample Parameters']
2953            sampSig = SetSampleParms(pfx,Sample,parmDict,sigDict)
2954
2955            print >>pFile,'\n Histogram: ',histogram,' histogram Id: ',hId
2956            print >>pFile,135*'-'
2957            print >>pFile,' PWDR histogram weight factor = '+'%.3f'%(Histogram['wtFactor'])
2958            print >>pFile,' Final refinement wR = %.2f%% on %d observations in this histogram'%(Histogram['Residuals']['wR'],Histogram['Residuals']['Nobs'])
2959            print >>pFile,' Other residuals: R = %.2f%%, Rb = %.2f%%, wRb = %.2f%% wRmin = %.2f%%'% \
2960                (Histogram['Residuals']['R'],Histogram['Residuals']['Rb'],Histogram['Residuals']['wRb'],Histogram['Residuals']['wRmin'])
2961            if Print:
2962                print >>pFile,' Instrument type: ',Sample['Type']
2963                PrintSampleParmsSig(Sample,sampSig)
2964                PrintInstParmsSig(Inst,instSig)
2965                PrintBackgroundSig(Background,backSig)
2966               
Note: See TracBrowser for help on using the repository browser.