source: trunk/GSASIIstrMath.py @ 3427

Last change on this file since 3427 was 3423, checked in by vondreele, 7 years ago

fix chemical composition restraint. Wasn't updating with new fracs after each cycle. Now OK.
new routine GetAtomFracById? in G2math called in G2strMath
fix a wx.wx.... bug in G2ctrlGUI!
fix G2testplot to use wx-Phoenix; ditto testSSymbols

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