source: trunk/GSASIIstruct.py @ 383

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

small fixes

  • Property svn:keywords set to Date Author Revision URL Id
File size: 90.5 KB
Line 
1#GSASIIstructure - structure computation routines
2########### SVN repository information ###################
3# $Date: 2011-10-05 18:40:37 +0000 (Wed, 05 Oct 2011) $
4# $Author: vondreele $
5# $Revision: 383 $
6# $URL: trunk/GSASIIstruct.py $
7# $Id: GSASIIstruct.py 383 2011-10-05 18:40:37Z 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        fb = [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        fa = 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            fb = np.sum(np.sum(fb,axis=1),axis=1)        #imaginary
1279        refl[9] = fa[0]**2+fb[1]**2+fb[0]+fa[1]**2
1280        refl[10] = atan2d(fb[0],fa[0])
1281    return refList
1282   
1283def StructureFactorDerv(refList,G,hfx,pfx,SGData,calcControls,parmDict):
1284    twopi = 2.0*np.pi
1285    twopisq = 2.0*np.pi**2
1286    ast = np.sqrt(np.diag(G))
1287    Mast = twopisq*np.multiply.outer(ast,ast)
1288    FFtables = calcControls['FFtables']
1289    FFdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata = GetAtomFXU(pfx,FFtables,calcControls,parmDict)
1290    FP = np.array([El[hfx+'FP'] for El in FFdata])
1291    FPP = np.array([El[hfx+'FPP'] for El in FFdata])
1292    maxPos = len(SGData['SGOps'])       
1293    Uij = np.array(G2lat.U6toUij(Uijdata))
1294    bij = Mast*Uij.T
1295    dFdvDict = {}
1296    dFdfr = np.zeros((len(refList),len(Mdata)))
1297    dFdx = np.zeros((len(refList),len(Mdata),3))
1298    dFdui = np.zeros((len(refList),len(Mdata)))
1299    dFdua = np.zeros((len(refList),len(Mdata),6))
1300    for iref,refl in enumerate(refList):
1301        H = np.array(refl[:3])
1302        SQ = 1./(2.*refl[4])**2          # or (sin(theta)/lambda)**2
1303        FF = np.array([G2el.ScatFac(El,SQ)[0] for El in FFdata])
1304        SQfactor = 8.0*SQ*np.pi**2
1305        Uniq = refl[11]
1306        phi = refl[12]
1307        phase = twopi*(np.inner((dXdata.T+Xdata.T),Uniq)+phi[np.newaxis,:])
1308        sinp = np.sin(phase)
1309        cosp = np.cos(phase)
1310        occ = Mdata*Fdata/len(Uniq)
1311        biso = -SQfactor*Uisodata
1312        Tiso = np.where(biso<1.,np.exp(biso),1.0)
1313#        HbH = np.array([-np.inner(h,np.inner(bij,h)) for h in Uniq])
1314        HbH = -np.inner(H,np.inner(bij,H))
1315        Hij = np.array([Mast*np.multiply.outer(U,U) for U in Uniq])
1316        Hij = np.array([G2lat.UijtoU6(Uij) for Uij in Hij])
1317        Tuij = np.where(HbH<1.,np.exp(HbH),1.0)
1318        Tcorr = Tiso*Tuij
1319        fot = (FF+FP)*occ*Tcorr
1320        fotp = FPP*occ*Tcorr
1321        fa = np.array([fot[:,np.newaxis]*cosp,fotp[:,np.newaxis]*cosp])       #non positions
1322        fb = np.array([fot[:,np.newaxis]*sinp,-fotp[:,np.newaxis]*sinp])
1323       
1324        fas = np.sum(np.sum(fa,axis=1),axis=1)
1325        fbs = np.sum(np.sum(fb,axis=1),axis=1)
1326        fax = np.array([-fot[:,np.newaxis]*sinp,-fotp[:,np.newaxis]*sinp])   #positions
1327        fbx = np.array([fot[:,np.newaxis]*cosp,-fot[:,np.newaxis]*cosp])
1328        #sum below is over Uniq
1329        dfadfr = np.sum(fa/occ[:,np.newaxis],axis=2)
1330        dfadx = np.sum(twopi*Uniq*fax[:,:,:,np.newaxis],axis=2)
1331        dfadui = np.sum(-SQfactor*fa,axis=2)
1332        dfadua = np.sum(-Hij*fa[:,:,:,np.newaxis],axis=2)
1333        #NB: the above have been checked against PA(1:10,1:2) in strfctr.for     
1334        dFdfr[iref] = 2.*(fas[0]*dfadfr[0]+fas[1]*dfadfr[1])*Mdata/len(Uniq)
1335        dFdx[iref] = 2.*(fas[0]*dfadx[0]+fas[1]*dfadx[1])
1336        dFdui[iref] = 2.*(fas[0]*dfadui[0]+fas[1]*dfadui[1])
1337        dFdua[iref] = 2.*(fas[0]*dfadua[0]+fas[1]*dfadua[1])
1338        if not SGData['SGInv']:
1339            dfbdfr = np.sum(fb/occ[:,np.newaxis],axis=2)
1340            dfbdx = np.sum(twopi*Uniq*fbx[:,:,:,np.newaxis],axis=2)         
1341            dfbdui = np.sum(-SQfactor*fb,axis=2)
1342            dfbdua = np.sum(-Hij*fb[:,:,:,np.newaxis],axis=2)
1343            dFdfr[iref] += 2.*(fbs[0]*dfbdfr[0]-fbs[1]*dfbdfr[1])*Mdata/len(Uniq)
1344            dFdx[iref] += 2.*(fbs[0]*dfbdx[0]+fbs[1]*dfbdx[1])
1345            dFdui[iref] += 2.*(fbs[0]*dfbdui[0]-fbs[1]*dfbdui[1])
1346            dFdua[iref] += 2.*(fbs[0]*dfbdua[0]+fbs[1]*dfbdua[1])
1347        #loop over atoms - each dict entry is list of derivatives for all the reflections
1348    for i in range(len(Mdata)):     
1349        dFdvDict[pfx+'Afrac:'+str(i)] = dFdfr.T[i]
1350        dFdvDict[pfx+'dAx:'+str(i)] = dFdx.T[0][i]
1351        dFdvDict[pfx+'dAy:'+str(i)] = dFdx.T[1][i]
1352        dFdvDict[pfx+'dAz:'+str(i)] = dFdx.T[2][i]
1353        dFdvDict[pfx+'AUiso:'+str(i)] = dFdui.T[i]
1354        dFdvDict[pfx+'AU11:'+str(i)] = dFdua.T[0][i]
1355        dFdvDict[pfx+'AU22:'+str(i)] = dFdua.T[1][i]
1356        dFdvDict[pfx+'AU33:'+str(i)] = dFdua.T[2][i]
1357        dFdvDict[pfx+'AU12:'+str(i)] = 2.*dFdua.T[3][i]
1358        dFdvDict[pfx+'AU13:'+str(i)] = 2.*dFdua.T[4][i]
1359        dFdvDict[pfx+'AU23:'+str(i)] = 2.*dFdua.T[5][i]
1360    return dFdvDict
1361       
1362def Dict2Values(parmdict, varylist):
1363    '''Use before call to leastsq to setup list of values for the parameters
1364    in parmdict, as selected by key in varylist'''
1365    return [parmdict[key] for key in varylist] 
1366   
1367def Values2Dict(parmdict, varylist, values):
1368    ''' Use after call to leastsq to update the parameter dictionary with
1369    values corresponding to keys in varylist'''
1370    parmdict.update(zip(varylist,values))
1371   
1372def ApplyXYZshifts(parmDict,varyList):
1373    ''' takes atom x,y,z shift and applies it to corresponding atom x,y,z value
1374    '''
1375    for vary in varyList:
1376        if 'dA' in vary:
1377            parm = ''.join(vary.split('d'))
1378            parmDict[parm] += parmDict[vary]
1379   
1380def SHPOcal(refl,g,phfx,hfx,SGData,calcControls,parmDict):
1381    odfCor = 1.0
1382    H = refl[:3]
1383    cell = G2lat.Gmat2cell(g)
1384    Sangl = [0.,0.,0.]
1385    if 'Bragg' in calcControls[hfx+'instType']:
1386        Gangls = [0.,90.,0.,parmDict[hfx+'Azimuth']]
1387        IFCoup = True
1388    else:
1389        Gangls = [0.,0.,0.,parmDict[hfx+'Azimuth']]
1390        IFCoup = False
1391    phi,beta = G2lat.CrsAng(H,cell,SGData)
1392    psi,gam,x,x = G2lat.SamAng(refl[5]/2.,Gangls,Sangl,IFCoup) #ignore 2 sets of angle derivs.
1393    SHnames = G2lat.GenSHCoeff(SGData['SGLaue'],None,calcControls[phfx+'SHord'])
1394    for item in SHnames:
1395        L,N = eval(item.strip('C'))
1396        Kcsl,Lnorm = G2lat.GetKclKsl(L,N,SGData['SGLaue'],psi,phi,beta) 
1397        odfCor += parmDict[phfx+item]*Lnorm*Kcsl
1398    return odfCor
1399   
1400def SHPOcalDerv(refl,g,phfx,hfx,SGData,calcControls,parmDict):
1401    FORPI = 12.5663706143592
1402    odfCor = 1.0
1403    dFdODF = {}
1404    H = refl[:3]
1405    cell = G2lat.Gmat2cell(g)
1406    Sangl = [0.,0.,0.]
1407    if 'Bragg' in calcControls[hfx+'instType']:
1408        Gangls = [0.,90.,0.,parmDict[hfx+'Azimuth']]
1409        IFCoup = True
1410    else:
1411        Gangls = [0.,0.,0.,parmDict[hfx+'Azimuth']]
1412        IFCoup = False
1413    phi,beta = G2lat.CrsAng(H,cell,SGData)
1414    psi,gam,x,x = G2lat.SamAng(refl[5]/2.,Gangls,Sangl,IFCoup) #ignore 2 sets of angle derivs.
1415    SHnames = G2lat.GenSHCoeff(SGData['SGLaue'],None,calcControls[phfx+'SHord'])
1416    for item in SHnames:
1417        L,N = eval(item.strip('C'))
1418        Kcsl,Lnorm = G2lat.GetKclKsl(L,N,SGData['SGLaue'],psi,phi,beta) 
1419        odfCor += parmDict[phfx+item]*Lnorm*Kcsl
1420        dFdODF[phfx+item] = FORPI*Kcsl
1421    return odfCor,dFdODF
1422   
1423def GetPrefOri(refl,G,g,phfx,hfx,SGData,calcControls,parmDict):
1424    if calcControls[phfx+'poType'] == 'MD':
1425        MD = parmDict[phfx+'MD']
1426        MDAxis = calcControls[phfx+'MDAxis']
1427        sumMD = 0
1428        for H in refl[11]:           
1429            cosP,sinP = G2lat.CosSinAngle(H,MDAxis,G)
1430            A = 1.0/np.sqrt((MD*cosP)**2+sinP**2/MD)
1431            sumMD += A**3
1432        POcorr = sumMD/len(refl[11])
1433    else:   #spherical harmonics
1434        POcorr = SHPOcal(refl,g,phfx,hfx,SGData,calcControls,parmDict)
1435    return POcorr
1436   
1437def GetPrefOriDerv(refl,G,g,phfx,hfx,SGData,calcControls,parmDict):
1438    POderv = {}
1439    if calcControls[phfx+'poType'] == 'MD':
1440        MD = parmDict[phfx+'MD']
1441        MDAxis = calcControls[phfx+'MDAxis']
1442        sumMD = 0
1443        sumdMD = 0
1444        for H in refl[11]:           
1445            cosP,sinP = G2lat.CosSinAngle(H,MDAxis,G)
1446            A = 1.0/np.sqrt((MD*cosP)**2+sinP**2/MD)
1447            sumMD += A**3
1448            sumdMD -= (1.5*A**5)*(2.0*MD*cosP**2-(sinP/MD)**2)
1449        POcorr = sumMD/len(refl[11])
1450        POderv[phfx+'MD'] = sumdMD/len(refl[11])
1451    else:   #spherical harmonics
1452        POcorr,POderv = SHPOcalDerv(refl,g,phfx,hfx,SGData,calcControls,parmDict)
1453    return POcorr,POderv
1454   
1455def GetIntensityCorr(refl,G,g,phfx,hfx,SGData,calcControls,parmDict):
1456    Icorr = parmDict[phfx+'Scale']*parmDict[hfx+'Scale']*refl[3]               #scale*multiplicity
1457    Icorr *= G2pwd.Polarization(parmDict[hfx+'Polariz.'],refl[5],parmDict[hfx+'Azimuth'])[0]
1458    Icorr *= GetPrefOri(refl,G,g,phfx,hfx,SGData,calcControls,parmDict)       
1459    return Icorr
1460   
1461def GetIntensityDerv(refl,G,g,phfx,hfx,SGData,calcControls,parmDict):
1462    Icorr = GetIntensityCorr(refl,G,g,phfx,hfx,SGData,calcControls,parmDict)
1463    pola,dIdPola = G2pwd.Polarization(parmDict[hfx+'Polariz.'],refl[5],parmDict[hfx+'Azimuth'])
1464    POcorr,dIdPO = GetPrefOriDerv(refl,G,g,phfx,hfx,SGData,calcControls,parmDict)
1465    dIdPola /= pola
1466    for iPO in dIdPO:
1467        dIdPO[iPO] /= POcorr
1468    dIdsh = 1./parmDict[hfx+'Scale']
1469    dIdsp = 1./parmDict[phfx+'Scale']
1470    return Icorr,dIdsh,dIdsp,dIdPola,dIdPO
1471       
1472def GetSampleGam(refl,wave,G,phfx,calcControls,parmDict,sizeEllipse):
1473    costh = cosd(refl[5]/2.)
1474    #crystallite size
1475    if calcControls[phfx+'SizeType'] == 'isotropic':
1476        gam = 1.8*wave/(np.pi*parmDict[phfx+'Size:0']*costh)
1477    elif calcControls[phfx+'SizeType'] == 'uniaxial':
1478        H = np.array(refl[:3])
1479        P = np.array(calcControls[phfx+'SizeAxis'])
1480        cosP,sinP = G2lat.CosSinAngle(H,P,G)
1481        gam = (1.8*wave/np.pi)/(parmDict[phfx+'Size:0']*parmDict[phfx+'Size:1']*costh)
1482        gam *= np.sqrt((cosP*parmDict[phfx+'Size:1'])**2+(sinP*parmDict[phfx+'Size:0'])**2)
1483    else:           #ellipsoidal crystallites - wrong not make sense
1484        H = np.array(refl[:3])
1485        gam += 1.8*wave/(np.pi*costh*np.inner(H,np.inner(sizeEllipse,H)))
1486    #microstrain               
1487    if calcControls[phfx+'MustrainType'] == 'isotropic':
1488        gam += 0.018*parmDict[phfx+'Mustrain:0']*tand(refl[5]/2.)/np.pi
1489    elif calcControls[phfx+'MustrainType'] == 'uniaxial':
1490        H = np.array(refl[:3])
1491        P = np.array(calcControls[phfx+'MustrainAxis'])
1492        cosP,sinP = G2lat.CosSinAngle(H,P,G)
1493        Si = parmDict[phfx+'Mustrain:0']
1494        Sa = parmDict[phfx+'Mustrain:1']
1495        gam += 0.018*Si*Sa*tand(refl[5]/2.)/(np.pi*np.sqrt((Si*cosP)**2+(Sa*sinP)**2))
1496    else:       #generalized - P.W. Stephens model
1497        pwrs = calcControls[phfx+'MuPwrs']
1498        sum = 0
1499        for i,pwr in enumerate(pwrs):
1500            sum += parmDict[phfx+'Mustrain:'+str(i)]*refl[0]**pwr[0]*refl[1]**pwr[1]*refl[2]**pwr[2]
1501        gam += 0.018*refl[4]**2*tand(refl[5]/2.)*sum           
1502    return gam
1503       
1504def GetSampleGamDerv(refl,wave,G,phfx,calcControls,parmDict,sizeEllipse):
1505    gamDict = {}
1506    costh = cosd(refl[5]/2.)
1507    tanth = tand(refl[5]/2.)
1508    #crystallite size derivatives
1509    if calcControls[phfx+'SizeType'] == 'isotropic':
1510        gamDict[phfx+'Size:0'] = -1.80*wave/(np.pi*costh)
1511    elif calcControls[phfx+'SizeType'] == 'uniaxial':
1512        H = np.array(refl[:3])
1513        P = np.array(calcControls[phfx+'SizeAxis'])
1514        cosP,sinP = G2lat.CosSinAngle(H,P,G)
1515        Si = parmDict[phfx+'Size:0']
1516        Sa = parmDict[phfx+'Size:1']
1517        gami = (1.80*wave/np.pi)/(Si*Sa)
1518        sqtrm = np.sqrt((cosP*Sa)**2+(sinP*Si)**2)
1519        gam = gami*sqtrm/costh           
1520        gamDict[phfx+'Size:0'] = gami*Si*sinP**2/(sqtrm*costh)-gam/Si
1521        gamDict[phfx+'Size:1'] = gami*Sa*cosP**2/(sqtrm*costh)-gam/Sa         
1522    else:           #ellipsoidal crystallites - do numerically? - not right not make sense
1523        H = np.array(refl[:3])
1524        gam = 1.8*wave/(np.pi*costh*np.inner(H,np.inner(sizeEllipse,H)))
1525    #microstrain derivatives               
1526    if calcControls[phfx+'MustrainType'] == 'isotropic':
1527        gamDict[phfx+'Mustrain:0'] =  0.018*tanth/np.pi           
1528    elif calcControls[phfx+'MustrainType'] == 'uniaxial':
1529        H = np.array(refl[:3])
1530        P = np.array(calcControls[phfx+'MustrainAxis'])
1531        cosP,sinP = G2lat.CosSinAngle(H,P,G)
1532        Si = parmDict[phfx+'Mustrain:0']
1533        Sa = parmDict[phfx+'Mustrain:1']
1534        gami = 0.018*Si*Sa*tanth/np.pi
1535        sqtrm = np.sqrt((Si*cosP)**2+(Sa*sinP)**2)
1536        gam = gami/sqtrm
1537        gamDict[phfx+'Mustrain:0'] = gam/Si-gami*Si*cosP**2/sqtrm**3
1538        gamDict[phfx+'Mustrain:1'] = gam/Sa-gami*Sa*sinP**2/sqtrm**3
1539    else:       #generalized - P.W. Stephens model
1540        pwrs = calcControls[phfx+'MuPwrs']
1541        const = 0.018*refl[4]**2*tanth
1542        for i,pwr in enumerate(pwrs):
1543            gamDict[phfx+'Mustrain:'+str(i)] = const*refl[0]**pwr[0]*refl[1]**pwr[1]*refl[2]**pwr[2]
1544    return gamDict
1545       
1546def GetReflPos(refl,wave,G,hfx,calcControls,parmDict):
1547    h,k,l = refl[:3]
1548    dsq = 1./G2lat.calc_rDsq2(np.array([h,k,l]),G)
1549    d = np.sqrt(dsq)
1550    refl[4] = d
1551    pos = 2.0*asind(wave/(2.0*d))+parmDict[hfx+'Zero']
1552    const = 9.e-2/(np.pi*parmDict[hfx+'Gonio. radius'])                  #shifts in microns
1553    if 'Bragg' in calcControls[hfx+'instType']:
1554        pos -= const*(4.*parmDict[hfx+'Shift']*cosd(pos/2.0)+ \
1555            parmDict[hfx+'Transparency']*sind(pos)*100.0)            #trans(=1/mueff) in cm
1556    else:               #Debye-Scherrer - simple but maybe not right
1557        pos -= const*(parmDict[hfx+'DisplaceX']*cosd(pos)+parmDict[hfx+'DisplaceY']*sind(pos))
1558    return pos
1559
1560def GetReflPosDerv(refl,wave,A,hfx,calcControls,parmDict):
1561    dpr = 180./np.pi
1562    h,k,l = refl[:3]
1563    dstsq = G2lat.calc_rDsq(np.array([h,k,l]),A)
1564    dst = np.sqrt(dstsq)
1565    pos = refl[5]
1566    const = dpr/np.sqrt(1.0-wave*dst/4.0)
1567    dpdw = const*dst
1568    dpdA = np.array([h**2,k**2,l**2,h*k,h*l,k*l])
1569    dpdA *= const*wave/(2.0*dst)
1570    dpdZ = 1.0
1571    const = 9.e-2/(np.pi*parmDict[hfx+'Gonio. radius'])                  #shifts in microns
1572    if 'Bragg' in calcControls[hfx+'instType']:
1573        dpdSh = -4.*const*cosd(pos/2.0)
1574        dpdTr = -const*sind(pos)*100.0
1575        return dpdA,dpdw,dpdZ,dpdSh,dpdTr,0.,0.
1576    else:               #Debye-Scherrer - simple but maybe not right
1577        dpdXd = -const*cosd(pos)
1578        dpdYd = -const*sind(pos)
1579        return dpdA,dpdw,dpdZ,0.,0.,dpdXd,dpdYd
1580           
1581def GetHStrainShift(refl,SGData,phfx,parmDict):
1582    laue = SGData['SGLaue']
1583    uniq = SGData['SGUniq']
1584    h,k,l = refl[:3]
1585    if laue in ['m3','m3m']:
1586        Dij = parmDict[phfx+'D11']*(h**2+k**2+l**2)
1587    elif laue in ['6/m','6/mmm','3m1','31m','3']:
1588        Dij = parmDict[phfx+'D11']*(h**2+k**2+h*k)+parmDict[phfx+'D33']*l**2
1589    elif laue in ['3R','3mR']:
1590        Dij = parmDict[phfx+'D11']*(h**2+k**2+l**2)+parmDict[phfx+'D12']*(h*k+h*l+k*l)
1591    elif laue in ['4/m','4/mmm']:
1592        Dij = parmDict[phfx+'D11']*(h**2+k**2)+parmDict[phfx+'D33']*l**2
1593    elif laue in ['mmm']:
1594        Dij = parmDict[phfx+'D11']*h**2+parmDict[phfx+'D22']*k**2+parmDict[phfx+'D33']*l**2
1595    elif laue in ['2/m']:
1596        Dij = parmDict[phfx+'D11']*h**2+parmDict[phfx+'D22']*k**2+parmDict[phfx+'D33']*l**2
1597        if uniq == 'a':
1598            Dij += parmDict[phfx+'D23']*k*l
1599        elif uniq == 'b':
1600            Dij += parmDict[phfx+'D13']*h*l
1601        elif uniq == 'c':
1602            Dij += parmDict[phfx+'D12']*h*k
1603    else:
1604        Dij = parmDict[phfx+'D11']*h**2+parmDict[phfx+'D22']*k**2+parmDict[phfx+'D33']*l**2+ \
1605            parmDict[phfx+'D12']*h*k+parmDict[phfx+'D13']*h*l+parmDict[phfx+'D23']*k*l
1606    return Dij*refl[4]**2*tand(refl[5]/2.0)
1607           
1608def GetHStrainShiftDerv(refl,SGData,phfx):
1609    laue = SGData['SGLaue']
1610    uniq = SGData['SGUniq']
1611    h,k,l = refl[:3]
1612    if laue in ['m3','m3m']:
1613        dDijDict = {phfx+'D11':h**2+k**2+l**2,}
1614    elif laue in ['6/m','6/mmm','3m1','31m','3']:
1615        dDijDict = {phfx+'D11':h**2+k**2+h*k,phfx+'D33':l**2}
1616    elif laue in ['3R','3mR']:
1617        dDijDict = {phfx+'D11':h**2+k**2+l**2,phfx+'D12':h*k+h*l+k*l}
1618    elif laue in ['4/m','4/mmm']:
1619        dDijDict = {phfx+'D11':h**2+k**2,phfx+'D33':l**2}
1620    elif laue in ['mmm']:
1621        dDijDict = {phfx+'D11':h**2,phfx+'D22':k**2,phfx+'D33':l**2}
1622    elif laue in ['2/m']:
1623        dDijDict = {phfx+'D11':h**2,phfx+'D22':k**2,phfx+'D33':l**2}
1624        if uniq == 'a':
1625            dDijDict[phfx+'D23'] = k*l
1626        elif uniq == 'b':
1627            dDijDict[phfx+'D13'] = h*l
1628        elif uniq == 'c':
1629            dDijDict[phfx+'D12'] = h*k
1630            names.append()
1631    else:
1632        dDijDict = {phfx+'D11':h**2,phfx+'D22':k**2,phfx+'D33':l**2,
1633            phfx+'D12':h*k,phfx+'D13':h*l,phfx+'D23':k*l}
1634    for item in dDijDict:
1635        dDijDict[item] *= refl[4]**2*tand(refl[5]/2.0)
1636    return dDijDict
1637   
1638def GetFprime(controlDict,Histograms):
1639    FFtables = controlDict['FFtables']
1640    if not FFtables:
1641        return
1642    for histogram in Histograms:
1643        if 'PWDR' in histogram[:4]:
1644            Histogram = Histograms[histogram]
1645            hId = Histogram['hId']
1646            hfx = ':%d:'%(hId)
1647            keV = controlDict[hfx+'keV']
1648            for El in FFtables:
1649                Orbs = G2el.GetXsectionCoeff(El.split('+')[0].split('-')[0])
1650                FP,FPP,Mu = G2el.FPcalc(Orbs, keV)
1651                FFtables[El][hfx+'FP'] = FP
1652                FFtables[El][hfx+'FPP'] = FPP               
1653           
1654def getPowderProfile(parmDict,x,varylist,Histogram,Phases,calcControls,pawleyLookup):
1655   
1656    def GetReflSIgGam(refl,wave,G,hfx,phfx,calcControls,parmDict,sizeEllipse):
1657        U = parmDict[hfx+'U']
1658        V = parmDict[hfx+'V']
1659        W = parmDict[hfx+'W']
1660        X = parmDict[hfx+'X']
1661        Y = parmDict[hfx+'Y']
1662        tanPos = tand(refl[5]/2.0)
1663        sig = U*tanPos**2+V*tanPos+W        #save peak sigma
1664        sig = max(0.001,sig)
1665        gam = X/cosd(refl[5]/2.0)+Y*tanPos+GetSampleGam(refl,wave,G,phfx,calcControls,parmDict,sizeEllipse) #save peak gamma
1666        gam = max(0.001,gam)
1667        return sig,gam
1668               
1669    hId = Histogram['hId']
1670    hfx = ':%d:'%(hId)
1671    bakType = calcControls[hfx+'bakType']
1672    yb = G2pwd.getBackground(hfx,parmDict,bakType,x)
1673    yc = np.zeros_like(yb)
1674       
1675    if 'C' in calcControls[hfx+'histType']:   
1676        shl = max(parmDict[hfx+'SH/L'],0.002)
1677        Ka2 = False
1678        if hfx+'Lam1' in parmDict.keys():
1679            wave = parmDict[hfx+'Lam1']
1680            Ka2 = True
1681            lamRatio = 360*(parmDict[hfx+'Lam2']-parmDict[hfx+'Lam1'])/(np.pi*parmDict[hfx+'Lam1'])
1682            kRatio = parmDict[hfx+'I(L2)/I(L1)']
1683        else:
1684            wave = parmDict[hfx+'Lam']
1685    else:
1686        print 'TOF Undefined at present'
1687        raise ValueError
1688    for phase in Histogram['Reflection Lists']:
1689        refList = Histogram['Reflection Lists'][phase]
1690        Phase = Phases[phase]
1691        pId = Phase['pId']
1692        pfx = '%d::'%(pId)
1693        phfx = '%d:%d:'%(pId,hId)
1694        hfx = ':%d:'%(hId)
1695        SGData = Phase['General']['SGData']
1696        A = [parmDict[pfx+'A%d'%(i)] for i in range(6)]
1697        G,g = G2lat.A2Gmat(A)       #recip & real metric tensors
1698        Vst = np.sqrt(nl.det(G))    #V*
1699        if 'Pawley' not in Phase['General']['Type']:
1700            refList = StructureFactor(refList,G,hfx,pfx,SGData,calcControls,parmDict)
1701        sizeEllipse = []
1702        if calcControls[phfx+'SizeType'] == 'ellipsoidal':
1703            sizeEllipse = G2lat.U6toUij([parmDIct[phfx+'Size:%d'%(i)] for i in range(6)])
1704        for refl in refList:
1705            if 'C' in calcControls[hfx+'histType']:
1706                h,k,l = refl[:3]
1707                refl[5] = GetReflPos(refl,wave,G,hfx,calcControls,parmDict)         #corrected reflection position
1708                Lorenz = 1./(2.*sind(refl[5]/2.)**2*cosd(refl[5]/2.))           #Lorentz correction
1709                refl[5] += GetHStrainShift(refl,SGData,phfx,parmDict)               #apply hydrostatic strain shift
1710                refl[6:8] = GetReflSIgGam(refl,wave,G,hfx,phfx,calcControls,parmDict,sizeEllipse)    #peak sig & gam
1711                Icorr = GetIntensityCorr(refl,G,g,phfx,hfx,SGData,calcControls,parmDict)*Vst*Lorenz
1712                if 'Pawley' in Phase['General']['Type']:
1713                    try:
1714                        refl[9] = abs(parmDict[pfx+'PWLref:%d'%(pawleyLookup[pfx+'%d,%d,%d'%(h,k,l)])])
1715                    except KeyError:
1716#                        print ' ***Error %d,%d,%d missing from Pawley reflection list ***'%(h,k,l)
1717                        continue
1718                Wd,fmin,fmax = G2pwd.getWidths(refl[5],refl[6],refl[7],shl)
1719                iBeg = np.searchsorted(x,refl[5]-fmin)
1720                iFin = np.searchsorted(x,refl[5]+fmax)
1721                if not iBeg+iFin:       #peak below low limit - skip peak
1722                    continue
1723                elif not iBeg-iFin:     #peak above high limit - done
1724                    break
1725                yc[iBeg:iFin] += Icorr*refl[9]*G2pwd.getFCJVoigt3(refl[5],refl[6],refl[7],shl,x[iBeg:iFin])    #>90% of time spent here
1726                if Ka2:
1727                    pos2 = refl[5]+lamRatio*tand(refl[5]/2.0)       # + 360/pi * Dlam/lam * tan(th)
1728                    Wd,fmin,fmax = G2pwd.getWidths(pos2,refl[6],refl[7],shl)
1729                    iBeg = np.searchsorted(x,pos2-fmin)
1730                    iFin = np.searchsorted(x,pos2+fmax)
1731                    if not iBeg+iFin:       #peak below low limit - skip peak
1732                        continue
1733                    elif not iBeg-iFin:     #peak above high limit - done
1734                        return yc,yb
1735                    yc[iBeg:iFin] += Icorr*refl[9]*kRatio*G2pwd.getFCJVoigt3(pos2,refl[6],refl[7],shl,x[iBeg:iFin])        #and here
1736            elif 'T' in calcControls[hfx+'histType']:
1737                print 'TOF Undefined at present'
1738                raise ValueError    #no TOF yet
1739    return yc,yb   
1740           
1741def getPowderProfileDerv(parmDict,x,varylist,Histogram,Phases,calcControls,pawleyLookup):
1742   
1743    def cellVaryDerv(pfx,SGData,dpdA): 
1744        if SGData['SGLaue'] in ['-1',]:
1745            return [[pfx+'A0',dpdA[0]],[pfx+'A1',dpdA[1]],[pfx+'A2',dpdA[2]],
1746                [pfx+'A3',dpdA[3]],[pfx+'A4',dpdA[4]],[pfx+'A5',dpdA[5]]]
1747        elif SGData['SGLaue'] in ['2/m',]:
1748            if SGData['SGUniq'] == 'a':
1749                return [[pfx+'A0',dpdA[0]],[pfx+'A1',dpdA[1]],[pfx+'A2',dpdA[2]],[pfx+'A3',dpdA[3]]]
1750            elif SGData['SGUniq'] == 'b':
1751                return [[pfx+'A0',dpdA[0]],[pfx+'A1',dpdA[1]],[pfx+'A2',dpdA[2]],[pfx+'A4',dpdA[4]]]
1752            else:
1753                return [[pfx+'A0',dpdA[0]],[pfx+'A1',dpdA[1]],[pfx+'A2',dpdA[2]],[pfx+'A5',dpdA[5]]]
1754        elif SGData['SGLaue'] in ['mmm',]:
1755            return [[pfx+'A0',dpdA[0]],[pfx+'A1',dpdA[1]],[pfx+'A2',dpdA[2]]]
1756        elif SGData['SGLaue'] in ['4/m','4/mmm']:
1757            return [[pfx+'A0',dpdA[0]+dpdA[1]],[pfx+'A2',dpdA[2]]]
1758        elif SGData['SGLaue'] in ['6/m','6/mmm','3m1', '31m', '3']:
1759            return [[pfx+'A0',dpdA[0]+dpdA[1]+dpdA[3]],[pfx+'A2',dpdA[2]]]
1760        elif SGData['SGLaue'] in ['3R', '3mR']:
1761            return [[pfx+'A0',dpdA[0]+dpdA[1]+dpdA[2]],[pfx+'A3',dpdA[3]+dpdA[4]+dpdA[5]]]                       
1762        elif SGData['SGLaue'] in ['m3m','m3']:
1763            return [[pfx+'A0',dpdA[0]+dpdA[1]+dpdA[2]]]
1764   
1765    lenX = len(x)               
1766    hId = Histogram['hId']
1767    hfx = ':%d:'%(hId)
1768    bakType = calcControls[hfx+'bakType']
1769    dMdv = np.zeros(shape=(len(varylist),len(x)))
1770    if hfx+'Back:0' in varylist:
1771        dMdb = G2pwd.getBackgroundDerv(hfx,parmDict,bakType,x)
1772        bBpos =varylist.index(hfx+'Back:0')
1773        dMdv[bBpos:bBpos+len(dMdb)] = dMdb
1774       
1775    if 'C' in calcControls[hfx+'histType']:   
1776        dx = x[1]-x[0]
1777        shl = max(parmDict[hfx+'SH/L'],0.002)
1778        Ka2 = False
1779        if hfx+'Lam1' in parmDict.keys():
1780            wave = parmDict[hfx+'Lam1']
1781            Ka2 = True
1782            lamRatio = 360*(parmDict[hfx+'Lam2']-parmDict[hfx+'Lam1'])/(np.pi*parmDict[hfx+'Lam1'])
1783            kRatio = parmDict[hfx+'I(L2)/I(L1)']
1784        else:
1785            wave = parmDict[hfx+'Lam']
1786    else:
1787        print 'TOF Undefined at present'
1788        raise ValueError
1789    for phase in Histogram['Reflection Lists']:
1790        refList = Histogram['Reflection Lists'][phase]
1791        Phase = Phases[phase]
1792        SGData = Phase['General']['SGData']
1793        pId = Phase['pId']
1794        pfx = '%d::'%(pId)
1795        phfx = '%d:%d:'%(pId,hId)
1796        A = [parmDict[pfx+'A%d'%(i)] for i in range(6)]
1797        G,g = G2lat.A2Gmat(A)       #recip & real metric tensors
1798        Vst = np.sqrt(nl.det(G))    #V*
1799        if 'Pawley' not in Phase['General']['Type']:
1800            dFdvDict = StructureFactorDerv(refList,G,hfx,pfx,SGData,calcControls,parmDict)
1801        sizeEllipse = []
1802        if calcControls[phfx+'SizeType'] == 'ellipsoidal':
1803            sizeEllipse = G2lat.U6toUij([parmDIct[phfx+'Size:%d'%(i)] for i in range(6)])
1804        for iref,refl in enumerate(refList):
1805            if 'C' in calcControls[hfx+'histType']:        #CW powder
1806                h,k,l = refl[:3]
1807                Lorenz = 1./(2.*sind(refl[5]/2.)**2*cosd(refl[5]/2.))           #Lorentz correction
1808                Icorr,dIdsh,dIdsp,dIdpola,dIdPO = GetIntensityDerv(refl,G,g,phfx,hfx,SGData,calcControls,parmDict)
1809                Icorr *= Vst*Lorenz
1810                if 'Pawley' in Phase['General']['Type']:
1811                    try:
1812                        refl[9] = abs(parmDict[pfx+'PWLref:%d'%(pawleyLookup[pfx+'%d,%d,%d'%(h,k,l)])])
1813                    except KeyError:
1814#                        print ' ***Error %d,%d,%d missing from Pawley reflection list ***'%(h,k,l)
1815                        continue
1816                Wd,fmin,fmax = G2pwd.getWidths(refl[5],refl[6],refl[7],shl)
1817                iBeg = np.searchsorted(x,refl[5]-fmin)
1818                iFin = np.searchsorted(x,refl[5]+fmax)
1819                if not iBeg+iFin:       #peak below low limit - skip peak
1820                    continue
1821                elif not iBeg-iFin:     #peak above high limit - done
1822                    break
1823                pos = refl[5]
1824                tanth = tand(pos/2.0)
1825                costh = cosd(pos/2.0)
1826                dMdpk = np.zeros(shape=(6,len(x)))
1827                dMdipk = G2pwd.getdFCJVoigt3(refl[5],refl[6],refl[7],shl,x[iBeg:iFin])
1828                for i in range(1,5):
1829                    dMdpk[i][iBeg:iFin] += 100.*dx*Icorr*refl[9]*dMdipk[i]
1830                dMdpk[0][iBeg:iFin] += 100.*dx*Icorr*refl[9]*dMdipk[0]
1831                dervDict = {'int':dMdpk[0],'pos':dMdpk[1],'sig':dMdpk[2],'gam':dMdpk[3],'shl':dMdpk[4]}
1832                if Ka2:
1833                    pos2 = refl[5]+lamRatio*tanth       # + 360/pi * Dlam/lam * tan(th)
1834                    kdelt = int((pos2-refl[5])/dx)               
1835                    iBeg2 = min(lenX,iBeg+kdelt)
1836                    iFin2 = min(lenX,iFin+kdelt)
1837                    if iBeg2-iFin2:
1838                        dMdipk2 = G2pwd.getdFCJVoigt3(pos2,refl[6],refl[7],shl,x[iBeg2:iFin2])
1839                        for i in range(1,5):
1840                            dMdpk[i][iBeg2:iFin2] += 100.*dx*Icorr*refl[9]*kRatio*dMdipk2[i]
1841                        dMdpk[0][iBeg2:iFin2] += 100.*dx*Icorr*refl[9]*kRatio*dMdipk2[0]
1842                        dMdpk[5][iBeg2:iFin2] += 100.*dx*Icorr*dMdipk2[0]
1843                        dervDict = {'int':dMdpk[0],'pos':dMdpk[1],'sig':dMdpk[2],'gam':dMdpk[3],'shl':dMdpk[4],'L1/L2':dMdpk[5]*refl[9]}
1844                if 'Pawley' in Phase['General']['Type']:
1845                    try:
1846                        idx = varylist.index(pfx+'PWLref:'+str(pawleyLookup[pfx+'%d,%d,%d'%(h,k,l)]))
1847                        dMdv[idx] = dervDict['int']/refl[9]
1848                    except ValueError:
1849                        pass
1850                dpdA,dpdw,dpdZ,dpdSh,dpdTr,dpdX,dpdY = GetReflPosDerv(refl,wave,A,hfx,calcControls,parmDict)
1851                names = {hfx+'Scale':[dIdsh,'int'],hfx+'Polariz.':[dIdpola,'int'],phfx+'Scale':[dIdsp,'int'],
1852                    hfx+'U':[tanth**2,'sig'],hfx+'V':[tanth,'sig'],hfx+'W':[1.0,'sig'],
1853                    hfx+'X':[1.0/costh,'gam'],hfx+'Y':[tanth,'gam'],hfx+'SH/L':[1.0,'shl'],
1854                    hfx+'I(L2)/I(L1)':[1.0,'L1/L2'],hfx+'Zero':[dpdZ,'pos'],hfx+'Lam':[dpdw,'pos'],
1855                    hfx+'Shift':[dpdSh,'pos'],hfx+'Transparency':[dpdTr,'pos'],hfx+'DisplaceX':[dpdX,'pos'],
1856                    hfx+'DisplaceY':[dpdY,'pos'],}
1857                for name in names:
1858                    if name in varylist:
1859                        item = names[name]
1860                        dMdv[varylist.index(name)] += item[0]*dervDict[item[1]]
1861                for iPO in dIdPO:
1862                    if iPO in varylist:
1863                        dMdv[varylist.index(iPO)] += dIdPO[iPO]*dervDict['int']
1864                cellDervNames = cellVaryDerv(pfx,SGData,dpdA)
1865                for name,dpdA in cellDervNames:
1866                    if name in varylist:
1867                        dMdv[varylist.index(name)] += dpdA*dervDict['pos']
1868                dDijDict = GetHStrainShiftDerv(refl,SGData,phfx)
1869                for name in dDijDict:
1870                    if name in varylist:
1871                        dMdv[varylist.index(name)] += dDijDict[name]*dervDict['pos']
1872                gamDict = GetSampleGamDerv(refl,wave,G,phfx,calcControls,parmDict,sizeEllipse)
1873                for name in gamDict:
1874                    if name in varylist:
1875                        dMdv[varylist.index(name)] += gamDict[name]*dervDict['gam']
1876                                               
1877            elif 'T' in calcControls[hfx+'histType']:
1878                print 'TOF Undefined at present'
1879                raise Exception    #no TOF yet
1880#do atom derivatives -  for F,X & U so far             
1881            corr = dervDict['int']/refl[9]
1882            for name in varylist:
1883                try:
1884                    aname = name.split(pfx)[1][:2]
1885                    if aname in ['Af','dA','AU']:
1886                         dMdv[varylist.index(name)] += dFdvDict[name][iref]*corr
1887                except IndexError:
1888                    pass
1889    return dMdv   
1890                   
1891def Refine(GPXfile,dlg):
1892    import cPickle
1893    import pytexture as ptx
1894    ptx.pyqlmninit()            #initialize fortran arrays for spherical harmonics
1895   
1896    def dervRefine(values,HistoPhases,parmdict,varylist,calcControls,pawleyLookup,dlg):
1897        parmdict.update(zip(varylist,values))
1898        G2mv.Dict2Map(parmDict)
1899        Histograms,Phases = HistoPhases
1900        dMdv = np.empty(0)
1901        for histogram in Histograms:
1902            if 'PWDR' in histogram[:4]:
1903                Histogram = Histograms[histogram]
1904                hId = Histogram['hId']
1905                hfx = ':%d:'%(hId)
1906                Limits = calcControls[hfx+'Limits']
1907                x,y,w,yc,yb,yd = Histogram['Data']
1908                xB = np.searchsorted(x,Limits[0])
1909                xF = np.searchsorted(x,Limits[1])
1910                dMdvh = np.sqrt(w[xB:xF])*getPowderProfileDerv(parmdict,x[xB:xF],
1911                    varylist,Histogram,Phases,calcControls,pawleyLookup)
1912                if len(dMdv):
1913                    dMdv = np.concatenate((dMdv,dMdvh))
1914                else:
1915                    dMdv = dMdvh
1916        return dMdv
1917   
1918    def errRefine(values,HistoPhases,parmdict,varylist,calcControls,pawleyLookup,dlg):       
1919        parmdict.update(zip(varylist,values))
1920        G2mv.Dict2Map(parmDict)
1921        Histograms,Phases = HistoPhases
1922        M = np.empty(0)
1923        sumwYo = 0
1924        Nobs = 0
1925        for histogram in Histograms:
1926            if 'PWDR' in histogram[:4]:
1927                Histogram = Histograms[histogram]
1928                hId = Histogram['hId']
1929                hfx = ':%d:'%(hId)
1930                Limits = calcControls[hfx+'Limits']
1931                x,y,w,yc,yb,yd = Histogram['Data']
1932                yc *= 0.0                           #zero full calcd profiles
1933                yb *= 0.0
1934                yd *= 0.0
1935                xB = np.searchsorted(x,Limits[0])
1936                xF = np.searchsorted(x,Limits[1])
1937                Nobs += xF-xB
1938                Histogram['sumwYo'] = np.sum(w[xB:xF]*y[xB:xF]**2)
1939                sumwYo += Histogram['sumwYo']
1940                yc[xB:xF],yb[xB:xF] = getPowderProfile(parmdict,x[xB:xF],
1941                    varylist,Histogram,Phases,calcControls,pawleyLookup)
1942                yc[xB:xF] *= parmDict[hfx+'Scale']
1943                yc[xB:xF] += yb[xB:xF]
1944                yd[xB:xF] = yc[xB:xF]-y[xB:xF]          #yc-yo then all dydv have no '-' needed
1945                Histogram['sumwYd'] = np.sum(np.sqrt(w[xB:xF])*(yd[xB:xF]))
1946                M = np.concatenate((M,np.sqrt(w[xB:xF])*(yd[xB:xF])))
1947        Histograms['sumwYo'] = sumwYo
1948        Histograms['Nobs'] = Nobs
1949        Rwp = min(100.,np.sqrt(np.sum(M**2)/sumwYo)*100.)
1950        if dlg:
1951            GoOn = dlg.Update(Rwp,newmsg='%s%8.3f%s'%('Powder profile Rwp =',Rwp,'%'))[0]
1952            if not GoOn:
1953                return -M           #abort!!
1954        return M
1955   
1956    ShowBanner()
1957    varyList = []
1958    parmDict = {}
1959    calcControls = {}
1960    G2mv.InitVars()   
1961    Controls = GetControls(GPXfile)
1962    ShowControls(Controls)           
1963    Histograms,Phases = GetUsedHistogramsAndPhases(GPXfile)
1964    if not Phases:
1965        print ' *** ERROR - you have no histograms to refine! ***'
1966        print ' *** Refine aborted ***'
1967        raise Exception
1968    if not Histograms:
1969        print ' *** ERROR - you have no data to refine with! ***'
1970        print ' *** Refine aborted ***'
1971        raise Exception
1972    Natoms,phaseVary,phaseDict,pawleyLookup,FFtables = GetPhaseData(Phases)
1973    calcControls['Natoms'] = Natoms
1974    calcControls['FFtables'] = FFtables
1975    hapVary,hapDict,controlDict = GetHistogramPhaseData(Phases,Histograms)
1976    calcControls.update(controlDict)
1977    histVary,histDict,controlDict = GetHistogramData(Histograms)
1978    calcControls.update(controlDict)
1979    varyList = phaseVary+hapVary+histVary
1980    parmDict.update(phaseDict)
1981    parmDict.update(hapDict)
1982    parmDict.update(histDict)
1983    GetFprime(calcControls,Histograms)
1984    constrDict,constrFlag,fixedList = G2mv.InputParse([])        #constraints go here?
1985    groups,parmlist = G2mv.GroupConstraints(constrDict)
1986    G2mv.GenerateConstraints(groups,parmlist,constrDict,constrFlag,fixedList)
1987    G2mv.Map2Dict(parmDict,varyList)
1988
1989    while True:
1990        begin = time.time()
1991        values =  np.array(Dict2Values(parmDict, varyList))
1992        Ftol = Controls['min dM/M']
1993        Factor = Controls['shift factor']
1994        if Controls['deriv type'] == 'analytic':
1995            result = so.leastsq(errRefine,values,Dfun=dervRefine,full_output=True,
1996                ftol=Ftol,col_deriv=True,factor=Factor,
1997                args=([Histograms,Phases],parmDict,varyList,calcControls,pawleyLookup,dlg))
1998            ncyc = int(result[2]['nfev']/2)               
1999        else:           #'numeric'
2000            result = so.leastsq(errRefine,values,full_output=True,ftol=Ftol,epsfcn=1.e-8,factor=Factor,
2001                args=([Histograms,Phases],parmDict,varyList,calcControls,pawleyLookup,dlg))
2002            ncyc = int(result[2]['nfev']/len(varyList))
2003#        table = dict(zip(varyList,zip(values,result[0],(result[0]-values))))
2004#        for item in table: print item,table[item]               #useful debug - are things shifting?
2005        runtime = time.time()-begin
2006        chisq = np.sum(result[2]['fvec']**2)
2007        Values2Dict(parmDict, varyList, result[0])
2008        ApplyXYZshifts(parmDict,varyList)
2009        G2mv.Dict2Map(parmDict)
2010       
2011        Rwp = np.sqrt(chisq/Histograms['sumwYo'])*100.      #to %
2012        GOF = chisq/(Histograms['Nobs']-len(varyList))
2013        print '\n Refinement results:'
2014        print 135*'-'
2015        print ' Number of function calls:',result[2]['nfev'],' Number of observations: ',Histograms['Nobs'],' Number of parameters: ',len(varyList)
2016        print ' Refinement time = %8.3fs, %8.3fs/cycle'%(runtime,runtime/ncyc)
2017        print ' Rwp = %7.2f%%, chi**2 = %12.6g, reduced chi**2 = %6.2f'%(Rwp,chisq,GOF)
2018        try:
2019            covMatrix = result[1]*GOF
2020            sig = np.sqrt(np.diag(covMatrix))
2021            xvar = np.outer(sig,np.ones_like(sig))
2022            cov = np.divide(np.divide(covMatrix,xvar),xvar.T)
2023            if np.any(np.isnan(sig)):
2024                print '*** Least squares aborted - some invalid esds possible ***'
2025#            table = dict(zip(varyList,zip(values,result[0],(result[0]-values)/sig)))
2026#            for item in table: print item,table[item]               #useful debug - are things shifting?
2027            break                   #refinement succeeded - finish up!
2028        except TypeError:          #result[1] is None on singular matrix
2029            print '**** Refinement failed - singular matrix ****'
2030            Ipvt = result[2]['ipvt']
2031            for i,ipvt in enumerate(Ipvt):
2032                if not np.sum(result[2]['fjac'],axis=1)[i]:
2033                    print 'Removing parameter: ',varyList[ipvt-1]
2034                    del(varyList[ipvt-1])
2035                    break
2036
2037#    print 'dependentParmList: ',G2mv.dependentParmList
2038#    print 'arrayList: ',G2mv.arrayList
2039#    print 'invarrayList: ',G2mv.invarrayList
2040#    print 'indParmList: ',G2mv.indParmList
2041#    print 'fixedDict: ',G2mv.fixedDict
2042    sigDict = dict(zip(varyList,sig))
2043    SetPhaseData(parmDict,sigDict,Phases)
2044    SetHistogramPhaseData(parmDict,sigDict,Phases,Histograms)
2045    SetHistogramData(parmDict,sigDict,Histograms)
2046    covData = {'variables':result[0],'varyList':varyList,'covariance':cov}
2047    SetUsedHistogramsAndPhases(GPXfile,Histograms,Phases,covData)
2048#for testing purposes!!!
2049#    file = open('structTestdata.dat','wb')
2050#    cPickle.dump(parmDict,file,1)
2051#    cPickle.dump(varyList,file,1)
2052#    for histogram in Histograms:
2053#        if 'PWDR' in histogram[:4]:
2054#            Histogram = Histograms[histogram]
2055#    cPickle.dump(Histogram,file,1)
2056#    cPickle.dump(Phases,file,1)
2057#    cPickle.dump(calcControls,file,1)
2058#    cPickle.dump(pawleyLookup,file,1)
2059#    file.close()
2060
2061def main():
2062    arg = sys.argv
2063    if len(arg) > 1:
2064        GPXfile = arg[1]
2065        if not ospath.exists(GPXfile):
2066            print 'ERROR - ',GPXfile," doesn't exist!"
2067            exit()
2068        GPXpath = ospath.dirname(arg[1])
2069        Refine(GPXfile,None)
2070    else:
2071        print 'ERROR - missing filename'
2072        exit()
2073    print "Done"
2074         
2075if __name__ == '__main__':
2076    main()
Note: See TracBrowser for help on using the repository browser.