13 u_is_data_associated_to_cell,
18 All the parsers in a data set have to yield the same type of data, i.e.
19 with the same number of unknowns and dofs/patch. I return the crucial
20 data afterwards, i.e. this routine validates and returns the quantities
29 is_data_associated_to_cell =
True
38 is_data_associated_to_cell,
46 u_is_data_associated_to_cell,
51 if snapshot_dimensions
not in [2, 3]:
52 print(
"File parsing unsuccessful. Supported dimensions are d=2 and d=3")
55 print(
"File parsing unsuccessful. No dof specified")
57 if snapshot_unknowns == 0:
58 print(
"File parsing unsuccessful. No unknowns specified")
61 if snapshot_dimensions != dimensions
and dimensions > 0:
63 "Dimensions not compatible with dimensions from previous files in the snapshot"
66 dimensions = snapshot_dimensions
67 if snapshot_dof != dof
and dof > 0:
68 print(
"DoF not compatible with dof from previous files in the snapshot")
72 if snapshot_unknowns != unknowns
and unknowns > 0:
74 "Unknowns not compatible with unknowns from previous files in the snapshot"
77 unknowns = snapshot_unknowns
83 is_data_associated_to_cell,
91 Small class to capture all of the snapshots in a Patch meta file.
92 Just need the timestamp this is associated with and all of the
93 patch files that this file includes. Add them using the right
104 assert patch_file_name
not in self.
filenames,
"Already added this patch file!"
110 Property to indicate number of patch files in this snapshot
115 assert self.
timestamp == -1,
"Should only set this property once!"
119 return f
"Timestamp: {self.timestamp}, {self.include_file_counter} subdomains"
124 Helper class to capture the important data coming from a patch file
126 This is what we use to capture the combined patch file data from.
127 We could keep everything in the helper class from PatchFileParser,
128 but the intention during the rewrite was to keep everything fairly
129 close to the way the original vis scripts worked.
144 pass in a UnknownAttributes object from PatchFileParser.py,
145 steal everything and return
149 ),
"Comparing the wrong objects. something must have gone wrong..."
151 self.
_cell_data += unknown_attributes.cell_data
154 self.
_dof = unknown_attributes.dof
156 self.
_unknowns = unknown_attributes.unknowns
159 self.
_mapping = unknown_attributes.mapping
163 Pass in a renderer object which will modify everything
164 in the way that the filter.render() function intends
166 This is basically the same as render_or_validate_for_each_unknown() from
167 the PatchFileParser class. The reason why we don't need
168 to do it for each unknown here is that the different unknowns
169 have been captured in by the caller of this function
171 We could rename this to something more general, since i
172 think we modify the same attributes in the same order
173 as the validate function
194 return f
"{self._unknown_name}: {self._unknowns} unknowns"
199 The visualiser is first and foremost a persistency layer around
200 datasets. It serves as abstract base class for real output formats,
201 i.e. it can parse files and hold them, but it does not do anything
204 The flow should work like this:
205 - Pass the file name of the patch file meta data to this class.
206 We then use read_metadata() to read this file, and gather, for
207 each timestamp, the list of patch files that we need to read.
208 For each timestamp, we create an instance of the Snapshot
209 helper class, which captures the timestamp, plus a list of
211 - We then pass back to display(). Then, for each snapshot, we
214 - Create a PatchFileParser object for each patch file within
216 - Read all the patch file data and combine it into the
217 PatchFileData class in this file.
218 - Return this data to child class, so that it can be rendered
221 Currently, the only working child class is the VTU renderer.
224 def __init__(self, file_name, start, end, verbose=False):
226 Abstract superclass of a visualiser
229 Name of a Peano patch file. This does not
230 need to be a meta file.
232 If we run render.py with the argument -s (to denote we are using single
233 file), then we will use the file_name to create a member of the
234 snapshot class (which captures the patch file to read, with default
235 timestamp of 0). This is then parsed by parse_and_render, and handed
238 If this is a meta file, then display() will be used.
241 Controls how much the class writes out.
245 self.identifier: String
246 Pick one subidentifier from the input file. If this one is empty, we take
247 every input data set. However, some output formats (such as ParaView)
248 don't support multiple output data sets, so we might end up with either
249 the first or last one from the file - depending on the implementations.
291 This is the one routine the visualisers typically do overwrite.
299 If we are here we've supplied a single file which is
300 itself a snapshot. Turn it into an instance of the
301 snapshot helper class, set the timestamp to 0 and
302 pass it back. We can just call parse_and_render_snapshot()
307 snapshot.set_timestamp(0)
312 Read the patch file metadata. In this routine we should:
313 - Count the number of timesteps this patch file records
314 - Get each of the file paths for the timestep
316 The meta file includes the snapshot files relative to its own
317 location. We therefore prefix each included file with the directory
318 of the meta file, so the visualiser works from any working directory.
320 found_snapshot =
False
323 print(f
"Reading metadata for {self._file_name}")
327 if "begin dataset" in line:
333 "end dataset" not in line
335 if "timestamp" in line:
336 s.set_timestamp(float(list(line.split(
" "))[2][:-1]))
338 if "include" in line:
339 file_name = os.path.join(
340 os.path.dirname(self.
_file_name), line.split(
'"')[1]
343 s.add_patch_file(file_name)
347 found_snapshots.append(s)
348 found_snapshot =
True
353 ),
"No snapshots found. Did you mean to run just for a single file? If so, try using the argument -s"
359 print(f
"Got snapshot: {snapshot}")
371 We pass in a snapshot object here, which should contain
372 time stamp and filenames for everything we want to render here.
375 - parse all the files listed in snapshot (use the method we wrote)
376 - return a dict, where the keys are unknown names, and the values are cell data to be rendered
377 - child class should handle the rest.
383 return data_to_be_rendered
387 We rewrite "reload" from previous version of this file.
389 We take in a argument of "snapshot", which is a helper class
390 with two attributes: timestamp and a list of patch files to parse.
392 We need to ensure that self.identifier is set correctly so that
393 the correct unknown is picked by the PatchFileParser. Remove this
394 line of comment when this is done.
396 Also need to handle removal of relative file paths here
398 The reason we (possibly) apply filters on individual pieces of data,
399 or once the patches have been concatenated is because we may have
400 more than one file to parse per snapshot. The choice is is about
401 whether we want to apply filters before combining all the patches
402 into one list, or afterwards?
404 What does this function do?
405 - Get filename for each patch file in this timestamp
406 - Produce a PatchFileParser object for each
407 - Parse each file in parallel
408 - Apply all the filters specified in render.py
409 - Amalgamate data as in original reload() method
410 - Returns a dict, where the keys are unknown names, and the values are patches that can be placed into individual patch files
414 for file_counter, patch_filename
in enumerate(snapshot.filenames):
416 print(f
"Parsing file {patch_filename}")
424 parsers.append(parser)
426 for parser
in parsers:
430 print(
"All individual files are parsed")
431 print(
"Apply filter(s) to individual files (where appropriate)")
433 for parser
in parsers:
435 if fil.run_on_individual_pieces_of_data:
437 print(f
"Apply filter {fil} to snapshot")
444 parser.render_or_validate_for_each_unknown(fil.render)
447 patch_file_data_to_render = {}
453 for parser
in parsers:
454 for unknown_name, unknown_data
in parser.unknown_attributes.items():
456 if unknown_name
not in patch_file_data_to_render.keys():
459 unknown_name, unknown_data.dimensions
463 patch_file_data_to_render[unknown_name].copy_data_from_parser_object(
464 parser.unknown_attributes[unknown_name]
468 for unknown_name, patch_file_data
in patch_file_data_to_render.items():
470 if fil.run_on_concatenated_data:
472 patch_file_data.apply_renderer_to_data(fil.render)
475 f
"Parsing {unknown_name} complete. Found {len(patch_file_data._cell_data)} cells, {patch_file_data._dof} dofs/cell with {patch_file_data._unknowns} unknowns per dof"
478 for parser
in parsers:
481 parser.render_or_validate_for_each_unknown(validate)
482 return patch_file_data_to_render
#define validate(booleanExpr)
Helper class to capture the important data coming from a patch file.
_is_data_associated_to_cell
apply_renderer_to_data(self, renderer)
Pass in a renderer object which will modify everything in the way that the filter....
__init__(self, unknown_name, dimensions)
copy_data_from_parser_object(self, unknown_attributes)
pass in a UnknownAttributes object from PatchFileParser.py, steal everything and return
Small class to capture all of the snapshots in a Patch meta file.
add_patch_file(self, patch_file_name)
set_timestamp(self, timestamp)
include_file_counter(self)
Property to indicate number of patch files in this snapshot.
The visualiser is first and foremost a persistency layer around datasets.
__init__(self, file_name, start, end, verbose=False)
Abstract superclass of a visualiser.
append_filter(self, filter)
parse_snapshot(self, snapshot)
We rewrite "reload" from previous version of this file.
_is_data_associated_to_cell
parse_and_render_snapshot(self, snapshot)
We pass in a snapshot object here, which should contain time stamp and filenames for everything we wa...
display_single_file(self)
If we are here we've supplied a single file which is itself a snapshot.
display(self)
This is the one routine the visualisers typically do overwrite.
read_metadata(self)
Read the patch file metadata.