Skip to content

Commit

Permalink
Added code to deal with value types that we can get from plumed
Browse files Browse the repository at this point in the history
  • Loading branch information
Gareth Aneurin Tribello authored and Gareth Aneurin Tribello committed May 4, 2024
1 parent 2d8668a commit 4b3acb8
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 12 deletions.
34 changes: 31 additions & 3 deletions PlumedToHTML/PlumedFormatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,16 @@ def __init__(self, **options) :
self.egname=options["input_name"]
self.hasload=options["hasload"]
self.broken=options["broken"]
self.valuedict=options["valuedict"]
self.actions=options["actions"]
self.valcolors = {
"scalar": "black",
"atoms": "violet",
"vector": "blue",
"matrix": "red",
"grid": "green",
"mix": "brown"
}

def format(self, tokensource, outfile):
action, label, all_labels, keywords, shortcut_state, shortcut_depth, default_state, notooltips, expansion_label = "", "", set(), [], 0, 0, 0, False, ""
Expand All @@ -31,7 +40,8 @@ def format(self, tokensource, outfile):
# This outputs information on the values computed in the previous action for the header
if label not in all_labels :
all_labels.add(label)
if action in self.keyword_dict and "output" in self.keyword_dict[action]["syntax"] : self.writeValuesData( outfile, action, label, keywords, self.keyword_dict[action]["syntax"]["output"] )
if label in self.valuedict.keys() : self.writeValueInfo( outfile, action, label, self.valuedict[label] )
elif action in self.keyword_dict and "output" in self.keyword_dict[action]["syntax"] : self.writeValuesData( outfile, action, label, keywords, self.keyword_dict[action]["syntax"]["output"] )
else :
outfile.write('<span style="display:none;" id="' + self.egname + label + r'">')
outfile.write('The ' + action + ' action with label <b>' + label + '</b> calculates something')
Expand Down Expand Up @@ -137,7 +147,13 @@ def format(self, tokensource, outfile):
# Labels of actions
if not self.broken and action!="" and label!="" and label!=value.strip() : raise Exception("label for " + action + " is not what is expected. Is " + label + " should be " + value.strip() )
elif label=="" : label = value.strip()
outfile.write('<b name="' + self.egname + label + '" onclick=\'showPath("' + self.divname + '","' + self.egname + label + '")\'>' + value + '</b>')
valtype = "mix"
if label in self.valuedict.keys() :
valtype = "unset"
for key, ddd in self.valuedict[label].items() :
if valtype=="unset" : valtype = ddd["type"]
elif valtype!=ddd["type"] : valtype = "mix"
outfile.write('<b name="' + self.egname + label + '" onclick=\'showPath("' + self.divname + '","' + self.egname + label + '","' + self.valcolors[valtype] + '")\'>' + value + '</b>')
elif ttype==Comment :
# Comments
outfile.write('<span style="color:blue" class="comment">' + value + '</span>' )
Expand Down Expand Up @@ -194,7 +210,8 @@ def format(self, tokensource, outfile):
# Check if there is stuff to output for the last action in the file
if len(label)>0 and label not in all_labels :
all_labels.add( label )
if action in self.keyword_dict and "output" in self.keyword_dict[action]["syntax"] : self.writeValuesData( outfile, action, label, keywords, self.keyword_dict[action]["syntax"]["output"] )
if label in self.valuedict.keys() : self.writeValueInfo( outfile, action, label, self.valuedict[label] )
elif action in self.keyword_dict and "output" in self.keyword_dict[action]["syntax"] : self.writeValuesData( outfile, action, label, keywords, self.keyword_dict[action]["syntax"]["output"] )
else :
outfile.write('<span style="display:none;" id="' + self.egname + label + r'">')
outfile.write('The ' + action + ' action with label <b>' + label + '</b> calculates something')
Expand Down Expand Up @@ -224,6 +241,17 @@ def writeValuesData( self, outfile, action, label, keywords, outdict ) :
if flag==value["flag"] : present=True
if present or value["flag"]=="default" : outfile.write('<tr><td width="5%">' + label + "." + key + '</td><td>' + value["description"] + '</td></tr>')
outfile.write('</table>')
outfile.write('</span>')

def writeValueInfo( self, outfile, action, label, valinfo ) :
# Some header stuff
outfile.write('<span style="display:none;" id="' + self.egname + label + r'">')
outfile.write('The ' + action + ' action with label <b>' + label + '</b>')
outfile.write(' calculates the following quantities:')
outfile.write('<table align="center" frame="void" width="95%" cellpadding="5%">')
outfile.write('<tr><td width="5%"><b> Quantity </b> </td><td width="5%"><b> Type </b> </td><td><b> Description </b> </td></tr>')
for key, value in valinfo.items() :
outfile.write('<tr><td width="5%">' + key + '</td><td width="5%"><font color="' + self.valcolors[value["type"]] +'">' + value["type"] + '</font></td><td>' + value["description"] + '</td></tr>')
outfile.write('</table>')
outfile.write('</span>')

22 changes: 17 additions & 5 deletions PlumedToHTML/PlumedToHTML.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,15 @@ def test_and_get_html( inpt, name, actions=set({}) ) :
iff.write(test_inpt + "\n")
iff.close()
# Now do the test
broken = test_plumed( "plumed", filename, header="", shortcutfile=name + '.json' )
broken = test_plumed( "plumed", filename, header="", shortcutfile=name + '.json' ) #, valuefile='values_' + name + '.json' )
# Retrieve the html that is output by plumed
html = get_html( inpt, name, name, ("master",), (broken,), ("plumed",), actions )
# Remove the tempory files that we created
if not keepfile : os.remove(filename)

return html

def test_plumed( executible, filename, header=[], shortcutfile=[] ) :
def test_plumed( executible, filename, header=[], shortcutfile=[], valuefile=[] ) :
"""
Test if plumed can parse this input file
Expand All @@ -71,6 +71,7 @@ def test_plumed( executible, filename, header=[], shortcutfile=[] ) :
filename -- A string that contains the name of the plumed input file to parse
header -- A string to put at the top of the error page that is output
shortcutfile -- The file on which to output the json file containing the expansed shortcuts. If not present this is not output
valuefile -- The file on which to output the dictionary explaining what each value represents. If not present this is not output
"""
# Get the information for running the code
run_folder = str(pathlib.PurePosixPath(filename).parent)
Expand All @@ -88,6 +89,8 @@ def test_plumed( executible, filename, header=[], shortcutfile=[] ) :
if int(nreplicas)>1 : cmd = ['mpirun', '-np', str(nreplicas)] + cmd + ['--multi', str(nreplicas)]
# Add the shortcutfile output if the user has asked for it
if len(shortcutfile)>0 : cmd = cmd + ['--shortcut-ofile', shortcutfile]
# Add the value dictionary if the user has asked for it
if len(valuefile)>0 : cmd = cmd + ['--valuedict-ofile', valuefile]
# raw std output - to be zipped
outfile=filename + "." + executible + ".stdout.txt"
# raw std error - to be zipped
Expand Down Expand Up @@ -189,6 +192,15 @@ def get_html( inpt, name, outloc, tested, broken, plumedexe, actions=set({}) ) :
os.remove( name + ".json")
else : final_inpt = inpt

# Check for value dictionary to use to create labels
if os.path.exists( 'values_' + name + '.json') :
with open('values_' + name + '.json') as f :
try:
valuedict = json.load(f)
except ValueError as ve:
raise InvalidJSONError(ve)
else : valuedict = {}

# Create the lexer that will generate the pretty plumed input
lexerfile = os.path.join(os.path.dirname(__file__),"PlumedLexer.py")
plumed_lexer = load_lexer_from_file(lexerfile, "PlumedLexer" )
Expand All @@ -197,7 +209,7 @@ def get_html( inpt, name, outloc, tested, broken, plumedexe, actions=set({}) ) :
plumed_info = subprocess.run(cmd, capture_output=True, text=True )
keyfile = plumed_info.stdout.strip() + "/json/syntax.json"
formatfile = os.path.join(os.path.dirname(__file__),"PlumedFormatter.py")
plumed_formatter = load_formatter_from_file(formatfile, "PlumedFormatter", keyword_file=keyfile, input_name=name, hasload=found_load, broken=any(broken), actions=actions )
plumed_formatter = load_formatter_from_file(formatfile, "PlumedFormatter", keyword_file=keyfile, input_name=name, hasload=found_load, broken=any(broken), valuedict=valuedict, actions=actions )

# Now generate html of input
html = '<div style="width: 100%; float:left">\n'
Expand Down Expand Up @@ -239,8 +251,8 @@ def get_html( inpt, name, outloc, tested, broken, plumedexe, actions=set({}) ) :
for val in soup.find_all("b") :
if "onclick" in val.attrs.keys() :
vallabels = val.attrs["onclick"].split("\"")
if not soup.find("span", {"id": vallabels[3]}) : raise Exception("Generated html is invalid as label hidden box for label " + vallabel + " is missing")
if not soup.find("div", {"id": "value_details_" + vallabels[1]}) : raise Exception("Generated html is invalid as there is no place to show data for " + vallabel)
if not soup.find("span", {"id": vallabels[3]}) : raise Exception("Generated html is invalid as label hidden box for label " + vallabels[3] + " is missing")
if not soup.find("div", {"id": "value_details_" + vallabels[1]}) : raise Exception("Generated html is invalid as there is no place to show data for " + vallabell[1])

# Now check the togglers
for val in soup.find_all(attrs={'class': 'toggler'}) :
Expand Down
6 changes: 3 additions & 3 deletions PlumedToHTML/assets/header.html
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@
</style>
<script>
var redpath="";
function showPath(eg,name) {
function showPath(eg,name,color) {
var i; var y = document.getElementsByName(redpath);
for (i=0; i < y.length; i++ ) { y[i].style.color="black"; }
for (i=0; i < y.length; i++ ) { y[i].style.color=""; }
var x = document.getElementsByName(name); redpath=name;
for (i = 0; i < x.length; i++) { x[i].style.color="red"; }
for (i = 0; i < x.length; i++) { x[i].style.color=color; }
var valid="value_details_".concat(eg);
var valueField = document.getElementById(valid);
var dataField = document.getElementById(name);
Expand Down
2 changes: 1 addition & 1 deletion PlumedToHTML/tests/test_formatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def testSimple(self) :
keyfile = plumed_info.stdout.strip() + "/json/syntax.json"

# Setup a plumed formatter
f = PlumedFormatter( keyword_file=keyfile, input_name="testout", hasload=False, broken=False, actions=set({}) )
f = PlumedFormatter( keyword_file=keyfile, input_name="testout", hasload=False, broken=False, actions=set({}), valuedict=dict({}) )

# Now run over all the inputs in the json
for item in tests["regtests"] :
Expand Down

0 comments on commit 4b3acb8

Please sign in to comment.