source: trunk/GSASIIstrMath.py @ 1924

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

work on H-atom riding constraints
extend "short" phase names to full length - needed for riding constraint development

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 144.6 KB
Line 
1# -*- coding: utf-8 -*-
2'''
3*GSASIIstrMath - structure math routines*
4-----------------------------------------
5'''
6########### SVN repository information ###################
7# $Date: 2015-07-09 22:00:23 +0000 (Thu, 09 Jul 2015) $
8# $Author: vondreele $
9# $Revision: 1924 $
10# $URL: trunk/GSASIIstrMath.py $
11# $Id: GSASIIstrMath.py 1924 2015-07-09 22:00:23Z 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: 1924 $")
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[10+im] = atan2d(fbs[0],fas[0])
718   
719def StructureFactor2(refDict,G,hfx,pfx,SGData,calcControls,parmDict):
720    ''' Compute structure factors for all h,k,l for phase
721    puts the result, F^2, in each ref[8] in refList
722    input:
723   
724    :param dict refDict: where
725        'RefList' list where each ref = h,k,l,m,d,...
726        'FF' dict of form factors - filed in below
727    :param np.array G:      reciprocal metric tensor
728    :param str pfx:    phase id string
729    :param dict SGData: space group info. dictionary output from SpcGroup
730    :param dict calcControls:
731    :param dict ParmDict:
732
733    '''       
734    phfx = pfx.split(':')[0]+hfx
735    ast = np.sqrt(np.diag(G))
736    Mast = twopisq*np.multiply.outer(ast,ast)
737    SGMT = np.array([ops[0].T for ops in SGData['SGOps']])
738    SGT = np.array([ops[1] for ops in SGData['SGOps']])
739    FFtables = calcControls['FFtables']
740    BLtables = calcControls['BLtables']
741    Flack = 1.0
742    if not SGData['SGInv'] and 'S' in calcControls[hfx+'histType'] and phfx+'Flack' in parmDict:
743        Flack = 1.-2.*parmDict[phfx+'Flack']
744    TwinLaw = np.array([[[1,0,0],[0,1,0],[0,0,1]],])
745    TwDict = refDict.get('TwDict',{})           
746    if 'S' in calcControls[hfx+'histType']:
747        NTL = calcControls[phfx+'NTL']
748        NM = calcControls[phfx+'TwinNMN']+1
749        TwinLaw = calcControls[phfx+'TwinLaw']
750        TwinFr = np.array([parmDict[phfx+'TwinFr:'+str(i)] for i in range(len(TwinLaw))])
751        TwinInv = list(np.where(calcControls[phfx+'TwinInv'],-1,1))
752    Tdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata = GetAtomFXU(pfx,calcControls,parmDict)
753    FF = np.zeros(len(Tdata))
754    if 'NC' in calcControls[hfx+'histType']:
755        FP,FPP = G2el.BlenResCW(Tdata,BLtables,parmDict[hfx+'Lam'])
756    elif 'X' in calcControls[hfx+'histType']:
757        FP = np.array([FFtables[El][hfx+'FP'] for El in Tdata])
758        FPP = np.array([FFtables[El][hfx+'FPP'] for El in Tdata])
759    Uij = np.array(G2lat.U6toUij(Uijdata))
760    bij = Mast*Uij.T
761    blkSize = 100       #no. of reflections in a block
762    nRef = refDict['RefList'].shape[0]
763    if not len(refDict['FF']):                #no form factors - 1st time thru StructureFactor
764        if 'N' in calcControls[hfx+'histType']:
765            dat = G2el.getBLvalues(BLtables)
766            refDict['FF']['El'] = dat.keys()
767            refDict['FF']['FF'] = np.ones((nRef,len(dat)))*dat.values()           
768        else:       #'X'
769            dat = G2el.getFFvalues(FFtables,0.)
770            refDict['FF']['El'] = dat.keys()
771            refDict['FF']['FF'] = np.ones((nRef,len(dat)))
772            for iref,ref in enumerate(refDict['RefList']):
773                SQ = 1./(2.*ref[4])**2
774                dat = G2el.getFFvalues(FFtables,SQ)
775                refDict['FF']['FF'][iref] *= dat.values()
776#reflection processing begins here - big arrays!
777    iBeg = 0
778    while iBeg < nRef:
779        iFin = min(iBeg+blkSize,nRef)
780        refl = refDict['RefList'][iBeg:iFin]    #array(blkSize,nItems)
781        H = refl.T[:3]                          #array(blkSize,3)
782        H = np.squeeze(np.inner(H.T,TwinLaw))   #maybe array(blkSize,nTwins,3) or (blkSize,3)
783        TwMask = np.any(H,axis=-1)
784        if TwinLaw.shape[0] > 1 and TwDict: #need np.inner(TwinLaw[?],TwDict[iref][i])*TwinInv[i]
785            for ir in range(blkSize):
786                iref = ir+iBeg
787                if iref in TwDict:
788                    for i in TwDict[iref]:
789                        for n in range(NTL):
790                            H[ir][i+n*NM] = np.inner(TwinLaw[n*NM],np.array(TwDict[iref][i])*TwinInv[i+n*NM])
791            TwMask = np.any(H,axis=-1)
792        SQ = 1./(2.*refl.T[4])**2               #array(blkSize)
793        SQfactor = 4.0*SQ*twopisq               #ditto prev.
794        if 'T' in calcControls[hfx+'histType']:
795            if 'P' in calcControls[hfx+'histType']:
796                FP,FPP = G2el.BlenResTOF(Tdata,BLtables,refl.T[14])
797            else:
798                FP,FPP = G2el.BlenResTOF(Tdata,BLtables,refl.T[12])
799            FP = np.repeat(FP.T,len(SGT)*len(TwinLaw),axis=0)
800            FPP = np.repeat(FPP.T,len(SGT)*len(TwinLaw),axis=0)
801        Bab = np.repeat(parmDict[phfx+'BabA']*np.exp(-parmDict[phfx+'BabU']*SQfactor),len(SGT)*len(TwinLaw))
802        Tindx = np.array([refDict['FF']['El'].index(El) for El in Tdata])
803        FF = np.repeat(refDict['FF']['FF'][iBeg:iFin].T[Tindx].T,len(SGT)*len(TwinLaw),axis=0)
804        Uniq = np.inner(H,SGMT)
805        Phi = np.inner(H,SGT)
806        phase = twopi*(np.inner(Uniq,(dXdata+Xdata).T).T+Phi.T).T
807        sinp = np.sin(phase)
808        cosp = np.cos(phase)
809        biso = -SQfactor*Uisodata[:,np.newaxis]
810        Tiso = np.repeat(np.where(biso<1.,np.exp(biso),1.0),len(SGT)*len(TwinLaw),axis=1).T
811        HbH = -np.sum(Uniq.T*np.swapaxes(np.inner(bij,Uniq),2,-1),axis=1)
812        Tuij = np.where(HbH<1.,np.exp(HbH),1.0).T
813        Tcorr = np.reshape(Tiso,Tuij.shape)*Tuij*Mdata*Fdata/len(SGMT)
814        if 'T' in calcControls[hfx+'histType']:
815            fa = np.array([np.reshape(((FF+FP).T-Bab).T,cosp.shape)*cosp*Tcorr,-np.reshape(Flack*FPP,sinp.shape)*sinp*Tcorr])
816            fb = np.array([np.reshape(((FF+FP).T-Bab).T,sinp.shape)*sinp*Tcorr,np.reshape(Flack*FPP,cosp.shape)*cosp*Tcorr])
817        else:
818            fa = np.array([np.reshape(((FF+FP).T-Bab).T,cosp.shape)*cosp*Tcorr,-Flack*FPP*sinp*Tcorr])
819            fb = np.array([np.reshape(((FF+FP).T-Bab).T,sinp.shape)*sinp*Tcorr,Flack*FPP*cosp*Tcorr])
820        fas = np.sum(np.sum(fa,axis=-1),axis=-1)       #real sum over atoms & unique hkl
821        fbs = np.sum(np.sum(fb,axis=-1),axis=-1)  #imag sum over atoms & uniq hkl
822        if SGData['SGInv']: #centrosymmetric; B=0
823            fbs[0] *= 0.
824        if 'P' in calcControls[hfx+'histType']:
825            refl.T[9] = np.sum(fas**2,axis=0)+np.sum(fbs**2,axis=0)
826            refl.T[10] = atan2d(fbs[0],fas[0])  #ignore f' & f"
827        else:
828            if len(TwinLaw) > 1:
829                refl.T[9] = np.sum(fas[:,:,0]**2,axis=0)+np.sum(fbs[:,:,0]**2,axis=0)   #FcT from primary twin element
830                refl.T[7] = np.sum(TwinFr*np.sum(TwMask[np.newaxis,:,:]*fas,axis=0)**2,axis=-1)+   \
831                    np.sum(TwinFr*np.sum(TwMask[np.newaxis,:,:]*fbs,axis=0)**2,axis=-1)                        #Fc sum over twins
832                refl.T[10] = atan2d(fbs[0].T[0],fas[0].T[0])  #ignore f' & f"
833            else:
834                refl.T[9] = np.sum(fas,axis=0)**2+np.sum(fbs,axis=0)**2
835                refl.T[7] = np.copy(refl.T[9])               
836                refl.T[10] = atan2d(fbs[0],fas[0])  #ignore f' & f"
837#        refl.T[10] = atan2d(np.sum(fbs,axis=0),np.sum(fas,axis=0)) #include f' & f"
838        iBeg += blkSize
839   
840def StructureFactorDerv(refDict,G,hfx,pfx,SGData,calcControls,parmDict):
841    'Needs a doc string'
842    phfx = pfx.split(':')[0]+hfx
843    ast = np.sqrt(np.diag(G))
844    Mast = twopisq*np.multiply.outer(ast,ast)
845    SGMT = np.array([ops[0].T for ops in SGData['SGOps']])
846    SGT = np.array([ops[1] for ops in SGData['SGOps']])
847    FFtables = calcControls['FFtables']
848    BLtables = calcControls['BLtables']
849    TwinLaw = np.array([[[1,0,0],[0,1,0],[0,0,1]],])
850    TwDict = refDict.get('TwDict',{})           
851    if 'S' in calcControls[hfx+'histType']:
852        NTL = calcControls[phfx+'NTL']
853        NM = calcControls[phfx+'TwinNMN']+1
854        TwinLaw = calcControls[phfx+'TwinLaw']
855        TwinFr = np.array([parmDict[phfx+'TwinFr:'+str(i)] for i in range(len(TwinLaw))])
856        TwinInv = list(np.where(calcControls[phfx+'TwinInv'],-1,1))
857    nTwin = len(TwinLaw)       
858    nRef = len(refDict['RefList'])
859    Tdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata = GetAtomFXU(pfx,calcControls,parmDict)
860    mSize = len(Mdata)
861    FF = np.zeros(len(Tdata))
862    if 'NC' in calcControls[hfx+'histType']:
863        FP,FPP = G2el.BlenResCW(Tdata,BLtables,parmDict[hfx+'Lam'])
864    elif 'X' in calcControls[hfx+'histType']:
865        FP = np.array([FFtables[El][hfx+'FP'] for El in Tdata])
866        FPP = np.array([FFtables[El][hfx+'FPP'] for El in Tdata])
867    Uij = np.array(G2lat.U6toUij(Uijdata))
868    bij = Mast*Uij.T
869    dFdvDict = {}
870    if nTwin > 1:
871        dFdfr = np.zeros((nRef,nTwin,mSize))
872        dFdx = np.zeros((nRef,nTwin,mSize,3))
873        dFdui = np.zeros((nRef,nTwin,mSize))
874        dFdua = np.zeros((nRef,nTwin,mSize,6))
875        dFdbab = np.zeros((nRef,nTwin,2))
876        dFdfl = np.zeros((nRef,nTwin))
877        dFdtw = np.zeros((nRef,nTwin))
878    else:
879        dFdfr = np.zeros((nRef,mSize))
880        dFdx = np.zeros((nRef,mSize,3))
881        dFdui = np.zeros((nRef,mSize))
882        dFdua = np.zeros((nRef,mSize,6))
883        dFdbab = np.zeros((nRef,2))
884        dFdfl = np.zeros((nRef))
885        dFdtw = np.zeros((nRef))
886    Flack = 1.0
887    if not SGData['SGInv'] and 'S' in calcControls[hfx+'histType'] and phfx+'Flack' in parmDict:
888        Flack = 1.-2.*parmDict[phfx+'Flack']
889    for iref,refl in enumerate(refDict['RefList']):
890        if 'T' in calcControls[hfx+'histType']:
891            FP,FPP = G2el.BlenResCW(Tdata,BLtables,refl.T[12])
892        H = np.array(refl[:3])
893        H = np.squeeze(np.inner(H.T,TwinLaw))   #maybe array(3,nTwins) or (3)
894        TwMask = np.any(H,axis=-1)
895        if TwinLaw.shape[0] > 1 and TwDict:
896            if iref in TwDict:
897                for i in TwDict[iref]:
898                    for n in range(NTL):
899                        H[i+n*NM] = np.inner(TwinLaw[n*NM],np.array(TwDict[iref][i])*TwinInv[i+n*NM])
900            TwMask = np.any(H,axis=-1)
901        SQ = 1./(2.*refl[4])**2             # or (sin(theta)/lambda)**2
902        SQfactor = 8.0*SQ*np.pi**2
903        dBabdA = np.exp(-parmDict[phfx+'BabU']*SQfactor)
904        Bab = parmDict[phfx+'BabA']*dBabdA
905        Tindx = np.array([refDict['FF']['El'].index(El) for El in Tdata])
906        FF = refDict['FF']['FF'][iref].T[Tindx].T
907        Uniq = np.inner(H,SGMT)             # array(nSGOp,3) or (nTwin,nSGOp,3)
908        Phi = np.inner(H,SGT)
909        phase = twopi*(np.inner(Uniq,(dXdata+Xdata).T).T+Phi.T).T
910        sinp = np.sin(phase)
911        cosp = np.cos(phase)
912        occ = Mdata*Fdata/len(SGT)
913        biso = -SQfactor*Uisodata[:,np.newaxis]
914        Tiso = np.repeat(np.where(biso<1.,np.exp(biso),1.0),len(SGT)*nTwin,axis=1)
915        HbH = -np.sum(Uniq.T*np.swapaxes(np.inner(bij,Uniq),2,-1),axis=1)
916        Hij = np.array([Mast*np.multiply.outer(U,U) for U in np.reshape(Uniq,(-1,3))])
917        Hij = np.squeeze(np.reshape(np.array([G2lat.UijtoU6(Uij) for Uij in Hij]),(nTwin,-1,6)))
918        Tuij = np.where(HbH<1.,np.exp(HbH),1.0)
919        Tcorr = (np.reshape(Tiso,Tuij.shape)*Tuij).T*occ
920        fot = (FF+FP-Bab)*Tcorr
921        fotp = FPP*Tcorr       
922        fa = np.array([((FF+FP).T-Bab).T*cosp*Tcorr,-Flack*FPP*sinp*Tcorr]) # array(2,nTwin,nEqv,nAtoms)
923        fb = np.array([((FF+FP).T-Bab).T*sinp*Tcorr,Flack*FPP*cosp*Tcorr])
924        fas = np.sum(np.sum(fa,axis=-1),axis=-1)      #real sum over atoms & unique hkl array(2,nTwins)
925        fbs = np.sum(np.sum(fb,axis=-1),axis=-1)      #imag sum over atoms & uniq hkl
926        fax = np.array([-fot*sinp,-fotp*cosp])   #positions array(2,ntwi,nEqv,nAtoms)
927        fbx = np.array([fot*cosp,-fotp*sinp])
928        #sum below is over Uniq
929        dfadfr = np.sum(fa/occ,axis=-2)        #array(2,ntwin,nAtom) Fdata != 0 avoids /0. problem
930        dfadba = np.sum(-cosp*Tcorr[:,np.newaxis],axis=1)
931        dfadui = np.sum(-SQfactor*fa,axis=-2)
932        if nTwin > 1:
933            dfadx = np.array([np.sum(twopi*Uniq[it]*np.swapaxes(fax,-2,-1)[:,it,:,:,np.newaxis],axis=-2) for it in range(nTwin)])
934            dfadua = np.array([np.sum(-Hij[it]*np.swapaxes(fa,-2,-1)[:,it,:,:,np.newaxis],axis=-2) for it in range(nTwin)])
935            # array(nTwin,2,nAtom,3) & array(nTwin,2,nAtom,6)
936        else:
937            dfadx = np.sum(twopi*Uniq*np.swapaxes(fax,-2,-1)[:,:,:,np.newaxis],axis=-2)
938            dfadua = np.sum(-Hij*np.swapaxes(fa,-2,-1)[:,:,:,np.newaxis],axis=-2)
939            # array(2,nAtom,3) & array(2,nAtom,6)
940        if not SGData['SGInv']:
941            dfbdfr = np.sum(fb/occ,axis=-2)        #Fdata != 0 avoids /0. problem
942            dfbdba = np.sum(-sinp*Tcorr[:,np.newaxis],axis=1)
943            dfbdui = np.sum(-SQfactor*fb,axis=-2)
944            if len(TwinLaw) > 1:
945                dfbdx = np.array([np.sum(twopi*Uniq[it]*np.swapaxes(fbx,-2,-1)[:,it,:,:,np.newaxis],axis=2) for it in range(nTwin)])           
946                dfbdua = np.array([np.sum(-Hij[it]*np.swapaxes(fb,-2,-1)[:,it,:,:,np.newaxis],axis=2) for it in range(nTwin)])
947            else:
948                dfadfl = np.sum(-FPP*Tcorr*sinp)
949                dfbdfl = np.sum(FPP*Tcorr*cosp)
950                dfbdx = np.sum(twopi*Uniq*np.swapaxes(fbx,-2,-1)[:,:,:,np.newaxis],axis=2)           
951                dfbdua = np.sum(-Hij*np.swapaxes(fb,-2,-1)[:,:,:,np.newaxis],axis=2)
952        else:
953            dfbdfr = np.zeros_like(dfadfr)
954            dfbdx = np.zeros_like(dfadx)
955            dfbdui = np.zeros_like(dfadui)
956            dfbdua = np.zeros_like(dfadua)
957            dfbdba = np.zeros_like(dfadba)
958            dfadfl = 0.0
959            dfbdfl = 0.0
960        #NB: the above have been checked against PA(1:10,1:2) in strfctr.for for Al2O3!   
961        if 'P' in calcControls[hfx+'histType']: #checked perfect for centro & noncentro
962            dFdfr[iref] = 2.*(fas[0]*dfadfr[0]+fas[1]*dfadfr[1])*Mdata/len(Uniq)+   \
963                2.*(fbs[0]*dfbdfr[0]-fbs[1]*dfbdfr[1])*Mdata/len(Uniq)
964            dFdx[iref] = 2.*(fas[0]*dfadx[0]+fas[1]*dfadx[1])+  \
965                2.*(fbs[0]*dfbdx[0]+fbs[1]*dfbdx[1])
966            dFdui[iref] = 2.*(fas[0]*dfadui[0]+fas[1]*dfadui[1])+   \
967                2.*(fbs[0]*dfbdui[0]-fbs[1]*dfbdui[1])
968            dFdua[iref] = 2.*(fas[0]*dfadua[0]+fas[1]*dfadua[1])+   \
969                2.*(fbs[0]*dfbdua[0]+fbs[1]*dfbdua[1])
970        else:
971            SA = fas[0]-fbs[1]
972            SB = fbs[0]+fas[1]
973            if nTwin > 1:
974                dFdfr[iref] = [2.*TwMask[it]*SA[it]*(dfadfr[0][it]+dfbdfr[1][it])*Mdata/len(Uniq[it])+ \
975                    2.*TwMask[it]*SB[it]*(dfbdfr[0][it]+dfadfr[1][it])*Mdata/len(Uniq[it]) for it in range(nTwin)]
976                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)]
977                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)]
978                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)]
979                dFdtw[iref] = np.sum(TwMask*fas,axis=0)**2+np.sum(TwMask*fbs,axis=0)**2
980               
981            else:   #these are good for no twin single crystals
982                dFdfr[iref] = 2.*SA*(dfadfr[0]+dfbdfr[1])*Mdata/len(Uniq)+ \
983                    2.*SB*(dfbdfr[0]+dfadfr[1])*Mdata/len(Uniq) #array(nRef,nAtom)
984                dFdx[iref] = 2.*SA*(dfadx[0]+dfbdx[1])+2.*SB*(dfbdx[0]+dfadx[1])    #array(nRef,nAtom,3)
985                dFdui[iref] = 2.*SA*(dfadui[0]+dfbdui[1])+2.*SB*(dfbdui[0]+dfadui[1])   #array(nRef,nAtom)
986                dFdua[iref] = 2.*SA*(dfadua[0]+dfbdua[1])+2.*SB*(dfbdua[0]+dfadua[1])    #array(nRef,nAtom,6)
987                dFdfl[iref] = -SA*dfadfl-SB*dfbdfl  #array(nRef,)
988                dFdbab[iref] = 2.*fas[0]*np.array([np.sum(dfadba*dBabdA),np.sum(-dfadba*parmDict[phfx+'BabA']*SQfactor*dBabdA)]).T+ \
989                    2.*fbs[0]*np.array([np.sum(dfbdba*dBabdA),np.sum(-dfbdba*parmDict[phfx+'BabA']*SQfactor*dBabdA)]).T
990        #loop over atoms - each dict entry is list of derivatives for all the reflections
991    if nTwin > 1:
992        for i in range(len(Mdata)):     #these all OK?
993            dFdvDict[pfx+'Afrac:'+str(i)] = np.sum(dFdfr.T[i]*TwinFr[:,np.newaxis],axis=0)
994            dFdvDict[pfx+'dAx:'+str(i)] = np.sum(dFdx.T[0][i]*TwinFr[:,np.newaxis],axis=0)
995            dFdvDict[pfx+'dAy:'+str(i)] = np.sum(dFdx.T[1][i]*TwinFr[:,np.newaxis],axis=0)
996            dFdvDict[pfx+'dAz:'+str(i)] = np.sum(dFdx.T[2][i]*TwinFr[:,np.newaxis],axis=0)
997            dFdvDict[pfx+'AUiso:'+str(i)] = np.sum(dFdui.T[i]*TwinFr[:,np.newaxis],axis=0)
998            dFdvDict[pfx+'AU11:'+str(i)] = np.sum(dFdua.T[0][i]*TwinFr[:,np.newaxis],axis=0)
999            dFdvDict[pfx+'AU22:'+str(i)] = np.sum(dFdua.T[1][i]*TwinFr[:,np.newaxis],axis=0)
1000            dFdvDict[pfx+'AU33:'+str(i)] = np.sum(dFdua.T[2][i]*TwinFr[:,np.newaxis],axis=0)
1001            dFdvDict[pfx+'AU12:'+str(i)] = np.sum(0.5*dFdua.T[3][i]*TwinFr[:,np.newaxis],axis=0)
1002            dFdvDict[pfx+'AU13:'+str(i)] = np.sum(0.5*dFdua.T[4][i]*TwinFr[:,np.newaxis],axis=0)
1003            dFdvDict[pfx+'AU23:'+str(i)] = np.sum(0.5*dFdua.T[5][i]*TwinFr[:,np.newaxis],axis=0)
1004    else:
1005        for i in range(len(Mdata)):
1006            dFdvDict[pfx+'Afrac:'+str(i)] = dFdfr.T[i]
1007            dFdvDict[pfx+'dAx:'+str(i)] = dFdx.T[0][i]
1008            dFdvDict[pfx+'dAy:'+str(i)] = dFdx.T[1][i]
1009            dFdvDict[pfx+'dAz:'+str(i)] = dFdx.T[2][i]
1010            dFdvDict[pfx+'AUiso:'+str(i)] = dFdui.T[i]
1011            dFdvDict[pfx+'AU11:'+str(i)] = dFdua.T[0][i]
1012            dFdvDict[pfx+'AU22:'+str(i)] = dFdua.T[1][i]
1013            dFdvDict[pfx+'AU33:'+str(i)] = dFdua.T[2][i]
1014            dFdvDict[pfx+'AU12:'+str(i)] = 0.5*dFdua.T[3][i]
1015            dFdvDict[pfx+'AU13:'+str(i)] = 0.5*dFdua.T[4][i]
1016            dFdvDict[pfx+'AU23:'+str(i)] = 0.5*dFdua.T[5][i]
1017        dFdvDict[phfx+'Flack'] = 4.*dFdfl.T
1018    dFdvDict[phfx+'BabA'] = dFdbab.T[0]
1019    dFdvDict[phfx+'BabU'] = dFdbab.T[1]
1020    if nTwin > 1:
1021        for i in range(nTwin):
1022            dFdvDict[phfx+'TwinFr:'+str(i)] = dFdtw.T[i]
1023    return dFdvDict
1024   
1025def SStructureFactorDerv(refDict,im,G,hfx,pfx,SGData,SSGData,calcControls,parmDict):
1026    'Needs a doc string'
1027    phfx = pfx.split(':')[0]+hfx
1028    ast = np.sqrt(np.diag(G))
1029    Mast = twopisq*np.multiply.outer(ast,ast)
1030    SGMT = np.array([ops[0].T for ops in SGData['SGOps']])
1031    SGT = np.array([ops[1] for ops in SGData['SGOps']])
1032    SSGMT = np.array([ops[0].T for ops in SSGData['SSGOps']])
1033    SSGT = np.array([ops[1] for ops in SSGData['SSGOps']])
1034    FFtables = calcControls['FFtables']
1035    BLtables = calcControls['BLtables']
1036    nRef = len(refDict['RefList'])
1037    Tdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata = GetAtomFXU(pfx,calcControls,parmDict)
1038    waveTypes,FSSdata,XSSdata,USSdata,MSSdata = GetAtomSSFXU(pfx,calcControls,parmDict)
1039    mSize = len(Mdata)
1040    FF = np.zeros(len(Tdata))
1041    if 'NC' in calcControls[hfx+'histType']:
1042        FP,FPP = G2el.BlenResCW(Tdata,BLtables,parmDict[hfx+'Lam'])
1043    elif 'X' in calcControls[hfx+'histType']:
1044        FP = np.array([FFtables[El][hfx+'FP'] for El in Tdata])
1045        FPP = np.array([FFtables[El][hfx+'FPP'] for El in Tdata])
1046    Uij = np.array(G2lat.U6toUij(Uijdata))
1047    bij = Mast*Uij.T
1048    dFdvDict = {}
1049    dFdfr = np.zeros((nRef,mSize))
1050    dFdx = np.zeros((nRef,mSize,3))
1051    dFdui = np.zeros((nRef,mSize))
1052    dFdua = np.zeros((nRef,mSize,6))
1053    dFdbab = np.zeros((nRef,2))
1054    for iref,refl in enumerate(refDict['RefList']):
1055        if 'T' in calcControls[hfx+'histType']:
1056            FP,FPP = G2el.BlenResCW(Tdata,BLtables,refl.T[12+im])
1057        H = np.array(refl[:4])
1058        SQ = 1./(2.*refl[4+im])**2             # or (sin(theta)/lambda)**2
1059        SQfactor = 8.0*SQ*np.pi**2
1060        dBabdA = np.exp(-parmDict[phfx+'BabU']*SQfactor)
1061        Bab = parmDict[phfx+'BabA']*dBabdA
1062        Tindx = np.array([refDict['FF']['El'].index(El) for El in Tdata])
1063        FF = refDict['FF']['FF'][iref].T[Tindx]
1064        Uniq = np.inner(H[:3],SGMT)
1065        SSUniq = np.inner(H,SSGMT)
1066        Phi = np.inner(H[:3],SGT)
1067        SSPhi = np.inner(H,SSGT)
1068        GfpuA,GfpuB = G2mth.Modulation(waveTypes,SSUniq,SSPhi,FSSdata,XSSdata,USSdata)
1069        dGAdk,dGBdk = G2mth.ModulationDerv(waveTypes,SSUniq,SSPhi,FSSdata,XSSdata,USSdata)
1070        #need ModulationDerv here dGAdXsin, etc 
1071        phase = twopi*(np.inner((dXdata.T+Xdata.T),Uniq)+Phi[np.newaxis,:])
1072        sinp = np.sin(phase)
1073        cosp = np.cos(phase)
1074        occ = Mdata*Fdata/len(Uniq)
1075        biso = -SQfactor*Uisodata
1076        Tiso = np.where(biso<1.,np.exp(biso),1.0)
1077        HbH = -np.inner(H[:3],np.inner(bij,H[:3]))
1078        Hij = np.array([Mast*np.multiply.outer(U,U) for U in Uniq])
1079        Hij = np.array([G2lat.UijtoU6(Uij) for Uij in Hij])
1080        Tuij = np.where(HbH<1.,np.exp(HbH),1.0)
1081        Tcorr = Tiso*Tuij
1082        fot = (FF+FP-Bab)*occ*Tcorr
1083        fotp = FPP*occ*Tcorr
1084        fa = np.array([fot[:,np.newaxis]*cosp,fotp[:,np.newaxis]*cosp])       #non positions
1085        fb = np.array([fot[:,np.newaxis]*sinp,-fotp[:,np.newaxis]*sinp])
1086        GfpuA = np.swapaxes(GfpuA,1,2)
1087        GfpuB = np.swapaxes(GfpuB,1,2)
1088        fa = fa*GfpuA-fb*GfpuB
1089        fb = fb*GfpuA+fa*GfpuB
1090       
1091        fas = np.sum(np.sum(fa,axis=1),axis=1)
1092        fbs = np.sum(np.sum(fb,axis=1),axis=1)
1093        fax = np.array([-fot[:,np.newaxis]*sinp,-fotp[:,np.newaxis]*sinp])   #positions
1094        fbx = np.array([fot[:,np.newaxis]*cosp,-fot[:,np.newaxis]*cosp])
1095        fax = fax*GfpuA-fbx*GfpuB
1096        fbx = fbx*GfpuA+fax*GfpuB
1097        #sum below is over Uniq
1098        dfadfr = np.sum(fa/occ[:,np.newaxis],axis=2)        #Fdata != 0 ever avoids /0. problem
1099        dfadx = np.sum(twopi*Uniq*fax[:,:,:,np.newaxis],axis=2)
1100        dfadui = np.sum(-SQfactor*fa,axis=2)
1101        dfadua = np.sum(-Hij*fa[:,:,:,np.newaxis],axis=2)
1102        dfadba = np.sum(-cosp*(occ*Tcorr)[:,np.newaxis],axis=1)
1103        #NB: the above have been checked against PA(1:10,1:2) in strfctr.for for al2O3!   
1104        dFdfr[iref] = 2.*(fas[0]*dfadfr[0]+fas[1]*dfadfr[1])*Mdata/len(Uniq)
1105        dFdx[iref] = 2.*(fas[0]*dfadx[0]+fas[1]*dfadx[1])
1106        dFdui[iref] = 2.*(fas[0]*dfadui[0]+fas[1]*dfadui[1])
1107        dFdua[iref] = 2.*(fas[0]*dfadua[0]+fas[1]*dfadua[1])
1108        dFdbab[iref] = 2.*fas[0]*np.array([np.sum(dfadba*dBabdA),np.sum(-dfadba*parmDict[phfx+'BabA']*SQfactor*dBabdA)]).T
1109        #need dFdXsin, etc for modulations...
1110        if not SGData['SGInv']:
1111            dfbdfr = np.sum(fb/occ[:,np.newaxis],axis=2)        #Fdata != 0 ever avoids /0. problem
1112            dfbdx = np.sum(twopi*Uniq*fbx[:,:,:,np.newaxis],axis=2)           
1113            dfbdui = np.sum(-SQfactor*fb,axis=2)
1114            dfbdua = np.sum(-Hij*fb[:,:,:,np.newaxis],axis=2)
1115            dfbdba = np.sum(-sinp*(occ*Tcorr)[:,np.newaxis],axis=1)
1116            dFdfr[iref] += 2.*(fbs[0]*dfbdfr[0]-fbs[1]*dfbdfr[1])*Mdata/len(Uniq)
1117            dFdx[iref] += 2.*(fbs[0]*dfbdx[0]+fbs[1]*dfbdx[1])
1118            dFdui[iref] += 2.*(fbs[0]*dfbdui[0]-fbs[1]*dfbdui[1])
1119            dFdua[iref] += 2.*(fbs[0]*dfbdua[0]+fbs[1]*dfbdua[1])
1120            dFdbab[iref] += 2.*fbs[0]*np.array([np.sum(dfbdba*dBabdA),np.sum(-dfbdba*parmDict[phfx+'BabA']*SQfactor*dBabdA)]).T
1121        #need dFdXsin, etc for modulations...
1122        #loop over atoms - each dict entry is list of derivatives for all the reflections
1123    for i in range(len(Mdata)):     
1124        dFdvDict[pfx+'Afrac:'+str(i)] = dFdfr.T[i]
1125        dFdvDict[pfx+'dAx:'+str(i)] = dFdx.T[0][i]
1126        dFdvDict[pfx+'dAy:'+str(i)] = dFdx.T[1][i]
1127        dFdvDict[pfx+'dAz:'+str(i)] = dFdx.T[2][i]
1128        dFdvDict[pfx+'AUiso:'+str(i)] = dFdui.T[i]
1129        dFdvDict[pfx+'AU11:'+str(i)] = dFdua.T[0][i]
1130        dFdvDict[pfx+'AU22:'+str(i)] = dFdua.T[1][i]
1131        dFdvDict[pfx+'AU33:'+str(i)] = dFdua.T[2][i]
1132        dFdvDict[pfx+'AU12:'+str(i)] = .5*dFdua.T[3][i]
1133        dFdvDict[pfx+'AU13:'+str(i)] = .5*dFdua.T[4][i]
1134        dFdvDict[pfx+'AU23:'+str(i)] = .5*dFdua.T[5][i]
1135        #need dFdvDict[pfx+'Xsin:'+str[i]:str(m)], etc for modulations...
1136    dFdvDict[phfx+'BabA'] = dFdbab.T[0]
1137    dFdvDict[phfx+'BabU'] = dFdbab.T[1]
1138    return dFdvDict
1139   
1140def SCExtinction(ref,im,phfx,hfx,pfx,calcControls,parmDict,varyList):
1141    ''' Single crystal extinction function; returns extinction & derivative
1142    '''
1143    extCor = 1.0
1144    dervDict = {}
1145    dervCor = 1.0
1146    if calcControls[phfx+'EType'] != 'None':
1147        SQ = 1/(4.*ref[4+im]**2)
1148        if 'C' in parmDict[hfx+'Type']:           
1149            cos2T = 1.0-2.*SQ*parmDict[hfx+'Lam']**2           #cos(2theta)
1150        else:   #'T'
1151            cos2T = 1.0-2.*SQ*ref[12+im]**2                       #cos(2theta)           
1152        if 'SXC' in parmDict[hfx+'Type']:
1153            AV = 7.9406e5/parmDict[pfx+'Vol']**2
1154            PL = np.sqrt(1.0-cos2T**2)/parmDict[hfx+'Lam']
1155            P12 = (calcControls[phfx+'Cos2TM']+cos2T**4)/(calcControls[phfx+'Cos2TM']+cos2T**2)
1156            PLZ = AV*P12*ref[9+im]*parmDict[hfx+'Lam']**2
1157        elif 'SNT' in parmDict[hfx+'Type']:
1158            AV = 1.e7/parmDict[pfx+'Vol']**2
1159            PL = SQ
1160            PLZ = AV*ref[9+im]*ref[12+im]**2
1161        elif 'SNC' in parmDict[hfx+'Type']:
1162            AV = 1.e7/parmDict[pfx+'Vol']**2
1163            PL = np.sqrt(1.0-cos2T**2)/parmDict[hfx+'Lam']
1164            PLZ = AV*ref[9+im]*parmDict[hfx+'Lam']**2
1165           
1166        if 'Primary' in calcControls[phfx+'EType']:
1167            PLZ *= 1.5
1168        else:
1169            if 'C' in parmDict[hfx+'Type']:
1170                PLZ *= calcControls[phfx+'Tbar']
1171            else: #'T'
1172                PLZ *= ref[13+im]      #t-bar
1173        if 'Primary' in calcControls[phfx+'EType']:
1174            PLZ *= 1.5
1175            PSIG = parmDict[phfx+'Ep']
1176        elif 'I & II' in calcControls[phfx+'EType']:
1177            PSIG = parmDict[phfx+'Eg']/np.sqrt(1.+(parmDict[phfx+'Es']*PL/parmDict[phfx+'Eg'])**2)
1178        elif 'Type II' in calcControls[phfx+'EType']:
1179            PSIG = parmDict[phfx+'Es']
1180        else:       # 'Secondary Type I'
1181            PSIG = parmDict[phfx+'Eg']/PL
1182           
1183        AG = 0.58+0.48*cos2T+0.24*cos2T**2
1184        AL = 0.025+0.285*cos2T
1185        BG = 0.02-0.025*cos2T
1186        BL = 0.15-0.2*(0.75-cos2T)**2
1187        if cos2T < 0.:
1188            BL = -0.45*cos2T
1189        CG = 2.
1190        CL = 2.
1191        PF = PLZ*PSIG
1192       
1193        if 'Gaussian' in calcControls[phfx+'EApprox']:
1194            PF4 = 1.+CG*PF+AG*PF**2/(1.+BG*PF)
1195            extCor = np.sqrt(PF4)
1196            PF3 = 0.5*(CG+2.*AG*PF/(1.+BG*PF)-AG*PF**2*BG/(1.+BG*PF)**2)/(PF4*extCor)
1197        else:
1198            PF4 = 1.+CL*PF+AL*PF**2/(1.+BL*PF)
1199            extCor = np.sqrt(PF4)
1200            PF3 = 0.5*(CL+2.*AL*PF/(1.+BL*PF)-AL*PF**2*BL/(1.+BL*PF)**2)/(PF4*extCor)
1201
1202        dervCor = (1.+PF)*PF3   #extinction corr for other derivatives
1203        if 'Primary' in calcControls[phfx+'EType'] and phfx+'Ep' in varyList:
1204            dervDict[phfx+'Ep'] = -ref[7+im]*PLZ*PF3
1205        if 'II' in calcControls[phfx+'EType'] and phfx+'Es' in varyList:
1206            dervDict[phfx+'Es'] = -ref[7+im]*PLZ*PF3*(PSIG/parmDict[phfx+'Es'])**3
1207        if 'I' in calcControls[phfx+'EType'] and phfx+'Eg' in varyList:
1208            dervDict[phfx+'Eg'] = -ref[7+im]*PLZ*PF3*(PSIG/parmDict[phfx+'Eg'])**3*PL**2
1209               
1210    return 1./extCor,dervDict,dervCor
1211   
1212def Dict2Values(parmdict, varylist):
1213    '''Use before call to leastsq to setup list of values for the parameters
1214    in parmdict, as selected by key in varylist'''
1215    return [parmdict[key] for key in varylist] 
1216   
1217def Values2Dict(parmdict, varylist, values):
1218    ''' Use after call to leastsq to update the parameter dictionary with
1219    values corresponding to keys in varylist'''
1220    parmdict.update(zip(varylist,values))
1221   
1222def GetNewCellParms(parmDict,varyList):
1223    'Needs a doc string'
1224    newCellDict = {}
1225    Anames = ['A'+str(i) for i in range(6)]
1226    Ddict = dict(zip(['D11','D22','D33','D12','D13','D23'],Anames))
1227    for item in varyList:
1228        keys = item.split(':')
1229        if keys[2] in Ddict:
1230            key = keys[0]+'::'+Ddict[keys[2]]       #key is e.g. '0::A0'
1231            parm = keys[0]+'::'+keys[2]             #parm is e.g. '0::D11'
1232            newCellDict[parm] = [key,parmDict[key]+parmDict[item]]
1233    return newCellDict          # is e.g. {'0::D11':A0-D11}
1234   
1235def ApplyXYZshifts(parmDict,varyList):
1236    '''
1237    takes atom x,y,z shift and applies it to corresponding atom x,y,z value
1238   
1239    :param dict parmDict: parameter dictionary
1240    :param list varyList: list of variables (not used!)
1241    :returns: newAtomDict - dictionary of new atomic coordinate names & values; key is parameter shift name
1242
1243    '''
1244    newAtomDict = {}
1245    for item in parmDict:
1246        if 'dA' in item:
1247            parm = ''.join(item.split('d'))
1248            parmDict[parm] += parmDict[item]
1249            newAtomDict[item] = [parm,parmDict[parm]]
1250    return newAtomDict
1251   
1252def SHTXcal(refl,im,g,pfx,hfx,SGData,calcControls,parmDict):
1253    'Spherical harmonics texture'
1254    IFCoup = 'Bragg' in calcControls[hfx+'instType']
1255    if 'T' in calcControls[hfx+'histType']:
1256        tth = parmDict[hfx+'2-theta']
1257    else:
1258        tth = refl[5+im]
1259    odfCor = 1.0
1260    H = refl[:3]
1261    cell = G2lat.Gmat2cell(g)
1262    Sangls = [parmDict[pfx+'SH omega'],parmDict[pfx+'SH chi'],parmDict[pfx+'SH phi']]
1263    Gangls = [parmDict[hfx+'Phi'],parmDict[hfx+'Chi'],parmDict[hfx+'Omega'],parmDict[hfx+'Azimuth']]
1264    phi,beta = G2lat.CrsAng(H,cell,SGData)
1265    psi,gam,x,x = G2lat.SamAng(tth/2.,Gangls,Sangls,IFCoup) #ignore 2 sets of angle derivs.
1266    SHnames = G2lat.GenSHCoeff(SGData['SGLaue'],parmDict[pfx+'SHmodel'],parmDict[pfx+'SHorder'])
1267    for item in SHnames:
1268        L,M,N = eval(item.strip('C'))
1269        Kcl = G2lat.GetKcl(L,N,SGData['SGLaue'],phi,beta)
1270        Ksl,x,x = G2lat.GetKsl(L,M,parmDict[pfx+'SHmodel'],psi,gam)
1271        Lnorm = G2lat.Lnorm(L)
1272        odfCor += parmDict[pfx+item]*Lnorm*Kcl*Ksl
1273    return odfCor
1274   
1275def SHTXcalDerv(refl,im,g,pfx,hfx,SGData,calcControls,parmDict):
1276    'Spherical harmonics texture derivatives'
1277    if 'T' in calcControls[hfx+'histType']:
1278        tth = parmDict[hfx+'2-theta']
1279    else:
1280        tth = refl[5+im]
1281    IFCoup = 'Bragg' in calcControls[hfx+'instType']
1282    odfCor = 1.0
1283    dFdODF = {}
1284    dFdSA = [0,0,0]
1285    H = refl[:3]
1286    cell = G2lat.Gmat2cell(g)
1287    Sangls = [parmDict[pfx+'SH omega'],parmDict[pfx+'SH chi'],parmDict[pfx+'SH phi']]
1288    Gangls = [parmDict[hfx+'Phi'],parmDict[hfx+'Chi'],parmDict[hfx+'Omega'],parmDict[hfx+'Azimuth']]
1289    phi,beta = G2lat.CrsAng(H,cell,SGData)
1290    psi,gam,dPSdA,dGMdA = G2lat.SamAng(tth/2.,Gangls,Sangls,IFCoup)
1291    SHnames = G2lat.GenSHCoeff(SGData['SGLaue'],parmDict[pfx+'SHmodel'],parmDict[pfx+'SHorder'])
1292    for item in SHnames:
1293        L,M,N = eval(item.strip('C'))
1294        Kcl = G2lat.GetKcl(L,N,SGData['SGLaue'],phi,beta)
1295        Ksl,dKsdp,dKsdg = G2lat.GetKsl(L,M,parmDict[pfx+'SHmodel'],psi,gam)
1296        Lnorm = G2lat.Lnorm(L)
1297        odfCor += parmDict[pfx+item]*Lnorm*Kcl*Ksl
1298        dFdODF[pfx+item] = Lnorm*Kcl*Ksl
1299        for i in range(3):
1300            dFdSA[i] += parmDict[pfx+item]*Lnorm*Kcl*(dKsdp*dPSdA[i]+dKsdg*dGMdA[i])
1301    return odfCor,dFdODF,dFdSA
1302   
1303def SHPOcal(refl,im,g,phfx,hfx,SGData,calcControls,parmDict):
1304    'spherical harmonics preferred orientation (cylindrical symmetry only)'
1305    if 'T' in calcControls[hfx+'histType']:
1306        tth = parmDict[hfx+'2-theta']
1307    else:
1308        tth = refl[5+im]
1309    odfCor = 1.0
1310    H = refl[:3]
1311    cell = G2lat.Gmat2cell(g)
1312    Sangls = [0.,0.,0.]
1313    if 'Bragg' in calcControls[hfx+'instType']:
1314        Gangls = [0.,90.,0.,parmDict[hfx+'Azimuth']]
1315        IFCoup = True
1316    else:
1317        Gangls = [parmDict[hfx+'Phi'],parmDict[hfx+'Chi'],parmDict[hfx+'Omega'],parmDict[hfx+'Azimuth']]
1318        IFCoup = False
1319    phi,beta = G2lat.CrsAng(H,cell,SGData)
1320    psi,gam,x,x = G2lat.SamAng(tth/2.,Gangls,Sangls,IFCoup) #ignore 2 sets of angle derivs.
1321    SHnames = calcControls[phfx+'SHnames']
1322    for item in SHnames:
1323        L,N = eval(item.strip('C'))
1324        Kcl = G2lat.GetKcl(L,N,SGData['SGLaue'],phi,beta)
1325        Ksl,x,x = G2lat.GetKsl(L,0,'0',psi,gam)
1326        Lnorm = G2lat.Lnorm(L)
1327        odfCor += parmDict[phfx+item]*Lnorm*Kcl*Ksl
1328    return np.squeeze(odfCor)
1329   
1330def SHPOcalDerv(refl,im,g,phfx,hfx,SGData,calcControls,parmDict):
1331    'spherical harmonics preferred orientation derivatives (cylindrical symmetry only)'
1332    if 'T' in calcControls[hfx+'histType']:
1333        tth = parmDict[hfx+'2-theta']
1334    else:
1335        tth = refl[5+im]
1336    odfCor = 1.0
1337    dFdODF = {}
1338    H = refl[:3]
1339    cell = G2lat.Gmat2cell(g)
1340    Sangls = [0.,0.,0.]
1341    if 'Bragg' in calcControls[hfx+'instType']:
1342        Gangls = [0.,90.,0.,parmDict[hfx+'Azimuth']]
1343        IFCoup = True
1344    else:
1345        Gangls = [parmDict[hfx+'Phi'],parmDict[hfx+'Chi'],parmDict[hfx+'Omega'],parmDict[hfx+'Azimuth']]
1346        IFCoup = False
1347    phi,beta = G2lat.CrsAng(H,cell,SGData)
1348    psi,gam,x,x = G2lat.SamAng(tth/2.,Gangls,Sangls,IFCoup) #ignore 2 sets of angle derivs.
1349    SHnames = calcControls[phfx+'SHnames']
1350    for item in SHnames:
1351        L,N = eval(item.strip('C'))
1352        Kcl = G2lat.GetKcl(L,N,SGData['SGLaue'],phi,beta)
1353        Ksl,x,x = G2lat.GetKsl(L,0,'0',psi,gam)
1354        Lnorm = G2lat.Lnorm(L)
1355        odfCor += parmDict[phfx+item]*Lnorm*Kcl*Ksl
1356        dFdODF[phfx+item] = Kcl*Ksl*Lnorm
1357    return odfCor,dFdODF
1358   
1359def GetPrefOri(uniq,G,g,phfx,hfx,SGData,calcControls,parmDict):
1360    'March-Dollase preferred orientation correction'
1361    POcorr = 1.0
1362    MD = parmDict[phfx+'MD']
1363    if MD != 1.0:
1364        MDAxis = calcControls[phfx+'MDAxis']
1365        sumMD = 0
1366        for H in uniq:           
1367            cosP,sinP = G2lat.CosSinAngle(H,MDAxis,G)
1368            A = 1.0/np.sqrt((MD*cosP)**2+sinP**2/MD)
1369            sumMD += A**3
1370        POcorr = sumMD/len(uniq)
1371    return POcorr
1372   
1373def GetPrefOriDerv(refl,im,uniq,G,g,phfx,hfx,SGData,calcControls,parmDict):
1374    'Needs a doc string'
1375    POcorr = 1.0
1376    POderv = {}
1377    if calcControls[phfx+'poType'] == 'MD':
1378        MD = parmDict[phfx+'MD']
1379        MDAxis = calcControls[phfx+'MDAxis']
1380        sumMD = 0
1381        sumdMD = 0
1382        for H in uniq:           
1383            cosP,sinP = G2lat.CosSinAngle(H,MDAxis,G)
1384            A = 1.0/np.sqrt((MD*cosP)**2+sinP**2/MD)
1385            sumMD += A**3
1386            sumdMD -= (1.5*A**5)*(2.0*MD*cosP**2-(sinP/MD)**2)
1387        POcorr = sumMD/len(uniq)
1388        POderv[phfx+'MD'] = sumdMD/len(uniq)
1389    else:   #spherical harmonics
1390        if calcControls[phfx+'SHord']:
1391            POcorr,POderv = SHPOcalDerv(refl,im,g,phfx,hfx,SGData,calcControls,parmDict)
1392    return POcorr,POderv
1393   
1394def GetAbsorb(refl,im,hfx,calcControls,parmDict):
1395    'Needs a doc string'
1396    if 'Debye' in calcControls[hfx+'instType']:
1397        if 'T' in calcControls[hfx+'histType']:
1398            return G2pwd.Absorb('Cylinder',parmDict[hfx+'Absorption']*refl[14+im],abs(parmDict[hfx+'2-theta']),0,0)
1399        else:
1400            return G2pwd.Absorb('Cylinder',parmDict[hfx+'Absorption'],refl[5+im],0,0)
1401    else:
1402        return G2pwd.SurfaceRough(parmDict[hfx+'SurfRoughA'],parmDict[hfx+'SurfRoughB'],refl[5+im])
1403   
1404def GetAbsorbDerv(refl,im,hfx,calcControls,parmDict):
1405    'Needs a doc string'
1406    if 'Debye' in calcControls[hfx+'instType']:
1407        if 'T' in calcControls[hfx+'histType']:
1408            return G2pwd.AbsorbDerv('Cylinder',parmDict[hfx+'Absorption']*refl[14+im],abs(parmDict[hfx+'2-theta']),0,0)
1409        else:
1410            return G2pwd.AbsorbDerv('Cylinder',parmDict[hfx+'Absorption'],refl[5+im],0,0)
1411    else:
1412        return np.array(G2pwd.SurfaceRoughDerv(parmDict[hfx+'SurfRoughA'],parmDict[hfx+'SurfRoughB'],refl[5+im]))
1413       
1414def GetPwdrExt(refl,im,pfx,phfx,hfx,calcControls,parmDict):
1415    'Needs a doc string'
1416    coef = np.array([-0.5,0.25,-0.10416667,0.036458333,-0.0109375,2.8497409E-3])
1417    pi2 = np.sqrt(2./np.pi)
1418    if 'T' in calcControls[hfx+'histType']:
1419        sth2 = sind(abs(parmDict[hfx+'2-theta'])/2.)**2
1420        wave = refl[14+im]
1421    else:   #'C'W
1422        sth2 = sind(refl[5+im]/2.)**2
1423        wave = parmDict.get(hfx+'Lam',parmDict.get(hfx+'Lam1',1.0))
1424    c2th = 1.-2.0*sth2
1425    flv2 = refl[9+im]*(wave/parmDict[pfx+'Vol'])**2
1426    if 'X' in calcControls[hfx+'histType']:
1427        flv2 *= 0.079411*(1.0+c2th**2)/2.0
1428    xfac = flv2*parmDict[phfx+'Extinction']
1429    exb = 1.0
1430    if xfac > -1.:
1431        exb = 1./np.sqrt(1.+xfac)
1432    exl = 1.0
1433    if 0 < xfac <= 1.:
1434        xn = np.array([xfac**(i+1) for i in range(6)])
1435        exl += np.sum(xn*coef)
1436    elif xfac > 1.:
1437        xfac2 = 1./np.sqrt(xfac)
1438        exl = pi2*(1.-0.125/xfac)*xfac2
1439    return exb*sth2+exl*(1.-sth2)
1440   
1441def GetPwdrExtDerv(refl,im,pfx,phfx,hfx,calcControls,parmDict):
1442    'Needs a doc string'
1443    coef = np.array([-0.5,0.25,-0.10416667,0.036458333,-0.0109375,2.8497409E-3])
1444    pi2 = np.sqrt(2./np.pi)
1445    if 'T' in calcControls[hfx+'histType']:
1446        sth2 = sind(abs(parmDict[hfx+'2-theta'])/2.)**2
1447        wave = refl[14+im]
1448    else:   #'C'W
1449        sth2 = sind(refl[5+im]/2.)**2
1450        wave = parmDict.get(hfx+'Lam',parmDict.get(hfx+'Lam1',1.0))
1451    c2th = 1.-2.0*sth2
1452    flv2 = refl[9+im]*(wave/parmDict[pfx+'Vol'])**2
1453    if 'X' in calcControls[hfx+'histType']:
1454        flv2 *= 0.079411*(1.0+c2th**2)/2.0
1455    xfac = flv2*parmDict[phfx+'Extinction']
1456    dbde = -500.*flv2
1457    if xfac > -1.:
1458        dbde = -0.5*flv2/np.sqrt(1.+xfac)**3
1459    dlde = 0.
1460    if 0 < xfac <= 1.:
1461        xn = np.array([i*flv2*xfac**i for i in [1,2,3,4,5,6]])
1462        dlde = np.sum(xn*coef)
1463    elif xfac > 1.:
1464        xfac2 = 1./np.sqrt(xfac)
1465        dlde = flv2*pi2*xfac2*(-1./xfac+0.375/xfac**2)
1466       
1467    return dbde*sth2+dlde*(1.-sth2)
1468   
1469def GetIntensityCorr(refl,im,uniq,G,g,pfx,phfx,hfx,SGData,calcControls,parmDict):
1470    'Needs a doc string'    #need powder extinction!
1471    Icorr = parmDict[phfx+'Scale']*parmDict[hfx+'Scale']*refl[3+im]               #scale*multiplicity
1472    if 'X' in parmDict[hfx+'Type']:
1473        Icorr *= G2pwd.Polarization(parmDict[hfx+'Polariz.'],refl[5+im],parmDict[hfx+'Azimuth'])[0]
1474    POcorr = 1.0
1475    if pfx+'SHorder' in parmDict:                 #generalized spherical harmonics texture - takes precidence
1476        POcorr = SHTXcal(refl,im,g,pfx,hfx,SGData,calcControls,parmDict)
1477    elif calcControls[phfx+'poType'] == 'MD':         #March-Dollase
1478        POcorr = GetPrefOri(uniq,G,g,phfx,hfx,SGData,calcControls,parmDict)
1479    elif calcControls[phfx+'SHord']:                #cylindrical spherical harmonics
1480        POcorr = SHPOcal(refl,im,g,phfx,hfx,SGData,calcControls,parmDict)
1481    Icorr *= POcorr
1482    AbsCorr = 1.0
1483    AbsCorr = GetAbsorb(refl,im,hfx,calcControls,parmDict)
1484    Icorr *= AbsCorr
1485    ExtCorr = GetPwdrExt(refl,im,pfx,phfx,hfx,calcControls,parmDict)
1486    Icorr *= ExtCorr
1487    return Icorr,POcorr,AbsCorr,ExtCorr
1488   
1489def GetIntensityDerv(refl,im,wave,uniq,G,g,pfx,phfx,hfx,SGData,calcControls,parmDict):
1490    'Needs a doc string'    #need powder extinction derivs!
1491    dIdsh = 1./parmDict[hfx+'Scale']
1492    dIdsp = 1./parmDict[phfx+'Scale']
1493    if 'X' in parmDict[hfx+'Type']:
1494        pola,dIdPola = G2pwd.Polarization(parmDict[hfx+'Polariz.'],refl[5+im],parmDict[hfx+'Azimuth'])
1495        dIdPola /= pola
1496    else:       #'N'
1497        dIdPola = 0.0
1498    dFdODF = {}
1499    dFdSA = [0,0,0]
1500    dIdPO = {}
1501    if pfx+'SHorder' in parmDict:
1502        odfCor,dFdODF,dFdSA = SHTXcalDerv(refl,im,g,pfx,hfx,SGData,calcControls,parmDict)
1503        for iSH in dFdODF:
1504            dFdODF[iSH] /= odfCor
1505        for i in range(3):
1506            dFdSA[i] /= odfCor
1507    elif calcControls[phfx+'poType'] == 'MD' or calcControls[phfx+'SHord']:
1508        POcorr,dIdPO = GetPrefOriDerv(refl,im,uniq,G,g,phfx,hfx,SGData,calcControls,parmDict)       
1509        for iPO in dIdPO:
1510            dIdPO[iPO] /= POcorr
1511    if 'T' in parmDict[hfx+'Type']:
1512        dFdAb = GetAbsorbDerv(refl,im,hfx,calcControls,parmDict)*wave/refl[16+im] #wave/abs corr
1513        dFdEx = GetPwdrExtDerv(refl,im,pfx,phfx,hfx,calcControls,parmDict)/refl[17+im]    #/ext corr
1514    else:
1515        dFdAb = GetAbsorbDerv(refl,im,hfx,calcControls,parmDict)*wave/refl[13+im] #wave/abs corr
1516        dFdEx = GetPwdrExtDerv(refl,im,pfx,phfx,hfx,calcControls,parmDict)/refl[14+im]    #/ext corr       
1517    return dIdsh,dIdsp,dIdPola,dIdPO,dFdODF,dFdSA,dFdAb,dFdEx
1518       
1519def GetSampleSigGam(refl,im,wave,G,GB,SGData,hfx,phfx,calcControls,parmDict):
1520    'Needs a doc string'
1521    if 'C' in calcControls[hfx+'histType']:     #All checked & OK
1522        costh = cosd(refl[5+im]/2.)
1523        #crystallite size
1524        if calcControls[phfx+'SizeType'] == 'isotropic':
1525            Sgam = 1.8*wave/(np.pi*parmDict[phfx+'Size;i']*costh)
1526        elif calcControls[phfx+'SizeType'] == 'uniaxial':
1527            H = np.array(refl[:3])
1528            P = np.array(calcControls[phfx+'SizeAxis'])
1529            cosP,sinP = G2lat.CosSinAngle(H,P,G)
1530            Sgam = (1.8*wave/np.pi)/(parmDict[phfx+'Size;i']*parmDict[phfx+'Size;a']*costh)
1531            Sgam *= np.sqrt((sinP*parmDict[phfx+'Size;a'])**2+(cosP*parmDict[phfx+'Size;i'])**2)
1532        else:           #ellipsoidal crystallites
1533            Sij =[parmDict[phfx+'Size:%d'%(i)] for i in range(6)]
1534            H = np.array(refl[:3])
1535            lenR = G2pwd.ellipseSize(H,Sij,GB)
1536            Sgam = 1.8*wave/(np.pi*costh*lenR)
1537        #microstrain               
1538        if calcControls[phfx+'MustrainType'] == 'isotropic':
1539            Mgam = 0.018*parmDict[phfx+'Mustrain;i']*tand(refl[5+im]/2.)/np.pi
1540        elif calcControls[phfx+'MustrainType'] == 'uniaxial':
1541            H = np.array(refl[:3])
1542            P = np.array(calcControls[phfx+'MustrainAxis'])
1543            cosP,sinP = G2lat.CosSinAngle(H,P,G)
1544            Si = parmDict[phfx+'Mustrain;i']
1545            Sa = parmDict[phfx+'Mustrain;a']
1546            Mgam = 0.018*Si*Sa*tand(refl[5+im]/2.)/(np.pi*np.sqrt((Si*cosP)**2+(Sa*sinP)**2))
1547        else:       #generalized - P.W. Stephens model
1548            Strms = G2spc.MustrainCoeff(refl[:3],SGData)
1549            Sum = 0
1550            for i,strm in enumerate(Strms):
1551                Sum += parmDict[phfx+'Mustrain:'+str(i)]*strm
1552            Mgam = 0.018*refl[4+im]**2*tand(refl[5+im]/2.)*np.sqrt(Sum)/np.pi
1553    elif 'T' in calcControls[hfx+'histType']:       #All checked & OK
1554        #crystallite size
1555        if calcControls[phfx+'SizeType'] == 'isotropic':    #OK
1556            Sgam = 1.e-4*parmDict[hfx+'difC']*refl[4+im]**2/parmDict[phfx+'Size;i']
1557        elif calcControls[phfx+'SizeType'] == 'uniaxial':   #OK
1558            H = np.array(refl[:3])
1559            P = np.array(calcControls[phfx+'SizeAxis'])
1560            cosP,sinP = G2lat.CosSinAngle(H,P,G)
1561            Sgam = 1.e-4*parmDict[hfx+'difC']*refl[4+im]**2/(parmDict[phfx+'Size;i']*parmDict[phfx+'Size;a'])
1562            Sgam *= np.sqrt((sinP*parmDict[phfx+'Size;a'])**2+(cosP*parmDict[phfx+'Size;i'])**2)
1563        else:           #ellipsoidal crystallites   #OK
1564            Sij =[parmDict[phfx+'Size:%d'%(i)] for i in range(6)]
1565            H = np.array(refl[:3])
1566            lenR = G2pwd.ellipseSize(H,Sij,GB)
1567            Sgam = 1.e-4*parmDict[hfx+'difC']*refl[4+im]**2/lenR
1568        #microstrain               
1569        if calcControls[phfx+'MustrainType'] == 'isotropic':    #OK
1570            Mgam = 1.e-6*parmDict[hfx+'difC']*refl[4+im]*parmDict[phfx+'Mustrain;i']
1571        elif calcControls[phfx+'MustrainType'] == 'uniaxial':   #OK
1572            H = np.array(refl[:3])
1573            P = np.array(calcControls[phfx+'MustrainAxis'])
1574            cosP,sinP = G2lat.CosSinAngle(H,P,G)
1575            Si = parmDict[phfx+'Mustrain;i']
1576            Sa = parmDict[phfx+'Mustrain;a']
1577            Mgam = 1.e-6*parmDict[hfx+'difC']*refl[4+im]*Si*Sa/np.sqrt((Si*cosP)**2+(Sa*sinP)**2)
1578        else:       #generalized - P.W. Stephens model  OK
1579            Strms = G2spc.MustrainCoeff(refl[:3],SGData)
1580            Sum = 0
1581            for i,strm in enumerate(Strms):
1582                Sum += parmDict[phfx+'Mustrain:'+str(i)]*strm
1583            Mgam = 1.e-6*parmDict[hfx+'difC']*np.sqrt(Sum)*refl[4+im]**3
1584           
1585    gam = Sgam*parmDict[phfx+'Size;mx']+Mgam*parmDict[phfx+'Mustrain;mx']
1586    sig = (Sgam*(1.-parmDict[phfx+'Size;mx']))**2+(Mgam*(1.-parmDict[phfx+'Mustrain;mx']))**2
1587    sig /= ateln2
1588    return sig,gam
1589       
1590def GetSampleSigGamDerv(refl,im,wave,G,GB,SGData,hfx,phfx,calcControls,parmDict):
1591    'Needs a doc string'
1592    gamDict = {}
1593    sigDict = {}
1594    if 'C' in calcControls[hfx+'histType']:         #All checked & OK
1595        costh = cosd(refl[5+im]/2.)
1596        tanth = tand(refl[5+im]/2.)
1597        #crystallite size derivatives
1598        if calcControls[phfx+'SizeType'] == 'isotropic':
1599            Sgam = 1.8*wave/(np.pi*parmDict[phfx+'Size;i']*costh)
1600            gamDict[phfx+'Size;i'] = -1.8*wave*parmDict[phfx+'Size;mx']/(np.pi*costh)
1601            sigDict[phfx+'Size;i'] = -3.6*Sgam*wave*(1.-parmDict[phfx+'Size;mx'])**2/(np.pi*costh*ateln2)
1602        elif calcControls[phfx+'SizeType'] == 'uniaxial':
1603            H = np.array(refl[:3])
1604            P = np.array(calcControls[phfx+'SizeAxis'])
1605            cosP,sinP = G2lat.CosSinAngle(H,P,G)
1606            Si = parmDict[phfx+'Size;i']
1607            Sa = parmDict[phfx+'Size;a']
1608            gami = 1.8*wave/(costh*np.pi*Si*Sa)
1609            sqtrm = np.sqrt((sinP*Sa)**2+(cosP*Si)**2)
1610            Sgam = gami*sqtrm
1611            dsi = gami*Si*cosP**2/sqtrm-Sgam/Si
1612            dsa = gami*Sa*sinP**2/sqtrm-Sgam/Sa
1613            gamDict[phfx+'Size;i'] = dsi*parmDict[phfx+'Size;mx']
1614            gamDict[phfx+'Size;a'] = dsa*parmDict[phfx+'Size;mx']
1615            sigDict[phfx+'Size;i'] = 2.*dsi*Sgam*(1.-parmDict[phfx+'Size;mx'])**2/ateln2
1616            sigDict[phfx+'Size;a'] = 2.*dsa*Sgam*(1.-parmDict[phfx+'Size;mx'])**2/ateln2
1617        else:           #ellipsoidal crystallites
1618            const = 1.8*wave/(np.pi*costh)
1619            Sij =[parmDict[phfx+'Size:%d'%(i)] for i in range(6)]
1620            H = np.array(refl[:3])
1621            lenR,dRdS = G2pwd.ellipseSizeDerv(H,Sij,GB)
1622            Sgam = const/lenR
1623            for i,item in enumerate([phfx+'Size:%d'%(j) for j in range(6)]):
1624                gamDict[item] = -(const/lenR**2)*dRdS[i]*parmDict[phfx+'Size;mx']
1625                sigDict[item] = -2.*Sgam*(const/lenR**2)*dRdS[i]*(1.-parmDict[phfx+'Size;mx'])**2/ateln2
1626        gamDict[phfx+'Size;mx'] = Sgam
1627        sigDict[phfx+'Size;mx'] = -2.*Sgam**2*(1.-parmDict[phfx+'Size;mx'])/ateln2
1628               
1629        #microstrain derivatives               
1630        if calcControls[phfx+'MustrainType'] == 'isotropic':
1631            Mgam = 0.018*parmDict[phfx+'Mustrain;i']*tand(refl[5+im]/2.)/np.pi
1632            gamDict[phfx+'Mustrain;i'] =  0.018*tanth*parmDict[phfx+'Mustrain;mx']/np.pi
1633            sigDict[phfx+'Mustrain;i'] =  0.036*Mgam*tanth*(1.-parmDict[phfx+'Mustrain;mx'])**2/(np.pi*ateln2)       
1634        elif calcControls[phfx+'MustrainType'] == 'uniaxial':
1635            H = np.array(refl[:3])
1636            P = np.array(calcControls[phfx+'MustrainAxis'])
1637            cosP,sinP = G2lat.CosSinAngle(H,P,G)
1638            Si = parmDict[phfx+'Mustrain;i']
1639            Sa = parmDict[phfx+'Mustrain;a']
1640            gami = 0.018*Si*Sa*tanth/np.pi
1641            sqtrm = np.sqrt((Si*cosP)**2+(Sa*sinP)**2)
1642            Mgam = gami/sqtrm
1643            dsi = -gami*Si*cosP**2/sqtrm**3
1644            dsa = -gami*Sa*sinP**2/sqtrm**3
1645            gamDict[phfx+'Mustrain;i'] = (Mgam/Si+dsi)*parmDict[phfx+'Mustrain;mx']
1646            gamDict[phfx+'Mustrain;a'] = (Mgam/Sa+dsa)*parmDict[phfx+'Mustrain;mx']
1647            sigDict[phfx+'Mustrain;i'] = 2*(Mgam/Si+dsi)*Mgam*(1.-parmDict[phfx+'Mustrain;mx'])**2/ateln2
1648            sigDict[phfx+'Mustrain;a'] = 2*(Mgam/Sa+dsa)*Mgam*(1.-parmDict[phfx+'Mustrain;mx'])**2/ateln2       
1649        else:       #generalized - P.W. Stephens model
1650            const = 0.018*refl[4+im]**2*tanth/np.pi
1651            Strms = G2spc.MustrainCoeff(refl[:3],SGData)
1652            Sum = 0
1653            for i,strm in enumerate(Strms):
1654                Sum += parmDict[phfx+'Mustrain:'+str(i)]*strm
1655                gamDict[phfx+'Mustrain:'+str(i)] = strm*parmDict[phfx+'Mustrain;mx']/2.
1656                sigDict[phfx+'Mustrain:'+str(i)] = strm*(1.-parmDict[phfx+'Mustrain;mx'])**2
1657            Mgam = const*np.sqrt(Sum)
1658            for i in range(len(Strms)):
1659                gamDict[phfx+'Mustrain:'+str(i)] *= Mgam/Sum
1660                sigDict[phfx+'Mustrain:'+str(i)] *= const**2/ateln2
1661        gamDict[phfx+'Mustrain;mx'] = Mgam
1662        sigDict[phfx+'Mustrain;mx'] = -2.*Mgam**2*(1.-parmDict[phfx+'Mustrain;mx'])/ateln2
1663    else:   #'T'OF - All checked & OK
1664        if calcControls[phfx+'SizeType'] == 'isotropic':    #OK
1665            Sgam = 1.e-4*parmDict[hfx+'difC']*refl[4+im]**2/parmDict[phfx+'Size;i']
1666            gamDict[phfx+'Size;i'] = -Sgam*parmDict[phfx+'Size;mx']/parmDict[phfx+'Size;i']
1667            sigDict[phfx+'Size;i'] = -2.*Sgam**2*(1.-parmDict[phfx+'Size;mx'])**2/(ateln2*parmDict[phfx+'Size;i'])
1668        elif calcControls[phfx+'SizeType'] == 'uniaxial':   #OK
1669            const = 1.e-4*parmDict[hfx+'difC']*refl[4+im]**2
1670            H = np.array(refl[:3])
1671            P = np.array(calcControls[phfx+'SizeAxis'])
1672            cosP,sinP = G2lat.CosSinAngle(H,P,G)
1673            Si = parmDict[phfx+'Size;i']
1674            Sa = parmDict[phfx+'Size;a']
1675            gami = const/(Si*Sa)
1676            sqtrm = np.sqrt((sinP*Sa)**2+(cosP*Si)**2)
1677            Sgam = gami*sqtrm
1678            dsi = gami*Si*cosP**2/sqtrm-Sgam/Si
1679            dsa = gami*Sa*sinP**2/sqtrm-Sgam/Sa
1680            gamDict[phfx+'Size;i'] = dsi*parmDict[phfx+'Size;mx']
1681            gamDict[phfx+'Size;a'] = dsa*parmDict[phfx+'Size;mx']
1682            sigDict[phfx+'Size;i'] = 2.*dsi*Sgam*(1.-parmDict[phfx+'Size;mx'])**2/ateln2
1683            sigDict[phfx+'Size;a'] = 2.*dsa*Sgam*(1.-parmDict[phfx+'Size;mx'])**2/ateln2
1684        else:           #OK  ellipsoidal crystallites
1685            const = 1.e-4*parmDict[hfx+'difC']*refl[4+im]**2
1686            Sij =[parmDict[phfx+'Size:%d'%(i)] for i in range(6)]
1687            H = np.array(refl[:3])
1688            lenR,dRdS = G2pwd.ellipseSizeDerv(H,Sij,GB)
1689            Sgam = const/lenR
1690            for i,item in enumerate([phfx+'Size:%d'%(j) for j in range(6)]):
1691                gamDict[item] = -(const/lenR**2)*dRdS[i]*parmDict[phfx+'Size;mx']
1692                sigDict[item] = -2.*Sgam*(const/lenR**2)*dRdS[i]*(1.-parmDict[phfx+'Size;mx'])**2/ateln2
1693        gamDict[phfx+'Size;mx'] = Sgam  #OK
1694        sigDict[phfx+'Size;mx'] = -2.*Sgam**2*(1.-parmDict[phfx+'Size;mx'])/ateln2  #OK
1695               
1696        #microstrain derivatives               
1697        if calcControls[phfx+'MustrainType'] == 'isotropic':
1698            Mgam = 1.e-6*parmDict[hfx+'difC']*refl[4+im]*parmDict[phfx+'Mustrain;i']
1699            gamDict[phfx+'Mustrain;i'] =  1.e-6*refl[4+im]*parmDict[hfx+'difC']*parmDict[phfx+'Mustrain;mx']   #OK
1700            sigDict[phfx+'Mustrain;i'] =  2.*Mgam**2*(1.-parmDict[phfx+'Mustrain;mx'])**2/(ateln2*parmDict[phfx+'Mustrain;i'])       
1701        elif calcControls[phfx+'MustrainType'] == 'uniaxial':
1702            H = np.array(refl[:3])
1703            P = np.array(calcControls[phfx+'MustrainAxis'])
1704            cosP,sinP = G2lat.CosSinAngle(H,P,G)
1705            Si = parmDict[phfx+'Mustrain;i']
1706            Sa = parmDict[phfx+'Mustrain;a']
1707            gami = 1.e-6*parmDict[hfx+'difC']*refl[4+im]*Si*Sa
1708            sqtrm = np.sqrt((Si*cosP)**2+(Sa*sinP)**2)
1709            Mgam = gami/sqtrm
1710            dsi = -gami*Si*cosP**2/sqtrm**3
1711            dsa = -gami*Sa*sinP**2/sqtrm**3
1712            gamDict[phfx+'Mustrain;i'] = (Mgam/Si+dsi)*parmDict[phfx+'Mustrain;mx']
1713            gamDict[phfx+'Mustrain;a'] = (Mgam/Sa+dsa)*parmDict[phfx+'Mustrain;mx']
1714            sigDict[phfx+'Mustrain;i'] = 2*(Mgam/Si+dsi)*Mgam*(1.-parmDict[phfx+'Mustrain;mx'])**2/ateln2
1715            sigDict[phfx+'Mustrain;a'] = 2*(Mgam/Sa+dsa)*Mgam*(1.-parmDict[phfx+'Mustrain;mx'])**2/ateln2       
1716        else:       #generalized - P.W. Stephens model OK
1717            pwrs = calcControls[phfx+'MuPwrs']
1718            Strms = G2spc.MustrainCoeff(refl[:3],SGData)
1719            const = 1.e-6*parmDict[hfx+'difC']*refl[4+im]**3
1720            Sum = 0
1721            for i,strm in enumerate(Strms):
1722                Sum += parmDict[phfx+'Mustrain:'+str(i)]*strm
1723                gamDict[phfx+'Mustrain:'+str(i)] = strm*parmDict[phfx+'Mustrain;mx']/2.
1724                sigDict[phfx+'Mustrain:'+str(i)] = strm*(1.-parmDict[phfx+'Mustrain;mx'])**2
1725            Mgam = const*np.sqrt(Sum)
1726            for i in range(len(Strms)):
1727                gamDict[phfx+'Mustrain:'+str(i)] *= Mgam/Sum
1728                sigDict[phfx+'Mustrain:'+str(i)] *= const**2/ateln2       
1729        gamDict[phfx+'Mustrain;mx'] = Mgam
1730        sigDict[phfx+'Mustrain;mx'] = -2.*Mgam**2*(1.-parmDict[phfx+'Mustrain;mx'])/ateln2
1731       
1732    return sigDict,gamDict
1733       
1734def GetReflPos(refl,im,wave,A,pfx,hfx,calcControls,parmDict):
1735    'Needs a doc string'
1736    if im:
1737        h,k,l,m = refl[:4]
1738        vec = np.array([parmDict[pfx+'mV0'],parmDict[pfx+'mV1'],parmDict[pfx+'mV2']])
1739        d = 1./np.sqrt(G2lat.calc_rDsqSS(np.array([h,k,l,m]),A,vec))
1740    else:
1741        h,k,l = refl[:3]
1742        d = 1./np.sqrt(G2lat.calc_rDsq(np.array([h,k,l]),A))
1743    refl[4+im] = d
1744    if 'C' in calcControls[hfx+'histType']:
1745        pos = 2.0*asind(wave/(2.0*d))+parmDict[hfx+'Zero']
1746        const = 9.e-2/(np.pi*parmDict[hfx+'Gonio. radius'])                  #shifts in microns
1747        if 'Bragg' in calcControls[hfx+'instType']:
1748            pos -= const*(4.*parmDict[hfx+'Shift']*cosd(pos/2.0)+ \
1749                parmDict[hfx+'Transparency']*sind(pos)*100.0)            #trans(=1/mueff) in cm
1750        else:               #Debye-Scherrer - simple but maybe not right
1751            pos -= const*(parmDict[hfx+'DisplaceX']*cosd(pos)+parmDict[hfx+'DisplaceY']*sind(pos))
1752    elif 'T' in calcControls[hfx+'histType']:
1753        pos = parmDict[hfx+'difC']*d+parmDict[hfx+'difA']*d**2+parmDict[hfx+'difB']/d+parmDict[hfx+'Zero']
1754        #do I need sample position effects - maybe?
1755    return pos
1756
1757def GetReflPosDerv(refl,im,wave,A,pfx,hfx,calcControls,parmDict):
1758    'Needs a doc string'
1759    dpr = 180./np.pi
1760    if im:
1761        h,k,l,m = refl[:4]
1762        vec = np.array([parmDict[pfx+'mV0'],parmDict[pfx+'mV1'],parmDict[pfx+'mV2']])
1763        dstsq = G2lat.calc_rDsqSS(np.array([h,k,l,m]),A,vec)
1764    else:
1765        m = 0
1766        h,k,l = refl[:3]       
1767        dstsq = G2lat.calc_rDsq(np.array([h,k,l]),A)
1768    dst = np.sqrt(dstsq)
1769    dsp = 1./dst
1770    if 'C' in calcControls[hfx+'histType']:
1771        pos = refl[5+im]-parmDict[hfx+'Zero']
1772        const = dpr/np.sqrt(1.0-wave**2*dstsq/4.0)
1773        dpdw = const*dst
1774        dpdA = np.array([h**2,k**2,l**2,h*k,h*l,k*l])*const*wave/(2.0*dst)
1775        dpdZ = 1.0
1776        dpdV = np.array([2.*h*A[0]+k*A[3]+l*A[4],2*k*A[1]+h*A[3]+l*A[5],
1777            2*l*A[2]+h*A[4]+k*A[5]])*m*const*wave/(2.0*dst)
1778        shft = 9.e-2/(np.pi*parmDict[hfx+'Gonio. radius'])                  #shifts in microns
1779        if 'Bragg' in calcControls[hfx+'instType']:
1780            dpdSh = -4.*shft*cosd(pos/2.0)
1781            dpdTr = -shft*sind(pos)*100.0
1782            return dpdA,dpdw,dpdZ,dpdSh,dpdTr,0.,0.,dpdV
1783        else:               #Debye-Scherrer - simple but maybe not right
1784            dpdXd = -shft*cosd(pos)
1785            dpdYd = -shft*sind(pos)
1786            return dpdA,dpdw,dpdZ,0.,0.,dpdXd,dpdYd,dpdV
1787    elif 'T' in calcControls[hfx+'histType']:
1788        dpdA = -np.array([h**2,k**2,l**2,h*k,h*l,k*l])*parmDict[hfx+'difC']*dsp**3/2.
1789        dpdZ = 1.0
1790        dpdDC = dsp
1791        dpdDA = dsp**2
1792        dpdDB = 1./dsp
1793        dpdV = np.array([2.*h*A[0]+k*A[3]+l*A[4],2*k*A[1]+h*A[3]+l*A[5],
1794            2*l*A[2]+h*A[4]+k*A[5]])*m**parmDict[hfx+'difC']*dsp**3/2.
1795        return dpdA,dpdZ,dpdDC,dpdDA,dpdDB,dpdV
1796           
1797def GetHStrainShift(refl,im,SGData,phfx,hfx,calcControls,parmDict):
1798    'Needs a doc string'
1799    laue = SGData['SGLaue']
1800    uniq = SGData['SGUniq']
1801    h,k,l = refl[:3]
1802    if laue in ['m3','m3m']:
1803        Dij = parmDict[phfx+'D11']*(h**2+k**2+l**2)+ \
1804            refl[4+im]**2*parmDict[phfx+'eA']*((h*k)**2+(h*l)**2+(k*l)**2)/(h**2+k**2+l**2)**2
1805    elif laue in ['6/m','6/mmm','3m1','31m','3']:
1806        Dij = parmDict[phfx+'D11']*(h**2+k**2+h*k)+parmDict[phfx+'D33']*l**2
1807    elif laue in ['3R','3mR']:
1808        Dij = parmDict[phfx+'D11']*(h**2+k**2+l**2)+parmDict[phfx+'D12']*(h*k+h*l+k*l)
1809    elif laue in ['4/m','4/mmm']:
1810        Dij = parmDict[phfx+'D11']*(h**2+k**2)+parmDict[phfx+'D33']*l**2
1811    elif laue in ['mmm']:
1812        Dij = parmDict[phfx+'D11']*h**2+parmDict[phfx+'D22']*k**2+parmDict[phfx+'D33']*l**2
1813    elif laue in ['2/m']:
1814        Dij = parmDict[phfx+'D11']*h**2+parmDict[phfx+'D22']*k**2+parmDict[phfx+'D33']*l**2
1815        if uniq == 'a':
1816            Dij += parmDict[phfx+'D23']*k*l
1817        elif uniq == 'b':
1818            Dij += parmDict[phfx+'D13']*h*l
1819        elif uniq == 'c':
1820            Dij += parmDict[phfx+'D12']*h*k
1821    else:
1822        Dij = parmDict[phfx+'D11']*h**2+parmDict[phfx+'D22']*k**2+parmDict[phfx+'D33']*l**2+ \
1823            parmDict[phfx+'D12']*h*k+parmDict[phfx+'D13']*h*l+parmDict[phfx+'D23']*k*l
1824    if 'C' in calcControls[hfx+'histType']:
1825        return -180.*Dij*refl[4+im]**2*tand(refl[5+im]/2.0)/np.pi
1826    else:
1827        return -Dij*parmDict[hfx+'difC']*refl[4+im]**2/2.
1828           
1829def GetHStrainShiftDerv(refl,im,SGData,phfx,hfx,calcControls,parmDict):
1830    'Needs a doc string'
1831    laue = SGData['SGLaue']
1832    uniq = SGData['SGUniq']
1833    h,k,l = refl[:3]
1834    if laue in ['m3','m3m']:
1835        dDijDict = {phfx+'D11':h**2+k**2+l**2,
1836            phfx+'eA':refl[4+im]**2*((h*k)**2+(h*l)**2+(k*l)**2)/(h**2+k**2+l**2)**2}
1837    elif laue in ['6/m','6/mmm','3m1','31m','3']:
1838        dDijDict = {phfx+'D11':h**2+k**2+h*k,phfx+'D33':l**2}
1839    elif laue in ['3R','3mR']:
1840        dDijDict = {phfx+'D11':h**2+k**2+l**2,phfx+'D12':h*k+h*l+k*l}
1841    elif laue in ['4/m','4/mmm']:
1842        dDijDict = {phfx+'D11':h**2+k**2,phfx+'D33':l**2}
1843    elif laue in ['mmm']:
1844        dDijDict = {phfx+'D11':h**2,phfx+'D22':k**2,phfx+'D33':l**2}
1845    elif laue in ['2/m']:
1846        dDijDict = {phfx+'D11':h**2,phfx+'D22':k**2,phfx+'D33':l**2}
1847        if uniq == 'a':
1848            dDijDict[phfx+'D23'] = k*l
1849        elif uniq == 'b':
1850            dDijDict[phfx+'D13'] = h*l
1851        elif uniq == 'c':
1852            dDijDict[phfx+'D12'] = h*k
1853    else:
1854        dDijDict = {phfx+'D11':h**2,phfx+'D22':k**2,phfx+'D33':l**2,
1855            phfx+'D12':h*k,phfx+'D13':h*l,phfx+'D23':k*l}
1856    if 'C' in calcControls[hfx+'histType']:
1857        for item in dDijDict:
1858            dDijDict[item] *= 180.0*refl[4+im]**2*tand(refl[5+im]/2.0)/np.pi
1859    else:
1860        for item in dDijDict:
1861            dDijDict[item] *= -parmDict[hfx+'difC']*refl[4+im]**3/2.
1862    return dDijDict
1863   
1864def GetDij(phfx,SGData,parmDict):
1865    HSvals = [parmDict[phfx+name] for name in G2spc.HStrainNames(SGData)]
1866    return G2spc.HStrainVals(HSvals,SGData)
1867               
1868def GetFobsSq(Histograms,Phases,parmDict,calcControls):
1869    'Needs a doc string'
1870    histoList = Histograms.keys()
1871    histoList.sort()
1872    for histogram in histoList:
1873        if 'PWDR' in histogram[:4]:
1874            Histogram = Histograms[histogram]
1875            hId = Histogram['hId']
1876            hfx = ':%d:'%(hId)
1877            Limits = calcControls[hfx+'Limits']
1878            if 'C' in calcControls[hfx+'histType']:
1879                shl = max(parmDict[hfx+'SH/L'],0.0005)
1880                Ka2 = False
1881                kRatio = 0.0
1882                if hfx+'Lam1' in parmDict.keys():
1883                    Ka2 = True
1884                    lamRatio = 360*(parmDict[hfx+'Lam2']-parmDict[hfx+'Lam1'])/(np.pi*parmDict[hfx+'Lam1'])
1885                    kRatio = parmDict[hfx+'I(L2)/I(L1)']
1886            x,y,w,yc,yb,yd = Histogram['Data']
1887            xB = np.searchsorted(x,Limits[0])
1888            xF = np.searchsorted(x,Limits[1])
1889            ymb = np.array(y-yb)
1890            ymb = np.where(ymb,ymb,1.0)
1891            ycmb = np.array(yc-yb)
1892            ratio = 1./np.where(ycmb,ycmb/ymb,1.e10)         
1893            refLists = Histogram['Reflection Lists']
1894            for phase in refLists:
1895                if phase not in Phases:     #skips deleted or renamed phases silently!
1896                    continue
1897                Phase = Phases[phase]
1898                im = 0
1899                if Phase['General']['Type'] in ['modulated','magnetic']:
1900                    im = 1
1901                pId = Phase['pId']
1902                phfx = '%d:%d:'%(pId,hId)
1903                refDict = refLists[phase]
1904                sumFo = 0.0
1905                sumdF = 0.0
1906                sumFosq = 0.0
1907                sumdFsq = 0.0
1908                sumInt = 0.0
1909                for refl in refDict['RefList']:
1910                    if 'C' in calcControls[hfx+'histType']:
1911                        yp = np.zeros_like(yb)
1912                        Wd,fmin,fmax = G2pwd.getWidthsCW(refl[5+im],refl[6+im],refl[7+im],shl)
1913                        iBeg = max(xB,np.searchsorted(x,refl[5+im]-fmin))
1914                        iFin = max(xB,min(np.searchsorted(x,refl[5+im]+fmax),xF))
1915                        iFin2 = iFin
1916                        if not iBeg+iFin:       #peak below low limit - skip peak
1917                            continue
1918                        elif not iBeg-iFin:     #peak above high limit - done
1919                            break
1920                        elif iBeg < iFin:
1921                            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
1922                            sumInt += refl[11+im]*refl[9+im]
1923                            if Ka2:
1924                                pos2 = refl[5+im]+lamRatio*tand(refl[5+im]/2.0)       # + 360/pi * Dlam/lam * tan(th)
1925                                Wd,fmin,fmax = G2pwd.getWidthsCW(pos2,refl[6+im],refl[7+im],shl)
1926                                iBeg2 = max(xB,np.searchsorted(x,pos2-fmin))
1927                                iFin2 = min(np.searchsorted(x,pos2+fmax),xF)
1928                                if iFin2 > iBeg2: 
1929                                    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
1930                                    sumInt += refl[11+im]*refl[9+im]*kRatio
1931                            refl[8+im] = np.sum(np.where(ratio[iBeg:iFin2]>0.,yp[iBeg:iFin2]*ratio[iBeg:iFin2]/(refl[11+im]*(1.+kRatio)),0.0))
1932                               
1933                    elif 'T' in calcControls[hfx+'histType']:
1934                        yp = np.zeros_like(yb)
1935                        Wd,fmin,fmax = G2pwd.getWidthsTOF(refl[5+im],refl[12+im],refl[13+im],refl[6+im],refl[7+im])
1936                        iBeg = max(xB,np.searchsorted(x,refl[5+im]-fmin))
1937                        iFin = max(xB,min(np.searchsorted(x,refl[5+im]+fmax),xF))
1938                        if iBeg < iFin:
1939                            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
1940                            refl[8+im] = np.sum(np.where(ratio[iBeg:iFin]>0.,yp[iBeg:iFin]*ratio[iBeg:iFin]/refl[11+im],0.0))
1941                            sumInt += refl[11+im]*refl[9+im]
1942                    Fo = np.sqrt(np.abs(refl[8+im]))
1943                    Fc = np.sqrt(np.abs(refl[9]+im))
1944                    sumFo += Fo
1945                    sumFosq += refl[8+im]**2
1946                    sumdF += np.abs(Fo-Fc)
1947                    sumdFsq += (refl[8+im]-refl[9+im])**2
1948                if sumFo:
1949                    Histogram['Residuals'][phfx+'Rf'] = min(100.,(sumdF/sumFo)*100.)
1950                    Histogram['Residuals'][phfx+'Rf^2'] = min(100.,np.sqrt(sumdFsq/sumFosq)*100.)
1951                else:
1952                    Histogram['Residuals'][phfx+'Rf'] = 100.
1953                    Histogram['Residuals'][phfx+'Rf^2'] = 100.
1954                Histogram['Residuals'][phfx+'sumInt'] = sumInt
1955                Histogram['Residuals'][phfx+'Nref'] = len(refDict['RefList'])
1956                Histogram['Residuals']['hId'] = hId
1957        elif 'HKLF' in histogram[:4]:
1958            Histogram = Histograms[histogram]
1959            Histogram['Residuals']['hId'] = Histograms[histogram]['hId']
1960               
1961def getPowderProfile(parmDict,x,varylist,Histogram,Phases,calcControls,pawleyLookup):
1962    'Needs a doc string'
1963   
1964    def GetReflSigGamCW(refl,im,wave,G,GB,phfx,calcControls,parmDict):
1965        U = parmDict[hfx+'U']
1966        V = parmDict[hfx+'V']
1967        W = parmDict[hfx+'W']
1968        X = parmDict[hfx+'X']
1969        Y = parmDict[hfx+'Y']
1970        tanPos = tand(refl[5+im]/2.0)
1971        Ssig,Sgam = GetSampleSigGam(refl,im,wave,G,GB,SGData,hfx,phfx,calcControls,parmDict)
1972        sig = U*tanPos**2+V*tanPos+W+Ssig     #save peak sigma
1973        sig = max(0.001,sig)
1974        gam = X/cosd(refl[5+im]/2.0)+Y*tanPos+Sgam     #save peak gamma
1975        gam = max(0.001,gam)
1976        return sig,gam
1977               
1978    def GetReflSigGamTOF(refl,im,G,GB,phfx,calcControls,parmDict):
1979        sig = parmDict[hfx+'sig-0']+parmDict[hfx+'sig-1']*refl[4+im]**2+   \
1980            parmDict[hfx+'sig-2']*refl[4+im]**4+parmDict[hfx+'sig-q']/refl[4+im]**2
1981        gam = parmDict[hfx+'X']*refl[4+im]+parmDict[hfx+'Y']*refl[4+im]**2
1982        Ssig,Sgam = GetSampleSigGam(refl,im,0.0,G,GB,SGData,hfx,phfx,calcControls,parmDict)
1983        sig += Ssig
1984        gam += Sgam
1985        return sig,gam
1986       
1987    def GetReflAlpBet(refl,im,hfx,parmDict):
1988        alp = parmDict[hfx+'alpha']/refl[4+im]
1989        bet = parmDict[hfx+'beta-0']+parmDict[hfx+'beta-1']/refl[4+im]**4+parmDict[hfx+'beta-q']/refl[4+im]**2
1990        return alp,bet
1991       
1992    hId = Histogram['hId']
1993    hfx = ':%d:'%(hId)
1994    bakType = calcControls[hfx+'bakType']
1995    yb,Histogram['sumBk'] = G2pwd.getBackground(hfx,parmDict,bakType,calcControls[hfx+'histType'],x)
1996    yc = np.zeros_like(yb)
1997    cw = np.diff(x)
1998    cw = np.append(cw,cw[-1])
1999       
2000    if 'C' in calcControls[hfx+'histType']:   
2001        shl = max(parmDict[hfx+'SH/L'],0.002)
2002        Ka2 = False
2003        if hfx+'Lam1' in parmDict.keys():
2004            wave = parmDict[hfx+'Lam1']
2005            Ka2 = True
2006            lamRatio = 360*(parmDict[hfx+'Lam2']-parmDict[hfx+'Lam1'])/(np.pi*parmDict[hfx+'Lam1'])
2007            kRatio = parmDict[hfx+'I(L2)/I(L1)']
2008        else:
2009            wave = parmDict[hfx+'Lam']
2010    for phase in Histogram['Reflection Lists']:
2011        refDict = Histogram['Reflection Lists'][phase]
2012        if phase not in Phases:     #skips deleted or renamed phases silently!
2013            continue
2014        Phase = Phases[phase]
2015        pId = Phase['pId']
2016        pfx = '%d::'%(pId)
2017        phfx = '%d:%d:'%(pId,hId)
2018        hfx = ':%d:'%(hId)
2019        SGData = Phase['General']['SGData']
2020        SGMT = np.array([ops[0].T for ops in SGData['SGOps']])
2021        im = 0
2022        if Phase['General']['Type'] in ['modulated','magnetic']:
2023            SSGData = Phase['General']['SSGData']
2024            SSGMT = np.array([ops[0].T for ops in SSGData['SSGOps']])
2025            im = 1  #offset in SS reflection list
2026            #??
2027        Dij = GetDij(phfx,SGData,parmDict)
2028        A = [parmDict[pfx+'A%d'%(i)]+Dij[i] for i in range(6)]
2029        G,g = G2lat.A2Gmat(A)       #recip & real metric tensors
2030        if np.any(np.diag(G)<0.):
2031            raise G2obj.G2Exception('invalid metric tensor \n cell/Dij refinement not advised')
2032        GA,GB = G2lat.Gmat2AB(G)    #Orthogonalization matricies
2033        Vst = np.sqrt(nl.det(G))    #V*
2034        if not Phase['General'].get('doPawley'):
2035            time0 = time.time()
2036            if im:
2037                SStructureFactor(refDict,im,G,hfx,pfx,SGData,SSGData,calcControls,parmDict)
2038            else:
2039                StructureFactor2(refDict,G,hfx,pfx,SGData,calcControls,parmDict)
2040#            print 'sf calc time: %.3fs'%(time.time()-time0)
2041        time0 = time.time()
2042        badPeak = False
2043        for iref,refl in enumerate(refDict['RefList']):
2044            if 'C' in calcControls[hfx+'histType']:
2045                if im:
2046                    h,k,l,m = refl[:4]
2047                else:
2048                    h,k,l = refl[:3]
2049                Uniq = np.inner(refl[:3],SGMT)
2050                refl[5+im] = GetReflPos(refl,im,wave,A,pfx,hfx,calcControls,parmDict)         #corrected reflection position
2051                Lorenz = 1./(2.*sind(refl[5+im]/2.)**2*cosd(refl[5+im]/2.))           #Lorentz correction
2052                refl[6+im:8+im] = GetReflSigGamCW(refl,im,wave,G,GB,phfx,calcControls,parmDict)    #peak sig & gam
2053                refl[11+im:15+im] = GetIntensityCorr(refl,im,Uniq,G,g,pfx,phfx,hfx,SGData,calcControls,parmDict)
2054                refl[11+im] *= Vst*Lorenz
2055                 
2056                if Phase['General'].get('doPawley'):
2057                    try:
2058                        if im:
2059                            pInd = pfx+'PWLref:%d'%(pawleyLookup[pfx+'%d,%d,%d,%d'%(h,k,l,m)])
2060                        else:
2061                            pInd = pfx+'PWLref:%d'%(pawleyLookup[pfx+'%d,%d,%d'%(h,k,l)])
2062                        refl[9+im] = parmDict[pInd]
2063                    except KeyError:
2064#                        print ' ***Error %d,%d,%d missing from Pawley reflection list ***'%(h,k,l)
2065                        continue
2066                Wd,fmin,fmax = G2pwd.getWidthsCW(refl[5+im],refl[6+im],refl[7+im],shl)
2067                iBeg = np.searchsorted(x,refl[5+im]-fmin)
2068                iFin = np.searchsorted(x,refl[5+im]+fmax)
2069                if not iBeg+iFin:       #peak below low limit - skip peak
2070                    continue
2071                elif not iBeg-iFin:     #peak above high limit - done
2072                    break
2073                elif iBeg > iFin:   #bad peak coeff - skip
2074                    badPeak = True
2075                    continue
2076                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
2077                if Ka2:
2078                    pos2 = refl[5+im]+lamRatio*tand(refl[5+im]/2.0)       # + 360/pi * Dlam/lam * tan(th)
2079                    Wd,fmin,fmax = G2pwd.getWidthsCW(pos2,refl[6+im],refl[7+im],shl)
2080                    iBeg = np.searchsorted(x,pos2-fmin)
2081                    iFin = np.searchsorted(x,pos2+fmax)
2082                    if not iBeg+iFin:       #peak below low limit - skip peak
2083                        continue
2084                    elif not iBeg-iFin:     #peak above high limit - done
2085                        return yc,yb
2086                    elif iBeg > iFin:   #bad peak coeff - skip
2087                        continue
2088                    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
2089            elif 'T' in calcControls[hfx+'histType']:
2090                h,k,l = refl[:3]
2091                Uniq = np.inner(refl[:3],SGMT)
2092                refl[5+im] = GetReflPos(refl,im,0.0,A,pfx,hfx,calcControls,parmDict)         #corrected reflection position
2093                Lorenz = sind(abs(parmDict[hfx+'2-theta'])/2)*refl[4+im]**4                                                #TOF Lorentz correction
2094#                refl[5+im] += GetHStrainShift(refl,im,SGData,phfx,hfx,calcControls,parmDict)               #apply hydrostatic strain shift
2095                refl[6+im:8+im] = GetReflSigGamTOF(refl,im,G,GB,phfx,calcControls,parmDict)    #peak sig & gam
2096                refl[12+im:14+im] = GetReflAlpBet(refl,im,hfx,parmDict)
2097                refl[11+im],refl[15+im],refl[16+im],refl[17+im] = GetIntensityCorr(refl,im,Uniq,G,g,pfx,phfx,hfx,SGData,calcControls,parmDict)
2098                refl[11+im] *= Vst*Lorenz
2099                if Phase['General'].get('doPawley'):
2100                    try:
2101                        if im:
2102                            pInd =pfx+'PWLref:%d'%(pawleyLookup[pfx+'%d,%d,%d,%d'%(h,k,l,m)])
2103                        else:
2104                            pInd =pfx+'PWLref:%d'%(pawleyLookup[pfx+'%d,%d,%d'%(h,k,l)])
2105                        refl[9+im] = parmDict[pInd]
2106                    except KeyError:
2107#                        print ' ***Error %d,%d,%d missing from Pawley reflection list ***'%(h,k,l)
2108                        continue
2109                Wd,fmin,fmax = G2pwd.getWidthsTOF(refl[5+im],refl[12+im],refl[13+im],refl[6+im],refl[7+im])
2110                iBeg = np.searchsorted(x,refl[5+im]-fmin)
2111                iFin = np.searchsorted(x,refl[5+im]+fmax)
2112                if not iBeg+iFin:       #peak below low limit - skip peak
2113                    continue
2114                elif not iBeg-iFin:     #peak above high limit - done
2115                    break
2116                elif iBeg > iFin:   #bad peak coeff - skip
2117                    badPeak = True
2118                    continue
2119                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]
2120#        print 'profile calc time: %.3fs'%(time.time()-time0)
2121    if badPeak:
2122        print 'ouch #4 bad profile coefficients yield negative peak width; some reflections skipped' 
2123    return yc,yb
2124   
2125def getPowderProfileDerv(parmDict,x,varylist,Histogram,Phases,rigidbodyDict,calcControls,pawleyLookup):
2126    'Needs a doc string'
2127   
2128    def cellVaryDerv(pfx,SGData,dpdA): 
2129        if SGData['SGLaue'] in ['-1',]:
2130            return [[pfx+'A0',dpdA[0]],[pfx+'A1',dpdA[1]],[pfx+'A2',dpdA[2]],
2131                [pfx+'A3',dpdA[3]],[pfx+'A4',dpdA[4]],[pfx+'A5',dpdA[5]]]
2132        elif SGData['SGLaue'] in ['2/m',]:
2133            if SGData['SGUniq'] == 'a':
2134                return [[pfx+'A0',dpdA[0]],[pfx+'A1',dpdA[1]],[pfx+'A2',dpdA[2]],[pfx+'A5',dpdA[5]]]
2135            elif SGData['SGUniq'] == 'b':
2136                return [[pfx+'A0',dpdA[0]],[pfx+'A1',dpdA[1]],[pfx+'A2',dpdA[2]],[pfx+'A4',dpdA[4]]]
2137            else:
2138                return [[pfx+'A0',dpdA[0]],[pfx+'A1',dpdA[1]],[pfx+'A2',dpdA[2]],[pfx+'A3',dpdA[3]]]
2139        elif SGData['SGLaue'] in ['mmm',]:
2140            return [[pfx+'A0',dpdA[0]],[pfx+'A1',dpdA[1]],[pfx+'A2',dpdA[2]]]
2141        elif SGData['SGLaue'] in ['4/m','4/mmm']:
2142            return [[pfx+'A0',dpdA[0]],[pfx+'A2',dpdA[2]]]
2143        elif SGData['SGLaue'] in ['6/m','6/mmm','3m1', '31m', '3']:
2144            return [[pfx+'A0',dpdA[0]],[pfx+'A2',dpdA[2]]]
2145        elif SGData['SGLaue'] in ['3R', '3mR']:
2146            return [[pfx+'A0',dpdA[0]+dpdA[1]+dpdA[2]],[pfx+'A3',dpdA[3]+dpdA[4]+dpdA[5]]]                       
2147        elif SGData['SGLaue'] in ['m3m','m3']:
2148            return [[pfx+'A0',dpdA[0]]]
2149           
2150    # create a list of dependent variables and set up a dictionary to hold their derivatives
2151    dependentVars = G2mv.GetDependentVars()
2152    depDerivDict = {}
2153    for j in dependentVars:
2154        depDerivDict[j] = np.zeros(shape=(len(x)))
2155    #print 'dependent vars',dependentVars
2156    lenX = len(x)               
2157    hId = Histogram['hId']
2158    hfx = ':%d:'%(hId)
2159    bakType = calcControls[hfx+'bakType']
2160    dMdv = np.zeros(shape=(len(varylist),len(x)))
2161    dMdb,dMddb,dMdpk = G2pwd.getBackgroundDerv(hfx,parmDict,bakType,calcControls[hfx+'histType'],x)
2162    if hfx+'Back;0' in varylist: # for now assume that Back;x vars to not appear in constraints
2163        bBpos =varylist.index(hfx+'Back;0')
2164        dMdv[bBpos:bBpos+len(dMdb)] = dMdb
2165    names = [hfx+'DebyeA',hfx+'DebyeR',hfx+'DebyeU']
2166    for name in varylist:
2167        if 'Debye' in name:
2168            id = int(name.split(';')[-1])
2169            parm = name[:int(name.rindex(';'))]
2170            ip = names.index(parm)
2171            dMdv[varylist.index(name)] = dMddb[3*id+ip]
2172    names = [hfx+'BkPkpos',hfx+'BkPkint',hfx+'BkPksig',hfx+'BkPkgam']
2173    for name in varylist:
2174        if 'BkPk' in name:
2175            parm,id = name.split(';')
2176            id = int(id)
2177            if parm in names:
2178                ip = names.index(parm)
2179                dMdv[varylist.index(name)] = dMdpk[4*id+ip]
2180    cw = np.diff(x)
2181    cw = np.append(cw,cw[-1])
2182    Ka2 = False #also for TOF!
2183    if 'C' in calcControls[hfx+'histType']:   
2184        shl = max(parmDict[hfx+'SH/L'],0.002)
2185        if hfx+'Lam1' in parmDict.keys():
2186            wave = parmDict[hfx+'Lam1']
2187            Ka2 = True
2188            lamRatio = 360*(parmDict[hfx+'Lam2']-parmDict[hfx+'Lam1'])/(np.pi*parmDict[hfx+'Lam1'])
2189            kRatio = parmDict[hfx+'I(L2)/I(L1)']
2190        else:
2191            wave = parmDict[hfx+'Lam']
2192    for phase in Histogram['Reflection Lists']:
2193        refDict = Histogram['Reflection Lists'][phase]
2194        if phase not in Phases:     #skips deleted or renamed phases silently!
2195            continue
2196        Phase = Phases[phase]
2197        SGData = Phase['General']['SGData']
2198        SGMT = np.array([ops[0].T for ops in SGData['SGOps']])
2199        im = 0
2200        if Phase['General']['Type'] in ['modulated','magnetic']:
2201            SSGData = Phase['General']['SSGData']
2202            SSGMT = np.array([ops[0].T for ops in SSGData['SSGOps']])
2203            im = 1  #offset in SS reflection list
2204            #??
2205        pId = Phase['pId']
2206        pfx = '%d::'%(pId)
2207        phfx = '%d:%d:'%(pId,hId)
2208        Dij = GetDij(phfx,SGData,parmDict)
2209        A = [parmDict[pfx+'A%d'%(i)]+Dij[i] for i in range(6)]
2210        G,g = G2lat.A2Gmat(A)       #recip & real metric tensors
2211        GA,GB = G2lat.Gmat2AB(G)    #Orthogonalization matricies
2212        if not Phase['General'].get('doPawley'):
2213            time0 = time.time()
2214            if im:
2215                dFdvDict = SStructureFactorDerv(refDict,im,G,hfx,pfx,SGData,SSGData,calcControls,parmDict)
2216            else:
2217                dFdvDict = StructureFactorDerv(refDict,G,hfx,pfx,SGData,calcControls,parmDict)
2218#            print 'sf-derv time %.3fs'%(time.time()-time0)
2219            ApplyRBModelDervs(dFdvDict,parmDict,rigidbodyDict,Phase)
2220        time0 = time.time()
2221        for iref,refl in enumerate(refDict['RefList']):
2222            if im:
2223                h,k,l,m = refl[:4]
2224            else:
2225                h,k,l = refl[:3]
2226            Uniq = np.inner(refl[:3],SGMT)
2227            if 'T' in calcControls[hfx+'histType']:
2228                wave = refl[14+im]
2229            dIdsh,dIdsp,dIdpola,dIdPO,dFdODF,dFdSA,dFdAb,dFdEx = GetIntensityDerv(refl,im,wave,Uniq,G,g,pfx,phfx,hfx,SGData,calcControls,parmDict)
2230            if 'C' in calcControls[hfx+'histType']:        #CW powder
2231                Wd,fmin,fmax = G2pwd.getWidthsCW(refl[5+im],refl[6+im],refl[7+im],shl)
2232            else: #'T'OF
2233                Wd,fmin,fmax = G2pwd.getWidthsTOF(refl[5+im],refl[12+im],refl[13+im],refl[6+im],refl[7+im])
2234            iBeg = np.searchsorted(x,refl[5+im]-fmin)
2235            iFin = np.searchsorted(x,refl[5+im]+fmax)
2236            if not iBeg+iFin:       #peak below low limit - skip peak
2237                continue
2238            elif not iBeg-iFin:     #peak above high limit - done
2239                break
2240            pos = refl[5+im]
2241            if 'C' in calcControls[hfx+'histType']:
2242                tanth = tand(pos/2.0)
2243                costh = cosd(pos/2.0)
2244                lenBF = iFin-iBeg
2245                dMdpk = np.zeros(shape=(6,lenBF))
2246                dMdipk = G2pwd.getdFCJVoigt3(refl[5+im],refl[6+im],refl[7+im],shl,ma.getdata(x[iBeg:iFin]))
2247                for i in range(5):
2248                    dMdpk[i] += 100.*cw[iBeg:iFin]*refl[11+im]*refl[9+im]*dMdipk[i]
2249                dervDict = {'int':dMdpk[0],'pos':dMdpk[1],'sig':dMdpk[2],'gam':dMdpk[3],'shl':dMdpk[4],'L1/L2':np.zeros_like(dMdpk[0])}
2250                if Ka2:
2251                    pos2 = refl[5+im]+lamRatio*tanth       # + 360/pi * Dlam/lam * tan(th)
2252                    iBeg2 = np.searchsorted(x,pos2-fmin)
2253                    iFin2 = np.searchsorted(x,pos2+fmax)
2254                    if iBeg2-iFin2:
2255                        lenBF2 = iFin2-iBeg2
2256                        dMdpk2 = np.zeros(shape=(6,lenBF2))
2257                        dMdipk2 = G2pwd.getdFCJVoigt3(pos2,refl[6+im],refl[7+im],shl,ma.getdata(x[iBeg2:iFin2]))
2258                        for i in range(5):
2259                            dMdpk2[i] = 100.*cw[iBeg2:iFin2]*refl[11+im]*refl[9+im]*kRatio*dMdipk2[i]
2260                        dMdpk2[5] = 100.*cw[iBeg2:iFin2]*refl[11+im]*dMdipk2[0]
2261                        dervDict2 = {'int':dMdpk2[0],'pos':dMdpk2[1],'sig':dMdpk2[2],'gam':dMdpk2[3],'shl':dMdpk2[4],'L1/L2':dMdpk2[5]*refl[9]}
2262            else:   #'T'OF
2263                lenBF = iFin-iBeg
2264                if lenBF < 0:   #bad peak coeff
2265                    break
2266                dMdpk = np.zeros(shape=(6,lenBF))
2267                dMdipk = G2pwd.getdEpsVoigt(refl[5+im],refl[12+im],refl[13+im],refl[6+im],refl[7+im],ma.getdata(x[iBeg:iFin]))
2268                for i in range(6):
2269                    dMdpk[i] += refl[11+im]*refl[9+im]*dMdipk[i]      #cw[iBeg:iFin]*
2270                dervDict = {'int':dMdpk[0],'pos':dMdpk[1],'alp':dMdpk[2],'bet':dMdpk[3],'sig':dMdpk[4],'gam':dMdpk[5]}           
2271            if Phase['General'].get('doPawley'):
2272                dMdpw = np.zeros(len(x))
2273                try:
2274                    if im:
2275                        pIdx = pfx+'PWLref:'+str(pawleyLookup[pfx+'%d,%d,%d,%d'%(h,k,l,m)])
2276                    else:
2277                        pIdx = pfx+'PWLref:'+str(pawleyLookup[pfx+'%d,%d,%d'%(h,k,l)])
2278                    idx = varylist.index(pIdx)
2279                    dMdpw[iBeg:iFin] = dervDict['int']/refl[9+im]
2280                    if Ka2: #not for TOF either
2281                        dMdpw[iBeg2:iFin2] += dervDict2['int']/refl[9+im]
2282                    dMdv[idx] = dMdpw
2283                except: # ValueError:
2284                    pass
2285            if 'C' in calcControls[hfx+'histType']:
2286                dpdA,dpdw,dpdZ,dpdSh,dpdTr,dpdX,dpdY,dpdV = GetReflPosDerv(refl,im,wave,A,pfx,hfx,calcControls,parmDict)
2287                names = {hfx+'Scale':[dIdsh,'int'],hfx+'Polariz.':[dIdpola,'int'],phfx+'Scale':[dIdsp,'int'],
2288                    hfx+'U':[tanth**2,'sig'],hfx+'V':[tanth,'sig'],hfx+'W':[1.0,'sig'],
2289                    hfx+'X':[1.0/costh,'gam'],hfx+'Y':[tanth,'gam'],hfx+'SH/L':[1.0,'shl'],
2290                    hfx+'I(L2)/I(L1)':[1.0,'L1/L2'],hfx+'Zero':[dpdZ,'pos'],hfx+'Lam':[dpdw,'pos'],
2291                    hfx+'Shift':[dpdSh,'pos'],hfx+'Transparency':[dpdTr,'pos'],hfx+'DisplaceX':[dpdX,'pos'],
2292                    hfx+'DisplaceY':[dpdY,'pos'],}
2293                if 'Bragg' in calcControls[hfx+'instType']:
2294                    names.update({hfx+'SurfRoughA':[dFdAb[0],'int'],
2295                        hfx+'SurfRoughB':[dFdAb[1],'int'],})
2296                else:
2297                    names.update({hfx+'Absorption':[dFdAb,'int'],})
2298            else:   #'T'OF
2299                dpdA,dpdZ,dpdDC,dpdDA,dpdDB,dpdV = GetReflPosDerv(refl,im,0.0,A,pfx,hfx,calcControls,parmDict)
2300                names = {hfx+'Scale':[dIdsh,'int'],phfx+'Scale':[dIdsp,'int'],
2301                    hfx+'difC':[dpdDC,'pos'],hfx+'difA':[dpdDA,'pos'],hfx+'difB':[dpdDB,'pos'],
2302                    hfx+'Zero':[dpdZ,'pos'],hfx+'X':[refl[4+im],'gam'],hfx+'Y':[refl[4+im]**2,'gam'],
2303                    hfx+'alpha':[1./refl[4+im],'alp'],hfx+'beta-0':[1.0,'bet'],hfx+'beta-1':[1./refl[4+im]**4,'bet'],
2304                    hfx+'beta-q':[1./refl[4+im]**2,'bet'],hfx+'sig-0':[1.0,'sig'],hfx+'sig-1':[refl[4+im]**2,'sig'],
2305                    hfx+'sig-2':[refl[4+im]**4,'sig'],hfx+'sig-q':[1./refl[4+im]**2,'sig'],
2306                    hfx+'Absorption':[dFdAb,'int'],phfx+'Extinction':[dFdEx,'int'],}
2307            for name in names:
2308                item = names[name]
2309                if name in varylist:
2310                    dMdv[varylist.index(name)][iBeg:iFin] += item[0]*dervDict[item[1]]
2311                    if Ka2 and iFin2-iBeg2:
2312                        dMdv[varylist.index(name)][iBeg2:iFin2] += item[0]*dervDict2[item[1]]
2313                elif name in dependentVars:
2314                    depDerivDict[name][iBeg:iFin] += item[0]*dervDict[item[1]]
2315                    if Ka2 and iFin2-iBeg2:
2316                        depDerivDict[name][iBeg2:iFin2] += item[0]*dervDict2[item[1]]
2317            for iPO in dIdPO:
2318                if iPO in varylist:
2319                    dMdv[varylist.index(iPO)][iBeg:iFin] += dIdPO[iPO]*dervDict['int']
2320                    if Ka2 and iFin2-iBeg2:
2321                        dMdv[varylist.index(iPO)][iBeg2:iFin2] += dIdPO[iPO]*dervDict2['int']
2322                elif iPO in dependentVars:
2323                    depDerivDict[iPO][iBeg:iFin] += dIdPO[iPO]*dervDict['int']
2324                    if Ka2 and iFin2-iBeg2:
2325                        depDerivDict[iPO][iBeg2:iFin2] += dIdPO[iPO]*dervDict2['int']
2326            for i,name in enumerate(['omega','chi','phi']):
2327                aname = pfx+'SH '+name
2328                if aname in varylist:
2329                    dMdv[varylist.index(aname)][iBeg:iFin] += dFdSA[i]*dervDict['int']
2330                    if Ka2 and iFin2-iBeg2:
2331                        dMdv[varylist.index(aname)][iBeg2:iFin2] += dFdSA[i]*dervDict2['int']
2332                elif aname in dependentVars:
2333                    depDerivDict[aname][iBeg:iFin] += dFdSA[i]*dervDict['int']
2334                    if Ka2 and iFin2-iBeg2:
2335                        depDerivDict[aname][iBeg2:iFin2] += dFdSA[i]*dervDict2['int']
2336            for iSH in dFdODF:
2337                if iSH in varylist:
2338                    dMdv[varylist.index(iSH)][iBeg:iFin] += dFdODF[iSH]*dervDict['int']
2339                    if Ka2 and iFin2-iBeg2:
2340                        dMdv[varylist.index(iSH)][iBeg2:iFin2] += dFdODF[iSH]*dervDict2['int']
2341                elif iSH in dependentVars:
2342                    depDerivDict[iSH][iBeg:iFin] += dFdODF[iSH]*dervDict['int']
2343                    if Ka2 and iFin2-iBeg2:
2344                        depDerivDict[iSH][iBeg2:iFin2] += dFdODF[iSH]*dervDict2['int']
2345            cellDervNames = cellVaryDerv(pfx,SGData,dpdA)
2346            for name,dpdA in cellDervNames:
2347                if name in varylist:
2348                    dMdv[varylist.index(name)][iBeg:iFin] += dpdA*dervDict['pos']
2349                    if Ka2 and iFin2-iBeg2:
2350                        dMdv[varylist.index(name)][iBeg2:iFin2] += dpdA*dervDict2['pos']
2351                elif name in dependentVars:
2352                    depDerivDict[name][iBeg:iFin] += dpdA*dervDict['pos']
2353                    if Ka2 and iFin2-iBeg2:
2354                        depDerivDict[name][iBeg2:iFin2] += dpdA*dervDict2['pos']
2355            dDijDict = GetHStrainShiftDerv(refl,im,SGData,phfx,hfx,calcControls,parmDict)
2356            for name in dDijDict:
2357                if name in varylist:
2358                    dMdv[varylist.index(name)][iBeg:iFin] += dDijDict[name]*dervDict['pos']
2359                    if Ka2 and iFin2-iBeg2:
2360                        dMdv[varylist.index(name)][iBeg2:iFin2] += dDijDict[name]*dervDict2['pos']
2361                elif name in dependentVars:
2362                    depDerivDict[name][iBeg:iFin] += dDijDict[name]*dervDict['pos']
2363                    if Ka2 and iFin2-iBeg2:
2364                        depDerivDict[name][iBeg2:iFin2] += dDijDict[name]*dervDict2['pos']
2365            for i,name in enumerate([pfx+'mV0',pfx+'mV1',pfx+'mV2']):
2366                if name in varylist:
2367                    dMdv[varylist.index(name)][iBeg:iFin] += dpdV[i]*dervDict['pos']
2368                    if Ka2 and iFin2-iBeg2:
2369                        dMdv[varylist.index(name)][iBeg2:iFin2] += dpdV[i]*dervDict2['pos']
2370                elif name in dependentVars:
2371                    depDerivDict[name][iBeg:iFin] += dpdV[i]*dervDict['pos']
2372                    if Ka2 and iFin2-iBeg2:
2373                        depDerivDict[name][iBeg2:iFin2] += dpdV[i]*dervDict2['pos']
2374            if 'C' in calcControls[hfx+'histType']:
2375                sigDict,gamDict = GetSampleSigGamDerv(refl,im,wave,G,GB,SGData,hfx,phfx,calcControls,parmDict)
2376            else:   #'T'OF
2377                sigDict,gamDict = GetSampleSigGamDerv(refl,im,0.0,G,GB,SGData,hfx,phfx,calcControls,parmDict)
2378            for name in gamDict:
2379                if name in varylist:
2380                    dMdv[varylist.index(name)][iBeg:iFin] += gamDict[name]*dervDict['gam']
2381                    if Ka2 and iFin2-iBeg2:
2382                        dMdv[varylist.index(name)][iBeg2:iFin2] += gamDict[name]*dervDict2['gam']
2383                elif name in dependentVars:
2384                    depDerivDict[name][iBeg:iFin] += gamDict[name]*dervDict['gam']
2385                    if Ka2 and iFin2-iBeg2:
2386                        depDerivDict[name][iBeg2:iFin2] += gamDict[name]*dervDict2['gam']
2387            for name in sigDict:
2388                if name in varylist:
2389                    dMdv[varylist.index(name)][iBeg:iFin] += sigDict[name]*dervDict['sig']
2390                    if Ka2 and iFin2-iBeg2:
2391                        dMdv[varylist.index(name)][iBeg2:iFin2] += sigDict[name]*dervDict2['sig']
2392                elif name in dependentVars:
2393                    depDerivDict[name][iBeg:iFin] += sigDict[name]*dervDict['sig']
2394                    if Ka2 and iFin2-iBeg2:
2395                        depDerivDict[name][iBeg2:iFin2] += sigDict[name]*dervDict2['sig']
2396            for name in ['BabA','BabU']:
2397                if refl[9+im]:
2398                    if phfx+name in varylist:
2399                        dMdv[varylist.index(phfx+name)][iBeg:iFin] += dFdvDict[pfx+name][iref]*dervDict['int']/refl[9+im]
2400                        if Ka2 and iFin2-iBeg2:
2401                            dMdv[varylist.index(phfx+name)][iBeg2:iFin2] += dFdvDict[pfx+name][iref]*dervDict2['int']/refl[9+im]
2402                    elif phfx+name in dependentVars:                   
2403                        depDerivDict[phfx+name][iBeg:iFin] += dFdvDict[pfx+name][iref]*dervDict['int']/refl[9+im]
2404                        if Ka2 and iFin2-iBeg2:
2405                            depDerivDict[phfx+name][iBeg2:iFin2] += dFdvDict[pfx+name][iref]*dervDict2['int']/refl[9+im]                 
2406            if not Phase['General'].get('doPawley'):
2407                #do atom derivatives -  for RB,F,X & U so far             
2408                corr = dervDict['int']/refl[9+im]
2409                if Ka2 and iFin2-iBeg2:
2410                    corr2 = dervDict2['int']/refl[9+im]
2411                for name in varylist+dependentVars:
2412                    if '::RBV;' in name:
2413                        pass
2414                    else:
2415                        try:
2416                            aname = name.split(pfx)[1][:2]
2417                            if aname not in ['Af','dA','AU','RB']: continue # skip anything not an atom or rigid body param
2418                        except IndexError:
2419                            continue
2420                    if name in varylist:
2421                        dMdv[varylist.index(name)][iBeg:iFin] += dFdvDict[name][iref]*corr
2422                        if Ka2 and iFin2-iBeg2:
2423                            dMdv[varylist.index(name)][iBeg2:iFin2] += dFdvDict[name][iref]*corr2
2424                    elif name in dependentVars:
2425                        depDerivDict[name][iBeg:iFin] += dFdvDict[name][iref]*corr
2426                        if Ka2 and iFin2-iBeg2:
2427                            depDerivDict[name][iBeg2:iFin2] += dFdvDict[name][iref]*corr2
2428    #        print 'profile derv time: %.3fs'%(time.time()-time0)
2429    # now process derivatives in constraints
2430    G2mv.Dict2Deriv(varylist,depDerivDict,dMdv)
2431    return dMdv
2432   
2433def UserRejectHKL(ref,im,userReject):
2434    if ref[5+im]/ref[6+im] < userReject['minF/sig']:
2435        return False
2436    elif userReject['MaxD'] < ref[4+im] > userReject['MinD']:
2437        return False
2438    elif ref[11+im] < userReject['MinExt']:
2439        return False
2440    elif abs(ref[5+im]-ref[7+im])/ref[6+im] > userReject['MaxDF/F']:
2441        return False
2442    return True
2443   
2444def dervHKLF(Histogram,Phase,calcControls,varylist,parmDict,rigidbodyDict):
2445    '''Loop over reflections in a HKLF histogram and compute derivatives of the fitting
2446    model (M) with respect to all parameters.  Independent and dependant dM/dp arrays
2447    are returned to either dervRefine or HessRefine.
2448
2449    :returns:
2450    '''
2451    nobs = Histogram['Residuals']['Nobs']
2452    hId = Histogram['hId']
2453    hfx = ':%d:'%(hId)
2454    pfx = '%d::'%(Phase['pId'])
2455    phfx = '%d:%d:'%(Phase['pId'],hId)
2456    SGData = Phase['General']['SGData']
2457    im = 0
2458    if Phase['General']['Type'] in ['modulated','magnetic']:
2459        SSGData = Phase['General']['SSGData']
2460        SSGMT = np.array([ops[0].T for ops in SSGData['SSGOps']])
2461        im = 1  #offset in SS reflection list
2462    A = [parmDict[pfx+'A%d'%(i)] for i in range(6)]
2463    G,g = G2lat.A2Gmat(A)       #recip & real metric tensors
2464    refDict = Histogram['Data']
2465    if parmDict[phfx+'Scale'] < 0.:
2466        parmDict[phfx+'Scale'] = .001
2467    if im:
2468        dFdvDict = SStructureFactorDerv(refDict,im,G,hfx,pfx,SGData,SSGData,calcControls,parmDict)
2469    else:
2470        dFdvDict = StructureFactorDerv(refDict,G,hfx,pfx,SGData,calcControls,parmDict)
2471    ApplyRBModelDervs(dFdvDict,parmDict,rigidbodyDict,Phase)
2472    dMdvh = np.zeros((len(varylist),len(refDict['RefList'])))
2473    dependentVars = G2mv.GetDependentVars()
2474    depDerivDict = {}
2475    for j in dependentVars:
2476        depDerivDict[j] = np.zeros(shape=(len(refDict['RefList'])))
2477    wdf = np.zeros(len(refDict['RefList']))
2478    if calcControls['F**2']:
2479        for iref,ref in enumerate(refDict['RefList']):
2480            if ref[6+im] > 0:
2481                dervDict,dervCor = SCExtinction(ref,im,phfx,hfx,pfx,calcControls,parmDict,varylist+dependentVars)[1:]
2482                w = 1.0/ref[6+im]
2483                if ref[3+im] > 0:
2484                    wdf[iref] = w*(ref[5+im]-ref[7+im])
2485                    for j,var in enumerate(varylist):
2486                        if var in dFdvDict:
2487                            dMdvh[j][iref] = w*dFdvDict[var][iref]*parmDict[phfx+'Scale']*ref[11+im]
2488                    for var in dependentVars:
2489                        if var in dFdvDict:
2490                            depDerivDict[var][iref] = w*dFdvDict[var][iref]*parmDict[phfx+'Scale']*ref[11+im]
2491                    if phfx+'Scale' in varylist:
2492                        dMdvh[varylist.index(phfx+'Scale')][iref] = w*ref[7+im]*ref[11+im]/parmDict[phfx+'Scale']  #OK
2493                    elif phfx+'Scale' in dependentVars:
2494                        depDerivDict[phfx+'Scale'][iref] = w*ref[7+im]*ref[11+im]/parmDict[phfx+'Scale']   #OK
2495                    for item in ['Ep','Es','Eg']:
2496                        if phfx+item in varylist and phfx+item in dervDict:
2497                            dMdvh[varylist.index(phfx+item)][iref] = w*dervDict[phfx+item]/ref[11+im]  #OK
2498                        elif phfx+item in dependentVars and phfx+item in dervDict:
2499                            depDerivDict[phfx+item][iref] = w*dervDict[phfx+item]/ref[11+im]  #OK
2500                    for item in ['BabA','BabU']:
2501                        if phfx+item in varylist:
2502                            dMdvh[varylist.index(phfx+item)][iref] = w*dFdvDict[pfx+item][iref]*parmDict[phfx+'Scale']*ref[11+im]
2503                        elif phfx+item in dependentVars:
2504                            depDerivDict[phfx+item][iref] = w*dFdvDict[pfx+item][iref]*parmDict[phfx+'Scale']*ref[11+im]
2505    else:   #F refinement
2506        for iref,ref in enumerate(refDict['RefList']):
2507            if ref[5+im] > 0.:
2508                dervDict,dervCor = SCExtinction(ref,im,phfx,hfx,pfx,calcControls,parmDict,varylist+dependentVars)[1:]
2509                Fo = np.sqrt(ref[5+im])
2510                Fc = np.sqrt(ref[7+im])
2511                w = 1.0/ref[6+im]
2512                if ref[3+im] > 0:
2513                    wdf[iref] = 2.0*Fc*w*(Fo-Fc)
2514                    for j,var in enumerate(varylist):
2515                        if var in dFdvDict:
2516                            dMdvh[j][iref] = w*dFdvDict[var][iref]*parmDict[phfx+'Scale']*ref[11+im]
2517                    for var in dependentVars:
2518                        if var in dFdvDict:
2519                            depDerivDict[var][iref] = w*dFdvDict[var][iref]*parmDict[phfx+'Scale']*ref[11+im]
2520                    if phfx+'Scale' in varylist:
2521                        dMdvh[varylist.index(phfx+'Scale')][iref] = w*ref[7+im]*ref[11+im]/parmDict[phfx+'Scale']  #OK
2522                    elif phfx+'Scale' in dependentVars:
2523                        depDerivDict[phfx+'Scale'][iref] = w*ref[7+im]*ref[11+im]/parmDict[phfx+'Scale']   #OK                   
2524                    for item in ['Ep','Es','Eg']:   #OK!
2525                        if phfx+item in varylist and phfx+item in dervDict:
2526                            dMdvh[varylist.index(phfx+item)][iref] = w*dervDict[phfx+item]/ref[11+im] 
2527                        elif phfx+item in dependentVars and phfx+item in dervDict:
2528                            depDerivDict[phfx+item][iref] = w*dervDict[phfx+item]/ref[11+im]
2529                    for item in ['BabA','BabU']:
2530                        if phfx+item in varylist:
2531                            dMdvh[varylist.index(phfx+item)][iref] = w*dFdvDict[pfx+item][iref]*parmDict[phfx+'Scale']*ref[11+im]
2532                        elif phfx+item in dependentVars:
2533                            depDerivDict[phfx+item][iref] = w*dFdvDict[pfx+item][iref]*parmDict[phfx+'Scale']*ref[11+im]
2534    return dMdvh,depDerivDict,wdf
2535   
2536
2537def dervRefine(values,HistoPhases,parmDict,varylist,calcControls,pawleyLookup,dlg):
2538    '''Loop over histograms and compute derivatives of the fitting
2539    model (M) with respect to all parameters.  Results are returned in
2540    a Jacobian matrix (aka design matrix) of dimensions (n by m) where
2541    n is the number of parameters and m is the number of data
2542    points. This can exceed memory when m gets large. This routine is
2543    used when refinement derivatives are selected as "analtytic
2544    Jacobian" in Controls.
2545
2546    :returns: Jacobian numpy.array dMdv for all histograms concatinated
2547    '''
2548    parmDict.update(zip(varylist,values))
2549    G2mv.Dict2Map(parmDict,varylist)
2550    Histograms,Phases,restraintDict,rigidbodyDict = HistoPhases
2551    nvar = len(varylist)
2552    dMdv = np.empty(0)
2553    histoList = Histograms.keys()
2554    histoList.sort()
2555    for histogram in histoList:
2556        if 'PWDR' in histogram[:4]:
2557            Histogram = Histograms[histogram]
2558            hId = Histogram['hId']
2559            hfx = ':%d:'%(hId)
2560            wtFactor = calcControls[hfx+'wtFactor']
2561            Limits = calcControls[hfx+'Limits']
2562            x,y,w,yc,yb,yd = Histogram['Data']
2563            xB = np.searchsorted(x,Limits[0])
2564            xF = np.searchsorted(x,Limits[1])
2565            dMdvh = np.sqrt(w[xB:xF])*getPowderProfileDerv(parmDict,x[xB:xF],
2566                varylist,Histogram,Phases,rigidbodyDict,calcControls,pawleyLookup)
2567        elif 'HKLF' in histogram[:4]:
2568            Histogram = Histograms[histogram]
2569            phase = Histogram['Reflection Lists']
2570            Phase = Phases[phase]
2571            dMdvh,depDerivDict,wdf = dervHKLF(Histogram,Phase,calcControls,varylist,parmDict,rigidbodyDict)
2572            hfx = ':%d:'%(Histogram['hId'])
2573            wtFactor = calcControls[hfx+'wtFactor']
2574            # now process derivatives in constraints
2575            G2mv.Dict2Deriv(varylist,depDerivDict,dMdvh)
2576        else:
2577            continue        #skip non-histogram entries
2578        if len(dMdv):
2579            dMdv = np.concatenate((dMdv.T,np.sqrt(wtFactor)*dMdvh.T)).T
2580        else:
2581            dMdv = np.sqrt(wtFactor)*dMdvh
2582           
2583    pNames,pVals,pWt,pWsum = penaltyFxn(HistoPhases,calcControls,parmDict,varylist)
2584    if np.any(pVals):
2585        dpdv = penaltyDeriv(pNames,pVals,HistoPhases,calcControls,parmDict,varylist)
2586        dMdv = np.concatenate((dMdv.T,(np.sqrt(pWt)*dpdv).T)).T
2587       
2588    return dMdv
2589
2590def HessRefine(values,HistoPhases,parmDict,varylist,calcControls,pawleyLookup,dlg):
2591    '''Loop over histograms and compute derivatives of the fitting
2592    model (M) with respect to all parameters.  For each histogram, the
2593    Jacobian matrix, dMdv, with dimensions (n by m) where n is the
2594    number of parameters and m is the number of data points *in the
2595    histogram*. The (n by n) Hessian is computed from each Jacobian
2596    and it is returned.  This routine is used when refinement
2597    derivatives are selected as "analtytic Hessian" in Controls.
2598
2599    :returns: Vec,Hess where Vec is the least-squares vector and Hess is the Hessian
2600    '''
2601    parmDict.update(zip(varylist,values))
2602    G2mv.Dict2Map(parmDict,varylist)
2603    Histograms,Phases,restraintDict,rigidbodyDict = HistoPhases
2604    #fixup H atom positions here?
2605    ApplyRBModels(parmDict,Phases,rigidbodyDict)        #,Update=True??
2606    nvar = len(varylist)
2607    Hess = np.empty(0)
2608    histoList = Histograms.keys()
2609    histoList.sort()
2610    for histogram in histoList:
2611        if 'PWDR' in histogram[:4]:
2612            Histogram = Histograms[histogram]
2613            hId = Histogram['hId']
2614            hfx = ':%d:'%(hId)
2615            wtFactor = calcControls[hfx+'wtFactor']
2616            Limits = calcControls[hfx+'Limits']
2617            x,y,w,yc,yb,yd = Histogram['Data']
2618            W = wtFactor*w
2619            dy = y-yc
2620            xB = np.searchsorted(x,Limits[0])
2621            xF = np.searchsorted(x,Limits[1])
2622            dMdvh = getPowderProfileDerv(parmDict,x[xB:xF],
2623                varylist,Histogram,Phases,rigidbodyDict,calcControls,pawleyLookup)
2624            Wt = ma.sqrt(W[xB:xF])[np.newaxis,:]
2625            Dy = dy[xB:xF][np.newaxis,:]
2626            dMdvh *= Wt
2627            if dlg:
2628                dlg.Update(Histogram['Residuals']['wR'],newmsg='Hessian for histogram %d\nAll data Rw=%8.3f%s'%(hId,Histogram['Residuals']['wR'],'%'))
2629            if len(Hess):
2630                Hess += np.inner(dMdvh,dMdvh)
2631                dMdvh *= Wt*Dy
2632                Vec += np.sum(dMdvh,axis=1)
2633            else:
2634                Hess = np.inner(dMdvh,dMdvh)
2635                dMdvh *= Wt*Dy
2636                Vec = np.sum(dMdvh,axis=1)
2637        elif 'HKLF' in histogram[:4]:
2638            Histogram = Histograms[histogram]
2639            phase = Histogram['Reflection Lists']
2640            Phase = Phases[phase]
2641            dMdvh,depDerivDict,wdf = dervHKLF(Histogram,Phase,calcControls,varylist,parmDict,rigidbodyDict)
2642            hId = Histogram['hId']
2643            hfx = ':%d:'%(Histogram['hId'])
2644            wtFactor = calcControls[hfx+'wtFactor']
2645            # now process derivatives in constraints
2646            G2mv.Dict2Deriv(varylist,depDerivDict,dMdvh)
2647#            print 'matrix build time: %.3f'%(time.time()-time0)
2648
2649            if dlg:
2650                dlg.Update(Histogram['Residuals']['wR'],newmsg='Hessian for histogram %d Rw=%8.3f%s'%(hId,Histogram['Residuals']['wR'],'%'))[0]
2651            if len(Hess):
2652                Vec += wtFactor*np.sum(dMdvh*wdf,axis=1)
2653                Hess += wtFactor*np.inner(dMdvh,dMdvh)
2654            else:
2655                Vec = wtFactor*np.sum(dMdvh*wdf,axis=1)
2656                Hess = wtFactor*np.inner(dMdvh,dMdvh)
2657        else:
2658            continue        #skip non-histogram entries
2659    pNames,pVals,pWt,pWsum = penaltyFxn(HistoPhases,calcControls,parmDict,varylist)
2660    if np.any(pVals):
2661        dpdv = penaltyDeriv(pNames,pVals,HistoPhases,calcControls,parmDict,varylist)
2662        Vec += np.sum(dpdv*pWt*pVals,axis=1)
2663        Hess += np.inner(dpdv*pWt,dpdv)
2664    return Vec,Hess
2665
2666def errRefine(values,HistoPhases,parmDict,varylist,calcControls,pawleyLookup,dlg=None):       
2667    '''Computes the point-by-point discrepancies between every data point in every histogram
2668    and the observed value
2669   
2670    :returns: an np array of differences between observed and computed diffraction values.
2671    '''
2672    Values2Dict(parmDict, varylist, values)
2673    G2mv.Dict2Map(parmDict,varylist)
2674    Histograms,Phases,restraintDict,rigidbodyDict = HistoPhases
2675    M = np.empty(0)
2676    SumwYo = 0
2677    Nobs = 0
2678    Nrej = 0
2679    Next = 0
2680    ApplyRBModels(parmDict,Phases,rigidbodyDict)
2681    #fixup Hatom positions here....
2682    histoList = Histograms.keys()
2683    histoList.sort()
2684    for histogram in histoList:
2685        if 'PWDR' in histogram[:4]:
2686            Histogram = Histograms[histogram]
2687            hId = Histogram['hId']
2688            hfx = ':%d:'%(hId)
2689            wtFactor = calcControls[hfx+'wtFactor']
2690            Limits = calcControls[hfx+'Limits']
2691            x,y,w,yc,yb,yd = Histogram['Data']
2692            yc *= 0.0                           #zero full calcd profiles
2693            yb *= 0.0
2694            yd *= 0.0
2695            xB = np.searchsorted(x,Limits[0])
2696            xF = np.searchsorted(x,Limits[1])
2697            yc[xB:xF],yb[xB:xF] = getPowderProfile(parmDict,x[xB:xF],
2698                varylist,Histogram,Phases,calcControls,pawleyLookup)
2699            yc[xB:xF] += yb[xB:xF]
2700            if not np.any(y):                   #fill dummy data
2701                rv = st.poisson(yc[xB:xF])
2702                y[xB:xF] = rv.rvs()
2703                Z = np.ones_like(yc[xB:xF])
2704                Z[1::2] *= -1
2705                y[xB:xF] = yc[xB:xF]+np.abs(y[xB:xF]-yc[xB:xF])*Z
2706                w[xB:xF] = np.where(y[xB:xF]>0.,1./y[xB:xF],1.0)
2707            yd[xB:xF] = y[xB:xF]-yc[xB:xF]
2708            W = wtFactor*w
2709            wdy = -ma.sqrt(W[xB:xF])*(yd[xB:xF])
2710            Histogram['Residuals']['Nobs'] = ma.count(x[xB:xF])
2711            Nobs += Histogram['Residuals']['Nobs']
2712            Histogram['Residuals']['sumwYo'] = ma.sum(W[xB:xF]*y[xB:xF]**2)
2713            SumwYo += Histogram['Residuals']['sumwYo']
2714            Histogram['Residuals']['R'] = min(100.,ma.sum(ma.abs(yd[xB:xF]))/ma.sum(y[xB:xF])*100.)
2715            Histogram['Residuals']['wR'] = min(100.,ma.sqrt(ma.sum(wdy**2)/Histogram['Residuals']['sumwYo'])*100.)
2716            sumYmB = ma.sum(ma.where(yc[xB:xF]!=yb[xB:xF],ma.abs(y[xB:xF]-yb[xB:xF]),0.))
2717            sumwYmB2 = ma.sum(ma.where(yc[xB:xF]!=yb[xB:xF],W[xB:xF]*(y[xB:xF]-yb[xB:xF])**2,0.))
2718            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.))
2719            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.))
2720            Histogram['Residuals']['Rb'] = min(100.,100.*sumYB/sumYmB)
2721            Histogram['Residuals']['wRb'] = min(100.,100.*ma.sqrt(sumwYB2/sumwYmB2))
2722            Histogram['Residuals']['wRmin'] = min(100.,100.*ma.sqrt(Histogram['Residuals']['Nobs']/Histogram['Residuals']['sumwYo']))
2723            if dlg:
2724                dlg.Update(Histogram['Residuals']['wR'],newmsg='For histogram %d Rw=%8.3f%s'%(hId,Histogram['Residuals']['wR'],'%'))[0]
2725            M = np.concatenate((M,wdy))
2726#end of PWDR processing
2727        elif 'HKLF' in histogram[:4]:
2728            Histogram = Histograms[histogram]
2729            Histogram['Residuals'] = {}
2730            phase = Histogram['Reflection Lists']
2731            Phase = Phases[phase]
2732            hId = Histogram['hId']
2733            hfx = ':%d:'%(hId)
2734            wtFactor = calcControls[hfx+'wtFactor']
2735            pfx = '%d::'%(Phase['pId'])
2736            phfx = '%d:%d:'%(Phase['pId'],hId)
2737            SGData = Phase['General']['SGData']
2738            im = 0
2739            if parmDict[phfx+'Scale'] < 0.:
2740                parmDict[phfx+'Scale'] = .001               
2741            if Phase['General']['Type'] in ['modulated','magnetic']:
2742                SSGData = Phase['General']['SSGData']
2743                SSGMT = np.array([ops[0].T for ops in SSGData['SSGOps']])
2744                im = 1  #offset in SS reflection list
2745            A = [parmDict[pfx+'A%d'%(i)] for i in range(6)]
2746            G,g = G2lat.A2Gmat(A)       #recip & real metric tensors
2747            refDict = Histogram['Data']
2748            time0 = time.time()
2749            if im:
2750                SStructureFactor(refDict,im,G,hfx,pfx,SGData,SSGData,calcControls,parmDict)
2751            else:
2752                StructureFactor2(refDict,G,hfx,pfx,SGData,calcControls,parmDict)
2753#            print 'sf-calc time: %.3f'%(time.time()-time0)
2754            df = np.zeros(len(refDict['RefList']))
2755            sumwYo = 0
2756            sumFo = 0
2757            sumFo2 = 0
2758            sumdF = 0
2759            sumdF2 = 0
2760            nobs = 0
2761            nrej = 0
2762            next = 0
2763            if calcControls['F**2']:
2764                for i,ref in enumerate(refDict['RefList']):
2765                    if ref[6+im] > 0:
2766                        ref[11+im] = SCExtinction(ref,im,phfx,hfx,pfx,calcControls,parmDict,varylist)[0]
2767                        w = 1.0/ref[6+im]   # 1/sig(F^2)
2768                        ref[7+im] *= parmDict[phfx+'Scale']*ref[11+im]  #correct Fc^2 for extinction
2769                        ref[8+im] = ref[5+im]/(parmDict[phfx+'Scale']*ref[11+im])
2770                        if UserRejectHKL(ref,im,calcControls['UsrReject']) and ref[3+im]:    #skip sp.gp. absences (mul=0)
2771                            ref[3+im] = abs(ref[3+im])      #mark as allowed
2772                            Fo = np.sqrt(ref[5+im])
2773                            sumFo += Fo
2774                            sumFo2 += ref[5+im]
2775                            sumdF += abs(Fo-np.sqrt(ref[7+im]))
2776                            sumdF2 += abs(ref[5+im]-ref[7+im])
2777                            nobs += 1
2778                            df[i] = -w*(ref[5+im]-ref[7+im])
2779                            sumwYo += (w*ref[5+im])**2      #w*Fo^2
2780                        else:
2781                            if ref[3+im]:
2782                                ref[3+im] = -abs(ref[3+im])      #mark as rejected
2783                                nrej += 1
2784                            else:   #sp.gp.extinct
2785                                next += 1
2786            else:
2787                for i,ref in enumerate(refDict['RefList']):
2788                    if ref[5+im] > 0.:
2789                        ref[11+im] = SCExtinction(ref,im,phfx,hfx,pfx,calcControls,parmDict,varylist)[0]
2790                        ref[7+im] *= parmDict[phfx+'Scale']*ref[11+im]    #correct Fc^2 for extinction
2791                        ref[8+im] = ref[5+im]/(parmDict[phfx+'Scale']*ref[11+im])
2792                        Fo = np.sqrt(ref[5+im])
2793                        Fc = np.sqrt(ref[7+im])
2794                        w = 2.0*Fo/ref[6+im]    # 1/sig(F)?
2795                        if UserRejectHKL(ref,im,calcControls['UsrReject']) and ref[3+im]:    #skip sp.gp. absences (mul=0)
2796                            ref[3+im] = abs(ref[3+im])      #mark as allowed
2797                            sumFo += Fo
2798                            sumFo2 += ref[5+im]
2799                            sumdF += abs(Fo-Fc)
2800                            sumdF2 += abs(ref[5+im]-ref[7+im])
2801                            nobs += 1
2802                            df[i] = -w*(Fo-Fc)
2803                            sumwYo += (w*Fo)**2
2804                        else:
2805                            if ref[3+im]:
2806                                ref[3+im] = -abs(ref[3+im])      #mark as rejected
2807                                nrej += 1
2808                            else:   #sp.gp.extinct
2809                                next += 1
2810            Histogram['Residuals']['Nobs'] = nobs
2811            Histogram['Residuals']['sumwYo'] = sumwYo
2812            SumwYo += sumwYo
2813            Histogram['Residuals']['wR'] = min(100.,np.sqrt(np.sum(df**2)/sumwYo)*100.)
2814            Histogram['Residuals'][phfx+'Rf'] = 100.*sumdF/sumFo
2815            Histogram['Residuals'][phfx+'Rf^2'] = 100.*sumdF2/sumFo2
2816            Histogram['Residuals'][phfx+'Nref'] = nobs
2817            Histogram['Residuals'][phfx+'Nrej'] = nrej
2818            Histogram['Residuals'][phfx+'Next'] = next
2819            Nobs += nobs
2820            Nrej += nrej
2821            Next += next
2822            if dlg:
2823                dlg.Update(Histogram['Residuals']['wR'],newmsg='For histogram %d Rw=%8.3f%s'%(hId,Histogram['Residuals']['wR'],'%'))[0]
2824            M = np.concatenate((M,wtFactor*df))
2825# end of HKLF processing
2826    Histograms['sumwYo'] = SumwYo
2827    Histograms['Nobs'] = Nobs
2828    Histograms['Nrej'] = Nrej
2829    Histograms['Next'] = Next
2830    Rw = min(100.,np.sqrt(np.sum(M**2)/SumwYo)*100.)
2831    if dlg:
2832        GoOn = dlg.Update(Rw,newmsg='%s%8.3f%s'%('All data Rw =',Rw,'%'))[0]
2833        if not GoOn:
2834            parmDict['saved values'] = values
2835            dlg.Destroy()
2836            raise G2obj.G2Exception('User abort')         #Abort!!
2837    pDict,pVals,pWt,pWsum = penaltyFxn(HistoPhases,calcControls,parmDict,varylist)
2838    if len(pVals):
2839        pSum = np.sum(pWt*pVals**2)
2840        for name in pWsum:
2841            if pWsum[name]:
2842                print '  Penalty function for %8s = %12.5g'%(name,pWsum[name])
2843        print 'Total penalty function: %12.5g on %d terms'%(pSum,len(pVals))
2844        Nobs += len(pVals)
2845        M = np.concatenate((M,np.sqrt(pWt)*pVals))
2846    return M
2847                       
Note: See TracBrowser for help on using the repository browser.