Source code for pemtk.fit._plotters

# Additional plotting methods for pemtk.fitClass
#

import numpy as np
from pathlib import Path
from epsproc import matEleSelector, plotTypeSelector


#******************* Wrappers for some ePSproc plotting routines


[docs]def BLMfitPlot(self, keys = None, dataType='AFBLM', Etype='t', thres=1e-2, col=None, **kwargs): """ Wrap BLMplot for data + simulation results with default params. TODO: - better plotting (HV?). - fix legend & colour mapping. """ if keys is None: keys = [self.subKey] # Default to subset data # Add current fit results # if self.fitInd-1 >= 0: # keys.append(self.fitInd-1) # 12/09/22 - use self._getFitInds(), more robust. fitInd,_ = self._getFitInds() if fitInd is not None: keys.append(fitInd) if keys is 'all': keys = [self.subKey] keys.append(list(range(0, self.fitInd))) # Plot all fits # # Check keys OK - not required since BLMplot() will check this # keys = self._keysCheck(keys) # # print(keys) # super().BLMplot(keys=keys, dataType=dataType, thres = thres, Etype=Etype) # In this case renamed function to avoid messing up other routines using BLMplot # self.BLMplot(keys=keys, dataType=dataType, thres = thres, Etype=Etype, col=col, **kwargs) # Pass all keys - single plot, same parameters # Quick hack for marker types for key in keys: # print(key) if key is self.subKey: self.BLMplot(keys=key, dataType=dataType, thres = thres, Etype=Etype, col=col, marker = 'x', linestyle = 'dashed', **kwargs) else: self.BLMplot(keys=key, dataType=dataType, thres = thres, Etype=Etype, col=col, **kwargs)
[docs]def lmPlotFit(self, keys = None, dataType='AFBLM', Etype='t', thres=1e-2, **kwargs): """ Wrap lmPlot for data + simulation results with default params. """ if keys is None: keys = [self.subKey] # Default to subset data # Add current fit results # if self.fitInd-1 >= 0: # keys.append(self.fitInd-1) # 12/09/22 - use self._getFitInds(), more robust. fitInd,_ = self._getFitInds() if fitInd is not None: keys.append(fitInd) self.lmPlot(keys = keys, dataType=dataType, Etype=Etype, thres=thres, **kwargs)
#*********************** General plotters
[docs]def BLMsetPlot(self, key = 'fits', dataDict = 'AFxr', agg = True, ref = True, overlay = ['l','m'], pType = 'r', thres = 1e-3, sel = None, xDim = None, sq = True, drop = True, unstack = True, plotDict = 'plots'): """ Plot sets of BLM results from Xarray datasets with Holoviews. For plotting individual datasets with more control, see BLMfitPlot(). TODO: - add Seaborn plotting options. - Streamline, should be able to use recursively to stack additional plots...? Parameters ---------- agg : bool, default = True If True, define reduced data as hv.reduce(['Fit'], np.mean, spreadfn=np.std) NOTE: if False, rendering can be quite slow for large datasets. TODO: more options here. ref : bool, default = True If True, include original fitted data in plots. TODO: more options here. """ # TODO: add dim handling + global selectors options (e.g. 'redchiGroup') # Set xDims to sensible defaults if possible (ensures consistent selection behaviour) # if xDim is None: # if 't' in # Reduce data & subselect Xarray using matEleSelector functionality dataRed = matEleSelector(self.data[key][dataDict], thres = thres, inds = sel, dims = xDim, sq = sq, drop=drop) # May be required depending on dataType and package versions. if unstack: dataRed = dataRed.unstack() # Set plot data type daPlot = plotTypeSelector(dataRed, pType = pType, axisUW = xDim) hvDS = self.hv.Dataset(daPlot.rename('BLM')) # TODO: pull name from dataset? # SET HV Dataset & plot objects (or use .hvplot?) if agg: hvDS = hvDS.reduce(['Fit'], np.mean, spreadfn=np.std) # Spread over fits + inputs with marker hvPlot = hvDS.to(self.hv.Spread, kdims = xDim).overlay(overlay) else: # Basic line plots hvPlot = hvDS.to(self.hv.Curve, kdims = xDim).overlay(overlay) # Set ref data - currently use input data only here if ref: # dataRef = self.data[key][dataDict] # dataRef = self.data[self.subKey]['AFBLM'] dataRef = matEleSelector(self.data[self.subKey]['AFBLM'], thres = thres, inds = sel, dims = xDim, sq = sq, drop=drop) if unstack: dataRef = dataRef.unstack() dataRef = plotTypeSelector(dataRef, pType = pType, axisUW = xDim) refDS = self.hv.Dataset(dataRef.rename('BLM-ref')) # TODO: pull name from dataset? # Add to plot object refPlot = refDS.to(self.hv.Curve, kdims = xDim).opts(line_dash='dashed') * refDS.to(self.hv.Scatter, kdims = xDim).opts(marker='cross', size=15) # Ugly... but need to ensure matching dims. May be a neater way to force/check this. # if agg: # hvPlot = (hvPlot * refPlot).overlay(overlay) # else: # hvPlot = hvPlot * refPlot.overlay(overlay) hvPlot = hvPlot * refPlot.overlay(overlay) # Now fixed, but may be slow for multiple Fit case - overlay ordering may matter here? # if overlay: # hvPlot = hvPlot.overlay(overlay) # This fails on Fits if refDS is set, since it's an unmatched dim. But OK if set independently for both datasets, and overlay([]) just passes. # Set output if not plotDict in self.data.keys(): self.data[plotDict] = {} self.data[plotDict]['BLMsetData'] = hvDS self.data[plotDict]['BLMsetPlot'] = hvPlot if ref: self.data[plotDict]['BLMsetRef'] = refDS # Code from showPlot() if self.__notebook__: display(hvPlot) # If notebook, use display to push plot.
#************* Figure IO # from datetime import datetime as dt # timeString = dt.now()
[docs]def hvSave(self, key = 'plots', pTypes = None, outStem = None, outPath = None, outTypes = ['png', 'html']): """ Wrapper for quick plot save routine from data dict. If data is a HV object, set key=None to save directly Update: removed this, since it's not very clear or useful (missing defaults). """ # Set stem for output file names if not passed if outStem is None: outStem = self.job['fileIn'].stem # Default path if outPath is None: outPath = self.job['fileBase'] # Force list if type(pTypes) is not list: pTypes = [pTypes] # Loop over pTypes and outTypes and write to file # if key is not None: for item in pTypes: for out in outTypes: saveFile = Path(outPath, self.setTimeStampedFileName(f'{outStem}_{item}',ext=out)) if self.verbose['main']: print(f'Saving self.data[{key}][{item}] to {saveFile}') # hvPlotters.hv.save(data.data[key][item], Path(outPath, f'{outStem}_{item}_{timeString.strftime("%d%m%y")}'), fmt=out) self.hv.save(self.data[key][item], saveFile, fmt=out) # else: # for out in outTypes: # hvPlotters.hv.save(data, Path(outPath, f'{outStem}_{item}'), fmt=out) return True