source: trunk/GSASIIstrMath.py @ 3835

Last change on this file since 3835 was 3835, checked in by vondreele, 6 years ago

Allow constraints on modulation vector
changes to incommensurate mag. str factr math - a lot closer to correct

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