source: trunk/GSASIIstrMath.py @ 2238

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

fix bug - Mustrain: should be Mustrain; everywhere

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 219.6 KB
Line 
1# -*- coding: utf-8 -*-
2'''
3*GSASIIstrMath - structure math routines*
4-----------------------------------------
5'''
6########### SVN repository information ###################
7# $Date: 2016-02-23 16:20:56 +0000 (Tue, 23 Feb 2016) $
8# $Author: vondreele $
9# $Revision: 2155 $
10# $URL: trunk/GSASIIstrMath.py $
11# $Id: GSASIIstrMath.py 2155 2016-02-23 16:20:56Z 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: 2155 $")
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
40nxs = np.newaxis
41
42################################################################################
43##### Rigid Body Models
44################################################################################
45       
46def ApplyRBModels(parmDict,Phases,rigidbodyDict,Update=False):
47    ''' Takes RB info from RBModels in Phase and RB data in rigidbodyDict along with
48    current RB values in parmDict & modifies atom contents (xyz & Uij) of parmDict
49    '''
50    atxIds = ['Ax:','Ay:','Az:']
51    atuIds = ['AU11:','AU22:','AU33:','AU12:','AU13:','AU23:']
52    RBIds = rigidbodyDict.get('RBIds',{'Vector':[],'Residue':[]})  #these are lists of rbIds
53    if not RBIds['Vector'] and not RBIds['Residue']:
54        return
55    VRBIds = RBIds['Vector']
56    RRBIds = RBIds['Residue']
57    if Update:
58        RBData = rigidbodyDict
59    else:
60        RBData = copy.deepcopy(rigidbodyDict)     # don't mess with original!
61    if RBIds['Vector']:                       # first update the vector magnitudes
62        VRBData = RBData['Vector']
63        for i,rbId in enumerate(VRBIds):
64            if VRBData[rbId]['useCount']:
65                for j in range(len(VRBData[rbId]['VectMag'])):
66                    name = '::RBV;'+str(j)+':'+str(i)
67                    VRBData[rbId]['VectMag'][j] = parmDict[name]
68    for phase in Phases:
69        Phase = Phases[phase]
70        General = Phase['General']
71        cx,ct,cs,cia = General['AtomPtrs']
72        cell = General['Cell'][1:7]
73        Amat,Bmat = G2lat.cell2AB(cell)
74        AtLookup = G2mth.FillAtomLookUp(Phase['Atoms'],cia+8)
75        pfx = str(Phase['pId'])+'::'
76        if Update:
77            RBModels = Phase['RBModels']
78        else:
79            RBModels =  copy.deepcopy(Phase['RBModels']) # again don't mess with original!
80        for irb,RBObj in enumerate(RBModels.get('Vector',[])):
81            jrb = VRBIds.index(RBObj['RBId'])
82            rbsx = str(irb)+':'+str(jrb)
83            for i,px in enumerate(['RBVPx:','RBVPy:','RBVPz:']):
84                RBObj['Orig'][0][i] = parmDict[pfx+px+rbsx]
85            for i,po in enumerate(['RBVOa:','RBVOi:','RBVOj:','RBVOk:']):
86                RBObj['Orient'][0][i] = parmDict[pfx+po+rbsx]
87            RBObj['Orient'][0] = G2mth.normQ(RBObj['Orient'][0])
88            TLS = RBObj['ThermalMotion']
89            if 'T' in TLS[0]:
90                for i,pt in enumerate(['RBVT11:','RBVT22:','RBVT33:','RBVT12:','RBVT13:','RBVT23:']):
91                    TLS[1][i] = parmDict[pfx+pt+rbsx]
92            if 'L' in TLS[0]:
93                for i,pt in enumerate(['RBVL11:','RBVL22:','RBVL33:','RBVL12:','RBVL13:','RBVL23:']):
94                    TLS[1][i+6] = parmDict[pfx+pt+rbsx]
95            if 'S' in TLS[0]:
96                for i,pt in enumerate(['RBVS12:','RBVS13:','RBVS21:','RBVS23:','RBVS31:','RBVS32:','RBVSAA:','RBVSBB:']):
97                    TLS[1][i+12] = parmDict[pfx+pt+rbsx]
98            if 'U' in TLS[0]:
99                TLS[1][0] = parmDict[pfx+'RBVU:'+rbsx]
100            XYZ,Cart = G2mth.UpdateRBXYZ(Bmat,RBObj,RBData,'Vector')
101            UIJ = G2mth.UpdateRBUIJ(Bmat,Cart,RBObj)
102            for i,x in enumerate(XYZ):
103                atId = RBObj['Ids'][i]
104                for j in [0,1,2]:
105                    parmDict[pfx+atxIds[j]+str(AtLookup[atId])] = x[j]
106                if UIJ[i][0] == 'A':
107                    for j in range(6):
108                        parmDict[pfx+atuIds[j]+str(AtLookup[atId])] = UIJ[i][j+2]
109                elif UIJ[i][0] == 'I':
110                    parmDict[pfx+'AUiso:'+str(AtLookup[atId])] = UIJ[i][1]
111           
112        for irb,RBObj in enumerate(RBModels.get('Residue',[])):
113            jrb = RRBIds.index(RBObj['RBId'])
114            rbsx = str(irb)+':'+str(jrb)
115            for i,px in enumerate(['RBRPx:','RBRPy:','RBRPz:']):
116                RBObj['Orig'][0][i] = parmDict[pfx+px+rbsx]
117            for i,po in enumerate(['RBROa:','RBROi:','RBROj:','RBROk:']):
118                RBObj['Orient'][0][i] = parmDict[pfx+po+rbsx]               
119            RBObj['Orient'][0] = G2mth.normQ(RBObj['Orient'][0])
120            TLS = RBObj['ThermalMotion']
121            if 'T' in TLS[0]:
122                for i,pt in enumerate(['RBRT11:','RBRT22:','RBRT33:','RBRT12:','RBRT13:','RBRT23:']):
123                    RBObj['ThermalMotion'][1][i] = parmDict[pfx+pt+rbsx]
124            if 'L' in TLS[0]:
125                for i,pt in enumerate(['RBRL11:','RBRL22:','RBRL33:','RBRL12:','RBRL13:','RBRL23:']):
126                    RBObj['ThermalMotion'][1][i+6] = parmDict[pfx+pt+rbsx]
127            if 'S' in TLS[0]:
128                for i,pt in enumerate(['RBRS12:','RBRS13:','RBRS21:','RBRS23:','RBRS31:','RBRS32:','RBRSAA:','RBRSBB:']):
129                    RBObj['ThermalMotion'][1][i+12] = parmDict[pfx+pt+rbsx]
130            if 'U' in TLS[0]:
131                RBObj['ThermalMotion'][1][0] = parmDict[pfx+'RBRU:'+rbsx]
132            for itors,tors in enumerate(RBObj['Torsions']):
133                tors[0] = parmDict[pfx+'RBRTr;'+str(itors)+':'+rbsx]
134            XYZ,Cart = G2mth.UpdateRBXYZ(Bmat,RBObj,RBData,'Residue')
135            UIJ = G2mth.UpdateRBUIJ(Bmat,Cart,RBObj)
136            for i,x in enumerate(XYZ):
137                atId = RBObj['Ids'][i]
138                for j in [0,1,2]:
139                    parmDict[pfx+atxIds[j]+str(AtLookup[atId])] = x[j]
140                if UIJ[i][0] == 'A':
141                    for j in range(6):
142                        parmDict[pfx+atuIds[j]+str(AtLookup[atId])] = UIJ[i][j+2]
143                elif UIJ[i][0] == 'I':
144                    parmDict[pfx+'AUiso:'+str(AtLookup[atId])] = UIJ[i][1]
145                   
146def ApplyRBModelDervs(dFdvDict,parmDict,rigidbodyDict,Phase):
147    'Needs a doc string'
148    atxIds = ['dAx:','dAy:','dAz:']
149    atuIds = ['AU11:','AU22:','AU33:','AU12:','AU13:','AU23:']
150    TIds = ['T11:','T22:','T33:','T12:','T13:','T23:']
151    LIds = ['L11:','L22:','L33:','L12:','L13:','L23:']
152    SIds = ['S12:','S13:','S21:','S23:','S31:','S32:','SAA:','SBB:']
153    PIds = ['Px:','Py:','Pz:']
154    OIds = ['Oa:','Oi:','Oj:','Ok:']
155    RBIds = rigidbodyDict.get('RBIds',{'Vector':[],'Residue':[]})  #these are lists of rbIds
156    if not RBIds['Vector'] and not RBIds['Residue']:
157        return
158    VRBIds = RBIds['Vector']
159    RRBIds = RBIds['Residue']
160    RBData = rigidbodyDict
161    for item in parmDict:
162        if 'RB' in item:
163            dFdvDict[item] = 0.        #NB: this is a vector which is no. refl. long & must be filled!
164    General = Phase['General']
165    cx,ct,cs,cia = General['AtomPtrs']
166    cell = General['Cell'][1:7]
167    Amat,Bmat = G2lat.cell2AB(cell)
168    rpd = np.pi/180.
169    rpd2 = rpd**2
170    g = nl.inv(np.inner(Bmat,Bmat))
171    gvec = np.sqrt(np.array([g[0][0]**2,g[1][1]**2,g[2][2]**2,
172        g[0][0]*g[1][1],g[0][0]*g[2][2],g[1][1]*g[2][2]]))
173    AtLookup = G2mth.FillAtomLookUp(Phase['Atoms'],cia+8)
174    pfx = str(Phase['pId'])+'::'
175    RBModels =  Phase['RBModels']
176    for irb,RBObj in enumerate(RBModels.get('Vector',[])):
177        VModel = RBData['Vector'][RBObj['RBId']]
178        Q = RBObj['Orient'][0]
179        Pos = RBObj['Orig'][0]
180        jrb = VRBIds.index(RBObj['RBId'])
181        rbsx = str(irb)+':'+str(jrb)
182        dXdv = []
183        for iv in range(len(VModel['VectMag'])):
184            dCdv = []
185            for vec in VModel['rbVect'][iv]:
186                dCdv.append(G2mth.prodQVQ(Q,vec))
187            dXdv.append(np.inner(Bmat,np.array(dCdv)).T)
188        XYZ,Cart = G2mth.UpdateRBXYZ(Bmat,RBObj,RBData,'Vector')
189        for ia,atId in enumerate(RBObj['Ids']):
190            atNum = AtLookup[atId]
191            dx = 0.00001
192            for iv in range(len(VModel['VectMag'])):
193                for ix in [0,1,2]:
194                    dFdvDict['::RBV;'+str(iv)+':'+str(jrb)] += dXdv[iv][ia][ix]*dFdvDict[pfx+atxIds[ix]+str(atNum)]
195            for i,name in enumerate(['RBVPx:','RBVPy:','RBVPz:']):
196                dFdvDict[pfx+name+rbsx] += dFdvDict[pfx+atxIds[i]+str(atNum)]
197            for iv in range(4):
198                Q[iv] -= dx
199                XYZ1 = G2mth.RotateRBXYZ(Bmat,Cart,G2mth.normQ(Q))
200                Q[iv] += 2.*dx
201                XYZ2 = G2mth.RotateRBXYZ(Bmat,Cart,G2mth.normQ(Q))
202                Q[iv] -= dx
203                dXdO = (XYZ2[ia]-XYZ1[ia])/(2.*dx)
204                for ix in [0,1,2]:
205                    dFdvDict[pfx+'RBV'+OIds[iv]+rbsx] += dXdO[ix]*dFdvDict[pfx+atxIds[ix]+str(atNum)]
206            X = G2mth.prodQVQ(Q,Cart[ia])
207            dFdu = np.array([dFdvDict[pfx+Uid+str(AtLookup[atId])] for Uid in atuIds]).T/gvec
208            dFdu = G2lat.U6toUij(dFdu.T)
209            dFdu = np.tensordot(Amat,np.tensordot(Amat,dFdu,([1,0])),([0,1]))           
210            dFdu = G2lat.UijtoU6(dFdu)
211            atNum = AtLookup[atId]
212            if 'T' in RBObj['ThermalMotion'][0]:
213                for i,name in enumerate(['RBVT11:','RBVT22:','RBVT33:','RBVT12:','RBVT13:','RBVT23:']):
214                    dFdvDict[pfx+name+rbsx] += dFdu[i]
215            if 'L' in RBObj['ThermalMotion'][0]:
216                dFdvDict[pfx+'RBVL11:'+rbsx] += rpd2*(dFdu[1]*X[2]**2+dFdu[2]*X[1]**2-dFdu[5]*X[1]*X[2])
217                dFdvDict[pfx+'RBVL22:'+rbsx] += rpd2*(dFdu[0]*X[2]**2+dFdu[2]*X[0]**2-dFdu[4]*X[0]*X[2])
218                dFdvDict[pfx+'RBVL33:'+rbsx] += rpd2*(dFdu[0]*X[1]**2+dFdu[1]*X[0]**2-dFdu[3]*X[0]*X[1])
219                dFdvDict[pfx+'RBVL12:'+rbsx] += rpd2*(-dFdu[3]*X[2]**2-2.*dFdu[2]*X[0]*X[1]+
220                    dFdu[4]*X[1]*X[2]+dFdu[5]*X[0]*X[2])
221                dFdvDict[pfx+'RBVL13:'+rbsx] += rpd2*(-dFdu[4]*X[1]**2-2.*dFdu[1]*X[0]*X[2]+
222                    dFdu[3]*X[1]*X[2]+dFdu[5]*X[0]*X[1])
223                dFdvDict[pfx+'RBVL23:'+rbsx] += rpd2*(-dFdu[5]*X[0]**2-2.*dFdu[0]*X[1]*X[2]+
224                    dFdu[3]*X[0]*X[2]+dFdu[4]*X[0]*X[1])
225            if 'S' in RBObj['ThermalMotion'][0]:
226                dFdvDict[pfx+'RBVS12:'+rbsx] += rpd*(dFdu[5]*X[1]-2.*dFdu[1]*X[2])
227                dFdvDict[pfx+'RBVS13:'+rbsx] += rpd*(-dFdu[5]*X[2]+2.*dFdu[2]*X[1])
228                dFdvDict[pfx+'RBVS21:'+rbsx] += rpd*(-dFdu[4]*X[0]+2.*dFdu[0]*X[2])
229                dFdvDict[pfx+'RBVS23:'+rbsx] += rpd*(dFdu[4]*X[2]-2.*dFdu[2]*X[0])
230                dFdvDict[pfx+'RBVS31:'+rbsx] += rpd*(dFdu[3]*X[0]-2.*dFdu[0]*X[1])
231                dFdvDict[pfx+'RBVS32:'+rbsx] += rpd*(-dFdu[3]*X[1]+2.*dFdu[1]*X[0])
232                dFdvDict[pfx+'RBVSAA:'+rbsx] += rpd*(dFdu[4]*X[1]-dFdu[3]*X[2])
233                dFdvDict[pfx+'RBVSBB:'+rbsx] += rpd*(dFdu[5]*X[0]-dFdu[3]*X[2])
234            if 'U' in RBObj['ThermalMotion'][0]:
235                dFdvDict[pfx+'RBVU:'+rbsx] += dFdvDict[pfx+'AUiso:'+str(AtLookup[atId])]
236
237
238    for irb,RBObj in enumerate(RBModels.get('Residue',[])):
239        Q = RBObj['Orient'][0]
240        Pos = RBObj['Orig'][0]
241        jrb = RRBIds.index(RBObj['RBId'])
242        torData = RBData['Residue'][RBObj['RBId']]['rbSeq']
243        rbsx = str(irb)+':'+str(jrb)
244        XYZ,Cart = G2mth.UpdateRBXYZ(Bmat,RBObj,RBData,'Residue')
245        for itors,tors in enumerate(RBObj['Torsions']):     #derivative error?
246            tname = pfx+'RBRTr;'+str(itors)+':'+rbsx           
247            orId,pvId = torData[itors][:2]
248            pivotVec = Cart[orId]-Cart[pvId]
249            QA = G2mth.AVdeg2Q(-0.001,pivotVec)
250            QB = G2mth.AVdeg2Q(0.001,pivotVec)
251            for ir in torData[itors][3]:
252                atNum = AtLookup[RBObj['Ids'][ir]]
253                rVec = Cart[ir]-Cart[pvId]
254                dR = G2mth.prodQVQ(QB,rVec)-G2mth.prodQVQ(QA,rVec)
255                dRdT = np.inner(Bmat,G2mth.prodQVQ(Q,dR))/.002
256                for ix in [0,1,2]:
257                    dFdvDict[tname] += dRdT[ix]*dFdvDict[pfx+atxIds[ix]+str(atNum)]
258        for ia,atId in enumerate(RBObj['Ids']):
259            atNum = AtLookup[atId]
260            dx = 0.00001
261            for i,name in enumerate(['RBRPx:','RBRPy:','RBRPz:']):
262                dFdvDict[pfx+name+rbsx] += dFdvDict[pfx+atxIds[i]+str(atNum)]
263            for iv in range(4):
264                Q[iv] -= dx
265                XYZ1 = G2mth.RotateRBXYZ(Bmat,Cart,G2mth.normQ(Q))
266                Q[iv] += 2.*dx
267                XYZ2 = G2mth.RotateRBXYZ(Bmat,Cart,G2mth.normQ(Q))
268                Q[iv] -= dx
269                dXdO = (XYZ2[ia]-XYZ1[ia])/(2.*dx)
270                for ix in [0,1,2]:
271                    dFdvDict[pfx+'RBR'+OIds[iv]+rbsx] += dXdO[ix]*dFdvDict[pfx+atxIds[ix]+str(atNum)]
272            X = G2mth.prodQVQ(Q,Cart[ia])
273            dFdu = np.array([dFdvDict[pfx+Uid+str(AtLookup[atId])] for Uid in atuIds]).T/gvec
274            dFdu = G2lat.U6toUij(dFdu.T)
275            dFdu = np.tensordot(Amat.T,np.tensordot(Amat,dFdu,([1,0])),([0,1]))
276            dFdu = G2lat.UijtoU6(dFdu)
277            atNum = AtLookup[atId]
278            if 'T' in RBObj['ThermalMotion'][0]:
279                for i,name in enumerate(['RBRT11:','RBRT22:','RBRT33:','RBRT12:','RBRT13:','RBRT23:']):
280                    dFdvDict[pfx+name+rbsx] += dFdu[i]
281            if 'L' in RBObj['ThermalMotion'][0]:
282                dFdvDict[pfx+'RBRL11:'+rbsx] += rpd2*(dFdu[1]*X[2]**2+dFdu[2]*X[1]**2-dFdu[5]*X[1]*X[2])
283                dFdvDict[pfx+'RBRL22:'+rbsx] += rpd2*(dFdu[0]*X[2]**2+dFdu[2]*X[0]**2-dFdu[4]*X[0]*X[2])
284                dFdvDict[pfx+'RBRL33:'+rbsx] += rpd2*(dFdu[0]*X[1]**2+dFdu[1]*X[0]**2-dFdu[3]*X[0]*X[1])
285                dFdvDict[pfx+'RBRL12:'+rbsx] += rpd2*(-dFdu[3]*X[2]**2-2.*dFdu[2]*X[0]*X[1]+
286                    dFdu[4]*X[1]*X[2]+dFdu[5]*X[0]*X[2])
287                dFdvDict[pfx+'RBRL13:'+rbsx] += rpd2*(dFdu[4]*X[1]**2-2.*dFdu[1]*X[0]*X[2]+
288                    dFdu[3]*X[1]*X[2]+dFdu[5]*X[0]*X[1])
289                dFdvDict[pfx+'RBRL23:'+rbsx] += rpd2*(dFdu[5]*X[0]**2-2.*dFdu[0]*X[1]*X[2]+
290                    dFdu[3]*X[0]*X[2]+dFdu[4]*X[0]*X[1])
291            if 'S' in RBObj['ThermalMotion'][0]:
292                dFdvDict[pfx+'RBRS12:'+rbsx] += rpd*(dFdu[5]*X[1]-2.*dFdu[1]*X[2])
293                dFdvDict[pfx+'RBRS13:'+rbsx] += rpd*(-dFdu[5]*X[2]+2.*dFdu[2]*X[1])
294                dFdvDict[pfx+'RBRS21:'+rbsx] += rpd*(-dFdu[4]*X[0]+2.*dFdu[0]*X[2])
295                dFdvDict[pfx+'RBRS23:'+rbsx] += rpd*(dFdu[4]*X[2]-2.*dFdu[2]*X[0])
296                dFdvDict[pfx+'RBRS31:'+rbsx] += rpd*(dFdu[3]*X[0]-2.*dFdu[0]*X[1])
297                dFdvDict[pfx+'RBRS32:'+rbsx] += rpd*(-dFdu[3]*X[1]+2.*dFdu[1]*X[0])
298                dFdvDict[pfx+'RBRSAA:'+rbsx] += rpd*(dFdu[4]*X[1]-dFdu[3]*X[2])
299                dFdvDict[pfx+'RBRSBB:'+rbsx] += rpd*(dFdu[5]*X[0]-dFdu[3]*X[2])
300            if 'U' in RBObj['ThermalMotion'][0]:
301                dFdvDict[pfx+'RBRU:'+rbsx] += dFdvDict[pfx+'AUiso:'+str(AtLookup[atId])]
302   
303################################################################################
304##### Penalty & restraint functions
305################################################################################
306
307def penaltyFxn(HistoPhases,calcControls,parmDict,varyList):
308    'Needs a doc string'
309    Histograms,Phases,restraintDict,rigidbodyDict = HistoPhases
310    pNames = []
311    pVals = []
312    pWt = []
313    negWt = {}
314    pWsum = {}
315    for phase in Phases:
316        pId = Phases[phase]['pId']
317        negWt[pId] = Phases[phase]['General']['Pawley neg wt']
318        General = Phases[phase]['General']
319        cx,ct,cs,cia = General['AtomPtrs']
320        textureData = General['SH Texture']
321        SGData = General['SGData']
322        AtLookup = G2mth.FillAtomLookUp(Phases[phase]['Atoms'],cia+8)
323        cell = General['Cell'][1:7]
324        Amat,Bmat = G2lat.cell2AB(cell)
325        if phase not in restraintDict:
326            continue
327        phaseRest = restraintDict[phase]
328        names = [['Bond','Bonds'],['Angle','Angles'],['Plane','Planes'],
329            ['Chiral','Volumes'],['Torsion','Torsions'],['Rama','Ramas'],
330            ['ChemComp','Sites'],['Texture','HKLs'],]
331        for name,rest in names:
332            pWsum[name] = 0.
333            itemRest = phaseRest[name]
334            if itemRest[rest] and itemRest['Use']:
335                wt = itemRest['wtFactor']
336                if name in ['Bond','Angle','Plane','Chiral']:
337                    for i,[indx,ops,obs,esd] in enumerate(itemRest[rest]):
338                        pNames.append(str(pId)+':'+name+':'+str(i))
339                        XYZ = np.array(G2mth.GetAtomCoordsByID(pId,parmDict,AtLookup,indx))
340                        XYZ = G2mth.getSyXYZ(XYZ,ops,SGData)
341                        if name == 'Bond':
342                            calc = G2mth.getRestDist(XYZ,Amat)
343                        elif name == 'Angle':
344                            calc = G2mth.getRestAngle(XYZ,Amat)
345                        elif name == 'Plane':
346                            calc = G2mth.getRestPlane(XYZ,Amat)
347                        elif name == 'Chiral':
348                            calc = G2mth.getRestChiral(XYZ,Amat)
349                        pVals.append(obs-calc)
350                        pWt.append(wt/esd**2)
351                        pWsum[name] += wt*((obs-calc)/esd)**2
352                elif name in ['Torsion','Rama']:
353                    coeffDict = itemRest['Coeff']
354                    for i,[indx,ops,cofName,esd] in enumerate(itemRest[rest]):
355                        pNames.append(str(pId)+':'+name+':'+str(i))
356                        XYZ = np.array(G2mth.GetAtomCoordsByID(pId,parmDict,AtLookup,indx))
357                        XYZ = G2mth.getSyXYZ(XYZ,ops,SGData)
358                        if name == 'Torsion':
359                            tor = G2mth.getRestTorsion(XYZ,Amat)
360                            restr,calc = G2mth.calcTorsionEnergy(tor,coeffDict[cofName])
361                        else:
362                            phi,psi = G2mth.getRestRama(XYZ,Amat)
363                            restr,calc = G2mth.calcRamaEnergy(phi,psi,coeffDict[cofName])                               
364                        pVals.append(restr)
365                        pWt.append(wt/esd**2)
366                        pWsum[name] += wt*(restr/esd)**2
367                elif name == 'ChemComp':
368                    for i,[indx,factors,obs,esd] in enumerate(itemRest[rest]):
369                        pNames.append(str(pId)+':'+name+':'+str(i))
370                        mul = np.array(G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,cs+1))
371                        frac = np.array(G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,cs-1))
372                        calc = np.sum(mul*frac*factors)
373                        pVals.append(obs-calc)
374                        pWt.append(wt/esd**2)                   
375                        pWsum[name] += wt*((obs-calc)/esd)**2
376                elif name == 'Texture':
377                    SHkeys = textureData['SH Coeff'][1].keys()
378                    SHCoef = G2mth.GetSHCoeff(pId,parmDict,SHkeys)
379                    shModels = ['cylindrical','none','shear - 2/m','rolling - mmm']
380                    SamSym = dict(zip(shModels,['0','-1','2/m','mmm']))
381                    for i,[hkl,grid,esd1,ifesd2,esd2] in enumerate(itemRest[rest]):
382                        PH = np.array(hkl)
383                        phi,beta = G2lat.CrsAng(np.array(hkl),cell,SGData)
384                        ODFln = G2lat.Flnh(False,SHCoef,phi,beta,SGData)
385                        R,P,Z = G2mth.getRestPolefig(ODFln,SamSym[textureData['Model']],grid)
386                        Z1 = -ma.masked_greater(Z,0.0)
387                        IndZ1 = np.array(ma.nonzero(Z1))
388                        for ind in IndZ1.T:
389                            pNames.append('%d:%s:%d:%.2f:%.2f'%(pId,name,i,R[ind[0],ind[1]],P[ind[0],ind[1]]))
390                            pVals.append(Z1[ind[0]][ind[1]])
391                            pWt.append(wt/esd1**2)
392                            pWsum[name] += wt*(-Z1[ind[0]][ind[1]]/esd1)**2
393                        if ifesd2:
394                            Z2 = 1.-Z
395                            for ind in np.ndindex(grid,grid):
396                                pNames.append('%d:%s:%d:%.2f:%.2f'%(pId,name+'-unit',i,R[ind[0],ind[1]],P[ind[0],ind[1]]))
397                                pVals.append(Z1[ind[0]][ind[1]])
398                                pWt.append(wt/esd2**2)
399                                pWsum[name] += wt*(Z2/esd2)**2
400       
401    for phase in Phases:
402        name = 'SH-Pref.Ori.'
403        pId = Phases[phase]['pId']
404        General = Phases[phase]['General']
405        SGData = General['SGData']
406        cell = General['Cell'][1:7]
407        pWsum[name] = 0.0
408        for hist in Phases[phase]['Histograms']:
409            if hist in Histograms and 'PWDR' in hist:
410                hId = Histograms[hist]['hId']
411                phfx = '%d:%d:'%(pId,hId)
412                if calcControls[phfx+'poType'] == 'SH':
413                    toler = calcControls[phfx+'SHtoler']
414                    wt = 1./toler**2
415                    HKLs = np.array(calcControls[phfx+'SHhkl'])
416                    SHnames = calcControls[phfx+'SHnames']
417                    SHcof = dict(zip(SHnames,[parmDict[phfx+cof] for cof in SHnames]))
418                    for i,PH in enumerate(HKLs):
419                        phi,beta = G2lat.CrsAng(PH,cell,SGData)
420                        SH3Coef = {}
421                        for item in SHcof:
422                            L,N = eval(item.strip('C'))
423                            SH3Coef['C%d,0,%d'%(L,N)] = SHcof[item]                       
424                        ODFln = G2lat.Flnh(False,SH3Coef,phi,beta,SGData)
425                        X = np.linspace(0,90.0,26)
426                        Y = -ma.masked_greater(G2lat.polfcal(ODFln,'0',X,0.0),0.0)
427                        IndY = ma.nonzero(Y)
428                        for ind in IndY[0]:
429                            pNames.append('%d:%d:%s:%d:%.2f'%(pId,hId,name,i,X[ind]))
430                            pVals.append(Y[ind])
431                            pWt.append(wt)
432                            pWsum[name] += wt*(Y[ind])**2
433    pWsum['PWLref'] = 0.
434    for item in varyList:
435        if 'PWLref' in item and parmDict[item] < 0.:
436            pId = int(item.split(':')[0])
437            if negWt[pId]:
438                pNames.append(item)
439                pVals.append(-parmDict[item])
440                pWt.append(negWt[pId])
441                pWsum['PWLref'] += negWt[pId]*(-parmDict[item])**2
442    pVals = np.array(pVals)
443    pWt = np.array(pWt)         #should this be np.sqrt?
444    return pNames,pVals,pWt,pWsum
445   
446def penaltyDeriv(pNames,pVal,HistoPhases,calcControls,parmDict,varyList):
447    'Needs a doc string'
448    Histograms,Phases,restraintDict,rigidbodyDict = HistoPhases
449    pDerv = np.zeros((len(varyList),len(pVal)))
450    for phase in Phases:
451#        if phase not in restraintDict:
452#            continue
453        pId = Phases[phase]['pId']
454        General = Phases[phase]['General']
455        cx,ct,cs,cia = General['AtomPtrs']
456        SGData = General['SGData']
457        AtLookup = G2mth.FillAtomLookUp(Phases[phase]['Atoms'],cia+8)
458        cell = General['Cell'][1:7]
459        Amat,Bmat = G2lat.cell2AB(cell)
460        textureData = General['SH Texture']
461
462        SHkeys = textureData['SH Coeff'][1].keys()
463        SHCoef = G2mth.GetSHCoeff(pId,parmDict,SHkeys)
464        shModels = ['cylindrical','none','shear - 2/m','rolling - mmm']
465        SamSym = dict(zip(shModels,['0','-1','2/m','mmm']))
466        sam = SamSym[textureData['Model']]
467        phaseRest = restraintDict.get(phase,{})
468        names = {'Bond':'Bonds','Angle':'Angles','Plane':'Planes',
469            'Chiral':'Volumes','Torsion':'Torsions','Rama':'Ramas',
470            'ChemComp':'Sites','Texture':'HKLs'}
471        lasthkl = np.array([0,0,0])
472        for ip,pName in enumerate(pNames):
473            pnames = pName.split(':')
474            if pId == int(pnames[0]):
475                name = pnames[1]
476                if 'PWL' in pName:
477                    pDerv[varyList.index(pName)][ip] += 1.
478                    continue
479                elif 'SH-' in pName:
480                    continue
481                id = int(pnames[2]) 
482                itemRest = phaseRest[name]
483                if name in ['Bond','Angle','Plane','Chiral']:
484                    indx,ops,obs,esd = itemRest[names[name]][id]
485                    dNames = []
486                    for ind in indx:
487                        dNames += [str(pId)+'::dA'+Xname+':'+str(AtLookup[ind]) for Xname in ['x','y','z']]
488                    XYZ = np.array(G2mth.GetAtomCoordsByID(pId,parmDict,AtLookup,indx))
489                    if name == 'Bond':
490                        deriv = G2mth.getRestDeriv(G2mth.getRestDist,XYZ,Amat,ops,SGData)
491                    elif name == 'Angle':
492                        deriv = G2mth.getRestDeriv(G2mth.getRestAngle,XYZ,Amat,ops,SGData)
493                    elif name == 'Plane':
494                        deriv = G2mth.getRestDeriv(G2mth.getRestPlane,XYZ,Amat,ops,SGData)
495                    elif name == 'Chiral':
496                        deriv = G2mth.getRestDeriv(G2mth.getRestChiral,XYZ,Amat,ops,SGData)
497                elif name in ['Torsion','Rama']:
498                    coffDict = itemRest['Coeff']
499                    indx,ops,cofName,esd = itemRest[names[name]][id]
500                    dNames = []
501                    for ind in indx:
502                        dNames += [str(pId)+'::dA'+Xname+':'+str(AtLookup[ind]) for Xname in ['x','y','z']]
503                    XYZ = np.array(G2mth.GetAtomCoordsByID(pId,parmDict,AtLookup,indx))
504                    if name == 'Torsion':
505                        deriv = G2mth.getTorsionDeriv(XYZ,Amat,coffDict[cofName])
506                    else:
507                        deriv = G2mth.getRamaDeriv(XYZ,Amat,coffDict[cofName])
508                elif name == 'ChemComp':
509                    indx,factors,obs,esd = itemRest[names[name]][id]
510                    dNames = []
511                    for ind in indx:
512                        dNames += [str(pId)+'::Afrac:'+str(AtLookup[ind])]
513                        mul = np.array(G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,cs+1))
514                        deriv = mul*factors
515                elif 'Texture' in name:
516                    deriv = []
517                    dNames = []
518                    hkl,grid,esd1,ifesd2,esd2 = itemRest[names[name]][id]
519                    hkl = np.array(hkl)
520                    if np.any(lasthkl-hkl):
521                        PH = np.array(hkl)
522                        phi,beta = G2lat.CrsAng(np.array(hkl),cell,SGData)
523                        ODFln = G2lat.Flnh(False,SHCoef,phi,beta,SGData)
524                        lasthkl = copy.copy(hkl)                       
525                    if 'unit' in name:
526                        pass
527                    else:
528                        gam = float(pnames[3])
529                        psi = float(pnames[4])
530                        for SHname in ODFln:
531                            l,m,n = eval(SHname[1:])
532                            Ksl = G2lat.GetKsl(l,m,sam,psi,gam)[0]
533                            dNames += [str(pId)+'::'+SHname]
534                            deriv.append(-ODFln[SHname][0]*Ksl/SHCoef[SHname])
535                for dName,drv in zip(dNames,deriv):
536                    try:
537                        ind = varyList.index(dName)
538                        pDerv[ind][ip] += drv
539                    except ValueError:
540                        pass
541       
542        lasthkl = np.array([0,0,0])
543        for ip,pName in enumerate(pNames):
544            deriv = []
545            dNames = []
546            pnames = pName.split(':')
547            if 'SH-' in pName and pId == int(pnames[0]):
548                hId = int(pnames[1])
549                phfx = '%d:%d:'%(pId,hId)
550                psi = float(pnames[4])
551                HKLs = calcControls[phfx+'SHhkl']
552                SHnames = calcControls[phfx+'SHnames']
553                SHcof = dict(zip(SHnames,[parmDict[phfx+cof] for cof in SHnames]))
554                hkl = np.array(HKLs[int(pnames[3])])     
555                if np.any(lasthkl-hkl):
556                    PH = np.array(hkl)
557                    phi,beta = G2lat.CrsAng(np.array(hkl),cell,SGData)
558                    SH3Coef = {}
559                    for item in SHcof:
560                        L,N = eval(item.strip('C'))
561                        SH3Coef['C%d,0,%d'%(L,N)] = SHcof[item]                       
562                    ODFln = G2lat.Flnh(False,SH3Coef,phi,beta,SGData)
563                    lasthkl = copy.copy(hkl)                       
564                for SHname in SHnames:
565                    l,n = eval(SHname[1:])
566                    SH3name = 'C%d,0,%d'%(l,n)
567                    Ksl = G2lat.GetKsl(l,0,'0',psi,0.0)[0]
568                    dNames += [phfx+SHname]
569                    deriv.append(ODFln[SH3name][0]*Ksl/SHcof[SHname])
570            for dName,drv in zip(dNames,deriv):
571                try:
572                    ind = varyList.index(dName)
573                    pDerv[ind][ip] += drv
574                except ValueError:
575                    pass
576    return pDerv
577
578################################################################################
579##### Function & derivative calculations
580################################################################################       
581                   
582def GetAtomFXU(pfx,calcControls,parmDict):
583    'Needs a doc string'
584    Natoms = calcControls['Natoms'][pfx]
585    Tdata = Natoms*[' ',]
586    Mdata = np.zeros(Natoms)
587    IAdata = Natoms*[' ',]
588    Fdata = np.zeros(Natoms)
589    FFdata = []
590    BLdata = []
591    Xdata = np.zeros((3,Natoms))
592    dXdata = np.zeros((3,Natoms))
593    Uisodata = np.zeros(Natoms)
594    Uijdata = np.zeros((6,Natoms))
595    keys = {'Atype:':Tdata,'Amul:':Mdata,'Afrac:':Fdata,'AI/A:':IAdata,
596        'dAx:':dXdata[0],'dAy:':dXdata[1],'dAz:':dXdata[2],
597        'Ax:':Xdata[0],'Ay:':Xdata[1],'Az:':Xdata[2],'AUiso:':Uisodata,
598        'AU11:':Uijdata[0],'AU22:':Uijdata[1],'AU33:':Uijdata[2],
599        'AU12:':Uijdata[3],'AU13:':Uijdata[4],'AU23:':Uijdata[5]}
600    for iatm in range(Natoms):
601        for key in keys:
602            parm = pfx+key+str(iatm)
603            if parm in parmDict:
604                keys[key][iatm] = parmDict[parm]
605    Fdata = np.where(Fdata,Fdata,1.e-8)         #avoid divide by zero in derivative calc.
606    return Tdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata
607   
608def GetAtomSSFXU(pfx,calcControls,parmDict):
609    'Needs a doc string'
610    Natoms = calcControls['Natoms'][pfx]
611    maxSSwave = calcControls['maxSSwave'][pfx]
612    Nwave = {'F':maxSSwave['Sfrac'],'X':maxSSwave['Spos'],'Y':maxSSwave['Spos'],'Z':maxSSwave['Spos'],
613        'U':maxSSwave['Sadp'],'M':maxSSwave['Smag'],'T':maxSSwave['Spos']}
614    XSSdata = np.zeros((6,maxSSwave['Spos'],Natoms))
615    FSSdata = np.zeros((2,maxSSwave['Sfrac'],Natoms))
616    USSdata = np.zeros((12,maxSSwave['Sadp'],Natoms))
617    MSSdata = np.zeros((6,maxSSwave['Smag'],Natoms))
618    waveTypes = []
619    keys = {'Fsin:':FSSdata[0],'Fcos:':FSSdata[1],'Fzero:':FSSdata[0],'Fwid:':FSSdata[1],
620        'Tmin:':XSSdata[0],'Tmax:':XSSdata[1],'Xmax:':XSSdata[2],'Ymax:':XSSdata[3],'Zmax:':XSSdata[4],
621        'Xsin:':XSSdata[0],'Ysin:':XSSdata[1],'Zsin:':XSSdata[2],'Xcos:':XSSdata[3],'Ycos:':XSSdata[4],'Zcos:':XSSdata[5],
622        'U11sin:':USSdata[0],'U22sin:':USSdata[1],'U33sin:':USSdata[2],'U12sin:':USSdata[3],'U13sin:':USSdata[4],'U23sin:':USSdata[5],
623        'U11cos:':USSdata[6],'U22cos:':USSdata[7],'U33cos:':USSdata[8],'U12cos:':USSdata[9],'U13cos:':USSdata[10],'U23cos:':USSdata[11],
624        'MXsin:':MSSdata[0],'MYsin:':MSSdata[1],'MZsin:':MSSdata[2],'MXcos:':MSSdata[3],'MYcos:':MSSdata[4],'MZcos:':MSSdata[5]}
625    for iatm in range(Natoms):
626        waveTypes.append(parmDict[pfx+'waveType:'+str(iatm)])
627        for key in keys:
628            for m in range(Nwave[key[0]]):
629                parm = pfx+key+str(iatm)+':%d'%(m)
630                if parm in parmDict:
631                    keys[key][m][iatm] = parmDict[parm]
632    return np.array(waveTypes),FSSdata,XSSdata,USSdata,MSSdata
633   
634#def GetSSTauM(SGOps,SSOps,pfx,calcControls,XData):
635#   
636#    Natoms = calcControls['Natoms'][pfx]
637#    maxSSwave = calcControls['maxSSwave'][pfx]
638#    Smult = np.zeros((Natoms,len(SGOps)))
639#    TauT = np.zeros((Natoms,len(SGOps)))
640#    for ix,xyz in enumerate(XData.T):
641#        for isym,(sop,ssop) in enumerate(zip(SGOps,SSOps)):
642#            sdet,ssdet,dtau,dT,tauT = G2spc.getTauT(0,sop,ssop,xyz)
643#            Smult[ix][isym] = sdet
644#            TauT[ix][isym] = tauT
645#    return Smult,TauT
646#   
647def StructureFactor2(refDict,G,hfx,pfx,SGData,calcControls,parmDict):
648    ''' Compute structure factors for all h,k,l for phase
649    puts the result, F^2, in each ref[8] in refList
650    operates on blocks of 100 reflections for speed
651    input:
652   
653    :param dict refDict: where
654        'RefList' list where each ref = h,k,l,it,d,...
655        'FF' dict of form factors - filed in below
656    :param np.array G:      reciprocal metric tensor
657    :param str pfx:    phase id string
658    :param dict SGData: space group info. dictionary output from SpcGroup
659    :param dict calcControls:
660    :param dict ParmDict:
661
662    '''       
663    phfx = pfx.split(':')[0]+hfx
664    ast = np.sqrt(np.diag(G))
665    Mast = twopisq*np.multiply.outer(ast,ast)
666    SGMT = np.array([ops[0].T for ops in SGData['SGOps']])
667    SGT = np.array([ops[1] for ops in SGData['SGOps']])
668    FFtables = calcControls['FFtables']
669    BLtables = calcControls['BLtables']
670    Flack = 1.0
671    if not SGData['SGInv'] and 'S' in calcControls[hfx+'histType'] and phfx+'Flack' in parmDict:
672        Flack = 1.-2.*parmDict[phfx+'Flack']
673    TwinLaw = np.array([[[1,0,0],[0,1,0],[0,0,1]],])
674    TwDict = refDict.get('TwDict',{})           
675    if 'S' in calcControls[hfx+'histType']:
676        NTL = calcControls[phfx+'NTL']
677        NM = calcControls[phfx+'TwinNMN']+1
678        TwinLaw = calcControls[phfx+'TwinLaw']
679        TwinFr = np.array([parmDict[phfx+'TwinFr:'+str(i)] for i in range(len(TwinLaw))])
680        TwinInv = list(np.where(calcControls[phfx+'TwinInv'],-1,1))
681    Tdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata = GetAtomFXU(pfx,calcControls,parmDict)
682    FF = np.zeros(len(Tdata))
683    if 'NC' in calcControls[hfx+'histType']:
684        FP,FPP = G2el.BlenResCW(Tdata,BLtables,parmDict[hfx+'Lam'])
685    elif 'X' in calcControls[hfx+'histType']:
686        FP = np.array([FFtables[El][hfx+'FP'] for El in Tdata])
687        FPP = np.array([FFtables[El][hfx+'FPP'] for El in Tdata])
688    Uij = np.array(G2lat.U6toUij(Uijdata))
689    bij = Mast*Uij.T
690    blkSize = 100       #no. of reflections in a block - size seems optimal
691    nRef = refDict['RefList'].shape[0]
692    if not len(refDict['FF']):                #no form factors - 1st time thru StructureFactor
693        if 'N' in calcControls[hfx+'histType']:
694            dat = G2el.getBLvalues(BLtables)
695            refDict['FF']['El'] = dat.keys()
696            refDict['FF']['FF'] = np.ones((nRef,len(dat)))*dat.values()           
697        else:       #'X'
698            dat = G2el.getFFvalues(FFtables,0.)
699            refDict['FF']['El'] = dat.keys()
700            refDict['FF']['FF'] = np.ones((nRef,len(dat)))
701            for iref,ref in enumerate(refDict['RefList']):
702                SQ = 1./(2.*ref[4])**2
703                dat = G2el.getFFvalues(FFtables,SQ)
704                refDict['FF']['FF'][iref] *= dat.values()
705#reflection processing begins here - big arrays!
706    iBeg = 0
707    time0 = time.time()
708    while iBeg < nRef:
709        iFin = min(iBeg+blkSize,nRef)
710        refl = refDict['RefList'][iBeg:iFin]    #array(blkSize,nItems)
711        H = refl.T[:3]                          #array(blkSize,3)
712        H = np.squeeze(np.inner(H.T,TwinLaw))   #maybe array(blkSize,nTwins,3) or (blkSize,3)
713        TwMask = np.any(H,axis=-1)
714        if TwinLaw.shape[0] > 1 and TwDict: #need np.inner(TwinLaw[?],TwDict[iref][i])*TwinInv[i]
715            for ir in range(blkSize):
716                iref = ir+iBeg
717                if iref in TwDict:
718                    for i in TwDict[iref]:
719                        for n in range(NTL):
720                            H[ir][i+n*NM] = np.inner(TwinLaw[n*NM],np.array(TwDict[iref][i])*TwinInv[i+n*NM])
721            TwMask = np.any(H,axis=-1)
722        SQ = 1./(2.*refl.T[4])**2               #array(blkSize)
723        SQfactor = 4.0*SQ*twopisq               #ditto prev.
724        if 'T' in calcControls[hfx+'histType']:
725            if 'P' in calcControls[hfx+'histType']:
726                FP,FPP = G2el.BlenResTOF(Tdata,BLtables,refl.T[14])
727            else:
728                FP,FPP = G2el.BlenResTOF(Tdata,BLtables,refl.T[12])
729            FP = np.repeat(FP.T,len(SGT)*len(TwinLaw),axis=0)
730            FPP = np.repeat(FPP.T,len(SGT)*len(TwinLaw),axis=0)
731        Bab = np.repeat(parmDict[phfx+'BabA']*np.exp(-parmDict[phfx+'BabU']*SQfactor),len(SGT)*len(TwinLaw))
732        Tindx = np.array([refDict['FF']['El'].index(El) for El in Tdata])
733        FF = np.repeat(refDict['FF']['FF'][iBeg:iFin].T[Tindx].T,len(SGT)*len(TwinLaw),axis=0)
734        Uniq = np.inner(H,SGMT)
735        Phi = np.inner(H,SGT)
736        phase = twopi*(np.inner(Uniq,(dXdata+Xdata).T).T+Phi.T).T
737        sinp = np.sin(phase)
738        cosp = np.cos(phase)
739        biso = -SQfactor*Uisodata[:,nxs]
740        Tiso = np.repeat(np.where(biso<1.,np.exp(biso),1.0),len(SGT)*len(TwinLaw),axis=1).T
741        HbH = -np.sum(Uniq.T*np.swapaxes(np.inner(bij,Uniq),2,-1),axis=1)
742        Tuij = np.where(HbH<1.,np.exp(HbH),1.0).T
743        Tcorr = np.reshape(Tiso,Tuij.shape)*Tuij*Mdata*Fdata/len(SGMT)
744        if 'T' in calcControls[hfx+'histType']: #fa,fb are 2 X blkSize X nTwin X nOps x nAtoms
745            fa = np.array([np.reshape(((FF+FP).T-Bab).T,cosp.shape)*cosp*Tcorr,-np.reshape(Flack*FPP,sinp.shape)*sinp*Tcorr])
746            fb = np.array([np.reshape(((FF+FP).T-Bab).T,sinp.shape)*sinp*Tcorr,np.reshape(Flack*FPP,cosp.shape)*cosp*Tcorr])
747        else:
748            fa = np.array([np.reshape(((FF+FP).T-Bab).T,cosp.shape)*cosp*Tcorr,-Flack*FPP*sinp*Tcorr])
749            fb = np.array([np.reshape(((FF+FP).T-Bab).T,sinp.shape)*sinp*Tcorr,Flack*FPP*cosp*Tcorr])
750        fas = np.sum(np.sum(fa,axis=-1),axis=-1)  #real 2 x blkSize x nTwin; sum over atoms & uniq hkl
751        fbs = np.sum(np.sum(fb,axis=-1),axis=-1)  #imag
752        if SGData['SGInv']: #centrosymmetric; B=0
753            fbs[0] *= 0.
754            fas[1] *= 0.
755        if 'PWDR' in calcControls[hfx+'histType']:     #PWDR: F^2 = A[0]^2 + A[1]^2 + B[0]^2 + B[1]^2
756            refl.T[9] = np.sum(fas**2,axis=0)+np.sum(fbs**2,axis=0)     
757            refl.T[10] = atan2d(fbs[0],fas[0])  #ignore f' & f"
758        else:                                       #HKLF: F^2 = (A[0]+A[1])^2 + (B[0]+B[1])^2
759            if len(TwinLaw) > 1:
760                refl.T[9] = np.sum(fas[:,:,0],axis=0)**2+np.sum(fbs[:,:,0],axis=0)**2   #FcT from primary twin element
761                refl.T[7] = np.sum(TwinFr*TwMask*np.sum(fas,axis=0)**2,axis=-1)+   \
762                    np.sum(TwinFr*TwMask*np.sum(fbs,axis=0)**2,axis=-1)                        #Fc sum over twins
763                refl.T[10] = atan2d(fbs[0].T[0],fas[0].T[0])  #ignore f' & f" & use primary twin
764            else:   # checked correct!!
765                refl.T[9] = np.sum(fas,axis=0)**2+np.sum(fbs,axis=0)**2
766                refl.T[7] = np.copy(refl.T[9])               
767                refl.T[10] = atan2d(fbs[0],fas[0])  #ignore f' & f"
768#        GSASIIpath.IPyBreak()
769#                refl.T[10] = atan2d(np.sum(fbs,axis=0),np.sum(fas,axis=0)) #include f' & f"
770        iBeg += blkSize
771#    print ' %d sf time %.4f\r'%(nRef,time.time()-time0)
772   
773#def StructureFactorDerv(refDict,G,hfx,pfx,SGData,calcControls,parmDict):
774#    '''Compute structure factor derivatives on single reflections - keep as it works for twins
775#    but is slower for powders/nontwins
776#    input:
777#   
778#    :param dict refDict: where
779#        'RefList' list where each ref = h,k,l,it,d,...
780#        'FF' dict of form factors - filled in below
781#    :param np.array G:      reciprocal metric tensor
782#    :param str hfx:    histogram id string
783#    :param str pfx:    phase id string
784#    :param dict SGData: space group info. dictionary output from SpcGroup
785#    :param dict calcControls:
786#    :param dict ParmDict:
787#   
788#    :returns: dict dFdvDict: dictionary of derivatives
789#    '''
790#    phfx = pfx.split(':')[0]+hfx
791#    ast = np.sqrt(np.diag(G))
792#    Mast = twopisq*np.multiply.outer(ast,ast)
793#    SGMT = np.array([ops[0].T for ops in SGData['SGOps']])
794#    SGT = np.array([ops[1] for ops in SGData['SGOps']])
795#    FFtables = calcControls['FFtables']
796#    BLtables = calcControls['BLtables']
797#    TwinLaw = np.array([[[1,0,0],[0,1,0],[0,0,1]],])
798#    TwDict = refDict.get('TwDict',{})           
799#    if 'S' in calcControls[hfx+'histType']:
800#        NTL = calcControls[phfx+'NTL']
801#        NM = calcControls[phfx+'TwinNMN']+1
802#        TwinLaw = calcControls[phfx+'TwinLaw']
803#        TwinFr = np.array([parmDict[phfx+'TwinFr:'+str(i)] for i in range(len(TwinLaw))])
804#        TwinInv = list(np.where(calcControls[phfx+'TwinInv'],-1,1))
805#    nTwin = len(TwinLaw)       
806#    nRef = len(refDict['RefList'])
807#    Tdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata = GetAtomFXU(pfx,calcControls,parmDict)
808#    mSize = len(Mdata)
809#    FF = np.zeros(len(Tdata))
810#    if 'NC' in calcControls[hfx+'histType']:
811#        FP,FPP = G2el.BlenResCW(Tdata,BLtables,parmDict[hfx+'Lam'])
812#    elif 'X' in calcControls[hfx+'histType']:
813#        FP = np.array([FFtables[El][hfx+'FP'] for El in Tdata])
814#        FPP = np.array([FFtables[El][hfx+'FPP'] for El in Tdata])
815#    Uij = np.array(G2lat.U6toUij(Uijdata))
816#    bij = Mast*Uij.T
817#    dFdvDict = {}
818#    if nTwin > 1:
819#        dFdfr = np.zeros((nRef,nTwin,mSize))
820#        dFdx = np.zeros((nRef,nTwin,mSize,3))
821#        dFdui = np.zeros((nRef,nTwin,mSize))
822#        dFdua = np.zeros((nRef,nTwin,mSize,6))
823#        dFdbab = np.zeros((nRef,nTwin,2))
824#        dFdfl = np.zeros((nRef,nTwin))
825#        dFdtw = np.zeros((nRef,nTwin))
826#    else:
827#        dFdfr = np.zeros((nRef,mSize))
828#        dFdx = np.zeros((nRef,mSize,3))
829#        dFdui = np.zeros((nRef,mSize))
830#        dFdua = np.zeros((nRef,mSize,6))
831#        dFdbab = np.zeros((nRef,2))
832#        dFdfl = np.zeros((nRef))
833#        dFdtw = np.zeros((nRef))
834#    Flack = 1.0
835#    if not SGData['SGInv'] and 'S' in calcControls[hfx+'histType'] and phfx+'Flack' in parmDict:
836#        Flack = 1.-2.*parmDict[phfx+'Flack']
837#    time0 = time.time()
838#    nref = len(refDict['RefList'])/100   
839#    for iref,refl in enumerate(refDict['RefList']):
840#        if 'T' in calcControls[hfx+'histType']:
841#            FP,FPP = G2el.BlenResCW(Tdata,BLtables,refl.T[12])
842#        H = np.array(refl[:3])
843#        H = np.squeeze(np.inner(H.T,TwinLaw))   #maybe array(3,nTwins) or (3)
844#        TwMask = np.any(H,axis=-1)
845#        if TwinLaw.shape[0] > 1 and TwDict:
846#            if iref in TwDict:
847#                for i in TwDict[iref]:
848#                    for n in range(NTL):
849#                        H[i+n*NM] = np.inner(TwinLaw[n*NM],np.array(TwDict[iref][i])*TwinInv[i+n*NM])
850#            TwMask = np.any(H,axis=-1)
851#        SQ = 1./(2.*refl[4])**2             # or (sin(theta)/lambda)**2
852#        SQfactor = 8.0*SQ*np.pi**2
853#        dBabdA = np.exp(-parmDict[phfx+'BabU']*SQfactor)
854#        Bab = parmDict[phfx+'BabA']*dBabdA
855#        Tindx = np.array([refDict['FF']['El'].index(El) for El in Tdata])
856#        FF = refDict['FF']['FF'][iref].T[Tindx].T
857#        Uniq = np.inner(H,SGMT)             # array(nSGOp,3) or (nTwin,nSGOp,3)
858#        Phi = np.inner(H,SGT)
859#        phase = twopi*(np.inner(Uniq,(dXdata+Xdata).T).T+Phi.T).T
860#        sinp = np.sin(phase)
861#        cosp = np.cos(phase)
862#        occ = Mdata*Fdata/len(SGT)
863#        biso = -SQfactor*Uisodata[:,nxs]
864#        Tiso = np.repeat(np.where(biso<1.,np.exp(biso),1.0),len(SGT)*nTwin,axis=1)
865#        HbH = -np.sum(Uniq.T*np.swapaxes(np.inner(bij,Uniq),2,-1),axis=1)
866#        Hij = np.array([Mast*np.multiply.outer(U,U) for U in np.reshape(Uniq,(-1,3))])
867#        Hij = np.squeeze(np.reshape(np.array([G2lat.UijtoU6(Uij) for Uij in Hij]),(nTwin,-1,6)))
868#        Tuij = np.where(HbH<1.,np.exp(HbH),1.0)
869#        Tcorr = (np.reshape(Tiso,Tuij.shape)*Tuij).T*occ
870#        fot = (FF+FP-Bab)*Tcorr
871#        fotp = FPP*Tcorr       
872#        fa = np.array([((FF+FP).T-Bab).T*cosp*Tcorr,-Flack*FPP*sinp*Tcorr])
873#        fb = np.array([((FF+FP).T-Bab).T*sinp*Tcorr,Flack*FPP*cosp*Tcorr])
874##        GSASIIpath.IPyBreak()
875#        fas = np.sum(np.sum(fa,axis=-1),axis=-1)      #real sum over atoms & unique hkl array(2,nTwins)
876#        fbs = np.sum(np.sum(fb,axis=-1),axis=-1)      #imag sum over atoms & uniq hkl
877#        fax = np.array([-fot*sinp,-fotp*cosp])   #positions array(2,ntwi,nEqv,nAtoms)
878#        fbx = np.array([fot*cosp,-fotp*sinp])
879#        #sum below is over Uniq
880#        dfadfr = np.sum(fa/occ,axis=-2)        #array(2,ntwin,nAtom) Fdata != 0 avoids /0. problem
881#        dfadba = np.sum(-cosp*Tcorr[:,nxs],axis=1)
882#        dfadui = np.sum(-SQfactor*fa,axis=-2)
883#        if nTwin > 1:
884#            dfadx = np.array([np.sum(twopi*Uniq[it]*np.swapaxes(fax,-2,-1)[:,it,:,:,nxs],axis=-2) for it in range(nTwin)])
885#            dfadua = np.array([np.sum(-Hij[it]*np.swapaxes(fa,-2,-1)[:,it,:,:,nxs],axis=-2) for it in range(nTwin)])
886#            # array(nTwin,2,nAtom,3) & array(nTwin,2,nAtom,6)
887#        else:
888#            dfadx = np.sum(twopi*Uniq*np.swapaxes(fax,-2,-1)[:,:,:,nxs],axis=-2)
889#            dfadua = np.sum(-Hij*np.swapaxes(fa,-2,-1)[:,:,:,nxs],axis=-2)
890#            # array(2,nAtom,3) & array(2,nAtom,6)
891#        if not SGData['SGInv']:
892#            dfbdfr = np.sum(fb/occ,axis=-2)        #Fdata != 0 avoids /0. problem
893#            dfadba /= 2.
894#            dfbdba = np.sum(-sinp*Tcorr[:,nxs],axis=1)/2.
895#            dfbdui = np.sum(-SQfactor*fb,axis=-2)
896#            if len(TwinLaw) > 1:
897#                dfbdx = np.array([np.sum(twopi*Uniq[it]*np.swapaxes(fbx,-2,-1)[:,it,:,:,nxs],axis=2) for it in range(nTwin)])           
898#                dfbdua = np.array([np.sum(-Hij[it]*np.swapaxes(fb,-2,-1)[:,it,:,:,nxs],axis=2) for it in range(nTwin)])
899#            else:
900#                dfadfl = np.sum(-FPP*Tcorr*sinp)
901#                dfbdfl = np.sum(FPP*Tcorr*cosp)
902#                dfbdx = np.sum(twopi*Uniq*np.swapaxes(fbx,-2,-1)[:,:,:,nxs],axis=2)           
903#                dfbdua = np.sum(-Hij*np.swapaxes(fb,-2,-1)[:,:,:,nxs],axis=2)
904#        else:
905#            dfbdfr = np.zeros_like(dfadfr)
906#            dfbdx = np.zeros_like(dfadx)
907#            dfbdui = np.zeros_like(dfadui)
908#            dfbdua = np.zeros_like(dfadua)
909#            dfbdba = np.zeros_like(dfadba)
910#            dfadfl = 0.0
911#            dfbdfl = 0.0
912#        #NB: the above have been checked against PA(1:10,1:2) in strfctr.for for Al2O3!   
913#        SA = fas[0]+fas[1]
914#        SB = fbs[0]+fbs[1]
915#        if 'P' in calcControls[hfx+'histType']: #checked perfect for centro & noncentro
916#            dFdfr[iref] = 2.*(fas[0]*dfadfr[0]+fas[1]*dfadfr[1])*Mdata/len(Uniq)+   \
917#                2.*(fbs[0]*dfbdfr[0]-fbs[1]*dfbdfr[1])*Mdata/len(Uniq)
918#            dFdx[iref] = 2.*(fas[0]*dfadx[0]+fas[1]*dfadx[1])+  \
919#                2.*(fbs[0]*dfbdx[0]+fbs[1]*dfbdx[1])
920#            dFdui[iref] = 2.*(fas[0]*dfadui[0]+fas[1]*dfadui[1])+   \
921#                2.*(fbs[0]*dfbdui[0]-fbs[1]*dfbdui[1])
922#            dFdua[iref] = 2.*(fas[0]*dfadua[0]+fas[1]*dfadua[1])+   \
923#                2.*(fbs[0]*dfbdua[0]+fbs[1]*dfbdua[1])
924#        else:
925#            if nTwin > 1:
926#                dFdfr[iref] = [2.*TwMask[it]*(SA[it]*dfadfr[0][it]+SA[it]*dfadfr[1][it]+SB[it]*dfbdfr[0][it]+SB[it]*dfbdfr[1][it])*Mdata/len(Uniq[it]) for it in range(nTwin)]
927#                dFdx[iref] = [2.*TwMask[it]*(SA[it]*dfadx[it][0]+SA[it]*dfadx[it][1]+SB[it]*dfbdx[it][0]+SB[it]*dfbdx[it][1]) for it in range(nTwin)]
928#                dFdui[iref] = [2.*TwMask[it]*(SA[it]*dfadui[it][0]+SA[it]*dfadui[it][1]+SB[it]*dfbdui[it][0]+SB[it]*dfbdui[it][1]) for it in range(nTwin)]
929#                dFdua[iref] = [2.*TwMask[it]*(SA[it]*dfadua[it][0]+SA[it]*dfadua[it][1]+SB[it]*dfbdua[it][0]+SB[it]*dfbdua[it][1]) for it in range(nTwin)]
930#                dFdtw[iref] = np.sum(TwMask*fas,axis=0)**2+np.sum(TwMask*fbs,axis=0)**2
931#            else:   #these are good for no twin single crystals
932#                dFdfr[iref] = (2.*SA*(dfadfr[0]+dfadfr[1])+2.*SB*(dfbdfr[0]+dfbdfr[1]))*Mdata/len(Uniq)
933#                dFdx[iref] = 2.*SA*(dfadx[0]+dfadx[1])+2.*SB*(dfbdx[0]+dfbdx[1])
934#                dFdui[iref] = 2.*SA*(dfadui[0]+dfadui[1])+2.*SB*(dfbdui[0]+dfbdui[1])
935#                dFdua[iref] = 2.*SA*(dfadua[0]+dfadua[1])+2.*SB*(dfbdua[0]+dfbdua[1])
936#                dFdfl[iref] = -SA*dfadfl-SB*dfbdfl  #array(nRef,)
937#        dFdbab[iref] = fas[0]*np.array([np.sum(dfadba*dBabdA),np.sum(-dfadba*parmDict[phfx+'BabA']*SQfactor*dBabdA)]).T+ \
938#            fbs[0]*np.array([np.sum(dfbdba*dBabdA),np.sum(-dfbdba*parmDict[phfx+'BabA']*SQfactor*dBabdA)]).T
939##        GSASIIpath.IPyBreak()
940#        if not iref%100 :
941#            print ' %d derivative time %.4f\r'%(iref,time.time()-time0),
942#    print ' %d derivative time %.4f\r'%(len(refDict['RefList']),time.time()-time0)
943#        #loop over atoms - each dict entry is list of derivatives for all the reflections
944#    if nTwin > 1:
945#        for i in range(len(Mdata)):     #these all OK?
946#            dFdvDict[pfx+'Afrac:'+str(i)] = np.sum(dFdfr.T[i]*TwinFr[:,nxs],axis=0)
947#            dFdvDict[pfx+'dAx:'+str(i)] = np.sum(dFdx.T[0][i]*TwinFr[:,nxs],axis=0)
948#            dFdvDict[pfx+'dAy:'+str(i)] = np.sum(dFdx.T[1][i]*TwinFr[:,nxs],axis=0)
949#            dFdvDict[pfx+'dAz:'+str(i)] = np.sum(dFdx.T[2][i]*TwinFr[:,nxs],axis=0)
950#            dFdvDict[pfx+'AUiso:'+str(i)] = np.sum(dFdui.T[i]*TwinFr[:,nxs],axis=0)
951#            dFdvDict[pfx+'AU11:'+str(i)] = np.sum(dFdua.T[0][i]*TwinFr[:,nxs],axis=0)
952#            dFdvDict[pfx+'AU22:'+str(i)] = np.sum(dFdua.T[1][i]*TwinFr[:,nxs],axis=0)
953#            dFdvDict[pfx+'AU33:'+str(i)] = np.sum(dFdua.T[2][i]*TwinFr[:,nxs],axis=0)
954#            dFdvDict[pfx+'AU12:'+str(i)] = 2.*np.sum(dFdua.T[3][i]*TwinFr[:,nxs],axis=0)
955#            dFdvDict[pfx+'AU13:'+str(i)] = 2.*np.sum(dFdua.T[4][i]*TwinFr[:,nxs],axis=0)
956#            dFdvDict[pfx+'AU23:'+str(i)] = 2.*np.sum(dFdua.T[5][i]*TwinFr[:,nxs],axis=0)
957#    else:
958#        for i in range(len(Mdata)):
959#            dFdvDict[pfx+'Afrac:'+str(i)] = dFdfr.T[i]
960#            dFdvDict[pfx+'dAx:'+str(i)] = dFdx.T[0][i]
961#            dFdvDict[pfx+'dAy:'+str(i)] = dFdx.T[1][i]
962#            dFdvDict[pfx+'dAz:'+str(i)] = dFdx.T[2][i]
963#            dFdvDict[pfx+'AUiso:'+str(i)] = dFdui.T[i]
964#            dFdvDict[pfx+'AU11:'+str(i)] = dFdua.T[0][i]
965#            dFdvDict[pfx+'AU22:'+str(i)] = dFdua.T[1][i]
966#            dFdvDict[pfx+'AU33:'+str(i)] = dFdua.T[2][i]
967#            dFdvDict[pfx+'AU12:'+str(i)] = 2.*dFdua.T[3][i]
968#            dFdvDict[pfx+'AU13:'+str(i)] = 2.*dFdua.T[4][i]
969#            dFdvDict[pfx+'AU23:'+str(i)] = 2.*dFdua.T[5][i]
970#        dFdvDict[phfx+'Flack'] = 4.*dFdfl.T
971#    dFdvDict[phfx+'BabA'] = dFdbab.T[0]
972#    dFdvDict[phfx+'BabU'] = dFdbab.T[1]
973#    if nTwin > 1:
974#        for i in range(nTwin):
975#            dFdvDict[phfx+'TwinFr:'+str(i)] = dFdtw.T[i]
976#    return dFdvDict
977   
978def StructureFactorDerv2(refDict,G,hfx,pfx,SGData,calcControls,parmDict):
979    '''Compute structure factor derivatives on blocks of reflections - for powders/nontwins only
980    faster than StructureFactorDerv - correct for powders/nontwins!!
981    input:
982   
983    :param dict refDict: where
984        'RefList' list where each ref = h,k,l,it,d,...
985        'FF' dict of form factors - filled in below
986    :param np.array G:      reciprocal metric tensor
987    :param str hfx:    histogram id string
988    :param str pfx:    phase id string
989    :param dict SGData: space group info. dictionary output from SpcGroup
990    :param dict calcControls:
991    :param dict parmDict:
992   
993    :returns: dict dFdvDict: dictionary of derivatives
994    '''
995    phfx = pfx.split(':')[0]+hfx
996    ast = np.sqrt(np.diag(G))
997    Mast = twopisq*np.multiply.outer(ast,ast)
998    SGMT = np.array([ops[0].T for ops in SGData['SGOps']])
999    SGT = np.array([ops[1] for ops in SGData['SGOps']])
1000    FFtables = calcControls['FFtables']
1001    BLtables = calcControls['BLtables']
1002    nRef = len(refDict['RefList'])
1003    Tdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata = GetAtomFXU(pfx,calcControls,parmDict)
1004    mSize = len(Mdata)
1005    FF = np.zeros(len(Tdata))
1006    if 'NC' in calcControls[hfx+'histType']:
1007        FP,FPP = G2el.BlenResCW(Tdata,BLtables,parmDict[hfx+'Lam'])
1008    elif 'X' in calcControls[hfx+'histType']:
1009        FP = np.array([FFtables[El][hfx+'FP'] for El in Tdata])
1010        FPP = np.array([FFtables[El][hfx+'FPP'] for El in Tdata])
1011    Uij = np.array(G2lat.U6toUij(Uijdata))
1012    bij = Mast*Uij.T
1013    dFdvDict = {}
1014    dFdfr = np.zeros((nRef,mSize))
1015    dFdx = np.zeros((nRef,mSize,3))
1016    dFdui = np.zeros((nRef,mSize))
1017    dFdua = np.zeros((nRef,mSize,6))
1018    dFdbab = np.zeros((nRef,2))
1019    dFdfl = np.zeros((nRef))
1020    Flack = 1.0
1021    if not SGData['SGInv'] and 'S' in calcControls[hfx+'histType'] and phfx+'Flack' in parmDict:
1022        Flack = 1.-2.*parmDict[phfx+'Flack']
1023    time0 = time.time()
1024    nref = len(refDict['RefList'])/100   
1025#reflection processing begins here - big arrays!
1026    iBeg = 0
1027    blkSize = 32       #no. of reflections in a block - optimized for speed
1028    while iBeg < nRef:
1029        iFin = min(iBeg+blkSize,nRef)
1030        refl = refDict['RefList'][iBeg:iFin]    #array(blkSize,nItems)
1031        H = refl.T[:3]
1032        SQ = 1./(2.*refl.T[4])**2             # or (sin(theta)/lambda)**2
1033        SQfactor = 8.0*SQ*np.pi**2
1034        if 'T' in calcControls[hfx+'histType']:
1035            if 'P' in calcControls[hfx+'histType']:
1036                FP,FPP = G2el.BlenResTOF(Tdata,BLtables,refl.T[14])
1037            else:
1038                FP,FPP = G2el.BlenResTOF(Tdata,BLtables,refl.T[12])
1039            FP = np.repeat(FP.T,len(SGT),axis=0)
1040            FPP = np.repeat(FPP.T,len(SGT),axis=0)
1041        dBabdA = np.exp(-parmDict[phfx+'BabU']*SQfactor)
1042        Bab = np.repeat(parmDict[phfx+'BabA']*np.exp(-parmDict[phfx+'BabU']*SQfactor),len(SGT))
1043        Tindx = np.array([refDict['FF']['El'].index(El) for El in Tdata])
1044        FF = np.repeat(refDict['FF']['FF'][iBeg:iFin].T[Tindx].T,len(SGT),axis=0)
1045#        GSASIIpath.IPyBreak()
1046        Uniq = np.inner(H.T,SGMT)             # array(nSGOp,3)
1047        Phi = np.inner(H.T,SGT)
1048        phase = twopi*(np.inner(Uniq,(dXdata+Xdata).T).T+Phi.T).T
1049        sinp = np.sin(phase)        #refBlk x nOps x nAtoms
1050        cosp = np.cos(phase)
1051        occ = Mdata*Fdata/len(SGT)
1052        biso = -SQfactor*Uisodata[:,nxs]
1053        Tiso = np.repeat(np.where(biso<1.,np.exp(biso),1.0),len(SGT),axis=1).T
1054        HbH = -np.sum(Uniq.T*np.swapaxes(np.inner(bij,Uniq),2,-1),axis=1)
1055        Tuij = np.where(HbH<1.,np.exp(HbH),1.0).T
1056        Tcorr = np.reshape(Tiso,Tuij.shape)*Tuij*Mdata*Fdata/len(SGMT)
1057        Hij = np.array([Mast*np.multiply.outer(U,U) for U in np.reshape(Uniq,(-1,3))])
1058        Hij = np.reshape(np.array([G2lat.UijtoU6(Uij) for Uij in Hij]),(-1,len(SGT),6))
1059        fot = np.reshape(((FF+FP).T-Bab).T,cosp.shape)*Tcorr
1060        if len(FPP.shape) > 1:
1061            fotp = np.reshape(FPP,cosp.shape)*Tcorr
1062        else:
1063            fotp = FPP*Tcorr     
1064        if 'T' in calcControls[hfx+'histType']:
1065            fa = np.array([fot*cosp,-np.reshape(Flack*FPP,sinp.shape)*sinp*Tcorr])
1066            fb = np.array([fot*sinp,np.reshape(Flack*FPP,cosp.shape)*cosp*Tcorr])
1067        else:
1068            fa = np.array([fot*cosp,-Flack*FPP*sinp*Tcorr])
1069            fb = np.array([fot*sinp,Flack*FPP*cosp*Tcorr])
1070        fas = np.sum(np.sum(fa,axis=-1),axis=-1)      #real sum over atoms & unique hkl array(2,refBlk,nTwins)
1071        fbs = np.sum(np.sum(fb,axis=-1),axis=-1)      #imag sum over atoms & uniq hkl
1072        fax = np.array([-fot*sinp,-fotp*cosp])   #positions array(2,refBlk,nEqv,nAtoms)
1073        fbx = np.array([fot*cosp,-fotp*sinp])
1074        #sum below is over Uniq
1075        dfadfr = np.sum(fa/occ,axis=-2)        #array(2,refBlk,nAtom) Fdata != 0 avoids /0. problem
1076        dfadba = np.sum(-cosp*Tcorr,axis=-2)  #array(refBlk,nAtom)
1077        dfadx = np.sum(twopi*Uniq[nxs,:,nxs,:,:]*np.swapaxes(fax,-2,-1)[:,:,:,:,nxs],axis=-2)
1078        dfadui = np.sum(-SQfactor[nxs,:,nxs,nxs]*fa,axis=-2) #array(Ops,refBlk,nAtoms)
1079        dfadua = np.sum(-Hij[nxs,:,nxs,:,:]*np.swapaxes(fa,-2,-1)[:,:,:,:,nxs],axis=-2)
1080        # array(2,refBlk,nAtom,3) & array(2,refBlk,nAtom,6)
1081        if not SGData['SGInv']:
1082            dfbdfr = np.sum(fb/occ,axis=-2)        #Fdata != 0 avoids /0. problem
1083            dfbdba = np.sum(-sinp*Tcorr,axis=-2)
1084            dfadfl = np.sum(np.sum(-fotp*sinp,axis=-1),axis=-1)
1085            dfbdfl = np.sum(np.sum(fotp*cosp,axis=-1),axis=-1)
1086            dfbdx = np.sum(twopi*Uniq[nxs,:,nxs,:,:]*np.swapaxes(fbx,-2,-1)[:,:,:,:,nxs],axis=-2)           
1087            dfbdui = np.sum(-SQfactor[nxs,:,nxs,nxs]*fb,axis=-2)
1088            dfbdua = np.sum(-Hij[nxs,:,nxs,:,:]*np.swapaxes(fb,-2,-1)[:,:,:,:,nxs],axis=-2)
1089        else:
1090            dfbdfr = np.zeros_like(dfadfr)
1091            dfbdx = np.zeros_like(dfadx)
1092            dfbdui = np.zeros_like(dfadui)
1093            dfbdua = np.zeros_like(dfadua)
1094            dfbdba = np.zeros_like(dfadba)
1095            dfadfl = 0.0
1096            dfbdfl = 0.0
1097        #NB: the above have been checked against PA(1:10,1:2) in strfctr.for for Al2O3!   
1098        SA = fas[0]+fas[1]
1099        SB = fbs[0]+fbs[1]
1100        if 'P' in calcControls[hfx+'histType']: #checked perfect for centro & noncentro
1101            dFdfr[iBeg:iFin] = 2.*np.sum(fas[:,:,nxs]*dfadfr+fbs[:,:,nxs]*dfbdfr,axis=0)*Mdata/len(SGMT)
1102#            dFdfr[iBeg:iFin] = 2.*(fas[0,:,nxs]*dfadfr[0]+fas[1,:,nxs]*dfadfr[1])*Mdata/len(SGMT)+   \
1103#                2.*(fbs[0,:,nxs]*dfbdfr[0]+fbs[1,:,nxs]*dfbdfr[1])*Mdata/len(SGMT)
1104            dFdx[iBeg:iFin] = 2.*np.sum(fas[:,:,nxs,nxs]*dfadx+fbs[:,:,nxs,nxs]*dfbdx,axis=0)
1105#            dFdx[iBeg:iFin] = 2.*(fas[0,:,nxs,nxs]*dfadx[0]+fas[1,:,nxs,nxs]*dfadx[1])+  \
1106#                2.*(fbs[0,:,nxs,nxs]*dfbdx[0]+fbs[1,:,nxs,nxs]*dfbdx[1])
1107            dFdui[iBeg:iFin] = 2.*np.sum(fas[:,:,nxs]*dfadui+fbs[:,:,nxs]*dfbdui,axis=0)
1108#            dFdui[iBeg:iFin] = 2.*(fas[0,:,nxs]*dfadui[0]+fas[1,:,nxs]*dfadui[1])+   \
1109#                2.*(fbs[0,:,nxs]*dfbdui[0]+fbs[1,:,nxs]*dfbdui[1])
1110            dFdua[iBeg:iFin] = 2.*np.sum(fas[:,:,nxs,nxs]*dfadua+fbs[:,:,nxs,nxs]*dfbdua,axis=0)
1111#            dFdua[iBeg:iFin] = 2.*(fas[0,:,nxs,nxs]*dfadua[0]+fas[1,:,nxs,nxs]*dfadua[1])+   \
1112#                2.*(fbs[0,:,nxs,nxs]*dfbdua[0]+fbs[1,:,nxs,nxs]*dfbdua[1])
1113        else:
1114            dFdfr[iBeg:iFin] = (2.*SA[:,nxs]*(dfadfr[0]+dfadfr[1])+2.*SB[:,nxs]*(dfbdfr[0]+dfbdfr[1]))*Mdata/len(SGMT)
1115            dFdx[iBeg:iFin] = 2.*SA[:,nxs,nxs]*(dfadx[0]+dfadx[1])+2.*SB[:,nxs,nxs]*(dfbdx[0]+dfbdx[1])
1116            dFdui[iBeg:iFin] = 2.*SA[:,nxs]*(dfadui[0]+dfadui[1])+2.*SB[:,nxs]*(dfbdui[0]+dfbdui[1])
1117            dFdua[iBeg:iFin] = 2.*SA[:,nxs,nxs]*(dfadua[0]+dfadua[1])+2.*SB[:,nxs,nxs]*(dfbdua[0]+dfbdua[1])
1118            dFdfl[iBeg:iFin] = -SA*dfadfl-SB*dfbdfl  #array(nRef,)
1119        dFdbab[iBeg:iFin] = 2.*(fas[0,nxs]*np.array([np.sum(dfadba.T*dBabdA,axis=0),np.sum(-dfadba.T*parmDict[phfx+'BabA']*SQfactor*dBabdA,axis=0)])+ \
1120                            fbs[0,nxs]*np.array([np.sum(dfbdba.T*dBabdA,axis=0),np.sum(-dfbdba.T*parmDict[phfx+'BabA']*SQfactor*dBabdA,axis=0)])).T
1121#        GSASIIpath.IPyBreak()
1122        iBeg += blkSize
1123    print ' %d derivative time %.4f\r'%(nRef,time.time()-time0)
1124        #loop over atoms - each dict entry is list of derivatives for all the reflections
1125    for i in range(len(Mdata)):
1126        dFdvDict[pfx+'Afrac:'+str(i)] = dFdfr.T[i]
1127        dFdvDict[pfx+'dAx:'+str(i)] = dFdx.T[0][i]
1128        dFdvDict[pfx+'dAy:'+str(i)] = dFdx.T[1][i]
1129        dFdvDict[pfx+'dAz:'+str(i)] = dFdx.T[2][i]
1130        dFdvDict[pfx+'AUiso:'+str(i)] = dFdui.T[i]
1131        dFdvDict[pfx+'AU11:'+str(i)] = dFdua.T[0][i]
1132        dFdvDict[pfx+'AU22:'+str(i)] = dFdua.T[1][i]
1133        dFdvDict[pfx+'AU33:'+str(i)] = dFdua.T[2][i]
1134        dFdvDict[pfx+'AU12:'+str(i)] = 2.*dFdua.T[3][i]
1135        dFdvDict[pfx+'AU13:'+str(i)] = 2.*dFdua.T[4][i]
1136        dFdvDict[pfx+'AU23:'+str(i)] = 2.*dFdua.T[5][i]
1137    dFdvDict[phfx+'Flack'] = 4.*dFdfl.T
1138    dFdvDict[phfx+'BabA'] = dFdbab.T[0]
1139    dFdvDict[phfx+'BabU'] = dFdbab.T[1]
1140    return dFdvDict
1141   
1142#def StructureFactorDervTw(refDict,G,hfx,pfx,SGData,calcControls,parmDict):
1143#    '''Compute structure factor derivatives on single reflections - for twins only
1144#    input:
1145#   
1146#    :param dict refDict: where
1147#        'RefList' list where each ref = h,k,l,it,d,...
1148#        'FF' dict of form factors - filled in below
1149#    :param np.array G:      reciprocal metric tensor
1150#    :param str hfx:    histogram id string
1151#    :param str pfx:    phase id string
1152#    :param dict SGData: space group info. dictionary output from SpcGroup
1153#    :param dict calcControls:
1154#    :param dict parmDict:
1155#   
1156#    :returns: dict dFdvDict: dictionary of derivatives
1157#    '''
1158#    phfx = pfx.split(':')[0]+hfx
1159#    ast = np.sqrt(np.diag(G))
1160#    Mast = twopisq*np.multiply.outer(ast,ast)
1161#    SGMT = np.array([ops[0].T for ops in SGData['SGOps']])
1162#    SGT = np.array([ops[1] for ops in SGData['SGOps']])
1163#    FFtables = calcControls['FFtables']
1164#    BLtables = calcControls['BLtables']
1165#    TwDict = refDict.get('TwDict',{})           
1166#    NTL = calcControls[phfx+'NTL']
1167#    NM = calcControls[phfx+'TwinNMN']+1
1168#    TwinLaw = calcControls[phfx+'TwinLaw']
1169#    TwinFr = np.array([parmDict[phfx+'TwinFr:'+str(i)] for i in range(len(TwinLaw))])
1170#    TwinInv = list(np.where(calcControls[phfx+'TwinInv'],-1,1))
1171#    nTwin = len(TwinLaw)       
1172#    nRef = len(refDict['RefList'])
1173#    Tdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata = GetAtomFXU(pfx,calcControls,parmDict)
1174#    mSize = len(Mdata)
1175#    FF = np.zeros(len(Tdata))
1176#    if 'NC' in calcControls[hfx+'histType']:
1177#        FP,FPP = G2el.BlenResCW(Tdata,BLtables,parmDict[hfx+'Lam'])
1178#    elif 'X' in calcControls[hfx+'histType']:
1179#        FP = np.array([FFtables[El][hfx+'FP'] for El in Tdata])
1180#        FPP = np.array([FFtables[El][hfx+'FPP'] for El in Tdata])
1181#    Uij = np.array(G2lat.U6toUij(Uijdata))
1182#    bij = Mast*Uij.T
1183#    dFdvDict = {}
1184#    dFdfr = np.zeros((nRef,nTwin,mSize))
1185#    dFdx = np.zeros((nRef,nTwin,mSize,3))
1186#    dFdui = np.zeros((nRef,nTwin,mSize))
1187#    dFdua = np.zeros((nRef,nTwin,mSize,6))
1188#    dFdbab = np.zeros((nRef,nTwin,2))
1189#    dFdtw = np.zeros((nRef,nTwin))
1190#    time0 = time.time()
1191#    nref = len(refDict['RefList'])/100   
1192#    for iref,refl in enumerate(refDict['RefList']):
1193#        if 'T' in calcControls[hfx+'histType']:
1194#            FP,FPP = G2el.BlenResCW(Tdata,BLtables,refl.T[12])
1195#        H = np.array(refl[:3])
1196#        H = np.inner(H.T,TwinLaw)   #maybe array(3,nTwins) or (3)
1197#        TwMask = np.any(H,axis=-1)
1198#        if iref in TwDict:
1199#            for i in TwDict[iref]:
1200#                for n in range(NTL):
1201#                    H[i+n*NM] = np.inner(TwinLaw[n*NM],np.array(TwDict[iref][i])*TwinInv[i+n*NM])
1202#            TwMask = np.any(H,axis=-1)
1203#        SQ = 1./(2.*refl[4])**2             # or (sin(theta)/lambda)**2
1204#        SQfactor = 8.0*SQ*np.pi**2
1205#        dBabdA = np.exp(-parmDict[phfx+'BabU']*SQfactor)
1206#        Bab = parmDict[phfx+'BabA']*dBabdA
1207#        Tindx = np.array([refDict['FF']['El'].index(El) for El in Tdata])
1208#        FF = refDict['FF']['FF'][iref].T[Tindx].T
1209#        Uniq = np.inner(H,SGMT)             # array(nSGOp,3) or (nTwin,nSGOp,3)
1210#        Phi = np.inner(H,SGT)
1211#        phase = twopi*(np.inner(Uniq,(dXdata+Xdata).T).T+Phi.T).T
1212#        sinp = np.sin(phase)
1213#        cosp = np.cos(phase)
1214#        occ = Mdata*Fdata/len(SGT)
1215#        biso = -SQfactor*Uisodata[:,nxs]
1216#        Tiso = np.repeat(np.where(biso<1.,np.exp(biso),1.0),len(SGT)*nTwin,axis=1)
1217#        HbH = -np.sum(Uniq.T*np.swapaxes(np.inner(bij,Uniq),2,-1),axis=1)
1218#        Hij = np.array([Mast*np.multiply.outer(U,U) for U in np.reshape(Uniq,(-1,3))])
1219#        Hij = np.reshape(np.array([G2lat.UijtoU6(Uij) for Uij in Hij]),(nTwin,-1,6))
1220#        Tuij = np.where(HbH<1.,np.exp(HbH),1.0)
1221#        Tcorr = (np.reshape(Tiso,Tuij.shape)*Tuij).T*occ
1222#        fot = (FF+FP-Bab)*Tcorr
1223#        fotp = FPP*Tcorr       
1224#        fa = np.array([((FF+FP).T-Bab).T*cosp*Tcorr,-FPP*sinp*Tcorr])
1225#        fb = np.array([((FF+FP).T-Bab).T*sinp*Tcorr,FPP*cosp*Tcorr])
1226##        GSASIIpath.IPyBreak()
1227#        fas = np.sum(np.sum(fa,axis=-1),axis=-1)      #real sum over atoms & unique hkl array(2,nTwins)
1228#        fbs = np.sum(np.sum(fb,axis=-1),axis=-1)      #imag sum over atoms & uniq hkl
1229#        if SGData['SGInv']: #centrosymmetric; B=0
1230#            fbs[0] *= 0.
1231#            fas[1] *= 0.
1232#        fax = np.array([-fot*sinp,-fotp*cosp])   #positions array(2,ntwi,nEqv,nAtoms)
1233#        fbx = np.array([fot*cosp,-fotp*sinp])
1234#        #sum below is over Uniq
1235#        dfadfr = np.sum(fa/occ,axis=-2)        #array(2,ntwin,nAtom) Fdata != 0 avoids /0. problem
1236#        dfadba = np.sum(-cosp*Tcorr[:,nxs],axis=1)
1237#        dfadui = np.sum(-SQfactor*fa,axis=-2)
1238#        dfadx = np.array([np.sum(twopi*Uniq[it]*np.swapaxes(fax,-2,-1)[:,it,:,:,nxs],axis=-2) for it in range(nTwin)])
1239#        dfadua = np.array([np.sum(-Hij[it]*np.swapaxes(fa,-2,-1)[:,it,:,:,nxs],axis=-2) for it in range(nTwin)])
1240#        # array(nTwin,2,nAtom,3) & array(nTwin,2,nAtom,6)
1241#        if not SGData['SGInv']:
1242#            dfbdfr = np.sum(fb/occ,axis=-2)        #Fdata != 0 avoids /0. problem
1243#            dfadba /= 2.
1244#            dfbdba = np.sum(-sinp*Tcorr[:,nxs],axis=1)/2.
1245#            dfbdui = np.sum(-SQfactor*fb,axis=-2)
1246#            dfbdx = np.array([np.sum(twopi*Uniq[it]*np.swapaxes(fbx,-2,-1)[:,it,:,:,nxs],axis=2) for it in range(nTwin)])           
1247#            dfbdua = np.array([np.sum(-Hij[it]*np.swapaxes(fb,-2,-1)[:,it,:,:,nxs],axis=2) for it in range(nTwin)])
1248#        else:
1249#            dfbdfr = np.zeros_like(dfadfr)
1250#            dfbdx = np.zeros_like(dfadx)
1251#            dfbdui = np.zeros_like(dfadui)
1252#            dfbdua = np.zeros_like(dfadua)
1253#            dfbdba = np.zeros_like(dfadba)
1254#        SA = fas[0]+fas[1]
1255#        SB = fbs[0]+fbs[1]
1256#        dFdfr[iref] = [2.*TwMask[it]*(SA[it]*dfadfr[0,it]+SA[it]*dfadfr[1,it]+SB[it]*dfbdfr[0,it]+SB[it]*dfbdfr[1,it])*Mdata/len(Uniq[it]) for it in range(nTwin)]
1257#        dFdx[iref] = [2.*TwMask[it]*(SA[it]*dfadx[it,0]+SA[it]*dfadx[it,1]+SB[it]*dfbdx[it,0]+SB[it]*dfbdx[it,1]) for it in range(nTwin)]
1258#        dFdui[iref] = [2.*TwMask[it]*(SA[it]*dfadui[0,it]+SA[it]*dfadui[1,it]+SB[it]*dfbdui[0,it]+SB[it]*dfbdui[1,it]) for it in range(nTwin)]
1259#        dFdua[iref] = [2.*TwMask[it]*(SA[it]*dfadua[it,0]+SA[it]*dfadua[it,1]+SB[it]*dfbdua[it,0]+SB[it]*dfbdua[it,1]) for it in range(nTwin)]
1260#        if SGData['SGInv']: #centrosymmetric; B=0
1261#            dFdtw[iref] = np.sum(TwMask[nxs,:]*fas,axis=0)**2
1262#        else:               
1263#            dFdtw[iref] = np.sum(TwMask[nxs,:]*fas,axis=0)**2+np.sum(TwMask[nxs,:]*fbs,axis=0)**2
1264#        dFdbab[iref] = fas[0,:,nxs]*np.array([np.sum(dfadba*dBabdA),np.sum(-dfadba*parmDict[phfx+'BabA']*SQfactor*dBabdA)]).T+ \
1265#            fbs[0,:,nxs]*np.array([np.sum(dfbdba*dBabdA),np.sum(-dfbdba*parmDict[phfx+'BabA']*SQfactor*dBabdA)]).T
1266##        GSASIIpath.IPyBreak()
1267#    print ' %d derivative time %.4f\r'%(len(refDict['RefList']),time.time()-time0)
1268#    #loop over atoms - each dict entry is list of derivatives for all the reflections
1269#    for i in range(len(Mdata)):     #these all OK?
1270#        dFdvDict[pfx+'Afrac:'+str(i)] = np.sum(dFdfr.T[i]*TwinFr[:,nxs],axis=0)
1271#        dFdvDict[pfx+'dAx:'+str(i)] = np.sum(dFdx.T[0][i]*TwinFr[:,nxs],axis=0)
1272#        dFdvDict[pfx+'dAy:'+str(i)] = np.sum(dFdx.T[1][i]*TwinFr[:,nxs],axis=0)
1273#        dFdvDict[pfx+'dAz:'+str(i)] = np.sum(dFdx.T[2][i]*TwinFr[:,nxs],axis=0)
1274#        dFdvDict[pfx+'AUiso:'+str(i)] = np.sum(dFdui.T[i]*TwinFr[:,nxs],axis=0)
1275#        dFdvDict[pfx+'AU11:'+str(i)] = np.sum(dFdua.T[0][i]*TwinFr[:,nxs],axis=0)
1276#        dFdvDict[pfx+'AU22:'+str(i)] = np.sum(dFdua.T[1][i]*TwinFr[:,nxs],axis=0)
1277#        dFdvDict[pfx+'AU33:'+str(i)] = np.sum(dFdua.T[2][i]*TwinFr[:,nxs],axis=0)
1278#        dFdvDict[pfx+'AU12:'+str(i)] = 2.*np.sum(dFdua.T[3][i]*TwinFr[:,nxs],axis=0)
1279#        dFdvDict[pfx+'AU13:'+str(i)] = 2.*np.sum(dFdua.T[4][i]*TwinFr[:,nxs],axis=0)
1280#        dFdvDict[pfx+'AU23:'+str(i)] = 2.*np.sum(dFdua.T[5][i]*TwinFr[:,nxs],axis=0)
1281#    dFdvDict[phfx+'BabA'] = dFdbab.T[0]
1282#    dFdvDict[phfx+'BabU'] = dFdbab.T[1]
1283#    for i in range(nTwin):
1284#        dFdvDict[phfx+'TwinFr:'+str(i)] = dFdtw.T[i]
1285#    return dFdvDict
1286   
1287def StructureFactorDervTw2(refDict,G,hfx,pfx,SGData,calcControls,parmDict):
1288    '''Compute structure factor derivatives on blocks of reflections - for twins only
1289    faster than StructureFactorDervTw
1290    input:
1291   
1292    :param dict refDict: where
1293        'RefList' list where each ref = h,k,l,it,d,...
1294        'FF' dict of form factors - filled in below
1295    :param np.array G:      reciprocal metric tensor
1296    :param str hfx:    histogram id string
1297    :param str pfx:    phase id string
1298    :param dict SGData: space group info. dictionary output from SpcGroup
1299    :param dict calcControls:
1300    :param dict parmDict:
1301   
1302    :returns: dict dFdvDict: dictionary of derivatives
1303    '''
1304    phfx = pfx.split(':')[0]+hfx
1305    ast = np.sqrt(np.diag(G))
1306    Mast = twopisq*np.multiply.outer(ast,ast)
1307    SGMT = np.array([ops[0].T for ops in SGData['SGOps']])
1308    SGT = np.array([ops[1] for ops in SGData['SGOps']])
1309    FFtables = calcControls['FFtables']
1310    BLtables = calcControls['BLtables']
1311    TwDict = refDict.get('TwDict',{})           
1312    NTL = calcControls[phfx+'NTL']
1313    NM = calcControls[phfx+'TwinNMN']+1
1314    TwinLaw = calcControls[phfx+'TwinLaw']
1315    TwinFr = np.array([parmDict[phfx+'TwinFr:'+str(i)] for i in range(len(TwinLaw))])
1316    TwinInv = list(np.where(calcControls[phfx+'TwinInv'],-1,1))
1317    nTwin = len(TwinLaw)       
1318    nRef = len(refDict['RefList'])
1319    Tdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata = GetAtomFXU(pfx,calcControls,parmDict)
1320    mSize = len(Mdata)
1321    FF = np.zeros(len(Tdata))
1322    if 'NC' in calcControls[hfx+'histType']:
1323        FP,FPP = G2el.BlenResCW(Tdata,BLtables,parmDict[hfx+'Lam'])
1324    elif 'X' in calcControls[hfx+'histType']:
1325        FP = np.array([FFtables[El][hfx+'FP'] for El in Tdata])
1326        FPP = np.array([FFtables[El][hfx+'FPP'] for El in Tdata])
1327    Uij = np.array(G2lat.U6toUij(Uijdata))
1328    bij = Mast*Uij.T
1329    dFdvDict = {}
1330    dFdfr = np.zeros((nRef,nTwin,mSize))
1331    dFdx = np.zeros((nRef,nTwin,mSize,3))
1332    dFdui = np.zeros((nRef,nTwin,mSize))
1333    dFdua = np.zeros((nRef,nTwin,mSize,6))
1334    dFdbab = np.zeros((nRef,nTwin,2))
1335    dFdtw = np.zeros((nRef,nTwin))
1336    time0 = time.time()
1337#reflection processing begins here - big arrays!
1338    iBeg = 0
1339    blkSize = 16       #no. of reflections in a block - optimized for speed
1340    while iBeg < nRef:
1341        iFin = min(iBeg+blkSize,nRef)
1342        refl = refDict['RefList'][iBeg:iFin]    #array(blkSize,nItems)
1343        H = refl.T[:3]
1344        H = np.inner(H.T,TwinLaw)   #array(3,nTwins)
1345        TwMask = np.any(H,axis=-1)
1346        for ir in range(blkSize):
1347            iref = ir+iBeg
1348            if iref in TwDict:
1349                for i in TwDict[iref]:
1350                    for n in range(NTL):
1351                        H[ir][i+n*NM] = np.inner(TwinLaw[n*NM],np.array(TwDict[iref][i])*TwinInv[i+n*NM])
1352        TwMask = np.any(H,axis=-1)
1353        SQ = 1./(2.*refl.T[4])**2             # or (sin(theta)/lambda)**2
1354        SQfactor = 8.0*SQ*np.pi**2
1355        if 'T' in calcControls[hfx+'histType']:
1356            if 'P' in calcControls[hfx+'histType']:
1357                FP,FPP = G2el.BlenResTOF(Tdata,BLtables,refl.T[14])
1358            else:
1359                FP,FPP = G2el.BlenResTOF(Tdata,BLtables,refl.T[12])
1360            FP = np.repeat(FP.T,len(SGT)*len(TwinLaw),axis=0)
1361            FPP = np.repeat(FPP.T,len(SGT)*len(TwinLaw),axis=0)
1362        dBabdA = np.exp(-parmDict[phfx+'BabU']*SQfactor)
1363        Bab = np.repeat(parmDict[phfx+'BabA']*dBabdA,len(SGT)*nTwin)
1364        Tindx = np.array([refDict['FF']['El'].index(El) for El in Tdata])
1365        FF = np.repeat(refDict['FF']['FF'][iBeg:iFin].T[Tindx].T,len(SGT)*len(TwinLaw),axis=0)
1366        Uniq = np.inner(H,SGMT)             # (nTwin,nSGOp,3)
1367        Phi = np.inner(H,SGT)
1368        phase = twopi*(np.inner(Uniq,(dXdata+Xdata).T).T+Phi.T).T
1369        sinp = np.sin(phase)
1370        cosp = np.cos(phase)
1371        occ = Mdata*Fdata/len(SGT)
1372        biso = -SQfactor*Uisodata[:,nxs]
1373        Tiso = np.repeat(np.where(biso<1.,np.exp(biso),1.0),len(SGT)*nTwin,axis=1)
1374        HbH = -np.sum(Uniq.T*np.swapaxes(np.inner(bij,Uniq),2,-1),axis=1)
1375        Hij = np.array([Mast*np.multiply.outer(U,U) for U in np.reshape(Uniq,(-1,3))])
1376        Hij = np.reshape(np.array([G2lat.UijtoU6(Uij) for Uij in Hij]),(-1,nTwin,len(SGT),6))
1377        Tuij = np.where(HbH<1.,np.exp(HbH),1.0)
1378        Tcorr = (np.reshape(Tiso,Tuij.shape)*Tuij).T*Mdata*Fdata/len(SGMT)
1379        fot = np.reshape(((FF+FP).T-Bab).T,cosp.shape)*Tcorr
1380        fotp = FPP*Tcorr       
1381        if 'T' in calcControls[hfx+'histType']: #fa,fb are 2 X blkSize X nTwin X nOps x nAtoms
1382            fa = np.array([np.reshape(((FF+FP).T-Bab).T,cosp.shape)*cosp*Tcorr,-np.reshape(FPP,sinp.shape)*sinp*Tcorr])
1383            fb = np.array([np.reshape(((FF+FP).T-Bab).T,sinp.shape)*sinp*Tcorr,np.reshape(FPP,cosp.shape)*cosp*Tcorr])
1384        else:
1385            fa = np.array([np.reshape(((FF+FP).T-Bab).T,cosp.shape)*cosp*Tcorr,-FPP*sinp*Tcorr])
1386            fb = np.array([np.reshape(((FF+FP).T-Bab).T,sinp.shape)*sinp*Tcorr,FPP*cosp*Tcorr])
1387        fas = np.sum(np.sum(fa,axis=-1),axis=-1)      #real sum over atoms & unique hkl array(2,nTwins)
1388        fbs = np.sum(np.sum(fb,axis=-1),axis=-1)      #imag sum over atoms & uniq hkl
1389        if SGData['SGInv']: #centrosymmetric; B=0
1390            fbs[0] *= 0.
1391            fas[1] *= 0.
1392        fax = np.array([-fot*sinp,-fotp*cosp])   #positions array(2,nRef,ntwi,nEqv,nAtoms)
1393        fbx = np.array([fot*cosp,-fotp*sinp])
1394        #sum below is over Uniq
1395        dfadfr = np.sum(np.sum(fa/occ,axis=-2),axis=0)        #array(2,nRef,ntwin,nAtom) Fdata != 0 avoids /0. problem
1396        dfadba = np.sum(-cosp*Tcorr[:,nxs],axis=1)
1397        dfadui = np.sum(np.sum(-SQfactor[nxs,:,nxs,nxs,nxs]*fa,axis=-2),axis=0)           
1398        dfadx = np.sum(np.sum(twopi*Uniq[nxs,:,:,:,nxs,:]*fax[:,:,:,:,:,nxs],axis=-3),axis=0) # nRef x nTwin x nAtoms x xyz; sum on ops & A,A'
1399        dfadua = np.sum(np.sum(-Hij[nxs,:,:,:,nxs,:]*fa[:,:,:,:,:,nxs],axis=-3),axis=0) 
1400        if not SGData['SGInv']:
1401            dfbdfr = np.sum(np.sum(fb/occ,axis=-2),axis=0)        #Fdata != 0 avoids /0. problem
1402            dfadba /= 2.
1403            dfbdba = np.sum(-sinp*Tcorr[:,nxs],axis=1)/2.
1404            dfbdui = np.sum(np.sum(-SQfactor[nxs,:,nxs,nxs,nxs]*fb,axis=-2),axis=0)
1405            dfbdx = np.sum(np.sum(twopi*Uniq[nxs,:,:,:,nxs,:]*fbx[:,:,:,:,:,nxs],axis=-3),axis=0)
1406            dfbdua = np.sum(np.sum(-Hij[nxs,:,:,:,nxs,:]*fb[:,:,:,:,:,nxs],axis=-3),axis=0)
1407        else:
1408            dfbdfr = np.zeros_like(dfadfr)
1409            dfbdx = np.zeros_like(dfadx)
1410            dfbdui = np.zeros_like(dfadui)
1411            dfbdua = np.zeros_like(dfadua)
1412            dfbdba = np.zeros_like(dfadba)
1413        SA = fas[0]+fas[1]
1414        SB = fbs[0]+fbs[1]
1415#        GSASIIpath.IPyBreak()
1416        dFdfr[iBeg:iFin] = ((2.*TwMask*SA)[:,:,nxs]*dfadfr+(2.*TwMask*SB)[:,:,nxs]*dfbdfr)*Mdata[nxs,nxs,:]/len(SGMT)
1417        dFdx[iBeg:iFin] = (2.*TwMask*SA)[:,:,nxs,nxs]*dfadx+(2.*TwMask*SB)[:,:,nxs,nxs]*dfbdx
1418        dFdui[iBeg:iFin] = (2.*TwMask*SA)[:,:,nxs]*dfadui+(2.*TwMask*SB)[:,:,nxs]*dfbdui
1419        dFdua[iBeg:iFin] = (2.*TwMask*SA)[:,:,nxs,nxs]*dfadua+(2.*TwMask*SB)[:,:,nxs,nxs]*dfbdua
1420        if SGData['SGInv']: #centrosymmetric; B=0
1421            dFdtw[iBeg:iFin] = np.sum(TwMask[nxs,:]*fas,axis=0)**2
1422        else:               
1423            dFdtw[iBeg:iFin] = np.sum(TwMask[nxs,:]*fas,axis=0)**2+np.sum(TwMask[nxs,:]*fbs,axis=0)**2
1424#        dFdbab[iBeg:iFin] = fas[0,:,nxs]*np.array([np.sum(dfadba*dBabdA),np.sum(-dfadba*parmDict[phfx+'BabA']*SQfactor*dBabdA)]).T+ \
1425#            fbs[0,:,nxs]*np.array([np.sum(dfbdba*dBabdA),np.sum(-dfbdba*parmDict[phfx+'BabA']*SQfactor*dBabdA)]).T
1426        iBeg += blkSize
1427#        GSASIIpath.IPyBreak()
1428    print ' %d derivative time %.4f\r'%(len(refDict['RefList']),time.time()-time0)
1429    #loop over atoms - each dict entry is list of derivatives for all the reflections
1430    for i in range(len(Mdata)):     #these all OK
1431        dFdvDict[pfx+'Afrac:'+str(i)] = np.sum(dFdfr.T[i]*TwinFr[:,nxs],axis=0)
1432        dFdvDict[pfx+'dAx:'+str(i)] = np.sum(dFdx.T[0][i]*TwinFr[:,nxs],axis=0)
1433        dFdvDict[pfx+'dAy:'+str(i)] = np.sum(dFdx.T[1][i]*TwinFr[:,nxs],axis=0)
1434        dFdvDict[pfx+'dAz:'+str(i)] = np.sum(dFdx.T[2][i]*TwinFr[:,nxs],axis=0)
1435        dFdvDict[pfx+'AUiso:'+str(i)] = np.sum(dFdui.T[i]*TwinFr[:,nxs],axis=0)
1436        dFdvDict[pfx+'AU11:'+str(i)] = np.sum(dFdua.T[0][i]*TwinFr[:,nxs],axis=0)
1437        dFdvDict[pfx+'AU22:'+str(i)] = np.sum(dFdua.T[1][i]*TwinFr[:,nxs],axis=0)
1438        dFdvDict[pfx+'AU33:'+str(i)] = np.sum(dFdua.T[2][i]*TwinFr[:,nxs],axis=0)
1439        dFdvDict[pfx+'AU12:'+str(i)] = 2.*np.sum(dFdua.T[3][i]*TwinFr[:,nxs],axis=0)
1440        dFdvDict[pfx+'AU13:'+str(i)] = 2.*np.sum(dFdua.T[4][i]*TwinFr[:,nxs],axis=0)
1441        dFdvDict[pfx+'AU23:'+str(i)] = 2.*np.sum(dFdua.T[5][i]*TwinFr[:,nxs],axis=0)
1442    dFdvDict[phfx+'BabA'] = dFdbab.T[0]
1443    dFdvDict[phfx+'BabU'] = dFdbab.T[1]
1444    for i in range(nTwin):
1445        dFdvDict[phfx+'TwinFr:'+str(i)] = dFdtw.T[i]
1446    return dFdvDict
1447   
1448def SStructureFactor(refDict,G,hfx,pfx,SGData,SSGData,calcControls,parmDict):
1449    '''
1450    Compute super structure factors for all h,k,l,m for phase - no twins
1451    puts the result, F^2, in each ref[9] in refList
1452    works on blocks of 32 reflections for speed
1453    input:
1454   
1455    :param dict refDict: where
1456        'RefList' list where each ref = h,k,l,m,it,d,...
1457        'FF' dict of form factors - filed in below
1458    :param np.array G:      reciprocal metric tensor
1459    :param str pfx:    phase id string
1460    :param dict SGData: space group info. dictionary output from SpcGroup
1461    :param dict calcControls:
1462    :param dict ParmDict:
1463
1464    '''
1465    phfx = pfx.split(':')[0]+hfx
1466    ast = np.sqrt(np.diag(G))
1467    Mast = twopisq*np.multiply.outer(ast,ast)   
1468    SGInv = SGData['SGInv']
1469    SGMT = np.array([ops[0].T for ops in SGData['SGOps']])
1470    SGT = np.array([ops[1] for ops in SGData['SGOps']])
1471    SSGMT = np.array([ops[0].T for ops in SSGData['SSGOps']])
1472    SSGT = np.array([ops[1] for ops in SSGData['SSGOps']])
1473    FFtables = calcControls['FFtables']
1474    BLtables = calcControls['BLtables']
1475    Flack = 1.0
1476    if not SGData['SGInv'] and 'S' in calcControls[hfx+'histType'] and phfx+'Flack' in parmDict:
1477        Flack = 1.-2.*parmDict[phfx+'Flack']
1478    Tdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata = GetAtomFXU(pfx,calcControls,parmDict)
1479    waveTypes,FSSdata,XSSdata,USSdata,MSSdata = GetAtomSSFXU(pfx,calcControls,parmDict)
1480    ngl,nWaves,Fmod,Xmod,Umod,glTau,glWt = G2mth.makeWaves(waveTypes,FSSdata,XSSdata,USSdata,Mast)
1481    modQ = np.array([parmDict[pfx+'mV0'],parmDict[pfx+'mV1'],parmDict[pfx+'mV2']])
1482    FF = np.zeros(len(Tdata))
1483    if 'NC' in calcControls[hfx+'histType']:
1484        FP,FPP = G2el.BlenResCW(Tdata,BLtables,parmDict[hfx+'Lam'])
1485    elif 'X' in calcControls[hfx+'histType']:
1486        FP = np.array([FFtables[El][hfx+'FP'] for El in Tdata])
1487        FPP = np.array([FFtables[El][hfx+'FPP'] for El in Tdata])
1488    Uij = np.array(G2lat.U6toUij(Uijdata)).T
1489    bij = Mast*Uij
1490    blkSize = 32       #no. of reflections in a block
1491    nRef = refDict['RefList'].shape[0]
1492    if not len(refDict['FF']):
1493        if 'N' in calcControls[hfx+'histType']:
1494            dat = G2el.getBLvalues(BLtables)        #will need wave here for anom. neutron b's
1495            refDict['FF']['El'] = dat.keys()
1496            refDict['FF']['FF'] = np.ones((nRef,len(dat)))*dat.values()           
1497        else:
1498            dat = G2el.getFFvalues(FFtables,0.)       
1499            refDict['FF']['El'] = dat.keys()
1500            refDict['FF']['FF'] = np.ones((nRef,len(dat)))
1501            for iref,ref in enumerate(refDict['RefList']):
1502                SQ = 1./(2.*ref[5])**2
1503                dat = G2el.getFFvalues(FFtables,SQ)
1504                refDict['FF']['FF'][iref] *= dat.values()
1505    time0 = time.time()
1506#reflection processing begins here - big arrays!
1507    iBeg = 0
1508    while iBeg < nRef:
1509        iFin = min(iBeg+blkSize,nRef)
1510        refl = refDict['RefList'][iBeg:iFin]    #array(blkSize,nItems)
1511        H = refl.T[:4]                          #array(blkSize,4)
1512        HP = H[:3]+modQ[:,nxs]*H[3:]            #projected hklm to hkl
1513        SQ = 1./(2.*refl.T[5])**2               #array(blkSize)
1514        SQfactor = 4.0*SQ*twopisq               #ditto prev.
1515        Uniq = np.inner(H.T,SSGMT)
1516        UniqP = np.inner(HP.T,SGMT)
1517        Phi = np.inner(H.T,SSGT)
1518        if SGInv:   #if centro - expand HKL sets
1519            Uniq = np.hstack((Uniq,-Uniq))
1520            Phi = np.hstack((Phi,-Phi))
1521            UniqP = np.hstack((UniqP,-UniqP))
1522        if 'T' in calcControls[hfx+'histType']:
1523            if 'P' in calcControls[hfx+'histType']:
1524                FP,FPP = G2el.BlenResTOF(Tdata,BLtables,refl.T[14])
1525            else:
1526                FP,FPP = G2el.BlenResTOF(Tdata,BLtables,refl.T[12])
1527            FP = np.repeat(FP.T,Uniq.shape[1],axis=0)
1528            FPP = np.repeat(FPP.T,Uniq.shape[1],axis=0)
1529        Bab = np.repeat(parmDict[phfx+'BabA']*np.exp(-parmDict[phfx+'BabU']*SQfactor),Uniq.shape[1])
1530        Tindx = np.array([refDict['FF']['El'].index(El) for El in Tdata])
1531        FF = np.repeat(refDict['FF']['FF'][iBeg:iFin].T[Tindx].T,Uniq.shape[1],axis=0)
1532        phase = twopi*(np.inner(Uniq[:,:,:3],(dXdata.T+Xdata.T))-Phi[:,:,nxs])
1533        sinp = np.sin(phase)
1534        cosp = np.cos(phase)
1535        biso = -SQfactor*Uisodata[:,nxs]
1536        Tiso = np.repeat(np.where(biso<1.,np.exp(biso),1.0),Uniq.shape[1],axis=1).T
1537        HbH = -np.sum(UniqP[:,:,nxs,:]*np.inner(UniqP[:,:,:],bij),axis=-1)  #use hklt proj to hkl
1538        Tuij = np.where(HbH<1.,np.exp(HbH),1.0)
1539        Tcorr = np.reshape(Tiso,Tuij.shape)*Tuij*Mdata*Fdata/Uniq.shape[1]  #refBlk x ops x atoms
1540        if 'T' in calcControls[hfx+'histType']:
1541            fa = np.array([np.reshape(((FF+FP).T-Bab).T,cosp.shape)*cosp*Tcorr,-np.reshape(Flack*FPP,sinp.shape)*sinp*Tcorr])
1542            fb = np.array([np.reshape(Flack*FPP,cosp.shape)*cosp*Tcorr,np.reshape(((FF+FP).T-Bab).T,sinp.shape)*sinp*Tcorr])
1543        else:
1544            fa = np.array([np.reshape(((FF+FP).T-Bab).T,cosp.shape)*cosp*Tcorr,-Flack*FPP*sinp*Tcorr])
1545            fb = np.array([Flack*FPP*cosp*Tcorr,np.reshape(((FF+FP).T-Bab).T,sinp.shape)*sinp*Tcorr])
1546        GfpuA = G2mth.Modulation(Uniq,UniqP,nWaves,Fmod,Xmod,Umod,glTau,glWt) #2 x refBlk x sym X atoms
1547        fag = fa*GfpuA[0]-fb*GfpuA[1]   #real; 2 x refBlk x sym x atoms
1548        fbg = fb*GfpuA[0]+fa*GfpuA[1]
1549        fas = np.sum(np.sum(fag,axis=-1),axis=-1)   #2 x refBlk; sum sym & atoms
1550        fbs = np.sum(np.sum(fbg,axis=-1),axis=-1)
1551#        GSASIIpath.IPyBreak()
1552        if 'P' in calcControls[hfx+'histType']:
1553            refl.T[10] = np.sum(fas,axis=0)**2+np.sum(fbs,axis=0)**2    #square of sums
1554#            refl.T[10] = np.sum(fas**2,axis=0)+np.sum(fbs**2,axis=0)
1555            refl.T[11] = atan2d(fbs[0],fas[0])  #ignore f' & f"
1556        else:
1557            refl.T[10] = np.sum(fas,axis=0)**2+np.sum(fbs,axis=0)**2    #square of sums
1558            refl.T[8] = np.copy(refl.T[10])               
1559            refl.T[11] = atan2d(fbs[0],fas[0])  #ignore f' & f"
1560        iBeg += blkSize
1561    print 'nRef %d time %.4f\r'%(nRef,time.time()-time0)
1562
1563def SStructureFactorTw(refDict,G,hfx,pfx,SGData,SSGData,calcControls,parmDict):
1564    '''
1565    Compute super structure factors for all h,k,l,m for phase - twins only
1566    puts the result, F^2, in each ref[8+im] in refList
1567    works on blocks of 32 reflections for speed
1568    input:
1569   
1570    :param dict refDict: where
1571        'RefList' list where each ref = h,k,l,m,it,d,...
1572        'FF' dict of form factors - filed in below
1573    :param np.array G:      reciprocal metric tensor
1574    :param str pfx:    phase id string
1575    :param dict SGData: space group info. dictionary output from SpcGroup
1576    :param dict calcControls:
1577    :param dict ParmDict:
1578
1579    '''
1580    phfx = pfx.split(':')[0]+hfx
1581    ast = np.sqrt(np.diag(G))
1582    Mast = twopisq*np.multiply.outer(ast,ast)   
1583    SGInv = SGData['SGInv']
1584    SGMT = np.array([ops[0].T for ops in SGData['SGOps']])
1585    SGT = np.array([ops[1] for ops in SGData['SGOps']])
1586    SSGMT = np.array([ops[0].T for ops in SSGData['SSGOps']])
1587    SSGT = np.array([ops[1] for ops in SSGData['SSGOps']])
1588    FFtables = calcControls['FFtables']
1589    BLtables = calcControls['BLtables']
1590    Flack = 1.0
1591    if not SGData['SGInv'] and 'S' in calcControls[hfx+'histType'] and phfx+'Flack' in parmDict:
1592        Flack = 1.-2.*parmDict[phfx+'Flack']
1593    TwinLaw = np.array([[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],])    #4D?
1594    TwDict = refDict.get('TwDict',{})           
1595    if 'S' in calcControls[hfx+'histType']:
1596        NTL = calcControls[phfx+'NTL']
1597        NM = calcControls[phfx+'TwinNMN']+1
1598        TwinLaw = calcControls[phfx+'TwinLaw']  #this'll have to be 4D also...
1599        TwinFr = np.array([parmDict[phfx+'TwinFr:'+str(i)] for i in range(len(TwinLaw))])
1600        TwinInv = list(np.where(calcControls[phfx+'TwinInv'],-1,1))
1601    Tdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata = GetAtomFXU(pfx,calcControls,parmDict)
1602    waveTypes,FSSdata,XSSdata,USSdata,MSSdata = GetAtomSSFXU(pfx,calcControls,parmDict)
1603    ngl,nWaves,Fmod,Xmod,Umod,glTau,glWt = G2mth.makeWaves(waveTypes,FSSdata,XSSdata,USSdata,Mast)
1604    modQ = np.array([parmDict[pfx+'mV0'],parmDict[pfx+'mV1'],parmDict[pfx+'mV2']])
1605    FF = np.zeros(len(Tdata))
1606    if 'NC' in calcControls[hfx+'histType']:
1607        FP,FPP = G2el.BlenResCW(Tdata,BLtables,parmDict[hfx+'Lam'])
1608    elif 'X' in calcControls[hfx+'histType']:
1609        FP = np.array([FFtables[El][hfx+'FP'] for El in Tdata])
1610        FPP = np.array([FFtables[El][hfx+'FPP'] for El in Tdata])
1611    Uij = np.array(G2lat.U6toUij(Uijdata)).T
1612    bij = Mast*Uij
1613    blkSize = 32       #no. of reflections in a block
1614    nRef = refDict['RefList'].shape[0]
1615    if not len(refDict['FF']):
1616        if 'N' in calcControls[hfx+'histType']:
1617            dat = G2el.getBLvalues(BLtables)        #will need wave here for anom. neutron b's
1618            refDict['FF']['El'] = dat.keys()
1619            refDict['FF']['FF'] = np.ones((nRef,len(dat)))*dat.values()           
1620        else:
1621            dat = G2el.getFFvalues(FFtables,0.)       
1622            refDict['FF']['El'] = dat.keys()
1623            refDict['FF']['FF'] = np.ones((nRef,len(dat)))
1624            for iref,ref in enumerate(refDict['RefList']):
1625                SQ = 1./(2.*ref[5])**2
1626                dat = G2el.getFFvalues(FFtables,SQ)
1627                refDict['FF']['FF'][iref] *= dat.values()
1628    time0 = time.time()
1629#reflection processing begins here - big arrays!
1630    iBeg = 0
1631    while iBeg < nRef:
1632        iFin = min(iBeg+blkSize,nRef)
1633        refl = refDict['RefList'][iBeg:iFin]    #array(blkSize,nItems)
1634        H = refl[:,:4]                          #array(blkSize,4)
1635        H3 = refl[:,:3]
1636        HP = H[:,:3]+modQ[nxs,:]*H[:,3:]        #projected hklm to hkl
1637        HP = np.inner(HP,TwinLaw)             #array(blkSize,nTwins,4)
1638        H3 = np.inner(H3,TwinLaw)       
1639        TwMask = np.any(HP,axis=-1)
1640        if TwinLaw.shape[0] > 1 and TwDict: #need np.inner(TwinLaw[?],TwDict[iref][i])*TwinInv[i]
1641            for ir in range(blkSize):
1642                iref = ir+iBeg
1643                if iref in TwDict:
1644                    for i in TwDict[iref]:
1645                        for n in range(NTL):
1646                            HP[ir][i+n*NM] = np.inner(TwinLaw[n*NM],np.array(TwDict[iref][i])*TwinInv[i+n*NM])
1647                            H3[ir][i+n*NM] = np.inner(TwinLaw[n*NM],np.array(TwDict[iref][i])*TwinInv[i+n*NM])
1648            TwMask = np.any(HP,axis=-1)
1649        SQ = 1./(2.*refl.T[5])**2               #array(blkSize)
1650        SQfactor = 4.0*SQ*twopisq               #ditto prev.
1651        Uniq = np.inner(H,SSGMT)
1652        Uniq3 = np.inner(H3,SGMT)
1653        UniqP = np.inner(HP,SGMT)
1654        Phi = np.inner(H,SSGT)
1655        if SGInv:   #if centro - expand HKL sets
1656            Uniq = np.hstack((Uniq,-Uniq))
1657            Uniq3 = np.hstack((Uniq3,-Uniq3))
1658            Phi = np.hstack((Phi,-Phi))
1659            UniqP = np.hstack((UniqP,-UniqP))
1660        if 'T' in calcControls[hfx+'histType']:
1661            if 'P' in calcControls[hfx+'histType']:
1662                FP,FPP = G2el.BlenResTOF(Tdata,BLtables,refl.T[14])
1663            else:
1664                FP,FPP = G2el.BlenResTOF(Tdata,BLtables,refl.T[12])
1665            FP = np.repeat(FP.T,Uniq.shape[1]*len(TwinLaw),axis=0)
1666            FPP = np.repeat(FPP.T,Uniq.shape[1]*len(TwinLaw),axis=0)
1667        Bab = np.repeat(parmDict[phfx+'BabA']*np.exp(-parmDict[phfx+'BabU']*SQfactor),Uniq.shape[1]*len(TwinLaw))
1668        Tindx = np.array([refDict['FF']['El'].index(El) for El in Tdata])
1669        FF = np.repeat(refDict['FF']['FF'][iBeg:iFin].T[Tindx].T,Uniq.shape[1]*len(TwinLaw),axis=0)
1670        phase = twopi*(np.inner(Uniq3,(dXdata.T+Xdata.T))-Phi[:,nxs,:,nxs])
1671        sinp = np.sin(phase)
1672        cosp = np.cos(phase)
1673        biso = -SQfactor*Uisodata[:,nxs]
1674        Tiso = np.repeat(np.where(biso<1.,np.exp(biso),1.0),Uniq.shape[1]*len(TwinLaw),axis=1).T
1675        HbH = -np.sum(UniqP[:,:,:,nxs]*np.inner(UniqP[:,:,:],bij),axis=-1)  #use hklt proj to hkl
1676        Tuij = np.where(HbH<1.,np.exp(HbH),1.0)
1677        Tcorr = np.reshape(Tiso,Tuij.shape)*Tuij*Mdata*Fdata/Uniq.shape[1]  #refBlk x ops x atoms
1678#        GSASIIpath.IPyBreak()
1679        if 'T' in calcControls[hfx+'histType']:
1680            fa = np.array([np.reshape(((FF+FP).T-Bab).T,cosp.shape)*cosp*Tcorr,-np.reshape(Flack*FPP,sinp.shape)*sinp*Tcorr])
1681            fb = np.array([np.reshape(Flack*FPP,cosp.shape)*cosp*Tcorr,np.reshape(((FF+FP).T-Bab).T,sinp.shape)*sinp*Tcorr])
1682        else:
1683            fa = np.array([np.reshape(((FF+FP).T-Bab).T,cosp.shape)*cosp*Tcorr,-Flack*FPP*sinp*Tcorr])
1684            fb = np.array([Flack*FPP*cosp*Tcorr,np.reshape(((FF+FP).T-Bab).T,sinp.shape)*sinp*Tcorr])
1685        GfpuA = G2mth.ModulationTw(Uniq,UniqP,nWaves,Fmod,Xmod,Umod,glTau,glWt) #2 x refBlk x sym X atoms
1686        fag = fa*GfpuA[0]-fb*GfpuA[1]   #real; 2 x refBlk x sym x atoms
1687        fbg = fb*GfpuA[0]+fa*GfpuA[1]
1688        fas = np.sum(np.sum(fag,axis=-1),axis=-1)   #2 x refBlk; sum sym & atoms
1689        fbs = np.sum(np.sum(fbg,axis=-1),axis=-1)
1690        refl.T[10] = np.sum(fas[:,:,0],axis=0)**2+np.sum(fbs[:,:,0],axis=0)**2                  #FcT from primary twin element
1691        refl.T[8] = np.sum(TwinFr*np.sum(TwMask[nxs,:,:]*fas,axis=0)**2,axis=-1)+   \
1692            np.sum(TwinFr*np.sum(TwMask[nxs,:,:]*fbs,axis=0)**2,axis=-1)                 #Fc sum over twins
1693        refl.T[11] = atan2d(fbs[0].T[0],fas[0].T[0])  #ignore f' & f"
1694        iBeg += blkSize
1695    print 'nRef %d time %.4f\r'%(nRef,time.time()-time0)
1696
1697def SStructureFactorDerv(refDict,im,G,hfx,pfx,SGData,SSGData,calcControls,parmDict):
1698    '''
1699    Compute super structure factor derivatives for all h,k,l,m for phase - no twins
1700    input:
1701   
1702    :param dict refDict: where
1703        'RefList' list where each ref = h,k,l,m,it,d,...
1704        'FF' dict of form factors - filled in below
1705    :param int im: = 1 (could be eliminated)
1706    :param np.array G:      reciprocal metric tensor
1707    :param str hfx:    histogram id string
1708    :param str pfx:    phase id string
1709    :param dict SGData: space group info. dictionary output from SpcGroup
1710    :param dict SSGData: super space group info.
1711    :param dict calcControls:
1712    :param dict ParmDict:
1713   
1714    :returns: dict dFdvDict: dictionary of derivatives
1715    '''
1716    phfx = pfx.split(':')[0]+hfx
1717    ast = np.sqrt(np.diag(G))
1718    Mast = twopisq*np.multiply.outer(ast,ast)
1719    SGInv = SGData['SGInv']
1720    SGMT = np.array([ops[0].T for ops in SGData['SGOps']])
1721    SGT = np.array([ops[1] for ops in SGData['SGOps']])
1722    SSGMT = np.array([ops[0].T for ops in SSGData['SSGOps']])
1723    SSGT = np.array([ops[1] for ops in SSGData['SSGOps']])
1724    FFtables = calcControls['FFtables']
1725    BLtables = calcControls['BLtables']
1726    nRef = len(refDict['RefList'])
1727    Tdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata = GetAtomFXU(pfx,calcControls,parmDict)
1728    mSize = len(Mdata)  #no. atoms
1729    waveTypes,FSSdata,XSSdata,USSdata,MSSdata = GetAtomSSFXU(pfx,calcControls,parmDict)
1730    ngl,nWaves,Fmod,Xmod,Umod,glTau,glWt = G2mth.makeWaves(waveTypes,FSSdata,XSSdata,USSdata,Mast)
1731    waveShapes,SCtauF,SCtauX,SCtauU,UmodAB = G2mth.makeWavesDerv(ngl,waveTypes,FSSdata,XSSdata,USSdata,Mast)
1732    modQ = np.array([parmDict[pfx+'mV0'],parmDict[pfx+'mV1'],parmDict[pfx+'mV2']])
1733    FF = np.zeros(len(Tdata))
1734    if 'NC' in calcControls[hfx+'histType']:
1735        FP,FPP = G2el.BlenResCW(Tdata,BLtables,parmDict[hfx+'Lam'])
1736    elif 'X' in calcControls[hfx+'histType']:
1737        FP = np.array([FFtables[El][hfx+'FP'] for El in Tdata])
1738        FPP = np.array([FFtables[El][hfx+'FPP'] for El in Tdata])
1739    Uij = np.array(G2lat.U6toUij(Uijdata)).T
1740    bij = Mast*Uij
1741    if not len(refDict['FF']):
1742        if 'N' in calcControls[hfx+'histType']:
1743            dat = G2el.getBLvalues(BLtables)        #will need wave here for anom. neutron b's
1744        else:
1745            dat = G2el.getFFvalues(FFtables,0.)       
1746        refDict['FF']['El'] = dat.keys()
1747        refDict['FF']['FF'] = np.zeros((len(refDict['RefList']),len(dat)))
1748    dFdvDict = {}
1749    dFdfr = np.zeros((nRef,mSize))
1750    dFdx = np.zeros((nRef,mSize,3))
1751    dFdui = np.zeros((nRef,mSize))
1752    dFdua = np.zeros((nRef,mSize,6))
1753    dFdbab = np.zeros((nRef,2))
1754    dFdfl = np.zeros((nRef))
1755    dFdtw = np.zeros((nRef))
1756    dFdGf = np.zeros((nRef,mSize,FSSdata.shape[1],2))
1757    dFdGx = np.zeros((nRef,mSize,XSSdata.shape[1],6))
1758    dFdGz = np.zeros((nRef,mSize,5))
1759    dFdGu = np.zeros((nRef,mSize,USSdata.shape[1],12))
1760    Flack = 1.0
1761    if not SGData['SGInv'] and 'S' in calcControls[hfx+'histType'] and phfx+'Flack' in parmDict:
1762        Flack = 1.-2.*parmDict[phfx+'Flack']
1763    time0 = time.time()
1764    nRef = len(refDict['RefList'])/100
1765    for iref,refl in enumerate(refDict['RefList']):
1766        if 'T' in calcControls[hfx+'histType']:
1767            FP,FPP = G2el.BlenResCW(Tdata,BLtables,refl.T[12+im])
1768        H = np.array(refl[:4])
1769        HP = H[:3]+modQ*H[3:]            #projected hklm to hkl
1770        SQ = 1./(2.*refl[4+im])**2             # or (sin(theta)/lambda)**2
1771        SQfactor = 8.0*SQ*np.pi**2
1772        dBabdA = np.exp(-parmDict[phfx+'BabU']*SQfactor)
1773        Bab = parmDict[phfx+'BabA']*dBabdA
1774        Tindx = np.array([refDict['FF']['El'].index(El) for El in Tdata])
1775        FF = refDict['FF']['FF'][iref].T[Tindx]
1776        Uniq = np.inner(H,SSGMT)
1777        Phi = np.inner(H,SSGT)
1778        UniqP = np.inner(HP,SGMT)
1779        if SGInv:   #if centro - expand HKL sets
1780            Uniq = np.vstack((Uniq,-Uniq))
1781            Phi = np.hstack((Phi,-Phi))
1782            UniqP = np.vstack((UniqP,-UniqP))
1783        phase = twopi*(np.inner(Uniq[:,:3],(dXdata+Xdata).T)+Phi[:,nxs])
1784        sinp = np.sin(phase)
1785        cosp = np.cos(phase)
1786        occ = Mdata*Fdata/Uniq.shape[0]
1787        biso = -SQfactor*Uisodata[:,nxs]
1788        Tiso = np.repeat(np.where(biso<1.,np.exp(biso),1.0),Uniq.shape[0],axis=1).T    #ops x atoms
1789        HbH = -np.sum(UniqP[:,nxs,:3]*np.inner(UniqP[:,:3],bij),axis=-1)  #ops x atoms
1790        Hij = np.array([Mast*np.multiply.outer(U[:3],U[:3]) for U in UniqP]) #atoms x 3x3
1791        Hij = np.array([G2lat.UijtoU6(Uij) for Uij in Hij])                     #atoms x 6
1792        Tuij = np.where(HbH<1.,np.exp(HbH),1.0)     #ops x atoms
1793        Tcorr = np.reshape(Tiso,Tuij.shape)*Tuij*Mdata*Fdata/Uniq.shape[0]  #ops x atoms
1794        fot = (FF+FP-Bab)*Tcorr     #ops x atoms
1795        fotp = FPP*Tcorr            #ops x atoms
1796        GfpuA = G2mth.Modulation(Uniq,UniqP,nWaves,Fmod,Xmod,Umod,glTau,glWt) #2 x sym X atoms
1797        dGdf,dGdx,dGdu,dGdz = G2mth.ModulationDerv(Uniq,UniqP,Hij,nWaves,waveShapes,Fmod,Xmod,UmodAB,SCtauF,SCtauX,SCtauU,glTau,glWt)
1798        # GfpuA is 2 x ops x atoms
1799        # derivs are: ops x atoms x waves x 2,6,12, or 5 parms as [real,imag] parts
1800        fa = np.array([((FF+FP).T-Bab).T*cosp*Tcorr,-Flack*FPP*sinp*Tcorr]) # array(2,nEqv,nAtoms)
1801        fb = np.array([((FF+FP).T-Bab).T*sinp*Tcorr,Flack*FPP*cosp*Tcorr])  #or array(2,nEqv,nAtoms)
1802        fag = fa*GfpuA[0]-fb*GfpuA[1]
1803        fbg = fb*GfpuA[0]+fa*GfpuA[1]
1804       
1805        fas = np.sum(np.sum(fag,axis=1),axis=1)     # 2 x twin
1806        fbs = np.sum(np.sum(fbg,axis=1),axis=1)
1807        fax = np.array([-fot*sinp,-fotp*cosp])   #positions; 2 x ops x atoms
1808        fbx = np.array([fot*cosp,-fotp*sinp])
1809        fax = fax*GfpuA[0]-fbx*GfpuA[1]
1810        fbx = fbx*GfpuA[0]+fax*GfpuA[1]
1811        #sum below is over Uniq
1812        dfadfr = np.sum(fag/occ,axis=1)        #Fdata != 0 ever avoids /0. problem
1813        dfbdfr = np.sum(fbg/occ,axis=1)        #Fdata != 0 avoids /0. problem
1814        dfadba = np.sum(-cosp*Tcorr[:,nxs],axis=1)
1815        dfbdba = np.sum(-sinp*Tcorr[:,nxs],axis=1)
1816        dfadui = np.sum(-SQfactor*fag,axis=1)
1817        dfbdui = np.sum(-SQfactor*fbg,axis=1)
1818        dfadx = np.sum(twopi*Uniq[:,:3]*np.swapaxes(fax,-2,-1)[:,:,:,nxs],axis=-2)  #2 x nAtom x 3xyz; sum nOps
1819        dfbdx = np.sum(twopi*Uniq[:,:3]*np.swapaxes(fbx,-2,-1)[:,:,:,nxs],axis=-2)           
1820        dfadua = np.sum(-Hij*np.swapaxes(fag,-2,-1)[:,:,:,nxs],axis=-2)             #2 x nAtom x 6Uij; sum nOps
1821        dfbdua = np.sum(-Hij*np.swapaxes(fbg,-2,-1)[:,:,:,nxs],axis=-2)         #these are correct also for twins above
1822        # array(2,nAtom,nWave,2) & array(2,nAtom,nWave,6) & array(2,nAtom,nWave,12); sum on nOps
1823        dfadGf = np.sum(fa[:,:,:,nxs,nxs]*dGdf[0][nxs,:,:,:,:]-fb[:,:,:,nxs,nxs]*dGdf[1][nxs,:,:,:,:],axis=1)
1824        dfbdGf = np.sum(fb[:,:,:,nxs,nxs]*dGdf[0][nxs,:,:,:,:]+fa[:,:,:,nxs,nxs]*dGdf[1][nxs,:,:,:,:],axis=1)
1825        dfadGx = np.sum(fa[:,:,:,nxs,nxs]*dGdx[0][nxs,:,:,:,:]-fb[:,:,:,nxs,nxs]*dGdx[1][nxs,:,:,:,:],axis=1)
1826        dfbdGx = np.sum(fb[:,:,:,nxs,nxs]*dGdx[0][nxs,:,:,:,:]+fa[:,:,:,nxs,nxs]*dGdx[1][nxs,:,:,:,:],axis=1)
1827        dfadGz = np.sum(fa[:,:,0,nxs,nxs]*dGdz[0][nxs,:,:,:]-fb[:,:,0,nxs,nxs]*dGdz[1][nxs,:,:,:],axis=1)
1828        dfbdGz = np.sum(fb[:,:,0,nxs,nxs]*dGdz[0][nxs,:,:,:]+fa[:,:,0,nxs,nxs]*dGdz[1][nxs,:,:,:],axis=1)
1829        dfadGu = np.sum(fa[:,:,:,nxs,nxs]*dGdu[0][nxs,:,:,:,:]-fb[:,:,:,nxs,nxs]*dGdu[1][nxs,:,:,:,:],axis=1)
1830        dfbdGu = np.sum(fb[:,:,:,nxs,nxs]*dGdu[0][nxs,:,:,:,:]+fa[:,:,:,nxs,nxs]*dGdu[1][nxs,:,:,:,:],axis=1)   
1831        if not SGData['SGInv']:   #Flack derivative
1832            dfadfl = np.sum(-FPP*Tcorr*sinp)
1833            dfbdfl = np.sum(FPP*Tcorr*cosp)
1834        else:
1835            dfadfl = 1.0
1836            dfbdfl = 1.0
1837#        GSASIIpath.IPyBreak()
1838        #NB: the above have been checked against PA(1:10,1:2) in strfctr.for for Al2O3!   
1839        SA = fas[0]+fas[1]      #float = A+A'
1840        SB = fbs[0]+fbs[1]      #float = B+B'
1841        if 'P' in calcControls[hfx+'histType']: #checked perfect for centro & noncentro?
1842            dFdfl[iref] = -SA*dfadfl-SB*dfbdfl                  #array(nRef,)
1843            dFdfr[iref] = 2.*(fas[0]*dfadfr[0]+fas[1]*dfadfr[1])*Mdata/len(Uniq)+   \
1844                2.*(fbs[0]*dfbdfr[0]-fbs[1]*dfbdfr[1])*Mdata/len(Uniq)
1845            dFdx[iref] = 2.*(fas[0]*dfadx[0]+fas[1]*dfadx[1])+  \
1846                2.*(fbs[0]*dfbdx[0]+fbs[1]*dfbdx[1])
1847            dFdui[iref] = 2.*(fas[0]*dfadui[0]+fas[1]*dfadui[1])+   \
1848                2.*(fbs[0]*dfbdui[0]-fbs[1]*dfbdui[1])
1849            dFdua[iref] = 2.*(fas[0]*dfadua[0]+fas[1]*dfadua[1])+   \
1850                2.*(fbs[0]*dfbdua[0]+fbs[1]*dfbdua[1])
1851            dFdGf[iref] = 2.*(fas[0]*dfadGf[0]+fas[1]*dfadGf[1])+  \
1852                2.*(fbs[0]*dfbdGf[0]+fbs[1]*dfbdGf[1])
1853            dFdGx[iref] = 2.*(fas[0]*dfadGx[0]+fas[1]*dfadGx[1])+  \
1854                2.*(fbs[0]*dfbdGx[0]-fbs[1]*dfbdGx[1])
1855            dFdGz[iref] = 2.*(fas[0]*dfadGz[0]+fas[1]*dfadGz[1])+  \
1856                2.*(fbs[0]*dfbdGz[0]+fbs[1]*dfbdGz[1])
1857            dFdGu[iref] = 2.*(fas[0]*dfadGu[0]+fas[1]*dfadGu[1])+  \
1858                2.*(fbs[0]*dfbdGu[0]+fbs[1]*dfbdGu[1])
1859        else:                       #OK, I think
1860            dFdfr[iref] = 2.*(SA*dfadfr[0]+SA*dfadfr[1]+SB*dfbdfr[0]+SB*dfbdfr[1])*Mdata/len(Uniq) #array(nRef,nAtom)
1861            dFdx[iref] = 2.*(SA*dfadx[0]+SA*dfadx[1]+SB*dfbdx[0]+SB*dfbdx[1])    #array(nRef,nAtom,3)
1862            dFdui[iref] = 2.*(SA*dfadui[0]+SA*dfadui[1]+SB*dfbdui[0]+SB*dfbdui[1])   #array(nRef,nAtom)
1863            dFdua[iref] = 2.*(SA*dfadua[0]+SA*dfadua[1]+SB*dfbdua[0]+SB*dfbdua[1])    #array(nRef,nAtom,6)
1864            dFdfl[iref] = -SA*dfadfl-SB*dfbdfl                  #array(nRef,)
1865                           
1866            dFdGf[iref] = 2.*(SA*dfadGf[0]+SB*dfbdGf[1])      #array(nRef,natom,nwave,2)
1867            dFdGx[iref] = 2.*(SA*dfadGx[0]+SB*dfbdGx[1])      #array(nRef,natom,nwave,6)
1868            dFdGz[iref] = 2.*(SA*dfadGz[0]+SB*dfbdGz[1])      #array(nRef,natom,5)
1869            dFdGu[iref] = 2.*(SA*dfadGu[0]+SB*dfbdGu[1])      #array(nRef,natom,nwave,12)
1870#            GSASIIpath.IPyBreak()
1871        dFdbab[iref] = 2.*fas[0]*np.array([np.sum(dfadba*dBabdA),np.sum(-dfadba*parmDict[phfx+'BabA']*SQfactor*dBabdA)]).T+ \
1872            2.*fbs[0]*np.array([np.sum(dfbdba*dBabdA),np.sum(-dfbdba*parmDict[phfx+'BabA']*SQfactor*dBabdA)]).T
1873        #loop over atoms - each dict entry is list of derivatives for all the reflections
1874        if not iref%100 :
1875            print ' %d derivative time %.4f\r'%(iref,time.time()-time0),
1876    for i in range(len(Mdata)):     #loop over atoms
1877        dFdvDict[pfx+'Afrac:'+str(i)] = dFdfr.T[i]
1878        dFdvDict[pfx+'dAx:'+str(i)] = dFdx.T[0][i]
1879        dFdvDict[pfx+'dAy:'+str(i)] = dFdx.T[1][i]
1880        dFdvDict[pfx+'dAz:'+str(i)] = dFdx.T[2][i]
1881        dFdvDict[pfx+'AUiso:'+str(i)] = dFdui.T[i]
1882        dFdvDict[pfx+'AU11:'+str(i)] = dFdua.T[0][i]
1883        dFdvDict[pfx+'AU22:'+str(i)] = dFdua.T[1][i]
1884        dFdvDict[pfx+'AU33:'+str(i)] = dFdua.T[2][i]
1885        dFdvDict[pfx+'AU12:'+str(i)] = 2.*dFdua.T[3][i]
1886        dFdvDict[pfx+'AU13:'+str(i)] = 2.*dFdua.T[4][i]
1887        dFdvDict[pfx+'AU23:'+str(i)] = 2.*dFdua.T[5][i]
1888        for j in range(FSSdata.shape[1]):        #loop over waves Fzero & Fwid?
1889            dFdvDict[pfx+'Fsin:'+str(i)+':'+str(j)] = dFdGf.T[0][j][i]
1890            dFdvDict[pfx+'Fcos:'+str(i)+':'+str(j)] = dFdGf.T[1][j][i]
1891        nx = 0
1892        if waveTypes[i] in ['Block','ZigZag']:
1893            nx = 1 
1894            dFdvDict[pfx+'Tmin:'+str(i)+':0'] = dFdGz.T[0][i]   #ZigZag/Block waves (if any)
1895            dFdvDict[pfx+'Tmax:'+str(i)+':0'] = dFdGz.T[1][i]
1896            dFdvDict[pfx+'Xmax:'+str(i)+':0'] = dFdGz.T[2][i]
1897            dFdvDict[pfx+'Ymax:'+str(i)+':0'] = dFdGz.T[3][i]
1898            dFdvDict[pfx+'Zmax:'+str(i)+':0'] = dFdGz.T[4][i]
1899        for j in range(XSSdata.shape[1]-nx):       #loop over waves
1900            dFdvDict[pfx+'Xsin:'+str(i)+':'+str(j+nx)] = dFdGx.T[0][j][i]
1901            dFdvDict[pfx+'Ysin:'+str(i)+':'+str(j+nx)] = dFdGx.T[1][j][i]
1902            dFdvDict[pfx+'Zsin:'+str(i)+':'+str(j+nx)] = dFdGx.T[2][j][i]
1903            dFdvDict[pfx+'Xcos:'+str(i)+':'+str(j+nx)] = dFdGx.T[3][j][i]
1904            dFdvDict[pfx+'Ycos:'+str(i)+':'+str(j+nx)] = dFdGx.T[4][j][i]
1905            dFdvDict[pfx+'Zcos:'+str(i)+':'+str(j+nx)] = dFdGx.T[5][j][i]
1906        for j in range(USSdata.shape[1]):       #loop over waves
1907            dFdvDict[pfx+'U11sin:'+str(i)+':'+str(j)] = dFdGu.T[0][j][i]
1908            dFdvDict[pfx+'U22sin:'+str(i)+':'+str(j)] = dFdGu.T[1][j][i]
1909            dFdvDict[pfx+'U33sin:'+str(i)+':'+str(j)] = dFdGu.T[2][j][i]
1910            dFdvDict[pfx+'U12sin:'+str(i)+':'+str(j)] = 2.*dFdGu.T[3][j][i]
1911            dFdvDict[pfx+'U13sin:'+str(i)+':'+str(j)] = 2.*dFdGu.T[4][j][i]
1912            dFdvDict[pfx+'U23sin:'+str(i)+':'+str(j)] = 2.*dFdGu.T[5][j][i]
1913            dFdvDict[pfx+'U11cos:'+str(i)+':'+str(j)] = dFdGu.T[6][j][i]
1914            dFdvDict[pfx+'U22cos:'+str(i)+':'+str(j)] = dFdGu.T[7][j][i]
1915            dFdvDict[pfx+'U33cos:'+str(i)+':'+str(j)] = dFdGu.T[8][j][i]
1916            dFdvDict[pfx+'U12cos:'+str(i)+':'+str(j)] = 2.*dFdGu.T[9][j][i]
1917            dFdvDict[pfx+'U13cos:'+str(i)+':'+str(j)] = 2.*dFdGu.T[10][j][i]
1918            dFdvDict[pfx+'U23cos:'+str(i)+':'+str(j)] = 2.*dFdGu.T[11][j][i]
1919           
1920#        GSASIIpath.IPyBreak()
1921    dFdvDict[phfx+'Flack'] = 4.*dFdfl.T
1922    dFdvDict[phfx+'BabA'] = dFdbab.T[0]
1923    dFdvDict[phfx+'BabU'] = dFdbab.T[1]
1924    return dFdvDict
1925
1926def SStructureFactorDerv2(refDict,im,G,hfx,pfx,SGData,SSGData,calcControls,parmDict):
1927    'Needs a doc string - no twins'
1928    phfx = pfx.split(':')[0]+hfx
1929    ast = np.sqrt(np.diag(G))
1930    Mast = twopisq*np.multiply.outer(ast,ast)
1931    SGInv = SGData['SGInv']
1932    SGMT = np.array([ops[0].T for ops in SGData['SGOps']])
1933    SGT = np.array([ops[1] for ops in SGData['SGOps']])
1934    SSGMT = np.array([ops[0].T for ops in SSGData['SSGOps']])
1935    SSGT = np.array([ops[1] for ops in SSGData['SSGOps']])
1936    FFtables = calcControls['FFtables']
1937    BLtables = calcControls['BLtables']
1938    nRef = len(refDict['RefList'])
1939    Tdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata = GetAtomFXU(pfx,calcControls,parmDict)
1940    mSize = len(Mdata)  #no. atoms
1941    waveTypes,FSSdata,XSSdata,USSdata,MSSdata = GetAtomSSFXU(pfx,calcControls,parmDict)
1942    ngl,nWaves,Fmod,Xmod,Umod,glTau,glWt = G2mth.makeWaves(waveTypes,FSSdata,XSSdata,USSdata,Mast)
1943    waveShapes,SCtauF,SCtauX,SCtauU,UmodAB = G2mth.makeWavesDerv(ngl,waveTypes,FSSdata,XSSdata,USSdata,Mast)
1944    modQ = np.array([parmDict[pfx+'mV0'],parmDict[pfx+'mV1'],parmDict[pfx+'mV2']])
1945    FF = np.zeros(len(Tdata))
1946    if 'NC' in calcControls[hfx+'histType']:
1947        FP,FPP = G2el.BlenResCW(Tdata,BLtables,parmDict[hfx+'Lam'])
1948    elif 'X' in calcControls[hfx+'histType']:
1949        FP = np.array([FFtables[El][hfx+'FP'] for El in Tdata])
1950        FPP = np.array([FFtables[El][hfx+'FPP'] for El in Tdata])
1951    Uij = np.array(G2lat.U6toUij(Uijdata)).T
1952    bij = Mast*Uij
1953    if not len(refDict['FF']):
1954        if 'N' in calcControls[hfx+'histType']:
1955            dat = G2el.getBLvalues(BLtables)        #will need wave here for anom. neutron b's
1956        else:
1957            dat = G2el.getFFvalues(FFtables,0.)       
1958        refDict['FF']['El'] = dat.keys()
1959        refDict['FF']['FF'] = np.zeros((len(refDict['RefList']),len(dat)))
1960    dFdvDict = {}
1961    dFdfr = np.zeros((nRef,mSize))
1962    dFdx = np.zeros((nRef,mSize,3))
1963    dFdui = np.zeros((nRef,mSize))
1964    dFdua = np.zeros((nRef,mSize,6))
1965    dFdbab = np.zeros((nRef,2))
1966    dFdfl = np.zeros((nRef))
1967    dFdtw = np.zeros((nRef))
1968    dFdGf = np.zeros((nRef,mSize,FSSdata.shape[1],2))
1969    dFdGx = np.zeros((nRef,mSize,XSSdata.shape[1],6))
1970    dFdGz = np.zeros((nRef,mSize,5))
1971    dFdGu = np.zeros((nRef,mSize,USSdata.shape[1],12))
1972    Flack = 1.0
1973    if not SGData['SGInv'] and 'S' in calcControls[hfx+'histType'] and phfx+'Flack' in parmDict:
1974        Flack = 1.-2.*parmDict[phfx+'Flack']
1975    time0 = time.time()
1976    iBeg = 0
1977    blkSize = 4       #no. of reflections in a block - optimized for speed
1978    while iBeg < nRef:
1979        iFin = min(iBeg+blkSize,nRef)
1980        refl = refDict['RefList'][iBeg:iFin]    #array(blkSize,nItems)
1981        H = refl.T[:4]
1982        HP = H[:3].T+modQ*H.T[:,3:]            #projected hklm to hkl
1983        SQ = 1./(2.*refl.T[4+im])**2             # or (sin(theta)/lambda)**2
1984        SQfactor = 8.0*SQ*np.pi**2
1985        if 'T' in calcControls[hfx+'histType']:
1986            if 'P' in calcControls[hfx+'histType']:
1987                FP,FPP = G2el.BlenResTOF(Tdata,BLtables,refl.T[15])
1988            else:
1989                FP,FPP = G2el.BlenResTOF(Tdata,BLtables,refl.T[13])
1990            FP = np.repeat(FP.T,len(SGT),axis=0)
1991            FPP = np.repeat(FPP.T,len(SGT),axis=0)
1992        dBabdA = np.exp(-parmDict[phfx+'BabU']*SQfactor)
1993        Bab = np.repeat(parmDict[phfx+'BabA']*np.exp(-parmDict[phfx+'BabU']*SQfactor),len(SGT))
1994        Tindx = np.array([refDict['FF']['El'].index(El) for El in Tdata])
1995        FF = np.repeat(refDict['FF']['FF'][iBeg:iFin].T[Tindx].T,len(SGT),axis=0)
1996        Uniq = np.inner(H.T,SSGMT)
1997        Phi = np.inner(H.T,SSGT)
1998        UniqP = np.inner(HP,SGMT)
1999        if SGInv:   #if centro - expand HKL sets
2000            Uniq = np.hstack((Uniq,-Uniq))
2001            Phi = np.hstack((Phi,-Phi))
2002            UniqP = np.hstack((UniqP,-UniqP))
2003            FF = np.vstack((FF,FF))
2004            Bab = np.concatenate((Bab,Bab))
2005        phase = twopi*(np.inner(Uniq[:,:,:3],(dXdata+Xdata).T)+Phi[:,:,nxs])
2006        sinp = np.sin(phase)
2007        cosp = np.cos(phase)
2008        occ = Mdata*Fdata/Uniq.shape[1]
2009        biso = -SQfactor*Uisodata[:,nxs]
2010        Tiso = np.repeat(np.where(biso<1.,np.exp(biso),1.0),Uniq.shape[1],axis=1).T    #ops x atoms
2011        HbH = -np.sum(UniqP[:,:,nxs,:3]*np.inner(UniqP[:,:,:3],bij),axis=-1)  #ops x atoms
2012        Hij = np.array([Mast*np.multiply.outer(U[:3],U[:3]) for U in np.reshape(UniqP,(-1,3))]) #atoms x 3x3
2013        Hij = np.reshape(np.array([G2lat.UijtoU6(Uij) for Uij in Hij]),(iFin-iBeg,-1,6))                     #atoms x 6
2014        Tuij = np.where(HbH<1.,np.exp(HbH),1.0)     #ops x atoms
2015#        GSASIIpath.IPyBreak()
2016        Tcorr = np.reshape(Tiso,Tuij.shape)*Tuij*Mdata*Fdata/Uniq.shape[0]  #ops x atoms
2017        fot = np.reshape(FF+FP[nxs,:]-Bab[:,nxs],cosp.shape)*Tcorr     #ops x atoms
2018        fotp = FPP*Tcorr            #ops x atoms
2019        GfpuA = G2mth.Modulation(Uniq,UniqP,nWaves,Fmod,Xmod,Umod,glTau,glWt) #2 x sym X atoms
2020        dGdf,dGdx,dGdu,dGdz = G2mth.ModulationDerv2(Uniq,UniqP,Hij,nWaves,waveShapes,Fmod,Xmod,UmodAB,SCtauF,SCtauX,SCtauU,glTau,glWt)
2021        # GfpuA is 2 x ops x atoms
2022        # derivs are: ops x atoms x waves x 2,6,12, or 5 parms as [real,imag] parts
2023        fa = np.array([fot*cosp,-Flack*FPP*sinp*Tcorr]) # array(2,nEqv,nAtoms)
2024        fb = np.array([fot*sinp,Flack*FPP*cosp*Tcorr])  #or array(2,nEqv,nAtoms)
2025        fag = fa*GfpuA[0]-fb*GfpuA[1]
2026        fbg = fb*GfpuA[0]+fa*GfpuA[1]
2027       
2028        fas = np.sum(np.sum(fag,axis=-1),axis=-1)     # 2 x refBlk
2029        fbs = np.sum(np.sum(fbg,axis=-1),axis=-1)
2030        fax = np.array([-fot*sinp,-fotp*cosp])   #positions; 2 x ops x atoms
2031        fbx = np.array([fot*cosp,-fotp*sinp])
2032        fax = fax*GfpuA[0]-fbx*GfpuA[1]
2033        fbx = fbx*GfpuA[0]+fax*GfpuA[1]
2034        #sum below is over Uniq
2035        dfadfr = np.sum(fag/occ,axis=-2)        #Fdata != 0 ever avoids /0. problem
2036        dfbdfr = np.sum(fbg/occ,axis=-2)        #Fdata != 0 avoids /0. problem
2037        dfadba = np.sum(-cosp*Tcorr,axis=-2)
2038        dfbdba = np.sum(-sinp*Tcorr,axis=-2)
2039        dfadui = np.sum(-SQfactor[nxs,:,nxs,nxs]*fag,axis=-2)
2040        dfbdui = np.sum(-SQfactor[nxs,:,nxs,nxs]*fbg,axis=-2)
2041        dfadx = np.sum(twopi*Uniq[nxs,:,:,nxs,:3]*fax[:,:,:,:,nxs],axis=-3)  #2 refBlk x x nAtom x 3xyz; sum nOps
2042        dfbdx = np.sum(twopi*Uniq[nxs,:,:,nxs,:3]*fbx[:,:,:,:,nxs],axis=-3)  #2 refBlk x x nAtom x 3xyz; sum nOps
2043        dfadua = np.sum(-Hij[nxs,:,:,nxs,:]*fag[:,:,:,:,nxs],axis=-3)             #2 x nAtom x 6Uij; sum nOps
2044        dfbdua = np.sum(-Hij[nxs,:,:,nxs,:]*fbg[:,:,:,:,nxs],axis=-3)             #2 x nAtom x 6Uij; sum nOps
2045        # array(2,nAtom,nWave,2) & array(2,nAtom,nWave,6) & array(2,nAtom,nWave,12); sum on nOps
2046        dfadGf = np.sum(fa[:,:,:,:,nxs,nxs]*dGdf[0][nxs,:,nxs,:,:,:]-fb[:,:,:,:,nxs,nxs]*dGdf[1][nxs,:,nxs,:,:,:],axis=2)
2047        dfbdGf = np.sum(fb[:,:,:,:,nxs,nxs]*dGdf[0][nxs,:,nxs,:,:,:]+fa[:,:,:,:,nxs,nxs]*dGdf[1][nxs,:,nxs,:,:,:],axis=2)
2048        dfadGx = np.sum(fa[:,:,:,:,nxs,nxs]*dGdx[0][nxs,:,:,:,:,:]-fb[:,:,:,:,nxs,nxs]*dGdx[1][nxs,:,:,:,:,:],axis=2)
2049        dfbdGx = np.sum(fb[:,:,:,:,nxs,nxs]*dGdx[0][nxs,:,:,:,:,:]+fa[:,:,:,:,nxs,nxs]*dGdx[1][nxs,:,:,:,:,:],axis=2)
2050        dfadGz = np.sum(fa[:,:,:,:,nxs]*dGdz[0][nxs,:,:,:,:]-fb[:,:,:,:,nxs]*dGdz[1][nxs,:,:,:,:],axis=2)
2051        dfbdGz = np.sum(fb[:,:,:,:,nxs]*dGdz[0][nxs,:,:,:,:]+fa[:,:,:,:,nxs]*dGdz[1][nxs,:,:,:,:],axis=2)
2052        dfadGu = np.sum(fa[:,:,:,:,nxs,nxs]*dGdu[0][nxs,:,:,:,:]-fb[:,:,:,:,nxs,nxs]*dGdu[1][nxs,:,:,:,:],axis=2)
2053        dfbdGu = np.sum(fb[:,:,:,:,nxs,nxs]*dGdu[0][nxs,:,:,:,:]+fa[:,:,:,:,nxs,nxs]*dGdu[1][nxs,:,:,:,:],axis=2)   
2054        if not SGData['SGInv']:   #Flack derivative
2055            dfadfl = np.sum(np.sum(-FPP*Tcorr*sinp,axis=-1),axis=-1)
2056            dfbdfl = np.sum(np.sum(FPP*Tcorr*cosp,axis=-1),axis=-1)
2057        else:
2058            dfadfl = 1.0
2059            dfbdfl = 1.0
2060        #NB: the above have been checked against PA(1:10,1:2) in strfctr.for for Al2O3!   
2061        SA = fas[0]+fas[1]      #float = A+A' (might be array[nTwin])
2062        SB = fbs[0]+fbs[1]      #float = B+B' (might be array[nTwin])
2063        if 'P' in calcControls[hfx+'histType']: #checked perfect for centro & noncentro?
2064            dFdfl[iBeg:iFin] = -SA*dfadfl-SB*dfbdfl                  #array(nRef,)
2065            dFdfr[iBeg:iFin] = 2.*(fas[0,:,nxs]*dfadfr[0]+fas[1,:,nxs]*dfadfr[1])*Mdata/len(Uniq)+   \
2066                2.*(fbs[0,:,nxs]*dfbdfr[0]-fbs[1,:,nxs]*dfbdfr[1])*Mdata/len(Uniq)
2067            dFdx[iBeg:iFin] = 2.*(fas[0,:,nxs,nxs]*dfadx[0]+fas[1,:,nxs,nxs]*dfadx[1])+  \
2068                2.*(fbs[0,:,nxs,nxs]*dfbdx[0]+fbs[1,:,nxs,nxs]*dfbdx[1])
2069            dFdui[iBeg:iFin] = 2.*(fas[0,:,nxs]*dfadui[0]+fas[1,:,nxs]*dfadui[1])+   \
2070                2.*(fbs[0,:,nxs]*dfbdui[0]-fbs[1,:,nxs]*dfbdui[1])
2071            dFdua[iBeg:iFin] = 2.*(fas[0,:,nxs,nxs]*dfadua[0]+fas[1,:,nxs,nxs]*dfadua[1])+   \
2072                2.*(fbs[0,:,nxs,nxs]*dfbdua[0]+fbs[1,:,nxs,nxs]*dfbdua[1])
2073            dFdGf[iBeg:iFin] = 2.*(fas[0,:,nxs,nxs,nxs]*dfadGf[0]+fas[1,:,nxs,nxs,nxs]*dfadGf[1])+  \
2074                2.*(fbs[0,:,nxs,nxs,nxs]*dfbdGf[0]+fbs[1,:,nxs,nxs,nxs]*dfbdGf[1])
2075            dFdGx[iBeg:iFin] = 2.*(fas[0,:,nxs,nxs,nxs]*dfadGx[0]+fas[1,:,nxs,nxs,nxs]*dfadGx[1])+  \
2076                2.*(fbs[0,:,nxs,nxs,nxs]*dfbdGx[0]-fbs[1,:,nxs,nxs,nxs]*dfbdGx[1])
2077            dFdGz[iBeg:iFin] = 2.*(fas[0,:,nxs,nxs]*dfadGz[0]+fas[1,:,nxs,nxs]*dfadGz[1])+  \
2078                2.*(fbs[0,:,nxs,nxs]*dfbdGz[0]+fbs[1,:,nxs,nxs]*dfbdGz[1])
2079            dFdGu[iBeg:iFin] = 2.*(fas[0,:,nxs,nxs,nxs]*dfadGu[0]+fas[1,:,nxs,nxs,nxs]*dfadGu[1])+  \
2080                2.*(fbs[0,:,nxs,nxs,nxs]*dfbdGu[0]+fbs[1,:,nxs,nxs,nxs]*dfbdGu[1])
2081        else:                       #OK, I think
2082            dFdfr[iBeg:iFin] = 2.*(SA[:,nxs]*(dfadfr[0]+dfadfr[1])+SB[:,nxs]*(dfbdfr[0]+dfbdfr[1]))*Mdata/len(Uniq) #array(nRef,nAtom)
2083            dFdx[iBeg:iFin] = 2.*(SA[:,nxs,nxs]*(dfadx[0]+dfadx[1])+SB[:,nxs,nxs]*(dfbdx[0]+dfbdx[1]))    #array(nRef,nAtom,3)
2084            dFdui[iBeg:iFin] = 2.*(SA[:,nxs]*(dfadui[0]+dfadui[1])+SB[:,nxs]*(dfbdui[0]+dfbdui[1]))   #array(nRef,nAtom)
2085            dFdua[iBeg:iFin] = 2.*(SA[:,nxs,nxs]*(dfadua[0]+dfadua[1])+SB[:,nxs,nxs]*(dfbdua[0]+dfbdua[1]))    #array(nRef,nAtom,6)
2086            dFdfl[iBeg:iFin] = -SA*dfadfl-SB*dfbdfl                  #array(nRef,)
2087                           
2088            dFdGf[iBeg:iFin] = 2.*(SA[:,nxs,nxs,nxs]*dfadGf[0]+SB[:,nxs,nxs,nxs]*dfbdGf[1])      #array(nRef,natom,nwave,2)
2089            dFdGx[iBeg:iFin] = 2.*(SA[:,nxs,nxs,nxs]*dfadGx[0]+SB[:,nxs,nxs,nxs]*dfbdGx[1])      #array(nRef,natom,nwave,6)
2090            dFdGz[iBeg:iFin] = 2.*(SA[:,nxs,nxs]*dfadGz[0]+SB[:,nxs,nxs]*dfbdGz[1])      #array(nRef,natom,5)
2091            dFdGu[iBeg:iFin] = 2.*(SA[:,nxs,nxs,nxs]*dfadGu[0]+SB[:,nxs,nxs,nxs]*dfbdGu[1])      #array(nRef,natom,nwave,12)
2092#            GSASIIpath.IPyBreak()
2093#        dFdbab[iBeg:iFin] = 2.*fas[0,:,nxs]*np.array([np.sum(dfadba*dBabdA),np.sum(-dfadba*parmDict[phfx+'BabA']*SQfactor*dBabdA)]).T+ \
2094#            2.*fbs[0,:,nxs]*np.array([np.sum(dfbdba*dBabdA),np.sum(-dfbdba*parmDict[phfx+'BabA']*SQfactor*dBabdA)]).T
2095        #loop over atoms - each dict entry is list of derivatives for all the reflections
2096        print ' %d derivative time %.4f\r'%(iBeg,time.time()-time0),
2097        iBeg += blkSize
2098    for i in range(len(Mdata)):     #loop over atoms
2099        dFdvDict[pfx+'Afrac:'+str(i)] = dFdfr.T[i]
2100        dFdvDict[pfx+'dAx:'+str(i)] = dFdx.T[0][i]
2101        dFdvDict[pfx+'dAy:'+str(i)] = dFdx.T[1][i]
2102        dFdvDict[pfx+'dAz:'+str(i)] = dFdx.T[2][i]
2103        dFdvDict[pfx+'AUiso:'+str(i)] = dFdui.T[i]
2104        dFdvDict[pfx+'AU11:'+str(i)] = dFdua.T[0][i]
2105        dFdvDict[pfx+'AU22:'+str(i)] = dFdua.T[1][i]
2106        dFdvDict[pfx+'AU33:'+str(i)] = dFdua.T[2][i]
2107        dFdvDict[pfx+'AU12:'+str(i)] = 2.*dFdua.T[3][i]
2108        dFdvDict[pfx+'AU13:'+str(i)] = 2.*dFdua.T[4][i]
2109        dFdvDict[pfx+'AU23:'+str(i)] = 2.*dFdua.T[5][i]
2110        for j in range(FSSdata.shape[1]):        #loop over waves Fzero & Fwid?
2111            dFdvDict[pfx+'Fsin:'+str(i)+':'+str(j)] = dFdGf.T[0][j][i]
2112            dFdvDict[pfx+'Fcos:'+str(i)+':'+str(j)] = dFdGf.T[1][j][i]
2113        nx = 0
2114        if waveTypes[i] in ['Block','ZigZag']:
2115            nx = 1 
2116            dFdvDict[pfx+'Tmin:'+str(i)+':0'] = dFdGz.T[0][i]   #ZigZag/Block waves (if any)
2117            dFdvDict[pfx+'Tmax:'+str(i)+':0'] = dFdGz.T[1][i]
2118            dFdvDict[pfx+'Xmax:'+str(i)+':0'] = dFdGz.T[2][i]
2119            dFdvDict[pfx+'Ymax:'+str(i)+':0'] = dFdGz.T[3][i]
2120            dFdvDict[pfx+'Zmax:'+str(i)+':0'] = dFdGz.T[4][i]
2121        for j in range(XSSdata.shape[1]-nx):       #loop over waves
2122            dFdvDict[pfx+'Xsin:'+str(i)+':'+str(j+nx)] = dFdGx.T[0][j][i]
2123            dFdvDict[pfx+'Ysin:'+str(i)+':'+str(j+nx)] = dFdGx.T[1][j][i]
2124            dFdvDict[pfx+'Zsin:'+str(i)+':'+str(j+nx)] = dFdGx.T[2][j][i]
2125            dFdvDict[pfx+'Xcos:'+str(i)+':'+str(j+nx)] = dFdGx.T[3][j][i]
2126            dFdvDict[pfx+'Ycos:'+str(i)+':'+str(j+nx)] = dFdGx.T[4][j][i]
2127            dFdvDict[pfx+'Zcos:'+str(i)+':'+str(j+nx)] = dFdGx.T[5][j][i]
2128        for j in range(USSdata.shape[1]):       #loop over waves
2129            dFdvDict[pfx+'U11sin:'+str(i)+':'+str(j)] = dFdGu.T[0][j][i]
2130            dFdvDict[pfx+'U22sin:'+str(i)+':'+str(j)] = dFdGu.T[1][j][i]
2131            dFdvDict[pfx+'U33sin:'+str(i)+':'+str(j)] = dFdGu.T[2][j][i]
2132            dFdvDict[pfx+'U12sin:'+str(i)+':'+str(j)] = 2.*dFdGu.T[3][j][i]
2133            dFdvDict[pfx+'U13sin:'+str(i)+':'+str(j)] = 2.*dFdGu.T[4][j][i]
2134            dFdvDict[pfx+'U23sin:'+str(i)+':'+str(j)] = 2.*dFdGu.T[5][j][i]
2135            dFdvDict[pfx+'U11cos:'+str(i)+':'+str(j)] = dFdGu.T[6][j][i]
2136            dFdvDict[pfx+'U22cos:'+str(i)+':'+str(j)] = dFdGu.T[7][j][i]
2137            dFdvDict[pfx+'U33cos:'+str(i)+':'+str(j)] = dFdGu.T[8][j][i]
2138            dFdvDict[pfx+'U12cos:'+str(i)+':'+str(j)] = 2.*dFdGu.T[9][j][i]
2139            dFdvDict[pfx+'U13cos:'+str(i)+':'+str(j)] = 2.*dFdGu.T[10][j][i]
2140            dFdvDict[pfx+'U23cos:'+str(i)+':'+str(j)] = 2.*dFdGu.T[11][j][i]
2141           
2142#        GSASIIpath.IPyBreak()
2143    dFdvDict[phfx+'BabA'] = dFdbab.T[0]
2144    dFdvDict[phfx+'BabU'] = dFdbab.T[1]
2145    return dFdvDict
2146   
2147def SStructureFactorDervTw(refDict,im,G,hfx,pfx,SGData,SSGData,calcControls,parmDict):
2148    'Needs a doc string'
2149    phfx = pfx.split(':')[0]+hfx
2150    ast = np.sqrt(np.diag(G))
2151    Mast = twopisq*np.multiply.outer(ast,ast)
2152    SGInv = SGData['SGInv']
2153    SGMT = np.array([ops[0].T for ops in SGData['SGOps']])
2154    SGT = np.array([ops[1] for ops in SGData['SGOps']])
2155    SSGMT = np.array([ops[0].T for ops in SSGData['SSGOps']])
2156    SSGT = np.array([ops[1] for ops in SSGData['SSGOps']])
2157    FFtables = calcControls['FFtables']
2158    BLtables = calcControls['BLtables']
2159    TwinLaw = np.array([[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],])
2160    TwDict = refDict.get('TwDict',{})           
2161    if 'S' in calcControls[hfx+'histType']:
2162        NTL = calcControls[phfx+'NTL']
2163        NM = calcControls[phfx+'TwinNMN']+1
2164        TwinLaw = calcControls[phfx+'TwinLaw']
2165        TwinFr = np.array([parmDict[phfx+'TwinFr:'+str(i)] for i in range(len(TwinLaw))])
2166        TwinInv = list(np.where(calcControls[phfx+'TwinInv'],-1,1))
2167    nTwin = len(TwinLaw)       
2168    nRef = len(refDict['RefList'])
2169    Tdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata = GetAtomFXU(pfx,calcControls,parmDict)
2170    mSize = len(Mdata)  #no. atoms
2171    waveTypes,FSSdata,XSSdata,USSdata,MSSdata = GetAtomSSFXU(pfx,calcControls,parmDict)
2172    ngl,nWaves,Fmod,Xmod,Umod,glTau,glWt = G2mth.makeWaves(waveTypes,FSSdata,XSSdata,USSdata,Mast)
2173    waveShapes,SCtauF,SCtauX,SCtauU,UmodAB = G2mth.makeWavesDerv(ngl,waveTypes,FSSdata,XSSdata,USSdata,Mast)
2174    modQ = np.array([parmDict[pfx+'mV0'],parmDict[pfx+'mV1'],parmDict[pfx+'mV2']])
2175    FF = np.zeros(len(Tdata))
2176    if 'NC' in calcControls[hfx+'histType']:
2177        FP,FPP = G2el.BlenResCW(Tdata,BLtables,parmDict[hfx+'Lam'])
2178    elif 'X' in calcControls[hfx+'histType']:
2179        FP = np.array([FFtables[El][hfx+'FP'] for El in Tdata])
2180        FPP = np.array([FFtables[El][hfx+'FPP'] for El in Tdata])
2181    Uij = np.array(G2lat.U6toUij(Uijdata)).T
2182    bij = Mast*Uij
2183    if not len(refDict['FF']):
2184        if 'N' in calcControls[hfx+'histType']:
2185            dat = G2el.getBLvalues(BLtables)        #will need wave here for anom. neutron b's
2186        else:
2187            dat = G2el.getFFvalues(FFtables,0.)       
2188        refDict['FF']['El'] = dat.keys()
2189        refDict['FF']['FF'] = np.zeros((len(refDict['RefList']),len(dat)))
2190    dFdvDict = {}
2191    dFdfr = np.zeros((nRef,nTwin,mSize))
2192    dFdx = np.zeros((nRef,nTwin,mSize,3))
2193    dFdui = np.zeros((nRef,nTwin,mSize))
2194    dFdua = np.zeros((nRef,nTwin,mSize,6))
2195    dFdbab = np.zeros((nRef,nTwin,2))
2196    dFdfl = np.zeros((nRef,nTwin))
2197    dFdtw = np.zeros((nRef,nTwin))
2198    dFdGf = np.zeros((nRef,nTwin,mSize,FSSdata.shape[1]))
2199    dFdGx = np.zeros((nRef,nTwin,mSize,XSSdata.shape[1],3))
2200    dFdGz = np.zeros((nRef,nTwin,mSize,5))
2201    dFdGu = np.zeros((nRef,nTwin,mSize,USSdata.shape[1],6))
2202    Flack = 1.0
2203    if not SGData['SGInv'] and 'S' in calcControls[hfx+'histType'] and phfx+'Flack' in parmDict:
2204        Flack = 1.-2.*parmDict[phfx+'Flack']
2205    time0 = time.time()
2206    nRef = len(refDict['RefList'])/100
2207    for iref,refl in enumerate(refDict['RefList']):
2208        if 'T' in calcControls[hfx+'histType']:
2209            FP,FPP = G2el.BlenResCW(Tdata,BLtables,refl.T[12+im])
2210        H = np.array(refl[:4])
2211        HP = H[:3]+modQ*H[3:]            #projected hklm to hkl
2212        H = np.inner(H.T,TwinLaw)   #maybe array(4,nTwins) or (4)
2213        TwMask = np.any(H,axis=-1)
2214        if TwinLaw.shape[0] > 1 and TwDict:
2215            if iref in TwDict:
2216                for i in TwDict[iref]:
2217                    for n in range(NTL):
2218                        H[i+n*NM] = np.inner(TwinLaw[n*NM],np.array(TwDict[iref][i])*TwinInv[i+n*NM])
2219            TwMask = np.any(H,axis=-1)
2220        SQ = 1./(2.*refl[4+im])**2             # or (sin(theta)/lambda)**2
2221        SQfactor = 8.0*SQ*np.pi**2
2222        dBabdA = np.exp(-parmDict[phfx+'BabU']*SQfactor)
2223        Bab = parmDict[phfx+'BabA']*dBabdA
2224        Tindx = np.array([refDict['FF']['El'].index(El) for El in Tdata])
2225        FF = refDict['FF']['FF'][iref].T[Tindx]
2226        Uniq = np.inner(H,SSGMT)
2227        Phi = np.inner(H,SSGT)
2228        UniqP = np.inner(HP,SGMT)
2229        if SGInv:   #if centro - expand HKL sets
2230            Uniq = np.vstack((Uniq,-Uniq))
2231            Phi = np.hstack((Phi,-Phi))
2232            UniqP = np.vstack((UniqP,-UniqP))
2233        phase = twopi*(np.inner(Uniq[:,:3],(dXdata+Xdata).T)+Phi[:,nxs])
2234        sinp = np.sin(phase)
2235        cosp = np.cos(phase)
2236        occ = Mdata*Fdata/Uniq.shape[0]
2237        biso = -SQfactor*Uisodata[:,nxs]
2238        Tiso = np.repeat(np.where(biso<1.,np.exp(biso),1.0),Uniq.shape[0]*len(TwinLaw),axis=1).T    #ops x atoms
2239        HbH = -np.sum(UniqP[:,nxs,:3]*np.inner(UniqP[:,:3],bij),axis=-1)  #ops x atoms
2240        Hij = np.array([Mast*np.multiply.outer(U[:3],U[:3]) for U in UniqP]) #atoms x 3x3
2241        Hij = np.squeeze(np.reshape(np.array([G2lat.UijtoU6(Uij) for Uij in Hij]),(nTwin,-1,6)))
2242        Tuij = np.where(HbH<1.,np.exp(HbH),1.0)     #ops x atoms
2243        Tcorr = np.reshape(Tiso,Tuij.shape)*Tuij*Mdata*Fdata/Uniq.shape[0]  #ops x atoms
2244        fot = (FF+FP-Bab)*Tcorr     #ops x atoms
2245        fotp = FPP*Tcorr            #ops x atoms
2246        GfpuA = G2mth.Modulation(Uniq,UniqP,nWaves,Fmod,Xmod,Umod,glTau,glWt) #2 x sym X atoms
2247        dGdf,dGdx,dGdu,dGdz = G2mth.ModulationDerv(Uniq,UniqP,Hij,nWaves,waveShapes,Fmod,Xmod,UmodAB,SCtauF,SCtauX,SCtauU,glTau,glWt)
2248        # GfpuA is 2 x ops x atoms
2249        # derivs are: ops x atoms x waves x 2,6,12, or 5 parms as [real,imag] parts
2250        fa = np.array([((FF+FP).T-Bab).T*cosp*Tcorr,-Flack*FPP*sinp*Tcorr]) # array(2,nTwin,nEqv,nAtoms)
2251        fb = np.array([((FF+FP).T-Bab).T*sinp*Tcorr,Flack*FPP*cosp*Tcorr])  #or array(2,nEqv,nAtoms)
2252        fag = fa*GfpuA[0]-fb*GfpuA[1]
2253        fbg = fb*GfpuA[0]+fa*GfpuA[1]
2254       
2255        fas = np.sum(np.sum(fag,axis=1),axis=1)     # 2 x twin
2256        fbs = np.sum(np.sum(fbg,axis=1),axis=1)
2257        fax = np.array([-fot*sinp,-fotp*cosp])   #positions; 2 x twin x ops x atoms
2258        fbx = np.array([fot*cosp,-fotp*sinp])
2259        fax = fax*GfpuA[0]-fbx*GfpuA[1]
2260        fbx = fbx*GfpuA[0]+fax*GfpuA[1]
2261        #sum below is over Uniq
2262        dfadfr = np.sum(fag/occ,axis=1)        #Fdata != 0 ever avoids /0. problem
2263        dfbdfr = np.sum(fbg/occ,axis=1)        #Fdata != 0 avoids /0. problem
2264        dfadba = np.sum(-cosp*Tcorr[:,nxs],axis=1)
2265        dfbdba = np.sum(-sinp*Tcorr[:,nxs],axis=1)
2266        dfadui = np.sum(-SQfactor*fag,axis=1)
2267        dfbdui = np.sum(-SQfactor*fbg,axis=1)
2268        dfadx = np.array([np.sum(twopi*Uniq[it,:,:3]*np.swapaxes(fax,-2,-1)[:,it,:,:,nxs],axis=-2) for it in range(nTwin)])
2269        dfbdx = np.array([np.sum(twopi*Uniq[it,:,:3]*np.swapaxes(fbx,-2,-1)[:,it,:,:,nxs],axis=-2) for it in range(nTwin)])           
2270        dfadua = np.array([np.sum(-Hij[it]*np.swapaxes(fag,-2,-1)[:,it,:,:,nxs],axis=-2) for it in range(nTwin)])
2271        dfbdua = np.array([np.sum(-Hij[it]*np.swapaxes(fbg,-2,-1)[:,it,:,:,nxs],axis=-2) for it in range(nTwin)])
2272        # array(2,nTwin,nAtom,3) & array(2,nTwin,nAtom,6) & array(2,nTwin,nAtom,12)
2273        dfadGf = np.sum(fa[:,it,:,:,nxs,nxs]*dGdf[0][nxs,nxs,:,:,:,:]-fb[:,it,:,:,nxs,nxs]*dGdf[1][nxs,nxs,:,:,:,:],axis=1)
2274        dfbdGf = np.sum(fb[:,it,:,:,nxs,nxs]*dGdf[0][nxs,nxs,:,:,:,:]+fa[:,it,:,:,nxs,nxs]*dGdf[1][nxs,nxs,:,:,:,:],axis=1)
2275        dfadGx = np.sum(fa[:,it,:,:,nxs,nxs]*dGdx[0][nxs,nxs,:,:,:,:]-fb[:,it,:,:,nxs,nxs]*dGdx[1][nxs,nxs,:,:,:,:],axis=1)
2276        dfbdGx = np.sum(fb[:,it,:,:,nxs,nxs]*dGdx[0][nxs,nxs,:,:,:,:]+fa[:,it,:,:,nxs,nxs]*dGdx[1][nxs,nxs,:,:,:,:],axis=1)
2277        dfadGz = np.sum(fa[:,it,:,0,nxs,nxs]*dGdz[0][nxs,nxs,:,:,:]-fb[:,it,:,0,nxs,nxs]*dGdz[1][nxs,nxs,:,:,:],axis=1)
2278        dfbdGz = np.sum(fb[:,it,:,0,nxs,nxs]*dGdz[0][nxs,nxs,:,:,:]+fa[:,it,:,0,nxs,nxs]*dGdz[1][nxs,nxs,:,:,:],axis=1)
2279        dfadGu = np.sum(fa[:,it,:,:,nxs,nxs]*dGdu[0][nxs,nxs,:,:,:,:]-fb[:,it,:,:,nxs,nxs]*dGdu[1][nxs,nxs,:,:,:,:],axis=1)
2280        dfbdGu = np.sum(fb[:,it,:,:,nxs,nxs]*dGdu[0][nxs,nxs,:,:,:,:]+fa[:,it,:,:,nxs,nxs]*dGdu[1][nxs,nxs,:,:,:,:],axis=1)
2281#        GSASIIpath.IPyBreak()
2282        if not SGData['SGInv'] and len(TwinLaw) == 1:   #Flack derivative
2283            dfadfl = np.sum(-FPP*Tcorr*sinp)
2284            dfbdfl = np.sum(FPP*Tcorr*cosp)
2285        else:
2286            dfadfl = 1.0
2287            dfbdfl = 1.0
2288        #NB: the above have been checked against PA(1:10,1:2) in strfctr.for for Al2O3!   
2289        SA = fas[0]+fas[1]      #float = A+A' (might be array[nTwin])
2290        SB = fbs[0]+fbs[1]      #float = B+B' (might be array[nTwin])
2291        dFdfr[iref] = [2.*TwMask[it]*(SA[it]*dfadfr[0][it]+SA[it]*dfadfr[1][it]+SB[it]*dfbdfr[0][it]+SB[it]*dfbdfr[1][it])*Mdata/len(Uniq[it]) for it in range(nTwin)]
2292        dFdx[iref] = [2.*TwMask[it]*(SA[it]*dfadx[it][0]+SA[it]*dfadx[it][1]+SB[it]*dfbdx[it][0]+SB[it]*dfbdx[it][1]) for it in range(nTwin)]
2293        dFdui[iref] = [2.*TwMask[it]*(SA[it]*dfadui[it][0]+SA[it]*dfadui[it][1]+SB[it]*dfbdui[it][0]+SB[it]*dfbdui[it][1]) for it in range(nTwin)]
2294        dFdua[iref] = [2.*TwMask[it]*(SA[it]*dfadua[it][0]+SA[it]*dfadua[it][1]+SB[it]*dfbdua[it][0]+SB[it]*dfbdua[it][1]) for it in range(nTwin)]
2295        dFdtw[iref] = np.sum(TwMask*fas,axis=0)**2+np.sum(TwMask*fbs,axis=0)**2
2296
2297        dFdGf[iref] = [2.*TwMask[it]*(SA[it]*dfadGf[1]+SB[it]*dfbdGf[1]) for it in range(nTwin)]
2298        dFdGx[iref] = [2.*TwMask[it]*(SA[it]*dfadGx[1]+SB[it]*dfbdGx[1]) for it in range(nTwin)]
2299        dFdGz[iref] = [2.*TwMask[it]*(SA[it]*dfadGz[1]+SB[it]*dfbdGz[1]) for it in range(nTwin)]
2300        dFdGu[iref] = [2.*TwMask[it]*(SA[it]*dfadGu[1]+SB[it]*dfbdGu[1]) for it in range(nTwin)]               
2301#            GSASIIpath.IPyBreak()
2302        dFdbab[iref] = 2.*fas[0]*np.array([np.sum(dfadba*dBabdA),np.sum(-dfadba*parmDict[phfx+'BabA']*SQfactor*dBabdA)]).T+ \
2303            2.*fbs[0]*np.array([np.sum(dfbdba*dBabdA),np.sum(-dfbdba*parmDict[phfx+'BabA']*SQfactor*dBabdA)]).T
2304        #loop over atoms - each dict entry is list of derivatives for all the reflections
2305        if not iref%100 :
2306            print ' %d derivative time %.4f\r'%(iref,time.time()-time0),
2307    for i in range(len(Mdata)):     #loop over atoms
2308        dFdvDict[pfx+'Afrac:'+str(i)] = dFdfr.T[i]
2309        dFdvDict[pfx+'dAx:'+str(i)] = dFdx.T[0][i]
2310        dFdvDict[pfx+'dAy:'+str(i)] = dFdx.T[1][i]
2311        dFdvDict[pfx+'dAz:'+str(i)] = dFdx.T[2][i]
2312        dFdvDict[pfx+'AUiso:'+str(i)] = dFdui.T[i]
2313        dFdvDict[pfx+'AU11:'+str(i)] = dFdua.T[0][i]
2314        dFdvDict[pfx+'AU22:'+str(i)] = dFdua.T[1][i]
2315        dFdvDict[pfx+'AU33:'+str(i)] = dFdua.T[2][i]
2316        dFdvDict[pfx+'AU12:'+str(i)] = 2.*dFdua.T[3][i]
2317        dFdvDict[pfx+'AU13:'+str(i)] = 2.*dFdua.T[4][i]
2318        dFdvDict[pfx+'AU23:'+str(i)] = 2.*dFdua.T[5][i]
2319        for j in range(FSSdata.shape[1]):        #loop over waves Fzero & Fwid?
2320            dFdvDict[pfx+'Fsin:'+str(i)+':'+str(j)] = dFdGf.T[0][j][i]
2321            dFdvDict[pfx+'Fcos:'+str(i)+':'+str(j)] = dFdGf.T[1][j][i]
2322        nx = 0
2323        if waveTypes[i] in ['Block','ZigZag']:
2324            nx = 1 
2325            dFdvDict[pfx+'Tmin:'+str(i)+':0'] = dFdGz.T[0][i]   #ZigZag/Block waves (if any)
2326            dFdvDict[pfx+'Tmax:'+str(i)+':0'] = dFdGz.T[1][i]
2327            dFdvDict[pfx+'Xmax:'+str(i)+':0'] = dFdGz.T[2][i]
2328            dFdvDict[pfx+'Ymax:'+str(i)+':0'] = dFdGz.T[3][i]
2329            dFdvDict[pfx+'Zmax:'+str(i)+':0'] = dFdGz.T[4][i]
2330        for j in range(XSSdata.shape[1]-nx):       #loop over waves
2331            dFdvDict[pfx+'Xsin:'+str(i)+':'+str(j+nx)] = dFdGx.T[0][j][i]
2332            dFdvDict[pfx+'Ysin:'+str(i)+':'+str(j+nx)] = dFdGx.T[1][j][i]
2333            dFdvDict[pfx+'Zsin:'+str(i)+':'+str(j+nx)] = dFdGx.T[2][j][i]
2334            dFdvDict[pfx+'Xcos:'+str(i)+':'+str(j+nx)] = dFdGx.T[3][j][i]
2335            dFdvDict[pfx+'Ycos:'+str(i)+':'+str(j+nx)] = dFdGx.T[4][j][i]
2336            dFdvDict[pfx+'Zcos:'+str(i)+':'+str(j+nx)] = dFdGx.T[5][j][i]
2337        for j in range(USSdata.shape[1]):       #loop over waves
2338            dFdvDict[pfx+'U11sin:'+str(i)+':'+str(j)] = dFdGu.T[0][j][i]
2339            dFdvDict[pfx+'U22sin:'+str(i)+':'+str(j)] = dFdGu.T[1][j][i]
2340            dFdvDict[pfx+'U33sin:'+str(i)+':'+str(j)] = dFdGu.T[2][j][i]
2341            dFdvDict[pfx+'U12sin:'+str(i)+':'+str(j)] = 2.*dFdGu.T[3][j][i]
2342            dFdvDict[pfx+'U13sin:'+str(i)+':'+str(j)] = 2.*dFdGu.T[4][j][i]
2343            dFdvDict[pfx+'U23sin:'+str(i)+':'+str(j)] = 2.*dFdGu.T[5][j][i]
2344            dFdvDict[pfx+'U11cos:'+str(i)+':'+str(j)] = dFdGu.T[6][j][i]
2345            dFdvDict[pfx+'U22cos:'+str(i)+':'+str(j)] = dFdGu.T[7][j][i]
2346            dFdvDict[pfx+'U33cos:'+str(i)+':'+str(j)] = dFdGu.T[8][j][i]
2347            dFdvDict[pfx+'U12cos:'+str(i)+':'+str(j)] = 2.*dFdGu.T[9][j][i]
2348            dFdvDict[pfx+'U13cos:'+str(i)+':'+str(j)] = 2.*dFdGu.T[10][j][i]
2349            dFdvDict[pfx+'U23cos:'+str(i)+':'+str(j)] = 2.*dFdGu.T[11][j][i]
2350           
2351#        GSASIIpath.IPyBreak()
2352    dFdvDict[phfx+'BabA'] = dFdbab.T[0]
2353    dFdvDict[phfx+'BabU'] = dFdbab.T[1]
2354    return dFdvDict
2355   
2356def SCExtinction(ref,im,phfx,hfx,pfx,calcControls,parmDict,varyList):
2357    ''' Single crystal extinction function; returns extinction & derivative
2358    '''
2359    extCor = 1.0
2360    dervDict = {}
2361    dervCor = 1.0
2362    if calcControls[phfx+'EType'] != 'None':
2363        SQ = 1/(4.*ref[4+im]**2)
2364        if 'C' in parmDict[hfx+'Type']:           
2365            cos2T = 1.0-2.*SQ*parmDict[hfx+'Lam']**2           #cos(2theta)
2366        else:   #'T'
2367            cos2T = 1.0-2.*SQ*ref[12+im]**2                       #cos(2theta)           
2368        if 'SXC' in parmDict[hfx+'Type']:
2369            AV = 7.9406e5/parmDict[pfx+'Vol']**2
2370            PL = np.sqrt(1.0-cos2T**2)/parmDict[hfx+'Lam']
2371            P12 = (calcControls[phfx+'Cos2TM']+cos2T**4)/(calcControls[phfx+'Cos2TM']+cos2T**2)
2372            PLZ = AV*P12*ref[9+im]*parmDict[hfx+'Lam']**2
2373        elif 'SNT' in parmDict[hfx+'Type']:
2374            AV = 1.e7/parmDict[pfx+'Vol']**2
2375            PL = SQ
2376            PLZ = AV*ref[9+im]*ref[12+im]**2
2377        elif 'SNC' in parmDict[hfx+'Type']:
2378            AV = 1.e7/parmDict[pfx+'Vol']**2
2379            PL = np.sqrt(1.0-cos2T**2)/parmDict[hfx+'Lam']
2380            PLZ = AV*ref[9+im]*parmDict[hfx+'Lam']**2
2381           
2382        if 'Primary' in calcControls[phfx+'EType']:
2383            PLZ *= 1.5
2384        else:
2385            if 'C' in parmDict[hfx+'Type']:
2386                PLZ *= calcControls[phfx+'Tbar']
2387            else: #'T'
2388                PLZ *= ref[13+im]      #t-bar
2389        if 'Primary' in calcControls[phfx+'EType']:
2390            PLZ *= 1.5
2391            PSIG = parmDict[phfx+'Ep']
2392        elif 'I & II' in calcControls[phfx+'EType']:
2393            PSIG = parmDict[phfx+'Eg']/np.sqrt(1.+(parmDict[phfx+'Es']*PL/parmDict[phfx+'Eg'])**2)
2394        elif 'Type II' in calcControls[phfx+'EType']:
2395            PSIG = parmDict[phfx+'Es']
2396        else:       # 'Secondary Type I'
2397            PSIG = parmDict[phfx+'Eg']/PL
2398           
2399        AG = 0.58+0.48*cos2T+0.24*cos2T**2
2400        AL = 0.025+0.285*cos2T
2401        BG = 0.02-0.025*cos2T
2402        BL = 0.15-0.2*(0.75-cos2T)**2
2403        if cos2T < 0.:
2404            BL = -0.45*cos2T
2405        CG = 2.
2406        CL = 2.
2407        PF = PLZ*PSIG
2408       
2409        if 'Gaussian' in calcControls[phfx+'EApprox']:
2410            PF4 = 1.+CG*PF+AG*PF**2/(1.+BG*PF)
2411            extCor = np.sqrt(PF4)
2412            PF3 = 0.5*(CG+2.*AG*PF/(1.+BG*PF)-AG*PF**2*BG/(1.+BG*PF)**2)/(PF4*extCor)
2413        else:
2414            PF4 = 1.+CL*PF+AL*PF**2/(1.+BL*PF)
2415            extCor = np.sqrt(PF4)
2416            PF3 = 0.5*(CL+2.*AL*PF/(1.+BL*PF)-AL*PF**2*BL/(1.+BL*PF)**2)/(PF4*extCor)
2417
2418        dervCor = (1.+PF)*PF3   #extinction corr for other derivatives
2419        if 'Primary' in calcControls[phfx+'EType'] and phfx+'Ep' in varyList:
2420            dervDict[phfx+'Ep'] = -ref[7+im]*PLZ*PF3
2421        if 'II' in calcControls[phfx+'EType'] and phfx+'Es' in varyList:
2422            dervDict[phfx+'Es'] = -ref[7+im]*PLZ*PF3*(PSIG/parmDict[phfx+'Es'])**3
2423        if 'I' in calcControls[phfx+'EType'] and phfx+'Eg' in varyList:
2424            dervDict[phfx+'Eg'] = -ref[7+im]*PLZ*PF3*(PSIG/parmDict[phfx+'Eg'])**3*PL**2
2425               
2426    return 1./extCor,dervDict,dervCor
2427   
2428def Dict2Values(parmdict, varylist):
2429    '''Use before call to leastsq to setup list of values for the parameters
2430    in parmdict, as selected by key in varylist'''
2431    return [parmdict[key] for key in varylist] 
2432   
2433def Values2Dict(parmdict, varylist, values):
2434    ''' Use after call to leastsq to update the parameter dictionary with
2435    values corresponding to keys in varylist'''
2436    parmdict.update(zip(varylist,values))
2437   
2438def GetNewCellParms(parmDict,varyList):
2439    'Needs a doc string'
2440    newCellDict = {}
2441    Anames = ['A'+str(i) for i in range(6)]
2442    Ddict = dict(zip(['D11','D22','D33','D12','D13','D23'],Anames))
2443    for item in varyList:
2444        keys = item.split(':')
2445        if keys[2] in Ddict:
2446            key = keys[0]+'::'+Ddict[keys[2]]       #key is e.g. '0::A0'
2447            parm = keys[0]+'::'+keys[2]             #parm is e.g. '0::D11'
2448            newCellDict[parm] = [key,parmDict[key]+parmDict[item]]
2449    return newCellDict          # is e.g. {'0::D11':A0-D11}
2450   
2451def ApplyXYZshifts(parmDict,varyList):
2452    '''
2453    takes atom x,y,z shift and applies it to corresponding atom x,y,z value
2454   
2455    :param dict parmDict: parameter dictionary
2456    :param list varyList: list of variables (not used!)
2457    :returns: newAtomDict - dictionary of new atomic coordinate names & values; key is parameter shift name
2458
2459    '''
2460    newAtomDict = {}
2461    for item in parmDict:
2462        if 'dA' in item:
2463            parm = ''.join(item.split('d'))
2464            parmDict[parm] += parmDict[item]
2465            newAtomDict[item] = [parm,parmDict[parm]]
2466    return newAtomDict
2467   
2468def SHTXcal(refl,im,g,pfx,hfx,SGData,calcControls,parmDict):
2469    'Spherical harmonics texture'
2470    IFCoup = 'Bragg' in calcControls[hfx+'instType']
2471    if 'T' in calcControls[hfx+'histType']:
2472        tth = parmDict[hfx+'2-theta']
2473    else:
2474        tth = refl[5+im]
2475    odfCor = 1.0
2476    H = refl[:3]
2477    cell = G2lat.Gmat2cell(g)
2478    Sangls = [parmDict[pfx+'SH omega'],parmDict[pfx+'SH chi'],parmDict[pfx+'SH phi']]
2479    Gangls = [parmDict[hfx+'Phi'],parmDict[hfx+'Chi'],parmDict[hfx+'Omega'],parmDict[hfx+'Azimuth']]
2480    phi,beta = G2lat.CrsAng(H,cell,SGData)
2481    psi,gam,x,x = G2lat.SamAng(tth/2.,Gangls,Sangls,IFCoup) #ignore 2 sets of angle derivs.
2482    SHnames = G2lat.GenSHCoeff(SGData['SGLaue'],parmDict[pfx+'SHmodel'],parmDict[pfx+'SHorder'])
2483    for item in SHnames:
2484        L,M,N = eval(item.strip('C'))
2485        Kcl = G2lat.GetKcl(L,N,SGData['SGLaue'],phi,beta)
2486        Ksl,x,x = G2lat.GetKsl(L,M,parmDict[pfx+'SHmodel'],psi,gam)
2487        Lnorm = G2lat.Lnorm(L)
2488        odfCor += parmDict[pfx+item]*Lnorm*Kcl*Ksl
2489    return odfCor
2490   
2491def SHTXcalDerv(refl,im,g,pfx,hfx,SGData,calcControls,parmDict):
2492    'Spherical harmonics texture derivatives'
2493    if 'T' in calcControls[hfx+'histType']:
2494        tth = parmDict[hfx+'2-theta']
2495    else:
2496        tth = refl[5+im]
2497    IFCoup = 'Bragg' in calcControls[hfx+'instType']
2498    odfCor = 1.0
2499    dFdODF = {}
2500    dFdSA = [0,0,0]
2501    H = refl[:3]
2502    cell = G2lat.Gmat2cell(g)
2503    Sangls = [parmDict[pfx+'SH omega'],parmDict[pfx+'SH chi'],parmDict[pfx+'SH phi']]
2504    Gangls = [parmDict[hfx+'Phi'],parmDict[hfx+'Chi'],parmDict[hfx+'Omega'],parmDict[hfx+'Azimuth']]
2505    phi,beta = G2lat.CrsAng(H,cell,SGData)
2506    psi,gam,dPSdA,dGMdA = G2lat.SamAng(tth/2.,Gangls,Sangls,IFCoup)
2507    SHnames = G2lat.GenSHCoeff(SGData['SGLaue'],parmDict[pfx+'SHmodel'],parmDict[pfx+'SHorder'])
2508    for item in SHnames:
2509        L,M,N = eval(item.strip('C'))
2510        Kcl = G2lat.GetKcl(L,N,SGData['SGLaue'],phi,beta)
2511        Ksl,dKsdp,dKsdg = G2lat.GetKsl(L,M,parmDict[pfx+'SHmodel'],psi,gam)
2512        Lnorm = G2lat.Lnorm(L)
2513        odfCor += parmDict[pfx+item]*Lnorm*Kcl*Ksl
2514        dFdODF[pfx+item] = Lnorm*Kcl*Ksl
2515        for i in range(3):
2516            dFdSA[i] += parmDict[pfx+item]*Lnorm*Kcl*(dKsdp*dPSdA[i]+dKsdg*dGMdA[i])
2517    return odfCor,dFdODF,dFdSA
2518   
2519def SHPOcal(refl,im,g,phfx,hfx,SGData,calcControls,parmDict):
2520    'spherical harmonics preferred orientation (cylindrical symmetry only)'
2521    if 'T' in calcControls[hfx+'histType']:
2522        tth = parmDict[hfx+'2-theta']
2523    else:
2524        tth = refl[5+im]
2525    odfCor = 1.0
2526    H = refl[:3]
2527    cell = G2lat.Gmat2cell(g)
2528    Sangls = [0.,0.,0.]
2529    if 'Bragg' in calcControls[hfx+'instType']:
2530        Gangls = [0.,90.,0.,parmDict[hfx+'Azimuth']]
2531        IFCoup = True
2532    else:
2533        Gangls = [parmDict[hfx+'Phi'],parmDict[hfx+'Chi'],parmDict[hfx+'Omega'],parmDict[hfx+'Azimuth']]
2534        IFCoup = False
2535    phi,beta = G2lat.CrsAng(H,cell,SGData)
2536    psi,gam,x,x = G2lat.SamAng(tth/2.,Gangls,Sangls,IFCoup) #ignore 2 sets of angle derivs.
2537    SHnames = calcControls[phfx+'SHnames']
2538    for item in SHnames:
2539        L,N = eval(item.strip('C'))
2540        Kcl = G2lat.GetKcl(L,N,SGData['SGLaue'],phi,beta)
2541        Ksl,x,x = G2lat.GetKsl(L,0,'0',psi,gam)
2542        Lnorm = G2lat.Lnorm(L)
2543        odfCor += parmDict[phfx+item]*Lnorm*Kcl*Ksl
2544    return np.squeeze(odfCor)
2545   
2546def SHPOcalDerv(refl,im,g,phfx,hfx,SGData,calcControls,parmDict):
2547    'spherical harmonics preferred orientation derivatives (cylindrical symmetry only)'
2548    if 'T' in calcControls[hfx+'histType']:
2549        tth = parmDict[hfx+'2-theta']
2550    else:
2551        tth = refl[5+im]
2552    odfCor = 1.0
2553    dFdODF = {}
2554    H = refl[:3]
2555    cell = G2lat.Gmat2cell(g)
2556    Sangls = [0.,0.,0.]
2557    if 'Bragg' in calcControls[hfx+'instType']:
2558        Gangls = [0.,90.,0.,parmDict[hfx+'Azimuth']]
2559        IFCoup = True
2560    else:
2561        Gangls = [parmDict[hfx+'Phi'],parmDict[hfx+'Chi'],parmDict[hfx+'Omega'],parmDict[hfx+'Azimuth']]
2562        IFCoup = False
2563    phi,beta = G2lat.CrsAng(H,cell,SGData)
2564    psi,gam,x,x = G2lat.SamAng(tth/2.,Gangls,Sangls,IFCoup) #ignore 2 sets of angle derivs.
2565    SHnames = calcControls[phfx+'SHnames']
2566    for item in SHnames:
2567        L,N = eval(item.strip('C'))
2568        Kcl = G2lat.GetKcl(L,N,SGData['SGLaue'],phi,beta)
2569        Ksl,x,x = G2lat.GetKsl(L,0,'0',psi,gam)
2570        Lnorm = G2lat.Lnorm(L)
2571        odfCor += parmDict[phfx+item]*Lnorm*Kcl*Ksl
2572        dFdODF[phfx+item] = Kcl*Ksl*Lnorm
2573    return odfCor,dFdODF
2574   
2575def GetPrefOri(uniq,G,g,phfx,hfx,SGData,calcControls,parmDict):
2576    'March-Dollase preferred orientation correction'
2577    POcorr = 1.0
2578    MD = parmDict[phfx+'MD']
2579    if MD != 1.0:
2580        MDAxis = calcControls[phfx+'MDAxis']
2581        sumMD = 0
2582        for H in uniq:           
2583            cosP,sinP = G2lat.CosSinAngle(H,MDAxis,G)
2584            A = 1.0/np.sqrt((MD*cosP)**2+sinP**2/MD)
2585            sumMD += A**3
2586        POcorr = sumMD/len(uniq)
2587    return POcorr
2588   
2589def GetPrefOriDerv(refl,im,uniq,G,g,phfx,hfx,SGData,calcControls,parmDict):
2590    'Needs a doc string'
2591    POcorr = 1.0
2592    POderv = {}
2593    if calcControls[phfx+'poType'] == 'MD':
2594        MD = parmDict[phfx+'MD']
2595        MDAxis = calcControls[phfx+'MDAxis']
2596        sumMD = 0
2597        sumdMD = 0
2598        for H in uniq:           
2599            cosP,sinP = G2lat.CosSinAngle(H,MDAxis,G)
2600            A = 1.0/np.sqrt((MD*cosP)**2+sinP**2/MD)
2601            sumMD += A**3
2602            sumdMD -= (1.5*A**5)*(2.0*MD*cosP**2-(sinP/MD)**2)
2603        POcorr = sumMD/len(uniq)
2604        POderv[phfx+'MD'] = sumdMD/len(uniq)
2605    else:   #spherical harmonics
2606        if calcControls[phfx+'SHord']:
2607            POcorr,POderv = SHPOcalDerv(refl,im,g,phfx,hfx,SGData,calcControls,parmDict)
2608    return POcorr,POderv
2609   
2610def GetAbsorb(refl,im,hfx,calcControls,parmDict):
2611    'Needs a doc string'
2612    if 'Debye' in calcControls[hfx+'instType']:
2613        if 'T' in calcControls[hfx+'histType']:
2614            return G2pwd.Absorb('Cylinder',parmDict[hfx+'Absorption']*refl[14+im],abs(parmDict[hfx+'2-theta']),0,0)
2615        else:
2616            return G2pwd.Absorb('Cylinder',parmDict[hfx+'Absorption'],refl[5+im],0,0)
2617    else:
2618        return G2pwd.SurfaceRough(parmDict[hfx+'SurfRoughA'],parmDict[hfx+'SurfRoughB'],refl[5+im])
2619   
2620def GetAbsorbDerv(refl,im,hfx,calcControls,parmDict):
2621    'Needs a doc string'
2622    if 'Debye' in calcControls[hfx+'instType']:
2623        if 'T' in calcControls[hfx+'histType']:
2624            return G2pwd.AbsorbDerv('Cylinder',parmDict[hfx+'Absorption']*refl[14+im],abs(parmDict[hfx+'2-theta']),0,0)
2625        else:
2626            return G2pwd.AbsorbDerv('Cylinder',parmDict[hfx+'Absorption'],refl[5+im],0,0)
2627    else:
2628        return np.array(G2pwd.SurfaceRoughDerv(parmDict[hfx+'SurfRoughA'],parmDict[hfx+'SurfRoughB'],refl[5+im]))
2629       
2630def GetPwdrExt(refl,im,pfx,phfx,hfx,calcControls,parmDict):
2631    'Needs a doc string'
2632    coef = np.array([-0.5,0.25,-0.10416667,0.036458333,-0.0109375,2.8497409E-3])
2633    pi2 = np.sqrt(2./np.pi)
2634    if 'T' in calcControls[hfx+'histType']:
2635        sth2 = sind(abs(parmDict[hfx+'2-theta'])/2.)**2
2636        wave = refl[14+im]
2637    else:   #'C'W
2638        sth2 = sind(refl[5+im]/2.)**2
2639        wave = parmDict.get(hfx+'Lam',parmDict.get(hfx+'Lam1',1.0))
2640    c2th = 1.-2.0*sth2
2641    flv2 = refl[9+im]*(wave/parmDict[pfx+'Vol'])**2
2642    if 'X' in calcControls[hfx+'histType']:
2643        flv2 *= 0.079411*(1.0+c2th**2)/2.0
2644    xfac = flv2*parmDict[phfx+'Extinction']
2645    exb = 1.0
2646    if xfac > -1.:
2647        exb = 1./np.sqrt(1.+xfac)
2648    exl = 1.0
2649    if 0 < xfac <= 1.:
2650        xn = np.array([xfac**(i+1) for i in range(6)])
2651        exl += np.sum(xn*coef)
2652    elif xfac > 1.:
2653        xfac2 = 1./np.sqrt(xfac)
2654        exl = pi2*(1.-0.125/xfac)*xfac2
2655    return exb*sth2+exl*(1.-sth2)
2656   
2657def GetPwdrExtDerv(refl,im,pfx,phfx,hfx,calcControls,parmDict):
2658    'Needs a doc string'
2659    coef = np.array([-0.5,0.25,-0.10416667,0.036458333,-0.0109375,2.8497409E-3])
2660    pi2 = np.sqrt(2./np.pi)
2661    if 'T' in calcControls[hfx+'histType']:
2662        sth2 = sind(abs(parmDict[hfx+'2-theta'])/2.)**2
2663        wave = refl[14+im]
2664    else:   #'C'W
2665        sth2 = sind(refl[5+im]/2.)**2
2666        wave = parmDict.get(hfx+'Lam',parmDict.get(hfx+'Lam1',1.0))
2667    c2th = 1.-2.0*sth2
2668    flv2 = refl[9+im]*(wave/parmDict[pfx+'Vol'])**2
2669    if 'X' in calcControls[hfx+'histType']:
2670        flv2 *= 0.079411*(1.0+c2th**2)/2.0
2671    xfac = flv2*parmDict[phfx+'Extinction']
2672    dbde = -500.*flv2
2673    if xfac > -1.:
2674        dbde = -0.5*flv2/np.sqrt(1.+xfac)**3
2675    dlde = 0.
2676    if 0 < xfac <= 1.:
2677        xn = np.array([i*flv2*xfac**i for i in [1,2,3,4,5,6]])
2678        dlde = np.sum(xn*coef)
2679    elif xfac > 1.:
2680        xfac2 = 1./np.sqrt(xfac)
2681        dlde = flv2*pi2*xfac2*(-1./xfac+0.375/xfac**2)
2682       
2683    return dbde*sth2+dlde*(1.-sth2)
2684   
2685def GetIntensityCorr(refl,im,uniq,G,g,pfx,phfx,hfx,SGData,calcControls,parmDict):
2686    'Needs a doc string'    #need powder extinction!
2687    Icorr = parmDict[phfx+'Scale']*parmDict[hfx+'Scale']*refl[3+im]               #scale*multiplicity
2688    if 'X' in parmDict[hfx+'Type']:
2689        Icorr *= G2pwd.Polarization(parmDict[hfx+'Polariz.'],refl[5+im],parmDict[hfx+'Azimuth'])[0]
2690    POcorr = 1.0
2691    if pfx+'SHorder' in parmDict:                 #generalized spherical harmonics texture - takes precidence
2692        POcorr = SHTXcal(refl,im,g,pfx,hfx,SGData,calcControls,parmDict)
2693    elif calcControls[phfx+'poType'] == 'MD':         #March-Dollase
2694        POcorr = GetPrefOri(uniq,G,g,phfx,hfx,SGData,calcControls,parmDict)
2695    elif calcControls[phfx+'SHord']:                #cylindrical spherical harmonics
2696        POcorr = SHPOcal(refl,im,g,phfx,hfx,SGData,calcControls,parmDict)
2697    Icorr *= POcorr
2698    AbsCorr = 1.0
2699    AbsCorr = GetAbsorb(refl,im,hfx,calcControls,parmDict)
2700    Icorr *= AbsCorr
2701    ExtCorr = GetPwdrExt(refl,im,pfx,phfx,hfx,calcControls,parmDict)
2702    Icorr *= ExtCorr
2703    return Icorr,POcorr,AbsCorr,ExtCorr
2704   
2705def GetIntensityDerv(refl,im,wave,uniq,G,g,pfx,phfx,hfx,SGData,calcControls,parmDict):
2706    'Needs a doc string'    #need powder extinction derivs!
2707    dIdsh = 1./parmDict[hfx+'Scale']
2708    dIdsp = 1./parmDict[phfx+'Scale']
2709    if 'X' in parmDict[hfx+'Type']:
2710        pola,dIdPola = G2pwd.Polarization(parmDict[hfx+'Polariz.'],refl[5+im],parmDict[hfx+'Azimuth'])
2711        dIdPola /= pola
2712    else:       #'N'
2713        dIdPola = 0.0
2714    dFdODF = {}
2715    dFdSA = [0,0,0]
2716    dIdPO = {}
2717    if pfx+'SHorder' in parmDict:
2718        odfCor,dFdODF,dFdSA = SHTXcalDerv(refl,im,g,pfx,hfx,SGData,calcControls,parmDict)
2719        for iSH in dFdODF:
2720            dFdODF[iSH] /= odfCor
2721        for i in range(3):
2722            dFdSA[i] /= odfCor
2723    elif calcControls[phfx+'poType'] == 'MD' or calcControls[phfx+'SHord']:
2724        POcorr,dIdPO = GetPrefOriDerv(refl,im,uniq,G,g,phfx,hfx,SGData,calcControls,parmDict)       
2725        for iPO in dIdPO:
2726            dIdPO[iPO] /= POcorr
2727    if 'T' in parmDict[hfx+'Type']:
2728        dFdAb = GetAbsorbDerv(refl,im,hfx,calcControls,parmDict)*wave/refl[16+im] #wave/abs corr
2729        dFdEx = GetPwdrExtDerv(refl,im,pfx,phfx,hfx,calcControls,parmDict)/refl[17+im]    #/ext corr
2730    else:
2731        dFdAb = GetAbsorbDerv(refl,im,hfx,calcControls,parmDict)*wave/refl[13+im] #wave/abs corr
2732        dFdEx = GetPwdrExtDerv(refl,im,pfx,phfx,hfx,calcControls,parmDict)/refl[14+im]    #/ext corr       
2733    return dIdsh,dIdsp,dIdPola,dIdPO,dFdODF,dFdSA,dFdAb,dFdEx
2734       
2735def GetSampleSigGam(refl,im,wave,G,GB,SGData,hfx,phfx,calcControls,parmDict):
2736    'Needs a doc string'
2737    if 'C' in calcControls[hfx+'histType']:     #All checked & OK
2738        costh = cosd(refl[5+im]/2.)
2739        #crystallite size
2740        if calcControls[phfx+'SizeType'] == 'isotropic':
2741            Sgam = 1.8*wave/(np.pi*parmDict[phfx+'Size;i']*costh)
2742        elif calcControls[phfx+'SizeType'] == 'uniaxial':
2743            H = np.array(refl[:3])
2744            P = np.array(calcControls[phfx+'SizeAxis'])
2745            cosP,sinP = G2lat.CosSinAngle(H,P,G)
2746            Sgam = (1.8*wave/np.pi)/(parmDict[phfx+'Size;i']*parmDict[phfx+'Size;a']*costh)
2747            Sgam *= np.sqrt((sinP*parmDict[phfx+'Size;a'])**2+(cosP*parmDict[phfx+'Size;i'])**2)
2748        else:           #ellipsoidal crystallites
2749            Sij =[parmDict[phfx+'Size:%d'%(i)] for i in range(6)]
2750            H = np.array(refl[:3])
2751            lenR = G2pwd.ellipseSize(H,Sij,GB)
2752            Sgam = 1.8*wave/(np.pi*costh*lenR)
2753        #microstrain               
2754        if calcControls[phfx+'MustrainType'] == 'isotropic':
2755            Mgam = 0.018*parmDict[phfx+'Mustrain;i']*tand(refl[5+im]/2.)/np.pi
2756        elif calcControls[phfx+'MustrainType'] == 'uniaxial':
2757            H = np.array(refl[:3])
2758            P = np.array(calcControls[phfx+'MustrainAxis'])
2759            cosP,sinP = G2lat.CosSinAngle(H,P,G)
2760            Si = parmDict[phfx+'Mustrain;i']
2761            Sa = parmDict[phfx+'Mustrain;a']
2762            Mgam = 0.018*Si*Sa*tand(refl[5+im]/2.)/(np.pi*np.sqrt((Si*cosP)**2+(Sa*sinP)**2))
2763        else:       #generalized - P.W. Stephens model
2764            Strms = G2spc.MustrainCoeff(refl[:3],SGData)
2765            Sum = 0
2766            for i,strm in enumerate(Strms):
2767                Sum += parmDict[phfx+'Mustrain;'+str(i)]*strm
2768            Mgam = 0.018*refl[4+im]**2*tand(refl[5+im]/2.)*np.sqrt(Sum)/np.pi
2769    elif 'T' in calcControls[hfx+'histType']:       #All checked & OK
2770        #crystallite size
2771        if calcControls[phfx+'SizeType'] == 'isotropic':    #OK
2772            Sgam = 1.e-4*parmDict[hfx+'difC']*refl[4+im]**2/parmDict[phfx+'Size;i']
2773        elif calcControls[phfx+'SizeType'] == 'uniaxial':   #OK
2774            H = np.array(refl[:3])
2775            P = np.array(calcControls[phfx+'SizeAxis'])
2776            cosP,sinP = G2lat.CosSinAngle(H,P,G)
2777            Sgam = 1.e-4*parmDict[hfx+'difC']*refl[4+im]**2/(parmDict[phfx+'Size;i']*parmDict[phfx+'Size;a'])
2778            Sgam *= np.sqrt((sinP*parmDict[phfx+'Size;a'])**2+(cosP*parmDict[phfx+'Size;i'])**2)
2779        else:           #ellipsoidal crystallites   #OK
2780            Sij =[parmDict[phfx+'Size:%d'%(i)] for i in range(6)]
2781            H = np.array(refl[:3])
2782            lenR = G2pwd.ellipseSize(H,Sij,GB)
2783            Sgam = 1.e-4*parmDict[hfx+'difC']*refl[4+im]**2/lenR
2784        #microstrain               
2785        if calcControls[phfx+'MustrainType'] == 'isotropic':    #OK
2786            Mgam = 1.e-6*parmDict[hfx+'difC']*refl[4+im]*parmDict[phfx+'Mustrain;i']
2787        elif calcControls[phfx+'MustrainType'] == 'uniaxial':   #OK
2788            H = np.array(refl[:3])
2789            P = np.array(calcControls[phfx+'MustrainAxis'])
2790            cosP,sinP = G2lat.CosSinAngle(H,P,G)
2791            Si = parmDict[phfx+'Mustrain;i']
2792            Sa = parmDict[phfx+'Mustrain;a']
2793            Mgam = 1.e-6*parmDict[hfx+'difC']*refl[4+im]*Si*Sa/np.sqrt((Si*cosP)**2+(Sa*sinP)**2)
2794        else:       #generalized - P.W. Stephens model  OK
2795            Strms = G2spc.MustrainCoeff(refl[:3],SGData)
2796            Sum = 0
2797            for i,strm in enumerate(Strms):
2798                Sum += parmDict[phfx+'Mustrain;'+str(i)]*strm
2799            Mgam = 1.e-6*parmDict[hfx+'difC']*np.sqrt(Sum)*refl[4+im]**3
2800           
2801    gam = Sgam*parmDict[phfx+'Size;mx']+Mgam*parmDict[phfx+'Mustrain;mx']
2802    sig = (Sgam*(1.-parmDict[phfx+'Size;mx']))**2+(Mgam*(1.-parmDict[phfx+'Mustrain;mx']))**2
2803    sig /= ateln2
2804    return sig,gam
2805       
2806def GetSampleSigGamDerv(refl,im,wave,G,GB,SGData,hfx,phfx,calcControls,parmDict):
2807    'Needs a doc string'
2808    gamDict = {}
2809    sigDict = {}
2810    if 'C' in calcControls[hfx+'histType']:         #All checked & OK
2811        costh = cosd(refl[5+im]/2.)
2812        tanth = tand(refl[5+im]/2.)
2813        #crystallite size derivatives
2814        if calcControls[phfx+'SizeType'] == 'isotropic':
2815            Sgam = 1.8*wave/(np.pi*parmDict[phfx+'Size;i']*costh)
2816            gamDict[phfx+'Size;i'] = -1.8*wave*parmDict[phfx+'Size;mx']/(np.pi*costh)
2817            sigDict[phfx+'Size;i'] = -3.6*Sgam*wave*(1.-parmDict[phfx+'Size;mx'])**2/(np.pi*costh*ateln2)
2818        elif calcControls[phfx+'SizeType'] == 'uniaxial':
2819            H = np.array(refl[:3])
2820            P = np.array(calcControls[phfx+'SizeAxis'])
2821            cosP,sinP = G2lat.CosSinAngle(H,P,G)
2822            Si = parmDict[phfx+'Size;i']
2823            Sa = parmDict[phfx+'Size;a']
2824            gami = 1.8*wave/(costh*np.pi*Si*Sa)
2825            sqtrm = np.sqrt((sinP*Sa)**2+(cosP*Si)**2)
2826            Sgam = gami*sqtrm
2827            dsi = gami*Si*cosP**2/sqtrm-Sgam/Si
2828            dsa = gami*Sa*sinP**2/sqtrm-Sgam/Sa
2829            gamDict[phfx+'Size;i'] = dsi*parmDict[phfx+'Size;mx']
2830            gamDict[phfx+'Size;a'] = dsa*parmDict[phfx+'Size;mx']
2831            sigDict[phfx+'Size;i'] = 2.*dsi*Sgam*(1.-parmDict[phfx+'Size;mx'])**2/ateln2
2832            sigDict[phfx+'Size;a'] = 2.*dsa*Sgam*(1.-parmDict[phfx+'Size;mx'])**2/ateln2
2833        else:           #ellipsoidal crystallites
2834            const = 1.8*wave/(np.pi*costh)
2835            Sij =[parmDict[phfx+'Size:%d'%(i)] for i in range(6)]
2836            H = np.array(refl[:3])
2837            lenR,dRdS = G2pwd.ellipseSizeDerv(H,Sij,GB)
2838            Sgam = const/lenR
2839            for i,item in enumerate([phfx+'Size:%d'%(j) for j in range(6)]):
2840                gamDict[item] = -(const/lenR**2)*dRdS[i]*parmDict[phfx+'Size;mx']
2841                sigDict[item] = -2.*Sgam*(const/lenR**2)*dRdS[i]*(1.-parmDict[phfx+'Size;mx'])**2/ateln2
2842        gamDict[phfx+'Size;mx'] = Sgam
2843        sigDict[phfx+'Size;mx'] = -2.*Sgam**2*(1.-parmDict[phfx+'Size;mx'])/ateln2
2844               
2845        #microstrain derivatives               
2846        if calcControls[phfx+'MustrainType'] == 'isotropic':
2847            Mgam = 0.018*parmDict[phfx+'Mustrain;i']*tand(refl[5+im]/2.)/np.pi
2848            gamDict[phfx+'Mustrain;i'] =  0.018*tanth*parmDict[phfx+'Mustrain;mx']/np.pi
2849            sigDict[phfx+'Mustrain;i'] =  0.036*Mgam*tanth*(1.-parmDict[phfx+'Mustrain;mx'])**2/(np.pi*ateln2)       
2850        elif calcControls[phfx+'MustrainType'] == 'uniaxial':
2851            H = np.array(refl[:3])
2852            P = np.array(calcControls[phfx+'MustrainAxis'])
2853            cosP,sinP = G2lat.CosSinAngle(H,P,G)
2854            Si = parmDict[phfx+'Mustrain;i']
2855            Sa = parmDict[phfx+'Mustrain;a']
2856            gami = 0.018*Si*Sa*tanth/np.pi
2857            sqtrm = np.sqrt((Si*cosP)**2+(Sa*sinP)**2)
2858            Mgam = gami/sqtrm
2859            dsi = -gami*Si*cosP**2/sqtrm**3
2860            dsa = -gami*Sa*sinP**2/sqtrm**3
2861            gamDict[phfx+'Mustrain;i'] = (Mgam/Si+dsi)*parmDict[phfx+'Mustrain;mx']
2862            gamDict[phfx+'Mustrain;a'] = (Mgam/Sa+dsa)*parmDict[phfx+'Mustrain;mx']
2863            sigDict[phfx+'Mustrain;i'] = 2*(Mgam/Si+dsi)*Mgam*(1.-parmDict[phfx+'Mustrain;mx'])**2/ateln2
2864            sigDict[phfx+'Mustrain;a'] = 2*(Mgam/Sa+dsa)*Mgam*(1.-parmDict[phfx+'Mustrain;mx'])**2/ateln2       
2865        else:       #generalized - P.W. Stephens model
2866            const = 0.018*refl[4+im]**2*tanth/np.pi
2867            Strms = G2spc.MustrainCoeff(refl[:3],SGData)
2868            Sum = 0
2869            for i,strm in enumerate(Strms):
2870                Sum += parmDict[phfx+'Mustrain;'+str(i)]*strm
2871                gamDict[phfx+'Mustrain;'+str(i)] = strm*parmDict[phfx+'Mustrain;mx']/2.
2872                sigDict[phfx+'Mustrain;'+str(i)] = strm*(1.-parmDict[phfx+'Mustrain;mx'])**2
2873            Mgam = const*np.sqrt(Sum)
2874            for i in range(len(Strms)):
2875                gamDict[phfx+'Mustrain;'+str(i)] *= Mgam/Sum
2876                sigDict[phfx+'Mustrain;'+str(i)] *= const**2/ateln2
2877        gamDict[phfx+'Mustrain;mx'] = Mgam
2878        sigDict[phfx+'Mustrain;mx'] = -2.*Mgam**2*(1.-parmDict[phfx+'Mustrain;mx'])/ateln2
2879    else:   #'T'OF - All checked & OK
2880        if calcControls[phfx+'SizeType'] == 'isotropic':    #OK
2881            Sgam = 1.e-4*parmDict[hfx+'difC']*refl[4+im]**2/parmDict[phfx+'Size;i']
2882            gamDict[phfx+'Size;i'] = -Sgam*parmDict[phfx+'Size;mx']/parmDict[phfx+'Size;i']
2883            sigDict[phfx+'Size;i'] = -2.*Sgam**2*(1.-parmDict[phfx+'Size;mx'])**2/(ateln2*parmDict[phfx+'Size;i'])
2884        elif calcControls[phfx+'SizeType'] == 'uniaxial':   #OK
2885            const = 1.e-4*parmDict[hfx+'difC']*refl[4+im]**2
2886            H = np.array(refl[:3])
2887            P = np.array(calcControls[phfx+'SizeAxis'])
2888            cosP,sinP = G2lat.CosSinAngle(H,P,G)
2889            Si = parmDict[phfx+'Size;i']
2890            Sa = parmDict[phfx+'Size;a']
2891            gami = const/(Si*Sa)
2892            sqtrm = np.sqrt((sinP*Sa)**2+(cosP*Si)**2)
2893            Sgam = gami*sqtrm
2894            dsi = gami*Si*cosP**2/sqtrm-Sgam/Si
2895            dsa = gami*Sa*sinP**2/sqtrm-Sgam/Sa
2896            gamDict[phfx+'Size;i'] = dsi*parmDict[phfx+'Size;mx']
2897            gamDict[phfx+'Size;a'] = dsa*parmDict[phfx+'Size;mx']
2898            sigDict[phfx+'Size;i'] = 2.*dsi*Sgam*(1.-parmDict[phfx+'Size;mx'])**2/ateln2
2899            sigDict[phfx+'Size;a'] = 2.*dsa*Sgam*(1.-parmDict[phfx+'Size;mx'])**2/ateln2
2900        else:           #OK  ellipsoidal crystallites
2901            const = 1.e-4*parmDict[hfx+'difC']*refl[4+im]**2
2902            Sij =[parmDict[phfx+'Size:%d'%(i)] for i in range(6)]
2903            H = np.array(refl[:3])
2904            lenR,dRdS = G2pwd.ellipseSizeDerv(H,Sij,GB)
2905            Sgam = const/lenR
2906            for i,item in enumerate([phfx+'Size:%d'%(j) for j in range(6)]):
2907                gamDict[item] = -(const/lenR**2)*dRdS[i]*parmDict[phfx+'Size;mx']
2908                sigDict[item] = -2.*Sgam*(const/lenR**2)*dRdS[i]*(1.-parmDict[phfx+'Size;mx'])**2/ateln2
2909        gamDict[phfx+'Size;mx'] = Sgam  #OK
2910        sigDict[phfx+'Size;mx'] = -2.*Sgam**2*(1.-parmDict[phfx+'Size;mx'])/ateln2  #OK
2911               
2912        #microstrain derivatives               
2913        if calcControls[phfx+'MustrainType'] == 'isotropic':
2914            Mgam = 1.e-6*parmDict[hfx+'difC']*refl[4+im]*parmDict[phfx+'Mustrain;i']
2915            gamDict[phfx+'Mustrain;i'] =  1.e-6*refl[4+im]*parmDict[hfx+'difC']*parmDict[phfx+'Mustrain;mx']   #OK
2916            sigDict[phfx+'Mustrain;i'] =  2.*Mgam**2*(1.-parmDict[phfx+'Mustrain;mx'])**2/(ateln2*parmDict[phfx+'Mustrain;i'])       
2917        elif calcControls[phfx+'MustrainType'] == 'uniaxial':
2918            H = np.array(refl[:3])
2919            P = np.array(calcControls[phfx+'MustrainAxis'])
2920            cosP,sinP = G2lat.CosSinAngle(H,P,G)
2921            Si = parmDict[phfx+'Mustrain;i']
2922            Sa = parmDict[phfx+'Mustrain;a']
2923            gami = 1.e-6*parmDict[hfx+'difC']*refl[4+im]*Si*Sa
2924            sqtrm = np.sqrt((Si*cosP)**2+(Sa*sinP)**2)
2925            Mgam = gami/sqtrm
2926            dsi = -gami*Si*cosP**2/sqtrm**3
2927            dsa = -gami*Sa*sinP**2/sqtrm**3
2928            gamDict[phfx+'Mustrain;i'] = (Mgam/Si+dsi)*parmDict[phfx+'Mustrain;mx']
2929            gamDict[phfx+'Mustrain;a'] = (Mgam/Sa+dsa)*parmDict[phfx+'Mustrain;mx']
2930            sigDict[phfx+'Mustrain;i'] = 2*(Mgam/Si+dsi)*Mgam*(1.-parmDict[phfx+'Mustrain;mx'])**2/ateln2
2931            sigDict[phfx+'Mustrain;a'] = 2*(Mgam/Sa+dsa)*Mgam*(1.-parmDict[phfx+'Mustrain;mx'])**2/ateln2       
2932        else:       #generalized - P.W. Stephens model OK
2933            pwrs = calcControls[phfx+'MuPwrs']
2934            Strms = G2spc.MustrainCoeff(refl[:3],SGData)
2935            const = 1.e-6*parmDict[hfx+'difC']*refl[4+im]**3
2936            Sum = 0
2937            for i,strm in enumerate(Strms):
2938                Sum += parmDict[phfx+'Mustrain;'+str(i)]*strm
2939                gamDict[phfx+'Mustrain;'+str(i)] = strm*parmDict[phfx+'Mustrain;mx']/2.
2940                sigDict[phfx+'Mustrain;'+str(i)] = strm*(1.-parmDict[phfx+'Mustrain;mx'])**2
2941            Mgam = const*np.sqrt(Sum)
2942            for i in range(len(Strms)):
2943                gamDict[phfx+'Mustrain;'+str(i)] *= Mgam/Sum
2944                sigDict[phfx+'Mustrain;'+str(i)] *= const**2/ateln2       
2945        gamDict[phfx+'Mustrain;mx'] = Mgam
2946        sigDict[phfx+'Mustrain;mx'] = -2.*Mgam**2*(1.-parmDict[phfx+'Mustrain;mx'])/ateln2
2947       
2948    return sigDict,gamDict
2949       
2950def GetReflPos(refl,im,wave,A,pfx,hfx,calcControls,parmDict):
2951    'Needs a doc string'
2952    if im:
2953        h,k,l,m = refl[:4]
2954        vec = np.array([parmDict[pfx+'mV0'],parmDict[pfx+'mV1'],parmDict[pfx+'mV2']])
2955        d = 1./np.sqrt(G2lat.calc_rDsqSS(np.array([h,k,l,m]),A,vec))
2956    else:
2957        h,k,l = refl[:3]
2958        d = 1./np.sqrt(G2lat.calc_rDsq(np.array([h,k,l]),A))
2959    refl[4+im] = d
2960    if 'C' in calcControls[hfx+'histType']:
2961        pos = 2.0*asind(wave/(2.0*d))+parmDict[hfx+'Zero']
2962        const = 9.e-2/(np.pi*parmDict[hfx+'Gonio. radius'])                  #shifts in microns
2963        if 'Bragg' in calcControls[hfx+'instType']:
2964            pos -= const*(4.*parmDict[hfx+'Shift']*cosd(pos/2.0)+ \
2965                parmDict[hfx+'Transparency']*sind(pos)*100.0)            #trans(=1/mueff) in cm
2966        else:               #Debye-Scherrer - simple but maybe not right
2967            pos -= const*(parmDict[hfx+'DisplaceX']*cosd(pos)+parmDict[hfx+'DisplaceY']*sind(pos))
2968    elif 'T' in calcControls[hfx+'histType']:
2969        pos = parmDict[hfx+'difC']*d+parmDict[hfx+'difA']*d**2+parmDict[hfx+'difB']/d+parmDict[hfx+'Zero']
2970        #do I need sample position effects - maybe?
2971    return pos
2972
2973def GetReflPosDerv(refl,im,wave,A,pfx,hfx,calcControls,parmDict):
2974    'Needs a doc string'
2975    dpr = 180./np.pi
2976    if im:
2977        h,k,l,m = refl[:4]
2978        vec = np.array([parmDict[pfx+'mV0'],parmDict[pfx+'mV1'],parmDict[pfx+'mV2']])
2979        dstsq = G2lat.calc_rDsqSS(np.array([h,k,l,m]),A,vec)
2980        h,k,l = [h+m*vec[0],k+m*vec[1],l+m*vec[2]]          #do proj of hklm to hkl so dPdA & dPdV come out right
2981    else:
2982        m = 0
2983        h,k,l = refl[:3]       
2984        dstsq = G2lat.calc_rDsq(np.array([h,k,l]),A)
2985    dst = np.sqrt(dstsq)
2986    dsp = 1./dst
2987    if 'C' in calcControls[hfx+'histType']:
2988        pos = refl[5+im]-parmDict[hfx+'Zero']
2989        const = dpr/np.sqrt(1.0-wave**2*dstsq/4.0)
2990        dpdw = const*dst
2991        dpdA = np.array([h**2,k**2,l**2,h*k,h*l,k*l])*const*wave/(2.0*dst)
2992        dpdZ = 1.0
2993        dpdV = np.array([2.*h*A[0]+k*A[3]+l*A[4],2*k*A[1]+h*A[3]+l*A[5],
2994            2*l*A[2]+h*A[4]+k*A[5]])*m*const*wave/(2.0*dst)
2995        shft = 9.e-2/(np.pi*parmDict[hfx+'Gonio. radius'])                  #shifts in microns
2996        if 'Bragg' in calcControls[hfx+'instType']:
2997            dpdSh = -4.*shft*cosd(pos/2.0)
2998            dpdTr = -shft*sind(pos)*100.0
2999            return dpdA,dpdw,dpdZ,dpdSh,dpdTr,0.,0.,dpdV
3000        else:               #Debye-Scherrer - simple but maybe not right
3001            dpdXd = -shft*cosd(pos)
3002            dpdYd = -shft*sind(pos)
3003            return dpdA,dpdw,dpdZ,0.,0.,dpdXd,dpdYd,dpdV
3004    elif 'T' in calcControls[hfx+'histType']:
3005        dpdA = -np.array([h**2,k**2,l**2,h*k,h*l,k*l])*parmDict[hfx+'difC']*dsp**3/2.
3006        dpdZ = 1.0
3007        dpdDC = dsp
3008        dpdDA = dsp**2
3009        dpdDB = 1./dsp
3010        dpdV = np.array([2.*h*A[0]+k*A[3]+l*A[4],2*k*A[1]+h*A[3]+l*A[5],
3011            2*l*A[2]+h*A[4]+k*A[5]])*m*parmDict[hfx+'difC']*dsp**3/2.
3012        return dpdA,dpdZ,dpdDC,dpdDA,dpdDB,dpdV
3013           
3014def GetHStrainShift(refl,im,SGData,phfx,hfx,calcControls,parmDict):
3015    'Needs a doc string'
3016    laue = SGData['SGLaue']
3017    uniq = SGData['SGUniq']
3018    h,k,l = refl[:3]
3019    if laue in ['m3','m3m']:
3020        Dij = parmDict[phfx+'D11']*(h**2+k**2+l**2)+ \
3021            refl[4+im]**2*parmDict[phfx+'eA']*((h*k)**2+(h*l)**2+(k*l)**2)/(h**2+k**2+l**2)**2
3022    elif laue in ['6/m','6/mmm','3m1','31m','3']:
3023        Dij = parmDict[phfx+'D11']*(h**2+k**2+h*k)+parmDict[phfx+'D33']*l**2
3024    elif laue in ['3R','3mR']:
3025        Dij = parmDict[phfx+'D11']*(h**2+k**2+l**2)+parmDict[phfx+'D12']*(h*k+h*l+k*l)
3026    elif laue in ['4/m','4/mmm']:
3027        Dij = parmDict[phfx+'D11']*(h**2+k**2)+parmDict[phfx+'D33']*l**2
3028    elif laue in ['mmm']:
3029        Dij = parmDict[phfx+'D11']*h**2+parmDict[phfx+'D22']*k**2+parmDict[phfx+'D33']*l**2
3030    elif laue in ['2/m']:
3031        Dij = parmDict[phfx+'D11']*h**2+parmDict[phfx+'D22']*k**2+parmDict[phfx+'D33']*l**2
3032        if uniq == 'a':
3033            Dij += parmDict[phfx+'D23']*k*l
3034        elif uniq == 'b':
3035            Dij += parmDict[phfx+'D13']*h*l
3036        elif uniq == 'c':
3037            Dij += parmDict[phfx+'D12']*h*k
3038    else:
3039        Dij = parmDict[phfx+'D11']*h**2+parmDict[phfx+'D22']*k**2+parmDict[phfx+'D33']*l**2+ \
3040            parmDict[phfx+'D12']*h*k+parmDict[phfx+'D13']*h*l+parmDict[phfx+'D23']*k*l
3041    if 'C' in calcControls[hfx+'histType']:
3042        return -180.*Dij*refl[4+im]**2*tand(refl[5+im]/2.0)/np.pi
3043    else:
3044        return -Dij*parmDict[hfx+'difC']*refl[4+im]**2/2.
3045           
3046def GetHStrainShiftDerv(refl,im,SGData,phfx,hfx,calcControls,parmDict):
3047    'Needs a doc string'
3048    laue = SGData['SGLaue']
3049    uniq = SGData['SGUniq']
3050    h,k,l = refl[:3]
3051    if laue in ['m3','m3m']:
3052        dDijDict = {phfx+'D11':h**2+k**2+l**2,
3053            phfx+'eA':refl[4+im]**2*((h*k)**2+(h*l)**2+(k*l)**2)/(h**2+k**2+l**2)**2}
3054    elif laue in ['6/m','6/mmm','3m1','31m','3']:
3055        dDijDict = {phfx+'D11':h**2+k**2+h*k,phfx+'D33':l**2}
3056    elif laue in ['3R','3mR']:
3057        dDijDict = {phfx+'D11':h**2+k**2+l**2,phfx+'D12':h*k+h*l+k*l}
3058    elif laue in ['4/m','4/mmm']:
3059        dDijDict = {phfx+'D11':h**2+k**2,phfx+'D33':l**2}
3060    elif laue in ['mmm']:
3061        dDijDict = {phfx+'D11':h**2,phfx+'D22':k**2,phfx+'D33':l**2}
3062    elif laue in ['2/m']:
3063        dDijDict = {phfx+'D11':h**2,phfx+'D22':k**2,phfx+'D33':l**2}
3064        if uniq == 'a':
3065            dDijDict[phfx+'D23'] = k*l
3066        elif uniq == 'b':
3067            dDijDict[phfx+'D13'] = h*l
3068        elif uniq == 'c':
3069            dDijDict[phfx+'D12'] = h*k
3070    else:
3071        dDijDict = {phfx+'D11':h**2,phfx+'D22':k**2,phfx+'D33':l**2,
3072            phfx+'D12':h*k,phfx+'D13':h*l,phfx+'D23':k*l}
3073    if 'C' in calcControls[hfx+'histType']:
3074        for item in dDijDict:
3075            dDijDict[item] *= 180.0*refl[4+im]**2*tand(refl[5+im]/2.0)/np.pi
3076    else:
3077        for item in dDijDict:
3078            dDijDict[item] *= -parmDict[hfx+'difC']*refl[4+im]**3/2.
3079    return dDijDict
3080   
3081def GetDij(phfx,SGData,parmDict):
3082    HSvals = [parmDict[phfx+name] for name in G2spc.HStrainNames(SGData)]
3083    return G2spc.HStrainVals(HSvals,SGData)
3084               
3085def GetFobsSq(Histograms,Phases,parmDict,calcControls):
3086    'Needs a doc string'
3087    histoList = Histograms.keys()
3088    histoList.sort()
3089    for histogram in histoList:
3090        if 'PWDR' in histogram[:4]:
3091            Histogram = Histograms[histogram]
3092            hId = Histogram['hId']
3093            hfx = ':%d:'%(hId)
3094            Limits = calcControls[hfx+'Limits']
3095            if 'C' in calcControls[hfx+'histType']:
3096                shl = max(parmDict[hfx+'SH/L'],0.0005)
3097                Ka2 = False
3098                kRatio = 0.0
3099                if hfx+'Lam1' in parmDict.keys():
3100                    Ka2 = True
3101                    lamRatio = 360*(parmDict[hfx+'Lam2']-parmDict[hfx+'Lam1'])/(np.pi*parmDict[hfx+'Lam1'])
3102                    kRatio = parmDict[hfx+'I(L2)/I(L1)']
3103            x,y,w,yc,yb,yd = Histogram['Data']
3104            xMask = ma.getmaskarray(x)
3105            xB = np.searchsorted(x,Limits[0])
3106            xF = np.searchsorted(x,Limits[1])
3107            ymb = np.array(y-yb)
3108            ymb = np.where(ymb,ymb,1.0)
3109            ycmb = np.array(yc-yb)
3110            ratio = 1./np.where(ycmb,ycmb/ymb,1.e10)         
3111            refLists = Histogram['Reflection Lists']
3112            for phase in refLists:
3113                if phase not in Phases:     #skips deleted or renamed phases silently!
3114                    continue
3115                Phase = Phases[phase]
3116                im = 0
3117                if Phase['General']['Type'] in ['modulated','magnetic']:
3118                    im = 1
3119                pId = Phase['pId']
3120                phfx = '%d:%d:'%(pId,hId)
3121                refDict = refLists[phase]
3122                sumFo = 0.0
3123                sumdF = 0.0
3124                sumFosq = 0.0
3125                sumdFsq = 0.0
3126                sumInt = 0.0
3127                nExcl = 0
3128                for refl in refDict['RefList']:
3129                    if 'C' in calcControls[hfx+'histType']:
3130                        yp = np.zeros_like(yb)
3131                        Wd,fmin,fmax = G2pwd.getWidthsCW(refl[5+im],refl[6+im],refl[7+im],shl)
3132                        iBeg = max(xB,np.searchsorted(x,refl[5+im]-fmin))
3133                        iFin = max(xB,min(np.searchsorted(x,refl[5+im]+fmax),xF))
3134                        iFin2 = iFin
3135                        if not iBeg+iFin:       #peak below low limit - skip peak
3136                            continue
3137                        if ma.all(xMask[iBeg:iFin]):    #peak entirely masked - skip peak
3138                            refl[3+im] *= -1
3139                            nExcl += 1
3140                            continue
3141                        elif not iBeg-iFin:     #peak above high limit - done
3142                            break
3143                        elif iBeg < iFin:
3144                            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
3145                            sumInt += refl[11+im]*refl[9+im]
3146                            if Ka2:
3147                                pos2 = refl[5+im]+lamRatio*tand(refl[5+im]/2.0)       # + 360/pi * Dlam/lam * tan(th)
3148                                Wd,fmin,fmax = G2pwd.getWidthsCW(pos2,refl[6+im],refl[7+im],shl)
3149                                iBeg2 = max(xB,np.searchsorted(x,pos2-fmin))
3150                                iFin2 = min(np.searchsorted(x,pos2+fmax),xF)
3151                                if iFin2 > iBeg2: 
3152                                    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
3153                                    sumInt += refl[11+im]*refl[9+im]*kRatio
3154                            refl[8+im] = np.sum(np.where(ratio[iBeg:iFin2]>0.,yp[iBeg:iFin2]*ratio[iBeg:iFin2]/(refl[11+im]*(1.+kRatio)),0.0))
3155                               
3156                    elif 'T' in calcControls[hfx+'histType']:
3157                        yp = np.zeros_like(yb)
3158                        Wd,fmin,fmax = G2pwd.getWidthsTOF(refl[5+im],refl[12+im],refl[13+im],refl[6+im],refl[7+im])
3159                        iBeg = max(xB,np.searchsorted(x,refl[5+im]-fmin))
3160                        iFin = max(xB,min(np.searchsorted(x,refl[5+im]+fmax),xF))
3161                        if not iBeg+iFin:       #peak below low limit - skip peak
3162                            continue
3163                        if ma.all(xMask[iBeg:iFin]):    #peak entirely masked - skip peak
3164                            refl[3+im] *= -1
3165                            nExcl += 1
3166                            continue
3167                        elif not iBeg-iFin:     #peak above high limit - done
3168                            break
3169                        if iBeg < iFin:
3170                            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
3171                            refl[8+im] = np.sum(np.where(ratio[iBeg:iFin]>0.,yp[iBeg:iFin]*ratio[iBeg:iFin]/refl[11+im],0.0))
3172                            sumInt += refl[11+im]*refl[9+im]
3173                    Fo = np.sqrt(np.abs(refl[8+im]))
3174                    Fc = np.sqrt(np.abs(refl[9]+im))
3175                    sumFo += Fo
3176                    sumFosq += refl[8+im]**2
3177                    sumdF += np.abs(Fo-Fc)
3178                    sumdFsq += (refl[8+im]-refl[9+im])**2
3179                if sumFo:
3180                    Histogram['Residuals'][phfx+'Rf'] = min(100.,(sumdF/sumFo)*100.)
3181                    Histogram['Residuals'][phfx+'Rf^2'] = min(100.,np.sqrt(sumdFsq/sumFosq)*100.)
3182                else:
3183                    Histogram['Residuals'][phfx+'Rf'] = 100.
3184                    Histogram['Residuals'][phfx+'Rf^2'] = 100.
3185                Histogram['Residuals'][phfx+'sumInt'] = sumInt
3186                Histogram['Residuals'][phfx+'Nref'] = len(refDict['RefList'])-nExcl
3187                Histogram['Residuals']['hId'] = hId
3188        elif 'HKLF' in histogram[:4]:
3189            Histogram = Histograms[histogram]
3190            Histogram['Residuals']['hId'] = Histograms[histogram]['hId']
3191               
3192def getPowderProfile(parmDict,x,varylist,Histogram,Phases,calcControls,pawleyLookup):
3193    'Needs a doc string'
3194   
3195    def GetReflSigGamCW(refl,im,wave,G,GB,phfx,calcControls,parmDict):
3196        U = parmDict[hfx+'U']
3197        V = parmDict[hfx+'V']
3198        W = parmDict[hfx+'W']
3199        X = parmDict[hfx+'X']
3200        Y = parmDict[hfx+'Y']
3201        tanPos = tand(refl[5+im]/2.0)
3202        Ssig,Sgam = GetSampleSigGam(refl,im,wave,G,GB,SGData,hfx,phfx,calcControls,parmDict)
3203        sig = U*tanPos**2+V*tanPos+W+Ssig     #save peak sigma
3204        sig = max(0.001,sig)
3205        gam = X/cosd(refl[5+im]/2.0)+Y*tanPos+Sgam     #save peak gamma
3206        gam = max(0.001,gam)
3207        return sig,gam
3208               
3209    def GetReflSigGamTOF(refl,im,G,GB,phfx,calcControls,parmDict):
3210        sig = parmDict[hfx+'sig-0']+parmDict[hfx+'sig-1']*refl[4+im]**2+   \
3211            parmDict[hfx+'sig-2']*refl[4+im]**4+parmDict[hfx+'sig-q']/refl[4+im]**2
3212        gam = parmDict[hfx+'X']*refl[4+im]+parmDict[hfx+'Y']*refl[4+im]**2
3213        Ssig,Sgam = GetSampleSigGam(refl,im,0.0,G,GB,SGData,hfx,phfx,calcControls,parmDict)
3214        sig += Ssig
3215        gam += Sgam
3216        return sig,gam
3217       
3218    def GetReflAlpBet(refl,im,hfx,parmDict):
3219        alp = parmDict[hfx+'alpha']/refl[4+im]
3220        bet = parmDict[hfx+'beta-0']+parmDict[hfx+'beta-1']/refl[4+im]**4+parmDict[hfx+'beta-q']/refl[4+im]**2
3221        return alp,bet
3222       
3223    hId = Histogram['hId']
3224    hfx = ':%d:'%(hId)
3225    bakType = calcControls[hfx+'bakType']
3226    yb,Histogram['sumBk'] = G2pwd.getBackground(hfx,parmDict,bakType,calcControls[hfx+'histType'],x)
3227    yc = np.zeros_like(yb)
3228    cw = np.diff(x)
3229    cw = np.append(cw,cw[-1])
3230       
3231    if 'C' in calcControls[hfx+'histType']:   
3232        shl = max(parmDict[hfx+'SH/L'],0.002)
3233        Ka2 = False
3234        if hfx+'Lam1' in parmDict.keys():
3235            wave = parmDict[hfx+'Lam1']
3236            Ka2 = True
3237            lamRatio = 360*(parmDict[hfx+'Lam2']-parmDict[hfx+'Lam1'])/(np.pi*parmDict[hfx+'Lam1'])
3238            kRatio = parmDict[hfx+'I(L2)/I(L1)']
3239        else:
3240            wave = parmDict[hfx+'Lam']
3241    for phase in Histogram['Reflection Lists']:
3242        refDict = Histogram['Reflection Lists'][phase]
3243        if phase not in Phases:     #skips deleted or renamed phases silently!
3244            continue
3245        Phase = Phases[phase]
3246        pId = Phase['pId']
3247        pfx = '%d::'%(pId)
3248        phfx = '%d:%d:'%(pId,hId)
3249        hfx = ':%d:'%(hId)
3250        SGData = Phase['General']['SGData']
3251        SGMT = np.array([ops[0].T for ops in SGData['SGOps']])
3252        im = 0
3253        if Phase['General']['Type'] in ['modulated','magnetic']:
3254            SSGData = Phase['General']['SSGData']
3255            SSGMT = np.array([ops[0].T for ops in SSGData['SSGOps']])
3256            im = 1  #offset in SS reflection list
3257            #??
3258        Dij = GetDij(phfx,SGData,parmDict)
3259        A = [parmDict[pfx+'A%d'%(i)]+Dij[i] for i in range(6)]
3260        G,g = G2lat.A2Gmat(A)       #recip & real metric tensors
3261        if np.any(np.diag(G)<0.):
3262            raise G2obj.G2Exception('invalid metric tensor \n cell/Dij refinement not advised')
3263        GA,GB = G2lat.Gmat2AB(G)    #Orthogonalization matricies
3264        Vst = np.sqrt(nl.det(G))    #V*
3265        if not Phase['General'].get('doPawley'):
3266            time0 = time.time()
3267            if im:
3268                SStructureFactor(refDict,G,hfx,pfx,SGData,SSGData,calcControls,parmDict)
3269            else:
3270                StructureFactor2(refDict,G,hfx,pfx,SGData,calcControls,parmDict)
3271#            print 'sf calc time: %.3fs'%(time.time()-time0)
3272        time0 = time.time()
3273        badPeak = False
3274        for iref,refl in enumerate(refDict['RefList']):
3275            if 'C' in calcControls[hfx+'histType']:
3276                if im:
3277                    h,k,l,m = refl[:4]
3278                else:
3279                    h,k,l = refl[:3]
3280                Uniq = np.inner(refl[:3],SGMT)
3281                refl[5+im] = GetReflPos(refl,im,wave,A,pfx,hfx,calcControls,parmDict)         #corrected reflection position
3282                Lorenz = 1./(2.*sind(refl[5+im]/2.)**2*cosd(refl[5+im]/2.))           #Lorentz correction
3283                refl[6+im:8+im] = GetReflSigGamCW(refl,im,wave,G,GB,phfx,calcControls,parmDict)    #peak sig & gam
3284                refl[11+im:15+im] = GetIntensityCorr(refl,im,Uniq,G,g,pfx,phfx,hfx,SGData,calcControls,parmDict)
3285                refl[11+im] *= Vst*Lorenz
3286                 
3287                if Phase['General'].get('doPawley'):
3288                    try:
3289                        if im:
3290                            pInd = pfx+'PWLref:%d'%(pawleyLookup[pfx+'%d,%d,%d,%d'%(h,k,l,m)])
3291                        else:
3292                            pInd = pfx+'PWLref:%d'%(pawleyLookup[pfx+'%d,%d,%d'%(h,k,l)])
3293                        refl[9+im] = parmDict[pInd]
3294                    except KeyError:
3295#                        print ' ***Error %d,%d,%d missing from Pawley reflection list ***'%(h,k,l)
3296                        continue
3297                Wd,fmin,fmax = G2pwd.getWidthsCW(refl[5+im],refl[6+im],refl[7+im],shl)
3298                iBeg = np.searchsorted(x,refl[5+im]-fmin)
3299                iFin = np.searchsorted(x,refl[5+im]+fmax)
3300                if not iBeg+iFin:       #peak below low limit - skip peak
3301                    continue
3302                elif not iBeg-iFin:     #peak above high limit - done
3303                    break
3304                elif iBeg > iFin:   #bad peak coeff - skip
3305                    badPeak = True
3306                    continue
3307                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
3308                if Ka2:
3309                    pos2 = refl[5+im]+lamRatio*tand(refl[5+im]/2.0)       # + 360/pi * Dlam/lam * tan(th)
3310                    Wd,fmin,fmax = G2pwd.getWidthsCW(pos2,refl[6+im],refl[7+im],shl)
3311                    iBeg = np.searchsorted(x,pos2-fmin)
3312                    iFin = np.searchsorted(x,pos2+fmax)
3313                    if not iBeg+iFin:       #peak below low limit - skip peak
3314                        continue
3315                    elif not iBeg-iFin:     #peak above high limit - done
3316                        return yc,yb
3317                    elif iBeg > iFin:   #bad peak coeff - skip
3318                        continue
3319                    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
3320            elif 'T' in calcControls[hfx+'histType']:
3321                h,k,l = refl[:3]
3322                Uniq = np.inner(refl[:3],SGMT)
3323                refl[5+im] = GetReflPos(refl,im,0.0,A,pfx,hfx,calcControls,parmDict)         #corrected reflection position
3324                Lorenz = sind(abs(parmDict[hfx+'2-theta'])/2)*refl[4+im]**4                                                #TOF Lorentz correction
3325#                refl[5+im] += GetHStrainShift(refl,im,SGData,phfx,hfx,calcControls,parmDict)               #apply hydrostatic strain shift
3326                refl[6+im:8+im] = GetReflSigGamTOF(refl,im,G,GB,phfx,calcControls,parmDict)    #peak sig & gam
3327                refl[12+im:14+im] = GetReflAlpBet(refl,im,hfx,parmDict)
3328                refl[11+im],refl[15+im],refl[16+im],refl[17+im] = GetIntensityCorr(refl,im,Uniq,G,g,pfx,phfx,hfx,SGData,calcControls,parmDict)
3329                refl[11+im] *= Vst*Lorenz
3330                if Phase['General'].get('doPawley'):
3331                    try:
3332                        if im:
3333                            pInd =pfx+'PWLref:%d'%(pawleyLookup[pfx+'%d,%d,%d,%d'%(h,k,l,m)])
3334                        else:
3335                            pInd =pfx+'PWLref:%d'%(pawleyLookup[pfx+'%d,%d,%d'%(h,k,l)])
3336                        refl[9+im] = parmDict[pInd]
3337                    except KeyError:
3338#                        print ' ***Error %d,%d,%d missing from Pawley reflection list ***'%(h,k,l)
3339                        continue
3340                Wd,fmin,fmax = G2pwd.getWidthsTOF(refl[5+im],refl[12+im],refl[13+im],refl[6+im],refl[7+im])
3341                iBeg = np.searchsorted(x,refl[5+im]-fmin)
3342                iFin = np.searchsorted(x,refl[5+im]+fmax)
3343                if not iBeg+iFin:       #peak below low limit - skip peak
3344                    continue
3345                elif not iBeg-iFin:     #peak above high limit - done
3346                    break
3347                elif iBeg > iFin:   #bad peak coeff - skip
3348                    badPeak = True
3349                    continue
3350                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]
3351#        print 'profile calc time: %.3fs'%(time.time()-time0)
3352    if badPeak:
3353        print 'ouch #4 bad profile coefficients yield negative peak width; some reflections skipped' 
3354    return yc,yb
3355   
3356def getPowderProfileDerv(parmDict,x,varylist,Histogram,Phases,rigidbodyDict,calcControls,pawleyLookup):
3357    'Needs a doc string'
3358   
3359    def cellVaryDerv(pfx,SGData,dpdA): 
3360        if SGData['SGLaue'] in ['-1',]:
3361            return [[pfx+'A0',dpdA[0]],[pfx+'A1',dpdA[1]],[pfx+'A2',dpdA[2]],
3362                [pfx+'A3',dpdA[3]],[pfx+'A4',dpdA[4]],[pfx+'A5',dpdA[5]]]
3363        elif SGData['SGLaue'] in ['2/m',]:
3364            if SGData['SGUniq'] == 'a':
3365                return [[pfx+'A0',dpdA[0]],[pfx+'A1',dpdA[1]],[pfx+'A2',dpdA[2]],[pfx+'A5',dpdA[5]]]
3366            elif SGData['SGUniq'] == 'b':
3367                return [[pfx+'A0',dpdA[0]],[pfx+'A1',dpdA[1]],[pfx+'A2',dpdA[2]],[pfx+'A4',dpdA[4]]]
3368            else:
3369                return [[pfx+'A0',dpdA[0]],[pfx+'A1',dpdA[1]],[pfx+'A2',dpdA[2]],[pfx+'A3',dpdA[3]]]
3370        elif SGData['SGLaue'] in ['mmm',]:
3371            return [[pfx+'A0',dpdA[0]],[pfx+'A1',dpdA[1]],[pfx+'A2',dpdA[2]]]
3372        elif SGData['SGLaue'] in ['4/m','4/mmm']:
3373            return [[pfx+'A0',dpdA[0]],[pfx+'A2',dpdA[2]]]
3374        elif SGData['SGLaue'] in ['6/m','6/mmm','3m1', '31m', '3']:
3375            return [[pfx+'A0',dpdA[0]],[pfx+'A2',dpdA[2]]]
3376        elif SGData['SGLaue'] in ['3R', '3mR']:
3377            return [[pfx+'A0',dpdA[0]+dpdA[1]+dpdA[2]],[pfx+'A3',dpdA[3]+dpdA[4]+dpdA[5]]]                       
3378        elif SGData['SGLaue'] in ['m3m','m3']:
3379            return [[pfx+'A0',dpdA[0]]]
3380           
3381    # create a list of dependent variables and set up a dictionary to hold their derivatives
3382    dependentVars = G2mv.GetDependentVars()
3383    depDerivDict = {}
3384    for j in dependentVars:
3385        depDerivDict[j] = np.zeros(shape=(len(x)))
3386    #print 'dependent vars',dependentVars
3387    lenX = len(x)               
3388    hId = Histogram['hId']
3389    hfx = ':%d:'%(hId)
3390    bakType = calcControls[hfx+'bakType']
3391    dMdv = np.zeros(shape=(len(varylist),len(x)))
3392    dMdv = ma.array(dMdv,mask=np.outer(np.ones(len(varylist)),ma.getmaskarray(x)))      #x is a MaskedArray!
3393    dMdb,dMddb,dMdpk = G2pwd.getBackgroundDerv(hfx,parmDict,bakType,calcControls[hfx+'histType'],x)
3394    if hfx+'Back;0' in varylist: # for now assume that Back;x vars to not appear in constraints
3395        bBpos = varylist.index(hfx+'Back;0')
3396        dMdv[bBpos:bBpos+len(dMdb)] += dMdb
3397    names = [hfx+'DebyeA',hfx+'DebyeR',hfx+'DebyeU']
3398    for name in varylist:
3399        if 'Debye' in name:
3400            id = int(name.split(';')[-1])
3401            parm = name[:int(name.rindex(';'))]
3402            ip = names.index(parm)
3403            dMdv[varylist.index(name)] += dMddb[3*id+ip]
3404    names = [hfx+'BkPkpos',hfx+'BkPkint',hfx+'BkPksig',hfx+'BkPkgam']
3405    for name in varylist:
3406        if 'BkPk' in name:
3407            parm,id = name.split(';')
3408            id = int(id)
3409            if parm in names:
3410                ip = names.index(parm)
3411                dMdv[varylist.index(name)] += dMdpk[4*id+ip]
3412    cw = np.diff(x)
3413    cw = np.append(cw,cw[-1])
3414    Ka2 = False #also for TOF!
3415    if 'C' in calcControls[hfx+'histType']:   
3416        shl = max(parmDict[hfx+'SH/L'],0.002)
3417        if hfx+'Lam1' in parmDict.keys():
3418            wave = parmDict[hfx+'Lam1']
3419            Ka2 = True
3420            lamRatio = 360*(parmDict[hfx+'Lam2']-parmDict[hfx+'Lam1'])/(np.pi*parmDict[hfx+'Lam1'])
3421            kRatio = parmDict[hfx+'I(L2)/I(L1)']
3422        else:
3423            wave = parmDict[hfx+'Lam']
3424    for phase in Histogram['Reflection Lists']:
3425        refDict = Histogram['Reflection Lists'][phase]
3426        if phase not in Phases:     #skips deleted or renamed phases silently!
3427            continue
3428        Phase = Phases[phase]
3429        SGData = Phase['General']['SGData']
3430        SGMT = np.array([ops[0].T for ops in SGData['SGOps']])
3431        im = 0
3432        if Phase['General']['Type'] in ['modulated','magnetic']:
3433            SSGData = Phase['General']['SSGData']
3434            SSGMT = np.array([ops[0].T for ops in SSGData['SSGOps']])
3435            im = 1  #offset in SS reflection list
3436            #??
3437        pId = Phase['pId']
3438        pfx = '%d::'%(pId)
3439        phfx = '%d:%d:'%(pId,hId)
3440        Dij = GetDij(phfx,SGData,parmDict)
3441        A = [parmDict[pfx+'A%d'%(i)]+Dij[i] for i in range(6)]
3442        G,g = G2lat.A2Gmat(A)       #recip & real metric tensors
3443        GA,GB = G2lat.Gmat2AB(G)    #Orthogonalization matricies
3444        if not Phase['General'].get('doPawley'):
3445            time0 = time.time()
3446            if im:
3447                dFdvDict = SStructureFactorDerv(refDict,im,G,hfx,pfx,SGData,SSGData,calcControls,parmDict)
3448            else:
3449                dFdvDict = StructureFactorDerv2(refDict,G,hfx,pfx,SGData,calcControls,parmDict)
3450#            print 'sf-derv time %.3fs'%(time.time()-time0)
3451            ApplyRBModelDervs(dFdvDict,parmDict,rigidbodyDict,Phase)
3452        time0 = time.time()
3453        for iref,refl in enumerate(refDict['RefList']):
3454            if im:
3455                h,k,l,m = refl[:4]
3456            else:
3457                h,k,l = refl[:3]
3458            Uniq = np.inner(refl[:3],SGMT)
3459            if 'T' in calcControls[hfx+'histType']:
3460                wave = refl[14+im]
3461            dIdsh,dIdsp,dIdpola,dIdPO,dFdODF,dFdSA,dFdAb,dFdEx = GetIntensityDerv(refl,im,wave,Uniq,G,g,pfx,phfx,hfx,SGData,calcControls,parmDict)
3462            if 'C' in calcControls[hfx+'histType']:        #CW powder
3463                Wd,fmin,fmax = G2pwd.getWidthsCW(refl[5+im],refl[6+im],refl[7+im],shl)
3464            else: #'T'OF
3465                Wd,fmin,fmax = G2pwd.getWidthsTOF(refl[5+im],refl[12+im],refl[13+im],refl[6+im],refl[7+im])
3466            iBeg = np.searchsorted(x,refl[5+im]-fmin)
3467            iFin = np.searchsorted(x,refl[5+im]+fmax)
3468            if not iBeg+iFin:       #peak below low limit - skip peak
3469                continue
3470            elif not iBeg-iFin:     #peak above high limit - done
3471                break
3472            pos = refl[5+im]
3473            if 'C' in calcControls[hfx+'histType']:
3474                tanth = tand(pos/2.0)
3475                costh = cosd(pos/2.0)
3476                lenBF = iFin-iBeg
3477                dMdpk = np.zeros(shape=(6,lenBF))
3478                dMdipk = G2pwd.getdFCJVoigt3(refl[5+im],refl[6+im],refl[7+im],shl,ma.getdata(x[iBeg:iFin]))
3479                for i in range(5):
3480                    dMdpk[i] += 100.*cw[iBeg:iFin]*refl[11+im]*refl[9+im]*dMdipk[i]
3481                dervDict = {'int':dMdpk[0],'pos':dMdpk[1],'sig':dMdpk[2],'gam':dMdpk[3],'shl':dMdpk[4],'L1/L2':np.zeros_like(dMdpk[0])}
3482                if Ka2:
3483                    pos2 = refl[5+im]+lamRatio*tanth       # + 360/pi * Dlam/lam * tan(th)
3484                    iBeg2 = np.searchsorted(x,pos2-fmin)
3485                    iFin2 = np.searchsorted(x,pos2+fmax)
3486                    if iBeg2-iFin2:
3487                        lenBF2 = iFin2-iBeg2
3488                        dMdpk2 = np.zeros(shape=(6,lenBF2))
3489                        dMdipk2 = G2pwd.getdFCJVoigt3(pos2,refl[6+im],refl[7+im],shl,ma.getdata(x[iBeg2:iFin2]))
3490                        for i in range(5):
3491                            dMdpk2[i] = 100.*cw[iBeg2:iFin2]*refl[11+im]*refl[9+im]*kRatio*dMdipk2[i]
3492                        dMdpk2[5] = 100.*cw[iBeg2:iFin2]*refl[11+im]*dMdipk2[0]
3493                        dervDict2 = {'int':dMdpk2[0],'pos':dMdpk2[1],'sig':dMdpk2[2],'gam':dMdpk2[3],'shl':dMdpk2[4],'L1/L2':dMdpk2[5]*refl[9]}
3494            else:   #'T'OF
3495                lenBF = iFin-iBeg
3496                if lenBF < 0:   #bad peak coeff
3497                    break
3498                dMdpk = np.zeros(shape=(6,lenBF))
3499                dMdipk = G2pwd.getdEpsVoigt(refl[5+im],refl[12+im],refl[13+im],refl[6+im],refl[7+im],ma.getdata(x[iBeg:iFin]))
3500                for i in range(6):
3501                    dMdpk[i] += refl[11+im]*refl[9+im]*dMdipk[i]      #cw[iBeg:iFin]*
3502                dervDict = {'int':dMdpk[0],'pos':dMdpk[1],'alp':dMdpk[2],'bet':dMdpk[3],'sig':dMdpk[4],'gam':dMdpk[5]}           
3503            if Phase['General'].get('doPawley'):
3504                dMdpw = np.zeros(len(x))
3505                try:
3506                    if im:
3507                        pIdx = pfx+'PWLref:'+str(pawleyLookup[pfx+'%d,%d,%d,%d'%(h,k,l,m)])
3508                    else:
3509                        pIdx = pfx+'PWLref:'+str(pawleyLookup[pfx+'%d,%d,%d'%(h,k,l)])
3510                    idx = varylist.index(pIdx)
3511                    dMdpw[iBeg:iFin] = dervDict['int']/refl[9+im]
3512                    if Ka2: #not for TOF either
3513                        dMdpw[iBeg2:iFin2] += dervDict2['int']/refl[9+im]
3514                    dMdv[idx] = dMdpw
3515                except: # ValueError:
3516                    pass
3517            if 'C' in calcControls[hfx+'histType']:
3518                dpdA,dpdw,dpdZ,dpdSh,dpdTr,dpdX,dpdY,dpdV = GetReflPosDerv(refl,im,wave,A,pfx,hfx,calcControls,parmDict)
3519                names = {hfx+'Scale':[dIdsh,'int'],hfx+'Polariz.':[dIdpola,'int'],phfx+'Scale':[dIdsp,'int'],
3520                    hfx+'U':[tanth**2,'sig'],hfx+'V':[tanth,'sig'],hfx+'W':[1.0,'sig'],
3521                    hfx+'X':[1.0/costh,'gam'],hfx+'Y':[tanth,'gam'],hfx+'SH/L':[1.0,'shl'],
3522                    hfx+'I(L2)/I(L1)':[1.0,'L1/L2'],hfx+'Zero':[dpdZ,'pos'],hfx+'Lam':[dpdw,'pos'],
3523                    hfx+'Shift':[dpdSh,'pos'],hfx+'Transparency':[dpdTr,'pos'],hfx+'DisplaceX':[dpdX,'pos'],
3524                    hfx+'DisplaceY':[dpdY,'pos'],}
3525                if 'Bragg' in calcControls[hfx+'instType']:
3526                    names.update({hfx+'SurfRoughA':[dFdAb[0],'int'],
3527                        hfx+'SurfRoughB':[dFdAb[1],'int'],})
3528                else:
3529                    names.update({hfx+'Absorption':[dFdAb,'int'],})
3530            else:   #'T'OF
3531                dpdA,dpdZ,dpdDC,dpdDA,dpdDB,dpdV = GetReflPosDerv(refl,im,0.0,A,pfx,hfx,calcControls,parmDict)
3532                names = {hfx+'Scale':[dIdsh,'int'],phfx+'Scale':[dIdsp,'int'],
3533                    hfx+'difC':[dpdDC,'pos'],hfx+'difA':[dpdDA,'pos'],hfx+'difB':[dpdDB,'pos'],
3534                    hfx+'Zero':[dpdZ,'pos'],hfx+'X':[refl[4+im],'gam'],hfx+'Y':[refl[4+im]**2,'gam'],
3535                    hfx+'alpha':[1./refl[4+im],'alp'],hfx+'beta-0':[1.0,'bet'],hfx+'beta-1':[1./refl[4+im]**4,'bet'],
3536                    hfx+'beta-q':[1./refl[4+im]**2,'bet'],hfx+'sig-0':[1.0,'sig'],hfx+'sig-1':[refl[4+im]**2,'sig'],
3537                    hfx+'sig-2':[refl[4+im]**4,'sig'],hfx+'sig-q':[1./refl[4+im]**2,'sig'],
3538                    hfx+'Absorption':[dFdAb,'int'],phfx+'Extinction':[dFdEx,'int'],}
3539            for name in names:
3540                item = names[name]
3541                if name in varylist:
3542                    dMdv[varylist.index(name)][iBeg:iFin] += item[0]*dervDict[item[1]]
3543                    if Ka2 and iFin2-iBeg2:
3544                        dMdv[varylist.index(name)][iBeg2:iFin2] += item[0]*dervDict2[item[1]]
3545                elif name in dependentVars:
3546                    depDerivDict[name][iBeg:iFin] += item[0]*dervDict[item[1]]
3547                    if Ka2 and iFin2-iBeg2:
3548                        depDerivDict[name][iBeg2:iFin2] += item[0]*dervDict2[item[1]]
3549            for iPO in dIdPO:
3550                if iPO in varylist:
3551                    dMdv[varylist.index(iPO)][iBeg:iFin] += dIdPO[iPO]*dervDict['int']
3552                    if Ka2 and iFin2-iBeg2:
3553                        dMdv[varylist.index(iPO)][iBeg2:iFin2] += dIdPO[iPO]*dervDict2['int']
3554                elif iPO in dependentVars:
3555                    depDerivDict[iPO][iBeg:iFin] += dIdPO[iPO]*dervDict['int']
3556                    if Ka2 and iFin2-iBeg2:
3557                        depDerivDict[iPO][iBeg2:iFin2] += dIdPO[iPO]*dervDict2['int']
3558            for i,name in enumerate(['omega','chi','phi']):
3559                aname = pfx+'SH '+name
3560                if aname in varylist:
3561                    dMdv[varylist.index(aname)][iBeg:iFin] += dFdSA[i]*dervDict['int']
3562                    if Ka2 and iFin2-iBeg2:
3563                        dMdv[varylist.index(aname)][iBeg2:iFin2] += dFdSA[i]*dervDict2['int']
3564                elif aname in dependentVars:
3565                    depDerivDict[aname][iBeg:iFin] += dFdSA[i]*dervDict['int']
3566                    if Ka2 and iFin2-iBeg2:
3567                        depDerivDict[aname][iBeg2:iFin2] += dFdSA[i]*dervDict2['int']
3568            for iSH in dFdODF:
3569                if iSH in varylist:
3570                    dMdv[varylist.index(iSH)][iBeg:iFin] += dFdODF[iSH]*dervDict['int']
3571                    if Ka2 and iFin2-iBeg2:
3572                        dMdv[varylist.index(iSH)][iBeg2:iFin2] += dFdODF[iSH]*dervDict2['int']
3573                elif iSH in dependentVars:
3574                    depDerivDict[iSH][iBeg:iFin] += dFdODF[iSH]*dervDict['int']
3575                    if Ka2 and iFin2-iBeg2:
3576                        depDerivDict[iSH][iBeg2:iFin2] += dFdODF[iSH]*dervDict2['int']
3577            cellDervNames = cellVaryDerv(pfx,SGData,dpdA)
3578            for name,dpdA in cellDervNames:
3579                if name in varylist:
3580                    dMdv[varylist.index(name)][iBeg:iFin] += dpdA*dervDict['pos']
3581                    if Ka2 and iFin2-iBeg2:
3582                        dMdv[varylist.index(name)][iBeg2:iFin2] += dpdA*dervDict2['pos']
3583                elif name in dependentVars:
3584                    depDerivDict[name][iBeg:iFin] += dpdA*dervDict['pos']
3585                    if Ka2 and iFin2-iBeg2:
3586                        depDerivDict[name][iBeg2:iFin2] += dpdA*dervDict2['pos']
3587            dDijDict = GetHStrainShiftDerv(refl,im,SGData,phfx,hfx,calcControls,parmDict)
3588            for name in dDijDict:
3589                if name in varylist:
3590                    dMdv[varylist.index(name)][iBeg:iFin] += dDijDict[name]*dervDict['pos']
3591                    if Ka2 and iFin2-iBeg2:
3592                        dMdv[varylist.index(name)][iBeg2:iFin2] += dDijDict[name]*dervDict2['pos']
3593                elif name in dependentVars:
3594                    depDerivDict[name][iBeg:iFin] += dDijDict[name]*dervDict['pos']
3595                    if Ka2 and iFin2-iBeg2:
3596                        depDerivDict[name][iBeg2:iFin2] += dDijDict[name]*dervDict2['pos']
3597            for i,name in enumerate([pfx+'mV0',pfx+'mV1',pfx+'mV2']):
3598                if name in varylist:
3599                    dMdv[varylist.index(name)][iBeg:iFin] += dpdV[i]*dervDict['pos']
3600                    if Ka2 and iFin2-iBeg2:
3601                        dMdv[varylist.index(name)][iBeg2:iFin2] += dpdV[i]*dervDict2['pos']
3602                elif name in dependentVars:
3603                    depDerivDict[name][iBeg:iFin] += dpdV[i]*dervDict['pos']
3604                    if Ka2 and iFin2-iBeg2:
3605                        depDerivDict[name][iBeg2:iFin2] += dpdV[i]*dervDict2['pos']
3606            if 'C' in calcControls[hfx+'histType']:
3607                sigDict,gamDict = GetSampleSigGamDerv(refl,im,wave,G,GB,SGData,hfx,phfx,calcControls,parmDict)
3608            else:   #'T'OF
3609                sigDict,gamDict = GetSampleSigGamDerv(refl,im,0.0,G,GB,SGData,hfx,phfx,calcControls,parmDict)
3610            for name in gamDict:
3611                if name in varylist:
3612                    dMdv[varylist.index(name)][iBeg:iFin] += gamDict[name]*dervDict['gam']
3613                    if Ka2 and iFin2-iBeg2:
3614                        dMdv[varylist.index(name)][iBeg2:iFin2] += gamDict[name]*dervDict2['gam']
3615                elif name in dependentVars:
3616                    depDerivDict[name][iBeg:iFin] += gamDict[name]*dervDict['gam']
3617                    if Ka2 and iFin2-iBeg2:
3618                        depDerivDict[name][iBeg2:iFin2] += gamDict[name]*dervDict2['gam']
3619            for name in sigDict:
3620                if name in varylist:
3621                    dMdv[varylist.index(name)][iBeg:iFin] += sigDict[name]*dervDict['sig']
3622                    if Ka2 and iFin2-iBeg2:
3623                        dMdv[varylist.index(name)][iBeg2:iFin2] += sigDict[name]*dervDict2['sig']
3624                elif name in dependentVars:
3625                    depDerivDict[name][iBeg:iFin] += sigDict[name]*dervDict['sig']
3626                    if Ka2 and iFin2-iBeg2:
3627                        depDerivDict[name][iBeg2:iFin2] += sigDict[name]*dervDict2['sig']
3628            for name in ['BabA','BabU']:
3629                if refl[9+im]:
3630                    if phfx+name in varylist:
3631                        dMdv[varylist.index(phfx+name)][iBeg:iFin] += parmDict[phfx+'Scale']*dFdvDict[phfx+name][iref]*dervDict['int']/refl[9+im]
3632                        if Ka2 and iFin2-iBeg2:
3633                            dMdv[varylist.index(phfx+name)][iBeg2:iFin2] += parmDict[phfx+'Scale']*dFdvDict[phfx+name][iref]*dervDict2['int']/refl[9+im]
3634                    elif phfx+name in dependentVars:                   
3635                        depDerivDict[phfx+name][iBeg:iFin] += parmDict[phfx+'Scale']*dFdvDict[phfx+name][iref]*dervDict['int']/refl[9+im]
3636                        if Ka2 and iFin2-iBeg2:
3637                            depDerivDict[phfx+name][iBeg2:iFin2] += parmDict[phfx+'Scale']*dFdvDict[phfx+name][iref]*dervDict2['int']/refl[9+im]                 
3638            if not Phase['General'].get('doPawley'):
3639                #do atom derivatives -  for RB,F,X & U so far             
3640                corr = dervDict['int']/refl[9+im]
3641                if Ka2 and iFin2-iBeg2:
3642                    corr2 = dervDict2['int']/refl[9+im]
3643                for name in varylist+dependentVars:
3644                    if '::RBV;' in name:
3645                        pass
3646                    else:
3647                        try:
3648                            aname = name.split(pfx)[1][:2]
3649                            if aname not in ['Af','dA','AU','RB','Xs','Xc','Ys','Yc','Zs','Zc','Tm','Xm','Ym','Zm','U1','U2','U3']: continue # skip anything not an atom or rigid body param
3650                        except IndexError:
3651                            continue
3652                    if name in varylist:
3653                        dMdv[varylist.index(name)][iBeg:iFin] += dFdvDict[name][iref]*corr
3654                        if Ka2 and iFin2-iBeg2:
3655                            dMdv[varylist.index(name)][iBeg2:iFin2] += dFdvDict[name][iref]*corr2
3656                    elif name in dependentVars:
3657                        depDerivDict[name][iBeg:iFin] += dFdvDict[name][iref]*corr
3658                        if Ka2 and iFin2-iBeg2:
3659                            depDerivDict[name][iBeg2:iFin2] += dFdvDict[name][iref]*corr2
3660    #        print 'profile derv time: %.3fs'%(time.time()-time0)
3661    # now process derivatives in constraints
3662    G2mv.Dict2Deriv(varylist,depDerivDict,dMdv)
3663    return dMdv
3664   
3665def UserRejectHKL(ref,im,userReject):
3666    if ref[5+im]/ref[6+im] < userReject['minF/sig']:
3667        return False
3668    elif userReject['MaxD'] < ref[4+im] > userReject['MinD']:
3669        return False
3670    elif ref[11+im] < userReject['MinExt']:
3671        return False
3672    elif abs(ref[5+im]-ref[7+im])/ref[6+im] > userReject['MaxDF/F']:
3673        return False
3674    return True
3675   
3676def dervHKLF(Histogram,Phase,calcControls,varylist,parmDict,rigidbodyDict):
3677    '''Loop over reflections in a HKLF histogram and compute derivatives of the fitting
3678    model (M) with respect to all parameters.  Independent and dependant dM/dp arrays
3679    are returned to either dervRefine or HessRefine.
3680
3681    :returns:
3682    '''
3683    nobs = Histogram['Residuals']['Nobs']
3684    hId = Histogram['hId']
3685    hfx = ':%d:'%(hId)
3686    pfx = '%d::'%(Phase['pId'])
3687    phfx = '%d:%d:'%(Phase['pId'],hId)
3688    SGData = Phase['General']['SGData']
3689    im = 0
3690    if Phase['General']['Type'] in ['modulated','magnetic']:
3691        SSGData = Phase['General']['SSGData']
3692        SSGMT = np.array([ops[0].T for ops in SSGData['SSGOps']])
3693        im = 1  #offset in SS reflection list
3694    A = [parmDict[pfx+'A%d'%(i)] for i in range(6)]
3695    G,g = G2lat.A2Gmat(A)       #recip & real metric tensors
3696    TwinLaw = calcControls[phfx+'TwinLaw']
3697    refDict = Histogram['Data']
3698    if parmDict[phfx+'Scale'] < 0.:
3699        parmDict[phfx+'Scale'] = .001
3700    if im: # split to nontwin/twin versions
3701        if len(TwinLaw) > 1:
3702            dFdvDict = SStructureFactorDervTw(refDict,im,G,hfx,pfx,SGData,SSGData,calcControls,parmDict)    #?
3703        else:
3704            dFdvDict = SStructureFactorDerv(refDict,im,G,hfx,pfx,SGData,SSGData,calcControls,parmDict)  #OK
3705    else:
3706        if len(TwinLaw) > 1:
3707            dFdvDict = StructureFactorDervTw2(refDict,G,hfx,pfx,SGData,calcControls,parmDict)
3708        else:   #correct!!
3709            dFdvDict = StructureFactorDerv2(refDict,G,hfx,pfx,SGData,calcControls,parmDict)
3710    ApplyRBModelDervs(dFdvDict,parmDict,rigidbodyDict,Phase)
3711    dMdvh = np.zeros((len(varylist),len(refDict['RefList'])))
3712    dependentVars = G2mv.GetDependentVars()
3713    depDerivDict = {}
3714    for j in dependentVars:
3715        depDerivDict[j] = np.zeros(shape=(len(refDict['RefList'])))
3716    wdf = np.zeros(len(refDict['RefList']))
3717    if calcControls['F**2']:
3718        for iref,ref in enumerate(refDict['RefList']):
3719            if ref[6+im] > 0:
3720                dervDict,dervCor = SCExtinction(ref,im,phfx,hfx,pfx,calcControls,parmDict,varylist+dependentVars)[1:]
3721                w = 1.0/ref[6+im]
3722                if ref[3+im] > 0:
3723                    wdf[iref] = w*(ref[5+im]-ref[7+im])
3724                    for j,var in enumerate(varylist):
3725                        if var in dFdvDict:
3726                            dMdvh[j][iref] = w*dFdvDict[var][iref]*parmDict[phfx+'Scale']*ref[11+im]
3727                    for var in dependentVars:
3728                        if var in dFdvDict:
3729                            depDerivDict[var][iref] = w*dFdvDict[var][iref]*parmDict[phfx+'Scale']*ref[11+im]
3730                    if phfx+'Scale' in varylist:
3731                        dMdvh[varylist.index(phfx+'Scale')][iref] = w*ref[7+im]*ref[11+im]/parmDict[phfx+'Scale']  #OK
3732                    elif phfx+'Scale' in dependentVars:
3733                        depDerivDict[phfx+'Scale'][iref] = w*ref[7+im]*ref[11+im]/parmDict[phfx+'Scale']   #OK
3734                    for item in ['Ep','Es','Eg']:
3735                        if phfx+item in varylist and phfx+item in dervDict:
3736                            dMdvh[varylist.index(phfx+item)][iref] = w*dervDict[phfx+item]/ref[11+im]  #OK
3737                        elif phfx+item in dependentVars and phfx+item in dervDict:
3738                            depDerivDict[phfx+item][iref] = w*dervDict[phfx+item]/ref[11+im]  #OK
3739                    for item in ['BabA','BabU']:
3740                        if phfx+item in varylist:
3741                            dMdvh[varylist.index(phfx+item)][iref] = w*dFdvDict[pfx+item][iref]*parmDict[phfx+'Scale']*ref[11+im]
3742                        elif phfx+item in dependentVars:
3743                            depDerivDict[phfx+item][iref] = w*dFdvDict[pfx+item][iref]*parmDict[phfx+'Scale']*ref[11+im]
3744    else:   #F refinement
3745        for iref,ref in enumerate(refDict['RefList']):
3746            if ref[5+im] > 0.:
3747                dervDict,dervCor = SCExtinction(ref,im,phfx,hfx,pfx,calcControls,parmDict,varylist+dependentVars)[1:]
3748                Fo = np.sqrt(ref[5+im])
3749                Fc = np.sqrt(ref[7+im])
3750                w = 1.0/ref[6+im]
3751                if ref[3+im] > 0:
3752                    wdf[iref] = 2.0*Fc*w*(Fo-Fc)
3753                    for j,var in enumerate(varylist):
3754                        if var in dFdvDict:
3755                            dMdvh[j][iref] = w*dFdvDict[var][iref]*parmDict[phfx+'Scale']*ref[11+im]
3756                    for var in dependentVars:
3757                        if var in dFdvDict:
3758                            depDerivDict[var][iref] = w*dFdvDict[var][iref]*parmDict[phfx+'Scale']*ref[11+im]
3759                    if phfx+'Scale' in varylist:
3760                        dMdvh[varylist.index(phfx+'Scale')][iref] = w*ref[7+im]*ref[11+im]/parmDict[phfx+'Scale']  #OK
3761                    elif phfx+'Scale' in dependentVars:
3762                        depDerivDict[phfx+'Scale'][iref] = w*ref[7+im]*ref[11+im]/parmDict[phfx+'Scale']   #OK                   
3763                    for item in ['Ep','Es','Eg']:   #OK!
3764                        if phfx+item in varylist and phfx+item in dervDict:
3765                            dMdvh[varylist.index(phfx+item)][iref] = w*dervDict[phfx+item]/ref[11+im] 
3766                        elif phfx+item in dependentVars and phfx+item in dervDict:
3767                            depDerivDict[phfx+item][iref] = w*dervDict[phfx+item]/ref[11+im]
3768                    for item in ['BabA','BabU']:
3769                        if phfx+item in varylist:
3770                            dMdvh[varylist.index(phfx+item)][iref] = w*dFdvDict[phfx+item][iref]*parmDict[phfx+'Scale']*ref[11+im]
3771                        elif phfx+item in dependentVars:
3772                            depDerivDict[phfx+item][iref] = w*dFdvDict[phfx+item][iref]*parmDict[phfx+'Scale']*ref[11+im]
3773    return dMdvh,depDerivDict,wdf
3774   
3775
3776def dervRefine(values,HistoPhases,parmDict,varylist,calcControls,pawleyLookup,dlg):
3777    '''Loop over histograms and compute derivatives of the fitting
3778    model (M) with respect to all parameters.  Results are returned in
3779    a Jacobian matrix (aka design matrix) of dimensions (n by m) where
3780    n is the number of parameters and m is the number of data
3781    points. This can exceed memory when m gets large. This routine is
3782    used when refinement derivatives are selected as "analtytic
3783    Jacobian" in Controls.
3784
3785    :returns: Jacobian numpy.array dMdv for all histograms concatinated
3786    '''
3787    parmDict.update(zip(varylist,values))
3788    G2mv.Dict2Map(parmDict,varylist)
3789    Histograms,Phases,restraintDict,rigidbodyDict = HistoPhases
3790    nvar = len(varylist)
3791    dMdv = np.empty(0)
3792    histoList = Histograms.keys()
3793    histoList.sort()
3794    for histogram in histoList:
3795        if 'PWDR' in histogram[:4]:
3796            Histogram = Histograms[histogram]
3797            hId = Histogram['hId']
3798            hfx = ':%d:'%(hId)
3799            wtFactor = calcControls[hfx+'wtFactor']
3800            Limits = calcControls[hfx+'Limits']
3801            x,y,w,yc,yb,yd = Histogram['Data']
3802            xB = np.searchsorted(x,Limits[0])
3803            xF = np.searchsorted(x,Limits[1])
3804            dMdvh = np.sqrt(w[xB:xF])*getPowderProfileDerv(parmDict,x[xB:xF],
3805                varylist,Histogram,Phases,rigidbodyDict,calcControls,pawleyLookup)
3806        elif 'HKLF' in histogram[:4]:
3807            Histogram = Histograms[histogram]
3808            phase = Histogram['Reflection Lists']
3809            Phase = Phases[phase]
3810            dMdvh,depDerivDict,wdf = dervHKLF(Histogram,Phase,calcControls,varylist,parmDict,rigidbodyDict)
3811            hfx = ':%d:'%(Histogram['hId'])
3812            wtFactor = calcControls[hfx+'wtFactor']
3813            # now process derivatives in constraints
3814            G2mv.Dict2Deriv(varylist,depDerivDict,dMdvh)
3815        else:
3816            continue        #skip non-histogram entries
3817        if len(dMdv):
3818            dMdv = np.concatenate((dMdv.T,np.sqrt(wtFactor)*dMdvh.T)).T
3819        else:
3820            dMdv = np.sqrt(wtFactor)*dMdvh
3821           
3822    pNames,pVals,pWt,pWsum = penaltyFxn(HistoPhases,calcControls,parmDict,varylist)
3823    if np.any(pVals):
3824        dpdv = penaltyDeriv(pNames,pVals,HistoPhases,calcControls,parmDict,varylist)
3825        dMdv = np.concatenate((dMdv.T,(np.sqrt(pWt)*dpdv).T)).T
3826       
3827    return dMdv
3828
3829def HessRefine(values,HistoPhases,parmDict,varylist,calcControls,pawleyLookup,dlg):
3830    '''Loop over histograms and compute derivatives of the fitting
3831    model (M) with respect to all parameters.  For each histogram, the
3832    Jacobian matrix, dMdv, with dimensions (n by m) where n is the
3833    number of parameters and m is the number of data points *in the
3834    histogram*. The (n by n) Hessian is computed from each Jacobian
3835    and it is returned.  This routine is used when refinement
3836    derivatives are selected as "analtytic Hessian" in Controls.
3837
3838    :returns: Vec,Hess where Vec is the least-squares vector and Hess is the Hessian
3839    '''
3840    parmDict.update(zip(varylist,values))
3841    G2mv.Dict2Map(parmDict,varylist)
3842    Histograms,Phases,restraintDict,rigidbodyDict = HistoPhases
3843    #fixup H atom positions here?
3844    ApplyRBModels(parmDict,Phases,rigidbodyDict)        #,Update=True??
3845    nvar = len(varylist)
3846    Hess = np.empty(0)
3847    histoList = Histograms.keys()
3848    histoList.sort()
3849    for histogram in histoList:
3850        if 'PWDR' in histogram[:4]:
3851            Histogram = Histograms[histogram]
3852            hId = Histogram['hId']
3853            hfx = ':%d:'%(hId)
3854            wtFactor = calcControls[hfx+'wtFactor']
3855            Limits = calcControls[hfx+'Limits']
3856            x,y,w,yc,yb,yd = Histogram['Data']
3857            W = wtFactor*w
3858            dy = y-yc
3859            xB = np.searchsorted(x,Limits[0])
3860            xF = np.searchsorted(x,Limits[1])
3861            dMdvh = getPowderProfileDerv(parmDict,x[xB:xF],
3862                varylist,Histogram,Phases,rigidbodyDict,calcControls,pawleyLookup)
3863            Wt = ma.sqrt(W[xB:xF])[nxs,:]
3864            Dy = dy[xB:xF][nxs,:]
3865            dMdvh *= Wt
3866            if dlg:
3867                dlg.Update(Histogram['Residuals']['wR'],newmsg='Hessian for histogram %d\nAll data Rw=%8.3f%s'%(hId,Histogram['Residuals']['wR'],'%'))
3868            if len(Hess):
3869                Hess += np.inner(dMdvh,dMdvh)
3870                dMdvh *= Wt*Dy
3871                Vec += np.sum(dMdvh,axis=1)
3872            else:
3873                Hess = np.inner(dMdvh,dMdvh)
3874                dMdvh *= Wt*Dy
3875                Vec = np.sum(dMdvh,axis=1)
3876        elif 'HKLF' in histogram[:4]:
3877            Histogram = Histograms[histogram]
3878            phase = Histogram['Reflection Lists']
3879            Phase = Phases[phase]
3880            dMdvh,depDerivDict,wdf = dervHKLF(Histogram,Phase,calcControls,varylist,parmDict,rigidbodyDict)
3881            hId = Histogram['hId']
3882            hfx = ':%d:'%(Histogram['hId'])
3883            wtFactor = calcControls[hfx+'wtFactor']
3884            # now process derivatives in constraints
3885            G2mv.Dict2Deriv(varylist,depDerivDict,dMdvh)
3886#            print 'matrix build time: %.3f'%(time.time()-time0)
3887
3888            if dlg:
3889                dlg.Update(Histogram['Residuals']['wR'],newmsg='Hessian for histogram %d Rw=%8.3f%s'%(hId,Histogram['Residuals']['wR'],'%'))[0]
3890            if len(Hess):
3891                Vec += wtFactor*np.sum(dMdvh*wdf,axis=1)
3892                Hess += wtFactor*np.inner(dMdvh,dMdvh)
3893            else:
3894                Vec = wtFactor*np.sum(dMdvh*wdf,axis=1)
3895                Hess = wtFactor*np.inner(dMdvh,dMdvh)
3896        else:
3897            continue        #skip non-histogram entries
3898    pNames,pVals,pWt,pWsum = penaltyFxn(HistoPhases,calcControls,parmDict,varylist)
3899    if np.any(pVals):
3900        dpdv = penaltyDeriv(pNames,pVals,HistoPhases,calcControls,parmDict,varylist)
3901        Vec += np.sum(dpdv*pWt*pVals,axis=1)
3902        Hess += np.inner(dpdv*pWt,dpdv)
3903    return Vec,Hess
3904
3905def errRefine(values,HistoPhases,parmDict,varylist,calcControls,pawleyLookup,dlg=None):       
3906    '''Computes the point-by-point discrepancies between every data point in every histogram
3907    and the observed value. Used in the Jacobian, Hessian & numeric least-squares to compute function
3908   
3909    :returns: an np array of differences between observed and computed diffraction values.
3910    '''
3911    Values2Dict(parmDict, varylist, values)
3912    G2mv.Dict2Map(parmDict,varylist)
3913    Histograms,Phases,restraintDict,rigidbodyDict = HistoPhases
3914    M = np.empty(0)
3915    SumwYo = 0
3916    Nobs = 0
3917    Nrej = 0
3918    Next = 0
3919    ApplyRBModels(parmDict,Phases,rigidbodyDict)
3920    #fixup Hatom positions here....
3921    histoList = Histograms.keys()
3922    histoList.sort()
3923    for histogram in histoList:
3924        if 'PWDR' in histogram[:4]:
3925            Histogram = Histograms[histogram]
3926            hId = Histogram['hId']
3927            hfx = ':%d:'%(hId)
3928            wtFactor = calcControls[hfx+'wtFactor']
3929            Limits = calcControls[hfx+'Limits']
3930            x,y,w,yc,yb,yd = Histogram['Data']
3931            yc *= 0.0                           #zero full calcd profiles
3932            yb *= 0.0
3933            yd *= 0.0
3934            xB = np.searchsorted(x,Limits[0])
3935            xF = np.searchsorted(x,Limits[1])
3936            yc[xB:xF],yb[xB:xF] = getPowderProfile(parmDict,x[xB:xF],
3937                varylist,Histogram,Phases,calcControls,pawleyLookup)
3938            yc[xB:xF] += yb[xB:xF]
3939            if not np.any(y):                   #fill dummy data
3940                rv = st.poisson(yc[xB:xF])
3941                y[xB:xF] = rv.rvs()
3942                Z = np.ones_like(yc[xB:xF])
3943                Z[1::2] *= -1
3944                y[xB:xF] = yc[xB:xF]+np.abs(y[xB:xF]-yc[xB:xF])*Z
3945                w[xB:xF] = np.where(y[xB:xF]>0.,1./y[xB:xF],1.0)
3946            yd[xB:xF] = y[xB:xF]-yc[xB:xF]
3947            W = wtFactor*w
3948            wdy = -ma.sqrt(W[xB:xF])*(yd[xB:xF])
3949            Histogram['Residuals']['Nobs'] = ma.count(x[xB:xF])
3950            Nobs += Histogram['Residuals']['Nobs']
3951            Histogram['Residuals']['sumwYo'] = ma.sum(W[xB:xF]*y[xB:xF]**2)
3952            SumwYo += Histogram['Residuals']['sumwYo']
3953            Histogram['Residuals']['R'] = min(100.,ma.sum(ma.abs(yd[xB:xF]))/ma.sum(y[xB:xF])*100.)
3954            Histogram['Residuals']['wR'] = min(100.,ma.sqrt(ma.sum(wdy**2)/Histogram['Residuals']['sumwYo'])*100.)
3955            sumYmB = ma.sum(ma.where(yc[xB:xF]!=yb[xB:xF],ma.abs(y[xB:xF]-yb[xB:xF]),0.))
3956            sumwYmB2 = ma.sum(ma.where(yc[xB:xF]!=yb[xB:xF],W[xB:xF]*(y[xB:xF]-yb[xB:xF])**2,0.))
3957            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.))
3958            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.))
3959            Histogram['Residuals']['Rb'] = min(100.,100.*sumYB/sumYmB)
3960            Histogram['Residuals']['wRb'] = min(100.,100.*ma.sqrt(sumwYB2/sumwYmB2))
3961            Histogram['Residuals']['wRmin'] = min(100.,100.*ma.sqrt(Histogram['Residuals']['Nobs']/Histogram['Residuals']['sumwYo']))
3962            if dlg:
3963                dlg.Update(Histogram['Residuals']['wR'],newmsg='For histogram %d Rw=%8.3f%s'%(hId,Histogram['Residuals']['wR'],'%'))[0]
3964            M = np.concatenate((M,wdy))
3965#end of PWDR processing
3966        elif 'HKLF' in histogram[:4]:
3967            Histogram = Histograms[histogram]
3968            Histogram['Residuals'] = {}
3969            phase = Histogram['Reflection Lists']
3970            Phase = Phases[phase]
3971            hId = Histogram['hId']
3972            hfx = ':%d:'%(hId)
3973            wtFactor = calcControls[hfx+'wtFactor']
3974            pfx = '%d::'%(Phase['pId'])
3975            phfx = '%d:%d:'%(Phase['pId'],hId)
3976            SGData = Phase['General']['SGData']
3977            TwinLaw = calcControls[phfx+'TwinLaw']
3978            im = 0
3979            if parmDict[phfx+'Scale'] < 0.:
3980                parmDict[phfx+'Scale'] = .001               
3981            if Phase['General']['Type'] in ['modulated','magnetic']:
3982                SSGData = Phase['General']['SSGData']
3983                SSGMT = np.array([ops[0].T for ops in SSGData['SSGOps']])
3984                im = 1  #offset in SS reflection list
3985            A = [parmDict[pfx+'A%d'%(i)] for i in range(6)]
3986            G,g = G2lat.A2Gmat(A)       #recip & real metric tensors
3987            refDict = Histogram['Data']
3988            time0 = time.time()
3989            if im:
3990                if len(TwinLaw) > 1:
3991                    SStructureFactorTw(refDict,G,hfx,pfx,SGData,SSGData,calcControls,parmDict)
3992                else:
3993                    SStructureFactor(refDict,G,hfx,pfx,SGData,SSGData,calcControls,parmDict)
3994            else:
3995                StructureFactor2(refDict,G,hfx,pfx,SGData,calcControls,parmDict)
3996#            print 'sf-calc time: %.3f'%(time.time()-time0)
3997            df = np.zeros(len(refDict['RefList']))
3998            sumwYo = 0
3999            sumFo = 0
4000            sumFo2 = 0
4001            sumFc2 = 0
4002            sumdF = 0
4003            sumdF2 = 0
4004            if im:
4005                sumSSFo = np.zeros(10)
4006                sumSSFo2 = np.zeros(10)
4007                sumSSdF = np.zeros(10)
4008                sumSSdF2 = np.zeros(10)
4009                sumSSwYo = np.zeros(10)
4010                sumSSwdf2 = np.zeros(10)
4011                SSnobs = np.zeros(10)
4012            nobs = 0
4013            nrej = 0
4014            next = 0
4015            maxH = 0
4016            if calcControls['F**2']:
4017                for i,ref in enumerate(refDict['RefList']):
4018                    if ref[6+im] > 0:
4019                        ref[11+im] = SCExtinction(ref,im,phfx,hfx,pfx,calcControls,parmDict,varylist)[0]
4020                        w = 1.0/ref[6+im]   # 1/sig(F^2)
4021                        ref[7+im] *= parmDict[phfx+'Scale']*ref[11+im]  #correct Fc^2 for extinction
4022                        ref[8+im] = ref[5+im]/(parmDict[phfx+'Scale']*ref[11+im])
4023                        if UserRejectHKL(ref,im,calcControls['UsrReject']) and ref[3+im]:    #skip sp.gp. absences (mul=0)
4024                            ref[3+im] = abs(ref[3+im])      #mark as allowed
4025                            Fo = np.sqrt(ref[5+im])
4026                            sumFo += Fo
4027                            sumFo2 += ref[5+im]
4028                            sumFc2 += ref[7+im]
4029                            sumdF += abs(Fo-np.sqrt(ref[7+im]))
4030                            sumdF2 += abs(ref[5+im]-ref[7+im])
4031                            nobs += 1
4032                            df[i] = -w*(ref[5+im]-ref[7+im])
4033                            sumwYo += (w*ref[5+im])**2      #w*Fo^2
4034                            if im:  #accumulate super lattice sums
4035                                ind = int(abs(ref[3]))
4036                                sumSSFo[ind] += Fo
4037                                sumSSFo2[ind] += ref[5+im]
4038                                sumSSdF[ind] += abs(Fo-np.sqrt(ref[7+im]))
4039                                sumSSdF2[ind] += abs(ref[5+im]-ref[7+im])
4040                                sumSSwYo[ind] += (w*ref[5+im])**2      #w*Fo^2
4041                                sumSSwdf2[ind] +=  df[i]**2
4042                                SSnobs[ind] += 1
4043                                maxH = max(maxH,ind)                           
4044                        else:
4045                            if ref[3+im]:
4046                                ref[3+im] = -abs(ref[3+im])      #mark as rejected
4047                                nrej += 1
4048                            else:   #sp.gp.extinct
4049                                next += 1
4050            else:
4051                for i,ref in enumerate(refDict['RefList']):
4052                    if ref[5+im] > 0.:
4053                        ref[11+im] = SCExtinction(ref,im,phfx,hfx,pfx,calcControls,parmDict,varylist)[0]
4054                        ref[7+im] *= parmDict[phfx+'Scale']*ref[11+im]    #correct Fc^2 for extinction
4055                        ref[8+im] = ref[5+im]/(parmDict[phfx+'Scale']*ref[11+im])
4056                        Fo = np.sqrt(ref[5+im])
4057                        Fc = np.sqrt(ref[7+im])
4058                        w = 2.0*Fo/ref[6+im]    # 1/sig(F)?
4059                        if UserRejectHKL(ref,im,calcControls['UsrReject']) and ref[3+im]:    #skip sp.gp. absences (mul=0)
4060                            ref[3+im] = abs(ref[3+im])      #mark as allowed
4061                            sumFo += Fo
4062                            sumFo2 += ref[5+im]
4063                            sumFc2 += ref[7+im]
4064                            sumdF += abs(Fo-Fc)
4065                            sumdF2 += abs(ref[5+im]-ref[7+im])
4066                            nobs += 1
4067                            df[i] = -w*(Fo-Fc)
4068                            sumwYo += (w*Fo)**2
4069                            if im:
4070                                ind = int(abs(ref[3]))
4071                                sumSSFo[ind] += Fo
4072                                sumSSFo2[ind] += ref[5+im]
4073                                sumSSdF[ind] += abs(Fo-Fc)
4074                                sumSSdF2[ind] += abs(ref[5+im]-ref[7+im])
4075                                sumSSwYo[ind] += (w*Fo)**2                                                           
4076                                sumSSwdf2[ind] +=  df[i]**2
4077                                SSnobs[ind] += 1                           
4078                                maxH = max(maxH,ind)                           
4079                        else:
4080                            if ref[3+im]:
4081                                ref[3+im] = -abs(ref[3+im])      #mark as rejected
4082                                nrej += 1
4083                            else:   #sp.gp.extinct
4084                                next += 1
4085            Scale = sumFo2/sumFc2
4086            if (Scale < 0.8 or Scale > 1.2) and phfx+'Scale' in varylist:
4087                print 'New scale:',Scale*parmDict[phfx+'Scale']
4088                indx = varylist.index(phfx+'Scale')
4089                values[indx] = Scale*parmDict[phfx+'Scale']             
4090            Histogram['Residuals']['Nobs'] = nobs
4091            Histogram['Residuals']['sumwYo'] = sumwYo
4092            SumwYo += sumwYo
4093            Histogram['Residuals']['wR'] = min(100.,np.sqrt(np.sum(df**2)/sumwYo)*100.)
4094            Histogram['Residuals'][phfx+'Rf'] = 100.*sumdF/sumFo
4095            Histogram['Residuals'][phfx+'Rf^2'] = 100.*sumdF2/sumFo2
4096            Histogram['Residuals'][phfx+'Nref'] = nobs
4097            Histogram['Residuals'][phfx+'Nrej'] = nrej
4098            Histogram['Residuals'][phfx+'Next'] = next
4099            if im:
4100                Histogram['Residuals'][phfx+'SSRf'] = 100.*sumSSdF[:maxH+1]/sumSSFo[:maxH+1]
4101                Histogram['Residuals'][phfx+'SSRf^2'] = 100.*sumSSdF2[:maxH+1]/sumSSFo2[:maxH+1]
4102                Histogram['Residuals'][phfx+'SSNref'] = SSnobs[:maxH+1]
4103                Histogram['Residuals']['SSwR'] = np.sqrt(sumSSwdf2[:maxH+1]/sumSSwYo[:maxH+1])*100.               
4104            Nobs += nobs
4105            Nrej += nrej
4106            Next += next
4107            if dlg:
4108                dlg.Update(Histogram['Residuals']['wR'],newmsg='For histogram %d Rw=%8.3f%s'%(hId,Histogram['Residuals']['wR'],'%'))[0]
4109            M = np.concatenate((M,wtFactor*df))
4110# end of HKLF processing
4111    Histograms['sumwYo'] = SumwYo
4112    Histograms['Nobs'] = Nobs
4113    Histograms['Nrej'] = Nrej
4114    Histograms['Next'] = Next
4115    Rw = min(100.,np.sqrt(np.sum(M**2)/SumwYo)*100.)
4116    if dlg:
4117        GoOn = dlg.Update(Rw,newmsg='%s%8.3f%s'%('All data Rw =',Rw,'%'))[0]
4118        if not GoOn:
4119            parmDict['saved values'] = values
4120            dlg.Destroy()
4121            raise G2obj.G2Exception('User abort')         #Abort!!
4122    pDict,pVals,pWt,pWsum = penaltyFxn(HistoPhases,calcControls,parmDict,varylist)
4123    if len(pVals):
4124        pSum = np.sum(pWt*pVals**2)
4125        for name in pWsum:
4126            if pWsum[name]:
4127                print '  Penalty function for %8s = %12.5g'%(name,pWsum[name])
4128        print 'Total penalty function: %12.5g on %d terms'%(pSum,len(pVals))
4129        Nobs += len(pVals)
4130        M = np.concatenate((M,np.sqrt(pWt)*pVals))
4131    return M
4132                       
Note: See TracBrowser for help on using the repository browser.