source: trunk/GSASIIstruct.py @ 384

Last change on this file since 384 was 384, checked in by vondreele, 12 years ago

add constraint & restraint items to tree - now empty
fix noncentro calcs & special position position refinements

  • Property svn:keywords set to Date Author Revision URL Id
File size: 90.6 KB
Line 
1#GSASIIstructure - structure computation routines
2########### SVN repository information ###################
3# $Date: 2011-10-07 18:12:38 +0000 (Fri, 07 Oct 2011) $
4# $Author: vondreele $
5# $Revision: 384 $
6# $URL: trunk/GSASIIstruct.py $
7# $Id: GSASIIstruct.py 384 2011-10-07 18:12:38Z vondreele $
8########### SVN repository information ###################
9import sys
10import os
11import os.path as ospath
12import numpy as np
13import numpy.linalg as nl
14import cPickle
15import time
16import math
17import GSASIIpath
18import GSASIIElem as G2el
19import GSASIIlattice as G2lat
20import GSASIIspc as G2spc
21import GSASIIpwd as G2pwd
22import GSASIImapvars as G2mv
23import scipy.optimize as so
24
25sind = lambda x: np.sin(x*np.pi/180.)
26cosd = lambda x: np.cos(x*np.pi/180.)
27tand = lambda x: np.tan(x*np.pi/180.)
28asind = lambda x: 180.*np.arcsin(x)/np.pi
29atan2d = lambda y,x: 180.*np.arctan2(y,x)/np.pi
30
31
32def ShowBanner():
33    print 80*'*'
34    print '   General Structure Analysis System-II Crystal Structure Refinement'
35    print '     by Robert B. Von Dreele, Argonne National Laboratory(C), 2010'
36    print ' This product includes software developed by the UChicago Argonne, LLC,' 
37    print '            as Operator of Argonne National Laboratory.'
38    print 80*'*','\n'
39
40def GetControls(GPXfile):
41    ''' Returns dictionary of control items found in GSASII gpx file
42    input:
43        GPXfile = .gpx full file name
44    return:
45        Controls = dictionary of control items
46    '''
47    Controls = {'deriv type':'analytical','min dM/M':0.0001,'shift factor':1.}
48    file = open(GPXfile,'rb')
49    while True:
50        try:
51            data = cPickle.load(file)
52        except EOFError:
53            break
54        datum = data[0]
55        if datum[0] == 'Controls':
56            Controls.update(datum[1])
57    file.close()
58    return Controls
59   
60def ShowControls(Controls):
61    print ' Least squares controls:'
62    print ' Derivative type: ',Controls['deriv type']
63    print ' Minimum delta-M/M for convergence: ','%.2g'%(Controls['min dM/M'])
64    print ' Initial shift factor: ','%.3f'%(Controls['shift factor'])
65   
66def GetPhaseNames(GPXfile):
67    ''' Returns a list of phase names found under 'Phases' in GSASII gpx file
68    input:
69        GPXfile = gpx full file name
70    return:
71        PhaseNames = list of phase names
72    '''
73    file = open(GPXfile,'rb')
74    PhaseNames = []
75    while True:
76        try:
77            data = cPickle.load(file)
78        except EOFError:
79            break
80        datum = data[0]
81        if 'Phases' == datum[0]:
82            for datus in data[1:]:
83                PhaseNames.append(datus[0])
84    file.close()
85    return PhaseNames
86
87def GetAllPhaseData(GPXfile,PhaseName):
88    ''' Returns the entire dictionary for PhaseName from GSASII gpx file
89    input:
90        GPXfile = gpx full file name
91        PhaseName = phase name
92    return:
93        phase dictionary
94    '''       
95    file = open(GPXfile,'rb')
96    General = {}
97    Atoms = []
98    while True:
99        try:
100            data = cPickle.load(file)
101        except EOFError:
102            break
103        datum = data[0]
104        if 'Phases' == datum[0]:
105            for datus in data[1:]:
106                if datus[0] == PhaseName:
107                    break
108    file.close()
109    return datus[1]
110   
111def GetHistogramNames(GPXfile):
112    ''' Returns a list of histogram names found in GSASII gpx file
113    input:
114        GPXfile = .gpx full file name
115    return:
116        HistogramNames = list of histogram names (types = PWDR & HKLF)
117    '''
118    file = open(GPXfile,'rb')
119    HistogramNames = []
120    while True:
121        try:
122            data = cPickle.load(file)
123        except EOFError:
124            break
125        datum = data[0]
126        if datum[0][:4] in ['PWDR','HKLF']:
127            HistogramNames.append(datum[0])
128    file.close()
129    return HistogramNames
130   
131def GetUsedHistogramsAndPhases(GPXfile):
132    ''' Returns all histograms that are found in any phase
133    and any phase that uses a histogram
134    input:
135        GPXfile = .gpx full file name
136    return:
137        Histograms = dictionary of histograms as {name:data,...}
138        Phases = dictionary of phases that use histograms
139    '''
140    phaseNames = GetPhaseNames(GPXfile)
141    phaseData = {}
142    for name in phaseNames: 
143        phaseData[name] =  GetAllPhaseData(GPXfile,name)
144    Histograms = {}
145    Phases = {}
146    pId = 0
147    hId = 0
148    for phase in phaseData:
149        Phase = phaseData[phase]
150        if Phase['Histograms']:
151            if phase not in Phases:
152                Phase['pId'] = pId
153                pId += 1
154                Phases[phase] = Phase
155            for hist in Phase['Histograms']:
156                if hist not in Histograms:
157                    if 'PWDR' in hist[:4]: 
158                        Histograms[hist] = GetPWDRdata(GPXfile,hist)
159                    elif 'HKLF' in hist[:4]:
160                        Histograms[hist] = GetHKLFdata(GPXfile,hist)
161                    #future restraint, etc. histograms here           
162                    Histograms[hist]['hId'] = hId
163                    hId += 1
164    return Histograms,Phases
165   
166def SetUsedHistogramsAndPhases(GPXfile,Histograms,Phases,CovData):
167    ''' Updates gpxfile from all histograms that are found in any phase
168    and any phase that used a histogram
169    input:
170        GPXfile = .gpx full file name
171        Histograms = dictionary of histograms as {name:data,...}
172        Phases = dictionary of phases that use histograms
173        CovData = dictionary of refined variables, varyList, & covariance matrix
174    '''
175                       
176    def GPXBackup(GPXfile):
177        import distutils.file_util as dfu
178        GPXpath,GPXname = ospath.split(GPXfile)
179        Name = ospath.splitext(GPXname)[0]
180        files = os.listdir(GPXpath)
181        last = 0
182        for name in files:
183            name = name.split('.')
184            if len(name) == 3 and name[0] == Name and 'bak' in name[1]:
185                last = max(last,int(name[1].strip('bak'))+1)
186        GPXback = ospath.join(GPXpath,ospath.splitext(GPXname)[0]+'.bak'+str(last)+'.gpx')
187        dfu.copy_file(GPXfile,GPXback)
188        return GPXback
189       
190    GPXback = GPXBackup(GPXfile)
191    print '\n',130*'-'
192    print 'Read from file:',GPXback
193    print 'Save to file  :',GPXfile
194    infile = open(GPXback,'rb')
195    outfile = open(GPXfile,'wb')
196    while True:
197        try:
198            data = cPickle.load(infile)
199        except EOFError:
200            break
201        datum = data[0]
202        print 'read: ',datum[0]
203        if datum[0] == 'Phases':
204            for iphase in range(len(data)):
205                if data[iphase][0] in Phases:
206                    phaseName = data[iphase][0]
207                    data[iphase][1] = Phases[phaseName]
208        elif datum[0] == 'Covariance':
209            data[0][1] = CovData
210        try:
211            histogram = Histograms[datum[0]]
212            print 'found ',datum[0]
213            data[0][1][1] = histogram['Data']
214            for datus in data[1:]:
215                print '    read: ',datus[0]
216                if datus[0] in ['Background','Instrument Parameters','Sample Parameters','Reflection Lists']:
217                    datus[1] = histogram[datus[0]]
218        except KeyError:
219            pass
220                               
221        cPickle.dump(data,outfile,1)
222    infile.close()
223    outfile.close()
224    print 'refinement save successful'
225                   
226def GetPWDRdata(GPXfile,PWDRname):
227    ''' Returns powder data from GSASII gpx file
228    input:
229        GPXfile = .gpx full file name
230        PWDRname = powder histogram name as obtained from GetHistogramNames
231    return:
232        PWDRdata = powder data dictionary with:
233            Data - powder data arrays, Limits, Instrument Parameters, Sample Parameters
234       
235    '''
236    file = open(GPXfile,'rb')
237    PWDRdata = {}
238    while True:
239        try:
240            data = cPickle.load(file)
241        except EOFError:
242            break
243        datum = data[0]
244        if datum[0] == PWDRname:
245            PWDRdata['Data'] = datum[1][1]          #powder data arrays
246            PWDRdata[data[2][0]] = data[2][1]       #Limits
247            PWDRdata[data[3][0]] = data[3][1]       #Background
248            PWDRdata[data[4][0]] = data[4][1]       #Instrument parameters
249            PWDRdata[data[5][0]] = data[5][1]       #Sample parameters
250            try:
251                PWDRdata[data[9][0]] = data[9][1]       #Reflection lists might be missing
252            except IndexError:
253                PWDRdata['Reflection lists'] = {}
254    file.close()
255    return PWDRdata
256   
257def GetHKLFdata(GPXfile,HKLFname):
258    ''' Returns single crystal data from GSASII gpx file
259    input:
260        GPXfile = .gpx full file name
261        HKLFname = single crystal histogram name as obtained from GetHistogramNames
262    return:
263        HKLFdata = single crystal data list of reflections: for each reflection:
264            HKLF = [np.array([h,k,l]),FoSq,sigFoSq,FcSq,Fcp,Fcpp,phase]
265    '''
266    file = open(GPXfile,'rb')
267    HKLFdata = []
268    while True:
269        try:
270            data = cPickle.load(file)
271        except EOFError:
272            break
273        datum = data[0]
274        if datum[0] == HKLFname:
275            HKLFdata = datum[1:][0]
276    file.close()
277    return HKLFdata
278   
279def GetFFtable(General):
280    ''' returns a dictionary of form factor data for atom types found in General
281    input:
282        General = dictionary of phase info.; includes AtomTypes
283    return:
284        FFtable = dictionary of form factor data; key is atom type
285    '''
286    atomTypes = General['AtomTypes']
287    FFtable = {}
288    for El in atomTypes:
289        FFs = G2el.GetFormFactorCoeff(El.split('+')[0].split('-')[0])
290        for item in FFs:
291            if item['Symbol'] == El.upper():
292                FFtable[El] = item
293    return FFtable
294   
295def GetPawleyConstr(SGLaue,PawleyRef,pawleyVary):
296    if SGLaue in ['-1','2/m','mmm']:
297        return                      #no Pawley symmetry required constraints
298    for i,varyI in enumerate(pawleyVary):
299        refI = int(varyI.split(':')[-1])
300        ih,ik,il = PawleyRef[refI][:3]
301        for varyJ in pawleyVary[0:i]:
302            refJ = int(varyJ.split(':')[-1])
303            jh,jk,jl = PawleyRef[refJ][:3]
304            if SGLaue in ['4/m','4/mmm']:
305                isum = ih**2+ik**2
306                jsum = jh**2+jk**2
307                if abs(il) == abs(jl) and isum == jsum:
308                    G2mv.StoreEquivalence(varyJ,(varyI,))
309            elif SGLaue in ['3R','3mR']:
310                isum = ih**2+ik**2+il**2
311                jsum = jh**2+jk**2*jl**2
312                isum2 = ih*ik+ih*il+ik*il
313                jsum2 = jh*jk+jh*jl+jk*jl
314                if isum == jsum and isum2 == jsum2:
315                    G2mv.StoreEquivalence(varyJ,(varyI,))
316            elif SGLaue in ['3','3m1','31m','6/m','6/mmm']:
317                isum = ih**2+ik**2+ih*ik
318                jsum = jh**2+jk**2+jh*jk
319                if abs(il) == abs(jl) and isum == jsum:
320                    G2mv.StoreEquivalence(varyJ,(varyI,))
321            elif SGLaue in ['m3','m3m']:
322                isum = ih**2+ik**2+il**2
323                jsum = jh**2+jk**2+jl**2
324                if isum == jsum:
325                    G2mv.StoreEquivalence(varyJ,(varyI,))
326                   
327def cellVary(pfx,SGData): 
328    if SGData['SGLaue'] in ['-1',]:
329        return [pfx+'A0',pfx+'A1',pfx+'A2',pfx+'A3',pfx+'A4',pfx+'A5']
330    elif SGData['SGLaue'] in ['2/m',]:
331        if SGData['SGUniq'] == 'a':
332            return [pfx+'A0',pfx+'A1',pfx+'A2',pfx+'A3']
333        elif SGData['SGUniq'] == 'b':
334            return [pfx+'A0',pfx+'A1',pfx+'A2',pfx+'A4']
335        else:
336            return [pfx+'A0',pfx+'A1',pfx+'A2',pfx+'A5']
337    elif SGData['SGLaue'] in ['mmm',]:
338        return [pfx+'A0',pfx+'A1',pfx+'A2']
339    elif SGData['SGLaue'] in ['4/m','4/mmm']:
340        return [pfx+'A0',pfx+'A2']
341    elif SGData['SGLaue'] in ['6/m','6/mmm','3m1', '31m', '3']:
342        return [pfx+'A0',pfx+'A2']
343    elif SGData['SGLaue'] in ['3R', '3mR']:
344        return [pfx+'A0',pfx+'A3']                       
345    elif SGData['SGLaue'] in ['m3m','m3']:
346        return [pfx+'A0',]
347       
348           
349def GetPhaseData(PhaseData,Print=True):
350           
351    def PrintFFtable(FFtable):
352        print '\n Scattering factors:'
353        print '   Symbol     fa                                      fb                                      fc'
354        print 99*'-'
355        for Ename in FFtable:
356            ffdata = FFtable[Ename]
357            fa = ffdata['fa']
358            fb = ffdata['fb']
359            print ' %8s %9.5f %9.5f %9.5f %9.5f %9.5f %9.5f %9.5f %9.5f %9.5f' %  \
360                (Ename.ljust(8),fa[0],fa[1],fa[2],fa[3],fb[0],fb[1],fb[2],fb[3],ffdata['fc'])
361               
362    def PrintAtoms(General,Atoms):
363        print '\n Atoms:'
364        line = '   name    type  refine?   x         y         z    '+ \
365            '  frac site sym  mult I/A   Uiso     U11     U22     U33     U12     U13     U23'
366        if General['Type'] == 'magnetic':
367            line += '   Mx     My     Mz'
368        elif General['Type'] == 'macromolecular':
369            line = ' res no  residue  chain '+line
370        print line
371        if General['Type'] == 'nuclear':
372            print 135*'-'
373            for i,at in enumerate(Atoms):
374                line = '%7s'%(at[0])+'%7s'%(at[1])+'%7s'%(at[2])+'%10.5f'%(at[3])+'%10.5f'%(at[4])+ \
375                    '%10.5f'%(at[5])+'%8.3f'%(at[6])+'%7s'%(at[7])+'%5d'%(at[8])+'%5s'%(at[9])
376                if at[9] == 'I':
377                    line += '%8.4f'%(at[10])+48*' '
378                else:
379                    line += 8*' '
380                    for j in range(6):
381                        line += '%8.4f'%(at[11+j])
382                print line
383       
384       
385    if Print: print ' Phases:'
386    phaseVary = []
387    phaseDict = {}
388    phaseConstr = {}
389    pawleyLookup = {}
390    FFtables = {}
391    Natoms = {}
392    AtMults = {}
393    AtIA = {}
394    for name in PhaseData:
395        General = PhaseData[name]['General']
396        pId = PhaseData[name]['pId']
397        pfx = str(pId)+'::'
398        FFtable = GetFFtable(General)
399        FFtables.update(FFtable)
400        Atoms = PhaseData[name]['Atoms']
401        try:
402            PawleyRef = PhaseData[name]['Pawley ref']
403        except KeyError:
404            PawleyRef = []
405        if Print: print '\n Phase name: ',General['Name']
406        SGData = General['SGData']
407        SGtext = G2spc.SGPrint(SGData)
408        if Print: 
409            for line in SGtext: print line
410        cell = General['Cell']
411        A = G2lat.cell2A(cell[1:7])
412        phaseDict.update({pfx+'A0':A[0],pfx+'A1':A[1],pfx+'A2':A[2],pfx+'A3':A[3],pfx+'A4':A[4],pfx+'A5':A[5]})
413        if cell[0]:
414            phaseVary += cellVary(pfx,SGData)
415        if Print: print '\n Unit cell: a =','%.5f'%(cell[1]),' b =','%.5f'%(cell[2]),' c =','%.5f'%(cell[3]), \
416            ' alpha =','%.3f'%(cell[4]),' beta =','%.3f'%(cell[5]),' gamma =', \
417            '%.3f'%(cell[6]),' volume =','%.3f'%(cell[7]),' Refine?',cell[0]
418        if Print and FFtable:
419            PrintFFtable(FFtable)
420        Natoms[pfx] = 0
421        if Atoms:
422            if General['Type'] == 'nuclear':
423                Natoms[pfx] = len(Atoms)
424                for i,at in enumerate(Atoms):
425                    phaseDict.update({pfx+'Atype:'+str(i):at[1],pfx+'Afrac:'+str(i):at[6],pfx+'Amul:'+str(i):at[8],
426                        pfx+'Ax:'+str(i):at[3],pfx+'Ay:'+str(i):at[4],pfx+'Az:'+str(i):at[5],
427                        pfx+'dAx:'+str(i):0.,pfx+'dAy:'+str(i):0.,pfx+'dAz:'+str(i):0.,         #refined shifts for x,y,z
428                        pfx+'AI/A:'+str(i):at[9],})
429                    if at[9] == 'I':
430                        phaseDict[pfx+'AUiso:'+str(i)] = at[10]
431                    else:
432                        phaseDict.update({pfx+'AU11:'+str(i):at[11],pfx+'AU22:'+str(i):at[12],pfx+'AU33:'+str(i):at[13],
433                            pfx+'AU12:'+str(i):at[14],pfx+'AU13:'+str(i):at[15],pfx+'AU23:'+str(i):at[16]})
434                    if 'F' in at[2]:
435                        phaseVary.append(pfx+'Afrac:'+str(i))
436                    if 'X' in at[2]:
437                        xId,xCoef = G2spc.GetCSxinel(at[7])
438                        delnames = [pfx+'dAx:'+str(i),pfx+'dAy:'+str(i),pfx+'dAz:'+str(i)]
439                        for j in range(3):
440                            if xId[j] > 0:                               
441                                phaseVary.append(delnames[j])
442                                for k in range(j):
443                                    if xId[j] == xId[k]:
444                                        G2mv.StoreEquivalence(delnames[k],((delnames[j],xCoef[j]),)) 
445                    if 'U' in at[2]:
446                        if at[9] == 'I':
447                            phaseVary.append(pfx+'AUiso:'+str(i))
448                        else:
449                            uId,uCoef = G2spc.GetCSuinel(at[7])[:2]
450                            names = [pfx+'AU11:'+str(i),pfx+'AU22:'+str(i),pfx+'AU33:'+str(i),
451                                pfx+'AU12:'+str(i),pfx+'AU13:'+str(i),pfx+'AU23:'+str(i)]
452                            for j in range(6):
453                                if uId[j] > 0:                               
454                                    phaseVary.append(names[j])
455                                    for k in range(j):
456                                        if uId[j] == uId[k]:
457                                            G2mv.StoreEquivalence(names[k],((names[j],uCoef[j]),))
458            if Print:
459                PrintAtoms(General,Atoms)
460#        elif General['Type'] == 'magnetic':
461#        elif General['Type'] == 'macromolecular':
462#       PWDR: harmonics texture
463        elif PawleyRef:
464            pawleyVary = []
465            for i,refl in enumerate(PawleyRef):
466                phaseDict[pfx+'PWLref:'+str(i)] = refl[6]
467                pawleyLookup[pfx+'%d,%d,%d'%(refl[0],refl[1],refl[2])] = i
468                if refl[5]:
469                    pawleyVary.append(pfx+'PWLref:'+str(i))
470            GetPawleyConstr(SGData['SGLaue'],PawleyRef,pawleyVary)      #does G2mv.StoreEquivalence
471            phaseVary += pawleyVary
472               
473    return Natoms,phaseVary,phaseDict,pawleyLookup,FFtables
474   
475def SetPhaseData(parmDict,sigDict,Phases):
476   
477    def cellFill(pfx,SGData,parmDict,sigDict): 
478        if SGData['SGLaue'] in ['-1',]:
479            A = [parmDict[pfx+'A0'],parmDict[pfx+'A1'],parmDict[pfx+'A2'],
480                parmDict[pfx+'A3'],parmDict[pfx+'A4'],parmDict[pfx+'A5']]
481            sigA = [sigDict[pfx+'A0'],sigDict[pfx+'A1'],sigDict[pfx+'A2'],
482                sigDict[pfx+'A3'],sigDict[pfx+'A4'],sigDict[pfx+'A5']]
483        elif SGData['SGLaue'] in ['2/m',]:
484            if SGData['SGUniq'] == 'a':
485                A = [parmDict[pfx+'A0'],parmDict[pfx+'A1'],parmDict[pfx+'A2'],
486                    parmDict[pfx+'A3'],0,0]
487                sigA = [sigDict[pfx+'A0'],sigDict[pfx+'A1'],sigDict[pfx+'A2'],
488                    sigDict[pfx+'A3'],0,0]
489            elif SGData['SGUniq'] == 'b':
490                A = [parmDict[pfx+'A0'],parmDict[pfx+'A1'],parmDict[pfx+'A2'],
491                    0,parmDict[pfx+'A4'],0]
492                sigA = [sigDict[pfx+'A0'],sigDict[pfx+'A1'],sigDict[pfx+'A2'],
493                    0,sigDict[pfx+'A4'],0]
494            else:
495                A = [parmDict[pfx+'A0'],parmDict[pfx+'A1'],parmDict[pfx+'A2'],
496                    0,0,parmDict[pfx+'A5']]
497                sigA = [sigDict[pfx+'A0'],sigDict[pfx+'A1'],sigDict[pfx+'A2'],
498                    0,0,sigDict[pfx+'A5']]
499        elif SGData['SGLaue'] in ['mmm',]:
500            A = [parmDict[pfx+'A0'],parmDict[pfx+'A1'],parmDict[pfx+'A2'],0,0,0]
501            sigA = [sigDict[pfx+'A0'],sigDict[pfx+'A1'],sigDict[pfx+'A2'],0,0,0]
502        elif SGData['SGLaue'] in ['4/m','4/mmm']:
503            A = [parmDict[pfx+'A0'],parmDict[pfx+'A0'],parmDict[pfx+'A2'],0,0,0]
504            sigA = [sigDict[pfx+'A0'],0,sigDict[pfx+'A2'],0,0,0]
505        elif SGData['SGLaue'] in ['6/m','6/mmm','3m1', '31m', '3']:
506            A = [parmDict[pfx+'A0'],parmDict[pfx+'A0'],parmDict[pfx+'A2'],
507                parmDict[pfx+'A0'],0,0]
508            sigA = [sigDict[pfx+'A0'],0,sigDict[pfx+'A2'],0,0,0]
509        elif SGData['SGLaue'] in ['3R', '3mR']:
510            A = [parmDict[pfx+'A0'],parmDict[pfx+'A0'],parmDict[pfx+'A0'],
511                parmDict[pfx+'A3'],parmDict[pfx+'A3'],parmDict[pfx+'A3']]
512            sigA = [sigDict[pfx+'A0'],0,0,sigDict[pfx+'A3'],0,0]
513        elif SGData['SGLaue'] in ['m3m','m3']:
514            A = [parmDict[pfx+'A0'],parmDict[pfx+'A0'],parmDict[pfx+'A0'],0,0,0]
515            sigA = [sigDict[pfx+'A0'],0,0,0,0,0]
516        return A,sigA
517       
518    def PrintAtomsAndSig(General,Atoms,atomsSig):
519        print '\n Atoms:'
520        line = '   name      x         y         z      frac   Uiso     U11     U22     U33     U12     U13     U23'
521        if General['Type'] == 'magnetic':
522            line += '   Mx     My     Mz'
523        elif General['Type'] == 'macromolecular':
524            line = ' res no  residue  chain '+line
525        print line
526        if General['Type'] == 'nuclear':
527            print 135*'-'
528            fmt = {0:'%7s',1:'%7s',3:'%10.5f',4:'%10.5f',5:'%10.5f',6:'%8.3f',10:'%8.5f',
529                11:'%8.5f',12:'%8.5f',13:'%8.5f',14:'%8.5f',15:'%8.5f',16:'%8.5f'}
530            noFXsig = {3:[10*' ','%10s'],4:[10*' ','%10s'],5:[10*' ','%10s'],6:[8*' ','%8s']}
531            for i,at in enumerate(Atoms):
532                name = fmt[0]%(at[0])+fmt[1]%(at[1])+':'
533                valstr = ' values:'
534                sigstr = ' sig   :'
535                for ind in [3,4,5,6]:
536                    sigind = str(i)+':'+str(ind)
537                    valstr += fmt[ind]%(at[ind])                   
538                    if sigind in atomsSig:
539                        sigstr += fmt[ind]%(atomsSig[sigind])
540                    else:
541                        sigstr += noFXsig[ind][1]%(noFXsig[ind][0])
542                if at[9] == 'I':
543                    valstr += fmt[10]%(at[10])
544                    if str(i)+':10' in atomsSig:
545                        sigstr += fmt[10]%(atomsSig[str(i)+':10'])
546                    else:
547                        sigstr += 8*' '
548                else:
549                    valstr += 8*' '
550                    sigstr += 8*' '
551                    for ind in [11,12,13,14,15,16]:
552                        sigind = str(i)+':'+str(ind)
553                        valstr += fmt[ind]%(at[ind])
554                        if sigind in atomsSig:                       
555                            sigstr += fmt[ind]%(atomsSig[sigind])
556                        else:
557                            sigstr += 8*' '
558                print name
559                print valstr
560                print sigstr
561           
562    print '\n Phases:'
563    for phase in Phases:
564        print ' Result for phase: ',phase
565        Phase = Phases[phase]
566        General = Phase['General']
567        SGData = General['SGData']
568        Atoms = Phase['Atoms']
569        cell = General['Cell']
570        pId = Phase['pId']
571        pfx = str(pId)+'::'
572        if cell[0]:
573            A,sigA = cellFill(pfx,SGData,parmDict,sigDict)
574            print ' Reciprocal metric tensor: '
575            ptfmt = "%15.9f"
576            names = ['A11','A22','A33','A12','A13','A23']
577            namstr = '  names :'
578            ptstr =  '  values:'
579            sigstr = '  esds  :'
580            for name,a,siga in zip(names,A,sigA):
581                namstr += '%15s'%(name)
582                ptstr += ptfmt%(a)
583                if siga:
584                    sigstr += ptfmt%(siga)
585                else:
586                    sigstr += 15*' '
587            print namstr
588            print ptstr
589            print sigstr
590            cell[1:7] = G2lat.A2cell(A)
591            cell[7] = G2lat.calc_V(A)
592            print ' New unit cell: a = %.5f'%(cell[1]),' b = %.5f'%(cell[2]), \
593                ' c = %.5f'%(cell[3]),' alpha = %.3f'%(cell[4]),' beta = %.3f'%(cell[5]), \
594                ' gamma = %.3f'%(cell[6]),' volume = %.3f'%(cell[7])
595        if 'Pawley' in Phase['General']['Type']:
596            pawleyRef = Phase['Pawley ref']
597            for i,refl in enumerate(pawleyRef):
598                key = pfx+'PWLref:'+str(i)
599                refl[6] = abs(parmDict[key])        #suppress negative Fsq
600                if key in sigDict:
601                    refl[7] = sigDict[key]
602                else:
603                    refl[7] = 0
604        else:
605            atomsSig = {}
606            if General['Type'] == 'nuclear':
607                for i,at in enumerate(Atoms):
608                    names = {3:pfx+'Ax:'+str(i),4:pfx+'Ay:'+str(i),5:pfx+'Az:'+str(i),6:pfx+'Afrac:'+str(i),
609                        10:pfx+'AUiso:'+str(i),11:pfx+'AU11:'+str(i),12:pfx+'AU22:'+str(i),13:pfx+'AU33:'+str(i),
610                        14:pfx+'AU12:'+str(i),15:pfx+'AU13:'+str(i),16:pfx+'AU23:'+str(i)}
611                    for ind in [3,4,5,6]:
612                        at[ind] = parmDict[names[ind]]
613                        if ind in [3,4,5]:
614                            name = names[ind].replace('A','dA')
615                        else:
616                            name = names[ind]
617                        if name in sigDict:
618                            atomsSig[str(i)+':'+str(ind)] = sigDict[name]
619                    if at[9] == 'I':
620                        at[10] = parmDict[names[10]]
621                        if names[10] in sigDict:
622                            atomsSig[str(i)+':10'] = sigDict[names[10]]
623                    else:
624                        for ind in [11,12,13,14,15,16]:
625                            at[ind] = parmDict[names[ind]]
626                            if names[ind] in sigDict:
627                                atomsSig[str(i)+':'+str(ind)] = sigDict[names[ind]]
628            PrintAtomsAndSig(General,Atoms,atomsSig)   
629
630def GetHistogramPhaseData(Phases,Histograms,Print=True):
631   
632    def PrintSize(hapData):
633        line = '\n Size model    : '+hapData[0]
634        if hapData[0] in ['isotropic','uniaxial']:
635            line += ' equatorial:'+'%12.3f'%(hapData[1][0])+' Refine? '+str(hapData[2][0])
636            if hapData[0] == 'uniaxial':
637                line += ' axial:'+'%12.3f'%(hapData[1][1])+' Refine? '+str(hapData[2][1])
638            print line
639        else:
640            print line
641            Snames = ['S11','S22','S33','S12','S13','S23']
642            ptlbls = ' names :'
643            ptstr =  ' values:'
644            varstr = ' refine:'
645            for i,name in enumerate(Snames):
646                ptlbls += '%12s' % (name)
647                ptstr += '%12.6f' % (hapData[4][i])
648                varstr += '%12s' % (str(hapData[5][i]))
649            print ptlbls
650            print ptstr
651            print varstr
652       
653    def PrintMuStrain(hapData,SGData):
654        line = '\n Mustrain model: '+hapData[0]
655        if hapData[0] in ['isotropic','uniaxial']:
656            line += ' equatorial:'+'%12.1f'%(hapData[1][0])+' Refine? '+str(hapData[2][0])
657            if hapData[0] == 'uniaxial':
658                line += ' axial:'+'%12.1f'%(hapData[1][1])+' Refine? '+str(hapData[2][1])
659            print line
660        else:
661            print line
662            Snames = G2spc.MustrainNames(SGData)
663            ptlbls = ' names :'
664            ptstr =  ' values:'
665            varstr = ' refine:'
666            for i,name in enumerate(Snames):
667                ptlbls += '%12s' % (name)
668                ptstr += '%12.6f' % (hapData[4][i])
669                varstr += '%12s' % (str(hapData[5][i]))
670            print ptlbls
671            print ptstr
672            print varstr
673
674    def PrintHStrain(hapData,SGData):
675        print '\n Hydrostatic strain: '
676        Hsnames = G2spc.HStrainNames(SGData)
677        ptlbls = ' names :'
678        ptstr =  ' values:'
679        varstr = ' refine:'
680        for i,name in enumerate(Hsnames):
681            ptlbls += '%12s' % (name)
682            ptstr += '%12.6f' % (hapData[0][i])
683            varstr += '%12s' % (str(hapData[1][i]))
684        print ptlbls
685        print ptstr
686        print varstr
687
688    def PrintSHPO(hapData):
689        print '\n Spherical harmonics preferred orientation: Order:' + \
690            str(hapData[4])+' Refine? '+str(hapData[2])
691        ptlbls = ' names :'
692        ptstr =  ' values:'
693        for item in hapData[5]:
694            ptlbls += '%12s'%(item)
695            ptstr += '%12.4f'%(hapData[5][item]) 
696        print ptlbls
697        print ptstr
698   
699    hapDict = {}
700    hapVary = []
701    controlDict = {}
702    poType = {}
703    poAxes = {}
704    spAxes = {}
705    spType = {}
706   
707    for phase in Phases:
708        HistoPhase = Phases[phase]['Histograms']
709        SGData = Phases[phase]['General']['SGData']
710        cell = Phases[phase]['General']['Cell'][1:7]
711        A = G2lat.cell2A(cell)
712        pId = Phases[phase]['pId']
713        for histogram in HistoPhase:
714            hapData = HistoPhase[histogram]
715            Histogram = Histograms[histogram]
716            hId = Histogram['hId']
717            limits = Histogram['Limits'][1]
718            inst = Histogram['Instrument Parameters']
719            inst = dict(zip(inst[3],inst[1]))
720            Zero = inst['Zero']
721            if 'C' in inst['Type']:
722                try:
723                    wave = inst['Lam']
724                except KeyError:
725                    wave = inst['Lam1']
726                dmin = wave/(2.0*sind(limits[1]/2.0))
727            pfx = str(pId)+':'+str(hId)+':'
728            for item in ['Scale','Extinction']:
729                hapDict[pfx+item] = hapData[item][0]
730                if hapData[item][1]:
731                    hapVary.append(pfx+item)
732            names = G2spc.HStrainNames(SGData)
733            for i,name in enumerate(names):
734                hapDict[pfx+name] = hapData['HStrain'][0][i]
735                if hapData['HStrain'][1][i]:
736                    hapVary.append(pfx+name)
737            controlDict[pfx+'poType'] = hapData['Pref.Ori.'][0]
738            if hapData['Pref.Ori.'][0] == 'MD':
739                hapDict[pfx+'MD'] = hapData['Pref.Ori.'][1]
740                controlDict[pfx+'MDAxis'] = hapData['Pref.Ori.'][3]
741                if hapData['Pref.Ori.'][2]:
742                    hapVary.append(pfx+'MD')
743            else:                           #'SH' spherical harmonics
744                controlDict[pfx+'SHord'] = hapData['Pref.Ori.'][4]
745                controlDict[pfx+'SHncof'] = len(hapData['Pref.Ori.'][5])
746                for item in hapData['Pref.Ori.'][5]:
747                    hapDict[pfx+item] = hapData['Pref.Ori.'][5][item]
748                    if hapData['Pref.Ori.'][2]:
749                        hapVary.append(pfx+item)
750            for item in ['Mustrain','Size']:
751                controlDict[pfx+item+'Type'] = hapData[item][0]
752                if hapData[item][0] in ['isotropic','uniaxial']:
753                    hapDict[pfx+item+':0'] = hapData[item][1][0]
754                    if hapData[item][2][0]:
755                        hapVary.append(pfx+item+':0')
756                    if hapData[item][0] == 'uniaxial':
757                        controlDict[pfx+item+'Axis'] = hapData[item][3]
758                        hapDict[pfx+item+':1'] = hapData[item][1][1]
759                        if hapData[item][2][1]:
760                            hapVary.append(pfx+item+':1')
761                else:       #generalized for mustrain or ellipsoidal for size
762                    if item == 'Mustrain':
763                        names = G2spc.MustrainNames(SGData)
764                        pwrs = []
765                        for name in names:
766                            h,k,l = name[1:]
767                            pwrs.append([int(h),int(k),int(l)])
768                        controlDict[pfx+'MuPwrs'] = pwrs
769                    for i in range(len(hapData[item][4])):
770                        sfx = ':'+str(i)
771                        hapDict[pfx+item+sfx] = hapData[item][4][i]
772                        if hapData[item][5][i]:
773                            hapVary.append(pfx+item+sfx)
774                           
775            if Print: 
776                print '\n Phase: ',phase,' in histogram: ',histogram
777                print '\n Phase fraction  : %10.4f'%(hapData['Scale'][0]),' Refine?',hapData['Scale'][1]
778                print ' Extinction coeff: %10.4f'%(hapData['Extinction'][0]),' Refine?',hapData['Extinction'][1]
779                if hapData['Pref.Ori.'][0] == 'MD':
780                    Ax = hapData['Pref.Ori.'][3]
781                    print ' March-Dollase PO: %10.4f'%(hapData['Pref.Ori.'][1]),' Refine?',hapData['Pref.Ori.'][2], \
782                        ' Axis: %d %d %d'%(Ax[0],Ax[1],Ax[2])
783                else: #'SH' for spherical harmonics
784                    PrintSHPO(hapData['Pref.Ori.'])
785                PrintSize(hapData['Size'])
786                PrintMuStrain(hapData['Mustrain'],SGData)
787                PrintHStrain(hapData['HStrain'],SGData)
788            HKLd = np.array(G2lat.GenHLaue(dmin,SGData,A))
789            refList = []
790            for h,k,l,d in HKLd:
791                ext,mul,Uniq,phi = G2spc.GenHKLf([h,k,l],SGData)
792                if ext:
793                    continue
794                if 'C' in inst['Type']:
795                    pos = 2.0*asind(wave/(2.0*d))
796                    if limits[0] < pos < limits[1]:
797                        refList.append([h,k,l,mul,d,pos,0.0,0.0,0.0,0.0,0.0,Uniq,phi])
798                else:
799                    raise ValueError 
800            Histogram['Reflection Lists'][phase] = refList
801    return hapVary,hapDict,controlDict
802   
803def SetHistogramPhaseData(parmDict,sigDict,Phases,Histograms):
804   
805    def PrintSizeAndSig(hapData,sizeSig):
806        line = '\n Size model:     '+hapData[0]
807        if hapData[0] in ['isotropic','uniaxial']:
808            line += ' equatorial:%12.3f'%(hapData[1][0])
809            if sizeSig[0][0]:
810                line += ', sig: %8.3f'%(sizeSig[0][0])
811            if hapData[0] == 'uniaxial':
812                line += ' axial:%12.3f'%(hapData[1][1])
813                if sizeSig[0][1]:
814                    line += ', sig: %8.3f'%(sizeSig[0][1])
815            print line
816        else:
817            print line
818            Snames = ['S11','S22','S33','S12','S13','S23']
819            ptlbls = ' name  :'
820            ptstr =  ' value :'
821            sigstr = ' sig   :'
822            for i,name in enumerate(Snames):
823                ptlbls += '%12s' % (name)
824                ptstr += '%12.6f' % (hapData[4][i])
825                if sizeSig[1][i]:
826                    sigstr += '%12.6f' % (sizeSig[1][i])
827                else:
828                    sigstr += 12*' '
829            print ptlbls
830            print ptstr
831            print sigstr
832       
833    def PrintMuStrainAndSig(hapData,mustrainSig,SGData):
834        line = '\n Mustrain model: '+hapData[0]
835        if hapData[0] in ['isotropic','uniaxial']:
836            line += ' equatorial:%12.1f'%(hapData[1][0])
837            if mustrainSig[0][0]:
838                line += ', sig: %8.1f'%(mustrainSig[0][0])
839            if hapData[0] == 'uniaxial':
840                line += ' axial:%12.1f'%(hapData[1][1])
841                if mustrainSig[0][1]:
842                     line += ', sig: %8.1f'%(mustrainSig[0][1])
843            print line
844        else:
845            print line
846            Snames = G2spc.MustrainNames(SGData)
847            ptlbls = ' name  :'
848            ptstr =  ' value :'
849            sigstr = ' sig   :'
850            for i,name in enumerate(Snames):
851                ptlbls += '%12s' % (name)
852                ptstr += '%12.6f' % (hapData[4][i])
853                if mustrainSig[1][i]:
854                    sigstr += '%12.6f' % (mustrainSig[1][i])
855                else:
856                    sigstr += 12*' '
857            print ptlbls
858            print ptstr
859            print sigstr
860           
861    def PrintHStrainAndSig(hapData,strainSig,SGData):
862        print '\n Hydrostatic strain: '
863        Hsnames = G2spc.HStrainNames(SGData)
864        ptlbls = ' name  :'
865        ptstr =  ' value :'
866        sigstr = ' sig   :'
867        for i,name in enumerate(Hsnames):
868            ptlbls += '%12s' % (name)
869            ptstr += '%12.6g' % (hapData[0][i])
870            if name in strainSig:
871                sigstr += '%12.6g' % (strainSig[name])
872            else:
873                sigstr += 12*' '
874        print ptlbls
875        print ptstr
876        print sigstr
877       
878    def PrintSHPOAndSig(hapData,POsig):
879        print '\n Spherical harmonics preferred orientation: Order:'+str(hapData[4])
880        ptlbls = ' names :'
881        ptstr =  ' values:'
882        sigstr = ' sig   :'
883        for item in hapData[5]:
884            ptlbls += '%12s'%(item)
885            ptstr += '%12.4f'%(hapData[5][item])
886            if item in POsig:
887                sigstr += '%12.4f'%(POsig[item])
888            else:
889                sigstr += 12*' ' 
890        print ptlbls
891        print ptstr
892        print sigstr
893   
894    for phase in Phases:
895        HistoPhase = Phases[phase]['Histograms']
896        SGData = Phases[phase]['General']['SGData']
897        pId = Phases[phase]['pId']
898        for histogram in HistoPhase:
899            print '\n Phase: ',phase,' in histogram: ',histogram
900            hapData = HistoPhase[histogram]
901            Histogram = Histograms[histogram]
902            hId = Histogram['hId']
903            pfx = str(pId)+':'+str(hId)+':'
904           
905            PhFrExtPOSig = {}
906            for item in ['Scale','Extinction']:
907                hapData[item][0] = parmDict[pfx+item]
908                if pfx+item in sigDict:
909                    PhFrExtPOSig[item] = sigDict[pfx+item]
910            if hapData['Pref.Ori.'][0] == 'MD':
911                hapData['Pref.Ori.'][1] = parmDict[pfx+'MD']
912                if pfx+'MD' in sigDict:
913                    PhFrExtPOSig['MD'] = sigDict[pfx+'MD']
914            else:                           #'SH' spherical harmonics
915                for item in hapData['Pref.Ori.'][5]:
916                    hapData['Pref.Ori.'][5][item] = parmDict[pfx+item]
917                    if pfx+item in sigDict:
918                        PhFrExtPOSig[item] = sigDict[pfx+item]
919            print '\n'
920            if 'Scale' in PhFrExtPOSig:
921                print ' Phase fraction  : %10.4f, sig %10.4f'%(hapData['Scale'][0],PhFrExtPOSig['Scale'])
922            if 'Extinction' in PhFrExtPOSig:
923                print ' Extinction coeff: %10.4f, sig %10.4f'%(hapData['Extinction'][0],PhFrExtPOSig['Extinction'])
924            if hapData['Pref.Ori.'][0] == 'MD':
925                if 'MD' in PhFrExtPOSig:
926                    print ' March-Dollase PO: %10.4f, sig %10.4f'%(hapData['Pref.Ori.'][1],PhFrExtPOSig['MD'])
927            else:
928                PrintSHPOAndSig(hapData['Pref.Ori.'],PhFrExtPOSig)
929            SizeMuStrSig = {'Mustrain':[[0,0],[0 for i in range(len(hapData['Mustrain'][4]))]],
930                'Size':[[0,0],[0 for i in range(len(hapData['Size'][4]))]],
931                'HStrain':{}}                 
932            for item in ['Mustrain','Size']:
933                if hapData[item][0] in ['isotropic','uniaxial']:                   
934                    hapData[item][1][0] = parmDict[pfx+item+':0']
935                    if item == 'Size':
936                        hapData[item][1][0] = min(10.,max(0.01,hapData[item][1][0]))
937                    if pfx+item+':0' in sigDict: 
938                        SizeMuStrSig[item][0][0] = sigDict[pfx+item+':0']
939                    if hapData[item][0] == 'uniaxial':
940                        hapData[item][1][1] = parmDict[pfx+item+':1']
941                        if item == 'Size':
942                            hapData[item][1][1] = min(10.,max(0.01,hapData[item][1][1]))                       
943                        if pfx+item+':1' in sigDict:
944                            SizeMuStrSig[item][0][1] = sigDict[pfx+item+':1']
945                else:       #generalized for mustrain or ellipsoidal for size
946                    for i in range(len(hapData[item][4])):
947                        sfx = ':'+str(i)
948                        hapData[item][4][i] = parmDict[pfx+item+sfx]
949                        if pfx+item+sfx in sigDict:
950                            SizeMuStrSig[item][1][i] = sigDict[pfx+item+sfx]
951            names = G2spc.HStrainNames(SGData)
952            for i,name in enumerate(names):
953                hapData['HStrain'][0][i] = parmDict[pfx+name]
954                if pfx+name in sigDict:
955                    SizeMuStrSig['HStrain'][name] = sigDict[pfx+name]
956            PrintSizeAndSig(hapData['Size'],SizeMuStrSig['Size'])
957            PrintMuStrainAndSig(hapData['Mustrain'],SizeMuStrSig['Mustrain'],SGData)
958            PrintHStrainAndSig(hapData['HStrain'],SizeMuStrSig['HStrain'],SGData)
959   
960def GetHistogramData(Histograms,Print=True):
961   
962    def GetBackgroundParms(hId,Background):
963        bakType,bakFlag = Background[:2]
964        backVals = Background[3:]
965        backNames = [':'+str(hId)+':Back:'+str(i) for i in range(len(backVals))]
966        if bakFlag:                                 #returns backNames as varyList = backNames
967            return bakType,dict(zip(backNames,backVals)),backNames
968        else:                                       #no background varied; varyList = []
969            return bakType,dict(zip(backNames,backVals)),[]
970       
971    def GetInstParms(hId,Inst):
972        insVals,insFlags,insNames = Inst[1:4]
973        dataType = insVals[0]
974        instDict = {}
975        insVary = []
976        pfx = ':'+str(hId)+':'
977        for i,flag in enumerate(insFlags):
978            insName = pfx+insNames[i]
979            instDict[insName] = insVals[i]
980            if flag:
981                insVary.append(insName)
982        instDict[pfx+'X'] = max(instDict[pfx+'X'],0.01)
983        instDict[pfx+'Y'] = max(instDict[pfx+'Y'],0.01)
984        instDict[pfx+'SH/L'] = max(instDict[pfx+'SH/L'],0.0005)
985        return dataType,instDict,insVary
986       
987    def GetSampleParms(hId,Sample):
988        sampVary = []
989        hfx = ':'+str(hId)+':'       
990        sampDict = {hfx+'Gonio. radius':Sample['Gonio. radius']}
991        Type = Sample['Type']
992        if 'Bragg' in Type:             #Bragg-Brentano
993            for item in ['Scale','Shift','Transparency']:       #surface roughness?, diffuse scattering?
994                sampDict[hfx+item] = Sample[item][0]
995                if Sample[item][1]:
996                    sampVary.append(hfx+item)
997        elif 'Debye' in Type:        #Debye-Scherrer
998            for item in ['Scale','Absorption','DisplaceX','DisplaceY']:
999                sampDict[hfx+item] = Sample[item][0]
1000                if Sample[item][1]:
1001                    sampVary.append(hfx+item)
1002        return Type,sampDict,sampVary
1003       
1004    def PrintBackground(Background):
1005        print '\n Background function: ',Background[0],' Refine?',bool(Background[1])
1006        line = ' Coefficients: '
1007        for i,back in enumerate(Background[3:]):
1008            line += '%10.3f'%(back)
1009            if i and not i%10:
1010                line += '\n'+15*' '
1011        print line
1012       
1013    def PrintInstParms(Inst):
1014        print '\n Instrument Parameters:'
1015        ptlbls = ' name  :'
1016        ptstr =  ' value :'
1017        varstr = ' refine:'
1018        instNames = Inst[3][1:]
1019        for i,name in enumerate(instNames):
1020            ptlbls += '%12s' % (name)
1021            ptstr += '%12.6f' % (Inst[1][i+1])
1022            if name in ['Lam1','Lam2','Azimuth']:
1023                varstr += 12*' '
1024            else:
1025                varstr += '%12s' % (str(bool(Inst[2][i+1])))
1026        print ptlbls
1027        print ptstr
1028        print varstr
1029       
1030    def PrintSampleParms(Sample):
1031        print '\n Sample Parameters:'
1032        ptlbls = ' name  :'
1033        ptstr =  ' value :'
1034        varstr = ' refine:'
1035        if 'Bragg' in Sample['Type']:
1036            for item in ['Scale','Shift','Transparency']:
1037                ptlbls += '%14s'%(item)
1038                ptstr += '%14.4f'%(Sample[item][0])
1039                varstr += '%14s'%(str(bool(Sample[item][1])))
1040           
1041        elif 'Debye' in Type:        #Debye-Scherrer
1042            for item in ['Scale','Absorption','DisplaceX','DisplaceY']:
1043                ptlbls += '%14s'%(item)
1044                ptstr += '%14.4f'%(Sample[item][0])
1045                varstr += '%14s'%(str(bool(Sample[item][1])))
1046
1047        print ptlbls
1048        print ptstr
1049        print varstr
1050       
1051
1052    histDict = {}
1053    histVary = []
1054    controlDict = {}
1055    for histogram in Histograms:
1056        Histogram = Histograms[histogram]
1057        hId = Histogram['hId']
1058        pfx = ':'+str(hId)+':'
1059        controlDict[pfx+'Limits'] = Histogram['Limits'][1]
1060       
1061        Background = Histogram['Background'][0]
1062        Type,bakDict,bakVary = GetBackgroundParms(hId,Background)
1063        controlDict[pfx+'bakType'] = Type
1064        histDict.update(bakDict)
1065        histVary += bakVary
1066       
1067        Inst = Histogram['Instrument Parameters']
1068        Type,instDict,insVary = GetInstParms(hId,Inst)
1069        controlDict[pfx+'histType'] = Type
1070        if pfx+'Lam1' in instDict:
1071            controlDict[pfx+'keV'] = 12.397639/instDict[pfx+'Lam1']
1072        else:
1073            controlDict[pfx+'keV'] = 12.397639/instDict[pfx+'Lam']           
1074        histDict.update(instDict)
1075        histVary += insVary
1076       
1077        Sample = Histogram['Sample Parameters']
1078        Type,sampDict,sampVary = GetSampleParms(hId,Sample)
1079        controlDict[pfx+'instType'] = Type
1080        histDict.update(sampDict)
1081        histVary += sampVary
1082
1083        if Print: 
1084            print '\n Histogram: ',histogram,' histogram Id: ',hId
1085            print 135*'-'
1086            Units = {'C':' deg','T':' msec'}
1087            units = Units[controlDict[pfx+'histType'][2]]
1088            Limits = controlDict[pfx+'Limits']
1089            print ' Instrument type: ',Sample['Type']
1090            print ' Histogram limits: %8.2f%s to %8.2f%s'%(Limits[0],units,Limits[1],units)     
1091            PrintSampleParms(Sample)
1092            PrintInstParms(Inst)
1093            PrintBackground(Background)
1094       
1095    return histVary,histDict,controlDict
1096   
1097def SetHistogramData(parmDict,sigDict,Histograms):
1098   
1099    def SetBackgroundParms(pfx,Background,parmDict,sigDict):
1100        lenBack = len(Background[3:])
1101        backSig = [0 for i in range(lenBack)]
1102        for i in range(lenBack):
1103            Background[3+i] = parmDict[pfx+'Back:'+str(i)]
1104            if pfx+'Back:'+str(i) in sigDict:
1105                backSig[i] = sigDict[pfx+'Back:'+str(i)]
1106        return backSig
1107       
1108    def SetInstParms(pfx,Inst,parmDict,sigDict):
1109        insVals,insFlags,insNames = Inst[1:4]
1110        instSig = [0 for i in range(len(insVals))]
1111        for i,flag in enumerate(insFlags):
1112            insName = pfx+insNames[i]
1113            insVals[i] = parmDict[insName]
1114            if insName in sigDict:
1115                instSig[i] = sigDict[insName]
1116        return instSig
1117       
1118    def SetSampleParms(pfx,Sample,parmDict,sigDict):
1119        if 'Bragg' in Sample['Type']:             #Bragg-Brentano
1120            sampSig = [0 for i in range(3)]
1121            for i,item in enumerate(['Scale','Shift','Transparency']):       #surface roughness?, diffuse scattering?
1122                Sample[item][0] = parmDict[pfx+item]
1123                if pfx+item in sigDict:
1124                    sampSig[i] = sigDict[pfx+item]
1125        elif 'Debye' in Sample['Type']:        #Debye-Scherrer
1126            sampSig = [0 for i in range(4)]
1127            for i,item in enumerate(['Scale','Absorption','DisplaceX','DisplaceY']):
1128                Sample[item][0] = parmDict[pfx+item]
1129                if pfx+item in sigDict:
1130                    sampSig[i] = sigDict[pfx+item]
1131        return sampSig
1132       
1133    def PrintBackgroundSig(Background,backSig):
1134        print '\n Background function: ',Background[0]
1135        valstr = ' value : '
1136        sigstr = ' sig   : '
1137        for i,back in enumerate(Background[3:]):
1138            valstr += '%10.4f'%(back)
1139            if Background[1]:
1140                sigstr += '%10.4f'%(backSig[i])
1141            else:
1142                sigstr += 10*' '
1143        print valstr
1144        print sigstr
1145       
1146    def PrintInstParmsSig(Inst,instSig):
1147        print '\n Instrument Parameters:'
1148        ptlbls = ' names :'
1149        ptstr =  ' value :'
1150        sigstr = ' sig   :'
1151        instNames = Inst[3][1:]
1152        for i,name in enumerate(instNames):
1153            ptlbls += '%12s' % (name)
1154            ptstr += '%12.6f' % (Inst[1][i+1])
1155            if instSig[i+1]:
1156                sigstr += '%12.6f' % (instSig[i+1])
1157            else:
1158                sigstr += 12*' '
1159        print ptlbls
1160        print ptstr
1161        print sigstr
1162       
1163    def PrintSampleParmsSig(Sample,sampleSig):
1164        print '\n Sample Parameters:'
1165        ptlbls = ' names :'
1166        ptstr =  ' values:'
1167        sigstr = ' sig   :'
1168        if 'Bragg' in Sample['Type']:
1169            for i,item in enumerate(['Scale','Shift','Transparency']):
1170                ptlbls += '%14s'%(item)
1171                ptstr += '%14.4f'%(Sample[item][0])
1172                if sampleSig[i]:
1173                    sigstr += '%14.4f'%(sampleSig[i])
1174                else:
1175                    sigstr += 14*' '
1176           
1177        elif 'Debye' in Sample['Type']:        #Debye-Scherrer
1178            for i,item in enumerate(['Scale','Absorption','DisplaceX','DisplaceY']):
1179                ptlbls += '%14s'%(item)
1180                ptstr += '%14.4f'%(Sample[item][0])
1181                if sampleSig[i]:
1182                    sigstr += '%14.4f'%(sampleSig[i])
1183                else:
1184                    sigstr += 14*' '
1185
1186        print ptlbls
1187        print ptstr
1188        print sigstr
1189       
1190    for histogram in Histograms:
1191        if 'PWDR' in histogram:
1192            Histogram = Histograms[histogram]
1193            hId = Histogram['hId']
1194            pfx = ':'+str(hId)+':'
1195            Background = Histogram['Background'][0]
1196            backSig = SetBackgroundParms(pfx,Background,parmDict,sigDict)
1197           
1198            Inst = Histogram['Instrument Parameters']
1199            instSig = SetInstParms(pfx,Inst,parmDict,sigDict)
1200       
1201            Sample = Histogram['Sample Parameters']
1202            sampSig = SetSampleParms(pfx,Sample,parmDict,sigDict)
1203
1204            print '\n Histogram: ',histogram,' histogram Id: ',hId
1205            print 135*'-'
1206            print ' Instrument type: ',Sample['Type']
1207            PrintSampleParmsSig(Sample,sampSig)
1208            PrintInstParmsSig(Inst,instSig)
1209            PrintBackgroundSig(Background,backSig)
1210
1211def GetAtomFXU(pfx,FFtables,calcControls,parmDict):
1212    Natoms = calcControls['Natoms'][pfx]
1213    Tdata = Natoms*[' ',]
1214    Mdata = np.zeros(Natoms)
1215    IAdata = Natoms*[' ',]
1216    Fdata = np.zeros(Natoms)
1217    FFdata = []
1218    Xdata = np.zeros((3,Natoms))
1219    dXdata = np.zeros((3,Natoms))
1220    Uisodata = np.zeros(Natoms)
1221    Uijdata = np.zeros((6,Natoms))
1222    keys = {'Atype:':Tdata,'Amul:':Mdata,'Afrac:':Fdata,'AI/A:':IAdata,
1223        'dAx:':dXdata[0],'dAy:':dXdata[1],'dAz:':dXdata[2],
1224        'Ax:':Xdata[0],'Ay:':Xdata[1],'Az:':Xdata[2],'AUiso:':Uisodata,
1225        'AU11:':Uijdata[0],'AU22:':Uijdata[1],'AU33:':Uijdata[2],
1226        'AU12:':Uijdata[3],'AU13:':Uijdata[4],'AU23:':Uijdata[5]}
1227    for iatm in range(Natoms):
1228        for key in keys:
1229            parm = pfx+key+str(iatm)
1230            if parm in parmDict:
1231                keys[key][iatm] = parmDict[parm]
1232        FFdata.append(FFtables[Tdata[iatm]])
1233    return FFdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata
1234   
1235def StructureFactor(refList,G,hfx,pfx,SGData,calcControls,parmDict):
1236    ''' Compute structure factors for all h,k,l for phase
1237    input:
1238        refList: [ref] where each ref = h,k,l,m,d,...,[equiv h,k,l],phase[equiv]
1239        G:      reciprocal metric tensor
1240        pfx:    phase id string
1241        SGData: space group info. dictionary output from SpcGroup
1242        calcControls:
1243        ParmDict:
1244    puts result F^2 in each ref[8] in refList
1245    '''       
1246    twopi = 2.0*np.pi
1247    twopisq = 2.0*np.pi**2
1248    ast = np.sqrt(np.diag(G))
1249    Mast = twopisq*np.multiply.outer(ast,ast)
1250    FFtables = calcControls['FFtables']
1251    FFdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata = GetAtomFXU(pfx,FFtables,calcControls,parmDict)
1252    FP = np.array([El[hfx+'FP'] for El in FFdata])
1253    FPP = np.array([El[hfx+'FPP'] for El in FFdata])
1254    maxPos = len(SGData['SGOps'])
1255    Uij = np.array(G2lat.U6toUij(Uijdata))
1256    bij = Mast*Uij.T
1257    for refl in refList:
1258        fbs = np.array([0,0])
1259        H = refl[:3]
1260        SQ = 1./(2.*refl[4])**2
1261        FF = np.array([G2el.ScatFac(El,SQ)[0] for El in FFdata])
1262        SQfactor = 4.0*SQ*twopisq
1263        Uniq = refl[11]
1264        phi = refl[12]
1265        phase = twopi*(np.inner(Uniq,(dXdata.T+Xdata.T))+phi[:,np.newaxis])
1266        sinp = np.sin(phase)
1267        cosp = np.cos(phase)
1268        occ = Mdata*Fdata/len(Uniq)
1269        biso = -SQfactor*Uisodata
1270        Tiso = np.where(biso<1.,np.exp(biso),1.0)
1271        HbH = np.array([-np.inner(h,np.inner(bij,h)) for h in Uniq])
1272        Tuij = np.where(HbH<1.,np.exp(HbH),1.0)
1273        Tcorr = Tiso*Tuij
1274        fa = np.array([(FF+FP)*occ*cosp*Tcorr,-FPP*occ*sinp*Tcorr])
1275        fas = np.sum(np.sum(fa,axis=1),axis=1)        #real
1276        if not SGData['SGInv']:
1277            fb = np.array([(FF+FP)*occ*sinp*Tcorr,FPP*occ*cosp*Tcorr])
1278            fbs = np.sum(np.sum(fb,axis=1),axis=1)
1279        fasq = fas**2
1280        fbsq = fbs**2        #imaginary
1281        refl[9] = np.sum(fasq)+np.sum(fbsq)
1282        refl[10] = atan2d(fbs[0],fas[0])
1283    return refList
1284   
1285def StructureFactorDerv(refList,G,hfx,pfx,SGData,calcControls,parmDict):
1286    twopi = 2.0*np.pi
1287    twopisq = 2.0*np.pi**2
1288    ast = np.sqrt(np.diag(G))
1289    Mast = twopisq*np.multiply.outer(ast,ast)
1290    FFtables = calcControls['FFtables']
1291    FFdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata = GetAtomFXU(pfx,FFtables,calcControls,parmDict)
1292    FP = np.array([El[hfx+'FP'] for El in FFdata])
1293    FPP = np.array([El[hfx+'FPP'] for El in FFdata])
1294    maxPos = len(SGData['SGOps'])       
1295    Uij = np.array(G2lat.U6toUij(Uijdata))
1296    bij = Mast*Uij.T
1297    dFdvDict = {}
1298    dFdfr = np.zeros((len(refList),len(Mdata)))
1299    dFdx = np.zeros((len(refList),len(Mdata),3))
1300    dFdui = np.zeros((len(refList),len(Mdata)))
1301    dFdua = np.zeros((len(refList),len(Mdata),6))
1302    for iref,refl in enumerate(refList):
1303        H = np.array(refl[:3])
1304        SQ = 1./(2.*refl[4])**2          # or (sin(theta)/lambda)**2
1305        FF = np.array([G2el.ScatFac(El,SQ)[0] for El in FFdata])
1306        SQfactor = 8.0*SQ*np.pi**2
1307        Uniq = refl[11]
1308        phi = refl[12]
1309        phase = twopi*(np.inner((dXdata.T+Xdata.T),Uniq)+phi[np.newaxis,:])
1310        sinp = np.sin(phase)
1311        cosp = np.cos(phase)
1312        occ = Mdata*Fdata/len(Uniq)
1313        biso = -SQfactor*Uisodata
1314        Tiso = np.where(biso<1.,np.exp(biso),1.0)
1315#        HbH = np.array([-np.inner(h,np.inner(bij,h)) for h in Uniq])
1316        HbH = -np.inner(H,np.inner(bij,H))
1317        Hij = np.array([Mast*np.multiply.outer(U,U) for U in Uniq])
1318        Hij = np.array([G2lat.UijtoU6(Uij) for Uij in Hij])
1319        Tuij = np.where(HbH<1.,np.exp(HbH),1.0)
1320        Tcorr = Tiso*Tuij
1321        fot = (FF+FP)*occ*Tcorr
1322        fotp = FPP*occ*Tcorr
1323        fa = np.array([fot[:,np.newaxis]*cosp,fotp[:,np.newaxis]*cosp])       #non positions
1324        fb = np.array([fot[:,np.newaxis]*sinp,-fotp[:,np.newaxis]*sinp])
1325       
1326        fas = np.sum(np.sum(fa,axis=1),axis=1)
1327        fbs = np.sum(np.sum(fb,axis=1),axis=1)
1328        fax = np.array([-fot[:,np.newaxis]*sinp,-fotp[:,np.newaxis]*sinp])   #positions
1329        fbx = np.array([fot[:,np.newaxis]*cosp,-fot[:,np.newaxis]*cosp])
1330        #sum below is over Uniq
1331        dfadfr = np.sum(fa/occ[:,np.newaxis],axis=2)
1332        dfadx = np.sum(twopi*Uniq*fax[:,:,:,np.newaxis],axis=2)
1333        dfadui = np.sum(-SQfactor*fa,axis=2)
1334        dfadua = np.sum(-Hij*fa[:,:,:,np.newaxis],axis=2)
1335        #NB: the above have been checked against PA(1:10,1:2) in strfctr.for     
1336        dFdfr[iref] = 2.*(fas[0]*dfadfr[0]+fas[1]*dfadfr[1])*Mdata/len(Uniq)
1337        dFdx[iref] = 2.*(fas[0]*dfadx[0]+fas[1]*dfadx[1])
1338        dFdui[iref] = 2.*(fas[0]*dfadui[0]+fas[1]*dfadui[1])
1339        dFdua[iref] = 2.*(fas[0]*dfadua[0]+fas[1]*dfadua[1])
1340        if not SGData['SGInv']:
1341            dfbdfr = np.sum(fb/occ[:,np.newaxis],axis=2)
1342            dfbdx = np.sum(twopi*Uniq*fbx[:,:,:,np.newaxis],axis=2)         
1343            dfbdui = np.sum(-SQfactor*fb,axis=2)
1344            dfbdua = np.sum(-Hij*fb[:,:,:,np.newaxis],axis=2)
1345            dFdfr[iref] += 2.*(fbs[0]*dfbdfr[0]-fbs[1]*dfbdfr[1])*Mdata/len(Uniq)
1346            dFdx[iref] += 2.*(fbs[0]*dfbdx[0]+fbs[1]*dfbdx[1])
1347            dFdui[iref] += 2.*(fbs[0]*dfbdui[0]-fbs[1]*dfbdui[1])
1348            dFdua[iref] += 2.*(fbs[0]*dfbdua[0]+fbs[1]*dfbdua[1])
1349        #loop over atoms - each dict entry is list of derivatives for all the reflections
1350    for i in range(len(Mdata)):     
1351        dFdvDict[pfx+'Afrac:'+str(i)] = dFdfr.T[i]
1352        dFdvDict[pfx+'dAx:'+str(i)] = dFdx.T[0][i]
1353        dFdvDict[pfx+'dAy:'+str(i)] = dFdx.T[1][i]
1354        dFdvDict[pfx+'dAz:'+str(i)] = dFdx.T[2][i]
1355        dFdvDict[pfx+'AUiso:'+str(i)] = dFdui.T[i]
1356        dFdvDict[pfx+'AU11:'+str(i)] = dFdua.T[0][i]
1357        dFdvDict[pfx+'AU22:'+str(i)] = dFdua.T[1][i]
1358        dFdvDict[pfx+'AU33:'+str(i)] = dFdua.T[2][i]
1359        dFdvDict[pfx+'AU12:'+str(i)] = 2.*dFdua.T[3][i]
1360        dFdvDict[pfx+'AU13:'+str(i)] = 2.*dFdua.T[4][i]
1361        dFdvDict[pfx+'AU23:'+str(i)] = 2.*dFdua.T[5][i]
1362    return dFdvDict
1363       
1364def Dict2Values(parmdict, varylist):
1365    '''Use before call to leastsq to setup list of values for the parameters
1366    in parmdict, as selected by key in varylist'''
1367    return [parmdict[key] for key in varylist] 
1368   
1369def Values2Dict(parmdict, varylist, values):
1370    ''' Use after call to leastsq to update the parameter dictionary with
1371    values corresponding to keys in varylist'''
1372    parmdict.update(zip(varylist,values))
1373   
1374def ApplyXYZshifts(parmDict,varyList):
1375    ''' takes atom x,y,z shift and applies it to corresponding atom x,y,z value
1376    '''
1377    for item in parmDict:
1378        if 'dA' in item:
1379            parm = ''.join(item.split('d'))
1380            parmDict[parm] += parmDict[item]
1381   
1382def SHPOcal(refl,g,phfx,hfx,SGData,calcControls,parmDict):
1383    odfCor = 1.0
1384    H = refl[:3]
1385    cell = G2lat.Gmat2cell(g)
1386    Sangl = [0.,0.,0.]
1387    if 'Bragg' in calcControls[hfx+'instType']:
1388        Gangls = [0.,90.,0.,parmDict[hfx+'Azimuth']]
1389        IFCoup = True
1390    else:
1391        Gangls = [0.,0.,0.,parmDict[hfx+'Azimuth']]
1392        IFCoup = False
1393    phi,beta = G2lat.CrsAng(H,cell,SGData)
1394    psi,gam,x,x = G2lat.SamAng(refl[5]/2.,Gangls,Sangl,IFCoup) #ignore 2 sets of angle derivs.
1395    SHnames = G2lat.GenSHCoeff(SGData['SGLaue'],None,calcControls[phfx+'SHord'])
1396    for item in SHnames:
1397        L,N = eval(item.strip('C'))
1398        Kcsl,Lnorm = G2lat.GetKclKsl(L,N,SGData['SGLaue'],psi,phi,beta) 
1399        odfCor += parmDict[phfx+item]*Lnorm*Kcsl
1400    return odfCor
1401   
1402def SHPOcalDerv(refl,g,phfx,hfx,SGData,calcControls,parmDict):
1403    FORPI = 12.5663706143592
1404    odfCor = 1.0
1405    dFdODF = {}
1406    H = refl[:3]
1407    cell = G2lat.Gmat2cell(g)
1408    Sangl = [0.,0.,0.]
1409    if 'Bragg' in calcControls[hfx+'instType']:
1410        Gangls = [0.,90.,0.,parmDict[hfx+'Azimuth']]
1411        IFCoup = True
1412    else:
1413        Gangls = [0.,0.,0.,parmDict[hfx+'Azimuth']]
1414        IFCoup = False
1415    phi,beta = G2lat.CrsAng(H,cell,SGData)
1416    psi,gam,x,x = G2lat.SamAng(refl[5]/2.,Gangls,Sangl,IFCoup) #ignore 2 sets of angle derivs.
1417    SHnames = G2lat.GenSHCoeff(SGData['SGLaue'],None,calcControls[phfx+'SHord'])
1418    for item in SHnames:
1419        L,N = eval(item.strip('C'))
1420        Kcsl,Lnorm = G2lat.GetKclKsl(L,N,SGData['SGLaue'],psi,phi,beta) 
1421        odfCor += parmDict[phfx+item]*Lnorm*Kcsl
1422        dFdODF[phfx+item] = FORPI*Kcsl
1423    return odfCor,dFdODF
1424   
1425def GetPrefOri(refl,G,g,phfx,hfx,SGData,calcControls,parmDict):
1426    if calcControls[phfx+'poType'] == 'MD':
1427        MD = parmDict[phfx+'MD']
1428        MDAxis = calcControls[phfx+'MDAxis']
1429        sumMD = 0
1430        for H in refl[11]:           
1431            cosP,sinP = G2lat.CosSinAngle(H,MDAxis,G)
1432            A = 1.0/np.sqrt((MD*cosP)**2+sinP**2/MD)
1433            sumMD += A**3
1434        POcorr = sumMD/len(refl[11])
1435    else:   #spherical harmonics
1436        POcorr = SHPOcal(refl,g,phfx,hfx,SGData,calcControls,parmDict)
1437    return POcorr
1438   
1439def GetPrefOriDerv(refl,G,g,phfx,hfx,SGData,calcControls,parmDict):
1440    POderv = {}
1441    if calcControls[phfx+'poType'] == 'MD':
1442        MD = parmDict[phfx+'MD']
1443        MDAxis = calcControls[phfx+'MDAxis']
1444        sumMD = 0
1445        sumdMD = 0
1446        for H in refl[11]:           
1447            cosP,sinP = G2lat.CosSinAngle(H,MDAxis,G)
1448            A = 1.0/np.sqrt((MD*cosP)**2+sinP**2/MD)
1449            sumMD += A**3
1450            sumdMD -= (1.5*A**5)*(2.0*MD*cosP**2-(sinP/MD)**2)
1451        POcorr = sumMD/len(refl[11])
1452        POderv[phfx+'MD'] = sumdMD/len(refl[11])
1453    else:   #spherical harmonics
1454        POcorr,POderv = SHPOcalDerv(refl,g,phfx,hfx,SGData,calcControls,parmDict)
1455    return POcorr,POderv
1456   
1457def GetIntensityCorr(refl,G,g,phfx,hfx,SGData,calcControls,parmDict):
1458    Icorr = parmDict[phfx+'Scale']*parmDict[hfx+'Scale']*refl[3]               #scale*multiplicity
1459    Icorr *= G2pwd.Polarization(parmDict[hfx+'Polariz.'],refl[5],parmDict[hfx+'Azimuth'])[0]
1460    Icorr *= GetPrefOri(refl,G,g,phfx,hfx,SGData,calcControls,parmDict)       
1461    return Icorr
1462   
1463def GetIntensityDerv(refl,G,g,phfx,hfx,SGData,calcControls,parmDict):
1464    Icorr = GetIntensityCorr(refl,G,g,phfx,hfx,SGData,calcControls,parmDict)
1465    pola,dIdPola = G2pwd.Polarization(parmDict[hfx+'Polariz.'],refl[5],parmDict[hfx+'Azimuth'])
1466    POcorr,dIdPO = GetPrefOriDerv(refl,G,g,phfx,hfx,SGData,calcControls,parmDict)
1467    dIdPola /= pola
1468    for iPO in dIdPO:
1469        dIdPO[iPO] /= POcorr
1470    dIdsh = 1./parmDict[hfx+'Scale']
1471    dIdsp = 1./parmDict[phfx+'Scale']
1472    return Icorr,dIdsh,dIdsp,dIdPola,dIdPO
1473       
1474def GetSampleGam(refl,wave,G,phfx,calcControls,parmDict,sizeEllipse):
1475    costh = cosd(refl[5]/2.)
1476    #crystallite size
1477    if calcControls[phfx+'SizeType'] == 'isotropic':
1478        gam = 1.8*wave/(np.pi*parmDict[phfx+'Size:0']*costh)
1479    elif calcControls[phfx+'SizeType'] == 'uniaxial':
1480        H = np.array(refl[:3])
1481        P = np.array(calcControls[phfx+'SizeAxis'])
1482        cosP,sinP = G2lat.CosSinAngle(H,P,G)
1483        gam = (1.8*wave/np.pi)/(parmDict[phfx+'Size:0']*parmDict[phfx+'Size:1']*costh)
1484        gam *= np.sqrt((cosP*parmDict[phfx+'Size:1'])**2+(sinP*parmDict[phfx+'Size:0'])**2)
1485    else:           #ellipsoidal crystallites - wrong not make sense
1486        H = np.array(refl[:3])
1487        gam += 1.8*wave/(np.pi*costh*np.inner(H,np.inner(sizeEllipse,H)))
1488    #microstrain               
1489    if calcControls[phfx+'MustrainType'] == 'isotropic':
1490        gam += 0.018*parmDict[phfx+'Mustrain:0']*tand(refl[5]/2.)/np.pi
1491    elif calcControls[phfx+'MustrainType'] == 'uniaxial':
1492        H = np.array(refl[:3])
1493        P = np.array(calcControls[phfx+'MustrainAxis'])
1494        cosP,sinP = G2lat.CosSinAngle(H,P,G)
1495        Si = parmDict[phfx+'Mustrain:0']
1496        Sa = parmDict[phfx+'Mustrain:1']
1497        gam += 0.018*Si*Sa*tand(refl[5]/2.)/(np.pi*np.sqrt((Si*cosP)**2+(Sa*sinP)**2))
1498    else:       #generalized - P.W. Stephens model
1499        pwrs = calcControls[phfx+'MuPwrs']
1500        sum = 0
1501        for i,pwr in enumerate(pwrs):
1502            sum += parmDict[phfx+'Mustrain:'+str(i)]*refl[0]**pwr[0]*refl[1]**pwr[1]*refl[2]**pwr[2]
1503        gam += 0.018*refl[4]**2*tand(refl[5]/2.)*sum           
1504    return gam
1505       
1506def GetSampleGamDerv(refl,wave,G,phfx,calcControls,parmDict,sizeEllipse):
1507    gamDict = {}
1508    costh = cosd(refl[5]/2.)
1509    tanth = tand(refl[5]/2.)
1510    #crystallite size derivatives
1511    if calcControls[phfx+'SizeType'] == 'isotropic':
1512        gamDict[phfx+'Size:0'] = -1.80*wave/(np.pi*costh)
1513    elif calcControls[phfx+'SizeType'] == 'uniaxial':
1514        H = np.array(refl[:3])
1515        P = np.array(calcControls[phfx+'SizeAxis'])
1516        cosP,sinP = G2lat.CosSinAngle(H,P,G)
1517        Si = parmDict[phfx+'Size:0']
1518        Sa = parmDict[phfx+'Size:1']
1519        gami = (1.80*wave/np.pi)/(Si*Sa)
1520        sqtrm = np.sqrt((cosP*Sa)**2+(sinP*Si)**2)
1521        gam = gami*sqtrm/costh           
1522        gamDict[phfx+'Size:0'] = gami*Si*sinP**2/(sqtrm*costh)-gam/Si
1523        gamDict[phfx+'Size:1'] = gami*Sa*cosP**2/(sqtrm*costh)-gam/Sa         
1524    else:           #ellipsoidal crystallites - do numerically? - not right not make sense
1525        H = np.array(refl[:3])
1526        gam = 1.8*wave/(np.pi*costh*np.inner(H,np.inner(sizeEllipse,H)))
1527    #microstrain derivatives               
1528    if calcControls[phfx+'MustrainType'] == 'isotropic':
1529        gamDict[phfx+'Mustrain:0'] =  0.018*tanth/np.pi           
1530    elif calcControls[phfx+'MustrainType'] == 'uniaxial':
1531        H = np.array(refl[:3])
1532        P = np.array(calcControls[phfx+'MustrainAxis'])
1533        cosP,sinP = G2lat.CosSinAngle(H,P,G)
1534        Si = parmDict[phfx+'Mustrain:0']
1535        Sa = parmDict[phfx+'Mustrain:1']
1536        gami = 0.018*Si*Sa*tanth/np.pi
1537        sqtrm = np.sqrt((Si*cosP)**2+(Sa*sinP)**2)
1538        gam = gami/sqtrm
1539        gamDict[phfx+'Mustrain:0'] = gam/Si-gami*Si*cosP**2/sqtrm**3
1540        gamDict[phfx+'Mustrain:1'] = gam/Sa-gami*Sa*sinP**2/sqtrm**3
1541    else:       #generalized - P.W. Stephens model
1542        pwrs = calcControls[phfx+'MuPwrs']
1543        const = 0.018*refl[4]**2*tanth
1544        for i,pwr in enumerate(pwrs):
1545            gamDict[phfx+'Mustrain:'+str(i)] = const*refl[0]**pwr[0]*refl[1]**pwr[1]*refl[2]**pwr[2]
1546    return gamDict
1547       
1548def GetReflPos(refl,wave,G,hfx,calcControls,parmDict):
1549    h,k,l = refl[:3]
1550    dsq = 1./G2lat.calc_rDsq2(np.array([h,k,l]),G)
1551    d = np.sqrt(dsq)
1552    refl[4] = d
1553    pos = 2.0*asind(wave/(2.0*d))+parmDict[hfx+'Zero']
1554    const = 9.e-2/(np.pi*parmDict[hfx+'Gonio. radius'])                  #shifts in microns
1555    if 'Bragg' in calcControls[hfx+'instType']:
1556        pos -= const*(4.*parmDict[hfx+'Shift']*cosd(pos/2.0)+ \
1557            parmDict[hfx+'Transparency']*sind(pos)*100.0)            #trans(=1/mueff) in cm
1558    else:               #Debye-Scherrer - simple but maybe not right
1559        pos -= const*(parmDict[hfx+'DisplaceX']*cosd(pos)+parmDict[hfx+'DisplaceY']*sind(pos))
1560    return pos
1561
1562def GetReflPosDerv(refl,wave,A,hfx,calcControls,parmDict):
1563    dpr = 180./np.pi
1564    h,k,l = refl[:3]
1565    dstsq = G2lat.calc_rDsq(np.array([h,k,l]),A)
1566    dst = np.sqrt(dstsq)
1567    pos = refl[5]
1568    const = dpr/np.sqrt(1.0-wave*dst/4.0)
1569    dpdw = const*dst
1570    dpdA = np.array([h**2,k**2,l**2,h*k,h*l,k*l])
1571    dpdA *= const*wave/(2.0*dst)
1572    dpdZ = 1.0
1573    const = 9.e-2/(np.pi*parmDict[hfx+'Gonio. radius'])                  #shifts in microns
1574    if 'Bragg' in calcControls[hfx+'instType']:
1575        dpdSh = -4.*const*cosd(pos/2.0)
1576        dpdTr = -const*sind(pos)*100.0
1577        return dpdA,dpdw,dpdZ,dpdSh,dpdTr,0.,0.
1578    else:               #Debye-Scherrer - simple but maybe not right
1579        dpdXd = -const*cosd(pos)
1580        dpdYd = -const*sind(pos)
1581        return dpdA,dpdw,dpdZ,0.,0.,dpdXd,dpdYd
1582           
1583def GetHStrainShift(refl,SGData,phfx,parmDict):
1584    laue = SGData['SGLaue']
1585    uniq = SGData['SGUniq']
1586    h,k,l = refl[:3]
1587    if laue in ['m3','m3m']:
1588        Dij = parmDict[phfx+'D11']*(h**2+k**2+l**2)
1589    elif laue in ['6/m','6/mmm','3m1','31m','3']:
1590        Dij = parmDict[phfx+'D11']*(h**2+k**2+h*k)+parmDict[phfx+'D33']*l**2
1591    elif laue in ['3R','3mR']:
1592        Dij = parmDict[phfx+'D11']*(h**2+k**2+l**2)+parmDict[phfx+'D12']*(h*k+h*l+k*l)
1593    elif laue in ['4/m','4/mmm']:
1594        Dij = parmDict[phfx+'D11']*(h**2+k**2)+parmDict[phfx+'D33']*l**2
1595    elif laue in ['mmm']:
1596        Dij = parmDict[phfx+'D11']*h**2+parmDict[phfx+'D22']*k**2+parmDict[phfx+'D33']*l**2
1597    elif laue in ['2/m']:
1598        Dij = parmDict[phfx+'D11']*h**2+parmDict[phfx+'D22']*k**2+parmDict[phfx+'D33']*l**2
1599        if uniq == 'a':
1600            Dij += parmDict[phfx+'D23']*k*l
1601        elif uniq == 'b':
1602            Dij += parmDict[phfx+'D13']*h*l
1603        elif uniq == 'c':
1604            Dij += parmDict[phfx+'D12']*h*k
1605    else:
1606        Dij = parmDict[phfx+'D11']*h**2+parmDict[phfx+'D22']*k**2+parmDict[phfx+'D33']*l**2+ \
1607            parmDict[phfx+'D12']*h*k+parmDict[phfx+'D13']*h*l+parmDict[phfx+'D23']*k*l
1608    return Dij*refl[4]**2*tand(refl[5]/2.0)
1609           
1610def GetHStrainShiftDerv(refl,SGData,phfx):
1611    laue = SGData['SGLaue']
1612    uniq = SGData['SGUniq']
1613    h,k,l = refl[:3]
1614    if laue in ['m3','m3m']:
1615        dDijDict = {phfx+'D11':h**2+k**2+l**2,}
1616    elif laue in ['6/m','6/mmm','3m1','31m','3']:
1617        dDijDict = {phfx+'D11':h**2+k**2+h*k,phfx+'D33':l**2}
1618    elif laue in ['3R','3mR']:
1619        dDijDict = {phfx+'D11':h**2+k**2+l**2,phfx+'D12':h*k+h*l+k*l}
1620    elif laue in ['4/m','4/mmm']:
1621        dDijDict = {phfx+'D11':h**2+k**2,phfx+'D33':l**2}
1622    elif laue in ['mmm']:
1623        dDijDict = {phfx+'D11':h**2,phfx+'D22':k**2,phfx+'D33':l**2}
1624    elif laue in ['2/m']:
1625        dDijDict = {phfx+'D11':h**2,phfx+'D22':k**2,phfx+'D33':l**2}
1626        if uniq == 'a':
1627            dDijDict[phfx+'D23'] = k*l
1628        elif uniq == 'b':
1629            dDijDict[phfx+'D13'] = h*l
1630        elif uniq == 'c':
1631            dDijDict[phfx+'D12'] = h*k
1632            names.append()
1633    else:
1634        dDijDict = {phfx+'D11':h**2,phfx+'D22':k**2,phfx+'D33':l**2,
1635            phfx+'D12':h*k,phfx+'D13':h*l,phfx+'D23':k*l}
1636    for item in dDijDict:
1637        dDijDict[item] *= refl[4]**2*tand(refl[5]/2.0)
1638    return dDijDict
1639   
1640def GetFprime(controlDict,Histograms):
1641    FFtables = controlDict['FFtables']
1642    if not FFtables:
1643        return
1644    for histogram in Histograms:
1645        if 'PWDR' in histogram[:4]:
1646            Histogram = Histograms[histogram]
1647            hId = Histogram['hId']
1648            hfx = ':%d:'%(hId)
1649            keV = controlDict[hfx+'keV']
1650            for El in FFtables:
1651                Orbs = G2el.GetXsectionCoeff(El.split('+')[0].split('-')[0])
1652                FP,FPP,Mu = G2el.FPcalc(Orbs, keV)
1653                FFtables[El][hfx+'FP'] = FP
1654                FFtables[El][hfx+'FPP'] = FPP               
1655           
1656def getPowderProfile(parmDict,x,varylist,Histogram,Phases,calcControls,pawleyLookup):
1657   
1658    def GetReflSIgGam(refl,wave,G,hfx,phfx,calcControls,parmDict,sizeEllipse):
1659        U = parmDict[hfx+'U']
1660        V = parmDict[hfx+'V']
1661        W = parmDict[hfx+'W']
1662        X = parmDict[hfx+'X']
1663        Y = parmDict[hfx+'Y']
1664        tanPos = tand(refl[5]/2.0)
1665        sig = U*tanPos**2+V*tanPos+W        #save peak sigma
1666        sig = max(0.001,sig)
1667        gam = X/cosd(refl[5]/2.0)+Y*tanPos+GetSampleGam(refl,wave,G,phfx,calcControls,parmDict,sizeEllipse) #save peak gamma
1668        gam = max(0.001,gam)
1669        return sig,gam
1670               
1671    hId = Histogram['hId']
1672    hfx = ':%d:'%(hId)
1673    bakType = calcControls[hfx+'bakType']
1674    yb = G2pwd.getBackground(hfx,parmDict,bakType,x)
1675    yc = np.zeros_like(yb)
1676       
1677    if 'C' in calcControls[hfx+'histType']:   
1678        shl = max(parmDict[hfx+'SH/L'],0.002)
1679        Ka2 = False
1680        if hfx+'Lam1' in parmDict.keys():
1681            wave = parmDict[hfx+'Lam1']
1682            Ka2 = True
1683            lamRatio = 360*(parmDict[hfx+'Lam2']-parmDict[hfx+'Lam1'])/(np.pi*parmDict[hfx+'Lam1'])
1684            kRatio = parmDict[hfx+'I(L2)/I(L1)']
1685        else:
1686            wave = parmDict[hfx+'Lam']
1687    else:
1688        print 'TOF Undefined at present'
1689        raise ValueError
1690    for phase in Histogram['Reflection Lists']:
1691        refList = Histogram['Reflection Lists'][phase]
1692        Phase = Phases[phase]
1693        pId = Phase['pId']
1694        pfx = '%d::'%(pId)
1695        phfx = '%d:%d:'%(pId,hId)
1696        hfx = ':%d:'%(hId)
1697        SGData = Phase['General']['SGData']
1698        A = [parmDict[pfx+'A%d'%(i)] for i in range(6)]
1699        G,g = G2lat.A2Gmat(A)       #recip & real metric tensors
1700        Vst = np.sqrt(nl.det(G))    #V*
1701        if 'Pawley' not in Phase['General']['Type']:
1702            refList = StructureFactor(refList,G,hfx,pfx,SGData,calcControls,parmDict)
1703        sizeEllipse = []
1704        if calcControls[phfx+'SizeType'] == 'ellipsoidal':
1705            sizeEllipse = G2lat.U6toUij([parmDIct[phfx+'Size:%d'%(i)] for i in range(6)])
1706        for refl in refList:
1707            if 'C' in calcControls[hfx+'histType']:
1708                h,k,l = refl[:3]
1709                refl[5] = GetReflPos(refl,wave,G,hfx,calcControls,parmDict)         #corrected reflection position
1710                Lorenz = 1./(2.*sind(refl[5]/2.)**2*cosd(refl[5]/2.))           #Lorentz correction
1711                refl[5] += GetHStrainShift(refl,SGData,phfx,parmDict)               #apply hydrostatic strain shift
1712                refl[6:8] = GetReflSIgGam(refl,wave,G,hfx,phfx,calcControls,parmDict,sizeEllipse)    #peak sig & gam
1713                Icorr = GetIntensityCorr(refl,G,g,phfx,hfx,SGData,calcControls,parmDict)*Vst*Lorenz
1714                if 'Pawley' in Phase['General']['Type']:
1715                    try:
1716                        refl[9] = abs(parmDict[pfx+'PWLref:%d'%(pawleyLookup[pfx+'%d,%d,%d'%(h,k,l)])])
1717                    except KeyError:
1718#                        print ' ***Error %d,%d,%d missing from Pawley reflection list ***'%(h,k,l)
1719                        continue
1720                Wd,fmin,fmax = G2pwd.getWidths(refl[5],refl[6],refl[7],shl)
1721                iBeg = np.searchsorted(x,refl[5]-fmin)
1722                iFin = np.searchsorted(x,refl[5]+fmax)
1723                if not iBeg+iFin:       #peak below low limit - skip peak
1724                    continue
1725                elif not iBeg-iFin:     #peak above high limit - done
1726                    break
1727                yc[iBeg:iFin] += Icorr*refl[9]*G2pwd.getFCJVoigt3(refl[5],refl[6],refl[7],shl,x[iBeg:iFin])    #>90% of time spent here
1728                if Ka2:
1729                    pos2 = refl[5]+lamRatio*tand(refl[5]/2.0)       # + 360/pi * Dlam/lam * tan(th)
1730                    Wd,fmin,fmax = G2pwd.getWidths(pos2,refl[6],refl[7],shl)
1731                    iBeg = np.searchsorted(x,pos2-fmin)
1732                    iFin = np.searchsorted(x,pos2+fmax)
1733                    if not iBeg+iFin:       #peak below low limit - skip peak
1734                        continue
1735                    elif not iBeg-iFin:     #peak above high limit - done
1736                        return yc,yb
1737                    yc[iBeg:iFin] += Icorr*refl[9]*kRatio*G2pwd.getFCJVoigt3(pos2,refl[6],refl[7],shl,x[iBeg:iFin])        #and here
1738            elif 'T' in calcControls[hfx+'histType']:
1739                print 'TOF Undefined at present'
1740                raise ValueError    #no TOF yet
1741    return yc,yb   
1742           
1743def getPowderProfileDerv(parmDict,x,varylist,Histogram,Phases,calcControls,pawleyLookup):
1744   
1745    def cellVaryDerv(pfx,SGData,dpdA): 
1746        if SGData['SGLaue'] in ['-1',]:
1747            return [[pfx+'A0',dpdA[0]],[pfx+'A1',dpdA[1]],[pfx+'A2',dpdA[2]],
1748                [pfx+'A3',dpdA[3]],[pfx+'A4',dpdA[4]],[pfx+'A5',dpdA[5]]]
1749        elif SGData['SGLaue'] in ['2/m',]:
1750            if SGData['SGUniq'] == 'a':
1751                return [[pfx+'A0',dpdA[0]],[pfx+'A1',dpdA[1]],[pfx+'A2',dpdA[2]],[pfx+'A3',dpdA[3]]]
1752            elif SGData['SGUniq'] == 'b':
1753                return [[pfx+'A0',dpdA[0]],[pfx+'A1',dpdA[1]],[pfx+'A2',dpdA[2]],[pfx+'A4',dpdA[4]]]
1754            else:
1755                return [[pfx+'A0',dpdA[0]],[pfx+'A1',dpdA[1]],[pfx+'A2',dpdA[2]],[pfx+'A5',dpdA[5]]]
1756        elif SGData['SGLaue'] in ['mmm',]:
1757            return [[pfx+'A0',dpdA[0]],[pfx+'A1',dpdA[1]],[pfx+'A2',dpdA[2]]]
1758        elif SGData['SGLaue'] in ['4/m','4/mmm']:
1759            return [[pfx+'A0',dpdA[0]+dpdA[1]],[pfx+'A2',dpdA[2]]]
1760        elif SGData['SGLaue'] in ['6/m','6/mmm','3m1', '31m', '3']:
1761            return [[pfx+'A0',dpdA[0]+dpdA[1]+dpdA[3]],[pfx+'A2',dpdA[2]]]
1762        elif SGData['SGLaue'] in ['3R', '3mR']:
1763            return [[pfx+'A0',dpdA[0]+dpdA[1]+dpdA[2]],[pfx+'A3',dpdA[3]+dpdA[4]+dpdA[5]]]                       
1764        elif SGData['SGLaue'] in ['m3m','m3']:
1765            return [[pfx+'A0',dpdA[0]+dpdA[1]+dpdA[2]]]
1766   
1767    lenX = len(x)               
1768    hId = Histogram['hId']
1769    hfx = ':%d:'%(hId)
1770    bakType = calcControls[hfx+'bakType']
1771    dMdv = np.zeros(shape=(len(varylist),len(x)))
1772    if hfx+'Back:0' in varylist:
1773        dMdb = G2pwd.getBackgroundDerv(hfx,parmDict,bakType,x)
1774        bBpos =varylist.index(hfx+'Back:0')
1775        dMdv[bBpos:bBpos+len(dMdb)] = dMdb
1776       
1777    if 'C' in calcControls[hfx+'histType']:   
1778        dx = x[1]-x[0]
1779        shl = max(parmDict[hfx+'SH/L'],0.002)
1780        Ka2 = False
1781        if hfx+'Lam1' in parmDict.keys():
1782            wave = parmDict[hfx+'Lam1']
1783            Ka2 = True
1784            lamRatio = 360*(parmDict[hfx+'Lam2']-parmDict[hfx+'Lam1'])/(np.pi*parmDict[hfx+'Lam1'])
1785            kRatio = parmDict[hfx+'I(L2)/I(L1)']
1786        else:
1787            wave = parmDict[hfx+'Lam']
1788    else:
1789        print 'TOF Undefined at present'
1790        raise ValueError
1791    for phase in Histogram['Reflection Lists']:
1792        refList = Histogram['Reflection Lists'][phase]
1793        Phase = Phases[phase]
1794        SGData = Phase['General']['SGData']
1795        pId = Phase['pId']
1796        pfx = '%d::'%(pId)
1797        phfx = '%d:%d:'%(pId,hId)
1798        A = [parmDict[pfx+'A%d'%(i)] for i in range(6)]
1799        G,g = G2lat.A2Gmat(A)       #recip & real metric tensors
1800        Vst = np.sqrt(nl.det(G))    #V*
1801        if 'Pawley' not in Phase['General']['Type']:
1802            dFdvDict = StructureFactorDerv(refList,G,hfx,pfx,SGData,calcControls,parmDict)
1803        sizeEllipse = []
1804        if calcControls[phfx+'SizeType'] == 'ellipsoidal':
1805            sizeEllipse = G2lat.U6toUij([parmDIct[phfx+'Size:%d'%(i)] for i in range(6)])
1806        for iref,refl in enumerate(refList):
1807            if 'C' in calcControls[hfx+'histType']:        #CW powder
1808                h,k,l = refl[:3]
1809                Lorenz = 1./(2.*sind(refl[5]/2.)**2*cosd(refl[5]/2.))           #Lorentz correction
1810                Icorr,dIdsh,dIdsp,dIdpola,dIdPO = GetIntensityDerv(refl,G,g,phfx,hfx,SGData,calcControls,parmDict)
1811                Icorr *= Vst*Lorenz
1812                if 'Pawley' in Phase['General']['Type']:
1813                    try:
1814                        refl[9] = abs(parmDict[pfx+'PWLref:%d'%(pawleyLookup[pfx+'%d,%d,%d'%(h,k,l)])])
1815                    except KeyError:
1816#                        print ' ***Error %d,%d,%d missing from Pawley reflection list ***'%(h,k,l)
1817                        continue
1818                Wd,fmin,fmax = G2pwd.getWidths(refl[5],refl[6],refl[7],shl)
1819                iBeg = np.searchsorted(x,refl[5]-fmin)
1820                iFin = np.searchsorted(x,refl[5]+fmax)
1821                if not iBeg+iFin:       #peak below low limit - skip peak
1822                    continue
1823                elif not iBeg-iFin:     #peak above high limit - done
1824                    break
1825                pos = refl[5]
1826                tanth = tand(pos/2.0)
1827                costh = cosd(pos/2.0)
1828                dMdpk = np.zeros(shape=(6,len(x)))
1829                dMdipk = G2pwd.getdFCJVoigt3(refl[5],refl[6],refl[7],shl,x[iBeg:iFin])
1830                for i in range(1,5):
1831                    dMdpk[i][iBeg:iFin] += 100.*dx*Icorr*refl[9]*dMdipk[i]
1832                dMdpk[0][iBeg:iFin] += 100.*dx*Icorr*refl[9]*dMdipk[0]
1833                dervDict = {'int':dMdpk[0],'pos':dMdpk[1],'sig':dMdpk[2],'gam':dMdpk[3],'shl':dMdpk[4]}
1834                if Ka2:
1835                    pos2 = refl[5]+lamRatio*tanth       # + 360/pi * Dlam/lam * tan(th)
1836                    kdelt = int((pos2-refl[5])/dx)               
1837                    iBeg2 = min(lenX,iBeg+kdelt)
1838                    iFin2 = min(lenX,iFin+kdelt)
1839                    if iBeg2-iFin2:
1840                        dMdipk2 = G2pwd.getdFCJVoigt3(pos2,refl[6],refl[7],shl,x[iBeg2:iFin2])
1841                        for i in range(1,5):
1842                            dMdpk[i][iBeg2:iFin2] += 100.*dx*Icorr*refl[9]*kRatio*dMdipk2[i]
1843                        dMdpk[0][iBeg2:iFin2] += 100.*dx*Icorr*refl[9]*kRatio*dMdipk2[0]
1844                        dMdpk[5][iBeg2:iFin2] += 100.*dx*Icorr*dMdipk2[0]
1845                        dervDict = {'int':dMdpk[0],'pos':dMdpk[1],'sig':dMdpk[2],'gam':dMdpk[3],'shl':dMdpk[4],'L1/L2':dMdpk[5]*refl[9]}
1846                if 'Pawley' in Phase['General']['Type']:
1847                    try:
1848                        idx = varylist.index(pfx+'PWLref:'+str(pawleyLookup[pfx+'%d,%d,%d'%(h,k,l)]))
1849                        dMdv[idx] = dervDict['int']/refl[9]
1850                    except ValueError:
1851                        pass
1852                dpdA,dpdw,dpdZ,dpdSh,dpdTr,dpdX,dpdY = GetReflPosDerv(refl,wave,A,hfx,calcControls,parmDict)
1853                names = {hfx+'Scale':[dIdsh,'int'],hfx+'Polariz.':[dIdpola,'int'],phfx+'Scale':[dIdsp,'int'],
1854                    hfx+'U':[tanth**2,'sig'],hfx+'V':[tanth,'sig'],hfx+'W':[1.0,'sig'],
1855                    hfx+'X':[1.0/costh,'gam'],hfx+'Y':[tanth,'gam'],hfx+'SH/L':[1.0,'shl'],
1856                    hfx+'I(L2)/I(L1)':[1.0,'L1/L2'],hfx+'Zero':[dpdZ,'pos'],hfx+'Lam':[dpdw,'pos'],
1857                    hfx+'Shift':[dpdSh,'pos'],hfx+'Transparency':[dpdTr,'pos'],hfx+'DisplaceX':[dpdX,'pos'],
1858                    hfx+'DisplaceY':[dpdY,'pos'],}
1859                for name in names:
1860                    if name in varylist:
1861                        item = names[name]
1862                        dMdv[varylist.index(name)] += item[0]*dervDict[item[1]]
1863                for iPO in dIdPO:
1864                    if iPO in varylist:
1865                        dMdv[varylist.index(iPO)] += dIdPO[iPO]*dervDict['int']
1866                cellDervNames = cellVaryDerv(pfx,SGData,dpdA)
1867                for name,dpdA in cellDervNames:
1868                    if name in varylist:
1869                        dMdv[varylist.index(name)] += dpdA*dervDict['pos']
1870                dDijDict = GetHStrainShiftDerv(refl,SGData,phfx)
1871                for name in dDijDict:
1872                    if name in varylist:
1873                        dMdv[varylist.index(name)] += dDijDict[name]*dervDict['pos']
1874                gamDict = GetSampleGamDerv(refl,wave,G,phfx,calcControls,parmDict,sizeEllipse)
1875                for name in gamDict:
1876                    if name in varylist:
1877                        dMdv[varylist.index(name)] += gamDict[name]*dervDict['gam']
1878                                               
1879            elif 'T' in calcControls[hfx+'histType']:
1880                print 'TOF Undefined at present'
1881                raise Exception    #no TOF yet
1882#do atom derivatives -  for F,X & U so far             
1883            corr = dervDict['int']/refl[9]
1884            for name in varylist:
1885                try:
1886                    aname = name.split(pfx)[1][:2]
1887                    if aname in ['Af','dA','AU']:
1888                         dMdv[varylist.index(name)] += dFdvDict[name][iref]*corr
1889                except IndexError:
1890                    pass
1891    return dMdv   
1892                   
1893def Refine(GPXfile,dlg):
1894    import cPickle
1895    import pytexture as ptx
1896    ptx.pyqlmninit()            #initialize fortran arrays for spherical harmonics
1897   
1898    def dervRefine(values,HistoPhases,parmdict,varylist,calcControls,pawleyLookup,dlg):
1899        parmdict.update(zip(varylist,values))
1900        G2mv.Dict2Map(parmDict)
1901        Histograms,Phases = HistoPhases
1902        dMdv = np.empty(0)
1903        for histogram in Histograms:
1904            if 'PWDR' in histogram[:4]:
1905                Histogram = Histograms[histogram]
1906                hId = Histogram['hId']
1907                hfx = ':%d:'%(hId)
1908                Limits = calcControls[hfx+'Limits']
1909                x,y,w,yc,yb,yd = Histogram['Data']
1910                xB = np.searchsorted(x,Limits[0])
1911                xF = np.searchsorted(x,Limits[1])
1912                dMdvh = np.sqrt(w[xB:xF])*getPowderProfileDerv(parmdict,x[xB:xF],
1913                    varylist,Histogram,Phases,calcControls,pawleyLookup)
1914                if len(dMdv):
1915                    dMdv = np.concatenate((dMdv,dMdvh))
1916                else:
1917                    dMdv = dMdvh
1918        return dMdv
1919   
1920    def errRefine(values,HistoPhases,parmdict,varylist,calcControls,pawleyLookup,dlg):       
1921        parmdict.update(zip(varylist,values))
1922        Values2Dict(parmdict, varylist, values)
1923        G2mv.Dict2Map(parmDict)
1924        Histograms,Phases = HistoPhases
1925        M = np.empty(0)
1926        sumwYo = 0
1927        Nobs = 0
1928        for histogram in Histograms:
1929            if 'PWDR' in histogram[:4]:
1930                Histogram = Histograms[histogram]
1931                hId = Histogram['hId']
1932                hfx = ':%d:'%(hId)
1933                Limits = calcControls[hfx+'Limits']
1934                x,y,w,yc,yb,yd = Histogram['Data']
1935                yc *= 0.0                           #zero full calcd profiles
1936                yb *= 0.0
1937                yd *= 0.0
1938                xB = np.searchsorted(x,Limits[0])
1939                xF = np.searchsorted(x,Limits[1])
1940                Nobs += xF-xB
1941                Histogram['sumwYo'] = np.sum(w[xB:xF]*y[xB:xF]**2)
1942                sumwYo += Histogram['sumwYo']
1943                yc[xB:xF],yb[xB:xF] = getPowderProfile(parmdict,x[xB:xF],
1944                    varylist,Histogram,Phases,calcControls,pawleyLookup)
1945                yc[xB:xF] *= parmDict[hfx+'Scale']
1946                yc[xB:xF] += yb[xB:xF]
1947                yd[xB:xF] = yc[xB:xF]-y[xB:xF]          #yc-yo then all dydv have no '-' needed
1948                Histogram['sumwYd'] = np.sum(np.sqrt(w[xB:xF])*(yd[xB:xF]))
1949                M = np.concatenate((M,np.sqrt(w[xB:xF])*(yd[xB:xF])))
1950        Histograms['sumwYo'] = sumwYo
1951        Histograms['Nobs'] = Nobs
1952        Rwp = min(100.,np.sqrt(np.sum(M**2)/sumwYo)*100.)
1953        if dlg:
1954            GoOn = dlg.Update(Rwp,newmsg='%s%8.3f%s'%('Powder profile Rwp =',Rwp,'%'))[0]
1955            if not GoOn:
1956                return -M           #abort!!
1957        return M
1958   
1959    ShowBanner()
1960    varyList = []
1961    parmDict = {}
1962    calcControls = {}
1963    G2mv.InitVars()   
1964    Controls = GetControls(GPXfile)
1965    ShowControls(Controls)           
1966    Histograms,Phases = GetUsedHistogramsAndPhases(GPXfile)
1967    if not Phases:
1968        print ' *** ERROR - you have no histograms to refine! ***'
1969        print ' *** Refine aborted ***'
1970        raise Exception
1971    if not Histograms:
1972        print ' *** ERROR - you have no data to refine with! ***'
1973        print ' *** Refine aborted ***'
1974        raise Exception
1975    Natoms,phaseVary,phaseDict,pawleyLookup,FFtables = GetPhaseData(Phases)
1976    calcControls['Natoms'] = Natoms
1977    calcControls['FFtables'] = FFtables
1978    hapVary,hapDict,controlDict = GetHistogramPhaseData(Phases,Histograms)
1979    calcControls.update(controlDict)
1980    histVary,histDict,controlDict = GetHistogramData(Histograms)
1981    calcControls.update(controlDict)
1982    varyList = phaseVary+hapVary+histVary
1983    parmDict.update(phaseDict)
1984    parmDict.update(hapDict)
1985    parmDict.update(histDict)
1986    GetFprime(calcControls,Histograms)
1987    constrDict,constrFlag,fixedList = G2mv.InputParse([])        #constraints go here?
1988    groups,parmlist = G2mv.GroupConstraints(constrDict)
1989    G2mv.GenerateConstraints(groups,parmlist,constrDict,constrFlag,fixedList)
1990    G2mv.Map2Dict(parmDict,varyList)
1991
1992    while True:
1993        begin = time.time()
1994        values =  np.array(Dict2Values(parmDict, varyList))
1995        Ftol = Controls['min dM/M']
1996        Factor = Controls['shift factor']
1997        if Controls['deriv type'] == 'analytic':
1998            result = so.leastsq(errRefine,values,Dfun=dervRefine,full_output=True,
1999                ftol=Ftol,col_deriv=True,factor=Factor,
2000                args=([Histograms,Phases],parmDict,varyList,calcControls,pawleyLookup,dlg))
2001            ncyc = int(result[2]['nfev']/2)               
2002        else:           #'numeric'
2003            result = so.leastsq(errRefine,values,full_output=True,ftol=Ftol,epsfcn=1.e-8,factor=Factor,
2004                args=([Histograms,Phases],parmDict,varyList,calcControls,pawleyLookup,dlg))
2005            ncyc = int(result[2]['nfev']/len(varyList))
2006#        table = dict(zip(varyList,zip(values,result[0],(result[0]-values))))
2007#        for item in table: print item,table[item]               #useful debug - are things shifting?
2008        runtime = time.time()-begin
2009        chisq = np.sum(result[2]['fvec']**2)
2010        Values2Dict(parmDict, varyList, result[0])
2011        G2mv.Dict2Map(parmDict)
2012        ApplyXYZshifts(parmDict,varyList)
2013       
2014        Rwp = np.sqrt(chisq/Histograms['sumwYo'])*100.      #to %
2015        GOF = chisq/(Histograms['Nobs']-len(varyList))
2016        print '\n Refinement results:'
2017        print 135*'-'
2018        print ' Number of function calls:',result[2]['nfev'],' Number of observations: ',Histograms['Nobs'],' Number of parameters: ',len(varyList)
2019        print ' Refinement time = %8.3fs, %8.3fs/cycle'%(runtime,runtime/ncyc)
2020        print ' Rwp = %7.2f%%, chi**2 = %12.6g, reduced chi**2 = %6.2f'%(Rwp,chisq,GOF)
2021        try:
2022            covMatrix = result[1]*GOF
2023            sig = np.sqrt(np.diag(covMatrix))
2024            xvar = np.outer(sig,np.ones_like(sig))
2025            cov = np.divide(np.divide(covMatrix,xvar),xvar.T)
2026            if np.any(np.isnan(sig)):
2027                print '*** Least squares aborted - some invalid esds possible ***'
2028#            table = dict(zip(varyList,zip(values,result[0],(result[0]-values)/sig)))
2029#            for item in table: print item,table[item]               #useful debug - are things shifting?
2030            break                   #refinement succeeded - finish up!
2031        except TypeError:          #result[1] is None on singular matrix
2032            print '**** Refinement failed - singular matrix ****'
2033            Ipvt = result[2]['ipvt']
2034            for i,ipvt in enumerate(Ipvt):
2035                if not np.sum(result[2]['fjac'],axis=1)[i]:
2036                    print 'Removing parameter: ',varyList[ipvt-1]
2037                    del(varyList[ipvt-1])
2038                    break
2039
2040#    print 'dependentParmList: ',G2mv.dependentParmList
2041#    print 'arrayList: ',G2mv.arrayList
2042#    print 'invarrayList: ',G2mv.invarrayList
2043#    print 'indParmList: ',G2mv.indParmList
2044#    print 'fixedDict: ',G2mv.fixedDict
2045    sigDict = dict(zip(varyList,sig))
2046    SetPhaseData(parmDict,sigDict,Phases)
2047    SetHistogramPhaseData(parmDict,sigDict,Phases,Histograms)
2048    SetHistogramData(parmDict,sigDict,Histograms)
2049    covData = {'variables':result[0],'varyList':varyList,'covariance':cov}
2050    SetUsedHistogramsAndPhases(GPXfile,Histograms,Phases,covData)
2051#for testing purposes!!!
2052#    file = open('structTestdata.dat','wb')
2053#    cPickle.dump(parmDict,file,1)
2054#    cPickle.dump(varyList,file,1)
2055#    for histogram in Histograms:
2056#        if 'PWDR' in histogram[:4]:
2057#            Histogram = Histograms[histogram]
2058#    cPickle.dump(Histogram,file,1)
2059#    cPickle.dump(Phases,file,1)
2060#    cPickle.dump(calcControls,file,1)
2061#    cPickle.dump(pawleyLookup,file,1)
2062#    file.close()
2063
2064def main():
2065    arg = sys.argv
2066    if len(arg) > 1:
2067        GPXfile = arg[1]
2068        if not ospath.exists(GPXfile):
2069            print 'ERROR - ',GPXfile," doesn't exist!"
2070            exit()
2071        GPXpath = ospath.dirname(arg[1])
2072        Refine(GPXfile,None)
2073    else:
2074        print 'ERROR - missing filename'
2075        exit()
2076    print "Done"
2077         
2078if __name__ == '__main__':
2079    main()
Note: See TracBrowser for help on using the repository browser.