Commit d3f18aaa authored by Dion Haefner's avatar Dion Haefner

fixed python tools - also, dorie plot works way better now

parent ff94bcf2
......@@ -39,7 +39,7 @@ initialize_folder()
plot_vtk()
{
$DORIE_PYTHON plot_vtk.py --vtk $1 --var $2
$DORIE_PYTHON plot_vtk.py -f $1 --var $2
}
pf_from_file()
......
......@@ -77,7 +77,7 @@ namespace Dune {
std::cout << "h5_Write: " << filename << std::endl;
UINT dim = local_count.size();
UINT dim = global_dim.size();
//std::cout << std::endl << "h5_Write: dim = " << dim << std::endl;
std::cout << "h5_Write: groupname = " << groupname << std::endl;
......@@ -137,34 +137,6 @@ namespace Dune {
//std::cout << "h5_Write: plist_id created." << std::endl;
herr_t status;
hsize_t maxnchunks = 1;
hsize_t chunk_dims[ dim ];
for(UINT i=0;i<dim;i++)
chunk_dims[i] = (hsize_t) 1;
status = H5Pset_chunk(
plist_id
, dim // must be == rank of the dataset
, chunk_dims // The values of the check_dims array define the size of the chunks to store the dataset's raw data. The unit of measure for check_dims values is dataset elements.
);
assert( status > -1 );
//std::cout << "h5_Write: H5Pset_chunk() o.k." << std::endl;
status = H5Pset_shuffle( plist_id ); // Sets the shuffle filter, H5Z_FILTER_SHUFFLE, in the dataset creation property list. This re-orders data to simplify compression.
assert( status > -1 );
//std::cout << "h5_Write: H5Pset_shuffle() o.k." << std::endl;
status = H5Pset_deflate( plist_id, 1 ); // Sets deflate (GNU gzip) compression method and compression level. ( 0 < level < 9, lower = faster, but less compression )
assert( status > -1 );
//std::cout << "h5_Write: H5Pset_deflate() o.k." << std::endl;
/* Create the dataset. */
hid_t dataset_id = H5Dcreate1( file_id,
......@@ -178,7 +150,7 @@ namespace Dune {
/* Write the dataset. */
status = H5Dwrite( // Writes raw data from a buffer to a dataset.
herr_t status = H5Dwrite( // Writes raw data from a buffer to a dataset.
dataset_id // dataset identifier
, H5T_NATIVE_DOUBLE // memory datatype id
, memspace_id // specifies the memory dataspace and the selection within it
......
......@@ -169,7 +169,7 @@ void RichardsSolver (GridType grid, GV& gv,
try{ // VTK Plotter has very bad exception handling
RF t = CCon.getTime();
if(asciiOutput) vtkwriter.write(t,Dune::VTK::ascii);
else vtkwriter.write(t,Dune::VTK::appendedraw);
else vtkwriter.write(t,Dune::VTK::base64);
}
catch(...){
DUNE_THROW(Dune::IOError,"Cannot write VTK output!");
......@@ -268,7 +268,7 @@ void RichardsSolver (GridType grid, GV& gv,
try{ // VTK Plotter has very bad exception handling
if(asciiOutput) vtkwriter.write(t,Dune::VTK::ascii);
else vtkwriter.write(t,Dune::VTK::appendedraw);
else vtkwriter.write(t,Dune::VTK::base64);
}
catch(...){
DUNE_THROW(Dune::IOError,"Cannot write VTK output!");
......
try: # Python 3.x
import configparser
except ImportError: # Python 2.x
import ConfigParser as configparser
from __future__ import absolute_import
import configparser
def add_section_header(properties_file, header_name):
# configparser.ConfigParser requires at least one section header
......@@ -10,7 +9,7 @@ def add_section_header(properties_file, header_name):
yield line
def cp(path):
f = open(path)
config = configparser.ConfigParser()
config.read_file(add_section_header(f, 'nosection'), source=path)
with open(path) as f:
config = configparser.RawConfigParser()
config.read_file(add_section_header(f, "nosection"), path)
return config
......@@ -12,7 +12,7 @@ from dorie.parfield import configparser
from dorie.parfield.parameterization import parameterizations
from dorie.utilities.text_to_bool import text_to_bool
class BaseConverter:
class BaseConverter(object):
"""
Base class for all parameter field generator modules. Implements the writing
of the parameter field to an H5 file, and supplies some utilities.
......
class Parameterization:
class Parameterization(object):
"""
Base class providing an interface for defining a parameterization (basically
just a set of possible parameter names, and their associated values).
......
h5py==2.6.0
Pillow==3.1.2
h5py
Pillow
configparser
......@@ -61,4 +61,5 @@ if __name__ == "__main__":
print(" {0}: {1}".format(w.category.__name__,w.message))
print("Parameter field generator exited successfully with ({0}) warning(s) and ({1}) error(s)".format(len(warn),0))
except Exception as e:
raise pfgerror.PFGError("Parameter field generator failed with ({0}) warning(s) and ({1}) error(s)".format(len(warn),1))
print("Parameter field generator failed with ({0}) warning(s) and ({1}) error(s)".format(len(warn),1))
raise
......@@ -61,4 +61,5 @@ if __name__ == "__main__":
print(" {0}: {1}".format(w.category.__name__,w.message))
print("Parameter field generator exited successfully with ({0}) warning(s) and ({1}) error(s)".format(len(warn),0))
except Exception as e:
raise pfgerror.PFGError("Parameter field generator failed with ({0}) warning(s) and ({1}) error(s)".format(len(warn),1))
print("Parameter field generator failed with ({0}) warning(s) and ({1}) error(s)".format(len(warn),1))
raise
......@@ -2,35 +2,12 @@ import os
import sys
import warnings
import argparse
import traceback
from dorie.parscraper import readers, writers, match_parameters
from dorie.parscraper.warnings import OutputWarning
def scrape(xml_file,source_folder,out,css=None,source_url=None):
"""
Main wrapper, doing most of the work in the parameter scraper.
This function calls the :mod:`XML reader <dorie.parscraper.readers.xml>`,
iterates over all source files in the given folder and calls the
:mod:`source scraper <dorie.parscraper.readers.source>` on each of them.
The output of the two readers is the passed to
:mod:`the matching function <dorie.parsraper.match_parameters>`.
For each given output format, the appropriate :mod:`writer <dorie.parscraper.writers>`
(must be the of the same name as the output file extension) is executed.
:param str xml_file: Path to the XML file holding parameter meta-information
:param str source_folder: The C++ source folder to scrape
:param array_like out: Output file(s)
:param str css: Path to a CSS file to include into HTML output (optional)
:param str source_url: Format string containing path to source files when creating \
links (optional, default: ``source_folder/\{filename\}``). May contain \{filename\} and \{line\} that are substituted \
by the file name and line number, respectively.
:raises Exception: In case the ini writer fails
:raises OutputWarning: In case any other writer fails
"""
def scrape(xml_file,source_folder,out,css=None,debug=False):
# PARSE XML FILE
if os.path.isfile(xml_file):
xml_parameters = readers.xml.parse(xml_file)
......@@ -57,23 +34,21 @@ def scrape(xml_file,source_folder,out,css=None,source_url=None):
# MATCH XML AND SCRAPED PARAMETERS
matched_parameters = match_parameters.match(xml_parameters,source_parameters,source_folder)
# SET LINK PATH
if not source_url is None:
path_format = source_url
else:
path_format = "file://" + source_folder + "{filename}"
# CALL OUTPUT SCRIPTS
for o in out:
file_suffix = o.split(".")[-1]
if hasattr(writers,file_suffix):
writer = getattr(writers,file_suffix)
try:
writer.write(matched_parameters,o,path_format=path_format,css=css)
writer.write(matched_parameters,o,source_folder,css=css)
except BaseException as e:
if file_suffix == "ini":
raise
else:
warnings.warn("Output failed for file {0} with error:\n{1}".format(o,repr(e)), OutputWarning)
if debug:
exc_type, exc_value, exc_traceback = sys.exc_info()
traceback.print_exception(exc_type, exc_value, exc_traceback)
else:
warnings.warn("Unknown output format: .{}. Skipping output".format(file_suffix), OutputWarning)
from __future__ import unicode_literals
import datetime
......@@ -205,5 +203,3 @@ def _sources(p,path_base):
out += "<a href='file://{2}' title='{3}'>{0}</a>:{1}<br />"\
.format(link_text,line_num,full_path,source_file)
return out
from __future__ import unicode_literals
import datetime
import os
import re
......@@ -5,7 +7,7 @@ import re
from dorie.utilities.check_path import check_path
from dorie.parscraper.parameter import Parameter
def write(parameters,out,**kwargs):
def write(parameters,out,*args,**kwargs):
"""
Writes the contents of the ``parameters`` input dict to a .ini file. The output is
structured as
......
from __future__ import unicode_literals
import datetime
......@@ -105,5 +103,3 @@ def _sources(p,path_base):
out += "`{0} <file://{2}>`_:{1}\n\n"\
.format(link_text,line_num,full_path,source_file)
return out
......@@ -9,7 +9,7 @@ Script invoking the parameter scraper on a folder given via command line.
"""
if __name__ == "__main__":
try: # catch all exceptions we we can output an error message
try: # catch all exceptions so we can output an error message
with warnings.catch_warnings(record=True) as warn: # catch all warnings so we can count them
# PARSE COMMAND LINE
parser = argparse.ArgumentParser()
......@@ -17,25 +17,22 @@ if __name__ == "__main__":
parser.add_argument('-s','--source',help='The C++ source folder to scrape',required=True)
parser.add_argument('-o','--out',help='Output file(s)',required=True,nargs="*")
parser.add_argument('-c','--css',help='Path to a CSS file to include into HTML output',required=False)
parser.add_argument('-u','--source_url',help='Format string containing path to source files when creating \
links (optional, default: source_folder/\{filename\}). May contain \{filename\} and \{line\} that are substituted \
by the file name and line number, respectively.',required=False)
parser.add_argument('--Wno',help='Hide warnings (optional, default off)',action='store_true',required=False)
parser.add_argument('--debug',help='Display warnings',action='store_true',required=False)
args = vars(parser.parse_args())
# CALL WRAPPER
scrape_folder.scrape(args["xml"],args["source"],args["out"],args["css"],args["source_url"])
scrape_folder.scrape(args["xml"],args["source"],args["out"],args["css"],args["debug"])
# HANDLE WARNINGS
if not "Wno" in args:
if not "debug" in args:
debug = False
else:
debug = not args["Wno"]
debug = args["debug"]
if debug:
for w in warn:
print(" {0}: {1}".format(w.category.__name__,w.message))
print("-- Parameter scraper exited with ({0}) warning(s) and ({1}) error(s)\n".format(len(warn),0))
except Exception as e:
print("-- Parameter scraper failed with ({0}) warning(s) and ({1}) error(s):".format(len(warn),1))
print("{}: {}\n".format(type(e),e.args[1]))
except:
print("-- Parameter scraper failed with ({0}) warning(s) and ({1}) error(s):\n".format(len(warn),1))
raise
......@@ -170,11 +170,10 @@ class VTKFile:
"""
# import these libraries only when needed
import numpy as np
import matplotlib as mpl
mpl.use("agg")
import matplotlib.tri as tri
import matplotlib.pyplot as plt
from matplotlib.collections import PolyCollection
if self.grid.dim > 2:
raise TypeError("Only 1- or 2-dimensional grids are supported")
......@@ -184,21 +183,9 @@ class VTKFile:
variables = list(data.keys())
x, y = self.grid.cellCenters()
(xt, yt), c = self.grid.triangulation()
try: # check if there already is a triangulation we can use
(xt, yt), c = self.grid.triangulation()
is_rectangular = self.grid.ppc == 4
if is_rectangular:
# create a triangular grid by splitting each rectangle into two
# right-angled triangles
ct = np.array([[x[:-1], x[[0,2,3]]] for x in c]).reshape(-1,3)
triang = tri.Triangulation(xt, yt, ct)
else:
triang = tri.Triangulation(xt, yt, c)
except NotImplementedError:
# create a triangulation by doing a delaunay tessalation of the cell centers
is_rectangular = False
triang = tri.Triangulation(x, y)
polygons = [[(xt[cii],yt[cii]) for cii in ci] for ci in c]
figures = []
for variable in variables:
......@@ -213,7 +200,7 @@ class VTKFile:
else:
ncomp = 1
fig = plt.figure(figsize=(10,8))
fig, ax = plt.subplots(1,1,figsize=(10,8))
if ncomp > 1: # we are plotting a vector
q = plt.quiver(x, y, d.T[0], d.T[1], angles="xy", scale_units="xy", scale=None, zorder=100)
d = np.sqrt(d[:,0]**2 + d[:,1]**2) # use absolute value of d for shading
......@@ -222,23 +209,26 @@ class VTKFile:
length_significand = round(arrow_length/10**int(np.log10(arrow_length)-1))
length_exponent = int(np.log10(arrow_length)-1)
plt.quiverkey(q, 0.9, 1.05, arrow_length,
'${0} \\cdot 10^{{{1}}} \\frac{{m}}{{s}}$'\
'${0} \\times 10^{{{1}}}$'\
.format(length_significand,length_exponent))
if is_rectangular:
# data array needs to be repeated because every cell consists of 2 triangles
d = np.repeat(d,2,axis=0)
plotargs = dict(zorder=1, edgecolors="k", linewidths=0.5)
if np.sign(d.min()) == np.sign(d.max()):
plotargs = {"cmap": plt.get_cmap("GnBu")}
clim = None
plotargs["cmap"] = plt.get_cmap("Blues")
else:
maxrange = max(abs(d.min()),abs(d.max()))
plotargs = {"cmap": plt.get_cmap("terrain"), "vmin": -maxrange, "vmax": maxrange}
if not is_rectangular:
plotargs["edgecolors"] = "k"
tc = plt.tripcolor(triang,facecolors=d.flatten(),zorder=1,**plotargs)
clim = (-maxrange,maxrange)
plotargs["cmap"] = plt.get_cmap("RdBu")
collection = PolyCollection(polygons, **plotargs)
collection.set_array(d.flatten())
if clim:
collection.set_clim(clim)
tc = ax.add_collection(collection)
if not self.time is None:
plt.title("{0}: {1} ($t = ${2:.2e}s)".format(self.path,variable,self.time))
plt.title("{0}: {1} ($t = ${2:.2e}s)".format(self.filename,variable,self.time))
else:
plt.title("{0}: {1}".format(self.filename,variable))
plt.colorbar(tc, format='%.2e')
figures.append(fig)
plt.close()
return figures
......@@ -38,14 +38,14 @@ if __name__ == "__main__":
print("Reading VTK file {}".format(f))
vtks = [vtkfile.VTKFile(f)]
for v in vtks:
print(" Plotting {}...".format(v))
v.read(variables=variables)
for vtk in vtks:
print(" Plotting {}...".format(vtk))
vtk.read(variables=variables)
if variables is None:
variables = list(v.grid.data().keys())
figures = v.plot(variables=variables)
variables = list(vtk.grid.data().keys())
figures = vtk.plot(variables=variables)
for v,fig in zip(variables,figures):
fig.savefig("{}/{}-{}.png".format(out,f,v))
fig.savefig("{}/{}-{}.png".format(out,vtk.filename,v))
# HANDLE WARNINGS
debug = args["Wno"]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment