source: trunk/GSASIIstrMath.py @ 2588

Last change on this file since 2588 was 2550, checked in by vondreele, 9 years ago

fix binary import for Bruker raw files
fix issues for new atoms in mag structures

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