Skip to content

Commit ae5007e

Browse files
committed
add spherical harmonics to scriptable; add test of pytexture to test_scriptref; minor cleanup of GUI code for SH
1 parent ed7ddd2 commit ae5007e

File tree

3 files changed

+62
-10
lines changed

3 files changed

+62
-10
lines changed

GSASII/GSASIIddataGUI.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -207,13 +207,21 @@ def OnPOAxis(event):
207207
Obj.SetValue('%3d %3d %3d'%(h,k,l))
208208

209209
def OnPOOrder(event):
210+
'''Respond when the SH order is changed in the GUI.
211+
Updates the dict with the cylindrical Spherical harmonics
212+
coefficients for the specified order, retaining values from
213+
the previous dict, if values were already present
214+
'''
210215
Obj = event.GetEventObject()
211216
Order = int(Obj.GetValue())
212217
UseList[G2frame.hist]['Pref.Ori.'][4] = Order
213-
UseList[G2frame.hist]['Pref.Ori.'][5] = SetPOCoef(Order,G2frame.hist)
218+
UseList[G2frame.hist]['Pref.Ori.'][5] = SetPOCoef(Order)
214219
wx.CallLater(100,RepaintHistogramInfo,DData.GetScrollPos(wx.VERTICAL))
215220

216221
def OnPOType(event):
222+
'''Respond when the SH type is changed in the GUI.
223+
Note that values set that are not used are also not changed.
224+
'''
217225
Obj = event.GetEventObject()
218226
if 'March' in Obj.GetValue():
219227
UseList[G2frame.hist]['Pref.Ori.'][0] = 'MD'
@@ -251,12 +259,16 @@ def OnAddFixed(event):
251259
UseList[G2frame.hist]['FixedSeqVars'] = [phaseKeys[i] for i in sel]
252260
wx.CallLater(100,RepaintHistogramInfo,DData.GetScrollPos(wx.VERTICAL))
253261

254-
def SetPOCoef(Order,hist):
262+
def SetPOCoef(Order):
263+
'''Sets up a dict with the cylindrical Spherical harmonics
264+
coefficients for the specified order.
265+
Retains values from the previous dict, if values were already present
266+
'''
255267
cofNames = G2lat.GenSHCoeff(SGData['SGLaue'],'0',Order,False) #cylindrical & no M
256-
newPOCoef = dict(zip(cofNames,np.zeros(len(cofNames))))
268+
newPOCoef = dict(zip(cofNames,len(cofNames)*[0.]))
257269
POCoeff = UseList[G2frame.hist]['Pref.Ori.'][5]
258270
for cofName in POCoeff:
259-
if cofName in cofNames:
271+
if cofName in cofNames:
260272
newPOCoef[cofName] = POCoeff[cofName]
261273
return newPOCoef
262274

GSASII/GSASIIscriptable.py

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4998,21 +4998,25 @@ def HAPvalue(self, param=None, newValue=None, targethistlist='all'):
49984998
"""Retrieves or sets individual HAP parameters for one histogram or
49994999
multiple histograms.
50005000
5001-
50025001
:param str param: is a parameter name, which can be 'Scale' or
50035002
'PhaseFraction' (either can be used for phase
5004-
fraction), 'Use', 'Extinction' or 'LeBail'.
5003+
fraction), 'Use', 'Extinction', 'LeBail', 'PO'
5004+
(for Prefered Orientation).
50055005
If not specified or invalid
50065006
an exception is generated showing the list of valid parameters.
50075007
At present, these HAP parameters cannot be access with this function:
5008-
'Pref.Ori.', 'Size', 'Mustrain', 'HStrain', 'Babinet'. On request this
5008+
'Size', 'Mustrain', 'HStrain', 'Babinet'. On request this
50095009
might be addressed in the future. Some of these values can be set via
50105010
:meth:`G2Phase.set_HAP_refinements`.
50115011
:param newValue: the value to use when setting the HAP parameter for the
50125012
appropriate histogram(s). Will be converted to the proper type or
50135013
an exception will be generated if not possible. If not specified,
50145014
and only one histogram is selected, the value is retrieved and
50155015
returned.
5016+
When param='PO' then this value is interpreted as the following:
5017+
if the value is 0 or an even integer, then the preferred
5018+
orientation model is set to "Spherical harmonics". If the value is
5019+
1, then "March-Dollase" is used. Any other value generates an error.
50165020
:param list targethistlist: a list of histograms where each item in the
50175021
list can be a histogram object (:class:`G2PwdrData`),
50185022
a histogram name or the index number of the histogram.
@@ -5022,7 +5026,8 @@ def HAPvalue(self, param=None, newValue=None, targethistlist='all'):
50225026
are used.
50235027
50245028
targethistlist must correspond to a single histogram if a value
5025-
is to be returned (when argument newValue is not specified).
5029+
is to be returned (i.e. when argument newValue is not specified).
5030+
:param int order: is a value for the order when
50265031
50275032
:returns: the value of the parameter, when argument newValue is not specified.
50285033
@@ -5050,17 +5055,20 @@ def HAPvalue(self, param=None, newValue=None, targethistlist='all'):
50505055
refFloatParam = ('Scale','Extinction')
50515056
useBool = False
50525057
useFloat = False
5058+
useInt = False
50535059
if param == 'PhaseFraction': param = 'Scale'
50545060
if param in boolParam:
50555061
useBool = True
50565062
elif param in refFloatParam:
50575063
useFloat = True
5064+
elif param in ['PO']:
5065+
useInt = True
50585066
else:
50595067
s = ''
5060-
for i in boolParam+refFloatParam+['PhaseFraction']:
5068+
for i in boolParam+refFloatParam+['PhaseFraction','PO']:
50615069
if s != '': s += ', '
50625070
s += f'"{i}"'
5063-
raise G2ScriptException('Invalid parameter. Valid choices are: '+s)
5071+
raise G2ScriptException(f'Invalid parameter. Valid choices are: {s}')
50645072
if not doSet and len(targethistlist) > 1:
50655073
raise G2ScriptException(f'Unable to report value from {len(targethistlist)} histograms')
50665074
for h in targethistlist:
@@ -5076,6 +5084,28 @@ def HAPvalue(self, param=None, newValue=None, targethistlist='all'):
50765084
self.data['Histograms'][h][param] = bool(newValue)
50775085
elif useFloat:
50785086
self.data['Histograms'][h][param][0] = float(newValue)
5087+
elif useInt:
5088+
if newValue is None:
5089+
return self.data['Histograms'][h]['Pref.Ori.']
5090+
try:
5091+
intval = int(newValue)
5092+
except:
5093+
intval = None
5094+
if intval == 1:
5095+
self.data['Histograms'][h]['Pref.Ori.'][0] = 'MD'
5096+
elif intval is not None and 2*int(intval//2) == intval:
5097+
SGData = self.data['General']['SGData']
5098+
cofNames = G2lat.GenSHCoeff(SGData['SGLaue'],'0',intval,False) #cylindrical & no M
5099+
5100+
self.data['Histograms'][h]['Pref.Ori.'][0] = 'SH'
5101+
self.data['Histograms'][h]['Pref.Ori.'][4] = intval
5102+
olddict = self.data['Histograms'][h]['Pref.Ori.'][5]
5103+
newdict = dict(zip(cofNames,len(cofNames)*[0.]))
5104+
# retain any old values in existing dict
5105+
newdict.update({i:olddict[i] for i in olddict if i in newdict})
5106+
self.data['Histograms'][h]['Pref.Ori.'][5] = newdict
5107+
else:
5108+
raise G2ScriptException(f'Preferred orientation value of {newValue} is invalid')
50795109
else:
50805110
print('unexpected action')
50815111

tests/test_scriptref.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,16 @@ def testR(msg,w1,w2):
7373
h2.set_refinements({'Instrument Parameters': ['U', 'V', 'W']})
7474
gpx.refine()
7575
testR('add UVW',10.785432, 4.130126)
76+
# change to Spherical Harmonics, order=2 for the 1st histogram & refine
77+
phase0.HAPvalue('PO',2,[h1])
78+
phase0.set_HAP_refinements({"Pref.Ori.":True})
79+
gpx.refine()
80+
POdict = phase0.HAPvalue('PO',targethistlist=[h1])[5]
81+
print('Spherical harmonics values:',POdict)
82+
npt.assert_allclose((POdict['C(2,0)'],POdict['C(2,2)']),
83+
[0.1171084051086,0.11462063648716], rtol=0.001)
84+
testR('add PO',10.496639, 4.128754)
85+
#
7686
print('OK')
7787

7888
if __name__ == '__main__':

0 commit comments

Comments
 (0)