source: trunk/GSASIIstrIO.py @ 1777

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

fixes to SH texture penalty fxn

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