source: trunk/GSASIIstrMath.py @ 3995

Last change on this file since 3995 was 3906, checked in by toby, 6 years ago

implement fixed backgound file in Riteveld Fit; show Rietveld & peak fits with bkg file added to calc bkg, not subtracted

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