source: trunk/GSASIIstrMath.py @ 1988

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

fix atom id problem in AddRestraints?
refactor Modulation & ModulationDerv? to remove expModInt
fix AtomRefine?
fix Uij derivative in SS problems

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