Skip to content

Commit 6c64f45

Browse files
committed
Add routines to save/restore limits on all plot axes; restore limits after refinement; fix reset of limits on w key; cleanup plot margins
1 parent 3dd616b commit 6c64f45

3 files changed

Lines changed: 92 additions & 33 deletions

File tree

GSASII/GSASIIdataGUI.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5538,6 +5538,8 @@ def OnRefine(self,event):
55385538
self.SaveTreeSetting() # save the current tree selection
55395539
self.GPXtree.SaveExposedItems() # save the exposed/hidden tree items
55405540
if self.PatternId and self.GPXtree.GetItemText(self.PatternId).startswith('PWDR '):
5541+
# true when a pattern is selected for plotting, which includes
5542+
# when a group is selected.
55415543
refPlotUpdate = G2pwpl.PlotPatterns(self,refineMode=True) # prepare for plot updating
55425544
else:
55435545
refPlotUpdate = None
@@ -9182,7 +9184,7 @@ def OnShowShift(event):
91829184
# if GSASIIpath.GetConfigValue('debug'):
91839185
# print('Debug: reloading',G2gr)
91849186
# from importlib import reload
9185-
# reload(G2G)
9187+
# reload(G2pwpl)
91869188
# reload(G2gr)
91879189
G2gr.UpdateGroup(G2frame,item)
91889190
elif GSASIIpath.GetConfigValue('debug'):

GSASII/GSASIIplot.py

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,7 @@ def __init__(self,parent,id=-1,G2frame=None):
325325
self.allowZoomReset = True # this indicates plot should be updated not initialized
326326
# (BHT: should this be in tabbed panel rather than here?)
327327
self.lastRaisedPlotTab = None
328+
self.savedPlotLims = None
328329

329330
def OnNotebookKey(self,event):
330331
'''Called when a keystroke event gets picked up by the notebook window
@@ -395,7 +396,7 @@ def GetTabIndex(self,label):
395396
# if plotNum is not None:
396397
# wx.CallAfter(self.SetSelectionNoRefresh,plotNum)
397398

398-
def FindPlotTab(self,label,Type,newImage=True):
399+
def FindPlotTab(self,label,Type,newImage=True,saveLimits=False):
399400
'''Open a plot tab for initial plotting, or raise the tab if it already exists
400401
Set a flag (Page.plotInvalid) that it has been redrawn
401402
Record the name of the this plot in self.lastRaisedPlotTab
@@ -409,6 +410,8 @@ def FindPlotTab(self,label,Type,newImage=True):
409410
410411
:param bool newImage: forces creation of a new graph for matplotlib
411412
plots only (defaults as True)
413+
:param bool saveLimits: When True, limits for all MPL axes (plots)
414+
are saved in self.savedPlotLims.
412415
:returns: new,plotNum,Page,Plot,limits where
413416
414417
* new: will be True if the tab was just created
@@ -417,15 +420,17 @@ def FindPlotTab(self,label,Type,newImage=True):
417420
the plot appears
418421
* Plot: the mpl.Axes object for the graphic (mpl) or the figure for
419422
openGL.
420-
* limits: for mpl plots, when a plot already exists, this will be a tuple
421-
with plot scaling. None otherwise.
423+
* limits: for mpl plots, when a plot already exists, this
424+
will be a tuple with plot scaling. None otherwise. Only appropriate
425+
for plots with one set of axes.
422426
'''
423427
limits = None
424428
Plot = None
425429
try:
426430
new = False
427431
plotNum,Page = self.GetTabIndex(label)
428432
if Type == 'mpl' or Type == '3d':
433+
if saveLimits: self.savePlotLims(Page)
429434
Axes = Page.figure.get_axes()
430435
Plot = Page.figure.gca() #get previous plot
431436
limits = [Plot.get_xlim(),Plot.get_ylim()] # save previous limits
@@ -469,6 +474,46 @@ def FindPlotTab(self,label,Type,newImage=True):
469474
Page.toolbar.enableArrows() # Disable Arrow keys if present
470475
return new,plotNum,Page,Plot,limits
471476

477+
def savePlotLims(self,Page):
478+
'''Make a copy of all the current axes in the notebook object
479+
'''
480+
self.savedPlotLims = [
481+
[i.get_xlim() for i in Page.figure.get_axes()],
482+
[i.get_ylim() for i in Page.figure.get_axes()]]
483+
#print(f'saved {len(self.savedPlotLims[1])} axes limits')
484+
485+
def restoreSavedPlotLims(self,Page):
486+
'''Restore the plot limits, when previously saved, and when
487+
``G2frame.restorePlotLimits`` is set to True, which
488+
is done when ``GSASIIpwdplot.refPlotUpdate`` is called with
489+
``restore=True``, which indicates that "live plotting" is done.
490+
The restore operation can only be done once, as the limits
491+
are deleted after use in this method.
492+
'''
493+
if self.savedPlotLims is None:
494+
#print('---- nothing to restore')
495+
return
496+
if not hasattr(self.G2frame,'restorePlotLimits'):
497+
#print('---- restorePlotLimits not set')
498+
return
499+
if not self.G2frame.restorePlotLimits:
500+
#print('---- restorePlotLimits: not yet')
501+
return
502+
savedPlotLims = self.savedPlotLims
503+
axesList = Page.figure.get_axes()
504+
if len(axesList) != len(savedPlotLims[0]):
505+
#print('saved lengths differ',len(axesList),len(savedPlotLims[0]))
506+
return
507+
for i,ax in enumerate(axesList):
508+
ax.set_xlim(savedPlotLims[0][i])
509+
ax.set_ylim(savedPlotLims[1][i])
510+
#print(i,
511+
# savedPlotLims[0][i][0],savedPlotLims[0][i][1],
512+
# savedPlotLims[1][i][0],savedPlotLims[1][i][1])
513+
self.savedPlotLims = None
514+
self.G2frame.restorePlotLimits = False
515+
Page.canvas.draw()
516+
472517
def _addPage(self,name,page):
473518
'''Add the newly created page to the notebook and associated lists.
474519

GSASII/GSASIIpwdplot.py

Lines changed: 41 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -121,20 +121,6 @@ def ReplotPattern(G2frame,newPlot,plotType,PatternName=None,PickName=None):
121121
G2frame.Extinct = [] # array of extinct reflections
122122
PlotPatterns(G2frame,plotType=plotType)
123123

124-
def plotVline(Page,Plot,Lines,Parms,pos,color,pickrad,style='dotted'):
125-
'''shortcut to plot vertical lines for limits & Laue satellites.
126-
Was used for extrapeaks'''
127-
if not pickrad: pickrad = 0.0
128-
if Page.plotStyle['qPlot']:
129-
Lines.append(Plot.axvline(2.*np.pi/G2lat.Pos2dsp(Parms,pos),color=color,
130-
picker=pickrad,linestyle=style))
131-
elif Page.plotStyle['dPlot']:
132-
Lines.append(Plot.axvline(G2lat.Pos2dsp(Parms,pos),color=color,
133-
picker=pickrad,linestyle=style))
134-
else:
135-
Lines.append(Plot.axvline(pos,color=color,
136-
picker=pickrad,linestyle=style))
137-
138124
def PlotPatterns(G2frame,newPlot=False,plotType='PWDR',data=None,
139125
extraKeys=[],refineMode=False,indexFrom='',fromTree=False):
140126
'''Powder pattern plotting package - displays single or multiple powder
@@ -209,7 +195,7 @@ def OnPlotKeyPress(event):
209195
G2frame.SinglePlot = True
210196
elif 'PWDR' in plottype: # Turning on Weight plot clears previous limits
211197
G2frame.FixedLimits['dylims'] = ['','']
212-
newPlot = True
198+
#newPlot = True # this resets the x & y limits, not wanted!
213199
elif event.key in ['shift+1','!']: # save current plot settings as defaults
214200
# shift+1 assumes US keyboard
215201
print('saving plotting defaults for',G2frame.GPXtree.GetItemText(G2frame.PatternId))
@@ -1501,15 +1487,19 @@ def onPlotFormat(event):
15011487
def refPlotUpdate(Histograms,cycle=None,restore=False):
15021488
'''called to update an existing plot during a Rietveld fit; it only
15031489
updates the curves, not the reflection marks or the legend.
1504-
It should be called with restore=True to reset plotting
1505-
parameters after the refinement is done.
1490+
After the refinement is complete it is called with restore=True to
1491+
reset plotting parameters.
15061492
1507-
Note that the Page.plotStyle values are stashed in G2frame
1508-
to be restored later
1493+
Note that the ``Page.plotStyle`` values are stashed in
1494+
``G2frame.savedPlotStyle`` to be restored after FindPlotTab is
1495+
called and ``G2frame.restorePlotLimits`` is set so that
1496+
saved plot limits will be applied when
1497+
``G2frame.G2plotNB.restoreSavedPlotLims`` is called.
15091498
'''
15101499
if restore:
15111500
(G2frame.SinglePlot,G2frame.Contour,G2frame.Weight,
15121501
G2frame.plusPlot,G2frame.SubBack,G2frame.savedPlotStyle) = savedSettings
1502+
G2frame.restorePlotLimits = True
15131503
return
15141504

15151505
if plottingItem not in Histograms:
@@ -1724,11 +1714,15 @@ def drawTicks(Phases,phaseList,group=False):
17241714
picker=3.,
17251715
label='_FLT_'+phase,lw=0.5)
17261716

1727-
# Callback used to update y-limits when user zooms interactively (MG/Cl Sonnet)
1717+
# Callback used to update y-limits when user zooms interactively (from MG/Cl Sonnet)
17281718
def onGroupXlimChanged(ax):
1729-
'''Callback to update y-limits for all panels when x-range changes.
1719+
'''Callback to update y-limits for all panels in group plot when x-range changes.
17301720
We calculate the global y-range across all panels for the visible x-range,
17311721
then explicitly set y-limits on ALL panels.
1722+
1723+
This currently allows the y-limit to be set manually for one plot. If
1724+
a second one is changed, the previous manual change is lost.
1725+
I wonder if we can identify which plots have manual changes.
17321726
'''
17331727
xlim = ax.get_xlim()
17341728
# Save x-limits for persistence across refinements
@@ -1831,10 +1825,11 @@ def onGroupXlimChanged(ax):
18311825
publish = None
18321826
if G2frame.Contour: publish = None
18331827

1834-
new,plotNum,Page,Plot,limits = G2frame.G2plotNB.FindPlotTab('Powder Patterns','mpl')
1828+
new,plotNum,Page,Plot,limits = G2frame.G2plotNB.FindPlotTab(
1829+
'Powder Patterns','mpl',saveLimits=refineMode)
18351830
if hasattr(G2frame, 'savedPlotStyle'):
18361831
Page.plotStyle.update(G2frame.savedPlotStyle)
1837-
del G2frame.savedPlotStyle # do this only once
1832+
del G2frame.savedPlotStyle # do this only once & after Page is defined
18381833
Page.toolbar.setPublish(publish)
18391834
Page.toolbar.arrows['_groupMode'] = None
18401835
# if we are changing histogram types (including group to individual, reset plot)
@@ -2338,13 +2333,12 @@ def onGroupXlimChanged(ax):
23382333
right=.99,top=1.-3/200.,hspace=0,wspace=0)
23392334

23402335
# Connect callback for all panels when sharedX is enabled
2336+
up,down = adjustDim(0,Page.groupN)
23412337
if (plotOpt['sharedX'] and
23422338
(Page.plotStyle['qPlot'] or Page.plotStyle['dPlot'])):
2343-
up, down = adjustDim(0, Page.groupN)
23442339
Plots[up].callbacks.connect('xlim_changed', onGroupXlimChanged)
23452340

23462341
# pretty up the tick labels
2347-
up,down = adjustDim(0,Page.groupN)
23482342
Plots[up].tick_params(axis='y', direction='inout', left=True, right=True)
23492343
Plots[down].tick_params(axis='y', direction='inout', left=True, right=True)
23502344
if Page.groupN > 1:
@@ -2479,7 +2473,8 @@ def onGroupXlimChanged(ax):
24792473
up,down = adjustDim(0,Page.groupN)
24802474
G2frame.groupXlim = Plots[up].get_xlim()
24812475
Page.canvas.draw()
2482-
return
2476+
wx.CallLater(100,G2frame.G2plotNB.restoreSavedPlotLims,Page) # restore limits to previous, if saved
2477+
return # end of group plot
24832478
elif G2frame.Weight and not G2frame.Contour:
24842479
Plot.set_visible(False) #hide old plot frame, will get replaced below
24852480
GS_kw = {'height_ratios':[4, 1],}
@@ -2489,10 +2484,10 @@ def onGroupXlimChanged(ax):
24892484
# Plot,Plot1 = MPLsubplots(Page.figure, 2, 1, sharex=True, gridspec_kw=GS_kw)
24902485
Plot1.set_ylabel(r'$\mathsf{\Delta(I)/\sigma(I)}$',fontsize=16)
24912486
Plot1.set_xlabel(xLabel,fontsize=16)
2492-
Page.figure.subplots_adjust(left=16/100.,bottom=16/150.,
2493-
right=.98,top=1.-16/200.,hspace=0)
24942487
else:
24952488
Plot.set_xlabel(xLabel,fontsize=16)
2489+
Page.figure.subplots_adjust(left=8/100.,bottom=16/150.,
2490+
right=.98,top=1.-8/100.,hspace=0,wspace=0)
24962491
if not G2frame.Contour:
24972492
Page.toolbar.enableArrows('',(PlotPatterns,G2frame))
24982493
if G2frame.Weight and G2frame.Contour:
@@ -3293,7 +3288,10 @@ def onGroupXlimChanged(ax):
32933288
G2frame.dataWindow.moveTickSpc.Enable(True)
32943289
if DifLine[0]:
32953290
G2frame.dataWindow.moveDiffCurve.Enable(True)
3296-
if refineMode: return refPlotUpdate
3291+
if refineMode:
3292+
return refPlotUpdate
3293+
else:
3294+
wx.CallLater(100,G2frame.G2plotNB.restoreSavedPlotLims,Page) # restore limits to previous, if saved
32973295

32983296
def PublishRietveldPlot(G2frame,Pattern,Plot,Page,reuse=None):
32993297
'''Creates a window to show a customizable "Rietveld" plot. Exports that
@@ -4810,3 +4808,17 @@ def StyleChange(*args):
48104808
mainSizer.Fit(dlg)
48114809
dlg.ShowModal()
48124810
StyleChange()
4811+
4812+
def plotVline(Page,Plot,Lines,Parms,pos,color,pickrad,style='dotted'):
4813+
'''shortcut to plot vertical lines for limits & Laue satellites.
4814+
Was used for extrapeaks'''
4815+
if not pickrad: pickrad = 0.0
4816+
if Page.plotStyle['qPlot']:
4817+
Lines.append(Plot.axvline(2.*np.pi/G2lat.Pos2dsp(Parms,pos),color=color,
4818+
picker=pickrad,linestyle=style))
4819+
elif Page.plotStyle['dPlot']:
4820+
Lines.append(Plot.axvline(G2lat.Pos2dsp(Parms,pos),color=color,
4821+
picker=pickrad,linestyle=style))
4822+
else:
4823+
Lines.append(Plot.axvline(pos,color=color,
4824+
picker=pickrad,linestyle=style))

0 commit comments

Comments
 (0)