source: trunk/GSASIIstrMath.py @ 5486

Last change on this file since 5486 was 5443, checked in by vondreele, 3 years ago

fix to the Paired problem in colors - new GSPaired & GSPaired_r choices
fix to ProgressDialog? - floats not legal
Spin RB changes - various & not complete

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