source: trunk/GSASIIstrMath.py @ 1984

Last change on this file since 1984 was 1984, checked in by vondreele, 7 years ago

some SS derv work

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 154.3 KB
Line 
1# -*- coding: utf-8 -*-
2'''
3*GSASIIstrMath - structure math routines*
4-----------------------------------------
5'''
6########### SVN repository information ###################
7# $Date: 2015-10-05 14:46:27 +0000 (Mon, 05 Oct 2015) $
8# $Author: vondreele $
9# $Revision: 1984 $
10# $URL: trunk/GSASIIstrMath.py $
11# $Id: GSASIIstrMath.py 1984 2015-10-05 14:46:27Z 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.optimize as so
19import scipy.stats as st
20import GSASIIpath
21GSASIIpath.SetVersionNumber("$Revision: 1984 $")
22import GSASIIElem as G2el
23import GSASIIlattice as G2lat
24import GSASIIspc as G2spc
25import GSASIIpwd as G2pwd
26import GSASIImapvars as G2mv
27import GSASIImath as G2mth
28import GSASIIobj as G2obj
29
30sind = lambda x: np.sin(x*np.pi/180.)
31cosd = lambda x: np.cos(x*np.pi/180.)
32tand = lambda x: np.tan(x*np.pi/180.)
33asind = lambda x: 180.*np.arcsin(x)/np.pi
34acosd = lambda x: 180.*np.arccos(x)/np.pi
35atan2d = lambda y,x: 180.*np.arctan2(y,x)/np.pi
36   
37ateln2 = 8.0*np.log(2.0)
38twopi = 2.0*np.pi
39twopisq = 2.0*np.pi**2
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    TIds = ['T11:','T22:','T33:','T12:','T13:','T23:']
150    LIds = ['L11:','L22:','L33:','L12:','L13:','L23:']
151    SIds = ['S12:','S13:','S21:','S23:','S31:','S32:','SAA:','SBB:']
152    PIds = ['Px:','Py:','Pz:']
153    OIds = ['Oa:','Oi:','Oj:','Ok:']
154    RBIds = rigidbodyDict.get('RBIds',{'Vector':[],'Residue':[]})  #these are lists of rbIds
155    if not RBIds['Vector'] and not RBIds['Residue']:
156        return
157    VRBIds = RBIds['Vector']
158    RRBIds = RBIds['Residue']
159    RBData = rigidbodyDict
160    for item in parmDict:
161        if 'RB' in item:
162            dFdvDict[item] = 0.        #NB: this is a vector which is no. refl. long & must be filled!
163    General = Phase['General']
164    cx,ct,cs,cia = General['AtomPtrs']
165    cell = General['Cell'][1:7]
166    Amat,Bmat = G2lat.cell2AB(cell)
167    rpd = np.pi/180.
168    rpd2 = rpd**2
169    g = nl.inv(np.inner(Bmat,Bmat))
170    gvec = np.sqrt(np.array([g[0][0]**2,g[1][1]**2,g[2][2]**2,
171        g[0][0]*g[1][1],g[0][0]*g[2][2],g[1][1]*g[2][2]]))
172    AtLookup = G2mth.FillAtomLookUp(Phase['Atoms'],cia+8)
173    pfx = str(Phase['pId'])+'::'
174    RBModels =  Phase['RBModels']
175    for irb,RBObj in enumerate(RBModels.get('Vector',[])):
176        VModel = RBData['Vector'][RBObj['RBId']]
177        Q = RBObj['Orient'][0]
178        Pos = RBObj['Orig'][0]
179        jrb = VRBIds.index(RBObj['RBId'])
180        rbsx = str(irb)+':'+str(jrb)
181        dXdv = []
182        for iv in range(len(VModel['VectMag'])):
183            dCdv = []
184            for vec in VModel['rbVect'][iv]:
185                dCdv.append(G2mth.prodQVQ(Q,vec))
186            dXdv.append(np.inner(Bmat,np.array(dCdv)).T)
187        XYZ,Cart = G2mth.UpdateRBXYZ(Bmat,RBObj,RBData,'Vector')
188        for ia,atId in enumerate(RBObj['Ids']):
189            atNum = AtLookup[atId]
190            dx = 0.00001
191            for iv in range(len(VModel['VectMag'])):
192                for ix in [0,1,2]:
193                    dFdvDict['::RBV;'+str(iv)+':'+str(jrb)] += dXdv[iv][ia][ix]*dFdvDict[pfx+atxIds[ix]+str(atNum)]
194            for i,name in enumerate(['RBVPx:','RBVPy:','RBVPz:']):
195                dFdvDict[pfx+name+rbsx] += dFdvDict[pfx+atxIds[i]+str(atNum)]
196            for iv in range(4):
197                Q[iv] -= dx
198                XYZ1 = G2mth.RotateRBXYZ(Bmat,Cart,G2mth.normQ(Q))
199                Q[iv] += 2.*dx
200                XYZ2 = G2mth.RotateRBXYZ(Bmat,Cart,G2mth.normQ(Q))
201                Q[iv] -= dx
202                dXdO = (XYZ2[ia]-XYZ1[ia])/(2.*dx)
203                for ix in [0,1,2]:
204                    dFdvDict[pfx+'RBV'+OIds[iv]+rbsx] += dXdO[ix]*dFdvDict[pfx+atxIds[ix]+str(atNum)]
205            X = G2mth.prodQVQ(Q,Cart[ia])
206            dFdu = np.array([dFdvDict[pfx+Uid+str(AtLookup[atId])] for Uid in atuIds]).T/gvec
207            dFdu = G2lat.U6toUij(dFdu.T)
208            dFdu = np.tensordot(Amat,np.tensordot(Amat,dFdu,([1,0])),([0,1]))           
209            dFdu = G2lat.UijtoU6(dFdu)
210            atNum = AtLookup[atId]
211            if 'T' in RBObj['ThermalMotion'][0]:
212                for i,name in enumerate(['RBVT11:','RBVT22:','RBVT33:','RBVT12:','RBVT13:','RBVT23:']):
213                    dFdvDict[pfx+name+rbsx] += dFdu[i]
214            if 'L' in RBObj['ThermalMotion'][0]:
215                dFdvDict[pfx+'RBVL11:'+rbsx] += rpd2*(dFdu[1]*X[2]**2+dFdu[2]*X[1]**2-dFdu[5]*X[1]*X[2])
216                dFdvDict[pfx+'RBVL22:'+rbsx] += rpd2*(dFdu[0]*X[2]**2+dFdu[2]*X[0]**2-dFdu[4]*X[0]*X[2])
217                dFdvDict[pfx+'RBVL33:'+rbsx] += rpd2*(dFdu[0]*X[1]**2+dFdu[1]*X[0]**2-dFdu[3]*X[0]*X[1])
218                dFdvDict[pfx+'RBVL12:'+rbsx] += rpd2*(-dFdu[3]*X[2]**2-2.*dFdu[2]*X[0]*X[1]+
219                    dFdu[4]*X[1]*X[2]+dFdu[5]*X[0]*X[2])
220                dFdvDict[pfx+'RBVL13:'+rbsx] += rpd2*(-dFdu[4]*X[1]**2-2.*dFdu[1]*X[0]*X[2]+
221                    dFdu[3]*X[1]*X[2]+dFdu[5]*X[0]*X[1])
222                dFdvDict[pfx+'RBVL23:'+rbsx] += rpd2*(-dFdu[5]*X[0]**2-2.*dFdu[0]*X[1]*X[2]+
223                    dFdu[3]*X[0]*X[2]+dFdu[4]*X[0]*X[1])
224            if 'S' in RBObj['ThermalMotion'][0]:
225                dFdvDict[pfx+'RBVS12:'+rbsx] += rpd*(dFdu[5]*X[1]-2.*dFdu[1]*X[2])
226                dFdvDict[pfx+'RBVS13:'+rbsx] += rpd*(-dFdu[5]*X[2]+2.*dFdu[2]*X[1])
227                dFdvDict[pfx+'RBVS21:'+rbsx] += rpd*(-dFdu[4]*X[0]+2.*dFdu[0]*X[2])
228                dFdvDict[pfx+'RBVS23:'+rbsx] += rpd*(dFdu[4]*X[2]-2.*dFdu[2]*X[0])
229                dFdvDict[pfx+'RBVS31:'+rbsx] += rpd*(dFdu[3]*X[0]-2.*dFdu[0]*X[1])
230                dFdvDict[pfx+'RBVS32:'+rbsx] += rpd*(-dFdu[3]*X[1]+2.*dFdu[1]*X[0])
231                dFdvDict[pfx+'RBVSAA:'+rbsx] += rpd*(dFdu[4]*X[1]-dFdu[3]*X[2])
232                dFdvDict[pfx+'RBVSBB:'+rbsx] += rpd*(dFdu[5]*X[0]-dFdu[3]*X[2])
233            if 'U' in RBObj['ThermalMotion'][0]:
234                dFdvDict[pfx+'RBVU:'+rbsx] += dFdvDict[pfx+'AUiso:'+str(AtLookup[atId])]
235
236
237    for irb,RBObj in enumerate(RBModels.get('Residue',[])):
238        Q = RBObj['Orient'][0]
239        Pos = RBObj['Orig'][0]
240        jrb = RRBIds.index(RBObj['RBId'])
241        torData = RBData['Residue'][RBObj['RBId']]['rbSeq']
242        rbsx = str(irb)+':'+str(jrb)
243        XYZ,Cart = G2mth.UpdateRBXYZ(Bmat,RBObj,RBData,'Residue')
244        for itors,tors in enumerate(RBObj['Torsions']):     #derivative error?
245            tname = pfx+'RBRTr;'+str(itors)+':'+rbsx           
246            orId,pvId = torData[itors][:2]
247            pivotVec = Cart[orId]-Cart[pvId]
248            QA = G2mth.AVdeg2Q(-0.001,pivotVec)
249            QB = G2mth.AVdeg2Q(0.001,pivotVec)
250            for ir in torData[itors][3]:
251                atNum = AtLookup[RBObj['Ids'][ir]]
252                rVec = Cart[ir]-Cart[pvId]
253                dR = G2mth.prodQVQ(QB,rVec)-G2mth.prodQVQ(QA,rVec)
254                dRdT = np.inner(Bmat,G2mth.prodQVQ(Q,dR))/.002
255                for ix in [0,1,2]:
256                    dFdvDict[tname] += dRdT[ix]*dFdvDict[pfx+atxIds[ix]+str(atNum)]
257        for ia,atId in enumerate(RBObj['Ids']):
258            atNum = AtLookup[atId]
259            dx = 0.00001
260            for i,name in enumerate(['RBRPx:','RBRPy:','RBRPz:']):
261                dFdvDict[pfx+name+rbsx] += dFdvDict[pfx+atxIds[i]+str(atNum)]
262            for iv in range(4):
263                Q[iv] -= dx
264                XYZ1 = G2mth.RotateRBXYZ(Bmat,Cart,G2mth.normQ(Q))
265                Q[iv] += 2.*dx
266                XYZ2 = G2mth.RotateRBXYZ(Bmat,Cart,G2mth.normQ(Q))
267                Q[iv] -= dx
268                dXdO = (XYZ2[ia]-XYZ1[ia])/(2.*dx)
269                for ix in [0,1,2]:
270                    dFdvDict[pfx+'RBR'+OIds[iv]+rbsx] += dXdO[ix]*dFdvDict[pfx+atxIds[ix]+str(atNum)]
271            X = G2mth.prodQVQ(Q,Cart[ia])
272            dFdu = np.array([dFdvDict[pfx+Uid+str(AtLookup[atId])] for Uid in atuIds]).T/gvec
273            dFdu = G2lat.U6toUij(dFdu.T)
274            dFdu = np.tensordot(Amat.T,np.tensordot(Amat,dFdu,([1,0])),([0,1]))
275            dFdu = G2lat.UijtoU6(dFdu)
276            atNum = AtLookup[atId]
277            if 'T' in RBObj['ThermalMotion'][0]:
278                for i,name in enumerate(['RBRT11:','RBRT22:','RBRT33:','RBRT12:','RBRT13:','RBRT23:']):
279                    dFdvDict[pfx+name+rbsx] += dFdu[i]
280            if 'L' in RBObj['ThermalMotion'][0]:
281                dFdvDict[pfx+'RBRL11:'+rbsx] += rpd2*(dFdu[1]*X[2]**2+dFdu[2]*X[1]**2-dFdu[5]*X[1]*X[2])
282                dFdvDict[pfx+'RBRL22:'+rbsx] += rpd2*(dFdu[0]*X[2]**2+dFdu[2]*X[0]**2-dFdu[4]*X[0]*X[2])
283                dFdvDict[pfx+'RBRL33:'+rbsx] += rpd2*(dFdu[0]*X[1]**2+dFdu[1]*X[0]**2-dFdu[3]*X[0]*X[1])
284                dFdvDict[pfx+'RBRL12:'+rbsx] += rpd2*(-dFdu[3]*X[2]**2-2.*dFdu[2]*X[0]*X[1]+
285                    dFdu[4]*X[1]*X[2]+dFdu[5]*X[0]*X[2])
286                dFdvDict[pfx+'RBRL13:'+rbsx] += rpd2*(dFdu[4]*X[1]**2-2.*dFdu[1]*X[0]*X[2]+
287                    dFdu[3]*X[1]*X[2]+dFdu[5]*X[0]*X[1])
288                dFdvDict[pfx+'RBRL23:'+rbsx] += rpd2*(dFdu[5]*X[0]**2-2.*dFdu[0]*X[1]*X[2]+
289                    dFdu[3]*X[0]*X[2]+dFdu[4]*X[0]*X[1])
290            if 'S' in RBObj['ThermalMotion'][0]:
291                dFdvDict[pfx+'RBRS12:'+rbsx] += rpd*(dFdu[5]*X[1]-2.*dFdu[1]*X[2])
292                dFdvDict[pfx+'RBRS13:'+rbsx] += rpd*(-dFdu[5]*X[2]+2.*dFdu[2]*X[1])
293                dFdvDict[pfx+'RBRS21:'+rbsx] += rpd*(-dFdu[4]*X[0]+2.*dFdu[0]*X[2])
294                dFdvDict[pfx+'RBRS23:'+rbsx] += rpd*(dFdu[4]*X[2]-2.*dFdu[2]*X[0])
295                dFdvDict[pfx+'RBRS31:'+rbsx] += rpd*(dFdu[3]*X[0]-2.*dFdu[0]*X[1])
296                dFdvDict[pfx+'RBRS32:'+rbsx] += rpd*(-dFdu[3]*X[1]+2.*dFdu[1]*X[0])
297                dFdvDict[pfx+'RBRSAA:'+rbsx] += rpd*(dFdu[4]*X[1]-dFdu[3]*X[2])
298                dFdvDict[pfx+'RBRSBB:'+rbsx] += rpd*(dFdu[5]*X[0]-dFdu[3]*X[2])
299            if 'U' in RBObj['ThermalMotion'][0]:
300                dFdvDict[pfx+'RBRU:'+rbsx] += dFdvDict[pfx+'AUiso:'+str(AtLookup[atId])]
301   
302################################################################################
303##### Penalty & restraint functions
304################################################################################
305
306def penaltyFxn(HistoPhases,calcControls,parmDict,varyList):
307    'Needs a doc string'
308    Histograms,Phases,restraintDict,rigidbodyDict = HistoPhases
309    pNames = []
310    pVals = []
311    pWt = []
312    negWt = {}
313    pWsum = {}
314    for phase in Phases:
315        pId = Phases[phase]['pId']
316        negWt[pId] = Phases[phase]['General']['Pawley neg wt']
317        General = Phases[phase]['General']
318        cx,ct,cs,cia = General['AtomPtrs']
319        textureData = General['SH Texture']
320        SGData = General['SGData']
321        AtLookup = G2mth.FillAtomLookUp(Phases[phase]['Atoms'],cia+8)
322        cell = General['Cell'][1:7]
323        Amat,Bmat = G2lat.cell2AB(cell)
324        if phase not in restraintDict:
325            continue
326        phaseRest = restraintDict[phase]
327        names = [['Bond','Bonds'],['Angle','Angles'],['Plane','Planes'],
328            ['Chiral','Volumes'],['Torsion','Torsions'],['Rama','Ramas'],
329            ['ChemComp','Sites'],['Texture','HKLs'],]
330        for name,rest in names:
331            pWsum[name] = 0.
332            itemRest = phaseRest[name]
333            if itemRest[rest] and itemRest['Use']:
334                wt = itemRest['wtFactor']
335                if name in ['Bond','Angle','Plane','Chiral']:
336                    for i,[indx,ops,obs,esd] in enumerate(itemRest[rest]):
337                        pNames.append(str(pId)+':'+name+':'+str(i))
338                        XYZ = np.array(G2mth.GetAtomCoordsByID(pId,parmDict,AtLookup,indx))
339                        XYZ = G2mth.getSyXYZ(XYZ,ops,SGData)
340                        if name == 'Bond':
341                            calc = G2mth.getRestDist(XYZ,Amat)
342                        elif name == 'Angle':
343                            calc = G2mth.getRestAngle(XYZ,Amat)
344                        elif name == 'Plane':
345                            calc = G2mth.getRestPlane(XYZ,Amat)
346                        elif name == 'Chiral':
347                            calc = G2mth.getRestChiral(XYZ,Amat)
348                        pVals.append(obs-calc)
349                        pWt.append(wt/esd**2)
350                        pWsum[name] += wt*((obs-calc)/esd)**2
351                elif name in ['Torsion','Rama']:
352                    coeffDict = itemRest['Coeff']
353                    for i,[indx,ops,cofName,esd] in enumerate(itemRest[rest]):
354                        pNames.append(str(pId)+':'+name+':'+str(i))
355                        XYZ = np.array(G2mth.GetAtomCoordsByID(pId,parmDict,AtLookup,indx))
356                        XYZ = G2mth.getSyXYZ(XYZ,ops,SGData)
357                        if name == 'Torsion':
358                            tor = G2mth.getRestTorsion(XYZ,Amat)
359                            restr,calc = G2mth.calcTorsionEnergy(tor,coeffDict[cofName])
360                        else:
361                            phi,psi = G2mth.getRestRama(XYZ,Amat)
362                            restr,calc = G2mth.calcRamaEnergy(phi,psi,coeffDict[cofName])                               
363                        pVals.append(restr)
364                        pWt.append(wt/esd**2)
365                        pWsum[name] += wt*(restr/esd)**2
366                elif name == 'ChemComp':
367                    for i,[indx,factors,obs,esd] in enumerate(itemRest[rest]):
368                        pNames.append(str(pId)+':'+name+':'+str(i))
369                        mul = np.array(G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,cs+1))
370                        frac = np.array(G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,cs-1))
371                        calc = np.sum(mul*frac*factors)
372                        pVals.append(obs-calc)
373                        pWt.append(wt/esd**2)                   
374                        pWsum[name] += wt*((obs-calc)/esd)**2
375                elif name == 'Texture':
376                    SHkeys = textureData['SH Coeff'][1].keys()
377                    SHCoef = G2mth.GetSHCoeff(pId,parmDict,SHkeys)
378                    shModels = ['cylindrical','none','shear - 2/m','rolling - mmm']
379                    SamSym = dict(zip(shModels,['0','-1','2/m','mmm']))
380                    for i,[hkl,grid,esd1,ifesd2,esd2] in enumerate(itemRest[rest]):
381                        PH = np.array(hkl)
382                        phi,beta = G2lat.CrsAng(np.array(hkl),cell,SGData)
383                        ODFln = G2lat.Flnh(False,SHCoef,phi,beta,SGData)
384                        R,P,Z = G2mth.getRestPolefig(ODFln,SamSym[textureData['Model']],grid)
385                        Z1 = -ma.masked_greater(Z,0.0)
386                        IndZ1 = np.array(ma.nonzero(Z1))
387                        for ind in IndZ1.T:
388                            pNames.append('%d:%s:%d:%.2f:%.2f'%(pId,name,i,R[ind[0],ind[1]],P[ind[0],ind[1]]))
389                            pVals.append(Z1[ind[0]][ind[1]])
390                            pWt.append(wt/esd1**2)
391                            pWsum[name] += wt*(-Z1[ind[0]][ind[1]]/esd1)**2
392                        if ifesd2:
393                            Z2 = 1.-Z
394                            for ind in np.ndindex(grid,grid):
395                                pNames.append('%d:%s:%d:%.2f:%.2f'%(pId,name+'-unit',i,R[ind[0],ind[1]],P[ind[0],ind[1]]))
396                                pVals.append(Z1[ind[0]][ind[1]])
397                                pWt.append(wt/esd2**2)
398                                pWsum[name] += wt*(Z2/esd2)**2
399       
400    for phase in Phases:
401        name = 'SH-Pref.Ori.'
402        pId = Phases[phase]['pId']
403        General = Phases[phase]['General']
404        SGData = General['SGData']
405        cell = General['Cell'][1:7]
406        pWsum[name] = 0.0
407        for hist in Phases[phase]['Histograms']:
408            if hist in Histograms and 'PWDR' in hist:
409                hId = Histograms[hist]['hId']
410                phfx = '%d:%d:'%(pId,hId)
411                if calcControls[phfx+'poType'] == 'SH':
412                    toler = calcControls[phfx+'SHtoler']
413                    wt = 1./toler**2
414                    HKLs = np.array(calcControls[phfx+'SHhkl'])
415                    SHnames = calcControls[phfx+'SHnames']
416                    SHcof = dict(zip(SHnames,[parmDict[phfx+cof] for cof in SHnames]))
417                    for i,PH in enumerate(HKLs):
418                        phi,beta = G2lat.CrsAng(PH,cell,SGData)
419                        SH3Coef = {}
420                        for item in SHcof:
421                            L,N = eval(item.strip('C'))
422                            SH3Coef['C%d,0,%d'%(L,N)] = SHcof[item]                       
423                        ODFln = G2lat.Flnh(False,SH3Coef,phi,beta,SGData)
424                        X = np.linspace(0,90.0,26)
425                        Y = -ma.masked_greater(G2lat.polfcal(ODFln,'0',X,0.0),0.0)
426                        IndY = ma.nonzero(Y)
427                        for ind in IndY[0]:
428                            pNames.append('%d:%d:%s:%d:%.2f'%(pId,hId,name,i,X[ind]))
429                            pVals.append(Y[ind])
430                            pWt.append(wt)
431                            pWsum[name] += wt*(Y[ind])**2
432    pWsum['PWLref'] = 0.
433    for item in varyList:
434        if 'PWLref' in item and parmDict[item] < 0.:
435            pId = int(item.split(':')[0])
436            if negWt[pId]:
437                pNames.append(item)
438                pVals.append(-parmDict[item])
439                pWt.append(negWt[pId])
440                pWsum['PWLref'] += negWt[pId]*(-parmDict[item])**2
441    pVals = np.array(pVals)
442    pWt = np.array(pWt)         #should this be np.sqrt?
443    return pNames,pVals,pWt,pWsum
444   
445def penaltyDeriv(pNames,pVal,HistoPhases,calcControls,parmDict,varyList):
446    'Needs a doc string'
447    Histograms,Phases,restraintDict,rigidbodyDict = HistoPhases
448    pDerv = np.zeros((len(varyList),len(pVal)))
449    for phase in Phases:
450#        if phase not in restraintDict:
451#            continue
452        pId = Phases[phase]['pId']
453        General = Phases[phase]['General']
454        cx,ct,cs,cia = General['AtomPtrs']
455        SGData = General['SGData']
456        AtLookup = G2mth.FillAtomLookUp(Phases[phase]['Atoms'],cia+8)
457        cell = General['Cell'][1:7]
458        Amat,Bmat = G2lat.cell2AB(cell)
459        textureData = General['SH Texture']
460
461        SHkeys = textureData['SH Coeff'][1].keys()
462        SHCoef = G2mth.GetSHCoeff(pId,parmDict,SHkeys)
463        shModels = ['cylindrical','none','shear - 2/m','rolling - mmm']
464        SamSym = dict(zip(shModels,['0','-1','2/m','mmm']))
465        sam = SamSym[textureData['Model']]
466        phaseRest = restraintDict.get(phase,{})
467        names = {'Bond':'Bonds','Angle':'Angles','Plane':'Planes',
468            'Chiral':'Volumes','Torsion':'Torsions','Rama':'Ramas',
469            'ChemComp':'Sites','Texture':'HKLs'}
470        lasthkl = np.array([0,0,0])
471        for ip,pName in enumerate(pNames):
472            pnames = pName.split(':')
473            if pId == int(pnames[0]):
474                name = pnames[1]
475                if 'PWL' in pName:
476                    pDerv[varyList.index(pName)][ip] += 1.
477                    continue
478                elif 'SH-' in pName:
479                    continue
480                id = int(pnames[2]) 
481                itemRest = phaseRest[name]
482                if name in ['Bond','Angle','Plane','Chiral']:
483                    indx,ops,obs,esd = itemRest[names[name]][id]
484                    dNames = []
485                    for ind in indx:
486                        dNames += [str(pId)+'::dA'+Xname+':'+str(AtLookup[ind]) for Xname in ['x','y','z']]
487                    XYZ = np.array(G2mth.GetAtomCoordsByID(pId,parmDict,AtLookup,indx))
488                    if name == 'Bond':
489                        deriv = G2mth.getRestDeriv(G2mth.getRestDist,XYZ,Amat,ops,SGData)
490                    elif name == 'Angle':
491                        deriv = G2mth.getRestDeriv(G2mth.getRestAngle,XYZ,Amat,ops,SGData)
492                    elif name == 'Plane':
493                        deriv = G2mth.getRestDeriv(G2mth.getRestPlane,XYZ,Amat,ops,SGData)
494                    elif name == 'Chiral':
495                        deriv = G2mth.getRestDeriv(G2mth.getRestChiral,XYZ,Amat,ops,SGData)
496                elif name in ['Torsion','Rama']:
497                    coffDict = itemRest['Coeff']
498                    indx,ops,cofName,esd = itemRest[names[name]][id]
499                    dNames = []
500                    for ind in indx:
501                        dNames += [str(pId)+'::dA'+Xname+':'+str(AtLookup[ind]) for Xname in ['x','y','z']]
502                    XYZ = np.array(G2mth.GetAtomCoordsByID(pId,parmDict,AtLookup,indx))
503                    if name == 'Torsion':
504                        deriv = G2mth.getTorsionDeriv(XYZ,Amat,coffDict[cofName])
505                    else:
506                        deriv = G2mth.getRamaDeriv(XYZ,Amat,coffDict[cofName])
507                elif name == 'ChemComp':
508                    indx,factors,obs,esd = itemRest[names[name]][id]
509                    dNames = []
510                    for ind in indx:
511                        dNames += [str(pId)+'::Afrac:'+str(AtLookup[ind])]
512                        mul = np.array(G2mth.GetAtomItemsById(Atoms,AtLookUp,indx,cs+1))
513                        deriv = mul*factors
514                elif 'Texture' in name:
515                    deriv = []
516                    dNames = []
517                    hkl,grid,esd1,ifesd2,esd2 = itemRest[names[name]][id]
518                    hkl = np.array(hkl)
519                    if np.any(lasthkl-hkl):
520                        PH = np.array(hkl)
521                        phi,beta = G2lat.CrsAng(np.array(hkl),cell,SGData)
522                        ODFln = G2lat.Flnh(False,SHCoef,phi,beta,SGData)
523                        lasthkl = copy.copy(hkl)                       
524                    if 'unit' in name:
525                        pass
526                    else:
527                        gam = float(pnames[3])
528                        psi = float(pnames[4])
529                        for SHname in ODFln:
530                            l,m,n = eval(SHname[1:])
531                            Ksl = G2lat.GetKsl(l,m,sam,psi,gam)[0]
532                            dNames += [str(pId)+'::'+SHname]
533                            deriv.append(-ODFln[SHname][0]*Ksl/SHCoef[SHname])
534                for dName,drv in zip(dNames,deriv):
535                    try:
536                        ind = varyList.index(dName)
537                        pDerv[ind][ip] += drv
538                    except ValueError:
539                        pass
540       
541        lasthkl = np.array([0,0,0])
542        for ip,pName in enumerate(pNames):
543            deriv = []
544            dNames = []
545            pnames = pName.split(':')
546            if 'SH-' in pName and pId == int(pnames[0]):
547                hId = int(pnames[1])
548                phfx = '%d:%d:'%(pId,hId)
549                psi = float(pnames[4])
550                HKLs = calcControls[phfx+'SHhkl']
551                SHnames = calcControls[phfx+'SHnames']
552                SHcof = dict(zip(SHnames,[parmDict[phfx+cof] for cof in SHnames]))
553                hkl = np.array(HKLs[int(pnames[3])])     
554                if np.any(lasthkl-hkl):
555                    PH = np.array(hkl)
556                    phi,beta = G2lat.CrsAng(np.array(hkl),cell,SGData)
557                    SH3Coef = {}
558                    for item in SHcof:
559                        L,N = eval(item.strip('C'))
560                        SH3Coef['C%d,0,%d'%(L,N)] = SHcof[item]                       
561                    ODFln = G2lat.Flnh(False,SH3Coef,phi,beta,SGData)
562                    lasthkl = copy.copy(hkl)                       
563                for SHname in SHnames:
564                    l,n = eval(SHname[1:])
565                    SH3name = 'C%d,0,%d'%(l,n)
566                    Ksl = G2lat.GetKsl(l,0,'0',psi,0.0)[0]
567                    dNames += [phfx+SHname]
568                    deriv.append(ODFln[SH3name][0]*Ksl/SHcof[SHname])
569            for dName,drv in zip(dNames,deriv):
570                try:
571                    ind = varyList.index(dName)
572                    pDerv[ind][ip] += drv
573                except ValueError:
574                    pass
575    return pDerv
576
577################################################################################
578##### Function & derivative calculations
579################################################################################       
580                   
581def GetAtomFXU(pfx,calcControls,parmDict):
582    'Needs a doc string'
583    Natoms = calcControls['Natoms'][pfx]
584    Tdata = Natoms*[' ',]
585    Mdata = np.zeros(Natoms)
586    IAdata = Natoms*[' ',]
587    Fdata = np.zeros(Natoms)
588    FFdata = []
589    BLdata = []
590    Xdata = np.zeros((3,Natoms))
591    dXdata = np.zeros((3,Natoms))
592    Uisodata = np.zeros(Natoms)
593    Uijdata = np.zeros((6,Natoms))
594    keys = {'Atype:':Tdata,'Amul:':Mdata,'Afrac:':Fdata,'AI/A:':IAdata,
595        'dAx:':dXdata[0],'dAy:':dXdata[1],'dAz:':dXdata[2],
596        'Ax:':Xdata[0],'Ay:':Xdata[1],'Az:':Xdata[2],'AUiso:':Uisodata,
597        'AU11:':Uijdata[0],'AU22:':Uijdata[1],'AU33:':Uijdata[2],
598        'AU12:':Uijdata[3],'AU13:':Uijdata[4],'AU23:':Uijdata[5]}
599    for iatm in range(Natoms):
600        for key in keys:
601            parm = pfx+key+str(iatm)
602            if parm in parmDict:
603                keys[key][iatm] = parmDict[parm]
604    Fdata = np.where(Fdata,Fdata,1.e-8)         #avoid divide by zero in derivative calc.
605    return Tdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata
606   
607def GetAtomSSFXU(pfx,calcControls,parmDict):
608    'Needs a doc string'
609    Natoms = calcControls['Natoms'][pfx]
610    maxSSwave = calcControls['maxSSwave'][pfx]
611    Nwave = {'F':maxSSwave['Sfrac'],'X':maxSSwave['Spos'],'Y':maxSSwave['Spos'],'Z':maxSSwave['Spos'],
612        'U':maxSSwave['Sadp'],'M':maxSSwave['Smag'],'T':maxSSwave['Spos']}
613    XSSdata = np.zeros((6,maxSSwave['Spos'],Natoms))
614    FSSdata = np.zeros((2,maxSSwave['Sfrac'],Natoms))
615    USSdata = np.zeros((12,maxSSwave['Sadp'],Natoms))
616    MSSdata = np.zeros((6,maxSSwave['Smag'],Natoms))
617    waveTypes = []
618    keys = {'Fsin:':FSSdata[0],'Fcos:':FSSdata[1],'Fzero:':FSSdata[0],'Fwid:':FSSdata[1],
619        'Tzero:':XSSdata[0],'Xslope:':XSSdata[1],'Yslope:':XSSdata[2],'Zslope:':XSSdata[3],
620        'Xsin:':XSSdata[0],'Ysin:':XSSdata[1],'Zsin:':XSSdata[2],'Xcos:':XSSdata[3],'Ycos:':XSSdata[4],'Zcos:':XSSdata[5],
621        'U11sin:':USSdata[0],'U22sin:':USSdata[1],'U33sin:':USSdata[2],'U12sin:':USSdata[3],'U13sin:':USSdata[4],'U23sin:':USSdata[5],
622        'U11cos:':USSdata[6],'U22cos:':USSdata[7],'U33cos:':USSdata[8],'U12cos:':USSdata[9],'U13cos:':USSdata[10],'U23cos:':USSdata[11],
623        'MXsin:':MSSdata[0],'MYsin:':MSSdata[1],'MZsin:':MSSdata[2],'MXcos:':MSSdata[3],'MYcos:':MSSdata[4],'MZcos:':MSSdata[5]}
624    for iatm in range(Natoms):
625        waveTypes.append(parmDict[pfx+'waveType:'+str(iatm)])
626        for key in keys:
627            for m in range(Nwave[key[0]]):
628                parm = pfx+key+str(iatm)+':%d'%(m)
629                if parm in parmDict:
630                    keys[key][m][iatm] = parmDict[parm]
631    return np.array(waveTypes),FSSdata,XSSdata,USSdata,MSSdata
632   
633def GetSSTauM(SGOps,SSOps,pfx,calcControls,XData):
634   
635    Natoms = calcControls['Natoms'][pfx]
636    maxSSwave = calcControls['maxSSwave'][pfx]
637    Smult = np.zeros((Natoms,len(SGOps)))
638    TauT = np.zeros((Natoms,len(SGOps)))
639    for ix,xyz in enumerate(XData.T):
640        for isym,(sop,ssop) in enumerate(zip(SGOps,SSOps)):
641            sdet,ssdet,dtau,dT,tauT = G2spc.getTauT(0,sop,ssop,xyz)
642            Smult[ix][isym] = sdet
643            TauT[ix][isym] = tauT
644    return Smult,TauT
645   
646def StructureFactor2(refDict,G,hfx,pfx,SGData,calcControls,parmDict):
647    ''' Compute structure factors for all h,k,l for phase
648    puts the result, F^2, in each ref[8] in refList
649    input:
650   
651    :param dict refDict: where
652        'RefList' list where each ref = h,k,l,m,d,...
653        'FF' dict of form factors - filed in below
654    :param np.array G:      reciprocal metric tensor
655    :param str pfx:    phase id string
656    :param dict SGData: space group info. dictionary output from SpcGroup
657    :param dict calcControls:
658    :param dict ParmDict:
659
660    '''       
661    phfx = pfx.split(':')[0]+hfx
662    ast = np.sqrt(np.diag(G))
663    Mast = twopisq*np.multiply.outer(ast,ast)
664    SGMT = np.array([ops[0].T for ops in SGData['SGOps']])
665    SGT = np.array([ops[1] for ops in SGData['SGOps']])
666    FFtables = calcControls['FFtables']
667    BLtables = calcControls['BLtables']
668    Flack = 1.0
669    if not SGData['SGInv'] and 'S' in calcControls[hfx+'histType'] and phfx+'Flack' in parmDict:
670        Flack = 1.-2.*parmDict[phfx+'Flack']
671    TwinLaw = np.array([[[1,0,0],[0,1,0],[0,0,1]],])
672    TwDict = refDict.get('TwDict',{})           
673    if 'S' in calcControls[hfx+'histType']:
674        NTL = calcControls[phfx+'NTL']
675        NM = calcControls[phfx+'TwinNMN']+1
676        TwinLaw = calcControls[phfx+'TwinLaw']
677        TwinFr = np.array([parmDict[phfx+'TwinFr:'+str(i)] for i in range(len(TwinLaw))])
678        TwinInv = list(np.where(calcControls[phfx+'TwinInv'],-1,1))
679    Tdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata = GetAtomFXU(pfx,calcControls,parmDict)
680    FF = np.zeros(len(Tdata))
681    if 'NC' in calcControls[hfx+'histType']:
682        FP,FPP = G2el.BlenResCW(Tdata,BLtables,parmDict[hfx+'Lam'])
683    elif 'X' in calcControls[hfx+'histType']:
684        FP = np.array([FFtables[El][hfx+'FP'] for El in Tdata])
685        FPP = np.array([FFtables[El][hfx+'FPP'] for El in Tdata])
686    Uij = np.array(G2lat.U6toUij(Uijdata))
687    bij = Mast*Uij.T
688    blkSize = 100       #no. of reflections in a block
689    nRef = refDict['RefList'].shape[0]
690    if not len(refDict['FF']):                #no form factors - 1st time thru StructureFactor
691        if 'N' in calcControls[hfx+'histType']:
692            dat = G2el.getBLvalues(BLtables)
693            refDict['FF']['El'] = dat.keys()
694            refDict['FF']['FF'] = np.ones((nRef,len(dat)))*dat.values()           
695        else:       #'X'
696            dat = G2el.getFFvalues(FFtables,0.)
697            refDict['FF']['El'] = dat.keys()
698            refDict['FF']['FF'] = np.ones((nRef,len(dat)))
699            for iref,ref in enumerate(refDict['RefList']):
700                SQ = 1./(2.*ref[4])**2
701                dat = G2el.getFFvalues(FFtables,SQ)
702                refDict['FF']['FF'][iref] *= dat.values()
703#reflection processing begins here - big arrays!
704    iBeg = 0
705    while iBeg < nRef:
706        iFin = min(iBeg+blkSize,nRef)
707        refl = refDict['RefList'][iBeg:iFin]    #array(blkSize,nItems)
708        H = refl.T[:3]                          #array(blkSize,3)
709        H = np.squeeze(np.inner(H.T,TwinLaw))   #maybe array(blkSize,nTwins,3) or (blkSize,3)
710        TwMask = np.any(H,axis=-1)
711        if TwinLaw.shape[0] > 1 and TwDict: #need np.inner(TwinLaw[?],TwDict[iref][i])*TwinInv[i]
712            for ir in range(blkSize):
713                iref = ir+iBeg
714                if iref in TwDict:
715                    for i in TwDict[iref]:
716                        for n in range(NTL):
717                            H[ir][i+n*NM] = np.inner(TwinLaw[n*NM],np.array(TwDict[iref][i])*TwinInv[i+n*NM])
718            TwMask = np.any(H,axis=-1)
719        SQ = 1./(2.*refl.T[4])**2               #array(blkSize)
720        SQfactor = 4.0*SQ*twopisq               #ditto prev.
721        if 'T' in calcControls[hfx+'histType']:
722            if 'P' in calcControls[hfx+'histType']:
723                FP,FPP = G2el.BlenResTOF(Tdata,BLtables,refl.T[14])
724            else:
725                FP,FPP = G2el.BlenResTOF(Tdata,BLtables,refl.T[12])
726            FP = np.repeat(FP.T,len(SGT)*len(TwinLaw),axis=0)
727            FPP = np.repeat(FPP.T,len(SGT)*len(TwinLaw),axis=0)
728        Bab = np.repeat(parmDict[phfx+'BabA']*np.exp(-parmDict[phfx+'BabU']*SQfactor),len(SGT)*len(TwinLaw))
729        Tindx = np.array([refDict['FF']['El'].index(El) for El in Tdata])
730        FF = np.repeat(refDict['FF']['FF'][iBeg:iFin].T[Tindx].T,len(SGT)*len(TwinLaw),axis=0)
731        Uniq = np.inner(H,SGMT)
732        Phi = np.inner(H,SGT)
733        phase = twopi*(np.inner(Uniq,(dXdata+Xdata).T).T+Phi.T).T
734        sinp = np.sin(phase)
735        cosp = np.cos(phase)
736        biso = -SQfactor*Uisodata[:,np.newaxis]
737        Tiso = np.repeat(np.where(biso<1.,np.exp(biso),1.0),len(SGT)*len(TwinLaw),axis=1).T
738        HbH = -np.sum(Uniq.T*np.swapaxes(np.inner(bij,Uniq),2,-1),axis=1)
739        Tuij = np.where(HbH<1.,np.exp(HbH),1.0).T
740        Tcorr = np.reshape(Tiso,Tuij.shape)*Tuij*Mdata*Fdata/len(SGMT)
741        if 'T' in calcControls[hfx+'histType']:
742            fa = np.array([np.reshape(((FF+FP).T-Bab).T,cosp.shape)*cosp*Tcorr,-np.reshape(Flack*FPP,sinp.shape)*sinp*Tcorr])
743            fb = np.array([np.reshape(((FF+FP).T-Bab).T,sinp.shape)*sinp*Tcorr,np.reshape(Flack*FPP,cosp.shape)*cosp*Tcorr])
744        else:
745            fa = np.array([np.reshape(((FF+FP).T-Bab).T,cosp.shape)*cosp*Tcorr,-Flack*FPP*sinp*Tcorr])
746            fb = np.array([np.reshape(((FF+FP).T-Bab).T,sinp.shape)*sinp*Tcorr,Flack*FPP*cosp*Tcorr])
747        fas = np.sum(np.sum(fa,axis=-1),axis=-1)       #real sum over atoms & unique hkl
748        fbs = np.sum(np.sum(fb,axis=-1),axis=-1)  #imag sum over atoms & uniq hkl
749        if SGData['SGInv']: #centrosymmetric; B=0
750            fbs[0] *= 0.
751        if 'P' in calcControls[hfx+'histType']:
752            refl.T[9] = np.sum(fas**2,axis=0)+np.sum(fbs**2,axis=0)
753            refl.T[10] = atan2d(fbs[0],fas[0])  #ignore f' & f"
754        else:
755            if len(TwinLaw) > 1:
756                refl.T[9] = np.sum(fas[:,:,0]**2,axis=0)+np.sum(fbs[:,:,0]**2,axis=0)   #FcT from primary twin element
757                refl.T[7] = np.sum(TwinFr*np.sum(TwMask[np.newaxis,:,:]*fas,axis=0)**2,axis=-1)+   \
758                    np.sum(TwinFr*np.sum(TwMask[np.newaxis,:,:]*fbs,axis=0)**2,axis=-1)                        #Fc sum over twins
759                refl.T[10] = atan2d(fbs[0].T[0],fas[0].T[0])  #ignore f' & f"
760            else:
761                refl.T[9] = np.sum(fas,axis=0)**2+np.sum(fbs,axis=0)**2
762                refl.T[7] = np.copy(refl.T[9])               
763                refl.T[10] = atan2d(fbs[0],fas[0])  #ignore f' & f"
764#        refl.T[10] = atan2d(np.sum(fbs,axis=0),np.sum(fas,axis=0)) #include f' & f"
765        iBeg += blkSize
766   
767def StructureFactorDerv(refDict,G,hfx,pfx,SGData,calcControls,parmDict):
768    'Needs a doc string'
769    phfx = pfx.split(':')[0]+hfx
770    ast = np.sqrt(np.diag(G))
771    Mast = twopisq*np.multiply.outer(ast,ast)
772    SGMT = np.array([ops[0].T for ops in SGData['SGOps']])
773    SGT = np.array([ops[1] for ops in SGData['SGOps']])
774    FFtables = calcControls['FFtables']
775    BLtables = calcControls['BLtables']
776    TwinLaw = np.array([[[1,0,0],[0,1,0],[0,0,1]],])
777    TwDict = refDict.get('TwDict',{})           
778    if 'S' in calcControls[hfx+'histType']:
779        NTL = calcControls[phfx+'NTL']
780        NM = calcControls[phfx+'TwinNMN']+1
781        TwinLaw = calcControls[phfx+'TwinLaw']
782        TwinFr = np.array([parmDict[phfx+'TwinFr:'+str(i)] for i in range(len(TwinLaw))])
783        TwinInv = list(np.where(calcControls[phfx+'TwinInv'],-1,1))
784    nTwin = len(TwinLaw)       
785    nRef = len(refDict['RefList'])
786    Tdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata = GetAtomFXU(pfx,calcControls,parmDict)
787    mSize = len(Mdata)
788    FF = np.zeros(len(Tdata))
789    if 'NC' in calcControls[hfx+'histType']:
790        FP,FPP = G2el.BlenResCW(Tdata,BLtables,parmDict[hfx+'Lam'])
791    elif 'X' in calcControls[hfx+'histType']:
792        FP = np.array([FFtables[El][hfx+'FP'] for El in Tdata])
793        FPP = np.array([FFtables[El][hfx+'FPP'] for El in Tdata])
794    Uij = np.array(G2lat.U6toUij(Uijdata))
795    bij = Mast*Uij.T
796    dFdvDict = {}
797    if nTwin > 1:
798        dFdfr = np.zeros((nRef,nTwin,mSize))
799        dFdx = np.zeros((nRef,nTwin,mSize,3))
800        dFdui = np.zeros((nRef,nTwin,mSize))
801        dFdua = np.zeros((nRef,nTwin,mSize,6))
802        dFdbab = np.zeros((nRef,nTwin,2))
803        dFdfl = np.zeros((nRef,nTwin))
804        dFdtw = np.zeros((nRef,nTwin))
805    else:
806        dFdfr = np.zeros((nRef,mSize))
807        dFdx = np.zeros((nRef,mSize,3))
808        dFdui = np.zeros((nRef,mSize))
809        dFdua = np.zeros((nRef,mSize,6))
810        dFdbab = np.zeros((nRef,2))
811        dFdfl = np.zeros((nRef))
812        dFdtw = np.zeros((nRef))
813    Flack = 1.0
814    if not SGData['SGInv'] and 'S' in calcControls[hfx+'histType'] and phfx+'Flack' in parmDict:
815        Flack = 1.-2.*parmDict[phfx+'Flack']
816    time0 = time.time()
817    nref = len(refDict['RefList'])/100   
818    for iref,refl in enumerate(refDict['RefList']):
819        if 'T' in calcControls[hfx+'histType']:
820            FP,FPP = G2el.BlenResCW(Tdata,BLtables,refl.T[12])
821        H = np.array(refl[:3])
822        H = np.squeeze(np.inner(H.T,TwinLaw))   #maybe array(3,nTwins) or (3)
823        TwMask = np.any(H,axis=-1)
824        if TwinLaw.shape[0] > 1 and TwDict:
825            if iref in TwDict:
826                for i in TwDict[iref]:
827                    for n in range(NTL):
828                        H[i+n*NM] = np.inner(TwinLaw[n*NM],np.array(TwDict[iref][i])*TwinInv[i+n*NM])
829            TwMask = np.any(H,axis=-1)
830        SQ = 1./(2.*refl[4])**2             # or (sin(theta)/lambda)**2
831        SQfactor = 8.0*SQ*np.pi**2
832        dBabdA = np.exp(-parmDict[phfx+'BabU']*SQfactor)
833        Bab = parmDict[phfx+'BabA']*dBabdA
834        Tindx = np.array([refDict['FF']['El'].index(El) for El in Tdata])
835        FF = refDict['FF']['FF'][iref].T[Tindx].T
836        Uniq = np.inner(H,SGMT)             # array(nSGOp,3) or (nTwin,nSGOp,3)
837        Phi = np.inner(H,SGT)
838        phase = twopi*(np.inner(Uniq,(dXdata+Xdata).T).T+Phi.T).T
839        sinp = np.sin(phase)
840        cosp = np.cos(phase)
841        occ = Mdata*Fdata/len(SGT)
842        biso = -SQfactor*Uisodata[:,np.newaxis]
843        Tiso = np.repeat(np.where(biso<1.,np.exp(biso),1.0),len(SGT)*nTwin,axis=1)
844        HbH = -np.sum(Uniq.T*np.swapaxes(np.inner(bij,Uniq),2,-1),axis=1)
845        Hij = np.array([Mast*np.multiply.outer(U,U) for U in np.reshape(Uniq,(-1,3))])
846        Hij = np.squeeze(np.reshape(np.array([G2lat.UijtoU6(Uij) for Uij in Hij]),(nTwin,-1,6)))
847        Tuij = np.where(HbH<1.,np.exp(HbH),1.0)
848        Tcorr = (np.reshape(Tiso,Tuij.shape)*Tuij).T*occ
849        fot = (FF+FP-Bab)*Tcorr
850        fotp = FPP*Tcorr       
851        fa = np.array([((FF+FP).T-Bab).T*cosp*Tcorr,-Flack*FPP*sinp*Tcorr]) # array(2,nTwin,nEqv,nAtoms)
852        fb = np.array([((FF+FP).T-Bab).T*sinp*Tcorr,Flack*FPP*cosp*Tcorr])
853        fas = np.sum(np.sum(fa,axis=-1),axis=-1)      #real sum over atoms & unique hkl array(2,nTwins)
854        fbs = np.sum(np.sum(fb,axis=-1),axis=-1)      #imag sum over atoms & uniq hkl
855        fax = np.array([-fot*sinp,-fotp*cosp])   #positions array(2,ntwi,nEqv,nAtoms)
856        fbx = np.array([fot*cosp,-fotp*sinp])
857        #sum below is over Uniq
858        dfadfr = np.sum(fa/occ,axis=-2)        #array(2,ntwin,nAtom) Fdata != 0 avoids /0. problem
859        dfadba = np.sum(-cosp*Tcorr[:,np.newaxis],axis=1)
860        dfadui = np.sum(-SQfactor*fa,axis=-2)
861        if nTwin > 1:
862            dfadx = np.array([np.sum(twopi*Uniq[it]*np.swapaxes(fax,-2,-1)[:,it,:,:,np.newaxis],axis=-2) for it in range(nTwin)])
863            dfadua = np.array([np.sum(-Hij[it]*np.swapaxes(fa,-2,-1)[:,it,:,:,np.newaxis],axis=-2) for it in range(nTwin)])
864            # array(nTwin,2,nAtom,3) & array(nTwin,2,nAtom,6)
865        else:
866            dfadx = np.sum(twopi*Uniq*np.swapaxes(fax,-2,-1)[:,:,:,np.newaxis],axis=-2)
867            dfadua = np.sum(-Hij*np.swapaxes(fa,-2,-1)[:,:,:,np.newaxis],axis=-2)
868            # array(2,nAtom,3) & array(2,nAtom,6)
869        if not SGData['SGInv']:
870            dfbdfr = np.sum(fb/occ,axis=-2)        #Fdata != 0 avoids /0. problem
871            dfbdba = np.sum(-sinp*Tcorr[:,np.newaxis],axis=1)
872            dfbdui = np.sum(-SQfactor*fb,axis=-2)
873            if len(TwinLaw) > 1:
874                dfbdx = np.array([np.sum(twopi*Uniq[it]*np.swapaxes(fbx,-2,-1)[:,it,:,:,np.newaxis],axis=2) for it in range(nTwin)])           
875                dfbdua = np.array([np.sum(-Hij[it]*np.swapaxes(fb,-2,-1)[:,it,:,:,np.newaxis],axis=2) for it in range(nTwin)])
876            else:
877                dfadfl = np.sum(-FPP*Tcorr*sinp)
878                dfbdfl = np.sum(FPP*Tcorr*cosp)
879                dfbdx = np.sum(twopi*Uniq*np.swapaxes(fbx,-2,-1)[:,:,:,np.newaxis],axis=2)           
880                dfbdua = np.sum(-Hij*np.swapaxes(fb,-2,-1)[:,:,:,np.newaxis],axis=2)
881        else:
882            dfbdfr = np.zeros_like(dfadfr)
883            dfbdx = np.zeros_like(dfadx)
884            dfbdui = np.zeros_like(dfadui)
885            dfbdua = np.zeros_like(dfadua)
886            dfbdba = np.zeros_like(dfadba)
887            dfadfl = 0.0
888            dfbdfl = 0.0
889        #NB: the above have been checked against PA(1:10,1:2) in strfctr.for for Al2O3!   
890        if 'P' in calcControls[hfx+'histType']: #checked perfect for centro & noncentro
891            dFdfr[iref] = 2.*(fas[0]*dfadfr[0]+fas[1]*dfadfr[1])*Mdata/len(Uniq)+   \
892                2.*(fbs[0]*dfbdfr[0]-fbs[1]*dfbdfr[1])*Mdata/len(Uniq)
893            dFdx[iref] = 2.*(fas[0]*dfadx[0]+fas[1]*dfadx[1])+  \
894                2.*(fbs[0]*dfbdx[0]+fbs[1]*dfbdx[1])
895            dFdui[iref] = 2.*(fas[0]*dfadui[0]+fas[1]*dfadui[1])+   \
896                2.*(fbs[0]*dfbdui[0]-fbs[1]*dfbdui[1])
897            dFdua[iref] = 2.*(fas[0]*dfadua[0]+fas[1]*dfadua[1])+   \
898                2.*(fbs[0]*dfbdua[0]+fbs[1]*dfbdua[1])
899        else:
900            SA = fas[0]-fbs[1]
901            SB = fbs[0]+fas[1]
902            if nTwin > 1:
903                dFdfr[iref] = [2.*TwMask[it]*SA[it]*(dfadfr[0][it]+dfbdfr[1][it])*Mdata/len(Uniq[it])+ \
904                    2.*TwMask[it]*SB[it]*(dfbdfr[0][it]+dfadfr[1][it])*Mdata/len(Uniq[it]) for it in range(nTwin)]
905                dFdx[iref] = [2.*TwMask[it]*SA[it]*(dfadx[it][0]+dfbdx[it][1])+2.*TwMask[it]*SB[it]*(dfbdx[it][0]+dfadx[it][1]) for it in range(nTwin)]
906                dFdui[iref] = [2.*TwMask[it]*SA[it]*(dfadui[0][it]+dfbdui[1][it])+2.*TwMask[it]*SB[it]*(dfbdui[0][it]+dfadui[1][it]) for it in range(nTwin)]
907                dFdua[iref] = [2.*TwMask[it]*SA[it]*(dfadua[it][0]+dfbdua[it][1])+2.*TwMask[it]*SB[it]*(dfbdua[it][0]+dfadua[it][1]) for it in range(nTwin)]
908                dFdtw[iref] = np.sum(TwMask*fas,axis=0)**2+np.sum(TwMask*fbs,axis=0)**2
909               
910            else:   #these are good for no twin single crystals
911                dFdfr[iref] = 2.*SA*(dfadfr[0]+dfbdfr[1])*Mdata/len(Uniq)+ \
912                    2.*SB*(dfbdfr[0]+dfadfr[1])*Mdata/len(Uniq) #array(nRef,nAtom)
913                dFdx[iref] = 2.*SA*(dfadx[0]+dfbdx[1])+2.*SB*(dfbdx[0]+dfadx[1])    #array(nRef,nAtom,3)
914                dFdui[iref] = 2.*SA*(dfadui[0]+dfbdui[1])+2.*SB*(dfbdui[0]+dfadui[1])   #array(nRef,nAtom)
915                dFdua[iref] = 2.*SA*(dfadua[0]+dfbdua[1])+2.*SB*(dfbdua[0]+dfadua[1])    #array(nRef,nAtom,6)
916                dFdfl[iref] = -SA*dfadfl-SB*dfbdfl  #array(nRef,)
917                dFdbab[iref] = 2.*fas[0]*np.array([np.sum(dfadba*dBabdA),np.sum(-dfadba*parmDict[phfx+'BabA']*SQfactor*dBabdA)]).T+ \
918                    2.*fbs[0]*np.array([np.sum(dfbdba*dBabdA),np.sum(-dfbdba*parmDict[phfx+'BabA']*SQfactor*dBabdA)]).T
919    print ' derivative time %.4f\r'%(time.time()-time0)
920        #loop over atoms - each dict entry is list of derivatives for all the reflections
921    if nTwin > 1:
922        for i in range(len(Mdata)):     #these all OK?
923            dFdvDict[pfx+'Afrac:'+str(i)] = np.sum(dFdfr.T[i]*TwinFr[:,np.newaxis],axis=0)
924            dFdvDict[pfx+'dAx:'+str(i)] = np.sum(dFdx.T[0][i]*TwinFr[:,np.newaxis],axis=0)
925            dFdvDict[pfx+'dAy:'+str(i)] = np.sum(dFdx.T[1][i]*TwinFr[:,np.newaxis],axis=0)
926            dFdvDict[pfx+'dAz:'+str(i)] = np.sum(dFdx.T[2][i]*TwinFr[:,np.newaxis],axis=0)
927            dFdvDict[pfx+'AUiso:'+str(i)] = np.sum(dFdui.T[i]*TwinFr[:,np.newaxis],axis=0)
928            dFdvDict[pfx+'AU11:'+str(i)] = np.sum(dFdua.T[0][i]*TwinFr[:,np.newaxis],axis=0)
929            dFdvDict[pfx+'AU22:'+str(i)] = np.sum(dFdua.T[1][i]*TwinFr[:,np.newaxis],axis=0)
930            dFdvDict[pfx+'AU33:'+str(i)] = np.sum(dFdua.T[2][i]*TwinFr[:,np.newaxis],axis=0)
931            dFdvDict[pfx+'AU12:'+str(i)] = np.sum(0.5*dFdua.T[3][i]*TwinFr[:,np.newaxis],axis=0)
932            dFdvDict[pfx+'AU13:'+str(i)] = np.sum(0.5*dFdua.T[4][i]*TwinFr[:,np.newaxis],axis=0)
933            dFdvDict[pfx+'AU23:'+str(i)] = np.sum(0.5*dFdua.T[5][i]*TwinFr[:,np.newaxis],axis=0)
934    else:
935        for i in range(len(Mdata)):
936            dFdvDict[pfx+'Afrac:'+str(i)] = dFdfr.T[i]
937            dFdvDict[pfx+'dAx:'+str(i)] = dFdx.T[0][i]
938            dFdvDict[pfx+'dAy:'+str(i)] = dFdx.T[1][i]
939            dFdvDict[pfx+'dAz:'+str(i)] = dFdx.T[2][i]
940            dFdvDict[pfx+'AUiso:'+str(i)] = dFdui.T[i]
941            dFdvDict[pfx+'AU11:'+str(i)] = dFdua.T[0][i]
942            dFdvDict[pfx+'AU22:'+str(i)] = dFdua.T[1][i]
943            dFdvDict[pfx+'AU33:'+str(i)] = dFdua.T[2][i]
944            dFdvDict[pfx+'AU12:'+str(i)] = 0.5*dFdua.T[3][i]
945            dFdvDict[pfx+'AU13:'+str(i)] = 0.5*dFdua.T[4][i]
946            dFdvDict[pfx+'AU23:'+str(i)] = 0.5*dFdua.T[5][i]
947        dFdvDict[phfx+'Flack'] = 4.*dFdfl.T
948    dFdvDict[phfx+'BabA'] = dFdbab.T[0]
949    dFdvDict[phfx+'BabU'] = dFdbab.T[1]
950    if nTwin > 1:
951        for i in range(nTwin):
952            dFdvDict[phfx+'TwinFr:'+str(i)] = dFdtw.T[i]
953    return dFdvDict
954   
955def SStructureFactor2(refDict,im,G,hfx,pfx,SGData,SSGData,calcControls,parmDict):
956    '''
957    Compute super structure factors for all h,k,l,m for phase
958    puts the result, F^2, in each ref[8+im] in refList
959    input:
960   
961    :param dict refDict: where
962        'RefList' list where each ref = h,k,l,m,d,...
963        'FF' dict of form factors - filed in below
964    :param np.array G:      reciprocal metric tensor
965    :param str pfx:    phase id string
966    :param dict SGData: space group info. dictionary output from SpcGroup
967    :param dict calcControls:
968    :param dict ParmDict:
969
970    '''
971    nxs = np.newaxis       
972    phfx = pfx.split(':')[0]+hfx
973    ast = np.sqrt(np.diag(G))
974    Mast = twopisq*np.multiply.outer(ast,ast)   
975#    SGMT = np.array([ops[0].T for ops in SGData['SGOps']])
976    SGInv = SGData['SGInv']
977#    SGT = np.array([ops[1] for ops in SGData['SGOps']])
978    SSGMT = np.array([ops[0].T for ops in SSGData['SSGOps']])
979    SSGT = np.array([ops[1] for ops in SSGData['SSGOps']])
980    FFtables = calcControls['FFtables']
981    BLtables = calcControls['BLtables']
982    Flack = 1.0
983    if not SGData['SGInv'] and 'S' in calcControls[hfx+'histType'] and phfx+'Flack' in parmDict:
984        Flack = 1.-2.*parmDict[phfx+'Flack']
985    TwinLaw = np.array([[[1,0,0],[0,1,0],[0,0,1]],])
986    TwDict = refDict.get('TwDict',{})           
987    if 'S' in calcControls[hfx+'histType']:
988        NTL = calcControls[phfx+'NTL']
989        NM = calcControls[phfx+'TwinNMN']+1
990        TwinLaw = calcControls[phfx+'TwinLaw']
991        TwinFr = np.array([parmDict[phfx+'TwinFr:'+str(i)] for i in range(len(TwinLaw))])
992        TwinInv = list(np.where(calcControls[phfx+'TwinInv'],-1,1))
993    Tdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata = GetAtomFXU(pfx,calcControls,parmDict)
994    waveTypes,FSSdata,XSSdata,USSdata,MSSdata = GetAtomSSFXU(pfx,calcControls,parmDict)
995    modQ = np.array([parmDict[pfx+'mV0'],parmDict[pfx+'mV1'],parmDict[pfx+'mV2']])
996    FF = np.zeros(len(Tdata))
997    if 'NC' in calcControls[hfx+'histType']:
998        FP,FPP = G2el.BlenResCW(Tdata,BLtables,parmDict[hfx+'Lam'])
999    else:
1000        FP = np.array([FFtables[El][hfx+'FP'] for El in Tdata])
1001        FPP = np.array([FFtables[El][hfx+'FPP'] for El in Tdata])
1002    Uij = np.array(G2lat.U6toUij(Uijdata))
1003    bij = Mast*Uij.T
1004    blkSize = 100       #no. of reflections in a block
1005    nRef = refDict['RefList'].shape[0]
1006    if not len(refDict['FF']):
1007        if 'N' in calcControls[hfx+'histType']:
1008            dat = G2el.getBLvalues(BLtables)        #will need wave here for anom. neutron b's
1009            refDict['FF']['El'] = dat.keys()
1010            refDict['FF']['FF'] = np.ones((nRef,len(dat)))*dat.values()           
1011        else:
1012            dat = G2el.getFFvalues(FFtables,0.)       
1013            refDict['FF']['El'] = dat.keys()
1014            refDict['FF']['FF'] = np.ones((nRef,len(dat)))
1015            for iref,ref in enumerate(refDict['RefList']):
1016                SQ = 1./(2.*ref[5])**2
1017                dat = G2el.getFFvalues(FFtables,SQ)
1018                refDict['FF']['FF'][iref] *= dat.values()
1019    time0 = time.time()
1020#reflection processing begins here - big arrays!
1021    iBeg = 0
1022    while iBeg < nRef:
1023        iFin = min(iBeg+blkSize,nRef)
1024        refl = refDict['RefList'][iBeg:iFin]    #array(blkSize,nItems)
1025        H = refl.T[:4]                          #array(blkSize,4)
1026#        H = np.squeeze(np.inner(H.T,TwinLaw))   #maybe array(blkSize,nTwins,4) or (blkSize,4)
1027#        TwMask = np.any(H,axis=-1)
1028#        if TwinLaw.shape[0] > 1 and TwDict: #need np.inner(TwinLaw[?],TwDict[iref][i])*TwinInv[i]
1029#            for ir in range(blkSize):
1030#                iref = ir+iBeg
1031#                if iref in TwDict:
1032#                    for i in TwDict[iref]:
1033#                        for n in range(NTL):
1034#                            H[ir][i+n*NM] = np.inner(TwinLaw[n*NM],np.array(TwDict[iref][i])*TwinInv[i+n*NM])
1035#            TwMask = np.any(H,axis=-1)
1036        SQ = 1./(2.*refl.T[5])**2               #array(blkSize)
1037        SQfactor = 4.0*SQ*twopisq               #ditto prev.
1038        Uniq = np.inner(H.T,SSGMT)
1039        Phi = np.inner(H.T,SSGT)
1040        if SGInv:   #if centro - expand HKL sets
1041            Uniq = np.hstack((Uniq,-Uniq))
1042            Phi = np.hstack((Phi,-Phi))
1043        if 'T' in calcControls[hfx+'histType']:
1044            if 'P' in calcControls[hfx+'histType']:
1045                FP,FPP = G2el.BlenResTOF(Tdata,BLtables,refl.T[14])
1046            else:
1047                FP,FPP = G2el.BlenResTOF(Tdata,BLtables,refl.T[12])
1048            FP = np.repeat(FP.T,Uniq.shape[1]*len(TwinLaw),axis=0)
1049            FPP = np.repeat(FPP.T,Uniq.shape[1]*len(TwinLaw),axis=0)
1050        Bab = np.repeat(parmDict[phfx+'BabA']*np.exp(-parmDict[phfx+'BabU']*SQfactor),Uniq.shape[1]*len(TwinLaw))
1051        Tindx = np.array([refDict['FF']['El'].index(El) for El in Tdata])
1052        FF = np.repeat(refDict['FF']['FF'][iBeg:iFin].T[Tindx].T,Uniq.shape[1]*len(TwinLaw),axis=0)
1053        phase = twopi*(np.inner(Uniq[:,:,:3],(dXdata.T+Xdata.T))+Phi[:,:,nxs])
1054        sinp = np.sin(phase)
1055        cosp = np.cos(phase)
1056        biso = -SQfactor*Uisodata[:,nxs]
1057        Tiso = np.repeat(np.where(biso<1.,np.exp(biso),1.0),Uniq.shape[1]*len(TwinLaw),axis=1).T
1058        HbH = -np.sum(Uniq[:,:,nxs,:3]*np.inner(Uniq[:,:,:3],bij),axis=-1)
1059        Tuij = np.where(HbH<1.,np.exp(HbH),1.0)
1060        Tcorr = np.reshape(Tiso,Tuij.shape)*Tuij*Mdata*Fdata/Uniq.shape[1]
1061        if 'T' in calcControls[hfx+'histType']:
1062            fa = np.array([np.reshape(((FF+FP).T-Bab).T,cosp.shape)*cosp*Tcorr,-np.reshape(Flack*FPP,sinp.shape)*sinp*Tcorr])
1063            fb = np.array([np.reshape(Flack*FPP,cosp.shape)*cosp*Tcorr,np.reshape(((FF+FP).T-Bab).T,sinp.shape)*sinp*Tcorr])
1064        else:
1065            fa = np.array([np.reshape(((FF+FP).T-Bab).T,cosp.shape)*cosp*Tcorr,-Flack*FPP*sinp*Tcorr])
1066            fb = np.array([Flack*FPP*cosp*Tcorr,np.reshape(((FF+FP).T-Bab).T,sinp.shape)*sinp*Tcorr])
1067        GfpuA = G2mth.Modulation(waveTypes,Uniq,FSSdata,XSSdata,USSdata,Mast) #2 x refBlk x sym X atoms
1068        fa *= GfpuA
1069        fb *= GfpuA       
1070#        GSASIIpath.IPyBreak()
1071        fas = np.sum(np.sum(fa,axis=-1),axis=-1)
1072        fbs = np.sum(np.sum(fb,axis=-1),axis=-1)
1073        if 'P' in calcControls[hfx+'histType']:
1074            refl.T[10] = np.sum(fas**2,axis=0)+np.sum(fbs**2,axis=0)
1075            refl.T[11] = atan2d(fbs[0],fas[0])  #ignore f' & f"
1076        else:
1077            if len(TwinLaw) > 1:
1078                refl.T[10] = np.sum(fas[:,:,0]**2,axis=0)+np.sum(fbs[:,:,0]**2,axis=0)   #FcT from primary twin element
1079                refl.T[8] = np.sum(TwinFr*np.sum(TwMask[np.newaxis,:,:]*fas,axis=0)**2,axis=-1)+   \
1080                    np.sum(TwinFr*np.sum(TwMask[np.newaxis,:,:]*fbs,axis=0)**2,axis=-1)                        #Fc sum over twins
1081                refl.T[11] = atan2d(fbs[0].T[0],fas[0].T[0])  #ignore f' & f"
1082            else:
1083                refl.T[10] = np.sum(fas,axis=0)**2+np.sum(fbs,axis=0)**2
1084                refl.T[8] = np.copy(refl.T[10])               
1085                refl.T[11] = atan2d(fbs[0],fas[0])  #ignore f' & f"
1086        iBeg += blkSize
1087    print 'nRef %d time %.4f\r'%(nRef,time.time()-time0)
1088
1089#def SStructureFactor(refDict,im,G,hfx,pfx,SGData,SSGData,calcControls,parmDict):
1090#    '''
1091#    Compute super structure factors for all h,k,l,m for phase
1092#    puts the result, F^2, in each ref[8+im] in refList
1093#    input:
1094#   
1095#    :param dict refDict: where
1096#        'RefList' list where each ref = h,k,l,m,d,...
1097#        'FF' dict of form factors - filed in below
1098#    :param np.array G:      reciprocal metric tensor
1099#    :param str pfx:    phase id string
1100#    :param dict SGData: space group info. dictionary output from SpcGroup
1101#    :param dict calcControls:
1102#    :param dict ParmDict:
1103#
1104#    '''       
1105#    phfx = pfx.split(':')[0]+hfx
1106#    ast = np.sqrt(np.diag(G))
1107#    Mast = twopisq*np.multiply.outer(ast,ast)
1108#   
1109#    SGInv = SGData['SGInv']
1110#    SSGMT = np.array([ops[0].T for ops in SSGData['SSGOps']])
1111#    SSGT = np.array([ops[1] for ops in SSGData['SSGOps']])
1112#    FFtables = calcControls['FFtables']
1113#    BLtables = calcControls['BLtables']
1114#    Tdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata = GetAtomFXU(pfx,calcControls,parmDict)
1115#    waveTypes,FSSdata,XSSdata,USSdata,MSSdata = GetAtomSSFXU(pfx,calcControls,parmDict)
1116#    FF = np.zeros(len(Tdata))
1117#    if 'NC' in calcControls[hfx+'histType']:
1118#        FP,FPP = G2el.BlenResCW(Tdata,BLtables,parmDict[hfx+'Lam'])
1119#    else:
1120#        FP = np.array([FFtables[El][hfx+'FP'] for El in Tdata])
1121#        FPP = np.array([FFtables[El][hfx+'FPP'] for El in Tdata])
1122#    Uij = np.array(G2lat.U6toUij(Uijdata))
1123#    bij = Mast*Uij.T
1124#    if not len(refDict['FF']):
1125#        if 'N' in calcControls[hfx+'histType']:
1126#            dat = G2el.getBLvalues(BLtables)        #will need wave here for anom. neutron b's
1127#        else:
1128#            dat = G2el.getFFvalues(FFtables,0.)       
1129#        refDict['FF']['El'] = dat.keys()
1130#        refDict['FF']['FF'] = np.zeros((len(refDict['RefList']),len(dat)))
1131#    time0 = time.time()
1132#    nref = len(refDict['RefList'])/100   
1133#    for iref,refl in enumerate(refDict['RefList']):
1134#        if 'NT' in calcControls[hfx+'histType']:
1135#            FP,FPP = G2el.BlenResCW(Tdata,BLtables,refl[14+im])
1136#        fbs = np.array([0,0])
1137#        H = refl[:4]
1138#        SQ = 1./(2.*refl[4+im])**2
1139#        SQfactor = 4.0*SQ*twopisq
1140#        Bab = parmDict[phfx+'BabA']*np.exp(-parmDict[phfx+'BabU']*SQfactor)
1141#        if not np.any(refDict['FF']['FF'][iref]):                #no form factors - 1st time thru StructureFactor
1142#            if 'N' in calcControls[hfx+'histType']:
1143#                dat = G2el.getBLvalues(BLtables)
1144#                refDict['FF']['FF'][iref] = dat.values()
1145#            else:       #'X'
1146#                dat = G2el.getFFvalues(FFtables,SQ)
1147#                refDict['FF']['FF'][iref] = dat.values()
1148#        Tindx = np.array([refDict['FF']['El'].index(El) for El in Tdata])
1149#        FF = refDict['FF']['FF'][iref][Tindx]
1150#        SSUniq = np.inner(H,SSGMT)
1151#        SSPhi = np.inner(H,SSGT)
1152#        if SGInv:   #if centro - expand HKL sets
1153#            SSUniq = np.vstack((SSUniq,-SSUniq))
1154#            SSPhi = np.hstack((SSPhi,-SSPhi))
1155#        phase = twopi*(np.inner(SSUniq[:,:3],(dXdata.T+Xdata.T))+SSPhi[:,np.newaxis])
1156#        sinp = np.sin(phase)
1157#        cosp = np.cos(phase)
1158#        biso = -SQfactor*Uisodata
1159#        Tiso = np.where(biso<1.,np.exp(biso),1.0)
1160#        HbH = np.array([-np.inner(h,np.inner(bij,h)) for h in SSUniq[:,:3]])
1161#        Tuij = np.where(HbH<1.,np.exp(HbH),1.0)
1162#        Tcorr = Tiso*Tuij*Mdata*Fdata/len(SSUniq)
1163#        fa = np.array([(FF+FP-Bab)*cosp*Tcorr,-FPP*sinp*Tcorr])     #2 x sym x atoms
1164#        fb = np.array([FPP*cosp*Tcorr,(FF+FP-Bab)*sinp*Tcorr])      #swapped around - better?
1165#        GfpuA = G2mth.Modulation(waveTypes,SSUniq,FSSdata,XSSdata,USSdata,Mast) #2 x sym X atoms
1166#        GSASIIpath.IPyBreak()
1167#        fa *= GfpuA
1168#        fb *= GfpuA       
1169#        fas = np.sum(np.sum(fa,axis=1),axis=1)
1170#        fbs = np.sum(np.sum(fb,axis=1),axis=1)
1171#        fasq = fas**2
1172#        fbsq = fbs**2        #imaginary
1173#        refl[9+im] = np.sum(fasq)+np.sum(fbsq)
1174#        refl[7+im] = np.sum(fasq)+np.sum(fbsq)
1175#        refl[10+im] = atan2d(fbs[0],fas[0])
1176#        if not iref%nref: print 'ref no. %d time %.4f\r'%(iref,time.time()-time0),
1177#    print '\nref no. %d time %.4f\r'%(iref,time.time()-time0)
1178#
1179def SStructureFactorDerv(refDict,im,G,hfx,pfx,SGData,SSGData,calcControls,parmDict):
1180    'Needs a doc string'
1181    phfx = pfx.split(':')[0]+hfx
1182    ast = np.sqrt(np.diag(G))
1183    Mast = twopisq*np.multiply.outer(ast,ast)
1184    SGMT = np.array([ops[0].T for ops in SGData['SGOps']])
1185    SGT = np.array([ops[1] for ops in SGData['SGOps']])
1186    SSGMT = np.array([ops[0].T for ops in SSGData['SSGOps']])
1187    SSGT = np.array([ops[1] for ops in SSGData['SSGOps']])
1188    FFtables = calcControls['FFtables']
1189    BLtables = calcControls['BLtables']
1190    nRef = len(refDict['RefList'])
1191    Tdata,Mdata,Fdata,Xdata,dXdata,IAdata,Uisodata,Uijdata = GetAtomFXU(pfx,calcControls,parmDict)
1192    waveTypes,FSSdata,XSSdata,USSdata,MSSdata = GetAtomSSFXU(pfx,calcControls,parmDict)
1193    SStauM = GetSSTauM(SGData['SGOps'],SSGData['SSGOps'],pfx,calcControls,Xdata)
1194    mSize = len(Mdata)
1195    FF = np.zeros(len(Tdata))
1196    if 'NC' in calcControls[hfx+'histType']:
1197        FP,FPP = G2el.BlenResCW(Tdata,BLtables,parmDict[hfx+'Lam'])
1198    elif 'X' in calcControls[hfx+'histType']:
1199        FP = np.array([FFtables[El][hfx+'FP'] for El in Tdata])
1200        FPP = np.array([FFtables[El][hfx+'FPP'] for El in Tdata])
1201    Uij = np.array(G2lat.U6toUij(Uijdata))
1202    bij = Mast*Uij.T
1203    dFdvDict = {}
1204    dFdfr = np.zeros((nRef,mSize))
1205    dFdx = np.zeros((nRef,mSize,3))
1206    dFdui = np.zeros((nRef,mSize))
1207    dFdua = np.zeros((nRef,mSize,6))
1208    dFdbab = np.zeros((nRef,2))
1209    for iref,refl in enumerate(refDict['RefList']):
1210        if 'T' in calcControls[hfx+'histType']:
1211            FP,FPP = G2el.BlenResCW(Tdata,BLtables,refl.T[12+im])
1212        H = np.array(refl[:4])
1213        SQ = 1./(2.*refl[4+im])**2             # or (sin(theta)/lambda)**2
1214        SQfactor = 8.0*SQ*np.pi**2
1215        dBabdA = np.exp(-parmDict[phfx+'BabU']*SQfactor)
1216        Bab = parmDict[phfx+'BabA']*dBabdA
1217        Tindx = np.array([refDict['FF']['El'].index(El) for El in Tdata])
1218        FF = refDict['FF']['FF'][iref].T[Tindx]
1219        Uniq = np.inner(H[:3],SGMT)
1220        SSUniq = np.inner(H,SSGMT)
1221        Phi = np.inner(H[:3],SGT)
1222        SSPhi = np.inner(H,SSGT)
1223        GfpuA,dGAdk = G2mth.ModulationDerv(waveTypes,SSUniq,FSSdata,XSSdata,USSdata,Mast)
1224        #need ModulationDerv here dGAdXsin, etc 
1225        phase = twopi*(np.inner((dXdata.T+Xdata.T),Uniq)+SSPhi[np.newaxis,:])
1226        sinp = np.sin(phase)
1227        cosp = np.cos(phase)
1228        occ = Mdata*Fdata/len(Uniq)
1229        biso = -SQfactor*Uisodata
1230        Tiso = np.where(biso<1.,np.exp(biso),1.0)
1231        HbH = -np.inner(H[:3],np.inner(bij,H[:3]))
1232        Hij = np.array([Mast*np.multiply.outer(U,U) for U in Uniq])
1233        Hij = np.array([G2lat.UijtoU6(Uij) for Uij in Hij])
1234        Tuij = np.where(HbH<1.,np.exp(HbH),1.0)
1235        Tcorr = Tiso*Tuij
1236        fot = (FF+FP-Bab)*occ*Tcorr
1237        fotp = FPP*occ*Tcorr
1238        fa *= GfpuA
1239        fb *= GfpuA       
1240       
1241        fas = np.sum(np.sum(fa,axis=1),axis=1)
1242        fbs = np.sum(np.sum(fb,axis=1),axis=1)
1243        fax = np.array([-fot[:,np.newaxis]*sinp,-fotp[:,np.newaxis]*sinp])   #positions
1244        fbx = np.array([fot[:,np.newaxis]*cosp,-fot[:,np.newaxis]*cosp])
1245        fax = fax*GfpuA[:,:,np.newaxis]-fbx*GfpuB[:,:,np.newaxis]
1246        fbx = fbx*GfpuA[:,:,np.newaxis]+fax*GfpuB[:,:,np.newaxis]
1247        #sum below is over Uniq
1248        dfadfr = np.sum(fa/occ[:,np.newaxis],axis=2)        #Fdata != 0 ever avoids /0. problem
1249        dfadx = np.sum(twopi*Uniq*fax[:,:,:,np.newaxis],axis=2)
1250        dfadui = np.sum(-SQfactor*fa,axis=2)
1251        dfadua = np.sum(-Hij*fa[:,:,:,np.newaxis],axis=2)
1252        dfadba = np.sum(-cosp*(occ*Tcorr)[:,np.newaxis],axis=1)
1253        #NB: the above have been checked against PA(1:10,1:2) in strfctr.for for al2O3!   
1254        dFdfr[iref] = 2.*(fas[0]*dfadfr[0]+fas[1]*dfadfr[1])*Mdata/len(Uniq)
1255        dFdx[iref] = 2.*(fas[0]*dfadx[0]+fas[1]*dfadx[1])
1256        dFdui[iref] = 2.*(fas[0]*dfadui[0]+fas[1]*dfadui[1])
1257        dFdua[iref] = 2.*(fas[0]*dfadua[0]+fas[1]*dfadua[1])
1258        dFdbab[iref] = 2.*fas[0]*np.array([np.sum(dfadba*dBabdA),np.sum(-dfadba*parmDict[phfx+'BabA']*SQfactor*dBabdA)]).T
1259        #need dFdXsin, etc for modulations...
1260        if not SGData['SGInv']:
1261            dfbdfr = np.sum(fb/occ[:,np.newaxis],axis=2)        #Fdata != 0 ever avoids /0. problem
1262            dfbdx = np.sum(twopi*Uniq*fbx[:,:,:,np.newaxis],axis=2)           
1263            dfbdui = np.sum(-SQfactor*fb,axis=2)
1264            dfbdua = np.sum(-Hij*fb[:,:,:,np.newaxis],axis=2)
1265            dfbdba = np.sum(-sinp*(occ*Tcorr)[:,np.newaxis],axis=1)
1266            dFdfr[iref] += 2.*(fbs[0]*dfbdfr[0]-fbs[1]*dfbdfr[1])*Mdata/len(Uniq)
1267            dFdx[iref] += 2.*(fbs[0]*dfbdx[0]+fbs[1]*dfbdx[1])
1268            dFdui[iref] += 2.*(fbs[0]*dfbdui[0]-fbs[1]*dfbdui[1])
1269            dFdua[iref] += 2.*(fbs[0]*dfbdua[0]+fbs[1]*dfbdua[1])
1270            dFdbab[iref] += 2.*fbs[0]*np.array([np.sum(dfbdba*dBabdA),np.sum(-dfbdba*parmDict[phfx+'BabA']*SQfactor*dBabdA)]).T
1271        #need dFdXsin, etc for modulations...
1272        #loop over atoms - each dict entry is list of derivatives for all the reflections
1273    for i in range(len(Mdata)):     
1274        dFdvDict[pfx+'Afrac:'+str(i)] = dFdfr.T[i]
1275        dFdvDict[pfx+'dAx:'+str(i)] = dFdx.T[0][i]
1276        dFdvDict[pfx+'dAy:'+str(i)] = dFdx.T[1][i]
1277        dFdvDict[pfx+'dAz:'+str(i)] = dFdx.T[2][i]
1278        dFdvDict[pfx+'AUiso:'+str(i)] = dFdui.T[i]
1279        dFdvDict[pfx+'AU11:'+str(i)] = dFdua.T[0][i]
1280        dFdvDict[pfx+'AU22:'+str(i)] = dFdua.T[1][i]
1281        dFdvDict[pfx+'AU33:'+str(i)] = dFdua.T[2][i]
1282        dFdvDict[pfx+'AU12:'+str(i)] = .5*dFdua.T[3][i]
1283        dFdvDict[pfx+'AU13:'+str(i)] = .5*dFdua.T[4][i]
1284        dFdvDict[pfx+'AU23:'+str(i)] = .5*dFdua.T[5][i]
1285        #need dFdvDict[pfx+'Xsin:'+str[i]:str(m)], etc for modulations...
1286    dFdvDict[phfx+'BabA'] = dFdbab.T[0]
1287    dFdvDict[phfx+'BabU'] = dFdbab.T[1]
1288    return dFdvDict
1289   
1290def SCExtinction(ref,im,phfx,hfx,pfx,calcControls,parmDict,varyList):
1291    ''' Single crystal extinction function; returns extinction & derivative
1292    '''
1293    extCor = 1.0
1294    dervDict = {}
1295    dervCor = 1.0
1296    if calcControls[phfx+'EType'] != 'None':
1297        SQ = 1/(4.*ref[4+im]**2)
1298        if 'C' in parmDict[hfx+'Type']:           
1299            cos2T = 1.0-2.*SQ*parmDict[hfx+'Lam']**2           #cos(2theta)
1300        else:   #'T'
1301            cos2T = 1.0-2.*SQ*ref[12+im]**2                       #cos(2theta)           
1302        if 'SXC' in parmDict[hfx+'Type']:
1303            AV = 7.9406e5/parmDict[pfx+'Vol']**2
1304            PL = np.sqrt(1.0-cos2T**2)/parmDict[hfx+'Lam']
1305            P12 = (calcControls[phfx+'Cos2TM']+cos2T**4)/(calcControls[phfx+'Cos2TM']+cos2T**2)
1306            PLZ = AV*P12*ref[9+im]*parmDict[hfx+'Lam']**2
1307        elif 'SNT' in parmDict[hfx+'Type']:
1308            AV = 1.e7/parmDict[pfx+'Vol']**2
1309            PL = SQ
1310            PLZ = AV*ref[9+im]*ref[12+im]**2
1311        elif 'SNC' in parmDict[hfx+'Type']:
1312            AV = 1.e7/parmDict[pfx+'Vol']**2
1313            PL = np.sqrt(1.0-cos2T**2)/parmDict[hfx+'Lam']
1314            PLZ = AV*ref[9+im]*parmDict[hfx+'Lam']**2
1315           
1316        if 'Primary' in calcControls[phfx+'EType']:
1317            PLZ *= 1.5
1318        else:
1319            if 'C' in parmDict[hfx+'Type']:
1320                PLZ *= calcControls[phfx+'Tbar']
1321            else: #'T'
1322                PLZ *= ref[13+im]      #t-bar
1323        if 'Primary' in calcControls[phfx+'EType']:
1324            PLZ *= 1.5
1325            PSIG = parmDict[phfx+'Ep']
1326        elif 'I & II' in calcControls[phfx+'EType']:
1327            PSIG = parmDict[phfx+'Eg']/np.sqrt(1.+(parmDict[phfx+'Es']*PL/parmDict[phfx+'Eg'])**2)
1328        elif 'Type II' in calcControls[phfx+'EType']:
1329            PSIG = parmDict[phfx+'Es']
1330        else:       # 'Secondary Type I'
1331            PSIG = parmDict[phfx+'Eg']/PL
1332           
1333        AG = 0.58+0.48*cos2T+0.24*cos2T**2
1334        AL = 0.025+0.285*cos2T
1335        BG = 0.02-0.025*cos2T
1336        BL = 0.15-0.2*(0.75-cos2T)**2
1337        if cos2T < 0.:
1338            BL = -0.45*cos2T
1339        CG = 2.
1340        CL = 2.
1341        PF = PLZ*PSIG
1342       
1343        if 'Gaussian' in calcControls[phfx+'EApprox']:
1344            PF4 = 1.+CG*PF+AG*PF**2/(1.+BG*PF)
1345            extCor = np.sqrt(PF4)
1346            PF3 = 0.5*(CG+2.*AG*PF/(1.+BG*PF)-AG*PF**2*BG/(1.+BG*PF)**2)/(PF4*extCor)
1347        else:
1348            PF4 = 1.+CL*PF+AL*PF**2/(1.+BL*PF)
1349            extCor = np.sqrt(PF4)
1350            PF3 = 0.5*(CL+2.*AL*PF/(1.+BL*PF)-AL*PF**2*BL/(1.+BL*PF)**2)/(PF4*extCor)
1351
1352        dervCor = (1.+PF)*PF3   #extinction corr for other derivatives
1353        if 'Primary' in calcControls[phfx+'EType'] and phfx+'Ep' in varyList:
1354            dervDict[phfx+'Ep'] = -ref[7+im]*PLZ*PF3
1355        if 'II' in calcControls[phfx+'EType'] and phfx+'Es' in varyList:
1356            dervDict[phfx+'Es'] = -ref[7+im]*PLZ*PF3*(PSIG/parmDict[phfx+'Es'])**3
1357        if 'I' in calcControls[phfx+'EType'] and phfx+'Eg' in varyList:
1358            dervDict[phfx+'Eg'] = -ref[7+im]*PLZ*PF3*(PSIG/parmDict[phfx+'Eg'])**3*PL**2
1359               
1360    return 1./extCor,dervDict,dervCor
1361   
1362def Dict2Values(parmdict, varylist):
1363    '''Use before call to leastsq to setup list of values for the parameters
1364    in parmdict, as selected by key in varylist'''
1365    return [parmdict[key] for key in varylist] 
1366   
1367def Values2Dict(parmdict, varylist, values):
1368    ''' Use after call to leastsq to update the parameter dictionary with
1369    values corresponding to keys in varylist'''
1370    parmdict.update(zip(varylist,values))
1371   
1372def GetNewCellParms(parmDict,varyList):
1373    'Needs a doc string'
1374    newCellDict = {}
1375    Anames = ['A'+str(i) for i in range(6)]
1376    Ddict = dict(zip(['D11','D22','D33','D12','D13','D23'],Anames))
1377    for item in varyList:
1378        keys = item.split(':')
1379        if keys[2] in Ddict:
1380            key = keys[0]+'::'+Ddict[keys[2]]       #key is e.g. '0::A0'
1381            parm = keys[0]+'::'+keys[2]             #parm is e.g. '0::D11'
1382            newCellDict[parm] = [key,parmDict[key]+parmDict[item]]
1383    return newCellDict          # is e.g. {'0::D11':A0-D11}
1384   
1385def ApplyXYZshifts(parmDict,varyList):
1386    '''
1387    takes atom x,y,z shift and applies it to corresponding atom x,y,z value
1388   
1389    :param dict parmDict: parameter dictionary
1390    :param list varyList: list of variables (not used!)
1391    :returns: newAtomDict - dictionary of new atomic coordinate names & values; key is parameter shift name
1392
1393    '''
1394    newAtomDict = {}
1395    for item in parmDict:
1396        if 'dA' in item:
1397            parm = ''.join(item.split('d'))
1398            parmDict[parm] += parmDict[item]
1399            newAtomDict[item] = [parm,parmDict[parm]]
1400    return newAtomDict
1401   
1402def SHTXcal(refl,im,g,pfx,hfx,SGData,calcControls,parmDict):
1403    'Spherical harmonics texture'
1404    IFCoup = 'Bragg' in calcControls[hfx+'instType']
1405    if 'T' in calcControls[hfx+'histType']:
1406        tth = parmDict[hfx+'2-theta']
1407    else:
1408        tth = refl[5+im]
1409    odfCor = 1.0
1410    H = refl[:3]
1411    cell = G2lat.Gmat2cell(g)
1412    Sangls = [parmDict[pfx+'SH omega'],parmDict[pfx+'SH chi'],parmDict[pfx+'SH phi']]
1413    Gangls = [parmDict[hfx+'Phi'],parmDict[hfx+'Chi'],parmDict[hfx+'Omega'],parmDict[hfx+'Azimuth']]
1414    phi,beta = G2lat.CrsAng(H,cell,SGData)
1415    psi,gam,x,x = G2lat.SamAng(tth/2.,Gangls,Sangls,IFCoup) #ignore 2 sets of angle derivs.
1416    SHnames = G2lat.GenSHCoeff(SGData['SGLaue'],parmDict[pfx+'SHmodel'],parmDict[pfx+'SHorder'])
1417    for item in SHnames:
1418        L,M,N = eval(item.strip('C'))
1419        Kcl = G2lat.GetKcl(L,N,SGData['SGLaue'],phi,beta)
1420        Ksl,x,x = G2lat.GetKsl(L,M,parmDict[pfx+'SHmodel'],psi,gam)
1421        Lnorm = G2lat.Lnorm(L)
1422        odfCor += parmDict[pfx+item]*Lnorm*Kcl*Ksl
1423    return odfCor
1424   
1425def SHTXcalDerv(refl,im,g,pfx,hfx,SGData,calcControls,parmDict):
1426    'Spherical harmonics texture derivatives'
1427    if 'T' in calcControls[hfx+'histType']:
1428        tth = parmDict[hfx+'2-theta']
1429    else:
1430        tth = refl[5+im]
1431    IFCoup = 'Bragg' in calcControls[hfx+'instType']
1432    odfCor = 1.0
1433    dFdODF = {}
1434    dFdSA = [0,0,0]
1435    H = refl[:3]
1436    cell = G2lat.Gmat2cell(g)
1437    Sangls = [parmDict[pfx+'SH omega'],parmDict[pfx+'SH chi'],parmDict[pfx+'SH phi']]
1438    Gangls = [parmDict[hfx+'Phi'],parmDict[hfx+'Chi'],parmDict[hfx+'Omega'],parmDict[hfx+'Azimuth']]
1439    phi,beta = G2lat.CrsAng(H,cell,SGData)
1440    psi,gam,dPSdA,dGMdA = G2lat.SamAng(tth/2.,Gangls,Sangls,IFCoup)
1441    SHnames = G2lat.GenSHCoeff(SGData['SGLaue'],parmDict[pfx+'SHmodel'],parmDict[pfx+'SHorder'])
1442    for item in SHnames:
1443        L,M,N = eval(item.strip('C'))
1444        Kcl = G2lat.GetKcl(L,N,SGData['SGLaue'],phi,beta)
1445        Ksl,dKsdp,dKsdg = G2lat.GetKsl(L,M,parmDict[pfx+'SHmodel'],psi,gam)
1446        Lnorm = G2lat.Lnorm(L)
1447        odfCor += parmDict[pfx+item]*Lnorm*Kcl*Ksl
1448        dFdODF[pfx+item] = Lnorm*Kcl*Ksl
1449        for i in range(3):
1450            dFdSA[i] += parmDict[pfx+item]*Lnorm*Kcl*(dKsdp*dPSdA[i]+dKsdg*dGMdA[i])
1451    return odfCor,dFdODF,dFdSA
1452   
1453def SHPOcal(refl,im,g,phfx,hfx,SGData,calcControls,parmDict):
1454    'spherical harmonics preferred orientation (cylindrical symmetry only)'
1455    if 'T' in calcControls[hfx+'histType']:
1456        tth = parmDict[hfx+'2-theta']
1457    else:
1458        tth = refl[5+im]
1459    odfCor = 1.0
1460    H = refl[:3]
1461    cell = G2lat.Gmat2cell(g)
1462    Sangls = [0.,0.,0.]
1463    if 'Bragg' in calcControls[hfx+'instType']:
1464        Gangls = [0.,90.,0.,parmDict[hfx+'Azimuth']]
1465        IFCoup = True
1466    else:
1467        Gangls = [parmDict[hfx+'Phi'],parmDict[hfx+'Chi'],parmDict[hfx+'Omega'],parmDict[hfx+'Azimuth']]
1468        IFCoup = False
1469    phi,beta = G2lat.CrsAng(H,cell,SGData)
1470    psi,gam,x,x = G2lat.SamAng(tth/2.,Gangls,Sangls,IFCoup) #ignore 2 sets of angle derivs.
1471    SHnames = calcControls[phfx+'SHnames']
1472    for item in SHnames:
1473        L,N = eval(item.strip('C'))
1474        Kcl = G2lat.GetKcl(L,N,SGData['SGLaue'],phi,beta)
1475        Ksl,x,x = G2lat.GetKsl(L,0,'0',psi,gam)
1476        Lnorm = G2lat.Lnorm(L)
1477        odfCor += parmDict[phfx+item]*Lnorm*Kcl*Ksl
1478    return np.squeeze(odfCor)
1479   
1480def SHPOcalDerv(refl,im,g,phfx,hfx,SGData,calcControls,parmDict):
1481    'spherical harmonics preferred orientation derivatives (cylindrical symmetry only)'
1482    if 'T' in calcControls[hfx+'histType']:
1483        tth = parmDict[hfx+'2-theta']
1484    else:
1485        tth = refl[5+im]
1486    odfCor = 1.0
1487    dFdODF = {}
1488    H = refl[:3]
1489    cell = G2lat.Gmat2cell(g)
1490    Sangls = [0.,0.,0.]
1491    if 'Bragg' in calcControls[hfx+'instType']:
1492        Gangls = [0.,90.,0.,parmDict[hfx+'Azimuth']]
1493        IFCoup = True
1494    else:
1495        Gangls = [parmDict[hfx+'Phi'],parmDict[hfx+'Chi'],parmDict[hfx+'Omega'],parmDict[hfx+'Azimuth']]
1496        IFCoup = False
1497    phi,beta = G2lat.CrsAng(H,cell,SGData)
1498    psi,gam,x,x = G2lat.SamAng(tth/2.,Gangls,Sangls,IFCoup) #ignore 2 sets of angle derivs.
1499    SHnames = calcControls[phfx+'SHnames']
1500    for item in SHnames:
1501        L,N = eval(item.strip('C'))
1502        Kcl = G2lat.GetKcl(L,N,SGData['SGLaue'],phi,beta)
1503        Ksl,x,x = G2lat.GetKsl(L,0,'0',psi,gam)
1504        Lnorm = G2lat.Lnorm(L)
1505        odfCor += parmDict[phfx+item]*Lnorm*Kcl*Ksl
1506        dFdODF[phfx+item] = Kcl*Ksl*Lnorm
1507    return odfCor,dFdODF
1508   
1509def GetPrefOri(uniq,G,g,phfx,hfx,SGData,calcControls,parmDict):
1510    'March-Dollase preferred orientation correction'
1511    POcorr = 1.0
1512    MD = parmDict[phfx+'MD']
1513    if MD != 1.0:
1514        MDAxis = calcControls[phfx+'MDAxis']
1515        sumMD = 0
1516        for H in uniq:           
1517            cosP,sinP = G2lat.CosSinAngle(H,MDAxis,G)
1518            A = 1.0/np.sqrt((MD*cosP)**2+sinP**2/MD)
1519            sumMD += A**3
1520        POcorr = sumMD/len(uniq)
1521    return POcorr
1522   
1523def GetPrefOriDerv(refl,im,uniq,G,g,phfx,hfx,SGData,calcControls,parmDict):
1524    'Needs a doc string'
1525    POcorr = 1.0
1526    POderv = {}
1527    if calcControls[phfx+'poType'] == 'MD':
1528        MD = parmDict[phfx+'MD']
1529        MDAxis = calcControls[phfx+'MDAxis']
1530        sumMD = 0
1531        sumdMD = 0
1532        for H in uniq:           
1533            cosP,sinP = G2lat.CosSinAngle(H,MDAxis,G)
1534            A = 1.0/np.sqrt((MD*cosP)**2+sinP**2/MD)
1535            sumMD += A**3
1536            sumdMD -= (1.5*A**5)*(2.0*MD*cosP**2-(sinP/MD)**2)
1537        POcorr = sumMD/len(uniq)
1538        POderv[phfx+'MD'] = sumdMD/len(uniq)
1539    else:   #spherical harmonics
1540        if calcControls[phfx+'SHord']:
1541            POcorr,POderv = SHPOcalDerv(refl,im,g,phfx,hfx,SGData,calcControls,parmDict)
1542    return POcorr,POderv
1543   
1544def GetAbsorb(refl,im,hfx,calcControls,parmDict):
1545    'Needs a doc string'
1546    if 'Debye' in calcControls[hfx+'instType']:
1547        if 'T' in calcControls[hfx+'histType']:
1548            return G2pwd.Absorb('Cylinder',parmDict[hfx+'Absorption']*refl[14+im],abs(parmDict[hfx+'2-theta']),0,0)
1549        else:
1550            return G2pwd.Absorb('Cylinder',parmDict[hfx+'Absorption'],refl[5+im],0,0)
1551    else:
1552        return G2pwd.SurfaceRough(parmDict[hfx+'SurfRoughA'],parmDict[hfx+'SurfRoughB'],refl[5+im])
1553   
1554def GetAbsorbDerv(refl,im,hfx,calcControls,parmDict):
1555    'Needs a doc string'
1556    if 'Debye' in calcControls[hfx+'instType']:
1557        if 'T' in calcControls[hfx+'histType']:
1558            return G2pwd.AbsorbDerv('Cylinder',parmDict[hfx+'Absorption']*refl[14+im],abs(parmDict[hfx+'2-theta']),0,0)
1559        else:
1560            return G2pwd.AbsorbDerv('Cylinder',parmDict[hfx+'Absorption'],refl[5+im],0,0)
1561    else:
1562        return np.array(G2pwd.SurfaceRoughDerv(parmDict[hfx+'SurfRoughA'],parmDict[hfx+'SurfRoughB'],refl[5+im]))
1563       
1564def GetPwdrExt(refl,im,pfx,phfx,hfx,calcControls,parmDict):
1565    'Needs a doc string'
1566    coef = np.array([-0.5,0.25,-0.10416667,0.036458333,-0.0109375,2.8497409E-3])
1567    pi2 = np.sqrt(2./np.pi)
1568    if 'T' in calcControls[hfx+'histType']:
1569        sth2 = sind(abs(parmDict[hfx+'2-theta'])/2.)**2
1570        wave = refl[14+im]
1571    else:   #'C'W
1572        sth2 = sind(refl[5+im]/2.)**2
1573        wave = parmDict.get(hfx+'Lam',parmDict.get(hfx+'Lam1',1.0))
1574    c2th = 1.-2.0*sth2
1575    flv2 = refl[9+im]*(wave/parmDict[pfx+'Vol'])**2
1576    if 'X' in calcControls[hfx+'histType']:
1577        flv2 *= 0.079411*(1.0+c2th**2)/2.0
1578    xfac = flv2*parmDict[phfx+'Extinction']
1579    exb = 1.0
1580    if xfac > -1.:
1581        exb = 1./np.sqrt(1.+xfac)
1582    exl = 1.0
1583    if 0 < xfac <= 1.:
1584        xn = np.array([xfac**(i+1) for i in range(6)])
1585        exl += np.sum(xn*coef)
1586    elif xfac > 1.:
1587        xfac2 = 1./np.sqrt(xfac)
1588        exl = pi2*(1.-0.125/xfac)*xfac2
1589    return exb*sth2+exl*(1.-sth2)
1590   
1591def GetPwdrExtDerv(refl,im,pfx,phfx,hfx,calcControls,parmDict):
1592    'Needs a doc string'
1593    coef = np.array([-0.5,0.25,-0.10416667,0.036458333,-0.0109375,2.8497409E-3])
1594    pi2 = np.sqrt(2./np.pi)
1595    if 'T' in calcControls[hfx+'histType']:
1596        sth2 = sind(abs(parmDict[hfx+'2-theta'])/2.)**2
1597        wave = refl[14+im]
1598    else:   #'C'W
1599        sth2 = sind(refl[5+im]/2.)**2
1600        wave = parmDict.get(hfx+'Lam',parmDict.get(hfx+'Lam1',1.0))
1601    c2th = 1.-2.0*sth2
1602    flv2 = refl[9+im]*(wave/parmDict[pfx+'Vol'])**2
1603    if 'X' in calcControls[hfx+'histType']:
1604        flv2 *= 0.079411*(1.0+c2th**2)/2.0
1605    xfac = flv2*parmDict[phfx+'Extinction']
1606    dbde = -500.*flv2
1607    if xfac > -1.:
1608        dbde = -0.5*flv2/np.sqrt(1.+xfac)**3
1609    dlde = 0.
1610    if 0 < xfac <= 1.:
1611        xn = np.array([i*flv2*xfac**i for i in [1,2,3,4,5,6]])
1612        dlde = np.sum(xn*coef)
1613    elif xfac > 1.:
1614        xfac2 = 1./np.sqrt(xfac)
1615        dlde = flv2*pi2*xfac2*(-1./xfac+0.375/xfac**2)
1616       
1617    return dbde*sth2+dlde*(1.-sth2)
1618   
1619def GetIntensityCorr(refl,im,uniq,G,g,pfx,phfx,hfx,SGData,calcControls,parmDict):
1620    'Needs a doc string'    #need powder extinction!
1621    Icorr = parmDict[phfx+'Scale']*parmDict[hfx+'Scale']*refl[3+im]               #scale*multiplicity
1622    if 'X' in parmDict[hfx+'Type']:
1623        Icorr *= G2pwd.Polarization(parmDict[hfx+'Polariz.'],refl[5+im],parmDict[hfx+'Azimuth'])[0]
1624    POcorr = 1.0
1625    if pfx+'SHorder' in parmDict:                 #generalized spherical harmonics texture - takes precidence
1626        POcorr = SHTXcal(refl,im,g,pfx,hfx,SGData,calcControls,parmDict)
1627    elif calcControls[phfx+'poType'] == 'MD':         #March-Dollase
1628        POcorr = GetPrefOri(uniq,G,g,phfx,hfx,SGData,calcControls,parmDict)
1629    elif calcControls[phfx+'SHord']:                #cylindrical spherical harmonics
1630        POcorr = SHPOcal(refl,im,g,phfx,hfx,SGData,calcControls,parmDict)
1631    Icorr *= POcorr
1632    AbsCorr = 1.0
1633    AbsCorr = GetAbsorb(refl,im,hfx,calcControls,parmDict)
1634    Icorr *= AbsCorr
1635    ExtCorr = GetPwdrExt(refl,im,pfx,phfx,hfx,calcControls,parmDict)
1636    Icorr *= ExtCorr
1637    return Icorr,POcorr,AbsCorr,ExtCorr
1638   
1639def GetIntensityDerv(refl,im,wave,uniq,G,g,pfx,phfx,hfx,SGData,calcControls,parmDict):
1640    'Needs a doc string'    #need powder extinction derivs!
1641    dIdsh = 1./parmDict[hfx+'Scale']
1642    dIdsp = 1./parmDict[phfx+'Scale']
1643    if 'X' in parmDict[hfx+'Type']:
1644        pola,dIdPola = G2pwd.Polarization(parmDict[hfx+'Polariz.'],refl[5+im],parmDict[hfx+'Azimuth'])
1645        dIdPola /= pola
1646    else:       #'N'
1647        dIdPola = 0.0
1648    dFdODF = {}
1649    dFdSA = [0,0,0]
1650    dIdPO = {}
1651    if pfx+'SHorder' in parmDict:
1652        odfCor,dFdODF,dFdSA = SHTXcalDerv(refl,im,g,pfx,hfx,SGData,calcControls,parmDict)
1653        for iSH in dFdODF:
1654            dFdODF[iSH] /= odfCor
1655        for i in range(3):
1656            dFdSA[i] /= odfCor
1657    elif calcControls[phfx+'poType'] == 'MD' or calcControls[phfx+'SHord']:
1658        POcorr,dIdPO = GetPrefOriDerv(refl,im,uniq,G,g,phfx,hfx,SGData,calcControls,parmDict)       
1659        for iPO in dIdPO:
1660            dIdPO[iPO] /= POcorr
1661    if 'T' in parmDict[hfx+'Type']:
1662        dFdAb = GetAbsorbDerv(refl,im,hfx,calcControls,parmDict)*wave/refl[16+im] #wave/abs corr
1663        dFdEx = GetPwdrExtDerv(refl,im,pfx,phfx,hfx,calcControls,parmDict)/refl[17+im]    #/ext corr
1664    else:
1665        dFdAb = GetAbsorbDerv(refl,im,hfx,calcControls,parmDict)*wave/refl[13+im] #wave/abs corr
1666        dFdEx = GetPwdrExtDerv(refl,im,pfx,phfx,hfx,calcControls,parmDict)/refl[14+im]    #/ext corr       
1667    return dIdsh,dIdsp,dIdPola,dIdPO,dFdODF,dFdSA,dFdAb,dFdEx
1668       
1669def GetSampleSigGam(refl,im,wave,G,GB,SGData,hfx,phfx,calcControls,parmDict):
1670    'Needs a doc string'
1671    if 'C' in calcControls[hfx+'histType']:     #All checked & OK
1672        costh = cosd(refl[5+im]/2.)
1673        #crystallite size
1674        if calcControls[phfx+'SizeType'] == 'isotropic':
1675            Sgam = 1.8*wave/(np.pi*parmDict[phfx+'Size;i']*costh)
1676        elif calcControls[phfx+'SizeType'] == 'uniaxial':
1677            H = np.array(refl[:3])
1678            P = np.array(calcControls[phfx+'SizeAxis'])
1679            cosP,sinP = G2lat.CosSinAngle(H,P,G)
1680            Sgam = (1.8*wave/np.pi)/(parmDict[phfx+'Size;i']*parmDict[phfx+'Size;a']*costh)
1681            Sgam *= np.sqrt((sinP*parmDict[phfx+'Size;a'])**2+(cosP*parmDict[phfx+'Size;i'])**2)
1682        else:           #ellipsoidal crystallites
1683            Sij =[parmDict[phfx+'Size:%d'%(i)] for i in range(6)]
1684            H = np.array(refl[:3])
1685            lenR = G2pwd.ellipseSize(H,Sij,GB)
1686            Sgam = 1.8*wave/(np.pi*costh*lenR)
1687        #microstrain               
1688        if calcControls[phfx+'MustrainType'] == 'isotropic':
1689            Mgam = 0.018*parmDict[phfx+'Mustrain;i']*tand(refl[5+im]/2.)/np.pi
1690        elif calcControls[phfx+'MustrainType'] == 'uniaxial':
1691            H = np.array(refl[:3])
1692            P = np.array(calcControls[phfx+'MustrainAxis'])
1693            cosP,sinP = G2lat.CosSinAngle(H,P,G)
1694            Si = parmDict[phfx+'Mustrain;i']
1695            Sa = parmDict[phfx+'Mustrain;a']
1696            Mgam = 0.018*Si*Sa*tand(refl[5+im]/2.)/(np.pi*np.sqrt((Si*cosP)**2+(Sa*sinP)**2))
1697        else:       #generalized - P.W. Stephens model
1698            Strms = G2spc.MustrainCoeff(refl[:3],SGData)
1699            Sum = 0
1700            for i,strm in enumerate(Strms):
1701                Sum += parmDict[phfx+'Mustrain:'+str(i)]*strm
1702            Mgam = 0.018*refl[4+im]**2*tand(refl[5+im]/2.)*np.sqrt(Sum)/np.pi
1703    elif 'T' in calcControls[hfx+'histType']:       #All checked & OK
1704        #crystallite size
1705        if calcControls[phfx+'SizeType'] == 'isotropic':    #OK
1706            Sgam = 1.e-4*parmDict[hfx+'difC']*refl[4+im]**2/parmDict[phfx+'Size;i']
1707        elif calcControls[phfx+'SizeType'] == 'uniaxial':   #OK
1708            H = np.array(refl[:3])
1709            P = np.array(calcControls[phfx+'SizeAxis'])
1710            cosP,sinP = G2lat.CosSinAngle(H,P,G)
1711            Sgam = 1.e-4*parmDict[hfx+'difC']*refl[4+im]**2/(parmDict[phfx+'Size;i']*parmDict[phfx+'Size;a'])
1712            Sgam *= np.sqrt((sinP*parmDict[phfx+'Size;a'])**2+(cosP*parmDict[phfx+'Size;i'])**2)
1713        else:           #ellipsoidal crystallites   #OK
1714            Sij =[parmDict[phfx+'Size:%d'%(i)] for i in range(6)]
1715            H = np.array(refl[:3])
1716            lenR = G2pwd.ellipseSize(H,Sij,GB)
1717            Sgam = 1.e-4*parmDict[hfx+'difC']*refl[4+im]**2/lenR
1718        #microstrain               
1719        if calcControls[phfx+'MustrainType'] == 'isotropic':    #OK
1720            Mgam = 1.e-6*parmDict[hfx+'difC']*refl[4+im]*parmDict[phfx+'Mustrain;i']
1721        elif calcControls[phfx+'MustrainType'] == 'uniaxial':   #OK
1722            H = np.array(refl[:3])
1723            P = np.array(calcControls[phfx+'MustrainAxis'])
1724            cosP,sinP = G2lat.CosSinAngle(H,P,G)
1725            Si = parmDict[phfx+'Mustrain;i']
1726            Sa = parmDict[phfx+'Mustrain;a']
1727            Mgam = 1.e-6*parmDict[hfx+'difC']*refl[4+im]*Si*Sa/np.sqrt((Si*cosP)**2+(Sa*sinP)**2)
1728        else:       #generalized - P.W. Stephens model  OK
1729            Strms = G2spc.MustrainCoeff(refl[:3],SGData)
1730            Sum = 0
1731            for i,strm in enumerate(Strms):
1732                Sum += parmDict[phfx+'Mustrain:'+str(i)]*strm
1733            Mgam = 1.e-6*parmDict[hfx+'difC']*np.sqrt(Sum)*refl[4+im]**3
1734           
1735    gam = Sgam*parmDict[phfx+'Size;mx']+Mgam*parmDict[phfx+'Mustrain;mx']
1736    sig = (Sgam*(1.-parmDict[phfx+'Size;mx']))**2+(Mgam*(1.-parmDict[phfx+'Mustrain;mx']))**2
1737    sig /= ateln2
1738    return sig,gam
1739       
1740def GetSampleSigGamDerv(refl,im,wave,G,GB,SGData,hfx,phfx,calcControls,parmDict):
1741    'Needs a doc string'
1742    gamDict = {}
1743    sigDict = {}
1744    if 'C' in calcControls[hfx+'histType']:         #All checked & OK
1745        costh = cosd(refl[5+im]/2.)
1746        tanth = tand(refl[5+im]/2.)
1747        #crystallite size derivatives
1748        if calcControls[phfx+'SizeType'] == 'isotropic':
1749            Sgam = 1.8*wave/(np.pi*parmDict[phfx+'Size;i']*costh)
1750            gamDict[phfx+'Size;i'] = -1.8*wave*parmDict[phfx+'Size;mx']/(np.pi*costh)
1751            sigDict[phfx+'Size;i'] = -3.6*Sgam*wave*(1.-parmDict[phfx+'Size;mx'])**2/(np.pi*costh*ateln2)
1752        elif calcControls[phfx+'SizeType'] == 'uniaxial':
1753            H = np.array(refl[:3])
1754            P = np.array(calcControls[phfx+'SizeAxis'])
1755            cosP,sinP = G2lat.CosSinAngle(H,P,G)
1756            Si = parmDict[phfx+'Size;i']
1757            Sa = parmDict[phfx+'Size;a']
1758            gami = 1.8*wave/(costh*np.pi*Si*Sa)
1759            sqtrm = np.sqrt((sinP*Sa)**2+(cosP*Si)**2)
1760            Sgam = gami*sqtrm
1761            dsi = gami*Si*cosP**2/sqtrm-Sgam/Si
1762            dsa = gami*Sa*sinP**2/sqtrm-Sgam/Sa
1763            gamDict[phfx+'Size;i'] = dsi*parmDict[phfx+'Size;mx']
1764            gamDict[phfx+'Size;a'] = dsa*parmDict[phfx+'Size;mx']
1765            sigDict[phfx+'Size;i'] = 2.*dsi*Sgam*(1.-parmDict[phfx+'Size;mx'])**2/ateln2
1766            sigDict[phfx+'Size;a'] = 2.*dsa*Sgam*(1.-parmDict[phfx+'Size;mx'])**2/ateln2
1767        else:           #ellipsoidal crystallites
1768            const = 1.8*wave/(np.pi*costh)
1769            Sij =[parmDict[phfx+'Size:%d'%(i)] for i in range(6)]
1770            H = np.array(refl[:3])
1771            lenR,dRdS = G2pwd.ellipseSizeDerv(H,Sij,GB)
1772            Sgam = const/lenR
1773            for i,item in enumerate([phfx+'Size:%d'%(j) for j in range(6)]):
1774                gamDict[item] = -(const/lenR**2)*dRdS[i]*parmDict[phfx+'Size;mx']
1775                sigDict[item] = -2.*Sgam*(const/lenR**2)*dRdS[i]*(1.-parmDict[phfx+'Size;mx'])**2/ateln2
1776        gamDict[phfx+'Size;mx'] = Sgam
1777        sigDict[phfx+'Size;mx'] = -2.*Sgam**2*(1.-parmDict[phfx+'Size;mx'])/ateln2
1778               
1779        #microstrain derivatives               
1780        if calcControls[phfx+'MustrainType'] == 'isotropic':
1781            Mgam = 0.018*parmDict[phfx+'Mustrain;i']*tand(refl[5+im]/2.)/np.pi
1782            gamDict[phfx+'Mustrain;i'] =  0.018*tanth*parmDict[phfx+'Mustrain;mx']/np.pi
1783            sigDict[phfx+'Mustrain;i'] =  0.036*Mgam*tanth*(1.-parmDict[phfx+'Mustrain;mx'])**2/(np.pi*ateln2)       
1784        elif calcControls[phfx+'MustrainType'] == 'uniaxial':
1785            H = np.array(refl[:3])
1786            P = np.array(calcControls[phfx+'MustrainAxis'])
1787            cosP,sinP = G2lat.CosSinAngle(H,P,G)
1788            Si = parmDict[phfx+'Mustrain;i']
1789            Sa = parmDict[phfx+'Mustrain;a']
1790            gami = 0.018*Si*Sa*tanth/np.pi
1791            sqtrm = np.sqrt((Si*cosP)**2+(Sa*sinP)**2)
1792            Mgam = gami/sqtrm
1793            dsi = -gami*Si*cosP**2/sqtrm**3
1794            dsa = -gami*Sa*sinP**2/sqtrm**3
1795            gamDict[phfx+'Mustrain;i'] = (Mgam/Si+dsi)*parmDict[phfx+'Mustrain;mx']
1796            gamDict[phfx+'Mustrain;a'] = (Mgam/Sa+dsa)*parmDict[phfx+'Mustrain;mx']
1797            sigDict[phfx+'Mustrain;i'] = 2*(Mgam/Si+dsi)*Mgam*(1.-parmDict[phfx+'Mustrain;mx'])**2/ateln2
1798            sigDict[phfx+'Mustrain;a'] = 2*(Mgam/Sa+dsa)*Mgam*(1.-parmDict[phfx+'Mustrain;mx'])**2/ateln2       
1799        else:       #generalized - P.W. Stephens model
1800            const = 0.018*refl[4+im]**2*tanth/np.pi
1801            Strms = G2spc.MustrainCoeff(refl[:3],SGData)
1802            Sum = 0
1803            for i,strm in enumerate(Strms):
1804                Sum += parmDict[phfx+'Mustrain:'+str(i)]*strm
1805                gamDict[phfx+'Mustrain:'+str(i)] = strm*parmDict[phfx+'Mustrain;mx']/2.
1806                sigDict[phfx+'Mustrain:'+str(i)] = strm*(1.-parmDict[phfx+'Mustrain;mx'])**2
1807            Mgam = const*np.sqrt(Sum)
1808            for i in range(len(Strms)):
1809                gamDict[phfx+'Mustrain:'+str(i)] *= Mgam/Sum
1810                sigDict[phfx+'Mustrain:'+str(i)] *= const**2/ateln2
1811        gamDict[phfx+'Mustrain;mx'] = Mgam
1812        sigDict[phfx+'Mustrain;mx'] = -2.*Mgam**2*(1.-parmDict[phfx+'Mustrain;mx'])/ateln2
1813    else:   #'T'OF - All checked & OK
1814        if calcControls[phfx+'SizeType'] == 'isotropic':    #OK
1815            Sgam = 1.e-4*parmDict[hfx+'difC']*refl[4+im]**2/parmDict[phfx+'Size;i']
1816            gamDict[phfx+'Size;i'] = -Sgam*parmDict[phfx+'Size;mx']/parmDict[phfx+'Size;i']
1817            sigDict[phfx+'Size;i'] = -2.*Sgam**2*(1.-parmDict[phfx+'Size;mx'])**2/(ateln2*parmDict[phfx+'Size;i'])
1818        elif calcControls[phfx+'SizeType'] == 'uniaxial':   #OK
1819            const = 1.e-4*parmDict[hfx+'difC']*refl[4+im]**2
1820            H = np.array(refl[:3])
1821            P = np.array(calcControls[phfx+'SizeAxis'])
1822            cosP,sinP = G2lat.CosSinAngle(H,P,G)
1823            Si = parmDict[phfx+'Size;i']
1824            Sa = parmDict[phfx+'Size;a']
1825            gami = const/(Si*Sa)
1826            sqtrm = np.sqrt((sinP*Sa)**2+(cosP*Si)**2)
1827            Sgam = gami*sqtrm
1828            dsi = gami*Si*cosP**2/sqtrm-Sgam/Si
1829            dsa = gami*Sa*sinP**2/sqtrm-Sgam/Sa
1830            gamDict[phfx+'Size;i'] = dsi*parmDict[phfx+'Size;mx']
1831            gamDict[phfx+'Size;a'] = dsa*parmDict[phfx+'Size;mx']
1832            sigDict[phfx+'Size;i'] = 2.*dsi*Sgam*(1.-parmDict[phfx+'Size;mx'])**2/ateln2
1833            sigDict[phfx+'Size;a'] = 2.*dsa*Sgam*(1.-parmDict[phfx+'Size;mx'])**2/ateln2
1834        else:           #OK  ellipsoidal crystallites
1835            const = 1.e-4*parmDict[hfx+'difC']*refl[4+im]**2
1836            Sij =[parmDict[phfx+'Size:%d'%(i)] for i in range(6)]
1837            H = np.array(refl[:3])
1838            lenR,dRdS = G2pwd.ellipseSizeDerv(H,Sij,GB)
1839            Sgam = const/lenR
1840            for i,item in enumerate([phfx+'Size:%d'%(j) for j in range(6)]):
1841                gamDict[item] = -(const/lenR**2)*dRdS[i]*parmDict[phfx+'Size;mx']
1842                sigDict[item] = -2.*Sgam*(const/lenR**2)*dRdS[i]*(1.-parmDict[phfx+'Size;mx'])**2/ateln2
1843        gamDict[phfx+'Size;mx'] = Sgam  #OK
1844        sigDict[phfx+'Size;mx'] = -2.*Sgam**2*(1.-parmDict[phfx+'Size;mx'])/ateln2  #OK
1845               
1846        #microstrain derivatives               
1847        if calcControls[phfx+'MustrainType'] == 'isotropic':
1848            Mgam = 1.e-6*parmDict[hfx+'difC']*refl[4+im]*parmDict[phfx+'Mustrain;i']
1849            gamDict[phfx+'Mustrain;i'] =  1.e-6*refl[4+im]*parmDict[hfx+'difC']*parmDict[phfx+'Mustrain;mx']   #OK
1850            sigDict[phfx+'Mustrain;i'] =  2.*Mgam**2*(1.-parmDict[phfx+'Mustrain;mx'])**2/(ateln2*parmDict[phfx+'Mustrain;i'])       
1851        elif calcControls[phfx+'MustrainType'] == 'uniaxial':
1852            H = np.array(refl[:3])
1853            P = np.array(calcControls[phfx+'MustrainAxis'])
1854            cosP,sinP = G2lat.CosSinAngle(H,P,G)
1855            Si = parmDict[phfx+'Mustrain;i']
1856            Sa = parmDict[phfx+'Mustrain;a']
1857            gami = 1.e-6*parmDict[hfx+'difC']*refl[4+im]*Si*Sa
1858            sqtrm = np.sqrt((Si*cosP)**2+(Sa*sinP)**2)
1859            Mgam = gami/sqtrm
1860            dsi = -gami*Si*cosP**2/sqtrm**3
1861            dsa = -gami*Sa*sinP**2/sqtrm**3
1862            gamDict[phfx+'Mustrain;i'] = (Mgam/Si+dsi)*parmDict[phfx+'Mustrain;mx']
1863            gamDict[phfx+'Mustrain;a'] = (Mgam/Sa+dsa)*parmDict[phfx+'Mustrain;mx']
1864            sigDict[phfx+'Mustrain;i'] = 2*(Mgam/Si+dsi)*Mgam*(1.-parmDict[phfx+'Mustrain;mx'])**2/ateln2
1865            sigDict[phfx+'Mustrain;a'] = 2*(Mgam/Sa+dsa)*Mgam*(1.-parmDict[phfx+'Mustrain;mx'])**2/ateln2       
1866        else:       #generalized - P.W. Stephens model OK
1867            pwrs = calcControls[phfx+'MuPwrs']
1868            Strms = G2spc.MustrainCoeff(refl[:3],SGData)
1869            const = 1.e-6*parmDict[hfx+'difC']*refl[4+im]**3
1870            Sum = 0
1871            for i,strm in enumerate(Strms):
1872                Sum += parmDict[phfx+'Mustrain:'+str(i)]*strm
1873                gamDict[phfx+'Mustrain:'+str(i)] = strm*parmDict[phfx+'Mustrain;mx']/2.
1874                sigDict[phfx+'Mustrain:'+str(i)] = strm*(1.-parmDict[phfx+'Mustrain;mx'])**2
1875            Mgam = const*np.sqrt(Sum)
1876            for i in range(len(Strms)):
1877                gamDict[phfx+'Mustrain:'+str(i)] *= Mgam/Sum
1878                sigDict[phfx+'Mustrain:'+str(i)] *= const**2/ateln2       
1879        gamDict[phfx+'Mustrain;mx'] = Mgam
1880        sigDict[phfx+'Mustrain;mx'] = -2.*Mgam**2*(1.-parmDict[phfx+'Mustrain;mx'])/ateln2
1881       
1882    return sigDict,gamDict
1883       
1884def GetReflPos(refl,im,wave,A,pfx,hfx,calcControls,parmDict):
1885    'Needs a doc string'
1886    if im:
1887        h,k,l,m = refl[:4]
1888        vec = np.array([parmDict[pfx+'mV0'],parmDict[pfx+'mV1'],parmDict[pfx+'mV2']])
1889        d = 1./np.sqrt(G2lat.calc_rDsqSS(np.array([h,k,l,m]),A,vec))
1890    else:
1891        h,k,l = refl[:3]
1892        d = 1./np.sqrt(G2lat.calc_rDsq(np.array([h,k,l]),A))
1893    refl[4+im] = d
1894    if 'C' in calcControls[hfx+'histType']:
1895        pos = 2.0*asind(wave/(2.0*d))+parmDict[hfx+'Zero']
1896        const = 9.e-2/(np.pi*parmDict[hfx+'Gonio. radius'])                  #shifts in microns
1897        if 'Bragg' in calcControls[hfx+'instType']:
1898            pos -= const*(4.*parmDict[hfx+'Shift']*cosd(pos/2.0)+ \
1899                parmDict[hfx+'Transparency']*sind(pos)*100.0)            #trans(=1/mueff) in cm
1900        else:               #Debye-Scherrer - simple but maybe not right
1901            pos -= const*(parmDict[hfx+'DisplaceX']*cosd(pos)+parmDict[hfx+'DisplaceY']*sind(pos))
1902    elif 'T' in calcControls[hfx+'histType']:
1903        pos = parmDict[hfx+'difC']*d+parmDict[hfx+'difA']*d**2+parmDict[hfx+'difB']/d+parmDict[hfx+'Zero']
1904        #do I need sample position effects - maybe?
1905    return pos
1906
1907def GetReflPosDerv(refl,im,wave,A,pfx,hfx,calcControls,parmDict):
1908    'Needs a doc string'
1909    dpr = 180./np.pi
1910    if im:
1911        h,k,l,m = refl[:4]
1912        vec = np.array([parmDict[pfx+'mV0'],parmDict[pfx+'mV1'],parmDict[pfx+'mV2']])
1913        dstsq = G2lat.calc_rDsqSS(np.array([h,k,l,m]),A,vec)
1914    else:
1915        m = 0
1916        h,k,l = refl[:3]       
1917        dstsq = G2lat.calc_rDsq(np.array([h,k,l]),A)
1918    dst = np.sqrt(dstsq)
1919    dsp = 1./dst
1920    if 'C' in calcControls[hfx+'histType']:
1921        pos = refl[5+im]-parmDict[hfx+'Zero']
1922        const = dpr/np.sqrt(1.0-wave**2*dstsq/4.0)
1923        dpdw = const*dst
1924        dpdA = np.array([h**2,k**2,l**2,h*k,h*l,k*l])*const*wave/(2.0*dst)
1925        dpdZ = 1.0
1926        dpdV = np.array([2.*h*A[0]+k*A[3]+l*A[4],2*k*A[1]+h*A[3]+l*A[5],
1927            2*l*A[2]+h*A[4]+k*A[5]])*m*const*wave/(2.0*dst)
1928        shft = 9.e-2/(np.pi*parmDict[hfx+'Gonio. radius'])                  #shifts in microns
1929        if 'Bragg' in calcControls[hfx+'instType']:
1930            dpdSh = -4.*shft*cosd(pos/2.0)
1931            dpdTr = -shft*sind(pos)*100.0
1932            return dpdA,dpdw,dpdZ,dpdSh,dpdTr,0.,0.,dpdV
1933        else:               #Debye-Scherrer - simple but maybe not right
1934            dpdXd = -shft*cosd(pos)
1935            dpdYd = -shft*sind(pos)
1936            return dpdA,dpdw,dpdZ,0.,0.,dpdXd,dpdYd,dpdV
1937    elif 'T' in calcControls[hfx+'histType']:
1938        dpdA = -np.array([h**2,k**2,l**2,h*k,h*l,k*l])*parmDict[hfx+'difC']*dsp**3/2.
1939        dpdZ = 1.0
1940        dpdDC = dsp
1941        dpdDA = dsp**2
1942        dpdDB = 1./dsp
1943        dpdV = np.array([2.*h*A[0]+k*A[3]+l*A[4],2*k*A[1]+h*A[3]+l*A[5],
1944            2*l*A[2]+h*A[4]+k*A[5]])*m**parmDict[hfx+'difC']*dsp**3/2.
1945        return dpdA,dpdZ,dpdDC,dpdDA,dpdDB,dpdV
1946           
1947def GetHStrainShift(refl,im,SGData,phfx,hfx,calcControls,parmDict):
1948    'Needs a doc string'
1949    laue = SGData['SGLaue']
1950    uniq = SGData['SGUniq']
1951    h,k,l = refl[:3]
1952    if laue in ['m3','m3m']:
1953        Dij = parmDict[phfx+'D11']*(h**2+k**2+l**2)+ \
1954            refl[4+im]**2*parmDict[phfx+'eA']*((h*k)**2+(h*l)**2+(k*l)**2)/(h**2+k**2+l**2)**2
1955    elif laue in ['6/m','6/mmm','3m1','31m','3']:
1956        Dij = parmDict[phfx+'D11']*(h**2+k**2+h*k)+parmDict[phfx+'D33']*l**2
1957    elif laue in ['3R','3mR']:
1958        Dij = parmDict[phfx+'D11']*(h**2+k**2+l**2)+parmDict[phfx+'D12']*(h*k+h*l+k*l)
1959    elif laue in ['4/m','4/mmm']:
1960        Dij = parmDict[phfx+'D11']*(h**2+k**2)+parmDict[phfx+'D33']*l**2
1961    elif laue in ['mmm']:
1962        Dij = parmDict[phfx+'D11']*h**2+parmDict[phfx+'D22']*k**2+parmDict[phfx+'D33']*l**2
1963    elif laue in ['2/m']:
1964        Dij = parmDict[phfx+'D11']*h**2+parmDict[phfx+'D22']*k**2+parmDict[phfx+'D33']*l**2
1965        if uniq == 'a':
1966            Dij += parmDict[phfx+'D23']*k*l
1967        elif uniq == 'b':
1968            Dij += parmDict[phfx+'D13']*h*l
1969        elif uniq == 'c':
1970            Dij += parmDict[phfx+'D12']*h*k
1971    else:
1972        Dij = parmDict[phfx+'D11']*h**2+parmDict[phfx+'D22']*k**2+parmDict[phfx+'D33']*l**2+ \
1973            parmDict[phfx+'D12']*h*k+parmDict[phfx+'D13']*h*l+parmDict[phfx+'D23']*k*l
1974    if 'C' in calcControls[hfx+'histType']:
1975        return -180.*Dij*refl[4+im]**2*tand(refl[5+im]/2.0)/np.pi
1976    else:
1977        return -Dij*parmDict[hfx+'difC']*refl[4+im]**2/2.
1978           
1979def GetHStrainShiftDerv(refl,im,SGData,phfx,hfx,calcControls,parmDict):
1980    'Needs a doc string'
1981    laue = SGData['SGLaue']
1982    uniq = SGData['SGUniq']
1983    h,k,l = refl[:3]
1984    if laue in ['m3','m3m']:
1985        dDijDict = {phfx+'D11':h**2+k**2+l**2,
1986            phfx+'eA':refl[4+im]**2*((h*k)**2+(h*l)**2+(k*l)**2)/(h**2+k**2+l**2)**2}
1987    elif laue in ['6/m','6/mmm','3m1','31m','3']:
1988        dDijDict = {phfx+'D11':h**2+k**2+h*k,phfx+'D33':l**2}
1989    elif laue in ['3R','3mR']:
1990        dDijDict = {phfx+'D11':h**2+k**2+l**2,phfx+'D12':h*k+h*l+k*l}
1991    elif laue in ['4/m','4/mmm']:
1992        dDijDict = {phfx+'D11':h**2+k**2,phfx+'D33':l**2}
1993    elif laue in ['mmm']:
1994        dDijDict = {phfx+'D11':h**2,phfx+'D22':k**2,phfx+'D33':l**2}
1995    elif laue in ['2/m']:
1996        dDijDict = {phfx+'D11':h**2,phfx+'D22':k**2,phfx+'D33':l**2}
1997        if uniq == 'a':
1998            dDijDict[phfx+'D23'] = k*l
1999        elif uniq == 'b':
2000            dDijDict[phfx+'D13'] = h*l
2001        elif uniq == 'c':
2002            dDijDict[phfx+'D12'] = h*k
2003    else:
2004        dDijDict = {phfx+'D11':h**2,phfx+'D22':k**2,phfx+'D33':l**2,
2005            phfx+'D12':h*k,phfx+'D13':h*l,phfx+'D23':k*l}
2006    if 'C' in calcControls[hfx+'histType']:
2007        for item in dDijDict:
2008            dDijDict[item] *= 180.0*refl[4+im]**2*tand(refl[5+im]/2.0)/np.pi
2009    else:
2010        for item in dDijDict:
2011            dDijDict[item] *= -parmDict[hfx+'difC']*refl[4+im]**3/2.
2012    return dDijDict
2013   
2014def GetDij(phfx,SGData,parmDict):
2015    HSvals = [parmDict[phfx+name] for name in G2spc.HStrainNames(SGData)]
2016    return G2spc.HStrainVals(HSvals,SGData)
2017               
2018def GetFobsSq(Histograms,Phases,parmDict,calcControls):
2019    'Needs a doc string'
2020    histoList = Histograms.keys()
2021    histoList.sort()
2022    for histogram in histoList:
2023        if 'PWDR' in histogram[:4]:
2024            Histogram = Histograms[histogram]
2025            hId = Histogram['hId']
2026            hfx = ':%d:'%(hId)
2027            Limits = calcControls[hfx+'Limits']
2028            if 'C' in calcControls[hfx+'histType']:
2029                shl = max(parmDict[hfx+'SH/L'],0.0005)
2030                Ka2 = False
2031                kRatio = 0.0
2032                if hfx+'Lam1' in parmDict.keys():
2033                    Ka2 = True
2034                    lamRatio = 360*(parmDict[hfx+'Lam2']-parmDict[hfx+'Lam1'])/(np.pi*parmDict[hfx+'Lam1'])
2035                    kRatio = parmDict[hfx+'I(L2)/I(L1)']
2036            x,y,w,yc,yb,yd = Histogram['Data']
2037            xB = np.searchsorted(x,Limits[0])
2038            xF = np.searchsorted(x,Limits[1])
2039            ymb = np.array(y-yb)
2040            ymb = np.where(ymb,ymb,1.0)
2041            ycmb = np.array(yc-yb)
2042            ratio = 1./np.where(ycmb,ycmb/ymb,1.e10)         
2043            refLists = Histogram['Reflection Lists']
2044            for phase in refLists:
2045                if phase not in Phases:     #skips deleted or renamed phases silently!
2046                    continue
2047                Phase = Phases[phase]
2048                im = 0
2049                if Phase['General']['Type'] in ['modulated','magnetic']:
2050                    im = 1
2051                pId = Phase['pId']
2052                phfx = '%d:%d:'%(pId,hId)
2053                refDict = refLists[phase]
2054                sumFo = 0.0
2055                sumdF = 0.0
2056                sumFosq = 0.0
2057                sumdFsq = 0.0
2058                sumInt = 0.0
2059                for refl in refDict['RefList']:
2060                    if 'C' in calcControls[hfx+'histType']:
2061                        yp = np.zeros_like(yb)
2062                        Wd,fmin,fmax = G2pwd.getWidthsCW(refl[5+im],refl[6+im],refl[7+im],shl)
2063                        iBeg = max(xB,np.searchsorted(x,refl[5+im]-fmin))
2064                        iFin = max(xB,min(np.searchsorted(x,refl[5+im]+fmax),xF))
2065                        iFin2 = iFin
2066                        if not iBeg+iFin:       #peak below low limit - skip peak
2067                            continue
2068                        elif not iBeg-iFin:     #peak above high limit - done
2069                            break
2070                        elif iBeg < iFin:
2071                            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
2072                            sumInt += refl[11+im]*refl[9+im]
2073                            if Ka2:
2074                                pos2 = refl[5+im]+lamRatio*tand(refl[5+im]/2.0)       # + 360/pi * Dlam/lam * tan(th)
2075                                Wd,fmin,fmax = G2pwd.getWidthsCW(pos2,refl[6+im],refl[7+im],shl)
2076                                iBeg2 = max(xB,np.searchsorted(x,pos2-fmin))
2077                                iFin2 = min(np.searchsorted(x,pos2+fmax),xF)
2078                                if iFin2 > iBeg2: 
2079                                    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
2080                                    sumInt += refl[11+im]*refl[9+im]*kRatio
2081                            refl[8+im] = np.sum(np.where(ratio[iBeg:iFin2]>0.,yp[iBeg:iFin2]*ratio[iBeg:iFin2]/(refl[11+im]*(1.+kRatio)),0.0))
2082                               
2083                    elif 'T' in calcControls[hfx+'histType']:
2084                        yp = np.zeros_like(yb)
2085                        Wd,fmin,fmax = G2pwd.getWidthsTOF(refl[5+im],refl[12+im],refl[13+im],refl[6+im],refl[7+im])
2086                        iBeg = max(xB,np.searchsorted(x,refl[5+im]-fmin))
2087                        iFin = max(xB,min(np.searchsorted(x,refl[5+im]+fmax),xF))
2088                        if iBeg < iFin:
2089                            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
2090                            refl[8+im] = np.sum(np.where(ratio[iBeg:iFin]>0.,yp[iBeg:iFin]*ratio[iBeg:iFin]/refl[11+im],0.0))
2091                            sumInt += refl[11+im]*refl[9+im]
2092                    Fo = np.sqrt(np.abs(refl[8+im]))
2093                    Fc = np.sqrt(np.abs(refl[9]+im))
2094                    sumFo += Fo
2095                    sumFosq += refl[8+im]**2
2096                    sumdF += np.abs(Fo-Fc)
2097                    sumdFsq += (refl[8+im]-refl[9+im])**2
2098                if sumFo:
2099                    Histogram['Residuals'][phfx+'Rf'] = min(100.,(sumdF/sumFo)*100.)
2100                    Histogram['Residuals'][phfx+'Rf^2'] = min(100.,np.sqrt(sumdFsq/sumFosq)*100.)
2101                else:
2102                    Histogram['Residuals'][phfx+'Rf'] = 100.
2103                    Histogram['Residuals'][phfx+'Rf^2'] = 100.
2104                Histogram['Residuals'][phfx+'sumInt'] = sumInt
2105                Histogram['Residuals'][phfx+'Nref'] = len(refDict['RefList'])
2106                Histogram['Residuals']['hId'] = hId
2107        elif 'HKLF' in histogram[:4]:
2108            Histogram = Histograms[histogram]
2109            Histogram['Residuals']['hId'] = Histograms[histogram]['hId']
2110               
2111def getPowderProfile(parmDict,x,varylist,Histogram,Phases,calcControls,pawleyLookup):
2112    'Needs a doc string'
2113   
2114    def GetReflSigGamCW(refl,im,wave,G,GB,phfx,calcControls,parmDict):
2115        U = parmDict[hfx+'U']
2116        V = parmDict[hfx+'V']
2117        W = parmDict[hfx+'W']
2118        X = parmDict[hfx+'X']
2119        Y = parmDict[hfx+'Y']
2120        tanPos = tand(refl[5+im]/2.0)
2121        Ssig,Sgam = GetSampleSigGam(refl,im,wave,G,GB,SGData,hfx,phfx,calcControls,parmDict)
2122        sig = U*tanPos**2+V*tanPos+W+Ssig     #save peak sigma
2123        sig = max(0.001,sig)
2124        gam = X/cosd(refl[5+im]/2.0)+Y*tanPos+Sgam     #save peak gamma
2125        gam = max(0.001,gam)
2126        return sig,gam
2127               
2128    def GetReflSigGamTOF(refl,im,G,GB,phfx,calcControls,parmDict):
2129        sig = parmDict[hfx+'sig-0']+parmDict[hfx+'sig-1']*refl[4+im]**2+   \
2130            parmDict[hfx+'sig-2']*refl[4+im]**4+parmDict[hfx+'sig-q']/refl[4+im]**2
2131        gam = parmDict[hfx+'X']*refl[4+im]+parmDict[hfx+'Y']*refl[4+im]**2
2132        Ssig,Sgam = GetSampleSigGam(refl,im,0.0,G,GB,SGData,hfx,phfx,calcControls,parmDict)
2133        sig += Ssig
2134        gam += Sgam
2135        return sig,gam
2136       
2137    def GetReflAlpBet(refl,im,hfx,parmDict):
2138        alp = parmDict[hfx+'alpha']/refl[4+im]
2139        bet = parmDict[hfx+'beta-0']+parmDict[hfx+'beta-1']/refl[4+im]**4+parmDict[hfx+'beta-q']/refl[4+im]**2
2140        return alp,bet
2141       
2142    hId = Histogram['hId']
2143    hfx = ':%d:'%(hId)
2144    bakType = calcControls[hfx+'bakType']
2145    yb,Histogram['sumBk'] = G2pwd.getBackground(hfx,parmDict,bakType,calcControls[hfx+'histType'],x)
2146    yc = np.zeros_like(yb)
2147    cw = np.diff(x)
2148    cw = np.append(cw,cw[-1])
2149       
2150    if 'C' in calcControls[hfx+'histType']:   
2151        shl = max(parmDict[hfx+'SH/L'],0.002)
2152        Ka2 = False
2153        if hfx+'Lam1' in parmDict.keys():
2154            wave = parmDict[hfx+'Lam1']
2155            Ka2 = True
2156            lamRatio = 360*(parmDict[hfx+'Lam2']-parmDict[hfx+'Lam1'])/(np.pi*parmDict[hfx+'Lam1'])
2157            kRatio = parmDict[hfx+'I(L2)/I(L1)']
2158        else:
2159            wave = parmDict[hfx+'Lam']
2160    for phase in Histogram['Reflection Lists']:
2161        refDict = Histogram['Reflection Lists'][phase]
2162        if phase not in Phases:     #skips deleted or renamed phases silently!
2163            continue
2164        Phase = Phases[phase]
2165        pId = Phase['pId']
2166        pfx = '%d::'%(pId)
2167        phfx = '%d:%d:'%(pId,hId)
2168        hfx = ':%d:'%(hId)
2169        SGData = Phase['General']['SGData']
2170        SGMT = np.array([ops[0].T for ops in SGData['SGOps']])
2171        im = 0
2172        if Phase['General']['Type'] in ['modulated','magnetic']:
2173            SSGData = Phase['General']['SSGData']
2174            SSGMT = np.array([ops[0].T for ops in SSGData['SSGOps']])
2175            im = 1  #offset in SS reflection list
2176            #??
2177        Dij = GetDij(phfx,SGData,parmDict)
2178        A = [parmDict[pfx+'A%d'%(i)]+Dij[i] for i in range(6)]
2179        G,g = G2lat.A2Gmat(A)       #recip & real metric tensors
2180        if np.any(np.diag(G)<0.):
2181            raise G2obj.G2Exception('invalid metric tensor \n cell/Dij refinement not advised')
2182        GA,GB = G2lat.Gmat2AB(G)    #Orthogonalization matricies
2183        Vst = np.sqrt(nl.det(G))    #V*
2184        if not Phase['General'].get('doPawley'):
2185            time0 = time.time()
2186            if im:
2187                SStructureFactor(refDict,im,G,hfx,pfx,SGData,SSGData,calcControls,parmDict)
2188            else:
2189                StructureFactor2(refDict,G,hfx,pfx,SGData,calcControls,parmDict)
2190#            print 'sf calc time: %.3fs'%(time.time()-time0)
2191        time0 = time.time()
2192        badPeak = False
2193        for iref,refl in enumerate(refDict['RefList']):
2194            if 'C' in calcControls[hfx+'histType']:
2195                if im:
2196                    h,k,l,m = refl[:4]
2197                else:
2198                    h,k,l = refl[:3]
2199                Uniq = np.inner(refl[:3],SGMT)
2200                refl[5+im] = GetReflPos(refl,im,wave,A,pfx,hfx,calcControls,parmDict)         #corrected reflection position
2201                Lorenz = 1./(2.*sind(refl[5+im]/2.)**2*cosd(refl[5+im]/2.))           #Lorentz correction
2202                refl[6+im:8+im] = GetReflSigGamCW(refl,im,wave,G,GB,phfx,calcControls,parmDict)    #peak sig & gam
2203                refl[11+im:15+im] = GetIntensityCorr(refl,im,Uniq,G,g,pfx,phfx,hfx,SGData,calcControls,parmDict)
2204                refl[11+im] *= Vst*Lorenz
2205                 
2206                if Phase['General'].get('doPawley'):
2207                    try:
2208                        if im:
2209                            pInd = pfx+'PWLref:%d'%(pawleyLookup[pfx+'%d,%d,%d,%d'%(h,k,l,m)])
2210                        else:
2211                            pInd = pfx+'PWLref:%d'%(pawleyLookup[pfx+'%d,%d,%d'%(h,k,l)])
2212                        refl[9+im] = parmDict[pInd]
2213                    except KeyError:
2214#                        print ' ***Error %d,%d,%d missing from Pawley reflection list ***'%(h,k,l)
2215                        continue
2216                Wd,fmin,fmax = G2pwd.getWidthsCW(refl[5+im],refl[6+im],refl[7+im],shl)
2217                iBeg = np.searchsorted(x,refl[5+im]-fmin)
2218                iFin = np.searchsorted(x,refl[5+im]+fmax)
2219                if not iBeg+iFin:       #peak below low limit - skip peak
2220                    continue
2221                elif not iBeg-iFin:     #peak above high limit - done
2222                    break
2223                elif iBeg > iFin:   #bad peak coeff - skip
2224                    badPeak = True
2225                    continue
2226                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
2227                if Ka2:
2228                    pos2 = refl[5+im]+lamRatio*tand(refl[5+im]/2.0)       # + 360/pi * Dlam/lam * tan(th)
2229                    Wd,fmin,fmax = G2pwd.getWidthsCW(pos2,refl[6+im],refl[7+im],shl)
2230                    iBeg = np.searchsorted(x,pos2-fmin)
2231                    iFin = np.searchsorted(x,pos2+fmax)
2232                    if not iBeg+iFin:       #peak below low limit - skip peak
2233                        continue
2234                    elif not iBeg-iFin:     #peak above high limit - done
2235                        return yc,yb
2236                    elif iBeg > iFin:   #bad peak coeff - skip
2237                        continue
2238                    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
2239            elif 'T' in calcControls[hfx+'histType']:
2240                h,k,l = refl[:3]
2241                Uniq = np.inner(refl[:3],SGMT)
2242                refl[5+im] = GetReflPos(refl,im,0.0,A,pfx,hfx,calcControls,parmDict)         #corrected reflection position
2243                Lorenz = sind(abs(parmDict[hfx+'2-theta'])/2)*refl[4+im]**4                                                #TOF Lorentz correction
2244#                refl[5+im] += GetHStrainShift(refl,im,SGData,phfx,hfx,calcControls,parmDict)               #apply hydrostatic strain shift
2245                refl[6+im:8+im] = GetReflSigGamTOF(refl,im,G,GB,phfx,calcControls,parmDict)    #peak sig & gam
2246                refl[12+im:14+im] = GetReflAlpBet(refl,im,hfx,parmDict)
2247                refl[11+im],refl[15+im],refl[16+im],refl[17+im] = GetIntensityCorr(refl,im,Uniq,G,g,pfx,phfx,hfx,SGData,calcControls,parmDict)
2248                refl[11+im] *= Vst*Lorenz
2249                if Phase['General'].get('doPawley'):
2250                    try:
2251                        if im:
2252                            pInd =pfx+'PWLref:%d'%(pawleyLookup[pfx+'%d,%d,%d,%d'%(h,k,l,m)])
2253                        else:
2254                            pInd =pfx+'PWLref:%d'%(pawleyLookup[pfx+'%d,%d,%d'%(h,k,l)])
2255                        refl[9+im] = parmDict[pInd]
2256                    except KeyError:
2257#                        print ' ***Error %d,%d,%d missing from Pawley reflection list ***'%(h,k,l)
2258                        continue
2259                Wd,fmin,fmax = G2pwd.getWidthsTOF(refl[5+im],refl[12+im],refl[13+im],refl[6+im],refl[7+im])
2260                iBeg = np.searchsorted(x,refl[5+im]-fmin)
2261                iFin = np.searchsorted(x,refl[5+im]+fmax)
2262                if not iBeg+iFin:       #peak below low limit - skip peak
2263                    continue
2264                elif not iBeg-iFin:     #peak above high limit - done
2265                    break
2266                elif iBeg > iFin:   #bad peak coeff - skip
2267                    badPeak = True
2268                    continue
2269                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]
2270#        print 'profile calc time: %.3fs'%(time.time()-time0)
2271    if badPeak:
2272        print 'ouch #4 bad profile coefficients yield negative peak width; some reflections skipped' 
2273    return yc,yb
2274   
2275def getPowderProfileDerv(parmDict,x,varylist,Histogram,Phases,rigidbodyDict,calcControls,pawleyLookup):
2276    'Needs a doc string'
2277   
2278    def cellVaryDerv(pfx,SGData,dpdA): 
2279        if SGData['SGLaue'] in ['-1',]:
2280            return [[pfx+'A0',dpdA[0]],[pfx+'A1',dpdA[1]],[pfx+'A2',dpdA[2]],
2281                [pfx+'A3',dpdA[3]],[pfx+'A4',dpdA[4]],[pfx+'A5',dpdA[5]]]
2282        elif SGData['SGLaue'] in ['2/m',]:
2283            if SGData['SGUniq'] == 'a':
2284                return [[pfx+'A0',dpdA[0]],[pfx+'A1',dpdA[1]],[pfx+'A2',dpdA[2]],[pfx+'A5',dpdA[5]]]
2285            elif SGData['SGUniq'] == 'b':
2286                return [[pfx+'A0',dpdA[0]],[pfx+'A1',dpdA[1]],[pfx+'A2',dpdA[2]],[pfx+'A4',dpdA[4]]]
2287            else:
2288                return [[pfx+'A0',dpdA[0]],[pfx+'A1',dpdA[1]],[pfx+'A2',dpdA[2]],[pfx+'A3',dpdA[3]]]
2289        elif SGData['SGLaue'] in ['mmm',]:
2290            return [[pfx+'A0',dpdA[0]],[pfx+'A1',dpdA[1]],[pfx+'A2',dpdA[2]]]
2291        elif SGData['SGLaue'] in ['4/m','4/mmm']:
2292            return [[pfx+'A0',dpdA[0]],[pfx+'A2',dpdA[2]]]
2293        elif SGData['SGLaue'] in ['6/m','6/mmm','3m1', '31m', '3']:
2294            return [[pfx+'A0',dpdA[0]],[pfx+'A2',dpdA[2]]]
2295        elif SGData['SGLaue'] in ['3R', '3mR']:
2296            return [[pfx+'A0',dpdA[0]+dpdA[1]+dpdA[2]],[pfx+'A3',dpdA[3]+dpdA[4]+dpdA[5]]]                       
2297        elif SGData['SGLaue'] in ['m3m','m3']:
2298            return [[pfx+'A0',dpdA[0]]]
2299           
2300    # create a list of dependent variables and set up a dictionary to hold their derivatives
2301    dependentVars = G2mv.GetDependentVars()
2302    depDerivDict = {}
2303    for j in dependentVars:
2304        depDerivDict[j] = np.zeros(shape=(len(x)))
2305    #print 'dependent vars',dependentVars
2306    lenX = len(x)               
2307    hId = Histogram['hId']
2308    hfx = ':%d:'%(hId)
2309    bakType = calcControls[hfx+'bakType']
2310    dMdv = np.zeros(shape=(len(varylist),len(x)))
2311    dMdb,dMddb,dMdpk = G2pwd.getBackgroundDerv(hfx,parmDict,bakType,calcControls[hfx+'histType'],x)
2312    if hfx+'Back;0' in varylist: # for now assume that Back;x vars to not appear in constraints
2313        bBpos =varylist.index(hfx+'Back;0')
2314        dMdv[bBpos:bBpos+len(dMdb)] = dMdb
2315    names = [hfx+'DebyeA',hfx+'DebyeR',hfx+'DebyeU']
2316    for name in varylist:
2317        if 'Debye' in name:
2318            id = int(name.split(';')[-1])
2319            parm = name[:int(name.rindex(';'))]
2320            ip = names.index(parm)
2321            dMdv[varylist.index(name)] = dMddb[3*id+ip]
2322    names = [hfx+'BkPkpos',hfx+'BkPkint',hfx+'BkPksig',hfx+'BkPkgam']
2323    for name in varylist:
2324        if 'BkPk' in name:
2325            parm,id = name.split(';')
2326            id = int(id)
2327            if parm in names:
2328                ip = names.index(parm)
2329                dMdv[varylist.index(name)] = dMdpk[4*id+ip]
2330    cw = np.diff(x)
2331    cw = np.append(cw,cw[-1])
2332    Ka2 = False #also for TOF!
2333    if 'C' in calcControls[hfx+'histType']:   
2334        shl = max(parmDict[hfx+'SH/L'],0.002)
2335        if hfx+'Lam1' in parmDict.keys():
2336            wave = parmDict[hfx+'Lam1']
2337            Ka2 = True
2338            lamRatio = 360*(parmDict[hfx+'Lam2']-parmDict[hfx+'Lam1'])/(np.pi*parmDict[hfx+'Lam1'])
2339            kRatio = parmDict[hfx+'I(L2)/I(L1)']
2340        else:
2341            wave = parmDict[hfx+'Lam']
2342    for phase in Histogram['Reflection Lists']:
2343        refDict = Histogram['Reflection Lists'][phase]
2344        if phase not in Phases:     #skips deleted or renamed phases silently!
2345            continue
2346        Phase = Phases[phase]
2347        SGData = Phase['General']['SGData']
2348        SGMT = np.array([ops[0].T for ops in SGData['SGOps']])
2349        im = 0
2350        if Phase['General']['Type'] in ['modulated','magnetic']:
2351            SSGData = Phase['General']['SSGData']
2352            SSGMT = np.array([ops[0].T for ops in SSGData['SSGOps']])
2353            im = 1  #offset in SS reflection list
2354            #??
2355        pId = Phase['pId']
2356        pfx = '%d::'%(pId)
2357        phfx = '%d:%d:'%(pId,hId)
2358        Dij = GetDij(phfx,SGData,parmDict)
2359        A = [parmDict[pfx+'A%d'%(i)]+Dij[i] for i in range(6)]
2360        G,g = G2lat.A2Gmat(A)       #recip & real metric tensors
2361        GA,GB = G2lat.Gmat2AB(G)    #Orthogonalization matricies
2362        if not Phase['General'].get('doPawley'):
2363            time0 = time.time()
2364            if im:
2365                dFdvDict = SStructureFactorDerv(refDict,im,G,hfx,pfx,SGData,SSGData,calcControls,parmDict)
2366            else:
2367                dFdvDict = StructureFactorDerv(refDict,G,hfx,pfx,SGData,calcControls,parmDict)
2368#            print 'sf-derv time %.3fs'%(time.time()-time0)
2369            ApplyRBModelDervs(dFdvDict,parmDict,rigidbodyDict,Phase)
2370        time0 = time.time()
2371        for iref,refl in enumerate(refDict['RefList']):
2372            if im:
2373                h,k,l,m = refl[:4]
2374            else:
2375                h,k,l = refl[:3]
2376            Uniq = np.inner(refl[:3],SGMT)
2377            if 'T' in calcControls[hfx+'histType']:
2378                wave = refl[14+im]
2379            dIdsh,dIdsp,dIdpola,dIdPO,dFdODF,dFdSA,dFdAb,dFdEx = GetIntensityDerv(refl,im,wave,Uniq,G,g,pfx,phfx,hfx,SGData,calcControls,parmDict)
2380            if 'C' in calcControls[hfx+'histType']:        #CW powder
2381                Wd,fmin,fmax = G2pwd.getWidthsCW(refl[5+im],refl[6+im],refl[7+im],shl)
2382            else: #'T'OF
2383                Wd,fmin,fmax = G2pwd.getWidthsTOF(refl[5+im],refl[12+im],refl[13+im],refl[6+im],refl[7+im])
2384            iBeg = np.searchsorted(x,refl[5+im]-fmin)
2385            iFin = np.searchsorted(x,refl[5+im]+fmax)
2386            if not iBeg+iFin:       #peak below low limit - skip peak
2387                continue
2388            elif not iBeg-iFin:     #peak above high limit - done
2389                break
2390            pos = refl[5+im]
2391            if 'C' in calcControls[hfx+'histType']:
2392                tanth = tand(pos/2.0)
2393                costh = cosd(pos/2.0)
2394                lenBF = iFin-iBeg
2395                dMdpk = np.zeros(shape=(6,lenBF))
2396                dMdipk = G2pwd.getdFCJVoigt3(refl[5+im],refl[6+im],refl[7+im],shl,ma.getdata(x[iBeg:iFin]))
2397                for i in range(5):
2398                    dMdpk[i] += 100.*cw[iBeg:iFin]*refl[11+im]*refl[9+im]*dMdipk[i]
2399                dervDict = {'int':dMdpk[0],'pos':dMdpk[1],'sig':dMdpk[2],'gam':dMdpk[3],'shl':dMdpk[4],'L1/L2':np.zeros_like(dMdpk[0])}
2400                if Ka2:
2401                    pos2 = refl[5+im]+lamRatio*tanth       # + 360/pi * Dlam/lam * tan(th)
2402                    iBeg2 = np.searchsorted(x,pos2-fmin)
2403                    iFin2 = np.searchsorted(x,pos2+fmax)
2404                    if iBeg2-iFin2:
2405                        lenBF2 = iFin2-iBeg2
2406                        dMdpk2 = np.zeros(shape=(6,lenBF2))
2407                        dMdipk2 = G2pwd.getdFCJVoigt3(pos2,refl[6+im],refl[7+im],shl,ma.getdata(x[iBeg2:iFin2]))
2408                        for i in range(5):
2409                            dMdpk2[i] = 100.*cw[iBeg2:iFin2]*refl[11+im]*refl[9+im]*kRatio*dMdipk2[i]
2410                        dMdpk2[5] = 100.*cw[iBeg2:iFin2]*refl[11+im]*dMdipk2[0]
2411                        dervDict2 = {'int':dMdpk2[0],'pos':dMdpk2[1],'sig':dMdpk2[2],'gam':dMdpk2[3],'shl':dMdpk2[4],'L1/L2':dMdpk2[5]*refl[9]}
2412            else:   #'T'OF
2413                lenBF = iFin-iBeg
2414                if lenBF < 0:   #bad peak coeff
2415                    break
2416                dMdpk = np.zeros(shape=(6,lenBF))
2417                dMdipk = G2pwd.getdEpsVoigt(refl[5+im],refl[12+im],refl[13+im],refl[6+im],refl[7+im],ma.getdata(x[iBeg:iFin]))
2418                for i in range(6):
2419                    dMdpk[i] += refl[11+im]*refl[9+im]*dMdipk[i]      #cw[iBeg:iFin]*
2420                dervDict = {'int':dMdpk[0],'pos':dMdpk[1],'alp':dMdpk[2],'bet':dMdpk[3],'sig':dMdpk[4],'gam':dMdpk[5]}           
2421            if Phase['General'].get('doPawley'):
2422                dMdpw = np.zeros(len(x))
2423                try:
2424                    if im:
2425                        pIdx = pfx+'PWLref:'+str(pawleyLookup[pfx+'%d,%d,%d,%d'%(h,k,l,m)])
2426                    else:
2427                        pIdx = pfx+'PWLref:'+str(pawleyLookup[pfx+'%d,%d,%d'%(h,k,l)])
2428                    idx = varylist.index(pIdx)
2429                    dMdpw[iBeg:iFin] = dervDict['int']/refl[9+im]
2430                    if Ka2: #not for TOF either
2431                        dMdpw[iBeg2:iFin2] += dervDict2['int']/refl[9+im]
2432                    dMdv[idx] = dMdpw
2433                except: # ValueError:
2434                    pass
2435            if 'C' in calcControls[hfx+'histType']:
2436                dpdA,dpdw,dpdZ,dpdSh,dpdTr,dpdX,dpdY,dpdV = GetReflPosDerv(refl,im,wave,A,pfx,hfx,calcControls,parmDict)
2437                names = {hfx+'Scale':[dIdsh,'int'],hfx+'Polariz.':[dIdpola,'int'],phfx+'Scale':[dIdsp,'int'],
2438                    hfx+'U':[tanth**2,'sig'],hfx+'V':[tanth,'sig'],hfx+'W':[1.0,'sig'],
2439                    hfx+'X':[1.0/costh,'gam'],hfx+'Y':[tanth,'gam'],hfx+'SH/L':[1.0,'shl'],
2440                    hfx+'I(L2)/I(L1)':[1.0,'L1/L2'],hfx+'Zero':[dpdZ,'pos'],hfx+'Lam':[dpdw,'pos'],
2441                    hfx+'Shift':[dpdSh,'pos'],hfx+'Transparency':[dpdTr,'pos'],hfx+'DisplaceX':[dpdX,'pos'],
2442                    hfx+'DisplaceY':[dpdY,'pos'],}
2443                if 'Bragg' in calcControls[hfx+'instType']:
2444                    names.update({hfx+'SurfRoughA':[dFdAb[0],'int'],
2445                        hfx+'SurfRoughB':[dFdAb[1],'int'],})
2446                else:
2447                    names.update({hfx+'Absorption':[dFdAb,'int'],})
2448            else:   #'T'OF
2449                dpdA,dpdZ,dpdDC,dpdDA,dpdDB,dpdV = GetReflPosDerv(refl,im,0.0,A,pfx,hfx,calcControls,parmDict)
2450                names = {hfx+'Scale':[dIdsh,'int'],phfx+'Scale':[dIdsp,'int'],
2451                    hfx+'difC':[dpdDC,'pos'],hfx+'difA':[dpdDA,'pos'],hfx+'difB':[dpdDB,'pos'],
2452                    hfx+'Zero':[dpdZ,'pos'],hfx+'X':[refl[4+im],'gam'],hfx+'Y':[refl[4+im]**2,'gam'],
2453                    hfx+'alpha':[1./refl[4+im],'alp'],hfx+'beta-0':[1.0,'bet'],hfx+'beta-1':[1./refl[4+im]**4,'bet'],
2454                    hfx+'beta-q':[1./refl[4+im]**2,'bet'],hfx+'sig-0':[1.0,'sig'],hfx+'sig-1':[refl[4+im]**2,'sig'],
2455                    hfx+'sig-2':[refl[4+im]**4,'sig'],hfx+'sig-q':[1./refl[4+im]**2,'sig'],
2456                    hfx+'Absorption':[dFdAb,'int'],phfx+'Extinction':[dFdEx,'int'],}
2457            for name in names:
2458                item = names[name]
2459                if name in varylist:
2460                    dMdv[varylist.index(name)][iBeg:iFin] += item[0]*dervDict[item[1]]
2461                    if Ka2 and iFin2-iBeg2:
2462                        dMdv[varylist.index(name)][iBeg2:iFin2] += item[0]*dervDict2[item[1]]
2463                elif name in dependentVars:
2464                    depDerivDict[name][iBeg:iFin] += item[0]*dervDict[item[1]]
2465                    if Ka2 and iFin2-iBeg2:
2466                        depDerivDict[name][iBeg2:iFin2] += item[0]*dervDict2[item[1]]
2467            for iPO in dIdPO:
2468                if iPO in varylist:
2469                    dMdv[varylist.index(iPO)][iBeg:iFin] += dIdPO[iPO]*dervDict['int']
2470                    if Ka2 and iFin2-iBeg2:
2471                        dMdv[varylist.index(iPO)][iBeg2:iFin2] += dIdPO[iPO]*dervDict2['int']
2472                elif iPO in dependentVars:
2473                    depDerivDict[iPO][iBeg:iFin] += dIdPO[iPO]*dervDict['int']
2474                    if Ka2 and iFin2-iBeg2:
2475                        depDerivDict[iPO][iBeg2:iFin2] += dIdPO[iPO]*dervDict2['int']
2476            for i,name in enumerate(['omega','chi','phi']):
2477                aname = pfx+'SH '+name
2478                if aname in varylist:
2479                    dMdv[varylist.index(aname)][iBeg:iFin] += dFdSA[i]*dervDict['int']
2480                    if Ka2 and iFin2-iBeg2:
2481                        dMdv[varylist.index(aname)][iBeg2:iFin2] += dFdSA[i]*dervDict2['int']
2482                elif aname in dependentVars:
2483                    depDerivDict[aname][iBeg:iFin] += dFdSA[i]*dervDict['int']
2484                    if Ka2 and iFin2-iBeg2:
2485                        depDerivDict[aname][iBeg2:iFin2] += dFdSA[i]*dervDict2['int']
2486            for iSH in dFdODF:
2487                if iSH in varylist:
2488                    dMdv[varylist.index(iSH)][iBeg:iFin] += dFdODF[iSH]*dervDict['int']
2489                    if Ka2 and iFin2-iBeg2:
2490                        dMdv[varylist.index(iSH)][iBeg2:iFin2] += dFdODF[iSH]*dervDict2['int']
2491                elif iSH in dependentVars:
2492                    depDerivDict[iSH][iBeg:iFin] += dFdODF[iSH]*dervDict['int']
2493                    if Ka2 and iFin2-iBeg2:
2494                        depDerivDict[iSH][iBeg2:iFin2] += dFdODF[iSH]*dervDict2['int']
2495            cellDervNames = cellVaryDerv(pfx,SGData,dpdA)
2496            for name,dpdA in cellDervNames:
2497                if name in varylist:
2498                    dMdv[varylist.index(name)][iBeg:iFin] += dpdA*dervDict['pos']
2499                    if Ka2 and iFin2-iBeg2:
2500                        dMdv[varylist.index(name)][iBeg2:iFin2] += dpdA*dervDict2['pos']
2501                elif name in dependentVars:
2502                    depDerivDict[name][iBeg:iFin] += dpdA*dervDict['pos']
2503                    if Ka2 and iFin2-iBeg2:
2504                        depDerivDict[name][iBeg2:iFin2] += dpdA*dervDict2['pos']
2505            dDijDict = GetHStrainShiftDerv(refl,im,SGData,phfx,hfx,calcControls,parmDict)
2506            for name in dDijDict:
2507                if name in varylist:
2508                    dMdv[varylist.index(name)][iBeg:iFin] += dDijDict[name]*dervDict['pos']
2509                    if Ka2 and iFin2-iBeg2:
2510                        dMdv[varylist.index(name)][iBeg2:iFin2] += dDijDict[name]*dervDict2['pos']
2511                elif name in dependentVars:
2512                    depDerivDict[name][iBeg:iFin] += dDijDict[name]*dervDict['pos']
2513                    if Ka2 and iFin2-iBeg2:
2514                        depDerivDict[name][iBeg2:iFin2] += dDijDict[name]*dervDict2['pos']
2515            for i,name in enumerate([pfx+'mV0',pfx+'mV1',pfx+'mV2']):
2516                if name in varylist:
2517                    dMdv[varylist.index(name)][iBeg:iFin] += dpdV[i]*dervDict['pos']
2518                    if Ka2 and iFin2-iBeg2:
2519                        dMdv[varylist.index(name)][iBeg2:iFin2] += dpdV[i]*dervDict2['pos']
2520                elif name in dependentVars:
2521                    depDerivDict[name][iBeg:iFin] += dpdV[i]*dervDict['pos']
2522                    if Ka2 and iFin2-iBeg2:
2523                        depDerivDict[name][iBeg2:iFin2] += dpdV[i]*dervDict2['pos']
2524            if 'C' in calcControls[hfx+'histType']:
2525                sigDict,gamDict = GetSampleSigGamDerv(refl,im,wave,G,GB,SGData,hfx,phfx,calcControls,parmDict)
2526            else:   #'T'OF
2527                sigDict,gamDict = GetSampleSigGamDerv(refl,im,0.0,G,GB,SGData,hfx,phfx,calcControls,parmDict)
2528            for name in gamDict:
2529                if name in varylist:
2530                    dMdv[varylist.index(name)][iBeg:iFin] += gamDict[name]*dervDict['gam']
2531                    if Ka2 and iFin2-iBeg2:
2532                        dMdv[varylist.index(name)][iBeg2:iFin2] += gamDict[name]*dervDict2['gam']
2533                elif name in dependentVars:
2534                    depDerivDict[name][iBeg:iFin] += gamDict[name]*dervDict['gam']
2535                    if Ka2 and iFin2-iBeg2:
2536                        depDerivDict[name][iBeg2:iFin2] += gamDict[name]*dervDict2['gam']
2537            for name in sigDict:
2538                if name in varylist:
2539                    dMdv[varylist.index(name)][iBeg:iFin] += sigDict[name]*dervDict['sig']
2540                    if Ka2 and iFin2-iBeg2:
2541                        dMdv[varylist.index(name)][iBeg2:iFin2] += sigDict[name]*dervDict2['sig']
2542                elif name in dependentVars:
2543                    depDerivDict[name][iBeg:iFin] += sigDict[name]*dervDict['sig']
2544                    if Ka2 and iFin2-iBeg2:
2545                        depDerivDict[name][iBeg2:iFin2] += sigDict[name]*dervDict2['sig']
2546            for name in ['BabA','BabU']:
2547                if refl[9+im]:
2548                    if phfx+name in varylist:
2549                        dMdv[varylist.index(phfx+name)][iBeg:iFin] += dFdvDict[pfx+name][iref]*dervDict['int']/refl[9+im]
2550                        if Ka2 and iFin2-iBeg2:
2551                            dMdv[varylist.index(phfx+name)][iBeg2:iFin2] += dFdvDict[pfx+name][iref]*dervDict2['int']/refl[9+im]
2552                    elif phfx+name in dependentVars:                   
2553                        depDerivDict[phfx+name][iBeg:iFin] += dFdvDict[pfx+name][iref]*dervDict['int']/refl[9+im]
2554                        if Ka2 and iFin2-iBeg2:
2555                            depDerivDict[phfx+name][iBeg2:iFin2] += dFdvDict[pfx+name][iref]*dervDict2['int']/refl[9+im]                 
2556            if not Phase['General'].get('doPawley'):
2557                #do atom derivatives -  for RB,F,X & U so far             
2558                corr = dervDict['int']/refl[9+im]
2559                if Ka2 and iFin2-iBeg2:
2560                    corr2 = dervDict2['int']/refl[9+im]
2561                for name in varylist+dependentVars:
2562                    if '::RBV;' in name:
2563                        pass
2564                    else:
2565                        try:
2566                            aname = name.split(pfx)[1][:2]
2567                            if aname not in ['Af','dA','AU','RB']: continue # skip anything not an atom or rigid body param
2568                        except IndexError:
2569                            continue
2570                    if name in varylist:
2571                        dMdv[varylist.index(name)][iBeg:iFin] += dFdvDict[name][iref]*corr
2572                        if Ka2 and iFin2-iBeg2:
2573                            dMdv[varylist.index(name)][iBeg2:iFin2] += dFdvDict[name][iref]*corr2
2574                    elif name in dependentVars:
2575                        depDerivDict[name][iBeg:iFin] += dFdvDict[name][iref]*corr
2576                        if Ka2 and iFin2-iBeg2:
2577                            depDerivDict[name][iBeg2:iFin2] += dFdvDict[name][iref]*corr2
2578    #        print 'profile derv time: %.3fs'%(time.time()-time0)
2579    # now process derivatives in constraints
2580    G2mv.Dict2Deriv(varylist,depDerivDict,dMdv)
2581    return dMdv
2582   
2583def UserRejectHKL(ref,im,userReject):
2584    if ref[5+im]/ref[6+im] < userReject['minF/sig']:
2585        return False
2586    elif userReject['MaxD'] < ref[4+im] > userReject['MinD']:
2587        return False
2588    elif ref[11+im] < userReject['MinExt']:
2589        return False
2590    elif abs(ref[5+im]-ref[7+im])/ref[6+im] > userReject['MaxDF/F']:
2591        return False
2592    return True
2593   
2594def dervHKLF(Histogram,Phase,calcControls,varylist,parmDict,rigidbodyDict):
2595    '''Loop over reflections in a HKLF histogram and compute derivatives of the fitting
2596    model (M) with respect to all parameters.  Independent and dependant dM/dp arrays
2597    are returned to either dervRefine or HessRefine.
2598
2599    :returns:
2600    '''
2601    nobs = Histogram['Residuals']['Nobs']
2602    hId = Histogram['hId']
2603    hfx = ':%d:'%(hId)
2604    pfx = '%d::'%(Phase['pId'])
2605    phfx = '%d:%d:'%(Phase['pId'],hId)
2606    SGData = Phase['General']['SGData']
2607    im = 0
2608    if Phase['General']['Type'] in ['modulated','magnetic']:
2609        SSGData = Phase['General']['SSGData']
2610        SSGMT = np.array([ops[0].T for ops in SSGData['SSGOps']])
2611        im = 1  #offset in SS reflection list
2612    A = [parmDict[pfx+'A%d'%(i)] for i in range(6)]
2613    G,g = G2lat.A2Gmat(A)       #recip & real metric tensors
2614    refDict = Histogram['Data']
2615    if parmDict[phfx+'Scale'] < 0.:
2616        parmDict[phfx+'Scale'] = .001
2617    if im:
2618        dFdvDict = SStructureFactorDerv(refDict,im,G,hfx,pfx,SGData,SSGData,calcControls,parmDict)
2619    else:
2620        dFdvDict = StructureFactorDerv(refDict,G,hfx,pfx,SGData,calcControls,parmDict)
2621    ApplyRBModelDervs(dFdvDict,parmDict,rigidbodyDict,Phase)
2622    dMdvh = np.zeros((len(varylist),len(refDict['RefList'])))
2623    dependentVars = G2mv.GetDependentVars()
2624    depDerivDict = {}
2625    for j in dependentVars:
2626        depDerivDict[j] = np.zeros(shape=(len(refDict['RefList'])))
2627    wdf = np.zeros(len(refDict['RefList']))
2628    if calcControls['F**2']:
2629        for iref,ref in enumerate(refDict['RefList']):
2630            if ref[6+im] > 0:
2631                dervDict,dervCor = SCExtinction(ref,im,phfx,hfx,pfx,calcControls,parmDict,varylist+dependentVars)[1:]
2632                w = 1.0/ref[6+im]
2633                if ref[3+im] > 0:
2634                    wdf[iref] = w*(ref[5+im]-ref[7+im])
2635                    for j,var in enumerate(varylist):
2636                        if var in dFdvDict:
2637                            dMdvh[j][iref] = w*dFdvDict[var][iref]*parmDict[phfx+'Scale']*ref[11+im]
2638                    for var in dependentVars:
2639                        if var in dFdvDict:
2640                            depDerivDict[var][iref] = w*dFdvDict[var][iref]*parmDict[phfx+'Scale']*ref[11+im]
2641                    if phfx+'Scale' in varylist:
2642                        dMdvh[varylist.index(phfx+'Scale')][iref] = w*ref[7+im]*ref[11+im]/parmDict[phfx+'Scale']  #OK
2643                    elif phfx+'Scale' in dependentVars:
2644                        depDerivDict[phfx+'Scale'][iref] = w*ref[7+im]*ref[11+im]/parmDict[phfx+'Scale']   #OK
2645                    for item in ['Ep','Es','Eg']:
2646                        if phfx+item in varylist and phfx+item in dervDict:
2647                            dMdvh[varylist.index(phfx+item)][iref] = w*dervDict[phfx+item]/ref[11+im]  #OK
2648                        elif phfx+item in dependentVars and phfx+item in dervDict:
2649                            depDerivDict[phfx+item][iref] = w*dervDict[phfx+item]/ref[11+im]  #OK
2650                    for item in ['BabA','BabU']:
2651                        if phfx+item in varylist:
2652                            dMdvh[varylist.index(phfx+item)][iref] = w*dFdvDict[pfx+item][iref]*parmDict[phfx+'Scale']*ref[11+im]
2653                        elif phfx+item in dependentVars:
2654                            depDerivDict[phfx+item][iref] = w*dFdvDict[pfx+item][iref]*parmDict[phfx+'Scale']*ref[11+im]
2655    else:   #F refinement
2656        for iref,ref in enumerate(refDict['RefList']):
2657            if ref[5+im] > 0.:
2658                dervDict,dervCor = SCExtinction(ref,im,phfx,hfx,pfx,calcControls,parmDict,varylist+dependentVars)[1:]
2659                Fo = np.sqrt(ref[5+im])
2660                Fc = np.sqrt(ref[7+im])
2661                w = 1.0/ref[6+im]
2662                if ref[3+im] > 0:
2663                    wdf[iref] = 2.0*Fc*w*(Fo-Fc)
2664                    for j,var in enumerate(varylist):
2665                        if var in dFdvDict:
2666                            dMdvh[j][iref] = w*dFdvDict[var][iref]*parmDict[phfx+'Scale']*ref[11+im]
2667                    for var in dependentVars:
2668                        if var in dFdvDict:
2669                            depDerivDict[var][iref] = w*dFdvDict[var][iref]*parmDict[phfx+'Scale']*ref[11+im]
2670                    if phfx+'Scale' in varylist:
2671                        dMdvh[varylist.index(phfx+'Scale')][iref] = w*ref[7+im]*ref[11+im]/parmDict[phfx+'Scale']  #OK
2672                    elif phfx+'Scale' in dependentVars:
2673                        depDerivDict[phfx+'Scale'][iref] = w*ref[7+im]*ref[11+im]/parmDict[phfx+'Scale']   #OK                   
2674                    for item in ['Ep','Es','Eg']:   #OK!
2675                        if phfx+item in varylist and phfx+item in dervDict:
2676                            dMdvh[varylist.index(phfx+item)][iref] = w*dervDict[phfx+item]/ref[11+im] 
2677                        elif phfx+item in dependentVars and phfx+item in dervDict:
2678                            depDerivDict[phfx+item][iref] = w*dervDict[phfx+item]/ref[11+im]
2679                    for item in ['BabA','BabU']:
2680                        if phfx+item in varylist:
2681                            dMdvh[varylist.index(phfx+item)][iref] = w*dFdvDict[pfx+item][iref]*parmDict[phfx+'Scale']*ref[11+im]
2682                        elif phfx+item in dependentVars:
2683                            depDerivDict[phfx+item][iref] = w*dFdvDict[pfx+item][iref]*parmDict[phfx+'Scale']*ref[11+im]
2684    return dMdvh,depDerivDict,wdf
2685   
2686
2687def dervRefine(values,HistoPhases,parmDict,varylist,calcControls,pawleyLookup,dlg):
2688    '''Loop over histograms and compute derivatives of the fitting
2689    model (M) with respect to all parameters.  Results are returned in
2690    a Jacobian matrix (aka design matrix) of dimensions (n by m) where
2691    n is the number of parameters and m is the number of data
2692    points. This can exceed memory when m gets large. This routine is
2693    used when refinement derivatives are selected as "analtytic
2694    Jacobian" in Controls.
2695
2696    :returns: Jacobian numpy.array dMdv for all histograms concatinated
2697    '''
2698    parmDict.update(zip(varylist,values))
2699    G2mv.Dict2Map(parmDict,varylist)
2700    Histograms,Phases,restraintDict,rigidbodyDict = HistoPhases
2701    nvar = len(varylist)
2702    dMdv = np.empty(0)
2703    histoList = Histograms.keys()
2704    histoList.sort()
2705    for histogram in histoList:
2706        if 'PWDR' in histogram[:4]:
2707            Histogram = Histograms[histogram]
2708            hId = Histogram['hId']
2709            hfx = ':%d:'%(hId)
2710            wtFactor = calcControls[hfx+'wtFactor']
2711            Limits = calcControls[hfx+'Limits']
2712            x,y,w,yc,yb,yd = Histogram['Data']
2713            xB = np.searchsorted(x,Limits[0])
2714            xF = np.searchsorted(x,Limits[1])
2715            dMdvh = np.sqrt(w[xB:xF])*getPowderProfileDerv(parmDict,x[xB:xF],
2716                varylist,Histogram,Phases,rigidbodyDict,calcControls,pawleyLookup)
2717        elif 'HKLF' in histogram[:4]:
2718            Histogram = Histograms[histogram]
2719            phase = Histogram['Reflection Lists']
2720            Phase = Phases[phase]
2721            dMdvh,depDerivDict,wdf = dervHKLF(Histogram,Phase,calcControls,varylist,parmDict,rigidbodyDict)
2722            hfx = ':%d:'%(Histogram['hId'])
2723            wtFactor = calcControls[hfx+'wtFactor']
2724            # now process derivatives in constraints
2725            G2mv.Dict2Deriv(varylist,depDerivDict,dMdvh)
2726        else:
2727            continue        #skip non-histogram entries
2728        if len(dMdv):
2729            dMdv = np.concatenate((dMdv.T,np.sqrt(wtFactor)*dMdvh.T)).T
2730        else:
2731            dMdv = np.sqrt(wtFactor)*dMdvh
2732           
2733    pNames,pVals,pWt,pWsum = penaltyFxn(HistoPhases,calcControls,parmDict,varylist)
2734    if np.any(pVals):
2735        dpdv = penaltyDeriv(pNames,pVals,HistoPhases,calcControls,parmDict,varylist)
2736        dMdv = np.concatenate((dMdv.T,(np.sqrt(pWt)*dpdv).T)).T
2737       
2738    return dMdv
2739
2740def HessRefine(values,HistoPhases,parmDict,varylist,calcControls,pawleyLookup,dlg):
2741    '''Loop over histograms and compute derivatives of the fitting
2742    model (M) with respect to all parameters.  For each histogram, the
2743    Jacobian matrix, dMdv, with dimensions (n by m) where n is the
2744    number of parameters and m is the number of data points *in the
2745    histogram*. The (n by n) Hessian is computed from each Jacobian
2746    and it is returned.  This routine is used when refinement
2747    derivatives are selected as "analtytic Hessian" in Controls.
2748
2749    :returns: Vec,Hess where Vec is the least-squares vector and Hess is the Hessian
2750    '''
2751    parmDict.update(zip(varylist,values))
2752    G2mv.Dict2Map(parmDict,varylist)
2753    Histograms,Phases,restraintDict,rigidbodyDict = HistoPhases
2754    #fixup H atom positions here?
2755    ApplyRBModels(parmDict,Phases,rigidbodyDict)        #,Update=True??
2756    nvar = len(varylist)
2757    Hess = np.empty(0)
2758    histoList = Histograms.keys()
2759    histoList.sort()
2760    for histogram in histoList:
2761        if 'PWDR' in histogram[:4]:
2762            Histogram = Histograms[histogram]
2763            hId = Histogram['hId']
2764            hfx = ':%d:'%(hId)
2765            wtFactor = calcControls[hfx+'wtFactor']
2766            Limits = calcControls[hfx+'Limits']
2767            x,y,w,yc,yb,yd = Histogram['Data']
2768            W = wtFactor*w
2769            dy = y-yc
2770            xB = np.searchsorted(x,Limits[0])
2771            xF = np.searchsorted(x,Limits[1])
2772            dMdvh = getPowderProfileDerv(parmDict,x[xB:xF],
2773                varylist,Histogram,Phases,rigidbodyDict,calcControls,pawleyLookup)
2774            Wt = ma.sqrt(W[xB:xF])[np.newaxis,:]
2775            Dy = dy[xB:xF][np.newaxis,:]
2776            dMdvh *= Wt
2777            if dlg:
2778                dlg.Update(Histogram['Residuals']['wR'],newmsg='Hessian for histogram %d\nAll data Rw=%8.3f%s'%(hId,Histogram['Residuals']['wR'],'%'))
2779            if len(Hess):
2780                Hess += np.inner(dMdvh,dMdvh)
2781                dMdvh *= Wt*Dy
2782                Vec += np.sum(dMdvh,axis=1)
2783            else:
2784                Hess = np.inner(dMdvh,dMdvh)
2785                dMdvh *= Wt*Dy
2786                Vec = np.sum(dMdvh,axis=1)
2787        elif 'HKLF' in histogram[:4]:
2788            Histogram = Histograms[histogram]
2789            phase = Histogram['Reflection Lists']
2790            Phase = Phases[phase]
2791            dMdvh,depDerivDict,wdf = dervHKLF(Histogram,Phase,calcControls,varylist,parmDict,rigidbodyDict)
2792            hId = Histogram['hId']
2793            hfx = ':%d:'%(Histogram['hId'])
2794            wtFactor = calcControls[hfx+'wtFactor']
2795            # now process derivatives in constraints
2796            G2mv.Dict2Deriv(varylist,depDerivDict,dMdvh)
2797#            print 'matrix build time: %.3f'%(time.time()-time0)
2798
2799            if dlg:
2800                dlg.Update(Histogram['Residuals']['wR'],newmsg='Hessian for histogram %d Rw=%8.3f%s'%(hId,Histogram['Residuals']['wR'],'%'))[0]
2801            if len(Hess):
2802                Vec += wtFactor*np.sum(dMdvh*wdf,axis=1)
2803                Hess += wtFactor*np.inner(dMdvh,dMdvh)
2804            else:
2805                Vec = wtFactor*np.sum(dMdvh*wdf,axis=1)
2806                Hess = wtFactor*np.inner(dMdvh,dMdvh)
2807        else:
2808            continue        #skip non-histogram entries
2809    pNames,pVals,pWt,pWsum = penaltyFxn(HistoPhases,calcControls,parmDict,varylist)
2810    if np.any(pVals):
2811        dpdv = penaltyDeriv(pNames,pVals,HistoPhases,calcControls,parmDict,varylist)
2812        Vec += np.sum(dpdv*pWt*pVals,axis=1)
2813        Hess += np.inner(dpdv*pWt,dpdv)
2814    return Vec,Hess
2815
2816def errRefine(values,HistoPhases,parmDict,varylist,calcControls,pawleyLookup,dlg=None):       
2817    '''Computes the point-by-point discrepancies between every data point in every histogram
2818    and the observed value
2819   
2820    :returns: an np array of differences between observed and computed diffraction values.
2821    '''
2822    Values2Dict(parmDict, varylist, values)
2823    G2mv.Dict2Map(parmDict,varylist)
2824    Histograms,Phases,restraintDict,rigidbodyDict = HistoPhases
2825    M = np.empty(0)
2826    SumwYo = 0
2827    Nobs = 0
2828    Nrej = 0
2829    Next = 0
2830    ApplyRBModels(parmDict,Phases,rigidbodyDict)
2831    #fixup Hatom positions here....
2832    histoList = Histograms.keys()
2833    histoList.sort()
2834    for histogram in histoList:
2835        if 'PWDR' in histogram[:4]:
2836            Histogram = Histograms[histogram]
2837            hId = Histogram['hId']
2838            hfx = ':%d:'%(hId)
2839            wtFactor = calcControls[hfx+'wtFactor']
2840            Limits = calcControls[hfx+'Limits']
2841            x,y,w,yc,yb,yd = Histogram['Data']
2842            yc *= 0.0                           #zero full calcd profiles
2843            yb *= 0.0
2844            yd *= 0.0
2845            xB = np.searchsorted(x,Limits[0])
2846            xF = np.searchsorted(x,Limits[1])
2847            yc[xB:xF],yb[xB:xF] = getPowderProfile(parmDict,x[xB:xF],
2848                varylist,Histogram,Phases,calcControls,pawleyLookup)
2849            yc[xB:xF] += yb[xB:xF]
2850            if not np.any(y):                   #fill dummy data
2851                rv = st.poisson(yc[xB:xF])
2852                y[xB:xF] = rv.rvs()
2853                Z = np.ones_like(yc[xB:xF])
2854                Z[1::2] *= -1
2855                y[xB:xF] = yc[xB:xF]+np.abs(y[xB:xF]-yc[xB:xF])*Z
2856                w[xB:xF] = np.where(y[xB:xF]>0.,1./y[xB:xF],1.0)
2857            yd[xB:xF] = y[xB:xF]-yc[xB:xF]
2858            W = wtFactor*w
2859            wdy = -ma.sqrt(W[xB:xF])*(yd[xB:xF])
2860            Histogram['Residuals']['Nobs'] = ma.count(x[xB:xF])
2861            Nobs += Histogram['Residuals']['Nobs']
2862            Histogram['Residuals']['sumwYo'] = ma.sum(W[xB:xF]*y[xB:xF]**2)
2863            SumwYo += Histogram['Residuals']['sumwYo']
2864            Histogram['Residuals']['R'] = min(100.,ma.sum(ma.abs(yd[xB:xF]))/ma.sum(y[xB:xF])*100.)
2865            Histogram['Residuals']['wR'] = min(100.,ma.sqrt(ma.sum(wdy**2)/Histogram['Residuals']['sumwYo'])*100.)
2866            sumYmB = ma.sum(ma.where(yc[xB:xF]!=yb[xB:xF],ma.abs(y[xB:xF]-yb[xB:xF]),0.))
2867            sumwYmB2 = ma.sum(ma.where(yc[xB:xF]!=yb[xB:xF],W[xB:xF]*(y[xB:xF]-yb[xB:xF])**2,0.))
2868            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.))
2869            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.))
2870            Histogram['Residuals']['Rb'] = min(100.,100.*sumYB/sumYmB)
2871            Histogram['Residuals']['wRb'] = min(100.,100.*ma.sqrt(sumwYB2/sumwYmB2))
2872            Histogram['Residuals']['wRmin'] = min(100.,100.*ma.sqrt(Histogram['Residuals']['Nobs']/Histogram['Residuals']['sumwYo']))
2873            if dlg:
2874                dlg.Update(Histogram['Residuals']['wR'],newmsg='For histogram %d Rw=%8.3f%s'%(hId,Histogram['Residuals']['wR'],'%'))[0]
2875            M = np.concatenate((M,wdy))
2876#end of PWDR processing
2877        elif 'HKLF' in histogram[:4]:
2878            Histogram = Histograms[histogram]
2879            Histogram['Residuals'] = {}
2880            phase = Histogram['Reflection Lists']
2881            Phase = Phases[phase]
2882            hId = Histogram['hId']
2883            hfx = ':%d:'%(hId)
2884            wtFactor = calcControls[hfx+'wtFactor']
2885            pfx = '%d::'%(Phase['pId'])
2886            phfx = '%d:%d:'%(Phase['pId'],hId)
2887            SGData = Phase['General']['SGData']
2888            im = 0
2889            if parmDict[phfx+'Scale'] < 0.:
2890                parmDict[phfx+'Scale'] = .001               
2891            if Phase['General']['Type'] in ['modulated','magnetic']:
2892                SSGData = Phase['General']['SSGData']
2893                SSGMT = np.array([ops[0].T for ops in SSGData['SSGOps']])
2894                im = 1  #offset in SS reflection list
2895            A = [parmDict[pfx+'A%d'%(i)] for i in range(6)]
2896            G,g = G2lat.A2Gmat(A)       #recip & real metric tensors
2897            refDict = Histogram['Data']
2898            time0 = time.time()
2899            if im:
2900                SStructureFactor2(refDict,im,G,hfx,pfx,SGData,SSGData,calcControls,parmDict)
2901            else:
2902                StructureFactor2(refDict,G,hfx,pfx,SGData,calcControls,parmDict)
2903#            print 'sf-calc time: %.3f'%(time.time()-time0)
2904            df = np.zeros(len(refDict['RefList']))
2905            sumwYo = 0
2906            sumFo = 0
2907            sumFo2 = 0
2908            sumdF = 0
2909            sumdF2 = 0
2910            if im:
2911                sumSSFo = np.zeros(10)
2912                sumSSFo2 = np.zeros(10)
2913                sumSSdF = np.zeros(10)
2914                sumSSdF2 = np.zeros(10)
2915                sumSSwYo = np.zeros(10)
2916                sumSSwdf2 = np.zeros(10)
2917                SSnobs = np.zeros(10)
2918            nobs = 0
2919            nrej = 0
2920            next = 0
2921            maxH = 0
2922            if calcControls['F**2']:
2923                for i,ref in enumerate(refDict['RefList']):
2924                    if ref[6+im] > 0:
2925                        ref[11+im] = SCExtinction(ref,im,phfx,hfx,pfx,calcControls,parmDict,varylist)[0]
2926                        w = 1.0/ref[6+im]   # 1/sig(F^2)
2927                        ref[7+im] *= parmDict[phfx+'Scale']*ref[11+im]  #correct Fc^2 for extinction
2928                        ref[8+im] = ref[5+im]/(parmDict[phfx+'Scale']*ref[11+im])
2929                        if UserRejectHKL(ref,im,calcControls['UsrReject']) and ref[3+im]:    #skip sp.gp. absences (mul=0)
2930                            ref[3+im] = abs(ref[3+im])      #mark as allowed
2931                            Fo = np.sqrt(ref[5+im])
2932                            sumFo += Fo
2933                            sumFo2 += ref[5+im]
2934                            sumdF += abs(Fo-np.sqrt(ref[7+im]))
2935                            sumdF2 += abs(ref[5+im]-ref[7+im])
2936                            nobs += 1
2937                            df[i] = -w*(ref[5+im]-ref[7+im])
2938                            sumwYo += (w*ref[5+im])**2      #w*Fo^2
2939                            if im:  #accumulate super lattice sums
2940                                ind = int(abs(ref[3]))
2941                                sumSSFo[ind] += Fo
2942                                sumSSFo2[ind] += ref[5+im]
2943                                sumSSdF[ind] += abs(Fo-np.sqrt(ref[7+im]))
2944                                sumSSdF2[ind] += abs(ref[5+im]-ref[7+im])
2945                                sumSSwYo[ind] += (w*ref[5+im])**2      #w*Fo^2
2946                                sumSSwdf2[ind] +=  df[i]**2
2947                                SSnobs[ind] += 1
2948                                maxH = max(maxH,ind)                           
2949                        else:
2950                            if ref[3+im]:
2951                                ref[3+im] = -abs(ref[3+im])      #mark as rejected
2952                                nrej += 1
2953                            else:   #sp.gp.extinct
2954                                next += 1
2955            else:
2956                for i,ref in enumerate(refDict['RefList']):
2957                    if ref[5+im] > 0.:
2958                        ref[11+im] = SCExtinction(ref,im,phfx,hfx,pfx,calcControls,parmDict,varylist)[0]
2959                        ref[7+im] *= parmDict[phfx+'Scale']*ref[11+im]    #correct Fc^2 for extinction
2960                        ref[8+im] = ref[5+im]/(parmDict[phfx+'Scale']*ref[11+im])
2961                        Fo = np.sqrt(ref[5+im])
2962                        Fc = np.sqrt(ref[7+im])
2963                        w = 2.0*Fo/ref[6+im]    # 1/sig(F)?
2964                        if UserRejectHKL(ref,im,calcControls['UsrReject']) and ref[3+im]:    #skip sp.gp. absences (mul=0)
2965                            ref[3+im] = abs(ref[3+im])      #mark as allowed
2966                            sumFo += Fo
2967                            sumFo2 += ref[5+im]
2968                            sumdF += abs(Fo-Fc)
2969                            sumdF2 += abs(ref[5+im]-ref[7+im])
2970                            nobs += 1
2971                            df[i] = -w*(Fo-Fc)
2972                            sumwYo += (w*Fo)**2
2973                            if im:
2974                                ind = int(abs(ref[3]))
2975                                sumSSFo[ind] += Fo
2976                                sumSSFo2[ind] += ref[5+im]
2977                                sumSSdF[ind] += abs(Fo-Fc)
2978                                sumSSdF2[ind] += abs(ref[5+im]-ref[7+im])
2979                                sumSSwYo[ind] += (w*Fo)**2                                                           
2980                                sumSSwdf2[ind] +=  df[i]**2
2981                                SSnobs[ind] += 1                           
2982                                maxH = max(maxH,ind)                           
2983                        else:
2984                            if ref[3+im]:
2985                                ref[3+im] = -abs(ref[3+im])      #mark as rejected
2986                                nrej += 1
2987                            else:   #sp.gp.extinct
2988                                next += 1
2989            Histogram['Residuals']['Nobs'] = nobs
2990            Histogram['Residuals']['sumwYo'] = sumwYo
2991            SumwYo += sumwYo
2992            Histogram['Residuals']['wR'] = min(100.,np.sqrt(np.sum(df**2)/sumwYo)*100.)
2993            Histogram['Residuals'][phfx+'Rf'] = 100.*sumdF/sumFo
2994            Histogram['Residuals'][phfx+'Rf^2'] = 100.*sumdF2/sumFo2
2995            Histogram['Residuals'][phfx+'Nref'] = nobs
2996            Histogram['Residuals'][phfx+'Nrej'] = nrej
2997            Histogram['Residuals'][phfx+'Next'] = next
2998            if im:
2999                Histogram['Residuals'][phfx+'SSRf'] = 100.*sumSSdF[:maxH+1]/sumSSFo[:maxH+1]
3000                Histogram['Residuals'][phfx+'SSRf^2'] = 100.*sumSSdF2[:maxH+1]/sumSSFo2[:maxH+1]
3001                Histogram['Residuals'][phfx+'SSNref'] = SSnobs[:maxH+1]
3002                Histogram['Residuals']['SSwR'] = np.sqrt(sumSSwdf2[:maxH+1]/sumSSwYo[:maxH+1])*100.               
3003            Nobs += nobs
3004            Nrej += nrej
3005            Next += next
3006            if dlg:
3007                dlg.Update(Histogram['Residuals']['wR'],newmsg='For histogram %d Rw=%8.3f%s'%(hId,Histogram['Residuals']['wR'],'%'))[0]
3008            M = np.concatenate((M,wtFactor*df))
3009# end of HKLF processing
3010    Histograms['sumwYo'] = SumwYo
3011    Histograms['Nobs'] = Nobs
3012    Histograms['Nrej'] = Nrej
3013    Histograms['Next'] = Next
3014    Rw = min(100.,np.sqrt(np.sum(M**2)/SumwYo)*100.)
3015    if dlg:
3016        GoOn = dlg.Update(Rw,newmsg='%s%8.3f%s'%('All data Rw =',Rw,'%'))[0]
3017        if not GoOn:
3018            parmDict['saved values'] = values
3019            dlg.Destroy()
3020            raise G2obj.G2Exception('User abort')         #Abort!!
3021    pDict,pVals,pWt,pWsum = penaltyFxn(HistoPhases,calcControls,parmDict,varylist)
3022    if len(pVals):
3023        pSum = np.sum(pWt*pVals**2)
3024        for name in pWsum:
3025            if pWsum[name]:
3026                print '  Penalty function for %8s = %12.5g'%(name,pWsum[name])
3027        print 'Total penalty function: %12.5g on %d terms'%(pSum,len(pVals))
3028        Nobs += len(pVals)
3029        M = np.concatenate((M,np.sqrt(pWt)*pVals))
3030    return M
3031                       
Note: See TracBrowser for help on using the repository browser.