source: trunk/GSASIIstrMath.py @ 5354

Last change on this file since 5354 was 5343, checked in by vondreele, 3 years ago

fix issue with TOF data in getPawleydRange & remove an obviously not needed "get"

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