source: trunk/GSASIIstrMath.py @ 1955

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

Add error message for TOF calibration if peak positions weren't fitted
fix a bug in SS structure factor calc.
put debug prints back in GetSSfxuinel; now only if debug=True

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