source: trunk/GSASIIstrMath.py @ 1877

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

another Flack fix

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 140.9 KB
Line 
1# -*- coding: utf-8 -*-
2'''
3*GSASIIstrMath - structure math routines*
4-----------------------------------------
5'''
6########### SVN repository information ###################
7# $Date: 2015-06-02 20:24:09 +0000 (Tue, 02 Jun 2015) $
8# $Author: vondreele $
9# $Revision: 1877 $
10# $URL: trunk/GSASIIstrMath.py $
11# $Id: GSASIIstrMath.py 1877 2015-06-02 20:24:09Z vondreele $
12########### SVN repository information ###################
13import time
14import math
15import copy
16import numpy as np
17import numpy.ma as ma
18import numpy.linalg as nl
19import scipy.optimize as so
20import scipy.stats as st
21import GSASIIpath
22GSASIIpath.SetVersionNumber("$Revision: 1877 $")
23import GSASIIElem as G2el
24import GSASIIlattice as G2lat
25import GSASIIspc as G2spc
26import GSASIIpwd as G2pwd
27import GSASIImapvars as G2mv
28import GSASIImath as G2mth
29import GSASIIobj as G2obj
30
31sind = lambda x: np.sin(x*np.pi/180.)
32cosd = lambda x: np.cos(x*np.pi/180.)
33tand = lambda x: np.tan(x*np.pi/180.)
34asind = lambda x: 180.*np.arcsin(x)/np.pi
35acosd = lambda x: 180.*np.arccos(x)/np.pi
36atan2d = lambda y,x: 180.*np.arctan2(y,x)/np.pi
37   
38ateln2 = 8.0*math.log(2.0)
39twopi = 2.0*np.pi
40twopisq = 2.0*np.pi**2
41
42################################################################################
43##### Rigid Body Models
44################################################################################
45       
46def ApplyRBModels(parmDict,Phases,rigidbodyDict,Update=False):
47    ''' Takes RB info from RBModels in Phase and RB data in rigidbodyDict along with
48    current RB values in parmDict & modifies atom contents (xyz & Uij) of parmDict
49    '''
50    atxIds = ['Ax:','Ay:','Az:']
51    atuIds = ['AU11:','AU22:','AU33:','AU12:','AU13:','AU23:']
52    RBIds = rigidbodyDict.get('RBIds',{'Vector':[],'Residue':[]})  #these are lists of rbIds
53    if not RBIds['Vector'] and not RBIds['Residue']:
54        return
55    VRBIds = RBIds['Vector']
56    RRBIds = RBIds['Residue']
57    if Update:
58        RBData = rigidbodyDict
59    else:
60        RBData = copy.deepcopy(rigidbodyDict)     # don't mess with original!
61    if RBIds['Vector']:                       # first update the vector magnitudes
62        VRBData = RBData['Vector']
63        for i,rbId in enumerate(VRBIds):
64            if VRBData[rbId]['useCount']:
65                for j in range(len(VRBData[rbId]['VectMag'])):
66                    name = '::RBV;'+str(j)+':'+str(i)
67                    VRBData[rbId]['VectMag'][j] = parmDict[name]
68    for phase in Phases:
69        Phase = Phases[phase]
70        General = Phase['General']
71        cx,ct,cs,cia = General['AtomPtrs']
72        cell = General['Cell'][1:7]
73        Amat,Bmat = G2lat.cell2AB(cell)
74        AtLookup = G2mth.FillAtomLookUp(Phase['Atoms'],cia+8)
75        pfx = str(Phase['pId'])+'::'
76        if Update:
77            RBModels = Phase['RBModels']
78        else:
79            RBModels =  copy.deepcopy(Phase['RBModels']) # again don't mess with original!
80        for irb,RBObj in enumerate(RBModels.get('Vector',[])):
81            jrb = VRBIds.index(RBObj['RBId'])
82            rbsx = str(irb)+':'+str(jrb)
83            for i,px in enumerate(['RBVPx:','RBVPy:','RBVPz:']):
84                RBObj['Orig'][0][i] = parmDict[pfx+px+rbsx]
85            for i,po in enumerate(['RBVOa:','RBVOi:','RBVOj:','RBVOk:']):
86                RBObj['Orient'][0][i] = parmDict[pfx+po+rbsx]
87            RBObj['Orient'][0] = G2mth.normQ(RBObj['Orient'][0])
88            TLS = RBObj['ThermalMotion']
89            if 'T' in TLS[0]:
90                for i,pt in enumerate(['RBVT11:','RBVT22:','RBVT33:','RBVT12:','RBVT13:','RBVT23:']):
91                    TLS[1][i] = parmDict[pfx+pt+rbsx]
92            if 'L' in TLS[0]:
93                for i,pt in enumerate(['RBVL11:','RBVL22:','RBVL33:','RBVL12:','RBVL13:','RBVL23:']):
94                    TLS[1][i+6] = parmDict[pfx+pt+rbsx]
95            if 'S' in TLS[0]:
96                for i,pt in enumerate(['RBVS12:','RBVS13:','RBVS21:','RBVS23:','RBVS31:','RBVS32:','RBVSAA:','RBVSBB:']):
97                    TLS[1][i+12] = parmDict[pfx+pt+rbsx]
98            if 'U' in TLS[0]:
99                TLS[1][0] = parmDict[pfx+'RBVU:'+rbsx]
100            XYZ,Cart = G2mth.UpdateRBXYZ(Bmat,RBObj,RBData,'Vector')
101            UIJ = G2mth.UpdateRBUIJ(Bmat,Cart,RBObj)
102            for i,x in enumerate(XYZ):
103                atId = RBObj['Ids'][i]
104                for j in [0,1,2]:
105                    parmDict[pfx+atxIds[j]+str(AtLookup[atId])] = x[j]
106                if UIJ[i][0] == 'A':
107                    for j in range(6):
108                        parmDict[pfx+atuIds[j]+str(AtLookup[atId])] = UIJ[i][j+2]
109                elif UIJ[i][0] == 'I':
110                    parmDict[pfx+'AUiso:'+str(AtLookup[atId])] = UIJ[i][1]
111           
112        for irb,RBObj in enumerate(RBModels.get('Residue',[])):
113            jrb = RRBIds.index(RBObj['RBId'])
114            rbsx = str(irb)+':'+str(jrb)
115            for i,px in enumerate(['RBRPx:','RBRPy:','RBRPz:']):
116                RBObj['Orig'][0][i] = parmDict[pfx+px+rbsx]
117            for i,po in enumerate(['RBROa:','RBROi:','RBROj:','RBROk:']):
118                RBObj['Orient'][0][i] = parmDict[pfx+po+rbsx]               
119            RBObj['Orient'][0] = G2mth.normQ(RBObj['Orient'][0])
120            TLS = RBObj['ThermalMotion']
121            if 'T' in TLS[0]:
122                for i,pt in enumerate(['RBRT11:','RBRT22:','RBRT33:','RBRT12:','RBRT13:','RBRT23:']):
123                    RBObj['ThermalMotion'][1][i] = parmDict[pfx+pt+rbsx]
124            if 'L' in TLS[0]:
125                for i,pt in enumerate(['RBRL11:','RBRL22:','RBRL33:','RBRL12:','RBRL13:','RBRL23:']):
126                    RBObj['ThermalMotion'][1][i+6] = parmDict[pfx+pt+rbsx]
127            if 'S' in TLS[0]:
128                for i,pt in enumerate(['RBRS12:','RBRS13:','RBRS21:','RBRS23:','RBRS31:','RBRS32:','RBRSAA:','RBRSBB:']):
129                    RBObj['ThermalMotion'][1][i+12] = parmDict[pfx+pt+rbsx]
130            if 'U' in TLS[0]:
131                RBObj['ThermalMotion'][1][0] = parmDict[pfx+'RBRU:'+rbsx]
132            for itors,tors in enumerate(RBObj['Torsions']):
133                tors[0] = parmDict[pfx+'RBRTr;'+str(itors)+':'+rbsx]
134            XYZ,Cart = G2mth.UpdateRBXYZ(Bmat,RBObj,RBData,'Residue')
135            UIJ = G2mth.UpdateRBUIJ(Bmat,Cart,RBObj)
136            for i,x in enumerate(XYZ):
137                atId = RBObj['Ids'][i]
138                for j in [0,1,2]:
139                    parmDict[pfx+atxIds[j]+str(AtLookup[atId])] = x[j]
140                if UIJ[i][0] == 'A':
141                    for j in range(6):
142                        parmDict[pfx+atuIds[j]+str(AtLookup[atId])] = UIJ[i][j+2]
143                elif UIJ[i][0] == 'I':
144                    parmDict[pfx+'AUiso:'+str(AtLookup[atId])] = UIJ[i][1]
145                   
146def ApplyRBModelDervs(dFdvDict,parmDict,rigidbodyDict,Phase):
147    'Needs a doc string'
148    atxIds = ['dAx:','dAy:','dAz:']
149    atuIds = ['AU11:','AU22:','AU33:','AU12:','AU13:','AU23:']
150    TIds = ['T11:','T22:','T33:','T12:','T13:','T23:']
151    LIds = ['L11:','L22:','L33:','L12:','L13:','L23:']
152    SIds = ['S12:','S13:','S21:','S23:','S31:','S32:','SAA:','SBB:']
153    PIds = ['Px:','Py:','Pz:']
154    OIds = ['Oa:','Oi:','Oj:','Ok:']
155    RBIds = rigidbodyDict.get('RBIds',{'Vector':[],'Residue':[]})  #these are lists of rbIds
156    if not RBIds['Vector'] and not RBIds['Residue']:
157        return
158    VRBIds = RBIds['Vector']
159    RRBIds = RBIds['Residue']
160    RBData = rigidbodyDict
161    for item in parmDict:
162        if 'RB' in item:
163            dFdvDict[item] = 0.        #NB: this is a vector which is no. refl. long & must be filled!
164    General = Phase['General']
165    cx,ct,cs,cia = General['AtomPtrs']
166    cell = General['Cell'][1:7]
167    Amat,Bmat = G2lat.cell2AB(cell)
168    rpd = np.pi/180.
169    rpd2 = rpd**2
170    g = nl.inv(np.inner(Bmat,Bmat))
171    gvec = np.sqrt(np.array([g[0][0]**2,g[1][1]**2,g[2][2]**2,
172        g[0][0]*g[1][1],g[0][0]*g[2][2],g[1][1]*g[2][2]]))
173    AtLookup = G2mth.FillAtomLookUp(Phase['Atoms'],cia+8)
174    pfx = str(Phase['pId'])+'::'
175    RBModels =  Phase['RBModels']
176    for irb,RBObj in enumerate(RBModels.get('Vector',[])):
177        VModel = RBData['Vector'][RBObj['RBId']]
178        Q = RBObj['Orient'][0]
179        Pos = RBObj['Orig'][0]
180        jrb = VRBIds.index(RBObj['RBId'])
181        rbsx = str(irb)+':'+str(jrb)
182        dXdv = []
183        for iv in range(len(VModel['VectMag'])):
184            dCdv = []
185            for vec in VModel['rbVect'][iv]:
186                dCdv.append(G2mth.prodQVQ(Q,vec))
187            dXdv.append(np.inner(Bmat,np.array(dCdv)).T)
188        XYZ,Cart = G2mth.UpdateRBXYZ(Bmat,RBObj,RBData,'Vector')
189        for ia,atId in enumerate(RBObj['Ids']):
190            atNum = AtLookup[atId]
191            dx = 0.00001
192            for iv in range(len(VModel['VectMag'])):
193                for ix in [0,1,2]:
194                    dFdvDict['::RBV;'+str(iv)+':'+str(jrb)] += dXdv[iv][ia][ix]*dFdvDict[pfx+atxIds[ix]+str(atNum)]
195            for i,name in enumerate(['RBVPx:','RBVPy:','RBVPz:']):
196                dFdvDict[pfx+name+rbsx] += dFdvDict[pfx+atxIds[i]+str(atNum)]
197            for iv in range(4):
198                Q[iv] -= dx
199                XYZ1 = G2mth.RotateRBXYZ(Bmat,Cart,G2mth.normQ(Q))
200                Q[iv] += 2.*dx
201                XYZ2 = G2mth.RotateRBXYZ(Bmat,Cart,G2mth.normQ(Q))
202                Q[iv] -= dx
203                dXdO = (XYZ2[ia]-XYZ1[ia])/(2.*dx)
204                for ix in [0,1,2]:
205                    dFdvDict[pfx+'RBV'+OIds[iv]+rbsx] += dXdO[ix]*dFdvDict[pfx+atxIds[ix]+str(atNum)]
206            X = G2mth.prodQVQ(Q,Cart[ia])
207            dFdu = np.array([dFdvDict[pfx+Uid+str(AtLookup[atId])] for Uid in atuIds]).T/gvec
208            dFdu = G2lat.U6toUij(dFdu.T)
209            dFdu = np.tensordot(Amat,np.tensordot(Amat,dFdu,([1,0])),([0,1]))           
210            dFdu = G2lat.UijtoU6(dFdu)
211            atNum = AtLookup[atId]
212            if 'T' in RBObj['ThermalMotion'][0]:
213                for i,name in enumerate(['RBVT11:','RBVT22:','RBVT33:','RBVT12:','RBVT13:','RBVT23:']):
214                    dFdvDict[pfx+name+rbsx] += dFdu[i]
215            if 'L' in RBObj['ThermalMotion'][0]:
216                dFdvDict[pfx+'RBVL11:'+rbsx] += rpd2*(dFdu[1]*X[2]**2+dFdu[2]*X[1]**2-dFdu[5]*X[1]*X[2])
217                dFdvDict[pfx+'RBVL22:'+rbsx] += rpd2*(dFdu[0]*X[2]**2+dFdu[2]*X[0]**2-dFdu[4]*X[0]*X[2])
218                dFdvDict[pfx+'RBVL33:'+rbsx] += rpd2*(dFdu[0]*X[1]**2+dFdu[1]*X[0]**2-dFdu[3]*X[0]*X[1])
219                dFdvDict[pfx+'RBVL12:'+rbsx] += rpd2*(-dFdu[3]*X[2]**2-2.*dFdu[2]*X[0]*X[1]+
220                    dFdu[4]*X[1]*X[2]+dFdu[5]*X[0]*X[2])
221                dFdvDict[pfx+'RBVL13:'+rbsx] += rpd2*(-dFdu[4]*X[1]**2-2.*dFdu[1]*X[0]*X[2]+
222                    dFdu[3]*X[1]*X[2]+dFdu[5]*X[0]*X[1])
223                dFdvDict[pfx+'RBVL23:'+rbsx] += rpd2*(-dFdu[5]*X[0]**2-2.*dFdu[0]*X[1]*X[2]+
224                    dFdu[3]*X[0]*X[2]+dFdu[4]*X[0]*X[1])
225            if 'S' in RBObj['ThermalMotion'][0]:
226                dFdvDict[pfx+'RBVS12:'+rbsx] += rpd*(dFdu[5]*X[1]-2.*dFdu[1]*X[2])
227                dFdvDict[pfx+'RBVS13:'+rbsx] += rpd*(-dFdu[5]*X[2]+2.*dFdu[2]*X[1])
228                dFdvDict[pfx+'RBVS21:'+rbsx] += rpd*(-dFdu[4]*X[0]+2.*dFdu[0]*X[2])
229                dFdvDict[pfx+'RBVS23:'+rbsx] += rpd*(dFdu[4]*X[2]-2.*dFdu[2]*X[0])
230                dFdvDict[pfx+'RBVS31:'+rbsx] += rpd*(dFdu[3]*X[0]-2.*dFdu[0]*X[1])
231                dFdvDict[pfx+'RBVS32:'+rbsx] += rpd*(-dFdu[3]*X[1]+2.*dFdu[1]*X[0])
232                dFdvDict[pfx+'RBVSAA:'+rbsx] += rpd*(dFdu[4]*X[1]-dFdu[3]*X[2])
233                dFdvDict[pfx+'RBVSBB:'+rbsx] += rpd*(dFdu[5]*X[0]-dFdu[3]*X[2])
234            if 'U' in RBObj['ThermalMotion'][0]:
235                dFdvDict[pfx+'RBVU:'+rbsx] += dFdvDict[pfx+'AUiso:'+str(AtLookup[atId])]
236
237
238    for irb,RBObj in enumerate(RBModels.get('Residue',[])):
239        Q = RBObj['Orient'][0]
240        Pos = RBObj['Orig'][0]
241        jrb = RRBIds.index(RBObj['RBId'])
242        torData = RBData['Residue'][RBObj['RBId']]['rbSeq']
243        rbsx = str(irb)+':'+str(jrb)
244        XYZ,Cart = G2mth.UpdateRBXYZ(Bmat,RBObj,RBData,'Residue')
245        for itors,tors in enumerate(RBObj['Torsions']):     #derivative error?
246            tname = pfx+'RBRTr;'+str(itors)+':'+rbsx           
247            orId,pvId = torData[itors][:2]
248            pivotVec = Cart[orId]-Cart[pvId]
249            QA = G2mth.AVdeg2Q(-0.001,pivotVec)
250            QB = G2mth.AVdeg2Q(0.001,pivotVec)
251            for ir in torData[itors][3]:
252                atNum = AtLookup[RBObj['Ids'][ir]]
253                rVec = Cart[ir]-Cart[pvId]
254                dR = G2mth.prodQVQ(QB,rVec)-G2mth.prodQVQ(QA,rVec)
255                dRdT = np.inner(Bmat,G2mth.prodQVQ(Q,dR))/.002
256                for ix in [0,1,2]:
257                    dFdvDict[tname] += dRdT[ix]*dFdvDict[pfx+atxIds[ix]+str(atNum)]
258        for ia,atId in enumerate(RBObj['Ids']):
259            atNum = AtLookup[atId]
260            dx = 0.00001
261            for i,name in enumerate(['RBRPx:','RBRPy:','RBRPz:']):
262                dFdvDict[pfx+name+rbsx] += dFdvDict[pfx+atxIds[i]+str(atNum)]
263            for iv in range(4):
264                Q[iv] -= dx
265                XYZ1 = G2mth.RotateRBXYZ(Bmat,Cart,G2mth.normQ(Q))
266                Q[iv] += 2.*dx
267                XYZ2 = G2mth.RotateRBXYZ(Bmat,Cart,G2mth.normQ(Q))
268                Q[iv] -= dx
269                dXdO = (XYZ2[ia]-XYZ1[ia])/(2.*dx)
270                for ix in [0,1,2]:
271                    dFdvDict[pfx+'RBR'+OIds[iv]+rbsx] += dXdO[ix]*dFdvDict[pfx+atxIds[ix]+str(atNum)]
272            X = G2mth.prodQVQ(Q,Cart[ia])
273            dFdu = np.array([dFdvDict[pfx+Uid+str(AtLookup[atId])] for Uid in atuIds]).T/gvec
274            dFdu = G2lat.U6toUij(dFdu.T)
275            dFdu = np.tensordot(Amat.T,np.tensordot(Amat,dFdu,([1,0])),([0,1]))
276            dFdu = G2lat.UijtoU6(dFdu)
277            atNum = AtLookup[atId]
278            if 'T' in RBObj['ThermalMotion'][0]:
279                for i,name in enumerate(['RBRT11:','RBRT22:','RBRT33:','RBRT12:','RBRT13:','RBRT23:']):
280                    dFdvDict[pfx+name+rbsx] += dFdu[i]
281            if 'L' in RBObj['ThermalMotion'][0]:
282                dFdvDict[pfx+'RBRL11:'+rbsx] += rpd2*(dFdu[1]*X[2]**2+dFdu[2]*X[1]**2-dFdu[5]*X[1]*X[2])
283                dFdvDict[pfx+'RBRL22:'+rbsx] += rpd2*(dFdu[0]*X[2]**2+dFdu[2]*X[0]**2-dFdu[4]*X[0]*X[2])
284                dFdvDict[pfx+'RBRL33:'+rbsx] += rpd2*(dFdu[0]*X[1]**2+dFdu[1]*X[0]**2-dFdu[3]*X[0]*X[1])
285                dFdvDict[pfx+'RBRL12:'+rbsx] += rpd2*(-dFdu[3]*X[2]**2-2.*dFdu[2]*X[0]*X[1]+
286                    dFdu[4]*X[1]*X[2]+dFdu[5]*X[0]*X[2])
287                dFdvDict[pfx+'RBRL13:'+rbsx] += rpd2*(dFdu[4]*X[1]**2-2.*dFdu[1]*X[0]*X[2]+
288                    dFdu[3]*X[1]*X[2]+dFdu[5]*X[0]*X[1])
289                dFdvDict[pfx+'RBRL23:'+rbsx] += rpd2*(dFdu[5]*X[0]**2-2.*dFdu[0]*X[1]*X[2]+
290                    dFdu[3]*X[0]*X[2]+dFdu[4]*X[0]*X[1])
291            if 'S' in RBObj['ThermalMotion'][0]:
292                dFdvDict[pfx+'RBRS12:'+rbsx] += rpd*(dFdu[5]*X[1]-2.*dFdu[1]*X[2])
293                dFdvDict[pfx+'RBRS13:'+rbsx] += rpd*(-dFdu[5]*X[2]+2.*dFdu[2]*X[1])
294                dFdvDict[pfx+'RBRS21:'+rbsx] += rpd*(-dFdu[4]*X[0]+2.*dFdu[0]*X[2])
295                dFdvDict[pfx+'RBRS23:'+rbsx] += rpd*(dFdu[4]*X[2]-2.*dFdu[2]*X[0])
296                dFdvDict[pfx+'RBRS31:'+rbsx] += rpd*(dFdu[3]*X[0]-2.*dFdu[0]*X[1])
297                dFdvDict[pfx+'RBRS32:'+rbsx] += rpd*(-dFdu[3]*X[1]+2.*dFdu[1]*X[0])
298                dFdvDict[pfx+'RBRSAA:'+rbsx] += rpd*(dFdu[4]*X[1]-dFdu[3]*X[2])
299                dFdvDict[pfx+'RBRSBB:'+rbsx] += rpd*(dFdu[5]*X[0]-dFdu[3]*X[2])
300            if 'U' in RBObj['ThermalMotion'][0]:
301                dFdvDict[pfx+'RBRU:'+rbsx] += dFdvDict[pfx+'AUiso:'+str(AtLookup[atId])]
302   
303################################################################################
304##### Penalty & restraint functions
305################################################################################
306
307def penaltyFxn(HistoPhases,calcControls,parmDict,varyList):
308    'Needs a doc string'
309    Histograms,Phases,restraintDict,rigidbodyDict = HistoPhases
310    pNames = []
311    pVals = []
312    pWt = []
313    negWt = {}
314    pWsum = {}
315    for phase in Phases:
316        pId = Phases[phase]['pId']
317        negWt[pId] = Phases[phase]['General']['Pawley neg wt']
318        General = Phases[phase]['General']
319        cx,ct,cs,cia = General['AtomPtrs']
320        textureData = General['SH Texture']
321        SGData = General['SGData']
322        AtLookup = G2mth.FillAtomLookUp(Phases[phase]['Atoms'],cia+8)
323        cell = General['Cell'][1:7]
324        Amat,Bmat = G2lat.cell2AB(cell)
325        if phase not in restraintDict:
326            continue
327        phaseRest = restraintDict[phase]
328        names = [['Bond','Bonds'],['Angle','Angles'],['Plane','Planes'],
329            ['Chiral','Volumes'],['Torsion','Torsions'],['Rama','Ramas'],
330            ['ChemComp','Sites'],['Texture','HKLs'],]
331        for name,rest in names:
332            pWsum[name] = 0.
333            itemRest = phaseRest[name]
334            if itemRest[rest] and itemRest['Use']:
335                wt = itemRest['wtFactor']
336                if name in ['Bond','Angle','Plane','Chiral']:
337                    for i,[indx,ops,obs,esd] in enumerate(itemRest[rest]):
338                        pNames.append(str(pId)+':'+name+':'+str(i))
339                        XYZ = np.array(G2mth.GetAtomCoordsByID(pId,parmDict,AtLookup,indx))
340                        XYZ = G2mth.getSyXYZ(XYZ,ops,SGData)
341                        if name == 'Bond':
342                            calc = G2mth.getRestDist(XYZ,Amat)
343                        elif name == 'Angle':
344                            calc = G2mth.getRestAngle(XYZ,Amat)
345                        elif name == 'Plane':
346                            calc = G2mth.getRestPlane(XYZ,Amat)
347                        elif name == 'Chiral':
348                            calc = G2mth.getRestChiral(XYZ,Amat)
349                        pVals.append(obs-calc)
350                        pWt.append(wt/esd**2)
351                        pWsum[name] += wt*((obs-calc)/esd)**2
352                elif name in ['Torsion','Rama']:
353                    coeffDict = itemRest['Coeff']
354                    for i,[indx,ops,cofName,esd] in enumerate(itemRest[rest]):
355                        pNames.append(str(pId)+':'+name+':'+str(i))
356                        XYZ = np.array(G2mth.GetAtomCoordsByID(pId,parmDict,AtLookup,indx))
357                        XYZ = G2mth.getSyXYZ(XYZ,ops,SGData)
358                        if name == 'Torsion':
359                            tor = G2mth.getRestTorsion(XYZ,Amat)
360                            restr,calc = G2mth.calcTorsionEnergy(tor,coeffDict[cofName])
361                        else:
362                            phi,psi = G2mth.getRestRama(XYZ,Amat)
363                            restr,calc = G2mth.calcRamaEnergy(phi,psi,coeffDict[cofName])                               
364                        pVals.append(restr)
365                        pWt.append(wt/esd**2)
366                        pWsum[name] += wt*(restr/esd)**2
367                elif name == 'ChemComp':
368                    for i,[indx,factors,obs,esd] in enumerate(itemRest[rest]):
369                        pNames.append(str(pId)+':'+name+':'+str(i))
370                        mul = np.array(G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,cs+1))
371                        frac = np.array(G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,cs-1))
372                        calc = np.sum(mul*frac*factors)
373                        pVals.append(obs-calc)
374                        pWt.append(wt/esd**2)                   
375                        pWsum[name] += wt*((obs-calc)/esd)**2
376                elif name == 'Texture':
377                    SHkeys = textureData['SH Coeff'][1].keys()
378                    SHCoef = G2mth.GetSHCoeff(pId,parmDict,SHkeys)
379                    shModels = ['cylindrical','none','shear - 2/m','rolling - mmm']
380                    SamSym = dict(zip(shModels,['0','-1','2/m','mmm']))
381                    for i,[hkl,grid,esd1,ifesd2,esd2] in enumerate(itemRest[rest]):
382                        PH = np.array(hkl)
383                        phi,beta = G2lat.CrsAng(np.array(hkl),cell,SGData)
384                        ODFln = G2lat.Flnh(False,SHCoef,phi,beta,SGData)
385                        R,P,Z = G2mth.getRestPolefig(ODFln,SamSym[textureData['Model']],grid)
386                        Z1 = -ma.masked_greater(Z,0.0)
387                        IndZ1 = np.array(ma.nonzero(Z1))
388                        for ind in IndZ1.T:
389                            pNames.append('%d:%s:%d:%.2f:%.2f'%(pId,name,i,R[ind[0],ind[1]],P[ind[0],ind[1]]))
390                            pVals.append(Z1[ind[0]][ind[1]])
391                            pWt.append(wt/esd1**2)
392                            pWsum[name] += wt*(-Z1[ind[0]][ind[1]]/esd1)**2
393                        if ifesd2:
394                            Z2 = 1.-Z
395                            for ind in np.ndindex(grid,grid):
396                                pNames.append('%d:%s:%d:%.2f:%.2f'%(pId,name+'-unit',i,R[ind[0],ind[1]],P[ind[0],ind[1]]))
397                                pVals.append(Z1[ind[0]][ind[1]])
398                                pWt.append(wt/esd2**2)
399                                pWsum[name] += wt*(Z2/esd2)**2
400       
401    for phase in Phases:
402        name = 'SH-Pref.Ori.'
403        pId = Phases[phase]['pId']
404        General = Phases[phase]['General']
405        SGData = General['SGData']
406        cell = General['Cell'][1:7]
407        pWsum[name] = 0.0
408        for hist in Phases[phase]['Histograms']:
409            if hist in Histograms and 'PWDR' in hist:
410                hId = Histograms[hist]['hId']
411                phfx = '%d:%d:'%(pId,hId)
412                if calcControls[phfx+'poType'] == 'SH':
413                    toler = calcControls[phfx+'SHtoler']
414                    wt = 1./toler**2
415                    HKLs = np.array(calcControls[phfx+'SHhkl'])
416                    SHnames = calcControls[phfx+'SHnames']
417                    SHcof = dict(zip(SHnames,[parmDict[phfx+cof] for cof in SHnames]))
418                    for i,PH in enumerate(HKLs):
419                        phi,beta = G2lat.CrsAng(PH,cell,SGData)
420                        SH3Coef = {}
421                        for item in SHcof:
422                            L,N = eval(item.strip('C'))
423                            SH3Coef['C%d,0,%d'%(L,N)] = SHcof[item]                       
424                        ODFln = G2lat.Flnh(False,SH3Coef,phi,beta,SGData)
425                        X = np.linspace(0,90.0,26)
426                        Y = -ma.masked_greater(G2lat.polfcal(ODFln,'0',X,0.0),0.0)
427                        IndY = ma.nonzero(Y)
428                        for ind in IndY[0]:
429                            pNames.append('%d:%d:%s:%d:%.2f'%(pId,hId,name,i,X[ind]))
430                            pVals.append(Y[ind])
431                            pWt.append(wt)
432                            pWsum[name] += wt*(Y[ind])**2
433    pWsum['PWLref'] = 0.
434    for item in varyList:
435        if 'PWLref' in item and parmDict[item] < 0.:
436            pId = int(item.split(':')[0])
437            if negWt[pId]:
438                pNames.append(item)
439                pVals.append(-parmDict[item])
440                pWt.append(negWt[pId])
441                pWsum['PWLref'] += negWt[pId]*(-parmDict[item])**2
442    pVals = np.array(pVals)
443    pWt = np.array(pWt)         #should this be np.sqrt?
444    return pNames,pVals,pWt,pWsum
445   
446def penaltyDeriv(pNames,pVal,HistoPhases,calcControls,parmDict,varyList):
447    'Needs a doc string'
448    Histograms,Phases,restraintDict,rigidbodyDict = HistoPhases
449    pDerv = np.zeros((len(varyList),len(pVal)))
450    for phase in Phases:
451#        if phase not in restraintDict:
452#            continue
453        pId = Phases[phase]['pId']
454        General = Phases[phase]['General']
455        cx,ct,cs,cia = General['AtomPtrs']
456        SGData = General['SGData']
457        AtLookup = G2mth.FillAtomLookUp(Phases[phase]['Atoms'],cia+8)
458        cell = General['Cell'][1:7]
459        Amat,Bmat = G2lat.cell2AB(cell)
460        textureData = General['SH Texture']
461
462        SHkeys = textureData['SH Coeff'][1].keys()
463        SHCoef = G2mth.GetSHCoeff(pId,parmDict,SHkeys)
464        shModels = ['cylindrical','none','shear - 2/m','rolling - mmm']
465        SamSym = dict(zip(shModels,['0','-1','2/m','mmm']))
466        sam = SamSym[textureData['Model']]
467        phaseRest = restraintDict.get(phase,{})
468        names = {'Bond':'Bonds','Angle':'Angles','Plane':'Planes',
469            'Chiral':'Volumes','Torsion':'Torsions','Rama':'Ramas',
470            'ChemComp':'Sites','Texture':'HKLs'}
471        lasthkl = np.array([0,0,0])
472        for ip,pName in enumerate(pNames):
473            pnames = pName.split(':')
474            if pId == int(pnames[0]):
475                name = pnames[1]
476                if 'PWL' in pName:
477                    pDerv[varyList.index(pName)][ip] += 1.
478                    continue
479                elif 'SH-' in pName:
480                    continue
481                id = int(pnames[2]) 
482                itemRest = phaseRest[name]
483                if name in ['Bond','Angle','Plane','Chiral']:
484                    indx,ops,obs,esd = itemRest[names[name]][id]
485                    dNames = []
486                    for ind in indx:
487                        dNames += [str(pId)+'::dA'+Xname+':'+str(AtLookup[ind]) for Xname in ['x','y','z']]
488                    XYZ = np.array(G2mth.GetAtomCoordsByID(pId,parmDict,AtLookup,indx))
489                    if name == 'Bond':
490                        deriv = G2mth.getRestDeriv(G2mth.getRestDist,XYZ,Amat,ops,SGData)
491                    elif name == 'Angle':
492                        deriv = G2mth.getRestDeriv(G2mth.getRestAngle,XYZ,Amat,ops,SGData)
493                    elif name == 'Plane':
494                        deriv = G2mth.getRestDeriv(G2mth.getRestPlane,XYZ,Amat,ops,SGData)
495                    elif name == 'Chiral':
496                        deriv = G2mth.getRestDeriv(G2mth.getRestChiral,XYZ,Amat,ops,SGData)
497                elif name in ['Torsion','Rama']:
498                    coffDict = itemRest['Coeff']
499                    indx,ops,cofName,esd = itemRest[names[name]][id]
500                    dNames = []
501                    for ind in indx:
502                        dNames += [str(pId)+'::dA'+Xname+':'+str(AtLookup[ind]) for Xname in ['x','y','z']]
503                    XYZ = np.array(G2mth.GetAtomCoordsByID(pId,parmDict,AtLookup,indx))
504                    if name == 'Torsion':
505                        deriv = G2mth.getTorsionDeriv(XYZ,Amat,coffDict[cofName])
506                    else:
507                        deriv = G2mth.getRamaDeriv(XYZ,Amat,coffDict[cofName])
508                elif name == 'ChemComp':
509                    indx,factors,obs,esd = itemRest[names[name]][id]
510                    dNames = []
511                    for ind in indx:
512                        dNames += [str(pId)+'::Afrac:'+str(AtLookup[ind])]
513                        mul = np.array(G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,cs+1))
514                        deriv = mul*factors
515                elif 'Texture' in name:
516                    deriv = []
517                    dNames = []
518                    hkl,grid,esd1,ifesd2,esd2 = itemRest[names[name]][id]
519                    hkl = np.array(hkl)
520                    if np.any(lasthkl-hkl):
521                        PH = np.array(hkl)
522                        phi,beta = G2lat.CrsAng(np.array(hkl),cell,SGData)
523                        ODFln = G2lat.Flnh(False,SHCoef,phi,beta,SGData)
524                        lasthkl = copy.copy(hkl)                       
525                    if 'unit' in name:
526                        pass
527                    else:
528                        gam = float(pnames[3])
529                        psi = float(pnames[4])
530                        for SHname in ODFln:
531                            l,m,n = eval(SHname[1:])
532                            Ksl = G2lat.GetKsl(l,m,sam,psi,gam)[0]
533                            dNames += [str(pId)+'::'+SHname]
534                            deriv.append(-ODFln[SHname][0]*Ksl/SHCoef[SHname])
535                for dName,drv in zip(dNames,deriv):
536                    try:
537                        ind = varyList.index(dName)
538                        pDerv[ind][ip] += drv
539                    except ValueError:
540                        pass
541       
542        lasthkl = np.array([0,0,0])
543        for ip,pName in enumerate(pNames):
544            deriv = []
545            dNames = []
546            pnames = pName.split(':')
547            if 'SH-' in pName and pId == int(pnames[0]):
548                hId = int(pnames[1])
549                phfx = '%d:%d:'%(pId,hId)
550                psi = float(pnames[4])
551                HKLs = calcControls[phfx+'SHhkl']
552                SHnames = calcControls[phfx+'SHnames']
553                SHcof = dict(zip(SHnames,[parmDict[phfx+cof] for cof in SHnames]))
554                hkl = np.array(HKLs[int(pnames[3])])     
555                if np.any(lasthkl-hkl):
556                    PH = np.array(hkl)
557                    phi,beta = G2lat.CrsAng(np.array(hkl),cell,SGData)
558                    SH3Coef = {}
559                    for item in SHcof:
560                        L,N = eval(item.strip('C'))
561                        SH3Coef['C%d,0,%d'%(L,N)] = SHcof[item]                       
562                    ODFln = G2lat.Flnh(False,SH3Coef,phi,beta,SGData)
563                    lasthkl = copy.copy(hkl)                       
564                for SHname in SHnames:
565                    l,n = eval(SHname[1:])
566                    SH3name = 'C%d,0,%d'%(l,n)
567                    Ksl = G2lat.GetKsl(l,0,'0',psi,0.0)[0]
568                    dNames += [phfx+SHname]
569                    deriv.append(ODFln[SH3name][0]*Ksl/SHcof[SHname])
570            for dName,drv in zip(dNames,deriv):
571                try:
572                    ind = varyList.index(dName)
573                    pDerv[ind][ip] += drv
574                except ValueError:
575                    pass
576    return pDerv
577
578################################################################################
579##### Function & derivative calculations
580################################################################################       
581                   
582def GetAtomFXU(pfx,calcControls,parmDict):
583    'Needs a doc string'
584    Natoms = calcControls['Natoms'][pfx]
585    Tdata = Natoms*[' ',]
586    Mdata = np.zeros(Natoms)
587    IAdata = Natoms*[' ',]
588    Fdata = np.zeros(Natoms)
589    FFdata = []
590    BLdata = []
591    Xdata = np.zeros((3,Natoms))
592    dXdata = np.zeros((3,Natoms))
593    Uisodata = np.zeros(Natoms)
594    Uijdata = np.zeros((6,Natoms))
595    keys = {'Atype:':Tdata,'Amul:':Mdata,'Afrac:':Fdata,'AI/A:':IAdata,
596        'dAx:':dXdata[0],'dAy:':dXdata[1],'dAz:':dXdata[2],
597        'Ax:':Xdata[0],'Ay:':Xdata[1],'Az:':Xdata[2],'AUiso:':Uisodata,
598        'AU11:':Uijdata[0],'AU22:':Uijdata[1],'AU33:':Uijdata[2],
599        'AU12:':Uijdata[3],'AU13:':Uijdata[4],'AU23:':Uijdata[5]}
600    for iatm in range(Natoms):
601        for key in keys:
602            parm = pfx+key+str(iatm)
603            if parm in parmDict:
604                keys[key][iatm] = parmDict[parm]
605    Fdata = np.where(Fdata,Fdata,1.e-8)         #avoid divide by zero in derivative calc.?
606    return Tdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata
607   
608def GetAtomSSFXU(pfx,calcControls,parmDict):
609    'Needs a doc string'
610    Natoms = calcControls['Natoms'][pfx]
611    maxSSwave = calcControls['maxSSwave'][pfx]
612    Nwave = {'F':maxSSwave['Sfrac'],'X':maxSSwave['Spos'],'Y':maxSSwave['Spos'],'Z':maxSSwave['Spos'],
613        'U':maxSSwave['Sadp'],'M':maxSSwave['Smag'],'T':maxSSwave['Spos']}
614    XSSdata = np.zeros((6,maxSSwave['Spos'],Natoms))
615    FSSdata = np.zeros((2,maxSSwave['Sfrac'],Natoms))
616    USSdata = np.zeros((12,maxSSwave['Sadp'],Natoms))
617    MSSdata = np.zeros((6,maxSSwave['Smag'],Natoms))
618    waveTypes = []
619    keys = {'Fsin:':FSSdata[0],'Fcos:':FSSdata[1],'Fzero:':FSSdata[0],'Fwid:':FSSdata[1],
620        'Tzero:':XSSdata[0],'Xslope:':XSSdata[1],'Yslope:':XSSdata[2],'Zslope:':XSSdata[3],
621        'Xsin:':XSSdata[0],'Ysin:':XSSdata[1],'Zsin:':XSSdata[2],'Xcos:':XSSdata[3],'Ycos:':XSSdata[4],'Zcos:':XSSdata[5],
622        'U11sin:':USSdata[0],'U22sin:':USSdata[1],'U33sin:':USSdata[2],'U12sin:':USSdata[3],'U13sin:':USSdata[4],'U23sin:':USSdata[5],
623        'U11cos:':USSdata[6],'U22cos:':USSdata[7],'U33cos:':USSdata[8],'U12cos:':USSdata[9],'U13cos:':USSdata[10],'U23cos:':USSdata[11],
624        'MXsin:':MSSdata[0],'MYsin:':MSSdata[1],'MZsin:':MSSdata[2],'MXcos:':MSSdata[3],'MYcos:':MSSdata[4],'MZcos:':MSSdata[5]}
625    for iatm in range(Natoms):
626        waveTypes.append(parmDict[pfx+'waveType:'+str(iatm)])
627        for key in keys:
628            for m in range(Nwave[key[0]]):
629                parm = pfx+key+str(iatm)+':%d'%(m)
630                if parm in parmDict:
631                    keys[key][m][iatm] = parmDict[parm]
632    return waveTypes,FSSdata.squeeze(),XSSdata.squeeze(),USSdata.squeeze(),MSSdata.squeeze()   
633   
634def StructureFactor(refDict,G,hfx,pfx,SGData,calcControls,parmDict):
635    ''' Not Used: here only for comparison the StructureFactor2 - faster version
636    Compute structure factors for all h,k,l for phase
637    puts the result, F^2, in each ref[8] in refList
638    input:
639   
640    :param dict refDict: where
641        'RefList' list where each ref = h,k,l,m,d,...
642        'FF' dict of form factors - filed in below
643    :param np.array G:      reciprocal metric tensor
644    :param str pfx:    phase id string
645    :param dict SGData: space group info. dictionary output from SpcGroup
646    :param dict calcControls:
647    :param dict ParmDict:
648
649    '''       
650    phfx = pfx.split(':')[0]+hfx
651    ast = np.sqrt(np.diag(G))
652    Mast = twopisq*np.multiply.outer(ast,ast)
653    SGMT = np.array([ops[0].T for ops in SGData['SGOps']])
654    SGT = np.array([ops[1] for ops in SGData['SGOps']])
655    FFtables = calcControls['FFtables']
656    BLtables = calcControls['BLtables']
657    Tdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata = GetAtomFXU(pfx,calcControls,parmDict)
658    FF = np.zeros(len(Tdata))
659    if 'NC' in calcControls[hfx+'histType']:
660        FP,FPP = G2el.BlenResCW(Tdata,BLtables,parmDict[hfx+'Lam'])
661    else:
662        FP = np.array([FFtables[El][hfx+'FP'] for El in Tdata])
663        FPP = np.array([FFtables[El][hfx+'FPP'] for El in Tdata])
664    Uij = np.array(G2lat.U6toUij(Uijdata))
665    bij = Mast*Uij.T
666    if not len(refDict['FF']):
667        if 'N' in calcControls[hfx+'histType']:
668            dat = G2el.getBLvalues(BLtables)        #will need wave here for anom. neutron b's
669        else:
670            dat = G2el.getFFvalues(FFtables,0.)       
671        refDict['FF']['El'] = dat.keys()
672        refDict['FF']['FF'] = np.zeros((len(refDict['RefList']),len(dat)))   
673    for iref,refl in enumerate(refDict['RefList']):
674        if 'NT' in calcControls[hfx+'histType']:
675            FP,FPP = G2el.BlenResCW(Tdata,BLtables,refl[14])
676        fbs = np.array([0,0])
677        H = refl[:3]
678        SQ = 1./(2.*refl[4])**2
679        SQfactor = 4.0*SQ*twopisq
680        Bab = parmDict[phfx+'BabA']*np.exp(-parmDict[phfx+'BabU']*SQfactor)
681        if not np.any(refDict['FF']['FF'][iref]):                #no form factors - 1st time thru StructureFactor
682            if 'N' in calcControls[hfx+'histType']:
683                dat = G2el.getBLvalues(BLtables)
684                refDict['FF']['FF'][iref] = dat.values()
685            else:       #'X'
686                dat = G2el.getFFvalues(FFtables,SQ)
687                refDict['FF']['FF'][iref] = dat.values()
688        Tindx = np.array([refDict['FF']['El'].index(El) for El in Tdata])
689        FF = refDict['FF']['FF'][iref][Tindx]
690        Uniq = np.inner(H,SGMT)
691        Phi = np.inner(H,SGT)
692        phase = twopi*(np.inner(Uniq,(dXdata.T+Xdata.T))+Phi[:,np.newaxis])
693        sinp = np.sin(phase)
694        cosp = np.cos(phase)
695        biso = -SQfactor*Uisodata
696        Tiso = np.where(biso<1.,np.exp(biso),1.0)
697        HbH = np.array([-np.inner(h,np.inner(bij,h)) for h in Uniq])
698        Tuij = np.where(HbH<1.,np.exp(HbH),1.0)
699        Tcorr = Tiso*Tuij*Mdata*Fdata/len(Uniq)
700        fa = np.array([(FF+FP-Bab)*cosp*Tcorr,-FPP*sinp*Tcorr])
701        fas = np.sum(np.sum(fa,axis=1),axis=1)        #real
702        if not SGData['SGInv']:
703            fb = np.array([(FF+FP-Bab)*sinp*Tcorr,FPP*cosp*Tcorr])
704            fbs = np.sum(np.sum(fb,axis=1),axis=1)
705        fasq = fas**2
706        fbsq = fbs**2        #imaginary
707        refl[9] = np.sum(fasq)+np.sum(fbsq)
708        refl[10] = atan2d(fbs[0],fas[0])
709   
710def SStructureFactor(refDict,im,G,hfx,pfx,SGData,SSGData,calcControls,parmDict):
711    '''
712    Compute super structure factors for all h,k,l,m for phase
713    puts the result, F^2, in each ref[8+im] in refList
714    input:
715   
716    :param dict refDict: where
717        'RefList' list where each ref = h,k,l,m,d,...
718        'FF' dict of form factors - filed in below
719    :param np.array G:      reciprocal metric tensor
720    :param str pfx:    phase id string
721    :param dict SGData: space group info. dictionary output from SpcGroup
722    :param dict calcControls:
723    :param dict ParmDict:
724
725    '''       
726    phfx = pfx.split(':')[0]+hfx
727    ast = np.sqrt(np.diag(G))
728    Mast = twopisq*np.multiply.outer(ast,ast)
729    SGMT = np.array([ops[0].T for ops in SGData['SGOps']])
730    SGT = np.array([ops[1] for ops in SGData['SGOps']])
731    SSGMT = np.array([ops[0].T for ops in SSGData['SSGOps']])
732    SSGT = np.array([ops[1] for ops in SSGData['SSGOps']])
733    FFtables = calcControls['FFtables']
734    BLtables = calcControls['BLtables']
735    Tdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata = GetAtomFXU(pfx,calcControls,parmDict)
736    waveTypes,FSSdata,XSSdata,USSdata,MSSdata = GetAtomSSFXU(pfx,calcControls,parmDict)
737    FF = np.zeros(len(Tdata))
738    if 'NC' in calcControls[hfx+'histType']:
739        FP,FPP = G2el.BlenResCW(Tdata,BLtables,parmDict[hfx+'Lam'])
740    else:
741        FP = np.array([FFtables[El][hfx+'FP'] for El in Tdata])
742        FPP = np.array([FFtables[El][hfx+'FPP'] for El in Tdata])
743    Uij = np.array(G2lat.U6toUij(Uijdata))
744    bij = Mast*Uij.T
745    if not len(refDict['FF']):
746        if 'N' in calcControls[hfx+'histType']:
747            dat = G2el.getBLvalues(BLtables)        #will need wave here for anom. neutron b's
748        else:
749            dat = G2el.getFFvalues(FFtables,0.)       
750        refDict['FF']['El'] = dat.keys()
751        refDict['FF']['FF'] = np.zeros((len(refDict['RefList']),len(dat)))   
752    for iref,refl in enumerate(refDict['RefList']):
753        if 'NT' in calcControls[hfx+'histType']:
754            FP,FPP = G2el.BlenResCW(Tdata,BLtables,refl[14+im])
755        fbs = np.array([0,0])
756        H = refl[:4]
757        SQ = 1./(2.*refl[4+im])**2
758        SQfactor = 4.0*SQ*twopisq
759        Bab = parmDict[phfx+'BabA']*np.exp(-parmDict[phfx+'BabU']*SQfactor)
760        if not np.any(refDict['FF']['FF'][iref]):                #no form factors - 1st time thru StructureFactor
761            if 'N' in calcControls[hfx+'histType']:
762                dat = G2el.getBLvalues(BLtables)
763                refDict['FF']['FF'][iref] = dat.values()
764            else:       #'X'
765                dat = G2el.getFFvalues(FFtables,SQ)
766                refDict['FF']['FF'][iref] = dat.values()
767        Tindx = np.array([refDict['FF']['El'].index(El) for El in Tdata])
768        FF = refDict['FF']['FF'][iref][Tindx]
769        Uniq = np.inner(H[:3],SGMT)
770        SSUniq = np.inner(H,SSGMT)
771        Phi = np.inner(H[:3],SGT)
772        SSPhi = np.inner(H,SSGT)
773        GfpuA,GfpuB = G2mth.Modulation(waveTypes,SSUniq,SSPhi,FSSdata,XSSdata,USSdata)       
774        phase = twopi*(np.inner(Uniq,(dXdata.T+Xdata.T))+Phi[:,np.newaxis])
775        sinp = np.sin(phase)
776        cosp = np.cos(phase)
777        biso = -SQfactor*Uisodata
778        Tiso = np.where(biso<1.,np.exp(biso),1.0)
779        HbH = np.array([-np.inner(h,np.inner(bij,h)) for h in Uniq])
780        Tuij = np.where(HbH<1.,np.exp(HbH),1.0)
781        Tcorr = Tiso*Tuij*Mdata*Fdata/len(Uniq)
782        fa = np.array([(FF+FP-Bab)*cosp*Tcorr,-FPP*sinp*Tcorr])
783        fb = np.zeros_like(fa)
784        if not SGData['SGInv']:
785            fb = np.array([(FF+FP-Bab)*sinp*Tcorr,FPP*cosp*Tcorr])
786        fa = fa*GfpuA-fb*GfpuB
787        fb = fb*GfpuA+fa*GfpuB
788        fas = np.real(np.sum(np.sum(fa,axis=1),axis=1))        #real
789        fbs = np.real(np.sum(np.sum(fb,axis=1),axis=1))
790           
791        fasq = fas**2
792        fbsq = fbs**2        #imaginary
793        refl[9+im] = np.sum(fasq)+np.sum(fbsq)
794        refl[10+im] = atan2d(fbs[0],fas[0])
795   
796def StructureFactor2(refDict,G,hfx,pfx,SGData,calcControls,parmDict):
797    ''' Compute structure factors for all h,k,l for phase
798    puts the result, F^2, in each ref[8] in refList
799    input:
800   
801    :param dict refDict: where
802        'RefList' list where each ref = h,k,l,m,d,...
803        'FF' dict of form factors - filed in below
804    :param np.array G:      reciprocal metric tensor
805    :param str pfx:    phase id string
806    :param dict SGData: space group info. dictionary output from SpcGroup
807    :param dict calcControls:
808    :param dict ParmDict:
809
810    '''       
811    phfx = pfx.split(':')[0]+hfx
812    ast = np.sqrt(np.diag(G))
813    Mast = twopisq*np.multiply.outer(ast,ast)
814    SGMT = np.array([ops[0].T for ops in SGData['SGOps']])
815    SGT = np.array([ops[1] for ops in SGData['SGOps']])
816    FFtables = calcControls['FFtables']
817    BLtables = calcControls['BLtables']
818    Tdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata = GetAtomFXU(pfx,calcControls,parmDict)
819    FF = np.zeros(len(Tdata))
820    if 'NC' in calcControls[hfx+'histType']:
821        FP,FPP = G2el.BlenResCW(Tdata,BLtables,parmDict[hfx+'Lam'])
822    elif 'X' in calcControls[hfx+'histType']:
823        FP = np.array([FFtables[El][hfx+'FP'] for El in Tdata])
824        FPP = np.array([FFtables[El][hfx+'FPP'] for El in Tdata])
825    Uij = np.array(G2lat.U6toUij(Uijdata))
826    bij = Mast*Uij.T
827    blkSize = 100       #no. of reflections in a block
828    nRef = refDict['RefList'].shape[0]
829    if not len(refDict['FF']):                #no form factors - 1st time thru StructureFactor
830        if 'N' in calcControls[hfx+'histType']:
831            dat = G2el.getBLvalues(BLtables)
832            refDict['FF']['El'] = dat.keys()
833            refDict['FF']['FF'] = np.ones((nRef,len(dat)))*dat.values()           
834        else:       #'X'
835            dat = G2el.getFFvalues(FFtables,0.)
836            refDict['FF']['El'] = dat.keys()
837            refDict['FF']['FF'] = np.ones((nRef,len(dat)))
838            for iref,ref in enumerate(refDict['RefList']):
839                SQ = 1./(2.*ref[4])**2
840                dat = G2el.getFFvalues(FFtables,SQ)
841                refDict['FF']['FF'][iref] *= dat.values()
842#reflection processing begins here - big arrays!
843    iBeg = 0           
844    while iBeg < nRef:
845        iFin = min(iBeg+blkSize,nRef)
846        refl = refDict['RefList'][iBeg:iFin]
847        H = refl.T[:3]
848        SQ = 1./(2.*refl.T[4])**2
849        SQfactor = 4.0*SQ*twopisq
850        if 'T' in calcControls[hfx+'histType']:
851            if 'P' in calcControls[hfx+'histType']:
852                FP,FPP = G2el.BlenResTOF(Tdata,BLtables,refl.T[14])
853            else:
854                FP,FPP = G2el.BlenResTOF(Tdata,BLtables,refl.T[12])
855            FP = np.repeat(FP.T,len(SGT),axis=0)
856            FPP = np.repeat(FPP.T,len(SGT),axis=0)
857        Bab = np.repeat(parmDict[phfx+'BabA']*np.exp(-parmDict[phfx+'BabU']*SQfactor),len(SGT))
858        Flack = 1.0
859#        Flack = 1.-2.*parmDict[phfx+'Flack']
860        Tindx = np.array([refDict['FF']['El'].index(El) for El in Tdata])
861        FF = np.repeat(refDict['FF']['FF'][iBeg:iFin].T[Tindx].T,len(SGT),axis=0)
862        Uniq = np.reshape(np.inner(H.T,SGMT),(-1,3))
863        Phi = np.inner(H.T,SGT).flatten()
864        phase = twopi*(np.inner(Uniq,(dXdata+Xdata).T)+Phi[:,np.newaxis])
865        sinp = np.sin(phase)
866        cosp = np.cos(phase)
867        biso = -SQfactor*Uisodata[:,np.newaxis]
868        Tiso = np.repeat(np.where(biso<1.,np.exp(biso),1.0),len(SGT),axis=1).T
869        HbH = -np.sum(Uniq.T*np.inner(bij,Uniq),axis=1)
870        Tuij = np.where(HbH<1.,np.exp(HbH),1.0).T
871        Tcorr = Tiso*Tuij*Mdata*Fdata/len(SGMT)
872        fa = np.array([((FF+FP).T-Bab).T*cosp*Tcorr,-Flack*FPP*sinp*Tcorr])
873        fa = np.reshape(fa,(2,len(refl),len(SGT),len(Mdata)))   #real A,-b
874        fas = np.sum(np.sum(fa,axis=2),axis=2)        #real sum over atoms & unique hkl
875        fb = np.array([((FF+FP).T-Bab).T*sinp*Tcorr,Flack*FPP*cosp*Tcorr])
876        fb = np.reshape(fb,(2,len(refl),len(SGT),len(Mdata)))   #imag -B,+a
877        fbs = np.sum(np.sum(fb,axis=2),axis=2)  #imag sum over atoms & uniq hkl
878        if SGData['SGInv']: #centrosymmetric; B=0
879            fbs[0] *= 0.
880        if 'P' in calcControls[hfx+'histType']:
881            refl.T[9] = np.sum(fas**2,axis=0)+np.sum(fbs**2,axis=0)
882        else:
883            refl.T[9] = np.sum(fas,axis=0)**2+np.sum(fbs,axis=0)**2
884        refl.T[10] = atan2d(fbs[0],fas[0])  #ignore f' & f"?
885#        refl.T[10] = atan2d(np.sum(fbs,axis=0),np.sum(fas,axis=0)) #include f' & f"
886        iBeg += blkSize
887   
888def StructureFactorDerv(refDict,G,hfx,pfx,SGData,calcControls,parmDict):
889    'Needs a doc string'
890    phfx = pfx.split(':')[0]+hfx
891    ast = np.sqrt(np.diag(G))
892    Mast = twopisq*np.multiply.outer(ast,ast)
893    SGMT = np.array([ops[0].T for ops in SGData['SGOps']])
894    SGT = np.array([ops[1] for ops in SGData['SGOps']])
895    FFtables = calcControls['FFtables']
896    BLtables = calcControls['BLtables']
897    nRef = len(refDict['RefList'])
898    Tdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata = GetAtomFXU(pfx,calcControls,parmDict)
899    mSize = len(Mdata)
900    FF = np.zeros(len(Tdata))
901    if 'NC' in calcControls[hfx+'histType']:
902        FP,FPP = G2el.BlenResCW(Tdata,BLtables,parmDict[hfx+'Lam'])
903    elif 'X' in calcControls[hfx+'histType']:
904        FP = np.array([FFtables[El][hfx+'FP'] for El in Tdata])
905        FPP = np.array([FFtables[El][hfx+'FPP'] for El in Tdata])
906    Uij = np.array(G2lat.U6toUij(Uijdata))
907    bij = Mast*Uij.T
908    dFdvDict = {}
909    dFdfr = np.zeros((nRef,mSize))
910    dFdx = np.zeros((nRef,mSize,3))
911    dFdui = np.zeros((nRef,mSize))
912    dFdua = np.zeros((nRef,mSize,6))
913    dFdbab = np.zeros((nRef,2))
914    for iref,refl in enumerate(refDict['RefList']):
915        if 'T' in calcControls[hfx+'histType']:
916            FP,FPP = G2el.BlenResCW(Tdata,BLtables,refl.T[12])
917        H = np.array(refl[:3])
918        SQ = 1./(2.*refl[4])**2             # or (sin(theta)/lambda)**2
919        SQfactor = 8.0*SQ*np.pi**2
920        dBabdA = np.exp(-parmDict[phfx+'BabU']*SQfactor)
921        Bab = parmDict[phfx+'BabA']*dBabdA
922        Tindx = np.array([refDict['FF']['El'].index(El) for El in Tdata])
923        FF = refDict['FF']['FF'][iref].T[Tindx]
924        Uniq = np.inner(H,SGMT)
925        Phi = np.inner(H,SGT)
926        phase = twopi*(np.inner((dXdata.T+Xdata.T),Uniq)+Phi[np.newaxis,:])
927        sinp = np.sin(phase)
928        cosp = np.cos(phase)
929        occ = Mdata*Fdata/len(Uniq)
930        biso = -SQfactor*Uisodata
931        Tiso = np.where(biso<1.,np.exp(biso),1.0)
932        HbH = -np.inner(H,np.inner(bij,H))
933        Hij = np.array([Mast*np.multiply.outer(U,U) for U in Uniq])
934        Hij = np.array([G2lat.UijtoU6(Uij) for Uij in Hij])
935        Tuij = np.where(HbH<1.,np.exp(HbH),1.0)
936        Tcorr = Tiso*Tuij
937        Flack = 1.0
938#        Flack = (1.-2.*parmDict[phfx+'Flack'])
939        fot = (FF+FP-Bab)*occ*Tcorr
940        fotp = Flack*FPP*occ*Tcorr
941        fa = np.array([fot[:,np.newaxis]*cosp,fotp[:,np.newaxis]*cosp])       #non positions
942        fb = np.array([fot[:,np.newaxis]*sinp,-fotp[:,np.newaxis]*sinp])
943       
944        fas = np.sum(np.sum(fa,axis=1),axis=1)      #real sum over atoms & unique hkl
945        fbs = np.sum(np.sum(fb,axis=1),axis=1)      #imag sum over atoms & uniq hkl
946        fax = np.array([-fot[:,np.newaxis]*sinp,-fotp[:,np.newaxis]*sinp])   #positions
947        fbx = np.array([fot[:,np.newaxis]*cosp,-fot[:,np.newaxis]*cosp])
948        #sum below is over Uniq
949        dfadfr = np.sum(fa/occ[:,np.newaxis],axis=2)        #Fdata != 0 ever avoids /0. problem
950        dfadx = np.sum(twopi*Uniq*fax[:,:,:,np.newaxis],axis=2)
951        dfadui = np.sum(-SQfactor*fa,axis=2)
952        dfadua = np.sum(-Hij*fa[:,:,:,np.newaxis],axis=2)
953        dfadba = np.sum(-cosp*(occ*Tcorr)[:,np.newaxis],axis=1)
954        if not SGData['SGInv']:
955            dfbdfr = np.sum(fb/occ[:,np.newaxis],axis=2)        #Fdata != 0 ever avoids /0. problem
956            dfbdx = np.sum(twopi*Uniq*fbx[:,:,:,np.newaxis],axis=2)           
957            dfbdui = np.sum(-SQfactor*fb,axis=2)
958            dfbdua = np.sum(-Hij*fb[:,:,:,np.newaxis],axis=2)
959            dfbdba = np.sum(-sinp*(occ*Tcorr)[:,np.newaxis],axis=1)
960        else:
961            dfbdfr = np.zeros_like(dfadfr)
962            dfbdx = np.zeros_like(dfadx)
963            dfbdui = np.zeros_like(dfadui)
964            dfbdua = np.zeros_like(dfadua)
965            dfbdba = np.zeros_like(dfadba)
966        #NB: the above have been checked against PA(1:10,1:2) in strfctr.for for Al2O3!   
967        if 'P' in calcControls[hfx+'histType']: #checked perfect for centro & noncentro
968            dFdfr[iref] = 2.*(fas[0]*dfadfr[0]+fas[1]*dfadfr[1])*Mdata/len(Uniq)+   \
969                2.*(fbs[0]*dfbdfr[0]-fbs[1]*dfbdfr[1])*Mdata/len(Uniq)
970            dFdx[iref] = 2.*(fas[0]*dfadx[0]+fas[1]*dfadx[1])+  \
971                2.*(fbs[0]*dfbdx[0]+fbs[1]*dfbdx[1])
972            dFdui[iref] = 2.*(fas[0]*dfadui[0]+fas[1]*dfadui[1])+   \
973                2.*(fbs[0]*dfbdui[0]-fbs[1]*dfbdui[1])
974            dFdua[iref] = 2.*(fas[0]*dfadua[0]+fas[1]*dfadua[1])+   \
975                2.*(fbs[0]*dfbdua[0]+fbs[1]*dfbdua[1])
976        else:
977            SA = fas[0]-fbs[1]
978            SB = fbs[0]+fas[1]
979            dFdfr[iref] = 2.*SA*(dfadfr[0]+dfbdfr[1])*Mdata/len(Uniq)+ \
980                2.*SB*(dfbdfr[0]+dfadfr[1])*Mdata/len(Uniq)
981            dFdx[iref] = 2.*SA*(dfadx[0]+dfbdx[1])+2.*SB*(dfbdx[0]+dfadx[1])
982            dFdui[iref] = 2.*SA*(dfadui[0]+dfbdui[1])+2.*SB*(dfbdui[0]+dfadui[1])
983            dFdua[iref] = 2.*SA*(dfadua[0]+dfbdua[1])+2.*SB*(dfbdua[0]+dfadua[1])
984        dFdbab[iref] = 2.*fas[0]*np.array([np.sum(dfadba*dBabdA),np.sum(-dfadba*parmDict[phfx+'BabA']*SQfactor*dBabdA)]).T+ \
985            2.*fbs[0]*np.array([np.sum(dfbdba*dBabdA),np.sum(-dfbdba*parmDict[phfx+'BabA']*SQfactor*dBabdA)]).T
986        #loop over atoms - each dict entry is list of derivatives for all the reflections
987    for i in range(len(Mdata)):
988        dFdvDict[pfx+'Afrac:'+str(i)] = dFdfr.T[i]
989        dFdvDict[pfx+'dAx:'+str(i)] = dFdx.T[0][i]
990        dFdvDict[pfx+'dAy:'+str(i)] = dFdx.T[1][i]
991        dFdvDict[pfx+'dAz:'+str(i)] = dFdx.T[2][i]
992        dFdvDict[pfx+'AUiso:'+str(i)] = dFdui.T[i]
993        dFdvDict[pfx+'AU11:'+str(i)] = dFdua.T[0][i]
994        dFdvDict[pfx+'AU22:'+str(i)] = dFdua.T[1][i]
995        dFdvDict[pfx+'AU33:'+str(i)] = dFdua.T[2][i]
996        dFdvDict[pfx+'AU12:'+str(i)] = 0.5*dFdua.T[3][i]
997        dFdvDict[pfx+'AU13:'+str(i)] = 0.5*dFdua.T[4][i]
998        dFdvDict[pfx+'AU23:'+str(i)] = 0.5*dFdua.T[5][i]
999    dFdvDict[pfx+'BabA'] = dFdbab.T[0]
1000    dFdvDict[pfx+'BabU'] = dFdbab.T[1]
1001    return dFdvDict
1002   
1003def SStructureFactorDerv(refDict,im,G,hfx,pfx,SGData,SSGData,calcControls,parmDict):
1004    'Needs a doc string'
1005    phfx = pfx.split(':')[0]+hfx
1006    ast = np.sqrt(np.diag(G))
1007    Mast = twopisq*np.multiply.outer(ast,ast)
1008    SGMT = np.array([ops[0].T for ops in SGData['SGOps']])
1009    SGT = np.array([ops[1] for ops in SGData['SGOps']])
1010    SSGMT = np.array([ops[0].T for ops in SSGData['SSGOps']])
1011    SSGT = np.array([ops[1] for ops in SSGData['SSGOps']])
1012    FFtables = calcControls['FFtables']
1013    BLtables = calcControls['BLtables']
1014    nRef = len(refDict['RefList'])
1015    Tdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata = GetAtomFXU(pfx,calcControls,parmDict)
1016    waveTypes,FSSdata,XSSdata,USSdata,MSSdata = GetAtomSSFXU(pfx,calcControls,parmDict)
1017    mSize = len(Mdata)
1018    FF = np.zeros(len(Tdata))
1019    if 'NC' in calcControls[hfx+'histType']:
1020        FP,FPP = G2el.BlenResCW(Tdata,BLtables,parmDict[hfx+'Lam'])
1021    elif 'X' in calcControls[hfx+'histType']:
1022        FP = np.array([FFtables[El][hfx+'FP'] for El in Tdata])
1023        FPP = np.array([FFtables[El][hfx+'FPP'] for El in Tdata])
1024    Uij = np.array(G2lat.U6toUij(Uijdata))
1025    bij = Mast*Uij.T
1026    dFdvDict = {}
1027    dFdfr = np.zeros((nRef,mSize))
1028    dFdx = np.zeros((nRef,mSize,3))
1029    dFdui = np.zeros((nRef,mSize))
1030    dFdua = np.zeros((nRef,mSize,6))
1031    dFdbab = np.zeros((nRef,2))
1032    for iref,refl in enumerate(refDict['RefList']):
1033        if 'T' in calcControls[hfx+'histType']:
1034            FP,FPP = G2el.BlenResCW(Tdata,BLtables,refl.T[12+im])
1035        H = np.array(refl[:4])
1036        SQ = 1./(2.*refl[4+im])**2             # or (sin(theta)/lambda)**2
1037        SQfactor = 8.0*SQ*np.pi**2
1038        dBabdA = np.exp(-parmDict[phfx+'BabU']*SQfactor)
1039        Bab = parmDict[phfx+'BabA']*dBabdA
1040        Tindx = np.array([refDict['FF']['El'].index(El) for El in Tdata])
1041        FF = refDict['FF']['FF'][iref].T[Tindx]
1042        Uniq = np.inner(H[:3],SGMT)
1043        SSUniq = np.inner(H,SSGMT)
1044        Phi = np.inner(H[:3],SGT)
1045        SSPhi = np.inner(H,SSGT)
1046        GfpuA,GfpuB = G2mth.Modulation(waveTypes,SSUniq,SSPhi,FSSdata,XSSdata,USSdata)
1047        dGAdk,dGBdk = G2mth.ModulationDerv(waveTypes,SSUniq,SSPhi,FSSdata,XSSdata,USSdata)
1048        #need ModulationDerv here dGAdXsin, etc 
1049        phase = twopi*(np.inner((dXdata.T+Xdata.T),Uniq)+Phi[np.newaxis,:])
1050        sinp = np.sin(phase)
1051        cosp = np.cos(phase)
1052        occ = Mdata*Fdata/len(Uniq)
1053        biso = -SQfactor*Uisodata
1054        Tiso = np.where(biso<1.,np.exp(biso),1.0)
1055        HbH = -np.inner(H[:3],np.inner(bij,H[:3]))
1056        Hij = np.array([Mast*np.multiply.outer(U,U) for U in Uniq])
1057        Hij = np.array([G2lat.UijtoU6(Uij) for Uij in Hij])
1058        Tuij = np.where(HbH<1.,np.exp(HbH),1.0)
1059        Tcorr = Tiso*Tuij
1060        fot = (FF+FP-Bab)*occ*Tcorr
1061        fotp = FPP*occ*Tcorr
1062        fa = np.array([fot[:,np.newaxis]*cosp,fotp[:,np.newaxis]*cosp])       #non positions
1063        fb = np.array([fot[:,np.newaxis]*sinp,-fotp[:,np.newaxis]*sinp])
1064        GfpuA = np.swapaxes(GfpuA,1,2)
1065        GfpuB = np.swapaxes(GfpuB,1,2)
1066        fa = fa*GfpuA-fb*GfpuB
1067        fb = fb*GfpuA+fa*GfpuB
1068       
1069        fas = np.sum(np.sum(fa,axis=1),axis=1)
1070        fbs = np.sum(np.sum(fb,axis=1),axis=1)
1071        fax = np.array([-fot[:,np.newaxis]*sinp,-fotp[:,np.newaxis]*sinp])   #positions
1072        fbx = np.array([fot[:,np.newaxis]*cosp,-fot[:,np.newaxis]*cosp])
1073        fax = fax*GfpuA-fbx*GfpuB
1074        fbx = fbx*GfpuA+fax*GfpuB
1075        #sum below is over Uniq
1076        dfadfr = np.sum(fa/occ[:,np.newaxis],axis=2)        #Fdata != 0 ever avoids /0. problem
1077        dfadx = np.sum(twopi*Uniq*fax[:,:,:,np.newaxis],axis=2)
1078        dfadui = np.sum(-SQfactor*fa,axis=2)
1079        dfadua = np.sum(-Hij*fa[:,:,:,np.newaxis],axis=2)
1080        dfadba = np.sum(-cosp*(occ*Tcorr)[:,np.newaxis],axis=1)
1081        #NB: the above have been checked against PA(1:10,1:2) in strfctr.for for al2O3!   
1082        dFdfr[iref] = 2.*(fas[0]*dfadfr[0]+fas[1]*dfadfr[1])*Mdata/len(Uniq)
1083        dFdx[iref] = 2.*(fas[0]*dfadx[0]+fas[1]*dfadx[1])
1084        dFdui[iref] = 2.*(fas[0]*dfadui[0]+fas[1]*dfadui[1])
1085        dFdua[iref] = 2.*(fas[0]*dfadua[0]+fas[1]*dfadua[1])
1086        dFdbab[iref] = 2.*fas[0]*np.array([np.sum(dfadba*dBabdA),np.sum(-dfadba*parmDict[phfx+'BabA']*SQfactor*dBabdA)]).T
1087        #need dFdXsin, etc for modulations...
1088        if not SGData['SGInv']:
1089            dfbdfr = np.sum(fb/occ[:,np.newaxis],axis=2)        #Fdata != 0 ever avoids /0. problem
1090            dfbdx = np.sum(twopi*Uniq*fbx[:,:,:,np.newaxis],axis=2)           
1091            dfbdui = np.sum(-SQfactor*fb,axis=2)
1092            dfbdua = np.sum(-Hij*fb[:,:,:,np.newaxis],axis=2)
1093            dfbdba = np.sum(-sinp*(occ*Tcorr)[:,np.newaxis],axis=1)
1094            dFdfr[iref] += 2.*(fbs[0]*dfbdfr[0]-fbs[1]*dfbdfr[1])*Mdata/len(Uniq)
1095            dFdx[iref] += 2.*(fbs[0]*dfbdx[0]+fbs[1]*dfbdx[1])
1096            dFdui[iref] += 2.*(fbs[0]*dfbdui[0]-fbs[1]*dfbdui[1])
1097            dFdua[iref] += 2.*(fbs[0]*dfbdua[0]+fbs[1]*dfbdua[1])
1098            dFdbab[iref] += 2.*fbs[0]*np.array([np.sum(dfbdba*dBabdA),np.sum(-dfbdba*parmDict[phfx+'BabA']*SQfactor*dBabdA)]).T
1099        #need dFdXsin, etc for modulations...
1100        #loop over atoms - each dict entry is list of derivatives for all the reflections
1101    for i in range(len(Mdata)):     
1102        dFdvDict[pfx+'Afrac:'+str(i)] = dFdfr.T[i]
1103        dFdvDict[pfx+'dAx:'+str(i)] = dFdx.T[0][i]
1104        dFdvDict[pfx+'dAy:'+str(i)] = dFdx.T[1][i]
1105        dFdvDict[pfx+'dAz:'+str(i)] = dFdx.T[2][i]
1106        dFdvDict[pfx+'AUiso:'+str(i)] = dFdui.T[i]
1107        dFdvDict[pfx+'AU11:'+str(i)] = dFdua.T[0][i]
1108        dFdvDict[pfx+'AU22:'+str(i)] = dFdua.T[1][i]
1109        dFdvDict[pfx+'AU33:'+str(i)] = dFdua.T[2][i]
1110        dFdvDict[pfx+'AU12:'+str(i)] = .5*dFdua.T[3][i]
1111        dFdvDict[pfx+'AU13:'+str(i)] = .5*dFdua.T[4][i]
1112        dFdvDict[pfx+'AU23:'+str(i)] = .5*dFdua.T[5][i]
1113        #need dFdvDict[pfx+'Xsin:'+str[i]:str(m)], etc for modulations...
1114    dFdvDict[pfx+'BabA'] = dFdbab.T[0]
1115    dFdvDict[pfx+'BabU'] = dFdbab.T[1]
1116    return dFdvDict
1117   
1118def SCExtinction(ref,im,phfx,hfx,pfx,calcControls,parmDict,varyList):
1119    ''' Single crystal extinction function; returns extinction & derivative
1120    '''
1121    extCor = 1.0
1122    dervDict = {}
1123    dervCor = 1.0
1124    if calcControls[phfx+'EType'] != 'None':
1125        SQ = 1/(4.*ref[4+im]**2)
1126        if 'C' in parmDict[hfx+'Type']:           
1127            cos2T = 1.0-2.*SQ*parmDict[hfx+'Lam']**2           #cos(2theta)
1128        else:   #'T'
1129            cos2T = 1.0-2.*SQ*ref[12+im]**2                       #cos(2theta)           
1130        if 'SXC' in parmDict[hfx+'Type']:
1131            AV = 7.9406e5/parmDict[pfx+'Vol']**2
1132            PL = np.sqrt(1.0-cos2T**2)/parmDict[hfx+'Lam']
1133            P12 = (calcControls[phfx+'Cos2TM']+cos2T**4)/(calcControls[phfx+'Cos2TM']+cos2T**2)
1134            PLZ = AV*P12*ref[9+im]*parmDict[hfx+'Lam']**2
1135        elif 'SNT' in parmDict[hfx+'Type']:
1136            AV = 1.e7/parmDict[pfx+'Vol']**2
1137            PL = SQ
1138            PLZ = AV*ref[9+im]*ref[12+im]**2
1139        elif 'SNC' in parmDict[hfx+'Type']:
1140            AV = 1.e7/parmDict[pfx+'Vol']**2
1141            PL = np.sqrt(1.0-cos2T**2)/parmDict[hfx+'Lam']
1142            PLZ = AV*ref[9+im]*parmDict[hfx+'Lam']**2
1143           
1144        if 'Primary' in calcControls[phfx+'EType']:
1145            PLZ *= 1.5
1146        else:
1147            if 'C' in parmDict[hfx+'Type']:
1148                PLZ *= calcControls[phfx+'Tbar']
1149            else: #'T'
1150                PLZ *= ref[13+im]      #t-bar
1151        if 'Primary' in calcControls[phfx+'EType']:
1152            PLZ *= 1.5
1153            PSIG = parmDict[phfx+'Ep']
1154        elif 'I & II' in calcControls[phfx+'EType']:
1155            PSIG = parmDict[phfx+'Eg']/np.sqrt(1.+(parmDict[phfx+'Es']*PL/parmDict[phfx+'Eg'])**2)
1156        elif 'Type II' in calcControls[phfx+'EType']:
1157            PSIG = parmDict[phfx+'Es']
1158        else:       # 'Secondary Type I'
1159            PSIG = parmDict[phfx+'Eg']/PL
1160           
1161        AG = 0.58+0.48*cos2T+0.24*cos2T**2
1162        AL = 0.025+0.285*cos2T
1163        BG = 0.02-0.025*cos2T
1164        BL = 0.15-0.2*(0.75-cos2T)**2
1165        if cos2T < 0.:
1166            BL = -0.45*cos2T
1167        CG = 2.
1168        CL = 2.
1169        PF = PLZ*PSIG
1170       
1171        if 'Gaussian' in calcControls[phfx+'EApprox']:
1172            PF4 = 1.+CG*PF+AG*PF**2/(1.+BG*PF)
1173            extCor = np.sqrt(PF4)
1174            PF3 = 0.5*(CG+2.*AG*PF/(1.+BG*PF)-AG*PF**2*BG/(1.+BG*PF)**2)/(PF4*extCor)
1175        else:
1176            PF4 = 1.+CL*PF+AL*PF**2/(1.+BL*PF)
1177            extCor = np.sqrt(PF4)
1178            PF3 = 0.5*(CL+2.*AL*PF/(1.+BL*PF)-AL*PF**2*BL/(1.+BL*PF)**2)/(PF4*extCor)
1179
1180        dervCor = (1.+PF)*PF3   #extinction corr for other derivatives
1181        if 'Primary' in calcControls[phfx+'EType'] and phfx+'Ep' in varyList:
1182            dervDict[phfx+'Ep'] = -ref[7+im]*PLZ*PF3
1183        if 'II' in calcControls[phfx+'EType'] and phfx+'Es' in varyList:
1184            dervDict[phfx+'Es'] = -ref[7+im]*PLZ*PF3*(PSIG/parmDict[phfx+'Es'])**3
1185        if 'I' in calcControls[phfx+'EType'] and phfx+'Eg' in varyList:
1186            dervDict[phfx+'Eg'] = -ref[7+im]*PLZ*PF3*(PSIG/parmDict[phfx+'Eg'])**3*PL**2
1187               
1188    return 1./extCor,dervDict,dervCor
1189   
1190def Dict2Values(parmdict, varylist):
1191    '''Use before call to leastsq to setup list of values for the parameters
1192    in parmdict, as selected by key in varylist'''
1193    return [parmdict[key] for key in varylist] 
1194   
1195def Values2Dict(parmdict, varylist, values):
1196    ''' Use after call to leastsq to update the parameter dictionary with
1197    values corresponding to keys in varylist'''
1198    parmdict.update(zip(varylist,values))
1199   
1200def GetNewCellParms(parmDict,varyList):
1201    'Needs a doc string'
1202    newCellDict = {}
1203    Anames = ['A'+str(i) for i in range(6)]
1204    Ddict = dict(zip(['D11','D22','D33','D12','D13','D23'],Anames))
1205    for item in varyList:
1206        keys = item.split(':')
1207        if keys[2] in Ddict:
1208            key = keys[0]+'::'+Ddict[keys[2]]       #key is e.g. '0::A0'
1209            parm = keys[0]+'::'+keys[2]             #parm is e.g. '0::D11'
1210            newCellDict[parm] = [key,parmDict[key]+parmDict[item]]
1211    return newCellDict          # is e.g. {'0::D11':A0-D11}
1212   
1213def ApplyXYZshifts(parmDict,varyList):
1214    '''
1215    takes atom x,y,z shift and applies it to corresponding atom x,y,z value
1216   
1217    :param dict parmDict: parameter dictionary
1218    :param list varyList: list of variables (not used!)
1219    :returns: newAtomDict - dictionary of new atomic coordinate names & values; key is parameter shift name
1220
1221    '''
1222    newAtomDict = {}
1223    for item in parmDict:
1224        if 'dA' in item:
1225            parm = ''.join(item.split('d'))
1226            parmDict[parm] += parmDict[item]
1227            newAtomDict[item] = [parm,parmDict[parm]]
1228    return newAtomDict
1229   
1230def SHTXcal(refl,im,g,pfx,hfx,SGData,calcControls,parmDict):
1231    'Spherical harmonics texture'
1232    IFCoup = 'Bragg' in calcControls[hfx+'instType']
1233    if 'T' in calcControls[hfx+'histType']:
1234        tth = parmDict[hfx+'2-theta']
1235    else:
1236        tth = refl[5+im]
1237    odfCor = 1.0
1238    H = refl[:3]
1239    cell = G2lat.Gmat2cell(g)
1240    Sangls = [parmDict[pfx+'SH omega'],parmDict[pfx+'SH chi'],parmDict[pfx+'SH phi']]
1241    Gangls = [parmDict[hfx+'Phi'],parmDict[hfx+'Chi'],parmDict[hfx+'Omega'],parmDict[hfx+'Azimuth']]
1242    phi,beta = G2lat.CrsAng(H,cell,SGData)
1243    psi,gam,x,x = G2lat.SamAng(tth/2.,Gangls,Sangls,IFCoup) #ignore 2 sets of angle derivs.
1244    SHnames = G2lat.GenSHCoeff(SGData['SGLaue'],parmDict[pfx+'SHmodel'],parmDict[pfx+'SHorder'])
1245    for item in SHnames:
1246        L,M,N = eval(item.strip('C'))
1247        Kcl = G2lat.GetKcl(L,N,SGData['SGLaue'],phi,beta)
1248        Ksl,x,x = G2lat.GetKsl(L,M,parmDict[pfx+'SHmodel'],psi,gam)
1249        Lnorm = G2lat.Lnorm(L)
1250        odfCor += parmDict[pfx+item]*Lnorm*Kcl*Ksl
1251    return odfCor
1252   
1253def SHTXcalDerv(refl,im,g,pfx,hfx,SGData,calcControls,parmDict):
1254    'Spherical harmonics texture derivatives'
1255    if 'T' in calcControls[hfx+'histType']:
1256        tth = parmDict[hfx+'2-theta']
1257    else:
1258        tth = refl[5+im]
1259    IFCoup = 'Bragg' in calcControls[hfx+'instType']
1260    odfCor = 1.0
1261    dFdODF = {}
1262    dFdSA = [0,0,0]
1263    H = refl[:3]
1264    cell = G2lat.Gmat2cell(g)
1265    Sangls = [parmDict[pfx+'SH omega'],parmDict[pfx+'SH chi'],parmDict[pfx+'SH phi']]
1266    Gangls = [parmDict[hfx+'Phi'],parmDict[hfx+'Chi'],parmDict[hfx+'Omega'],parmDict[hfx+'Azimuth']]
1267    phi,beta = G2lat.CrsAng(H,cell,SGData)
1268    psi,gam,dPSdA,dGMdA = G2lat.SamAng(tth/2.,Gangls,Sangls,IFCoup)
1269    SHnames = G2lat.GenSHCoeff(SGData['SGLaue'],parmDict[pfx+'SHmodel'],parmDict[pfx+'SHorder'])
1270    for item in SHnames:
1271        L,M,N = eval(item.strip('C'))
1272        Kcl = G2lat.GetKcl(L,N,SGData['SGLaue'],phi,beta)
1273        Ksl,dKsdp,dKsdg = G2lat.GetKsl(L,M,parmDict[pfx+'SHmodel'],psi,gam)
1274        Lnorm = G2lat.Lnorm(L)
1275        odfCor += parmDict[pfx+item]*Lnorm*Kcl*Ksl
1276        dFdODF[pfx+item] = Lnorm*Kcl*Ksl
1277        for i in range(3):
1278            dFdSA[i] += parmDict[pfx+item]*Lnorm*Kcl*(dKsdp*dPSdA[i]+dKsdg*dGMdA[i])
1279    return odfCor,dFdODF,dFdSA
1280   
1281def SHPOcal(refl,im,g,phfx,hfx,SGData,calcControls,parmDict):
1282    'spherical harmonics preferred orientation (cylindrical symmetry only)'
1283    if 'T' in calcControls[hfx+'histType']:
1284        tth = parmDict[hfx+'2-theta']
1285    else:
1286        tth = refl[5+im]
1287    odfCor = 1.0
1288    H = refl[:3]
1289    cell = G2lat.Gmat2cell(g)
1290    Sangls = [0.,0.,0.]
1291    if 'Bragg' in calcControls[hfx+'instType']:
1292        Gangls = [0.,90.,0.,parmDict[hfx+'Azimuth']]
1293        IFCoup = True
1294    else:
1295        Gangls = [parmDict[hfx+'Phi'],parmDict[hfx+'Chi'],parmDict[hfx+'Omega'],parmDict[hfx+'Azimuth']]
1296        IFCoup = False
1297    phi,beta = G2lat.CrsAng(H,cell,SGData)
1298    psi,gam,x,x = G2lat.SamAng(tth/2.,Gangls,Sangls,IFCoup) #ignore 2 sets of angle derivs.
1299    SHnames = calcControls[phfx+'SHnames']
1300    for item in SHnames:
1301        L,N = eval(item.strip('C'))
1302        Kcl = G2lat.GetKcl(L,N,SGData['SGLaue'],phi,beta)
1303        Ksl,x,x = G2lat.GetKsl(L,0,'0',psi,gam)
1304        Lnorm = G2lat.Lnorm(L)
1305        odfCor += parmDict[phfx+item]*Lnorm*Kcl*Ksl
1306    return np.squeeze(odfCor)
1307   
1308def SHPOcalDerv(refl,im,g,phfx,hfx,SGData,calcControls,parmDict):
1309    'spherical harmonics preferred orientation derivatives (cylindrical symmetry only)'
1310    if 'T' in calcControls[hfx+'histType']:
1311        tth = parmDict[hfx+'2-theta']
1312    else:
1313        tth = refl[5+im]
1314    odfCor = 1.0
1315    dFdODF = {}
1316    H = refl[:3]
1317    cell = G2lat.Gmat2cell(g)
1318    Sangls = [0.,0.,0.]
1319    if 'Bragg' in calcControls[hfx+'instType']:
1320        Gangls = [0.,90.,0.,parmDict[hfx+'Azimuth']]
1321        IFCoup = True
1322    else:
1323        Gangls = [parmDict[hfx+'Phi'],parmDict[hfx+'Chi'],parmDict[hfx+'Omega'],parmDict[hfx+'Azimuth']]
1324        IFCoup = False
1325    phi,beta = G2lat.CrsAng(H,cell,SGData)
1326    psi,gam,x,x = G2lat.SamAng(tth/2.,Gangls,Sangls,IFCoup) #ignore 2 sets of angle derivs.
1327    SHnames = calcControls[phfx+'SHnames']
1328    for item in SHnames:
1329        L,N = eval(item.strip('C'))
1330        Kcl = G2lat.GetKcl(L,N,SGData['SGLaue'],phi,beta)
1331        Ksl,x,x = G2lat.GetKsl(L,0,'0',psi,gam)
1332        Lnorm = G2lat.Lnorm(L)
1333        odfCor += parmDict[phfx+item]*Lnorm*Kcl*Ksl
1334        dFdODF[phfx+item] = Kcl*Ksl*Lnorm
1335    return odfCor,dFdODF
1336   
1337def GetPrefOri(uniq,G,g,phfx,hfx,SGData,calcControls,parmDict):
1338    'March-Dollase preferred orientation correction'
1339    POcorr = 1.0
1340    MD = parmDict[phfx+'MD']
1341    if MD != 1.0:
1342        MDAxis = calcControls[phfx+'MDAxis']
1343        sumMD = 0
1344        for H in uniq:           
1345            cosP,sinP = G2lat.CosSinAngle(H,MDAxis,G)
1346            A = 1.0/np.sqrt((MD*cosP)**2+sinP**2/MD)
1347            sumMD += A**3
1348        POcorr = sumMD/len(uniq)
1349    return POcorr
1350   
1351def GetPrefOriDerv(refl,im,uniq,G,g,phfx,hfx,SGData,calcControls,parmDict):
1352    'Needs a doc string'
1353    POcorr = 1.0
1354    POderv = {}
1355    if calcControls[phfx+'poType'] == 'MD':
1356        MD = parmDict[phfx+'MD']
1357        MDAxis = calcControls[phfx+'MDAxis']
1358        sumMD = 0
1359        sumdMD = 0
1360        for H in uniq:           
1361            cosP,sinP = G2lat.CosSinAngle(H,MDAxis,G)
1362            A = 1.0/np.sqrt((MD*cosP)**2+sinP**2/MD)
1363            sumMD += A**3
1364            sumdMD -= (1.5*A**5)*(2.0*MD*cosP**2-(sinP/MD)**2)
1365        POcorr = sumMD/len(uniq)
1366        POderv[phfx+'MD'] = sumdMD/len(uniq)
1367    else:   #spherical harmonics
1368        if calcControls[phfx+'SHord']:
1369            POcorr,POderv = SHPOcalDerv(refl,im,g,phfx,hfx,SGData,calcControls,parmDict)
1370    return POcorr,POderv
1371   
1372def GetAbsorb(refl,im,hfx,calcControls,parmDict):
1373    'Needs a doc string'
1374    if 'Debye' in calcControls[hfx+'instType']:
1375        if 'T' in calcControls[hfx+'histType']:
1376            return G2pwd.Absorb('Cylinder',parmDict[hfx+'Absorption']*refl[14+im],abs(parmDict[hfx+'2-theta']),0,0)
1377        else:
1378            return G2pwd.Absorb('Cylinder',parmDict[hfx+'Absorption'],refl[5+im],0,0)
1379    else:
1380        return G2pwd.SurfaceRough(parmDict[hfx+'SurfRoughA'],parmDict[hfx+'SurfRoughB'],refl[5+im])
1381   
1382def GetAbsorbDerv(refl,im,hfx,calcControls,parmDict):
1383    'Needs a doc string'
1384    if 'Debye' in calcControls[hfx+'instType']:
1385        if 'T' in calcControls[hfx+'histType']:
1386            return G2pwd.AbsorbDerv('Cylinder',parmDict[hfx+'Absorption']*refl[14+im],abs(parmDict[hfx+'2-theta']),0,0)
1387        else:
1388            return G2pwd.AbsorbDerv('Cylinder',parmDict[hfx+'Absorption'],refl[5+im],0,0)
1389    else:
1390        return np.array(G2pwd.SurfaceRoughDerv(parmDict[hfx+'SurfRoughA'],parmDict[hfx+'SurfRoughB'],refl[5+im]))
1391       
1392def GetPwdrExt(refl,im,pfx,phfx,hfx,calcControls,parmDict):
1393    'Needs a doc string'
1394    coef = np.array([-0.5,0.25,-0.10416667,0.036458333,-0.0109375,2.8497409E-3])
1395    pi2 = np.sqrt(2./np.pi)
1396    if 'T' in calcControls[hfx+'histType']:
1397        sth2 = sind(abs(parmDict[hfx+'2-theta'])/2.)**2
1398        wave = refl[14+im]
1399    else:   #'C'W
1400        sth2 = sind(refl[5+im]/2.)**2
1401        wave = parmDict.get(hfx+'Lam',parmDict.get(hfx+'Lam1',1.0))
1402    c2th = 1.-2.0*sth2
1403    flv2 = refl[9+im]*(wave/parmDict[pfx+'Vol'])**2
1404    if 'X' in calcControls[hfx+'histType']:
1405        flv2 *= 0.079411*(1.0+c2th**2)/2.0
1406    xfac = flv2*parmDict[phfx+'Extinction']
1407    exb = 1.0
1408    if xfac > -1.:
1409        exb = 1./np.sqrt(1.+xfac)
1410    exl = 1.0
1411    if 0 < xfac <= 1.:
1412        xn = np.array([xfac**(i+1) for i in range(6)])
1413        exl += np.sum(xn*coef)
1414    elif xfac > 1.:
1415        xfac2 = 1./np.sqrt(xfac)
1416        exl = pi2*(1.-0.125/xfac)*xfac2
1417    return exb*sth2+exl*(1.-sth2)
1418   
1419def GetPwdrExtDerv(refl,im,pfx,phfx,hfx,calcControls,parmDict):
1420    'Needs a doc string'
1421    coef = np.array([-0.5,0.25,-0.10416667,0.036458333,-0.0109375,2.8497409E-3])
1422    pi2 = np.sqrt(2./np.pi)
1423    if 'T' in calcControls[hfx+'histType']:
1424        sth2 = sind(abs(parmDict[hfx+'2-theta'])/2.)**2
1425        wave = refl[14+im]
1426    else:   #'C'W
1427        sth2 = sind(refl[5+im]/2.)**2
1428        wave = parmDict.get(hfx+'Lam',parmDict.get(hfx+'Lam1',1.0))
1429    c2th = 1.-2.0*sth2
1430    flv2 = refl[9+im]*(wave/parmDict[pfx+'Vol'])**2
1431    if 'X' in calcControls[hfx+'histType']:
1432        flv2 *= 0.079411*(1.0+c2th**2)/2.0
1433    xfac = flv2*parmDict[phfx+'Extinction']
1434    dbde = -500.*flv2
1435    if xfac > -1.:
1436        dbde = -0.5*flv2/np.sqrt(1.+xfac)**3
1437    dlde = 0.
1438    if 0 < xfac <= 1.:
1439        xn = np.array([i*flv2*xfac**i for i in [1,2,3,4,5,6]])
1440        dlde = np.sum(xn*coef)
1441    elif xfac > 1.:
1442        xfac2 = 1./np.sqrt(xfac)
1443        dlde = flv2*pi2*xfac2*(-1./xfac+0.375/xfac**2)
1444       
1445    return dbde*sth2+dlde*(1.-sth2)
1446   
1447def GetIntensityCorr(refl,im,uniq,G,g,pfx,phfx,hfx,SGData,calcControls,parmDict):
1448    'Needs a doc string'    #need powder extinction!
1449    Icorr = parmDict[phfx+'Scale']*parmDict[hfx+'Scale']*refl[3+im]               #scale*multiplicity
1450    if 'X' in parmDict[hfx+'Type']:
1451        Icorr *= G2pwd.Polarization(parmDict[hfx+'Polariz.'],refl[5+im],parmDict[hfx+'Azimuth'])[0]
1452    POcorr = 1.0
1453    if pfx+'SHorder' in parmDict:                 #generalized spherical harmonics texture - takes precidence
1454        POcorr = SHTXcal(refl,im,g,pfx,hfx,SGData,calcControls,parmDict)
1455    elif calcControls[phfx+'poType'] == 'MD':         #March-Dollase
1456        POcorr = GetPrefOri(uniq,G,g,phfx,hfx,SGData,calcControls,parmDict)
1457    elif calcControls[phfx+'SHord']:                #cylindrical spherical harmonics
1458        POcorr = SHPOcal(refl,im,g,phfx,hfx,SGData,calcControls,parmDict)
1459    Icorr *= POcorr
1460    AbsCorr = 1.0
1461    AbsCorr = GetAbsorb(refl,im,hfx,calcControls,parmDict)
1462    Icorr *= AbsCorr
1463    ExtCorr = GetPwdrExt(refl,im,pfx,phfx,hfx,calcControls,parmDict)
1464    Icorr *= ExtCorr
1465    return Icorr,POcorr,AbsCorr,ExtCorr
1466   
1467def GetIntensityDerv(refl,im,wave,uniq,G,g,pfx,phfx,hfx,SGData,calcControls,parmDict):
1468    'Needs a doc string'    #need powder extinction derivs!
1469    dIdsh = 1./parmDict[hfx+'Scale']
1470    dIdsp = 1./parmDict[phfx+'Scale']
1471    if 'X' in parmDict[hfx+'Type']:
1472        pola,dIdPola = G2pwd.Polarization(parmDict[hfx+'Polariz.'],refl[5+im],parmDict[hfx+'Azimuth'])
1473        dIdPola /= pola
1474    else:       #'N'
1475        dIdPola = 0.0
1476    dFdODF = {}
1477    dFdSA = [0,0,0]
1478    dIdPO = {}
1479    if pfx+'SHorder' in parmDict:
1480        odfCor,dFdODF,dFdSA = SHTXcalDerv(refl,im,g,pfx,hfx,SGData,calcControls,parmDict)
1481        for iSH in dFdODF:
1482            dFdODF[iSH] /= odfCor
1483        for i in range(3):
1484            dFdSA[i] /= odfCor
1485    elif calcControls[phfx+'poType'] == 'MD' or calcControls[phfx+'SHord']:
1486        POcorr,dIdPO = GetPrefOriDerv(refl,im,uniq,G,g,phfx,hfx,SGData,calcControls,parmDict)       
1487        for iPO in dIdPO:
1488            dIdPO[iPO] /= POcorr
1489    if 'T' in parmDict[hfx+'Type']:
1490        dFdAb = GetAbsorbDerv(refl,im,hfx,calcControls,parmDict)*wave/refl[16+im] #wave/abs corr
1491        dFdEx = GetPwdrExtDerv(refl,im,pfx,phfx,hfx,calcControls,parmDict)/refl[17+im]    #/ext corr
1492    else:
1493        dFdAb = GetAbsorbDerv(refl,im,hfx,calcControls,parmDict)*wave/refl[13+im] #wave/abs corr
1494        dFdEx = GetPwdrExtDerv(refl,im,pfx,phfx,hfx,calcControls,parmDict)/refl[14+im]    #/ext corr       
1495    return dIdsh,dIdsp,dIdPola,dIdPO,dFdODF,dFdSA,dFdAb,dFdEx
1496       
1497def GetSampleSigGam(refl,im,wave,G,GB,SGData,hfx,phfx,calcControls,parmDict):
1498    'Needs a doc string'
1499    if 'C' in calcControls[hfx+'histType']:     #All checked & OK
1500        costh = cosd(refl[5+im]/2.)
1501        #crystallite size
1502        if calcControls[phfx+'SizeType'] == 'isotropic':
1503            Sgam = 1.8*wave/(np.pi*parmDict[phfx+'Size;i']*costh)
1504        elif calcControls[phfx+'SizeType'] == 'uniaxial':
1505            H = np.array(refl[:3])
1506            P = np.array(calcControls[phfx+'SizeAxis'])
1507            cosP,sinP = G2lat.CosSinAngle(H,P,G)
1508            Sgam = (1.8*wave/np.pi)/(parmDict[phfx+'Size;i']*parmDict[phfx+'Size;a']*costh)
1509            Sgam *= np.sqrt((sinP*parmDict[phfx+'Size;a'])**2+(cosP*parmDict[phfx+'Size;i'])**2)
1510        else:           #ellipsoidal crystallites
1511            Sij =[parmDict[phfx+'Size:%d'%(i)] for i in range(6)]
1512            H = np.array(refl[:3])
1513            lenR = G2pwd.ellipseSize(H,Sij,GB)
1514            Sgam = 1.8*wave/(np.pi*costh*lenR)
1515        #microstrain               
1516        if calcControls[phfx+'MustrainType'] == 'isotropic':
1517            Mgam = 0.018*parmDict[phfx+'Mustrain;i']*tand(refl[5+im]/2.)/np.pi
1518        elif calcControls[phfx+'MustrainType'] == 'uniaxial':
1519            H = np.array(refl[:3])
1520            P = np.array(calcControls[phfx+'MustrainAxis'])
1521            cosP,sinP = G2lat.CosSinAngle(H,P,G)
1522            Si = parmDict[phfx+'Mustrain;i']
1523            Sa = parmDict[phfx+'Mustrain;a']
1524            Mgam = 0.018*Si*Sa*tand(refl[5+im]/2.)/(np.pi*np.sqrt((Si*cosP)**2+(Sa*sinP)**2))
1525        else:       #generalized - P.W. Stephens model
1526            Strms = G2spc.MustrainCoeff(refl[:3],SGData)
1527            Sum = 0
1528            for i,strm in enumerate(Strms):
1529                Sum += parmDict[phfx+'Mustrain:'+str(i)]*strm
1530            Mgam = 0.018*refl[4+im]**2*tand(refl[5+im]/2.)*np.sqrt(Sum)/np.pi
1531    elif 'T' in calcControls[hfx+'histType']:       #All checked & OK
1532        #crystallite size
1533        if calcControls[phfx+'SizeType'] == 'isotropic':    #OK
1534            Sgam = 1.e-4*parmDict[hfx+'difC']*refl[4+im]**2/parmDict[phfx+'Size;i']
1535        elif calcControls[phfx+'SizeType'] == 'uniaxial':   #OK
1536            H = np.array(refl[:3])
1537            P = np.array(calcControls[phfx+'SizeAxis'])
1538            cosP,sinP = G2lat.CosSinAngle(H,P,G)
1539            Sgam = 1.e-4*parmDict[hfx+'difC']*refl[4+im]**2/(parmDict[phfx+'Size;i']*parmDict[phfx+'Size;a'])
1540            Sgam *= np.sqrt((sinP*parmDict[phfx+'Size;a'])**2+(cosP*parmDict[phfx+'Size;i'])**2)
1541        else:           #ellipsoidal crystallites   #OK
1542            Sij =[parmDict[phfx+'Size:%d'%(i)] for i in range(6)]
1543            H = np.array(refl[:3])
1544            lenR = G2pwd.ellipseSize(H,Sij,GB)
1545            Sgam = 1.e-4*parmDict[hfx+'difC']*refl[4+im]**2/lenR
1546        #microstrain               
1547        if calcControls[phfx+'MustrainType'] == 'isotropic':    #OK
1548            Mgam = 1.e-6*parmDict[hfx+'difC']*refl[4+im]*parmDict[phfx+'Mustrain;i']
1549        elif calcControls[phfx+'MustrainType'] == 'uniaxial':   #OK
1550            H = np.array(refl[:3])
1551            P = np.array(calcControls[phfx+'MustrainAxis'])
1552            cosP,sinP = G2lat.CosSinAngle(H,P,G)
1553            Si = parmDict[phfx+'Mustrain;i']
1554            Sa = parmDict[phfx+'Mustrain;a']
1555            Mgam = 1.e-6*parmDict[hfx+'difC']*refl[4+im]*Si*Sa/np.sqrt((Si*cosP)**2+(Sa*sinP)**2)
1556        else:       #generalized - P.W. Stephens model  OK
1557            Strms = G2spc.MustrainCoeff(refl[:3],SGData)
1558            Sum = 0
1559            for i,strm in enumerate(Strms):
1560                Sum += parmDict[phfx+'Mustrain:'+str(i)]*strm
1561            Mgam = 1.e-6*parmDict[hfx+'difC']*np.sqrt(Sum)*refl[4+im]**3
1562           
1563    gam = Sgam*parmDict[phfx+'Size;mx']+Mgam*parmDict[phfx+'Mustrain;mx']
1564    sig = (Sgam*(1.-parmDict[phfx+'Size;mx']))**2+(Mgam*(1.-parmDict[phfx+'Mustrain;mx']))**2
1565    sig /= ateln2
1566    return sig,gam
1567       
1568def GetSampleSigGamDerv(refl,im,wave,G,GB,SGData,hfx,phfx,calcControls,parmDict):
1569    'Needs a doc string'
1570    gamDict = {}
1571    sigDict = {}
1572    if 'C' in calcControls[hfx+'histType']:         #All checked & OK
1573        costh = cosd(refl[5+im]/2.)
1574        tanth = tand(refl[5+im]/2.)
1575        #crystallite size derivatives
1576        if calcControls[phfx+'SizeType'] == 'isotropic':
1577            Sgam = 1.8*wave/(np.pi*parmDict[phfx+'Size;i']*costh)
1578            gamDict[phfx+'Size;i'] = -1.8*wave*parmDict[phfx+'Size;mx']/(np.pi*costh)
1579            sigDict[phfx+'Size;i'] = -3.6*Sgam*wave*(1.-parmDict[phfx+'Size;mx'])**2/(np.pi*costh*ateln2)
1580        elif calcControls[phfx+'SizeType'] == 'uniaxial':
1581            H = np.array(refl[:3])
1582            P = np.array(calcControls[phfx+'SizeAxis'])
1583            cosP,sinP = G2lat.CosSinAngle(H,P,G)
1584            Si = parmDict[phfx+'Size;i']
1585            Sa = parmDict[phfx+'Size;a']
1586            gami = 1.8*wave/(costh*np.pi*Si*Sa)
1587            sqtrm = np.sqrt((sinP*Sa)**2+(cosP*Si)**2)
1588            Sgam = gami*sqtrm
1589            dsi = gami*Si*cosP**2/sqtrm-Sgam/Si
1590            dsa = gami*Sa*sinP**2/sqtrm-Sgam/Sa
1591            gamDict[phfx+'Size;i'] = dsi*parmDict[phfx+'Size;mx']
1592            gamDict[phfx+'Size;a'] = dsa*parmDict[phfx+'Size;mx']
1593            sigDict[phfx+'Size;i'] = 2.*dsi*Sgam*(1.-parmDict[phfx+'Size;mx'])**2/ateln2
1594            sigDict[phfx+'Size;a'] = 2.*dsa*Sgam*(1.-parmDict[phfx+'Size;mx'])**2/ateln2
1595        else:           #ellipsoidal crystallites
1596            const = 1.8*wave/(np.pi*costh)
1597            Sij =[parmDict[phfx+'Size:%d'%(i)] for i in range(6)]
1598            H = np.array(refl[:3])
1599            lenR,dRdS = G2pwd.ellipseSizeDerv(H,Sij,GB)
1600            Sgam = const/lenR
1601            for i,item in enumerate([phfx+'Size:%d'%(j) for j in range(6)]):
1602                gamDict[item] = -(const/lenR**2)*dRdS[i]*parmDict[phfx+'Size;mx']
1603                sigDict[item] = -2.*Sgam*(const/lenR**2)*dRdS[i]*(1.-parmDict[phfx+'Size;mx'])**2/ateln2
1604        gamDict[phfx+'Size;mx'] = Sgam
1605        sigDict[phfx+'Size;mx'] = -2.*Sgam**2*(1.-parmDict[phfx+'Size;mx'])/ateln2
1606               
1607        #microstrain derivatives               
1608        if calcControls[phfx+'MustrainType'] == 'isotropic':
1609            Mgam = 0.018*parmDict[phfx+'Mustrain;i']*tand(refl[5+im]/2.)/np.pi
1610            gamDict[phfx+'Mustrain;i'] =  0.018*tanth*parmDict[phfx+'Mustrain;mx']/np.pi
1611            sigDict[phfx+'Mustrain;i'] =  0.036*Mgam*tanth*(1.-parmDict[phfx+'Mustrain;mx'])**2/(np.pi*ateln2)       
1612        elif calcControls[phfx+'MustrainType'] == 'uniaxial':
1613            H = np.array(refl[:3])
1614            P = np.array(calcControls[phfx+'MustrainAxis'])
1615            cosP,sinP = G2lat.CosSinAngle(H,P,G)
1616            Si = parmDict[phfx+'Mustrain;i']
1617            Sa = parmDict[phfx+'Mustrain;a']
1618            gami = 0.018*Si*Sa*tanth/np.pi
1619            sqtrm = np.sqrt((Si*cosP)**2+(Sa*sinP)**2)
1620            Mgam = gami/sqtrm
1621            dsi = -gami*Si*cosP**2/sqtrm**3
1622            dsa = -gami*Sa*sinP**2/sqtrm**3
1623            gamDict[phfx+'Mustrain;i'] = (Mgam/Si+dsi)*parmDict[phfx+'Mustrain;mx']
1624            gamDict[phfx+'Mustrain;a'] = (Mgam/Sa+dsa)*parmDict[phfx+'Mustrain;mx']
1625            sigDict[phfx+'Mustrain;i'] = 2*(Mgam/Si+dsi)*Mgam*(1.-parmDict[phfx+'Mustrain;mx'])**2/ateln2
1626            sigDict[phfx+'Mustrain;a'] = 2*(Mgam/Sa+dsa)*Mgam*(1.-parmDict[phfx+'Mustrain;mx'])**2/ateln2       
1627        else:       #generalized - P.W. Stephens model
1628            const = 0.018*refl[4+im]**2*tanth/np.pi
1629            Strms = G2spc.MustrainCoeff(refl[:3],SGData)
1630            Sum = 0
1631            for i,strm in enumerate(Strms):
1632                Sum += parmDict[phfx+'Mustrain:'+str(i)]*strm
1633                gamDict[phfx+'Mustrain:'+str(i)] = strm*parmDict[phfx+'Mustrain;mx']/2.
1634                sigDict[phfx+'Mustrain:'+str(i)] = strm*(1.-parmDict[phfx+'Mustrain;mx'])**2
1635            Mgam = const*np.sqrt(Sum)
1636            for i in range(len(Strms)):
1637                gamDict[phfx+'Mustrain:'+str(i)] *= Mgam/Sum
1638                sigDict[phfx+'Mustrain:'+str(i)] *= const**2/ateln2
1639        gamDict[phfx+'Mustrain;mx'] = Mgam
1640        sigDict[phfx+'Mustrain;mx'] = -2.*Mgam**2*(1.-parmDict[phfx+'Mustrain;mx'])/ateln2
1641    else:   #'T'OF - All checked & OK
1642        if calcControls[phfx+'SizeType'] == 'isotropic':    #OK
1643            Sgam = 1.e-4*parmDict[hfx+'difC']*refl[4+im]**2/parmDict[phfx+'Size;i']
1644            gamDict[phfx+'Size;i'] = -Sgam*parmDict[phfx+'Size;mx']/parmDict[phfx+'Size;i']
1645            sigDict[phfx+'Size;i'] = -2.*Sgam**2*(1.-parmDict[phfx+'Size;mx'])**2/(ateln2*parmDict[phfx+'Size;i'])
1646        elif calcControls[phfx+'SizeType'] == 'uniaxial':   #OK
1647            const = 1.e-4*parmDict[hfx+'difC']*refl[4+im]**2
1648            H = np.array(refl[:3])
1649            P = np.array(calcControls[phfx+'SizeAxis'])
1650            cosP,sinP = G2lat.CosSinAngle(H,P,G)
1651            Si = parmDict[phfx+'Size;i']
1652            Sa = parmDict[phfx+'Size;a']
1653            gami = const/(Si*Sa)
1654            sqtrm = np.sqrt((sinP*Sa)**2+(cosP*Si)**2)
1655            Sgam = gami*sqtrm
1656            dsi = gami*Si*cosP**2/sqtrm-Sgam/Si
1657            dsa = gami*Sa*sinP**2/sqtrm-Sgam/Sa
1658            gamDict[phfx+'Size;i'] = dsi*parmDict[phfx+'Size;mx']
1659            gamDict[phfx+'Size;a'] = dsa*parmDict[phfx+'Size;mx']
1660            sigDict[phfx+'Size;i'] = 2.*dsi*Sgam*(1.-parmDict[phfx+'Size;mx'])**2/ateln2
1661            sigDict[phfx+'Size;a'] = 2.*dsa*Sgam*(1.-parmDict[phfx+'Size;mx'])**2/ateln2
1662        else:           #OK  ellipsoidal crystallites
1663            const = 1.e-4*parmDict[hfx+'difC']*refl[4+im]**2
1664            Sij =[parmDict[phfx+'Size:%d'%(i)] for i in range(6)]
1665            H = np.array(refl[:3])
1666            lenR,dRdS = G2pwd.ellipseSizeDerv(H,Sij,GB)
1667            Sgam = const/lenR
1668            for i,item in enumerate([phfx+'Size:%d'%(j) for j in range(6)]):
1669                gamDict[item] = -(const/lenR**2)*dRdS[i]*parmDict[phfx+'Size;mx']
1670                sigDict[item] = -2.*Sgam*(const/lenR**2)*dRdS[i]*(1.-parmDict[phfx+'Size;mx'])**2/ateln2
1671        gamDict[phfx+'Size;mx'] = Sgam  #OK
1672        sigDict[phfx+'Size;mx'] = -2.*Sgam**2*(1.-parmDict[phfx+'Size;mx'])/ateln2  #OK
1673               
1674        #microstrain derivatives               
1675        if calcControls[phfx+'MustrainType'] == 'isotropic':
1676            Mgam = 1.e-6*parmDict[hfx+'difC']*refl[4+im]*parmDict[phfx+'Mustrain;i']
1677            gamDict[phfx+'Mustrain;i'] =  1.e-6*refl[4+im]*parmDict[hfx+'difC']*parmDict[phfx+'Mustrain;mx']   #OK
1678            sigDict[phfx+'Mustrain;i'] =  2.*Mgam**2*(1.-parmDict[phfx+'Mustrain;mx'])**2/(ateln2*parmDict[phfx+'Mustrain;i'])       
1679        elif calcControls[phfx+'MustrainType'] == 'uniaxial':
1680            H = np.array(refl[:3])
1681            P = np.array(calcControls[phfx+'MustrainAxis'])
1682            cosP,sinP = G2lat.CosSinAngle(H,P,G)
1683            Si = parmDict[phfx+'Mustrain;i']
1684            Sa = parmDict[phfx+'Mustrain;a']
1685            gami = 1.e-6*parmDict[hfx+'difC']*refl[4+im]*Si*Sa
1686            sqtrm = np.sqrt((Si*cosP)**2+(Sa*sinP)**2)
1687            Mgam = gami/sqtrm
1688            dsi = -gami*Si*cosP**2/sqtrm**3
1689            dsa = -gami*Sa*sinP**2/sqtrm**3
1690            gamDict[phfx+'Mustrain;i'] = (Mgam/Si+dsi)*parmDict[phfx+'Mustrain;mx']
1691            gamDict[phfx+'Mustrain;a'] = (Mgam/Sa+dsa)*parmDict[phfx+'Mustrain;mx']
1692            sigDict[phfx+'Mustrain;i'] = 2*(Mgam/Si+dsi)*Mgam*(1.-parmDict[phfx+'Mustrain;mx'])**2/ateln2
1693            sigDict[phfx+'Mustrain;a'] = 2*(Mgam/Sa+dsa)*Mgam*(1.-parmDict[phfx+'Mustrain;mx'])**2/ateln2       
1694        else:       #generalized - P.W. Stephens model OK
1695            pwrs = calcControls[phfx+'MuPwrs']
1696            Strms = G2spc.MustrainCoeff(refl[:3],SGData)
1697            const = 1.e-6*parmDict[hfx+'difC']*refl[4+im]**3
1698            Sum = 0
1699            for i,strm in enumerate(Strms):
1700                Sum += parmDict[phfx+'Mustrain:'+str(i)]*strm
1701                gamDict[phfx+'Mustrain:'+str(i)] = strm*parmDict[phfx+'Mustrain;mx']/2.
1702                sigDict[phfx+'Mustrain:'+str(i)] = strm*(1.-parmDict[phfx+'Mustrain;mx'])**2
1703            Mgam = const*np.sqrt(Sum)
1704            for i in range(len(Strms)):
1705                gamDict[phfx+'Mustrain:'+str(i)] *= Mgam/Sum
1706                sigDict[phfx+'Mustrain:'+str(i)] *= const**2/ateln2       
1707        gamDict[phfx+'Mustrain;mx'] = Mgam
1708        sigDict[phfx+'Mustrain;mx'] = -2.*Mgam**2*(1.-parmDict[phfx+'Mustrain;mx'])/ateln2
1709       
1710    return sigDict,gamDict
1711       
1712def GetReflPos(refl,im,wave,A,pfx,hfx,calcControls,parmDict):
1713    'Needs a doc string'
1714    if im:
1715        h,k,l,m = refl[:4]
1716        vec = np.array([parmDict[pfx+'mV0'],parmDict[pfx+'mV1'],parmDict[pfx+'mV2']])
1717        d = 1./np.sqrt(G2lat.calc_rDsqSS(np.array([h,k,l,m]),A,vec))
1718    else:
1719        h,k,l = refl[:3]
1720        d = 1./np.sqrt(G2lat.calc_rDsq(np.array([h,k,l]),A))
1721    refl[4+im] = d
1722    if 'C' in calcControls[hfx+'histType']:
1723        pos = 2.0*asind(wave/(2.0*d))+parmDict[hfx+'Zero']
1724        const = 9.e-2/(np.pi*parmDict[hfx+'Gonio. radius'])                  #shifts in microns
1725        if 'Bragg' in calcControls[hfx+'instType']:
1726            pos -= const*(4.*parmDict[hfx+'Shift']*cosd(pos/2.0)+ \
1727                parmDict[hfx+'Transparency']*sind(pos)*100.0)            #trans(=1/mueff) in cm
1728        else:               #Debye-Scherrer - simple but maybe not right
1729            pos -= const*(parmDict[hfx+'DisplaceX']*cosd(pos)+parmDict[hfx+'DisplaceY']*sind(pos))
1730    elif 'T' in calcControls[hfx+'histType']:
1731        pos = parmDict[hfx+'difC']*d+parmDict[hfx+'difA']*d**2+parmDict[hfx+'difB']/d+parmDict[hfx+'Zero']
1732        #do I need sample position effects - maybe?
1733    return pos
1734
1735def GetReflPosDerv(refl,im,wave,A,pfx,hfx,calcControls,parmDict):
1736    'Needs a doc string'
1737    dpr = 180./np.pi
1738    if im:
1739        h,k,l,m = refl[:4]
1740        vec = np.array([parmDict[pfx+'mV0'],parmDict[pfx+'mV1'],parmDict[pfx+'mV2']])
1741        dstsq = G2lat.calc_rDsqSS(np.array([h,k,l,m]),A,vec)
1742    else:
1743        m = 0
1744        h,k,l = refl[:3]       
1745        dstsq = G2lat.calc_rDsq(np.array([h,k,l]),A)
1746    dst = np.sqrt(dstsq)
1747    dsp = 1./dst
1748    if 'C' in calcControls[hfx+'histType']:
1749        pos = refl[5+im]-parmDict[hfx+'Zero']
1750        const = dpr/np.sqrt(1.0-wave**2*dstsq/4.0)
1751        dpdw = const*dst
1752        dpdA = np.array([h**2,k**2,l**2,h*k,h*l,k*l])*const*wave/(2.0*dst)
1753        dpdZ = 1.0
1754        dpdV = np.array([2.*h*A[0]+k*A[3]+l*A[4],2*k*A[1]+h*A[3]+l*A[5],
1755            2*l*A[2]+h*A[4]+k*A[5]])*m*const*wave/(2.0*dst)
1756        shft = 9.e-2/(np.pi*parmDict[hfx+'Gonio. radius'])                  #shifts in microns
1757        if 'Bragg' in calcControls[hfx+'instType']:
1758            dpdSh = -4.*shft*cosd(pos/2.0)
1759            dpdTr = -shft*sind(pos)*100.0
1760            return dpdA,dpdw,dpdZ,dpdSh,dpdTr,0.,0.,dpdV
1761        else:               #Debye-Scherrer - simple but maybe not right
1762            dpdXd = -shft*cosd(pos)
1763            dpdYd = -shft*sind(pos)
1764            return dpdA,dpdw,dpdZ,0.,0.,dpdXd,dpdYd,dpdV
1765    elif 'T' in calcControls[hfx+'histType']:
1766        dpdA = -np.array([h**2,k**2,l**2,h*k,h*l,k*l])*parmDict[hfx+'difC']*dsp**3/2.
1767        dpdZ = 1.0
1768        dpdDC = dsp
1769        dpdDA = dsp**2
1770        dpdDB = 1./dsp
1771        dpdV = np.array([2.*h*A[0]+k*A[3]+l*A[4],2*k*A[1]+h*A[3]+l*A[5],
1772            2*l*A[2]+h*A[4]+k*A[5]])*m**parmDict[hfx+'difC']*dsp**3/2.
1773        return dpdA,dpdZ,dpdDC,dpdDA,dpdDB,dpdV
1774           
1775def GetHStrainShift(refl,im,SGData,phfx,hfx,calcControls,parmDict):
1776    'Needs a doc string'
1777    laue = SGData['SGLaue']
1778    uniq = SGData['SGUniq']
1779    h,k,l = refl[:3]
1780    if laue in ['m3','m3m']:
1781        Dij = parmDict[phfx+'D11']*(h**2+k**2+l**2)+ \
1782            refl[4+im]**2*parmDict[phfx+'eA']*((h*k)**2+(h*l)**2+(k*l)**2)/(h**2+k**2+l**2)**2
1783    elif laue in ['6/m','6/mmm','3m1','31m','3']:
1784        Dij = parmDict[phfx+'D11']*(h**2+k**2+h*k)+parmDict[phfx+'D33']*l**2
1785    elif laue in ['3R','3mR']:
1786        Dij = parmDict[phfx+'D11']*(h**2+k**2+l**2)+parmDict[phfx+'D12']*(h*k+h*l+k*l)
1787    elif laue in ['4/m','4/mmm']:
1788        Dij = parmDict[phfx+'D11']*(h**2+k**2)+parmDict[phfx+'D33']*l**2
1789    elif laue in ['mmm']:
1790        Dij = parmDict[phfx+'D11']*h**2+parmDict[phfx+'D22']*k**2+parmDict[phfx+'D33']*l**2
1791    elif laue in ['2/m']:
1792        Dij = parmDict[phfx+'D11']*h**2+parmDict[phfx+'D22']*k**2+parmDict[phfx+'D33']*l**2
1793        if uniq == 'a':
1794            Dij += parmDict[phfx+'D23']*k*l
1795        elif uniq == 'b':
1796            Dij += parmDict[phfx+'D13']*h*l
1797        elif uniq == 'c':
1798            Dij += parmDict[phfx+'D12']*h*k
1799    else:
1800        Dij = parmDict[phfx+'D11']*h**2+parmDict[phfx+'D22']*k**2+parmDict[phfx+'D33']*l**2+ \
1801            parmDict[phfx+'D12']*h*k+parmDict[phfx+'D13']*h*l+parmDict[phfx+'D23']*k*l
1802    if 'C' in calcControls[hfx+'histType']:
1803        return -180.*Dij*refl[4+im]**2*tand(refl[5+im]/2.0)/np.pi
1804    else:
1805        return -Dij*parmDict[hfx+'difC']*refl[4+im]**2/2.
1806           
1807def GetHStrainShiftDerv(refl,im,SGData,phfx,hfx,calcControls,parmDict):
1808    'Needs a doc string'
1809    laue = SGData['SGLaue']
1810    uniq = SGData['SGUniq']
1811    h,k,l = refl[:3]
1812    if laue in ['m3','m3m']:
1813        dDijDict = {phfx+'D11':h**2+k**2+l**2,
1814            phfx+'eA':refl[4+im]**2*((h*k)**2+(h*l)**2+(k*l)**2)/(h**2+k**2+l**2)**2}
1815    elif laue in ['6/m','6/mmm','3m1','31m','3']:
1816        dDijDict = {phfx+'D11':h**2+k**2+h*k,phfx+'D33':l**2}
1817    elif laue in ['3R','3mR']:
1818        dDijDict = {phfx+'D11':h**2+k**2+l**2,phfx+'D12':h*k+h*l+k*l}
1819    elif laue in ['4/m','4/mmm']:
1820        dDijDict = {phfx+'D11':h**2+k**2,phfx+'D33':l**2}
1821    elif laue in ['mmm']:
1822        dDijDict = {phfx+'D11':h**2,phfx+'D22':k**2,phfx+'D33':l**2}
1823    elif laue in ['2/m']:
1824        dDijDict = {phfx+'D11':h**2,phfx+'D22':k**2,phfx+'D33':l**2}
1825        if uniq == 'a':
1826            dDijDict[phfx+'D23'] = k*l
1827        elif uniq == 'b':
1828            dDijDict[phfx+'D13'] = h*l
1829        elif uniq == 'c':
1830            dDijDict[phfx+'D12'] = h*k
1831    else:
1832        dDijDict = {phfx+'D11':h**2,phfx+'D22':k**2,phfx+'D33':l**2,
1833            phfx+'D12':h*k,phfx+'D13':h*l,phfx+'D23':k*l}
1834    if 'C' in calcControls[hfx+'histType']:
1835        for item in dDijDict:
1836            dDijDict[item] *= 180.0*refl[4+im]**2*tand(refl[5+im]/2.0)/np.pi
1837    else:
1838        for item in dDijDict:
1839            dDijDict[item] *= -parmDict[hfx+'difC']*refl[4+im]**3/2.
1840    return dDijDict
1841   
1842def GetDij(phfx,SGData,parmDict):
1843    HSvals = [parmDict[phfx+name] for name in G2spc.HStrainNames(SGData)]
1844    return G2spc.HStrainVals(HSvals,SGData)
1845               
1846def GetFobsSq(Histograms,Phases,parmDict,calcControls):
1847    'Needs a doc string'
1848    histoList = Histograms.keys()
1849    histoList.sort()
1850    for histogram in histoList:
1851        if 'PWDR' in histogram[:4]:
1852            Histogram = Histograms[histogram]
1853            hId = Histogram['hId']
1854            hfx = ':%d:'%(hId)
1855            Limits = calcControls[hfx+'Limits']
1856            if 'C' in calcControls[hfx+'histType']:
1857                shl = max(parmDict[hfx+'SH/L'],0.0005)
1858                Ka2 = False
1859                kRatio = 0.0
1860                if hfx+'Lam1' in parmDict.keys():
1861                    Ka2 = True
1862                    lamRatio = 360*(parmDict[hfx+'Lam2']-parmDict[hfx+'Lam1'])/(np.pi*parmDict[hfx+'Lam1'])
1863                    kRatio = parmDict[hfx+'I(L2)/I(L1)']
1864            x,y,w,yc,yb,yd = Histogram['Data']
1865            xB = np.searchsorted(x,Limits[0])
1866            xF = np.searchsorted(x,Limits[1])
1867            ymb = np.array(y-yb)
1868            ymb = np.where(ymb,ymb,1.0)
1869            ycmb = np.array(yc-yb)
1870            ratio = 1./np.where(ycmb,ycmb/ymb,1.e10)         
1871            refLists = Histogram['Reflection Lists']
1872            for phase in refLists:
1873                if phase not in Phases:     #skips deleted or renamed phases silently!
1874                    continue
1875                Phase = Phases[phase]
1876                im = 0
1877                if Phase['General']['Type'] in ['modulated','magnetic']:
1878                    im = 1
1879                pId = Phase['pId']
1880                phfx = '%d:%d:'%(pId,hId)
1881                refDict = refLists[phase]
1882                sumFo = 0.0
1883                sumdF = 0.0
1884                sumFosq = 0.0
1885                sumdFsq = 0.0
1886                sumInt = 0.0
1887                for refl in refDict['RefList']:
1888                    if 'C' in calcControls[hfx+'histType']:
1889                        yp = np.zeros_like(yb)
1890                        Wd,fmin,fmax = G2pwd.getWidthsCW(refl[5+im],refl[6+im],refl[7+im],shl)
1891                        iBeg = max(xB,np.searchsorted(x,refl[5+im]-fmin))
1892                        iFin = max(xB,min(np.searchsorted(x,refl[5+im]+fmax),xF))
1893                        iFin2 = iFin
1894                        if not iBeg+iFin:       #peak below low limit - skip peak
1895                            continue
1896                        elif not iBeg-iFin:     #peak above high limit - done
1897                            break
1898                        elif iBeg < iFin:
1899                            yp[iBeg:iFin] = refl[11+im]*refl[9+im]*G2pwd.getFCJVoigt3(refl[5+im],refl[6+im],refl[7+im],shl,ma.getdata(x[iBeg:iFin]))    #>90% of time spent here
1900                            sumInt += refl[11+im]*refl[9+im]
1901                            if Ka2:
1902                                pos2 = refl[5+im]+lamRatio*tand(refl[5+im]/2.0)       # + 360/pi * Dlam/lam * tan(th)
1903                                Wd,fmin,fmax = G2pwd.getWidthsCW(pos2,refl[6+im],refl[7+im],shl)
1904                                iBeg2 = max(xB,np.searchsorted(x,pos2-fmin))
1905                                iFin2 = min(np.searchsorted(x,pos2+fmax),xF)
1906                                if iFin2 > iBeg2: 
1907                                    yp[iBeg2:iFin2] += refl[11+im]*refl[9+im]*kRatio*G2pwd.getFCJVoigt3(pos2,refl[6+im],refl[7+im],shl,ma.getdata(x[iBeg2:iFin2]))        #and here
1908                                    sumInt += refl[11+im]*refl[9+im]*kRatio
1909                            refl[8+im] = np.sum(np.where(ratio[iBeg:iFin2]>0.,yp[iBeg:iFin2]*ratio[iBeg:iFin2]/(refl[11+im]*(1.+kRatio)),0.0))
1910                               
1911                    elif 'T' in calcControls[hfx+'histType']:
1912                        yp = np.zeros_like(yb)
1913                        Wd,fmin,fmax = G2pwd.getWidthsTOF(refl[5+im],refl[12+im],refl[13+im],refl[6+im],refl[7+im])
1914                        iBeg = max(xB,np.searchsorted(x,refl[5+im]-fmin))
1915                        iFin = max(xB,min(np.searchsorted(x,refl[5+im]+fmax),xF))
1916                        if iBeg < iFin:
1917                            yp[iBeg:iFin] = refl[11+im]*refl[9+im]*G2pwd.getEpsVoigt(refl[5+im],refl[12+im],refl[13+im],refl[6+im],refl[7+im],ma.getdata(x[iBeg:iFin]))  #>90% of time spent here
1918                            refl[8+im] = np.sum(np.where(ratio[iBeg:iFin]>0.,yp[iBeg:iFin]*ratio[iBeg:iFin]/refl[11+im],0.0))
1919                            sumInt += refl[11+im]*refl[9+im]
1920                    Fo = np.sqrt(np.abs(refl[8+im]))
1921                    Fc = np.sqrt(np.abs(refl[9]+im))
1922                    sumFo += Fo
1923                    sumFosq += refl[8+im]**2
1924                    sumdF += np.abs(Fo-Fc)
1925                    sumdFsq += (refl[8+im]-refl[9+im])**2
1926                if sumFo:
1927                    Histogram['Residuals'][phfx+'Rf'] = min(100.,(sumdF/sumFo)*100.)
1928                    Histogram['Residuals'][phfx+'Rf^2'] = min(100.,np.sqrt(sumdFsq/sumFosq)*100.)
1929                else:
1930                    Histogram['Residuals'][phfx+'Rf'] = 100.
1931                    Histogram['Residuals'][phfx+'Rf^2'] = 100.
1932                Histogram['Residuals'][phfx+'sumInt'] = sumInt
1933                Histogram['Residuals'][phfx+'Nref'] = len(refDict['RefList'])
1934                Histogram['Residuals']['hId'] = hId
1935        elif 'HKLF' in histogram[:4]:
1936            Histogram = Histograms[histogram]
1937            Histogram['Residuals']['hId'] = Histograms[histogram]['hId']
1938               
1939def getPowderProfile(parmDict,x,varylist,Histogram,Phases,calcControls,pawleyLookup):
1940    'Needs a doc string'
1941   
1942    def GetReflSigGamCW(refl,im,wave,G,GB,phfx,calcControls,parmDict):
1943        U = parmDict[hfx+'U']
1944        V = parmDict[hfx+'V']
1945        W = parmDict[hfx+'W']
1946        X = parmDict[hfx+'X']
1947        Y = parmDict[hfx+'Y']
1948        tanPos = tand(refl[5+im]/2.0)
1949        Ssig,Sgam = GetSampleSigGam(refl,im,wave,G,GB,SGData,hfx,phfx,calcControls,parmDict)
1950        sig = U*tanPos**2+V*tanPos+W+Ssig     #save peak sigma
1951        sig = max(0.001,sig)
1952        gam = X/cosd(refl[5+im]/2.0)+Y*tanPos+Sgam     #save peak gamma
1953        gam = max(0.001,gam)
1954        return sig,gam
1955               
1956    def GetReflSigGamTOF(refl,im,G,GB,phfx,calcControls,parmDict):
1957        sig = parmDict[hfx+'sig-0']+parmDict[hfx+'sig-1']*refl[4+im]**2+   \
1958            parmDict[hfx+'sig-2']*refl[4+im]**4+parmDict[hfx+'sig-q']/refl[4+im]**2
1959        gam = parmDict[hfx+'X']*refl[4+im]+parmDict[hfx+'Y']*refl[4+im]**2
1960        Ssig,Sgam = GetSampleSigGam(refl,im,0.0,G,GB,SGData,hfx,phfx,calcControls,parmDict)
1961        sig += Ssig
1962        gam += Sgam
1963        return sig,gam
1964       
1965    def GetReflAlpBet(refl,im,hfx,parmDict):
1966        alp = parmDict[hfx+'alpha']/refl[4+im]
1967        bet = parmDict[hfx+'beta-0']+parmDict[hfx+'beta-1']/refl[4+im]**4+parmDict[hfx+'beta-q']/refl[4+im]**2
1968        return alp,bet
1969       
1970    hId = Histogram['hId']
1971    hfx = ':%d:'%(hId)
1972    bakType = calcControls[hfx+'bakType']
1973    yb,Histogram['sumBk'] = G2pwd.getBackground(hfx,parmDict,bakType,calcControls[hfx+'histType'],x)
1974    yc = np.zeros_like(yb)
1975    cw = np.diff(x)
1976    cw = np.append(cw,cw[-1])
1977       
1978    if 'C' in calcControls[hfx+'histType']:   
1979        shl = max(parmDict[hfx+'SH/L'],0.002)
1980        Ka2 = False
1981        if hfx+'Lam1' in parmDict.keys():
1982            wave = parmDict[hfx+'Lam1']
1983            Ka2 = True
1984            lamRatio = 360*(parmDict[hfx+'Lam2']-parmDict[hfx+'Lam1'])/(np.pi*parmDict[hfx+'Lam1'])
1985            kRatio = parmDict[hfx+'I(L2)/I(L1)']
1986        else:
1987            wave = parmDict[hfx+'Lam']
1988    for phase in Histogram['Reflection Lists']:
1989        refDict = Histogram['Reflection Lists'][phase]
1990        if phase not in Phases:     #skips deleted or renamed phases silently!
1991            continue
1992        Phase = Phases[phase]
1993        pId = Phase['pId']
1994        pfx = '%d::'%(pId)
1995        phfx = '%d:%d:'%(pId,hId)
1996        hfx = ':%d:'%(hId)
1997        SGData = Phase['General']['SGData']
1998        SGMT = np.array([ops[0].T for ops in SGData['SGOps']])
1999        im = 0
2000        if Phase['General']['Type'] in ['modulated','magnetic']:
2001            SSGData = Phase['General']['SSGData']
2002            SSGMT = np.array([ops[0].T for ops in SSGData['SSGOps']])
2003            im = 1  #offset in SS reflection list
2004            #??
2005        Dij = GetDij(phfx,SGData,parmDict)
2006        A = [parmDict[pfx+'A%d'%(i)]+Dij[i] for i in range(6)]
2007        G,g = G2lat.A2Gmat(A)       #recip & real metric tensors
2008        if np.any(np.diag(G)<0.):
2009            raise G2obj.G2Exception('invalid metric tensor \n cell/Dij refinement not advised')
2010        GA,GB = G2lat.Gmat2AB(G)    #Orthogonalization matricies
2011        Vst = np.sqrt(nl.det(G))    #V*
2012        if not Phase['General'].get('doPawley'):
2013            time0 = time.time()
2014            if im:
2015                SStructureFactor(refDict,im,G,hfx,pfx,SGData,SSGData,calcControls,parmDict)
2016            else:
2017                StructureFactor2(refDict,G,hfx,pfx,SGData,calcControls,parmDict)
2018#            print 'sf calc time: %.3fs'%(time.time()-time0)
2019        time0 = time.time()
2020        badPeak = False
2021        for iref,refl in enumerate(refDict['RefList']):
2022            if 'C' in calcControls[hfx+'histType']:
2023                if im:
2024                    h,k,l,m = refl[:4]
2025                else:
2026                    h,k,l = refl[:3]
2027                Uniq = np.inner(refl[:3],SGMT)
2028                refl[5+im] = GetReflPos(refl,im,wave,A,pfx,hfx,calcControls,parmDict)         #corrected reflection position
2029                Lorenz = 1./(2.*sind(refl[5+im]/2.)**2*cosd(refl[5+im]/2.))           #Lorentz correction
2030                refl[6+im:8+im] = GetReflSigGamCW(refl,im,wave,G,GB,phfx,calcControls,parmDict)    #peak sig & gam
2031                refl[11+im:15+im] = GetIntensityCorr(refl,im,Uniq,G,g,pfx,phfx,hfx,SGData,calcControls,parmDict)
2032                refl[11+im] *= Vst*Lorenz
2033                 
2034                if Phase['General'].get('doPawley'):
2035                    try:
2036                        if im:
2037                            pInd = pfx+'PWLref:%d'%(pawleyLookup[pfx+'%d,%d,%d,%d'%(h,k,l,m)])
2038                        else:
2039                            pInd = pfx+'PWLref:%d'%(pawleyLookup[pfx+'%d,%d,%d'%(h,k,l)])
2040                        refl[9+im] = parmDict[pInd]
2041                    except KeyError:
2042#                        print ' ***Error %d,%d,%d missing from Pawley reflection list ***'%(h,k,l)
2043                        continue
2044                Wd,fmin,fmax = G2pwd.getWidthsCW(refl[5+im],refl[6+im],refl[7+im],shl)
2045                iBeg = np.searchsorted(x,refl[5+im]-fmin)
2046                iFin = np.searchsorted(x,refl[5+im]+fmax)
2047                if not iBeg+iFin:       #peak below low limit - skip peak
2048                    continue
2049                elif not iBeg-iFin:     #peak above high limit - done
2050                    break
2051                elif iBeg > iFin:   #bad peak coeff - skip
2052                    badPeak = True
2053                    continue
2054                yc[iBeg:iFin] += refl[11+im]*refl[9+im]*G2pwd.getFCJVoigt3(refl[5+im],refl[6+im],refl[7+im],shl,ma.getdata(x[iBeg:iFin]))    #>90% of time spent here
2055                if Ka2:
2056                    pos2 = refl[5+im]+lamRatio*tand(refl[5+im]/2.0)       # + 360/pi * Dlam/lam * tan(th)
2057                    Wd,fmin,fmax = G2pwd.getWidthsCW(pos2,refl[6+im],refl[7+im],shl)
2058                    iBeg = np.searchsorted(x,pos2-fmin)
2059                    iFin = np.searchsorted(x,pos2+fmax)
2060                    if not iBeg+iFin:       #peak below low limit - skip peak
2061                        continue
2062                    elif not iBeg-iFin:     #peak above high limit - done
2063                        return yc,yb
2064                    elif iBeg > iFin:   #bad peak coeff - skip
2065                        continue
2066                    yc[iBeg:iFin] += refl[11+im]*refl[9+im]*kRatio*G2pwd.getFCJVoigt3(pos2,refl[6+im],refl[7+im],shl,ma.getdata(x[iBeg:iFin]))        #and here
2067            elif 'T' in calcControls[hfx+'histType']:
2068                h,k,l = refl[:3]
2069                Uniq = np.inner(refl[:3],SGMT)
2070                refl[5+im] = GetReflPos(refl,im,0.0,A,pfx,hfx,calcControls,parmDict)         #corrected reflection position
2071                Lorenz = sind(abs(parmDict[hfx+'2-theta'])/2)*refl[4+im]**4                                                #TOF Lorentz correction
2072#                refl[5+im] += GetHStrainShift(refl,im,SGData,phfx,hfx,calcControls,parmDict)               #apply hydrostatic strain shift
2073                refl[6+im:8+im] = GetReflSigGamTOF(refl,im,G,GB,phfx,calcControls,parmDict)    #peak sig & gam
2074                refl[12+im:14+im] = GetReflAlpBet(refl,im,hfx,parmDict)
2075                refl[11+im],refl[15+im],refl[16+im],refl[17+im] = GetIntensityCorr(refl,im,Uniq,G,g,pfx,phfx,hfx,SGData,calcControls,parmDict)
2076                refl[11+im] *= Vst*Lorenz
2077                if Phase['General'].get('doPawley'):
2078                    try:
2079                        if im:
2080                            pInd =pfx+'PWLref:%d'%(pawleyLookup[pfx+'%d,%d,%d,%d'%(h,k,l,m)])
2081                        else:
2082                            pInd =pfx+'PWLref:%d'%(pawleyLookup[pfx+'%d,%d,%d'%(h,k,l)])
2083                        refl[9+im] = parmDict[pInd]
2084                    except KeyError:
2085#                        print ' ***Error %d,%d,%d missing from Pawley reflection list ***'%(h,k,l)
2086                        continue
2087                Wd,fmin,fmax = G2pwd.getWidthsTOF(refl[5+im],refl[12+im],refl[13+im],refl[6+im],refl[7+im])
2088                iBeg = np.searchsorted(x,refl[5+im]-fmin)
2089                iFin = np.searchsorted(x,refl[5+im]+fmax)
2090                if not iBeg+iFin:       #peak below low limit - skip peak
2091                    continue
2092                elif not iBeg-iFin:     #peak above high limit - done
2093                    break
2094                elif iBeg > iFin:   #bad peak coeff - skip
2095                    badPeak = True
2096                    continue
2097                yc[iBeg:iFin] += refl[11+im]*refl[9+im]*G2pwd.getEpsVoigt(refl[5+im],refl[12+im],refl[13+im],refl[6+im],refl[7+im],ma.getdata(x[iBeg:iFin]))/cw[iBeg:iFin]
2098#        print 'profile calc time: %.3fs'%(time.time()-time0)
2099    if badPeak:
2100        print 'ouch #4 bad profile coefficients yield negative peak width; some reflections skipped' 
2101    return yc,yb
2102   
2103def getPowderProfileDerv(parmDict,x,varylist,Histogram,Phases,rigidbodyDict,calcControls,pawleyLookup):
2104    'Needs a doc string'
2105   
2106    def cellVaryDerv(pfx,SGData,dpdA): 
2107        if SGData['SGLaue'] in ['-1',]:
2108            return [[pfx+'A0',dpdA[0]],[pfx+'A1',dpdA[1]],[pfx+'A2',dpdA[2]],
2109                [pfx+'A3',dpdA[3]],[pfx+'A4',dpdA[4]],[pfx+'A5',dpdA[5]]]
2110        elif SGData['SGLaue'] in ['2/m',]:
2111            if SGData['SGUniq'] == 'a':
2112                return [[pfx+'A0',dpdA[0]],[pfx+'A1',dpdA[1]],[pfx+'A2',dpdA[2]],[pfx+'A5',dpdA[5]]]
2113            elif SGData['SGUniq'] == 'b':
2114                return [[pfx+'A0',dpdA[0]],[pfx+'A1',dpdA[1]],[pfx+'A2',dpdA[2]],[pfx+'A4',dpdA[4]]]
2115            else:
2116                return [[pfx+'A0',dpdA[0]],[pfx+'A1',dpdA[1]],[pfx+'A2',dpdA[2]],[pfx+'A3',dpdA[3]]]
2117        elif SGData['SGLaue'] in ['mmm',]:
2118            return [[pfx+'A0',dpdA[0]],[pfx+'A1',dpdA[1]],[pfx+'A2',dpdA[2]]]
2119        elif SGData['SGLaue'] in ['4/m','4/mmm']:
2120            return [[pfx+'A0',dpdA[0]],[pfx+'A2',dpdA[2]]]
2121        elif SGData['SGLaue'] in ['6/m','6/mmm','3m1', '31m', '3']:
2122            return [[pfx+'A0',dpdA[0]],[pfx+'A2',dpdA[2]]]
2123        elif SGData['SGLaue'] in ['3R', '3mR']:
2124            return [[pfx+'A0',dpdA[0]+dpdA[1]+dpdA[2]],[pfx+'A3',dpdA[3]+dpdA[4]+dpdA[5]]]                       
2125        elif SGData['SGLaue'] in ['m3m','m3']:
2126            return [[pfx+'A0',dpdA[0]]]
2127           
2128    # create a list of dependent variables and set up a dictionary to hold their derivatives
2129    dependentVars = G2mv.GetDependentVars()
2130    depDerivDict = {}
2131    for j in dependentVars:
2132        depDerivDict[j] = np.zeros(shape=(len(x)))
2133    #print 'dependent vars',dependentVars
2134    lenX = len(x)               
2135    hId = Histogram['hId']
2136    hfx = ':%d:'%(hId)
2137    bakType = calcControls[hfx+'bakType']
2138    dMdv = np.zeros(shape=(len(varylist),len(x)))
2139    dMdb,dMddb,dMdpk = G2pwd.getBackgroundDerv(hfx,parmDict,bakType,calcControls[hfx+'histType'],x)
2140    if hfx+'Back;0' in varylist: # for now assume that Back;x vars to not appear in constraints
2141        bBpos =varylist.index(hfx+'Back;0')
2142        dMdv[bBpos:bBpos+len(dMdb)] = dMdb
2143    names = [hfx+'DebyeA',hfx+'DebyeR',hfx+'DebyeU']
2144    for name in varylist:
2145        if 'Debye' in name:
2146            id = int(name.split(';')[-1])
2147            parm = name[:int(name.rindex(';'))]
2148            ip = names.index(parm)
2149            dMdv[varylist.index(name)] = dMddb[3*id+ip]
2150    names = [hfx+'BkPkpos',hfx+'BkPkint',hfx+'BkPksig',hfx+'BkPkgam']
2151    for name in varylist:
2152        if 'BkPk' in name:
2153            parm,id = name.split(';')
2154            id = int(id)
2155            if parm in names:
2156                ip = names.index(parm)
2157                dMdv[varylist.index(name)] = dMdpk[4*id+ip]
2158    cw = np.diff(x)
2159    cw = np.append(cw,cw[-1])
2160    Ka2 = False #also for TOF!
2161    if 'C' in calcControls[hfx+'histType']:   
2162        shl = max(parmDict[hfx+'SH/L'],0.002)
2163        if hfx+'Lam1' in parmDict.keys():
2164            wave = parmDict[hfx+'Lam1']
2165            Ka2 = True
2166            lamRatio = 360*(parmDict[hfx+'Lam2']-parmDict[hfx+'Lam1'])/(np.pi*parmDict[hfx+'Lam1'])
2167            kRatio = parmDict[hfx+'I(L2)/I(L1)']
2168        else:
2169            wave = parmDict[hfx+'Lam']
2170    for phase in Histogram['Reflection Lists']:
2171        refDict = Histogram['Reflection Lists'][phase]
2172        if phase not in Phases:     #skips deleted or renamed phases silently!
2173            continue
2174        Phase = Phases[phase]
2175        SGData = Phase['General']['SGData']
2176        SGMT = np.array([ops[0].T for ops in SGData['SGOps']])
2177        im = 0
2178        if Phase['General']['Type'] in ['modulated','magnetic']:
2179            SSGData = Phase['General']['SSGData']
2180            SSGMT = np.array([ops[0].T for ops in SSGData['SSGOps']])
2181            im = 1  #offset in SS reflection list
2182            #??
2183        pId = Phase['pId']
2184        pfx = '%d::'%(pId)
2185        phfx = '%d:%d:'%(pId,hId)
2186        Dij = GetDij(phfx,SGData,parmDict)
2187        A = [parmDict[pfx+'A%d'%(i)]+Dij[i] for i in range(6)]
2188        G,g = G2lat.A2Gmat(A)       #recip & real metric tensors
2189        GA,GB = G2lat.Gmat2AB(G)    #Orthogonalization matricies
2190        if not Phase['General'].get('doPawley'):
2191            time0 = time.time()
2192            if im:
2193                dFdvDict = SStructureFactorDerv(refDict,im,G,hfx,pfx,SGData,SSGData,calcControls,parmDict)
2194            else:
2195                dFdvDict = StructureFactorDerv(refDict,G,hfx,pfx,SGData,calcControls,parmDict)
2196#            print 'sf-derv time %.3fs'%(time.time()-time0)
2197            ApplyRBModelDervs(dFdvDict,parmDict,rigidbodyDict,Phase)
2198        time0 = time.time()
2199        for iref,refl in enumerate(refDict['RefList']):
2200            if im:
2201                h,k,l,m = refl[:4]
2202            else:
2203                h,k,l = refl[:3]
2204            Uniq = np.inner(refl[:3],SGMT)
2205            if 'T' in calcControls[hfx+'histType']:
2206                wave = refl[14+im]
2207            dIdsh,dIdsp,dIdpola,dIdPO,dFdODF,dFdSA,dFdAb,dFdEx = GetIntensityDerv(refl,im,wave,Uniq,G,g,pfx,phfx,hfx,SGData,calcControls,parmDict)
2208            if 'C' in calcControls[hfx+'histType']:        #CW powder
2209                Wd,fmin,fmax = G2pwd.getWidthsCW(refl[5+im],refl[6+im],refl[7+im],shl)
2210            else: #'T'OF
2211                Wd,fmin,fmax = G2pwd.getWidthsTOF(refl[5+im],refl[12+im],refl[13+im],refl[6+im],refl[7+im])
2212            iBeg = np.searchsorted(x,refl[5+im]-fmin)
2213            iFin = np.searchsorted(x,refl[5+im]+fmax)
2214            if not iBeg+iFin:       #peak below low limit - skip peak
2215                continue
2216            elif not iBeg-iFin:     #peak above high limit - done
2217                break
2218            pos = refl[5+im]
2219            if 'C' in calcControls[hfx+'histType']:
2220                tanth = tand(pos/2.0)
2221                costh = cosd(pos/2.0)
2222                lenBF = iFin-iBeg
2223                dMdpk = np.zeros(shape=(6,lenBF))
2224                dMdipk = G2pwd.getdFCJVoigt3(refl[5+im],refl[6+im],refl[7+im],shl,ma.getdata(x[iBeg:iFin]))
2225                for i in range(5):
2226                    dMdpk[i] += 100.*cw[iBeg:iFin]*refl[11+im]*refl[9+im]*dMdipk[i]
2227                dervDict = {'int':dMdpk[0],'pos':dMdpk[1],'sig':dMdpk[2],'gam':dMdpk[3],'shl':dMdpk[4],'L1/L2':np.zeros_like(dMdpk[0])}
2228                if Ka2:
2229                    pos2 = refl[5+im]+lamRatio*tanth       # + 360/pi * Dlam/lam * tan(th)
2230                    iBeg2 = np.searchsorted(x,pos2-fmin)
2231                    iFin2 = np.searchsorted(x,pos2+fmax)
2232                    if iBeg2-iFin2:
2233                        lenBF2 = iFin2-iBeg2
2234                        dMdpk2 = np.zeros(shape=(6,lenBF2))
2235                        dMdipk2 = G2pwd.getdFCJVoigt3(pos2,refl[6+im],refl[7+im],shl,ma.getdata(x[iBeg2:iFin2]))
2236                        for i in range(5):
2237                            dMdpk2[i] = 100.*cw[iBeg2:iFin2]*refl[11+im]*refl[9+im]*kRatio*dMdipk2[i]
2238                        dMdpk2[5] = 100.*cw[iBeg2:iFin2]*refl[11+im]*dMdipk2[0]
2239                        dervDict2 = {'int':dMdpk2[0],'pos':dMdpk2[1],'sig':dMdpk2[2],'gam':dMdpk2[3],'shl':dMdpk2[4],'L1/L2':dMdpk2[5]*refl[9]}
2240            else:   #'T'OF
2241                lenBF = iFin-iBeg
2242                if lenBF < 0:   #bad peak coeff
2243                    break
2244                dMdpk = np.zeros(shape=(6,lenBF))
2245                dMdipk = G2pwd.getdEpsVoigt(refl[5+im],refl[12+im],refl[13+im],refl[6+im],refl[7+im],ma.getdata(x[iBeg:iFin]))
2246                for i in range(6):
2247                    dMdpk[i] += refl[11+im]*refl[9+im]*dMdipk[i]      #cw[iBeg:iFin]*
2248                dervDict = {'int':dMdpk[0],'pos':dMdpk[1],'alp':dMdpk[2],'bet':dMdpk[3],'sig':dMdpk[4],'gam':dMdpk[5]}           
2249            if Phase['General'].get('doPawley'):
2250                dMdpw = np.zeros(len(x))
2251                try:
2252                    if im:
2253                        pIdx = pfx+'PWLref:'+str(pawleyLookup[pfx+'%d,%d,%d,%d'%(h,k,l,m)])
2254                    else:
2255                        pIdx = pfx+'PWLref:'+str(pawleyLookup[pfx+'%d,%d,%d'%(h,k,l)])
2256                    idx = varylist.index(pIdx)
2257                    dMdpw[iBeg:iFin] = dervDict['int']/refl[9+im]
2258                    if Ka2: #not for TOF either
2259                        dMdpw[iBeg2:iFin2] += dervDict2['int']/refl[9+im]
2260                    dMdv[idx] = dMdpw
2261                except: # ValueError:
2262                    pass
2263            if 'C' in calcControls[hfx+'histType']:
2264                dpdA,dpdw,dpdZ,dpdSh,dpdTr,dpdX,dpdY,dpdV = GetReflPosDerv(refl,im,wave,A,pfx,hfx,calcControls,parmDict)
2265                names = {hfx+'Scale':[dIdsh,'int'],hfx+'Polariz.':[dIdpola,'int'],phfx+'Scale':[dIdsp,'int'],
2266                    hfx+'U':[tanth**2,'sig'],hfx+'V':[tanth,'sig'],hfx+'W':[1.0,'sig'],
2267                    hfx+'X':[1.0/costh,'gam'],hfx+'Y':[tanth,'gam'],hfx+'SH/L':[1.0,'shl'],
2268                    hfx+'I(L2)/I(L1)':[1.0,'L1/L2'],hfx+'Zero':[dpdZ,'pos'],hfx+'Lam':[dpdw,'pos'],
2269                    hfx+'Shift':[dpdSh,'pos'],hfx+'Transparency':[dpdTr,'pos'],hfx+'DisplaceX':[dpdX,'pos'],
2270                    hfx+'DisplaceY':[dpdY,'pos'],}
2271                if 'Bragg' in calcControls[hfx+'instType']:
2272                    names.update({hfx+'SurfRoughA':[dFdAb[0],'int'],
2273                        hfx+'SurfRoughB':[dFdAb[1],'int'],})
2274                else:
2275                    names.update({hfx+'Absorption':[dFdAb,'int'],})
2276            else:   #'T'OF
2277                dpdA,dpdZ,dpdDC,dpdDA,dpdDB,dpdV = GetReflPosDerv(refl,im,0.0,A,pfx,hfx,calcControls,parmDict)
2278                names = {hfx+'Scale':[dIdsh,'int'],phfx+'Scale':[dIdsp,'int'],
2279                    hfx+'difC':[dpdDC,'pos'],hfx+'difA':[dpdDA,'pos'],hfx+'difB':[dpdDB,'pos'],
2280                    hfx+'Zero':[dpdZ,'pos'],hfx+'X':[refl[4+im],'gam'],hfx+'Y':[refl[4+im]**2,'gam'],
2281                    hfx+'alpha':[1./refl[4+im],'alp'],hfx+'beta-0':[1.0,'bet'],hfx+'beta-1':[1./refl[4+im]**4,'bet'],
2282                    hfx+'beta-q':[1./refl[4+im]**2,'bet'],hfx+'sig-0':[1.0,'sig'],hfx+'sig-1':[refl[4+im]**2,'sig'],
2283                    hfx+'sig-2':[refl[4+im]**4,'sig'],hfx+'sig-q':[1./refl[4+im]**2,'sig'],
2284                    hfx+'Absorption':[dFdAb,'int'],phfx+'Extinction':[dFdEx,'int'],}
2285            for name in names:
2286                item = names[name]
2287                if name in varylist:
2288                    dMdv[varylist.index(name)][iBeg:iFin] += item[0]*dervDict[item[1]]
2289                    if Ka2 and iFin2-iBeg2:
2290                        dMdv[varylist.index(name)][iBeg2:iFin2] += item[0]*dervDict2[item[1]]
2291                elif name in dependentVars:
2292                    depDerivDict[name][iBeg:iFin] += item[0]*dervDict[item[1]]
2293                    if Ka2 and iFin2-iBeg2:
2294                        depDerivDict[name][iBeg2:iFin2] += item[0]*dervDict2[item[1]]
2295            for iPO in dIdPO:
2296                if iPO in varylist:
2297                    dMdv[varylist.index(iPO)][iBeg:iFin] += dIdPO[iPO]*dervDict['int']
2298                    if Ka2 and iFin2-iBeg2:
2299                        dMdv[varylist.index(iPO)][iBeg2:iFin2] += dIdPO[iPO]*dervDict2['int']
2300                elif iPO in dependentVars:
2301                    depDerivDict[iPO][iBeg:iFin] += dIdPO[iPO]*dervDict['int']
2302                    if Ka2 and iFin2-iBeg2:
2303                        depDerivDict[iPO][iBeg2:iFin2] += dIdPO[iPO]*dervDict2['int']
2304            for i,name in enumerate(['omega','chi','phi']):
2305                aname = pfx+'SH '+name
2306                if aname in varylist:
2307                    dMdv[varylist.index(aname)][iBeg:iFin] += dFdSA[i]*dervDict['int']
2308                    if Ka2 and iFin2-iBeg2:
2309                        dMdv[varylist.index(aname)][iBeg2:iFin2] += dFdSA[i]*dervDict2['int']
2310                elif aname in dependentVars:
2311                    depDerivDict[aname][iBeg:iFin] += dFdSA[i]*dervDict['int']
2312                    if Ka2 and iFin2-iBeg2:
2313                        depDerivDict[aname][iBeg2:iFin2] += dFdSA[i]*dervDict2['int']
2314            for iSH in dFdODF:
2315                if iSH in varylist:
2316                    dMdv[varylist.index(iSH)][iBeg:iFin] += dFdODF[iSH]*dervDict['int']
2317                    if Ka2 and iFin2-iBeg2:
2318                        dMdv[varylist.index(iSH)][iBeg2:iFin2] += dFdODF[iSH]*dervDict2['int']
2319                elif iSH in dependentVars:
2320                    depDerivDict[iSH][iBeg:iFin] += dFdODF[iSH]*dervDict['int']
2321                    if Ka2 and iFin2-iBeg2:
2322                        depDerivDict[iSH][iBeg2:iFin2] += dFdODF[iSH]*dervDict2['int']
2323            cellDervNames = cellVaryDerv(pfx,SGData,dpdA)
2324            for name,dpdA in cellDervNames:
2325                if name in varylist:
2326                    dMdv[varylist.index(name)][iBeg:iFin] += dpdA*dervDict['pos']
2327                    if Ka2 and iFin2-iBeg2:
2328                        dMdv[varylist.index(name)][iBeg2:iFin2] += dpdA*dervDict2['pos']
2329                elif name in dependentVars:
2330                    depDerivDict[name][iBeg:iFin] += dpdA*dervDict['pos']
2331                    if Ka2 and iFin2-iBeg2:
2332                        depDerivDict[name][iBeg2:iFin2] += dpdA*dervDict2['pos']
2333            dDijDict = GetHStrainShiftDerv(refl,im,SGData,phfx,hfx,calcControls,parmDict)
2334            for name in dDijDict:
2335                if name in varylist:
2336                    dMdv[varylist.index(name)][iBeg:iFin] += dDijDict[name]*dervDict['pos']
2337                    if Ka2 and iFin2-iBeg2:
2338                        dMdv[varylist.index(name)][iBeg2:iFin2] += dDijDict[name]*dervDict2['pos']
2339                elif name in dependentVars:
2340                    depDerivDict[name][iBeg:iFin] += dDijDict[name]*dervDict['pos']
2341                    if Ka2 and iFin2-iBeg2:
2342                        depDerivDict[name][iBeg2:iFin2] += dDijDict[name]*dervDict2['pos']
2343            for i,name in enumerate([pfx+'mV0',pfx+'mV1',pfx+'mV2']):
2344                if name in varylist:
2345                    dMdv[varylist.index(name)][iBeg:iFin] += dpdV[i]*dervDict['pos']
2346                    if Ka2 and iFin2-iBeg2:
2347                        dMdv[varylist.index(name)][iBeg2:iFin2] += dpdV[i]*dervDict2['pos']
2348                elif name in dependentVars:
2349                    depDerivDict[name][iBeg:iFin] += dpdV[i]*dervDict['pos']
2350                    if Ka2 and iFin2-iBeg2:
2351                        depDerivDict[name][iBeg2:iFin2] += dpdV[i]*dervDict2['pos']
2352            if 'C' in calcControls[hfx+'histType']:
2353                sigDict,gamDict = GetSampleSigGamDerv(refl,im,wave,G,GB,SGData,hfx,phfx,calcControls,parmDict)
2354            else:   #'T'OF
2355                sigDict,gamDict = GetSampleSigGamDerv(refl,im,0.0,G,GB,SGData,hfx,phfx,calcControls,parmDict)
2356            for name in gamDict:
2357                if name in varylist:
2358                    dMdv[varylist.index(name)][iBeg:iFin] += gamDict[name]*dervDict['gam']
2359                    if Ka2 and iFin2-iBeg2:
2360                        dMdv[varylist.index(name)][iBeg2:iFin2] += gamDict[name]*dervDict2['gam']
2361                elif name in dependentVars:
2362                    depDerivDict[name][iBeg:iFin] += gamDict[name]*dervDict['gam']
2363                    if Ka2 and iFin2-iBeg2:
2364                        depDerivDict[name][iBeg2:iFin2] += gamDict[name]*dervDict2['gam']
2365            for name in sigDict:
2366                if name in varylist:
2367                    dMdv[varylist.index(name)][iBeg:iFin] += sigDict[name]*dervDict['sig']
2368                    if Ka2 and iFin2-iBeg2:
2369                        dMdv[varylist.index(name)][iBeg2:iFin2] += sigDict[name]*dervDict2['sig']
2370                elif name in dependentVars:
2371                    depDerivDict[name][iBeg:iFin] += sigDict[name]*dervDict['sig']
2372                    if Ka2 and iFin2-iBeg2:
2373                        depDerivDict[name][iBeg2:iFin2] += sigDict[name]*dervDict2['sig']
2374            for name in ['BabA','BabU']:
2375                if refl[9+im]:
2376                    if phfx+name in varylist:
2377                        dMdv[varylist.index(phfx+name)][iBeg:iFin] += dFdvDict[pfx+name][iref]*dervDict['int']/refl[9+im]
2378                        if Ka2 and iFin2-iBeg2:
2379                            dMdv[varylist.index(phfx+name)][iBeg2:iFin2] += dFdvDict[pfx+name][iref]*dervDict2['int']/refl[9+im]
2380                    elif phfx+name in dependentVars:                   
2381                        depDerivDict[phfx+name][iBeg:iFin] += dFdvDict[pfx+name][iref]*dervDict['int']/refl[9+im]
2382                        if Ka2 and iFin2-iBeg2:
2383                            depDerivDict[phfx+name][iBeg2:iFin2] += dFdvDict[pfx+name][iref]*dervDict2['int']/refl[9+im]                 
2384            if not Phase['General'].get('doPawley'):
2385                #do atom derivatives -  for RB,F,X & U so far             
2386                corr = dervDict['int']/refl[9+im]
2387                if Ka2 and iFin2-iBeg2:
2388                    corr2 = dervDict2['int']/refl[9+im]
2389                for name in varylist+dependentVars:
2390                    if '::RBV;' in name:
2391                        pass
2392                    else:
2393                        try:
2394                            aname = name.split(pfx)[1][:2]
2395                            if aname not in ['Af','dA','AU','RB']: continue # skip anything not an atom or rigid body param
2396                        except IndexError:
2397                            continue
2398                    if name in varylist:
2399                        dMdv[varylist.index(name)][iBeg:iFin] += dFdvDict[name][iref]*corr
2400                        if Ka2 and iFin2-iBeg2:
2401                            dMdv[varylist.index(name)][iBeg2:iFin2] += dFdvDict[name][iref]*corr2
2402                    elif name in dependentVars:
2403                        depDerivDict[name][iBeg:iFin] += dFdvDict[name][iref]*corr
2404                        if Ka2 and iFin2-iBeg2:
2405                            depDerivDict[name][iBeg2:iFin2] += dFdvDict[name][iref]*corr2
2406    #        print 'profile derv time: %.3fs'%(time.time()-time0)
2407    # now process derivatives in constraints
2408    G2mv.Dict2Deriv(varylist,depDerivDict,dMdv)
2409    return dMdv
2410   
2411def UserRejectHKL(ref,im,userReject):
2412    if ref[5+im]/ref[6+im] < userReject['minF/sig']:
2413        return False
2414    elif userReject['MaxD'] < ref[4+im] > userReject['MinD']:
2415        return False
2416    elif ref[11+im] < userReject['MinExt']:
2417        return False
2418    elif abs(ref[5+im]-ref[7+im])/ref[6+im] > userReject['MaxDF/F']:
2419        return False
2420    return True
2421   
2422def dervHKLF(Histogram,Phase,calcControls,varylist,parmDict,rigidbodyDict):
2423    '''Loop over reflections in a HKLF histogram and compute derivatives of the fitting
2424    model (M) with respect to all parameters.  Independent and dependant dM/dp arrays
2425    are returned to either dervRefine or HessRefine.
2426
2427    :returns:
2428    '''
2429    nobs = Histogram['Residuals']['Nobs']
2430    hId = Histogram['hId']
2431    hfx = ':%d:'%(hId)
2432    pfx = '%d::'%(Phase['pId'])
2433    phfx = '%d:%d:'%(Phase['pId'],hId)
2434    SGData = Phase['General']['SGData']
2435    im = 0
2436    if Phase['General']['Type'] in ['modulated','magnetic']:
2437        SSGData = Phase['General']['SSGData']
2438        SSGMT = np.array([ops[0].T for ops in SSGData['SSGOps']])
2439        im = 1  #offset in SS reflection list
2440    A = [parmDict[pfx+'A%d'%(i)] for i in range(6)]
2441    G,g = G2lat.A2Gmat(A)       #recip & real metric tensors
2442    refDict = Histogram['Data']
2443    if im:
2444        dFdvDict = SStructureFactorDerv(refDict,im,G,hfx,pfx,SGData,SSGData,calcControls,parmDict)
2445    else:
2446        dFdvDict = StructureFactorDerv(refDict,G,hfx,pfx,SGData,calcControls,parmDict)
2447    ApplyRBModelDervs(dFdvDict,parmDict,rigidbodyDict,Phase)
2448    dMdvh = np.zeros((len(varylist),len(refDict['RefList'])))
2449    dependentVars = G2mv.GetDependentVars()
2450    depDerivDict = {}
2451    for j in dependentVars:
2452        depDerivDict[j] = np.zeros(shape=(len(refDict['RefList'])))
2453    wdf = np.zeros(len(refDict['RefList']))
2454    if calcControls['F**2']:
2455        for iref,ref in enumerate(refDict['RefList']):
2456            if ref[6+im] > 0:
2457                dervDict,dervCor = SCExtinction(ref,im,phfx,hfx,pfx,calcControls,parmDict,varylist+dependentVars)[1:]
2458                w = 1.0/ref[6+im]
2459                if ref[3+im] > 0:
2460                    wdf[iref] = w*(ref[5+im]-ref[7+im])
2461                    for j,var in enumerate(varylist):
2462                        if var in dFdvDict:
2463                            dMdvh[j][iref] = w*dFdvDict[var][iref]*parmDict[phfx+'Scale']*ref[11+im]
2464                    for var in dependentVars:
2465                        if var in dFdvDict:
2466                            depDerivDict[var][iref] = w*dFdvDict[var][iref]*parmDict[phfx+'Scale']*ref[11+im]
2467                    if phfx+'Scale' in varylist:
2468                        dMdvh[varylist.index(phfx+'Scale')][iref] = w*ref[9+im]*ref[11+im]  #OK
2469                    elif phfx+'Scale' in dependentVars:
2470                        depDerivDict[phfx+'Scale'][iref] = w*ref[9+im]*ref[11+im]   #OK
2471                    for item in ['Ep','Es','Eg']:
2472                        if phfx+item in varylist and phfx+item in dervDict:
2473                            dMdvh[varylist.index(phfx+item)][iref] = w*dervDict[phfx+item]/ref[11+im]  #OK
2474                        elif phfx+item in dependentVars and phfx+item in dervDict:
2475                            depDerivDict[phfx+item][iref] = w*dervDict[phfx+item]/ref[11+im]  #OK
2476                    for item in ['BabA','BabU']:
2477                        if phfx+item in varylist:
2478                            dMdvh[varylist.index(phfx+item)][iref] = w*dFdvDict[pfx+item][iref]*parmDict[phfx+'Scale']*ref[11+im]
2479                        elif phfx+item in dependentVars:
2480                            depDerivDict[phfx+item][iref] = w*dFdvDict[pfx+item][iref]*parmDict[phfx+'Scale']*ref[11+im]
2481    else:   #F refinement
2482        for iref,ref in enumerate(refDict['RefList']):
2483            if ref[5+im] > 0.:
2484                dervDict,dervCor = SCExtinction(ref,im,phfx,hfx,pfx,calcControls,parmDict,varylist+dependentVars)[1:]
2485                Fo = np.sqrt(ref[5+im])
2486                Fc = np.sqrt(ref[7+im])
2487                w = 1.0/ref[6+im]
2488                if ref[3+im] > 0:
2489                    wdf[iref] = 2.0*Fc*w*(Fo-Fc)
2490                    for j,var in enumerate(varylist):
2491                        if var in dFdvDict:
2492                            dMdvh[j][iref] = w*dFdvDict[var][iref]*parmDict[phfx+'Scale']*ref[11+im]
2493                    for var in dependentVars:
2494                        if var in dFdvDict:
2495                            depDerivDict[var][iref] = w*dFdvDict[var][iref]*parmDict[phfx+'Scale']*ref[11+im]
2496                    if phfx+'Scale' in varylist:
2497                        dMdvh[varylist.index(phfx+'Scale')][iref] = w*ref[9+im]*ref[11+im]  #OK
2498                    elif phfx+'Scale' in dependentVars:
2499                        depDerivDict[phfx+'Scale'][iref] = w*ref[9+im]*ref[11+im]   #OK                   
2500                    for item in ['Ep','Es','Eg']:   #OK!
2501                        if phfx+item in varylist and phfx+item in dervDict:
2502                            dMdvh[varylist.index(phfx+item)][iref] = w*dervDict[phfx+item]/ref[11+im] 
2503                        elif phfx+item in dependentVars and phfx+item in dervDict:
2504                            depDerivDict[phfx+item][iref] = w*dervDict[phfx+item]/ref[11+im]
2505                    for item in ['BabA','BabU']:
2506                        if phfx+item in varylist:
2507                            dMdvh[varylist.index(phfx+item)][iref] = w*dFdvDict[pfx+item][iref]*parmDict[phfx+'Scale']*ref[11+im]
2508                        elif phfx+item in dependentVars:
2509                            depDerivDict[phfx+item][iref] = w*dFdvDict[pfx+item][iref]*parmDict[phfx+'Scale']*ref[11+im]
2510    return dMdvh,depDerivDict,wdf
2511   
2512
2513def dervRefine(values,HistoPhases,parmDict,varylist,calcControls,pawleyLookup,dlg):
2514    '''Loop over histograms and compute derivatives of the fitting
2515    model (M) with respect to all parameters.  Results are returned in
2516    a Jacobian matrix (aka design matrix) of dimensions (n by m) where
2517    n is the number of parameters and m is the number of data
2518    points. This can exceed memory when m gets large. This routine is
2519    used when refinement derivatives are selected as "analtytic
2520    Jacobian" in Controls.
2521
2522    :returns: Jacobian numpy.array dMdv for all histograms concatinated
2523    '''
2524    parmDict.update(zip(varylist,values))
2525    G2mv.Dict2Map(parmDict,varylist)
2526    Histograms,Phases,restraintDict,rigidbodyDict = HistoPhases
2527    nvar = len(varylist)
2528    dMdv = np.empty(0)
2529    histoList = Histograms.keys()
2530    histoList.sort()
2531    for histogram in histoList:
2532        if 'PWDR' in histogram[:4]:
2533            Histogram = Histograms[histogram]
2534            hId = Histogram['hId']
2535            hfx = ':%d:'%(hId)
2536            wtFactor = calcControls[hfx+'wtFactor']
2537            Limits = calcControls[hfx+'Limits']
2538            x,y,w,yc,yb,yd = Histogram['Data']
2539            xB = np.searchsorted(x,Limits[0])
2540            xF = np.searchsorted(x,Limits[1])
2541            dMdvh = np.sqrt(w[xB:xF])*getPowderProfileDerv(parmDict,x[xB:xF],
2542                varylist,Histogram,Phases,rigidbodyDict,calcControls,pawleyLookup)
2543        elif 'HKLF' in histogram[:4]:
2544            Histogram = Histograms[histogram]
2545            phase = Histogram['Reflection Lists']
2546            Phase = Phases[phase]
2547            dMdvh,depDerivDict,wdf = dervHKLF(Histogram,Phase,calcControls,varylist,parmDict,rigidbodyDict)
2548            hfx = ':%d:'%(Histogram['hId'])
2549            wtFactor = calcControls[hfx+'wtFactor']
2550            # now process derivatives in constraints
2551            G2mv.Dict2Deriv(varylist,depDerivDict,dMdvh)
2552        else:
2553            continue        #skip non-histogram entries
2554        if len(dMdv):
2555            dMdv = np.concatenate((dMdv.T,np.sqrt(wtFactor)*dMdvh.T)).T
2556        else:
2557            dMdv = np.sqrt(wtFactor)*dMdvh
2558           
2559    pNames,pVals,pWt,pWsum = penaltyFxn(HistoPhases,calcControls,parmDict,varylist)
2560    if np.any(pVals):
2561        dpdv = penaltyDeriv(pNames,pVals,HistoPhases,calcControls,parmDict,varylist)
2562        dMdv = np.concatenate((dMdv.T,(np.sqrt(pWt)*dpdv).T)).T
2563       
2564    return dMdv
2565
2566def HessRefine(values,HistoPhases,parmDict,varylist,calcControls,pawleyLookup,dlg):
2567    '''Loop over histograms and compute derivatives of the fitting
2568    model (M) with respect to all parameters.  For each histogram, the
2569    Jacobian matrix, dMdv, with dimensions (n by m) where n is the
2570    number of parameters and m is the number of data points *in the
2571    histogram*. The (n by n) Hessian is computed from each Jacobian
2572    and it is returned.  This routine is used when refinement
2573    derivatives are selected as "analtytic Hessian" in Controls.
2574
2575    :returns: Vec,Hess where Vec is the least-squares vector and Hess is the Hessian
2576    '''
2577    parmDict.update(zip(varylist,values))
2578    G2mv.Dict2Map(parmDict,varylist)
2579    Histograms,Phases,restraintDict,rigidbodyDict = HistoPhases
2580    ApplyRBModels(parmDict,Phases,rigidbodyDict)        #,Update=True??
2581    nvar = len(varylist)
2582    Hess = np.empty(0)
2583    histoList = Histograms.keys()
2584    histoList.sort()
2585    for histogram in histoList:
2586        if 'PWDR' in histogram[:4]:
2587            Histogram = Histograms[histogram]
2588            hId = Histogram['hId']
2589            hfx = ':%d:'%(hId)
2590            wtFactor = calcControls[hfx+'wtFactor']
2591            Limits = calcControls[hfx+'Limits']
2592            x,y,w,yc,yb,yd = Histogram['Data']
2593            W = wtFactor*w
2594            dy = y-yc
2595            xB = np.searchsorted(x,Limits[0])
2596            xF = np.searchsorted(x,Limits[1])
2597            dMdvh = getPowderProfileDerv(parmDict,x[xB:xF],
2598                varylist,Histogram,Phases,rigidbodyDict,calcControls,pawleyLookup)
2599            Wt = ma.sqrt(W[xB:xF])[np.newaxis,:]
2600            Dy = dy[xB:xF][np.newaxis,:]
2601            dMdvh *= Wt
2602            if dlg:
2603                dlg.Update(Histogram['Residuals']['wR'],newmsg='Hessian for histogram %d\nAll data Rw=%8.3f%s'%(hId,Histogram['Residuals']['wR'],'%'))
2604            if len(Hess):
2605                Hess += np.inner(dMdvh,dMdvh)
2606                dMdvh *= Wt*Dy
2607                Vec += np.sum(dMdvh,axis=1)
2608            else:
2609                Hess = np.inner(dMdvh,dMdvh)
2610                dMdvh *= Wt*Dy
2611                Vec = np.sum(dMdvh,axis=1)
2612        elif 'HKLF' in histogram[:4]:
2613            Histogram = Histograms[histogram]
2614            phase = Histogram['Reflection Lists']
2615            Phase = Phases[phase]
2616            dMdvh,depDerivDict,wdf = dervHKLF(Histogram,Phase,calcControls,varylist,parmDict,rigidbodyDict)
2617            hId = Histogram['hId']
2618            hfx = ':%d:'%(Histogram['hId'])
2619            wtFactor = calcControls[hfx+'wtFactor']
2620            # now process derivatives in constraints
2621            G2mv.Dict2Deriv(varylist,depDerivDict,dMdvh)
2622#            print 'matrix build time: %.3f'%(time.time()-time0)
2623
2624            if dlg:
2625                dlg.Update(Histogram['Residuals']['wR'],newmsg='Hessian for histogram %d Rw=%8.3f%s'%(hId,Histogram['Residuals']['wR'],'%'))[0]
2626            if len(Hess):
2627                Vec += wtFactor*np.sum(dMdvh*wdf,axis=1)
2628                Hess += wtFactor*np.inner(dMdvh,dMdvh)
2629            else:
2630                Vec = wtFactor*np.sum(dMdvh*wdf,axis=1)
2631                Hess = wtFactor*np.inner(dMdvh,dMdvh)
2632        else:
2633            continue        #skip non-histogram entries
2634    pNames,pVals,pWt,pWsum = penaltyFxn(HistoPhases,calcControls,parmDict,varylist)
2635    if np.any(pVals):
2636        dpdv = penaltyDeriv(pNames,pVals,HistoPhases,calcControls,parmDict,varylist)
2637        Vec += np.sum(dpdv*pWt*pVals,axis=1)
2638        Hess += np.inner(dpdv*pWt,dpdv)
2639    return Vec,Hess
2640
2641def errRefine(values,HistoPhases,parmDict,varylist,calcControls,pawleyLookup,dlg=None):       
2642    '''Computes the point-by-point discrepancies between every data point in every histogram
2643    and the observed value
2644   
2645    :returns: an np array of differences between observed and computed diffraction values.
2646    '''
2647    Values2Dict(parmDict, varylist, values)
2648    G2mv.Dict2Map(parmDict,varylist)
2649    Histograms,Phases,restraintDict,rigidbodyDict = HistoPhases
2650    M = np.empty(0)
2651    SumwYo = 0
2652    Nobs = 0
2653    Nrej = 0
2654    Next = 0
2655    ApplyRBModels(parmDict,Phases,rigidbodyDict)
2656    histoList = Histograms.keys()
2657    histoList.sort()
2658    for histogram in histoList:
2659        if 'PWDR' in histogram[:4]:
2660            Histogram = Histograms[histogram]
2661            hId = Histogram['hId']
2662            hfx = ':%d:'%(hId)
2663            wtFactor = calcControls[hfx+'wtFactor']
2664            Limits = calcControls[hfx+'Limits']
2665            x,y,w,yc,yb,yd = Histogram['Data']
2666            yc *= 0.0                           #zero full calcd profiles
2667            yb *= 0.0
2668            yd *= 0.0
2669            xB = np.searchsorted(x,Limits[0])
2670            xF = np.searchsorted(x,Limits[1])
2671            yc[xB:xF],yb[xB:xF] = getPowderProfile(parmDict,x[xB:xF],
2672                varylist,Histogram,Phases,calcControls,pawleyLookup)
2673            yc[xB:xF] += yb[xB:xF]
2674            if not np.any(y):                   #fill dummy data
2675                rv = st.poisson(yc[xB:xF])
2676                y[xB:xF] = rv.rvs()
2677                Z = np.ones_like(yc[xB:xF])
2678                Z[1::2] *= -1
2679                y[xB:xF] = yc[xB:xF]+np.abs(y[xB:xF]-yc[xB:xF])*Z
2680                w[xB:xF] = np.where(y[xB:xF]>0.,1./y[xB:xF],1.0)
2681            yd[xB:xF] = y[xB:xF]-yc[xB:xF]
2682            W = wtFactor*w
2683            wdy = -ma.sqrt(W[xB:xF])*(yd[xB:xF])
2684            Histogram['Residuals']['Nobs'] = ma.count(x[xB:xF])
2685            Nobs += Histogram['Residuals']['Nobs']
2686            Histogram['Residuals']['sumwYo'] = ma.sum(W[xB:xF]*y[xB:xF]**2)
2687            SumwYo += Histogram['Residuals']['sumwYo']
2688            Histogram['Residuals']['R'] = min(100.,ma.sum(ma.abs(yd[xB:xF]))/ma.sum(y[xB:xF])*100.)
2689            Histogram['Residuals']['wR'] = min(100.,ma.sqrt(ma.sum(wdy**2)/Histogram['Residuals']['sumwYo'])*100.)
2690            sumYmB = ma.sum(ma.where(yc[xB:xF]!=yb[xB:xF],ma.abs(y[xB:xF]-yb[xB:xF]),0.))
2691            sumwYmB2 = ma.sum(ma.where(yc[xB:xF]!=yb[xB:xF],W[xB:xF]*(y[xB:xF]-yb[xB:xF])**2,0.))
2692            sumYB = ma.sum(ma.where(yc[xB:xF]!=yb[xB:xF],ma.abs(y[xB:xF]-yc[xB:xF])*ma.abs(y[xB:xF]-yb[xB:xF])/y[xB:xF],0.))
2693            sumwYB2 = ma.sum(ma.where(yc[xB:xF]!=yb[xB:xF],W[xB:xF]*(ma.abs(y[xB:xF]-yc[xB:xF])*ma.abs(y[xB:xF]-yb[xB:xF])/y[xB:xF])**2,0.))
2694            Histogram['Residuals']['Rb'] = min(100.,100.*sumYB/sumYmB)
2695            Histogram['Residuals']['wRb'] = min(100.,100.*ma.sqrt(sumwYB2/sumwYmB2))
2696            Histogram['Residuals']['wRmin'] = min(100.,100.*ma.sqrt(Histogram['Residuals']['Nobs']/Histogram['Residuals']['sumwYo']))
2697            if dlg:
2698                dlg.Update(Histogram['Residuals']['wR'],newmsg='For histogram %d Rw=%8.3f%s'%(hId,Histogram['Residuals']['wR'],'%'))[0]
2699            M = np.concatenate((M,wdy))
2700#end of PWDR processing
2701        elif 'HKLF' in histogram[:4]:
2702            Histogram = Histograms[histogram]
2703            Histogram['Residuals'] = {}
2704            phase = Histogram['Reflection Lists']
2705            Phase = Phases[phase]
2706            hId = Histogram['hId']
2707            hfx = ':%d:'%(hId)
2708            wtFactor = calcControls[hfx+'wtFactor']
2709            pfx = '%d::'%(Phase['pId'])
2710            phfx = '%d:%d:'%(Phase['pId'],hId)
2711            SGData = Phase['General']['SGData']
2712            im = 0
2713            if Phase['General']['Type'] in ['modulated','magnetic']:
2714                SSGData = Phase['General']['SSGData']
2715                SSGMT = np.array([ops[0].T for ops in SSGData['SSGOps']])
2716                im = 1  #offset in SS reflection list
2717            A = [parmDict[pfx+'A%d'%(i)] for i in range(6)]
2718            G,g = G2lat.A2Gmat(A)       #recip & real metric tensors
2719            refDict = Histogram['Data']
2720            time0 = time.time()
2721            if im:
2722                SStructureFactor(refDict,im,G,hfx,pfx,SGData,SSGData,calcControls,parmDict)
2723            else:
2724                StructureFactor2(refDict,G,hfx,pfx,SGData,calcControls,parmDict)
2725#            print 'sf-calc time: %.3f'%(time.time()-time0)
2726            df = np.zeros(len(refDict['RefList']))
2727            sumwYo = 0
2728            sumFo = 0
2729            sumFo2 = 0
2730            sumdF = 0
2731            sumdF2 = 0
2732            nobs = 0
2733            nrej = 0
2734            next = 0
2735            if calcControls['F**2']:
2736                for i,ref in enumerate(refDict['RefList']):
2737                    if ref[6+im] > 0:
2738                        ref[11+im] = SCExtinction(ref,im,phfx,hfx,pfx,calcControls,parmDict,varylist)[0]
2739                        w = 1.0/ref[6+im]   # 1/sig(F^2)
2740                        ref[7+im] = parmDict[phfx+'Scale']*ref[9+im]*ref[11+im]  #correct Fc^2 for extinction
2741                        ref[8+im] = ref[5+im]/(parmDict[phfx+'Scale']*ref[11+im])
2742                        if UserRejectHKL(ref,im,calcControls['UsrReject']) and ref[3+im]:    #skip sp.gp. absences (mul=0)
2743                            ref[3+im] = abs(ref[3+im])      #mark as allowed
2744                            Fo = np.sqrt(ref[5+im])
2745                            sumFo += Fo
2746                            sumFo2 += ref[5+im]
2747                            sumdF += abs(Fo-np.sqrt(ref[7+im]))
2748                            sumdF2 += abs(ref[5+im]-ref[7+im])
2749                            nobs += 1
2750                            df[i] = -w*(ref[5+im]-ref[7+im])
2751                            sumwYo += (w*ref[5+im])**2      #w*Fo^2
2752                        else:
2753                            if ref[3+im]:
2754                                ref[3+im] = -abs(ref[3+im])      #mark as rejected
2755                                nrej += 1
2756                            else:   #sp.gp.extinct
2757                                next += 1
2758            else:
2759                for i,ref in enumerate(refDict['RefList']):
2760                    if ref[5+im] > 0.:
2761                        ref[11+im] = SCExtinction(ref,im,phfx,hfx,pfx,calcControls,parmDict,varylist)[0]
2762                        ref[7+im] = parmDict[phfx+'Scale']*ref[9+im]*ref[11+im]    #correct Fc^2 for extinction
2763                        ref[8+im] = ref[5+im]/(parmDict[phfx+'Scale']*ref[11+im])
2764                        Fo = np.sqrt(ref[5+im])
2765                        Fc = np.sqrt(ref[7+im])
2766                        w = 2.0*Fo/ref[6+im]    # 1/sig(F)?
2767                        if UserRejectHKL(ref,im,calcControls['UsrReject']) and ref[3+im]:    #skip sp.gp. absences (mul=0)
2768                            ref[3+im] = abs(ref[3+im])      #mark as allowed
2769                            sumFo += Fo
2770                            sumFo2 += ref[5+im]
2771                            sumdF += abs(Fo-Fc)
2772                            sumdF2 += abs(ref[5+im]-ref[7+im])
2773                            nobs += 1
2774                            df[i] = -w*(Fo-Fc)
2775                            sumwYo += (w*Fo)**2
2776                        else:
2777                            if ref[3+im]:
2778                                ref[3+im] = -abs(ref[3+im])      #mark as rejected
2779                                nrej += 1
2780                            else:   #sp.gp.extinct
2781                                next += 1
2782            Histogram['Residuals']['Nobs'] = nobs
2783            Histogram['Residuals']['sumwYo'] = sumwYo
2784            SumwYo += sumwYo
2785            Histogram['Residuals']['wR'] = min(100.,np.sqrt(np.sum(df**2)/sumwYo)*100.)
2786            Histogram['Residuals'][phfx+'Rf'] = 100.*sumdF/sumFo
2787            Histogram['Residuals'][phfx+'Rf^2'] = 100.*sumdF2/sumFo2
2788            Histogram['Residuals'][phfx+'Nref'] = nobs
2789            Histogram['Residuals'][phfx+'Nrej'] = nrej
2790            Histogram['Residuals'][phfx+'Next'] = next
2791            Nobs += nobs
2792            Nrej += nrej
2793            Next += next
2794            if dlg:
2795                dlg.Update(Histogram['Residuals']['wR'],newmsg='For histogram %d Rw=%8.3f%s'%(hId,Histogram['Residuals']['wR'],'%'))[0]
2796            M = np.concatenate((M,wtFactor*df))
2797# end of HKLF processing
2798    Histograms['sumwYo'] = SumwYo
2799    Histograms['Nobs'] = Nobs
2800    Histograms['Nrej'] = Nrej
2801    Histograms['Next'] = Next
2802    Rw = min(100.,np.sqrt(np.sum(M**2)/SumwYo)*100.)
2803    if dlg:
2804        GoOn = dlg.Update(Rw,newmsg='%s%8.3f%s'%('All data Rw =',Rw,'%'))[0]
2805        if not GoOn:
2806            parmDict['saved values'] = values
2807            dlg.Destroy()
2808            raise G2obj.G2Exception('User abort')         #Abort!!
2809    pDict,pVals,pWt,pWsum = penaltyFxn(HistoPhases,calcControls,parmDict,varylist)
2810    if len(pVals):
2811        pSum = np.sum(pWt*pVals**2)
2812        for name in pWsum:
2813            if pWsum[name]:
2814                print '  Penalty function for %8s = %12.5g'%(name,pWsum[name])
2815        print 'Total penalty function: %12.5g on %d terms'%(pSum,len(pVals))
2816        Nobs += len(pVals)
2817        M = np.concatenate((M,np.sqrt(pWt)*pVals))
2818    return M
2819                       
Note: See TracBrowser for help on using the repository browser.