source: trunk/GSASIIstrMath.py @ 1864

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

revise single crystal derivatives - now same as for old GSAS
Scale & extinction parms - good derivs for Uiso, F & F2 refinement
X,Y,Z 7 Uij approx. correct. Still some variation from numeric vals.

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