# ICE Revision: $Id: GeneralPlotTimelines.py,v 3f8df529776e 2020-02-28 20:07:20Z bgschaid $
"""Plots a collection of timelines. General superclass for te other implementations"""
from PyFoam.Basics.CustomPlotInfo import readCustomPlotInfo,CustomPlotInfo
from PyFoam.Error import notImplemented
from PyFoam.ThirdParty.six import iteritems
import re
[docs]class PlotLinesRegistry(object):
"""Collects references to GeneralPlotLines objects"""
nr=1
def __init__(self):
self.plots={}
[docs] def clear(self):
PlotLinesRegistry.nr=1
self.plots={}
[docs] def add(self,plot):
nr=PlotLinesRegistry.nr
PlotLinesRegistry.nr+=1
self.plots[nr]=plot
return nr
[docs] def prepareForTransfer(self):
"""Makes sure that the data about the plots is to be transfered via XMLRPC"""
lst={}
for i,p in iteritems(self.plots):
lst[str(i)]={ "nr" : i,
"spec" : p.spec.getDict(),
"id" : p.spec.id,
"data" : p.data.lineNr }
return lst
_allPlots=PlotLinesRegistry()
[docs]def allPlots():
return _allPlots
[docs]class GeneralPlotTimelines(object):
"""This class defines the interface for specific implementations of plotting
This class is moedelled after the Gnuplot-class from the Gnuplot-package"""
def __init__(self,
timelines,
custom,
showWindow=True,
registry=None):
""":param timelines: The timelines object
:type timelines: TimeLineCollection
:param custom: A CustomplotInfo-object. Values in this object usually override the
other options
:param showWindow: whether or not to show a window. Doesn't affect all implementations
"""
self.data = timelines
self.spec = custom
self._label_tags = {}
if self.spec.xvalue is not None:
self.data.is_parametric = True
self.alternate=getattr(self.spec,"alternateAxis",[])
self.forbidden=getattr(self.spec,"forbidden",[])
self.showWindow=showWindow
if registry==None:
registry=allPlots()
self.nr=registry.add(self)
[docs] def get_label_tag(self, name):
try:
return self._label_tags[name]
except KeyError:
if len(self._label_tags) == 0:
new_tag = 1
else:
new_tag = max(self._label_tags.values()) + 1
self._label_tags[name] = new_tag
return new_tag
[docs] def testAlternate(self,name):
if name in self.alternate:
return True
if name.find("-collector")>0 and re.compile(r".+-collector[0-9]*").match(name):
return self.testAlternate(name[:name.find("-collector")])
for a in self.alternate:
try:
try:
if re.compile(a).fullmatch(name):
return True
except AttributeError:
# python 2 has no fullmatch
if re.compile("(?:" + a + r")\Z").match(name):
return True
except re.error:
pass
return False
[docs] def getNames(self):
"""Get the names of the data items"""
names=[]
tmp=self.data.getValueNames()
for n in tmp:
addIt=True
for f in self.forbidden:
if n.find(f)>=0:
addIt=False
break
if addIt:
names.append(n)
return sorted(names)
[docs] def hasTimes(self):
"""Check whether this timeline contains any timesteps"""
return len(self.data.getTimes())>0
[docs] def hasData(self):
"""Check whether there is any plotable data"""
return self.hasTimes() and len(self.getNames())>0
[docs] def redo(self):
"""Replot the timelines"""
if not self.hasData():
return
self.preparePlot()
names = self.getNames()
times = []
for n in names:
if self.spec.xvalue is not None and self.spec.xvalue == n:
continue
title = n
collectorExtension = ""
if title.rfind("-collector") >= 0:
collectorExtension = title[title.rfind("-collector"):]
title = title[: title.rfind("-collector")]
collectorNr = int(n[n.rfind("-collector")+len("-collector"):])
lastValid = self.data.collectors[collectorNr].lastValid[title]
if self.spec.xvalue and self.spec.xvalue == title:
continue
else:
lastValid=self.data.lastValid[title]
if self.spec.xvalue:
times = self.data.getValues(self.spec.xvalue + collectorExtension)
else:
times = self.data.getTimes(title)
if self.spec.xvalue:
tag = self.get_label_tag(n + "_last")
else:
tag = None
self.buildData(times,n,title,lastValid, tag=tag)
if len(names)>0 and len(times)>0:
self.doReplot()
[docs] def buildData(self, times, name, title, lastValid, tag=None):
"""Build the implementation specific data
:param times: The vector of times for which data exists
:param name: the name under which the data is stored in the timeline
:param title: the title under which this will be displayed
:param lastValid: wether the last data entry is valid"""
notImplemented(self,"buildData")
[docs] def preparePlot(self):
"""Prepare the plotting window"""
notImplemented(self,"preparePlot")
[docs] def doReplot(self):
"""Replot the whole data"""
notImplemented(self,"doReplot")
[docs] def addVerticalMarker(self,colorRGB=None,label=None):
"""Add a vertical line to the graph at the current time. Optionally
color it and add a label"""
notImplemented(self,"addVerticalMarker")
[docs] def actualSetTitle(self,title):
"""Sets the title"""
notImplemented(self,"actualSetTitle")
[docs] def setTitle(self,title):
"""Sets the title"""
self.actualSetTitle(title)
self.spec.theTitle=title
[docs] def setYLabel(self,title):
"""Sets the label on the first Y-Axis"""
notImplemented(self,"setYLabel")
[docs] def setYLabel2(self,title):
"""Sets the label on the second Y-Axis"""
notImplemented(self,"setYLabel2")
[docs] def doHardcopy(self,filename,form,termOpts=None):
"""Write the contents of the plot to disk
:param filename: Name of the file without type extension
:param form: String describing the format"""
notImplemented(self,"doHardcopy")
# Should work with Python3 and Python2