Skip to content

Commit 19ff6c3

Browse files
committed
As suggested by Bob, change post-refinement table to delta/sigma and add plotting when a parameter has been saved. Done with #228
1 parent 2bf22ff commit 19ff6c3

File tree

3 files changed

+92
-110
lines changed

3 files changed

+92
-110
lines changed

GSASII/GSASIIctrlGUI.py

Lines changed: 81 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -2610,29 +2610,90 @@ def G2MessageBox(parent,msg,title='Error'):
26102610
dlg.Destroy()
26112611

26122612
################################################################################
2613+
def findValsInNotebook(data,target):
2614+
'Pull a string of values from saved values in the GSAS-II notebook'
2615+
c = 0
2616+
vals = []
2617+
pos = []
2618+
for l in data:
2619+
if '[REF]' in l: c += 1
2620+
if '[VALS]' in l:
2621+
v = {i.split(' : ')[0].strip() : i.split(' : ')[1]
2622+
for i in l[6:].split(',')}
2623+
if target not in v:
2624+
continue
2625+
try:
2626+
vals.append(float(v[target]))
2627+
pos.append(c)
2628+
except:
2629+
pass
2630+
if '[CEL]' in l:
2631+
ph = l.split('Phase')[1].split()[0]
2632+
hst = l.split('Hist')[1].split(':')[0].strip()
2633+
vars = [i.split('=')[0] for i in l.split(':')[1].split()]
2634+
vars = [f'{v}[p{ph}_h{hst}]' for v in vars]
2635+
if target not in vars: continue
2636+
values = [i.split('=')[1].split('(')[0] for i in l.split(':')[1].split()]
2637+
try:
2638+
vals.append(float(dict(zip(vars,values))[target]))
2639+
pos.append(c)
2640+
except:
2641+
pass
2642+
return pos,vals
2643+
26132644
def G2AfterFit(parent,msg,title='Error',vartbl=[],txtwidth=300):
26142645
'''Shows the results from a refinement
26152646
26162647
:param wx.Frame parent: pointer to parent of window, usually G2frame
26172648
:param str msg: text from refinement results
26182649
:param str title: text to label window
26192650
:param list vartbl: a list of lists. The contents of each inner list
2620-
item will be [var-name, val-before, val-after, meaning]
2651+
item will be [var-name, val-before, val-after, sigma, meaning]
26212652
:param int txtwidth: width (in pixesl) to display msg. Defaults to 300
26222653
'''
2623-
2624-
displayTable = [ # create table to show from input
2625-
(var,
2626-
f'{before:.6g}',
2627-
f'{after:.6g}',
2628-
f'{after-before:.6g}',
2629-
what) for (var,before,after,what) in vartbl]
2630-
labels = ('var','before','after','change','parameter description')
2631-
just = (0 , 1 , 1 , 1 , 0)
2654+
def OnRowSelected(event):
2655+
'''plot the parameter results if it has been recorded
2656+
this is called when one clicks on a row in the parameter table
2657+
'''
2658+
row = event.GetIndex()
2659+
var = results.list.GetItemText(row)
2660+
val = valDict.get(var)
2661+
G2frame = wx.App.GetMainTopWindow()
2662+
G2frame.G2plotNB.Delete('fit results')
2663+
if val is None: return
2664+
nId = G2gd.GetGPXtreeItemId(G2frame,G2frame.root, 'Notebook')
2665+
if not nId: return
2666+
Notebook = G2frame.GPXtree.GetItemPyData(nId)
2667+
pos,vals = findValsInNotebook(Notebook,var)
2668+
if len(pos) < 2: return
2669+
pos.append(pos[-1]+1)
2670+
try:
2671+
vals.append(float(val))
2672+
except:
2673+
return
2674+
XY = [np.array(pos),np.array(vals)]
2675+
from . import GSASIIplot as G2plt
2676+
G2plt.PlotXY(G2frame,[XY,],Title='fit results',newPlot=True,
2677+
labelX='seq',labelY=var,lines=True)
2678+
# create table to show from input
2679+
displayTable = []
2680+
valDict = {}
2681+
for (var,before,after,sig,what) in vartbl:
2682+
valDict[var] = after # save lookup table of values
2683+
try:
2684+
d = f'{(after-before)/sig:.3g}'
2685+
b = G2mth.ValEsd(before,-abs(sig)/10,True)
2686+
a = G2mth.ValEsd(after,-abs(sig)/10,True)
2687+
except:
2688+
d = '0'
2689+
b = f'{before:.6g}'
2690+
a = f'{after:.6g}'
2691+
displayTable.append((var,b,a,d,what))
2692+
labels = ('var','before','after','del/sig','parameter description')
2693+
just = (0 , 1 , 1 , 1 , 0) # 0 left, 1 right
26322694
dlg = wx.Dialog(parent.GetTopLevelParent(), wx.ID_ANY, title,
26332695
style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
26342696
mainSizer = wx.BoxSizer(wx.VERTICAL)
2635-
26362697
txtSizer = wx.BoxSizer(wx.HORIZONTAL)
26372698
txt = wx.StaticText(dlg,wx.ID_ANY,msg)
26382699
txt.Wrap(txtwidth-20)
@@ -2652,14 +2713,16 @@ def G2AfterFit(parent,msg,title='Error',vartbl=[],txtwidth=300):
26522713
results.SetInitialSortColumn(3,False)
26532714
results.SetClientSize((450,250))
26542715
results.SetMinSize((450,250))
2716+
results.Bind(wx.EVT_LIST_ITEM_SELECTED, OnRowSelected) # plot
26552717
else:
26562718
results = wx.BoxSizer(wx.VERTICAL)
26572719
results.Add((-1,-1),1,wx.EXPAND)
2658-
results.Add(wx.StaticText(dlg,wx.ID_ANY,' (no parameter changes\nto display) ',size=(350,-1),style=wx.ALIGN_CENTER))
2720+
results.Add(wx.StaticText(dlg,wx.ID_ANY,
2721+
' (no parameter changes\nto display) ',
2722+
size=(350,-1),style=wx.ALIGN_CENTER))
26592723
results.Add((-1,-1),1,wx.EXPAND)
26602724
txtSizer.Add(results,1,wx.EXPAND,0)
26612725
mainSizer.Add(txtSizer,1,wx.EXPAND)
2662-
26632726
mainSizer.Add((-1,5))
26642727
txt = wx.StaticText(dlg,wx.ID_ANY,'Load new result?')
26652728
mainSizer.Add(txt,0,wx.CENTER)
@@ -2680,8 +2743,6 @@ def G2AfterFit(parent,msg,title='Error',vartbl=[],txtwidth=300):
26802743
ans = dlg.ShowModal()
26812744
dlg.Destroy()
26822745
return ans
2683-
#ans = dlg.Show()
2684-
#breakpoint()
26852746

26862747
def ShowScrolledInfo(parent,txt,width=600,height=400,header='Warning info',
26872748
buttonlist=None):
@@ -7786,57 +7847,13 @@ def SetColWidth(self,col,width=None,auto=True,minwidth=0,maxwidth=None,
77867847
def SetInitialSortColumn(self, col, ascending=True):
77877848
'''Sets the initial column to be used for sorting when the table is first displayed.
77887849
This method should be called after all PopulateLine calls are complete.
7850+
The up or down arrow indicator will be displayed on the specified column.
77897851
77907852
:param int col: the column index (0-based) to sort by initially
77917853
:param bool ascending: if True (default), sort in ascending order; if False, descending
77927854
'''
7793-
# Get the sort function
7794-
sorter = self.list.GetColumnSorter()
7795-
7796-
# Get all keys from itemDataMap
7797-
keys = list(self.list.itemDataMap.keys())
7798-
7799-
# Sort the keys using the comparison function
7800-
from functools import cmp_to_key
7801-
7802-
def make_cmp(col_idx, asc):
7803-
"""Create a comparison function for the given column"""
7804-
def cmp_func(key1, key2):
7805-
data1 = self.list.itemDataMap[key1][col_idx]
7806-
data2 = self.list.itemDataMap[key2][col_idx]
7807-
7808-
# For columns designated as self.AbsFloatCols, sort by absolute numerical value
7809-
if col_idx in self.list.AbsFloatCols:
7810-
try:
7811-
val1 = abs(float(data1))
7812-
val2 = abs(float(data2))
7813-
result = (val1 > val2) - (val1 < val2)
7814-
except (ValueError, TypeError):
7815-
result = (data1 > data2) - (data1 < data2)
7816-
elif col_idx in self.list.FloatCols:
7817-
try:
7818-
val1 = float(data1)
7819-
val2 = float(data2)
7820-
result = (val1 > val2) - (val1 < val2)
7821-
except (ValueError, TypeError):
7822-
result = (data1 > data2) - (data1 < data2)
7823-
else:
7824-
# For other columns, use string comparison
7825-
result = (data1 > data2) - (data1 < data2)
7826-
7827-
return result if asc else -result
7828-
return cmp_func
7829-
7830-
sorted_keys = sorted(keys, key=cmp_to_key(make_cmp(col, ascending)))
7831-
7832-
# Rebuild the list in sorted order
7833-
self.list.DeleteAllItems()
7834-
for key in sorted_keys:
7835-
data = self.list.itemDataMap[key]
7836-
index = self.list.InsertItem(self.list.GetItemCount(), data[0])
7837-
for i, d in enumerate(data[1:]):
7838-
self.list.SetItem(index, i+1, d)
7839-
self.list.SetItemData(index, key)
7855+
# Use SortListItems to both sort the items and display the sort indicator arrow
7856+
self.list.SortListItems(col, ascending)
78407857

78417858
try:
78427859
class G2LstCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.ColumnSorterMixin):
@@ -7867,10 +7884,10 @@ def __init__(self, parent, ID=wx.ID_ANY, pos=wx.DefaultPosition,
78677884
def GetListCtrl(self): # needed for sorting
78687885
return self
78697886
def GetSortImages(self):
7870-
#return (self.parent.DownArrow, self.parent.UpArrow)
78717887
return (self.DownArrow, self.UpArrow)
78727888
def GetColumnSorter(self):
7873-
"""Custom sorter that handles absolute numerical values for columns 1, 2, 3 (2nd, 3rd, 4th columns)"""
7889+
"""Custom sorter that handles absolute numerical values for columns 1, 2,
7890+
and 3 (2nd, 3rd, 4th columns)"""
78747891
def compare_func(key1, key2):
78757892
col = self.GetSortState()[0]
78767893
ascending = self.GetSortState()[1]

GSASII/GSASIIdataGUI.py

Lines changed: 10 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -5553,33 +5553,24 @@ def OnRefine(self,event):
55535553
' minimum may not have been reached or your result may be a false minimum.'+
55545554
' You should reconsider which parameters you refine: check covariance matrix.\n')
55555555
#breakpoint()
5556-
tbl = [] # assemble a list of changed parameters
5556+
tbl = [] # assemble a list of varied parameters
55575557
for i in Rvals.get('parmDictAfterFit',{}):
55585558
if i not in Rvals['parmDictBeforeFit']: continue
5559-
try:
5560-
mag = max(abs(Rvals['parmDictAfterFit'][i]),
5561-
abs(Rvals['parmDictBeforeFit'][i]))
5562-
diff = abs(Rvals['parmDictAfterFit'][i]-Rvals['parmDictBeforeFit'][i])
5563-
if mag < 1e-5 and diff < 1e-7: continue
5564-
if diff/mag < 1e-5: continue
5559+
if i not in Rvals['parmDictSigDict']: continue
5560+
try: # make ure we have valid numbers
5561+
diff = ((Rvals['parmDictAfterFit'][i]-
5562+
Rvals['parmDictBeforeFit'][i])
5563+
/ Rvals['parmDictSigDict'][i])
55655564
except:
55665565
continue
55675566
txt = '?'
55685567
v = G2obj.getVarDescr(i)
55695568
if v is not None and v[-1] is not None:
55705569
txt = G2obj.fmtVarDescr(i)
5571-
tbl.append((i,Rvals['parmDictBeforeFit'][i],Rvals['parmDictAfterFit'][i],txt))
5570+
tbl.append((i,Rvals['parmDictBeforeFit'][i],Rvals['parmDictAfterFit'][i],
5571+
Rvals['parmDictSigDict'].get(i),txt))
55725572
lbl = f'Refinement results, Rw={Rw:.3f}'
55735573
ans = G2G.G2AfterFit(self,text,lbl,tbl) # this replaces the next 8 lines
5574-
# text += '\nLoad new result?'
5575-
# dlg2 = wx.MessageDialog(self,text,lbl,wx.OK|wx.CANCEL)
5576-
# dlg2.CenterOnParent()
5577-
# ans = False
5578-
# try:
5579-
# ans = dlg2.ShowModal()
5580-
# finally:
5581-
# dlg2.Destroy()
5582-
# replace above with G2G.G2AfterFit line
55835574
if ans == wx.ID_OK: # refinement has been accepted save, log & display
55845575
self.reloadFromGPX(rtext,Rvals)
55855576
G2IO.LogCellChanges(self)
@@ -5593,7 +5584,7 @@ def OnRefine(self,event):
55935584
txt += (f'{i} : {Rvals["parmDictAfterFit"][i]:.7g}')
55945585
elif GSASIIpath.GetConfigValue('LogAllVars') and 'parmDictAfterFit' in Rvals:
55955586
txt = ''
5596-
for c,i in enumerate(Rvals['parmDictvaryList']):
5587+
for c,i in enumerate(Rvals['parmDictSigDict']):
55975588
if i not in Rvals['parmDictAfterFit']: continue
55985589
if txt: txt += ', '
55995590
txt += (f'{i} : {Rvals["parmDictAfterFit"][i]:.7g}')
@@ -7603,33 +7594,7 @@ def onPlotNotebook():
76037594
if target == 'none':
76047595
G2frame.G2plotNB.Delete('fit results')
76057596
return
7606-
c = 0
7607-
vals = []
7608-
pos = []
7609-
for l in data:
7610-
if '[REF]' in l: c += 1
7611-
if '[VALS]' in l:
7612-
v = {i.split(' : ')[0].strip() : i.split(' : ')[1]
7613-
for i in l[6:].split(',')}
7614-
if target not in v:
7615-
continue
7616-
try:
7617-
vals.append(float(v[target]))
7618-
pos.append(c)
7619-
except:
7620-
pass
7621-
if '[CEL]' in l:
7622-
ph = l.split('Phase')[1].split()[0]
7623-
hst = l.split('Hist')[1].split(':')[0].strip()
7624-
vars = [i.split('=')[0] for i in l.split(':')[1].split()]
7625-
vars = [f'{v}[p{ph}_h{hst}]' for v in vars]
7626-
if target not in vars: continue
7627-
values = [i.split('=')[1].split('(')[0] for i in l.split(':')[1].split()]
7628-
try:
7629-
vals.append(float(dict(zip(vars,values))[target]))
7630-
pos.append(c)
7631-
except:
7632-
pass
7597+
pos,vals = G2G.findValsInNotebook(data,target)
76337598
X = np.array(pos)
76347599
Y = np.array(vals)
76357600
if len(Y) == 0:

GSASII/GSASIIstrMain.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -644,7 +644,7 @@ def Refine(GPXfile,dlg=None,makeBack=True,refPlotUpdate=None,newLeBail=False,all
644644
Rvals['varyList'] = 'Varied: ' + ', '.join(varyList)
645645
Rvals['parmDictBeforeFit'] = parmDictBefore
646646
Rvals['parmDictAfterFit'] = copy.deepcopy(parmDict)
647-
Rvals['parmDictvaryList'] = copy.copy(varyList)
647+
Rvals['parmDictSigDict'] = dict(zip(varyList,sig))
648648
s = G2mv.VarRemapSumm()
649649
if s: Rvals['contrSumm'] = f'Constraints: {s}'
650650
Rvals['restrSumm'] = G2stIO.SummRestraints(restraintDict)

0 commit comments

Comments
 (0)