Page MenuHomec4science

graphhelper.py
No OneTemporary

File Metadata

Created
Fri, May 31, 23:39

graphhelper.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# -*- py-which-shell: "python"; -*-
__all__ = [ "GraphHelper", "GraphParser" ]
import base
import run
import job
import runselector
import jobselector
import bdparser
##############################################
##Temp workaround for broken debian package ##
##############################################
#import matplotlib#############################
#matplotlib.use('Agg')#########################
##############################################
#import matplotlib.pyplot as plt
import re
import sys
import numpy as np
class GraphHelper(object):
"""
"""
def getMeasures(self,run_list):
myresults = []
add_req = []
if (self.frequency):
add_req += ["step %% {0} = 0".format(self.frequency)]
if (self.start):
add_req += ["step > {0}".format(self.start) ]
if (self.end):
add_req += ["step < {0}".format(self.end) ]
for r,j in run_list:
#print ("retrieve data from run " + r["run_name"])
res = r.getScalarQuantities(self.quantities,add_req)
for key , value in res:
if (value is None):
del res[key]
myresults.append([r,j,res])
return myresults
def selectGraphs(self):
# print 'AAAAAAAAA ' + self.binary_operator
run_list = self.runSelector.selectRuns(self.run_constraints,self.job_constraints,
self.sort_by,binary_operator=self.binary_operator)
results = self.getMeasures(run_list)
return results
def show(self):
import matplotlib.pyplot as plt
plt.show()
def makeGraphs(self,fig=None,**kwargs):
import matplotlib.pyplot as plt
results = self.selectGraphs()
if fig is None:
fig = plt.figure(figsize=self.figsize)
for r,j,data in results:
if data:
self.makeCurve(data,fig=fig,myrun=r,myjob=j,**kwargs)
return fig
def replaceRunAndJobsParameters(self,name,myrun,myjob):
res = name
# print (res)
codes = [["%r."+key,myrun[key]] for key in myrun.entries.keys()]
codes += [["%j."+key,myjob[key]] for key in myjob.entries.keys()]
for code,val in codes:
res = res.replace(code,str(val))
return res
def generateLabels(self,results,myrun,myjob):
labels = []
names = [r[0] for r in results]
for i in range(0,len(results)):
name = results[i][0]
if (not self.legend or i >= len(self.legend) or not self.legend[i]):
labels.append(self.replaceRunAndJobsParameters(name,myrun,myjob))
continue
# print (self.legend[i])
head_legend = self.legend[i].replace("{","{{")
head_legend = head_legend.replace("}","}}")
head_legend = re.sub(r"(%)([0-9]+)",r'{\2}',head_legend).format(*names)
# print (head_legend)
head_legend = self.replaceRunAndJobsParameters(head_legend,myrun,myjob)
# print (head_legend)
# if (not head_legend.find("%") == -1):
# print("unknown variable name. Possible variables are:")
# print "\n".join([c[0] for c in codes])
# sys.exit(-1)
# print (head_legend)
labels.append(head_legend)
return labels
def makeComposedQuantity(self,results,myrun,myjob):
vecs = [r[1] for r in results]
names = [r[0] for r in results]
# print (vecs[0].shape)
new_results = []
for comp in self.using:
exprs = comp.split(":")
tmp_res = []
for i in [0,1]:
e = re.sub(r"(%)([0-9]+)\.(x)",r"vecs[\2][:,0]",exprs[i])
e = re.sub(r"(%)([0-9]+)\.(y)",r"vecs[\2][:,1]",e)
e = self.replaceRunAndJobsParameters(e,myrun,myjob)
try:
tmp_res.append(eval(e))
except Exception as ex:
print (names)
print ("invalid expression: '" + exprs[i] + "'")
print ("invalid expression: '" + e + "'")
print (ex)
i = 1
for v in vecs:
print ('quantity {0}/{1} shape: {2}'.format(i,len(vecs),v.shape))
i += 1
sys.exit(-1)
name = re.sub(r"(%)([0-9]+)\.([x|y])",r'(" + str(names[\2]) + ")',exprs[1])
res = np.zeros((tmp_res[0].shape[0],2))
res[:,0] = tmp_res[0]
res[:,1] = tmp_res[1]
# print (res.shape)
expr = re.sub(r"(%)([0-9]+)",r"vecs[\2]",comp)
# res[0] = eval(expr)
# print (name)
name = "\"" + name + "\""
# print (name)
name = eval(name)
# print (name)
new_results.append([name,res])
return new_results
def decorateGraph(self, fig, myrun, myjob, results):
if not results:
return
if fig is None:
fig = plt.figure()
axe=fig.add_subplot(1,1,1)
if self.xrange:
axe.set_xlim(self.xrange)
if self.yrange:
axe.set_ylim(self.yrange)
if (self.xlabel):
axe.set_xlabel(self.xlabel)
if (self.ylabel):
axe.set_ylabel(self.ylabel)
if (self.title):
t = self.replaceRunAndJobsParameters(self.title,myrun,myjob)
axe.set_title(t)
axe.grid(True,linewidth=0.1)
if (self.using):
results = self.makeComposedQuantity(results,myrun,myjob)
labels = self.generateLabels(results,myrun,myjob)
# print (labels)
return fig, axe, results, labels
def makeCurve(self,results,myrun=None,myjob=None,fig=None,**kwargs):
fig, axe, results, labels = self.decorateGraph(fig, myrun, myjob, results)
for count, result in enumerate(results):
name = result[0]
vec = result[1]
label = labels[count]
# print (self.quantities)
# print (name)
style=dict()
if (self.marker is not None):
style["marker"] = self.marker
if self.blackwhite:
width_index = self.cycle_index/len(self.linestyle_cycle)
style_index = self.cycle_index%len(self.linestyle_cycle)
self.cycle_index += 1
style["linewidth"] = self.linewidth_cycle[width_index]
style["linestyle"] = self.linestyle_cycle[style_index]
style["color"] = 'k'
axe.plot(vec[:,0]/self.xscale, vec[:,1]/self.yscale,
label=label, **style)
axe.legend(loc='best')
if (self.fileout):
fig.savefig(self.fileout)
return fig
def setJobConstraint(self,**params):
self.job_constraints = []
if ("job_constraints" in params):
self.job_constraints = params["job_constraints"]
def setRunConstraint(self,**params):
self.run_constraints = []
if ("run_constraints" in params):
self.run_constraints = params["run_constraints"]
def setBinaryOperator(self,**params):
self.binary_operator = 'and'
if ("binary_operator" in params):
self.binary_operator = params["binary_operator"]
def setQuantity(self,**params):
if ("quantity" in params):
self.quantities = params["quantity"]
else:
print ("quantity should be provided using option --quantity")
self.quantities = "__BLACKDYNAMITE_ERROR__"
def __init__ (self,base,**params):
self.setJobConstraint(**params)
self.setRunConstraint(**params)
self.setBinaryOperator(**params)
self.setQuantity(**params)
self.base = base
self.runSelector = runselector.RunSelector(self.base)
self.fig = None
self.xrange = None
self.yrange = None
self.xlabel = None
self.ylabel = None
self.xscale = None
self.yscale = None
self.fileout = None
self.title = None
self.using = None
self.frequency = None
self.start = None
self.end = None
self.figsize = None
self.blackwhite = None
self.legend = None
self.sort_by = None
self.marker = None
### set the members if keys are present in params
members = set(self.__dict__.keys())
p = set(params.keys())
for key in members & p:
setattr(self,key,params[key])
if(params["list_quantities"] == True):
myrun = run.Run(base)
print ("list of possible quantities:\n")
print("\n".join(myrun.listQuantities()))
sys.exit(0)
if(params["list_parameters"] == True):
myjob = job.Job(base)
myjob.prepare()
print ("****************************************************************")
print ("Job parameters:")
print ("****************************************************************")
params = [str(j[0]) + ": " + str(j[1]) for j in myjob.types.iteritems() ]
print("\n".join(params))
myrun = run.Run(base)
myrun.prepare()
print ("****************************************************************")
print ("Run parameters:")
print ("****************************************************************")
params = [str(j[0]) + ": " + str(j[1]) for j in myrun.types.iteritems() ]
print("\n".join(params))
sys.exit(0)
self.linewidth_cycle = [1, 2, 4]
self.linestyle_cycle = ['-', '--', '-.']
self.cycle_index = 0
################################################################
class GraphParser(bdparser.BDParser):
"""
"""
def __init__ (self):
bdparser.BDParser.__init__(self)
self.admissible_params["quantity"] = [str]
self.help["quantity"] = "Specify the quantity to be outputed"
self.admissible_params["xrange"] = [float]
self.help["xrange"] = "Specify range of values in the X direction"
self.admissible_params["yrange"] = [float]
self.help["yrange"] = "Specify range of values in the Y direction"
self.admissible_params["sort_by"] = [str]
self.help["sort_by"] = "Specify a study parameter to be used in sorting the curves"
self.admissible_params["xlabel"] = str
self.help["xlabel"] = "Specify the label for the X axis"
self.admissible_params["ylabel"] = str
self.help["ylabel"] = "Specify the label for the Y axis"
self.admissible_params["xscale"] = float
self.default_params["xscale"] = 1.
self.help["xscale"] = "Specify a scale factor for the X axis"
self.admissible_params["yscale"] = float
self.default_params["yscale"] = 1.
self.help["yscale"] = "Specify a scale factor for the Y axis"
self.admissible_params["title"] = str
self.help["title"] = "Specify title for the graph"
self.admissible_params["legend"] = [str]
self.help["legend"] = "Specify a legend for the curves. The syntax can use %%j.param or %%r.param to use get job and run values"
self.default_params["legend"] = None
self.admissible_params["using"] = [str]
self.help["using"] = "Allow to combine several quantities. The syntax uses python syntax where %%quantity1.column1:%%quantity2.column2 is the python numpy vector provided by quantity number (provided using the --quantities option) and column number (x or y). The sytax is comparable to the GNUPlot one in using the ':' to separate X from Y axis"
self.admissible_params["list_quantities"] = bool
self.help["list_quantities"] = "Request to list the possible quantities to be plotted"
self.admissible_params["list_parameters"] = bool
self.help["list_parameters"] = "Request to list the possible job/run parameters"
self.admissible_params["frequency"] = int
self.default_params["frequency"] = 1
self.help["frequency"] = "Set a frequency at which the quantity values should be retreived (helpful when the amount of data is very large)"
self.admissible_params["start"] = float
self.help["start"] = "Set the start X value for the graph"
self.admissible_params["end"] = int
self.help["end"] = "Set the end X value for the graph"
self.admissible_params["figsize"] = [float]
self.admissible_params["blackwhite"] = bool
self.default_params["blackwhite"] = False
self.help["blackwhite"] = "Request a black and white graph generation"
self.default_params["blackwhite"] = False
self.help["blackwhite"] = "Request to plot a black and white graph"
self.admissible_params["marker"] = str
self.help["marker"] = "Request a specific marker (matplotlib option)"
self.admissible_params["fileout"] = str
self.help["fileout"] = "Request to write a PDF file (given its name) containing the graph"
self.group_params["GraphHelper"] = [
"quantity",
"xrange",
"yrange",
"sort_by",
"xlabel",
"ylabel",
"xscale",
"yscale",
"title",
"legend",
"using",
"list_quantities",
"list_parameters",
"frequency",
"start",
"end",
"figsize",
"blackwhite",
"marker",
"fileout"]
################################################################

Event Timeline