source: trunk/GSASIIstrMath.py @ 1604

Last change on this file since 1604 was 1604, checked in by vondreele, 9 years ago

make modulation wave maps
fix atom index bugs
begin modulated structure imput to least squares

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