11 u_is_data_associated_to_cell,
16 All the parsers in a data set have to yield the same type of data, i.e.
17 with the same number of unknowns and dofs/patch. I return the crucial
18 data afterwards, i.e. this routine validates and returns the quantities
27 is_data_associated_to_cell =
True
36 is_data_associated_to_cell,
44 u_is_data_associated_to_cell,
49 if snapshot_dimensions
not in [2, 3]:
50 print(
"File parsing unsuccessful. Supported dimensions are d=2 and d=3")
53 print(
"File parsing unsuccessful. No dof specified")
55 if snapshot_unknowns == 0:
56 print(
"File parsing unsuccessful. No unknowns specified")
59 if snapshot_dimensions != dimensions
and dimensions > 0:
61 "Dimensions not compatible with dimensions from previous files in the snapshot"
64 dimensions = snapshot_dimensions
65 if snapshot_dof != dof
and dof > 0:
66 print(
"DoF not compatible with dof from previous files in the snapshot")
70 if snapshot_unknowns != unknowns
and unknowns > 0:
72 "Unknowns not compatible with unknowns from previous files in the snapshot"
75 unknowns = snapshot_unknowns
81 is_data_associated_to_cell,
89 Small class to capture all of the snapshots in a Patch meta file.
90 Just need the timestamp this is associated with and all of the
91 patch files that this file includes. Add them using the right
102 assert patch_file_name
not in self.
filenames,
"Already added this patch file!"
108 Property to indicate number of patch files in this snapshot
113 assert self.
timestamp == -1,
"Should only set this property once!"
117 return f
"Timestamp: {self.timestamp}, {self.include_file_counter} subdomains"
122 Helper class to capture the important data coming from a patch file
124 This is what we use to capture the combined patch file data from.
125 We could keep everything in the helper class from PatchFileParser,
126 but the intention during the rewrite was to keep everything fairly
127 close to the way the original vis scripts worked.
142 pass in a UnknownAttributes object from PatchFileParser.py,
143 steal everything and return
147 ),
"Comparing the wrong objects. something must have gone wrong..."
149 self.
_cell_data += unknown_attributes.cell_data
152 self.
_dof = unknown_attributes.dof
154 self.
_unknowns = unknown_attributes.unknowns
157 self.
_mapping = unknown_attributes.mapping
161 Pass in a renderer object which will modify everything
162 in the way that the filter.render() function intends
164 This is basically the same as render_or_validate_for_each_unknown() from
165 the PatchFileParser class. The reason why we don't need
166 to do it for each unknown here is that the different unknowns
167 have been captured in by the caller of this function
169 We could rename this to something more general, since i
170 think we modify the same attributes in the same order
171 as the validate function
192 return f
"{self._unknown_name}: {self._unknowns} unknowns"
197 The visualiser is first and foremost a persistency layer around
198 datasets. It serves as abstract base class for real output formats,
199 i.e. it can parse files and hold them, but it does not do anything
202 The flow should work like this:
203 - Pass the file name of the patch file meta data to this class.
204 We then use read_metadata() to read this file, and gather, for
205 each timestamp, the list of patch files that we need to read.
206 For each timestamp, we create an instance of the Snapshot
207 helper class, which captures the timestamp, plus a list of
209 - We then pass back to display(). Then, for each snapshot, we
212 - Create a PatchFileParser object for each patch file within
214 - Read all the patch file data and combine it into the
215 PatchFileData class in this file.
216 - Return this data to child class, so that it can be rendered
219 Currently, the only working child class is the VTU renderer.
222 def __init__(self, file_name, start, end, verbose=False):
224 Abstract superclass of a visualiser
227 Name of a Peano patch file. This does not
228 need to be a meta file.
230 If we run render.py with the argument -s (to denote we are using single
231 file), then we will use the file_name to create a member of the
232 snapshot class (which captures the patch file to read, with default
233 timestamp of 0). This is then parsed by parse_and_render, and handed
236 If this is a meta file, then display() will be used.
239 Controls how much the class writes out.
243 self.identifier: String
244 Pick one subidentifier from the input file. If this one is empty, we take
245 every input data set. However, some output formats (such as ParaView)
246 don't support multiple output data sets, so we might end up with either
247 the first or last one from the file - depending on the implementations.
273 This is the one routine the visualisers typically do overwrite.
281 If we are here we've supplied a single file which is
282 itself a snapshot. Turn it into an instance of the
283 snapshot helper class, set the timestamp to 0 and
284 pass it back. We can just call parse_and_render_snapshot()
289 snapshot.set_timestamp(0)
294 Read the patch file metadata. In this routine we should:
295 - Count the number of timesteps this patch file records
296 - Get each of the file paths for the timestep
298 found_snapshot =
False
301 print(f
"Reading metadata for {self._file_name}")
305 if "begin dataset" in line:
311 "end dataset" not in line
313 if "timestamp" in line:
314 s.set_timestamp(float(list(line.split(
" "))[2][:-1]))
316 if "include" in line:
317 file_name = line.split(
'"')[1]
319 s.add_patch_file(file_name)
323 found_snapshots.append(s)
324 found_snapshot =
True
329 ),
"No snapshots found. Did you mean to run just for a single file? If so, try using the argument -s"
335 print(f
"Got snapshot: {snapshot}")
347 We pass in a snapshot object here, which should contain
348 time stamp and filenames for everything we want to render here.
351 - parse all the files listed in snapshot (use the method we wrote)
352 - return a dict, where the keys are unknown names, and the values are cell data to be rendered
353 - child class should handle the rest.
359 return data_to_be_rendered
363 We rewrite "reload" from previous version of this file.
365 We take in a argument of "snapshot", which is a helper class
366 with two attributes: timestamp and a list of patch files to parse.
368 We need to ensure that self.identifier is set correctly so that
369 the correct unknown is picked by the PatchFileParser. Remove this
370 line of comment when this is done.
372 Also need to handle removal of relative file paths here
374 The reason we (possibly) apply filters on individual pieces of data,
375 or once the patches have been concatenated is because we may have
376 more than one file to parse per snapshot. The choice is is about
377 whether we want to apply filters before combining all the patches
378 into one list, or afterwards?
380 What does this function do?
381 - Get filename for each patch file in this timestamp
382 - Produce a PatchFileParser object for each
383 - Parse each file in parallel
384 - Apply all the filters specified in render.py
385 - Amalgamate data as in original reload() method
386 - Returns a dict, where the keys are unknown names, and the values are patches that can be placed into individual patch files
390 for file_counter, patch_filename
in enumerate(snapshot.filenames):
392 print(f
"Parsing file {patch_filename}")
394 parsers.append(parser)
396 for parser
in parsers:
400 print(
"All individual files are parsed")
401 print(
"Apply filter(s) to individual files (where appropriate)")
403 for parser
in parsers:
405 if fil.run_on_individual_pieces_of_data:
407 print(f
"Apply filter {fil} to snapshot")
414 parser.render_or_validate_for_each_unknown(fil.render)
417 patch_file_data_to_render = {}
423 for parser
in parsers:
424 for unknown_name, unknown_data
in parser.unknown_attributes.items():
426 if unknown_name
not in patch_file_data_to_render.keys():
429 unknown_name, unknown_data.dimensions
433 patch_file_data_to_render[unknown_name].copy_data_from_parser_object(
434 parser.unknown_attributes[unknown_name]
438 for unknown_name, patch_file_data
in patch_file_data_to_render.items():
440 if fil.run_on_concatenated_data:
442 patch_file_data.apply_renderer_to_data(fil.render)
445 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"
448 for parser
in parsers:
451 parser.render_or_validate_for_each_unknown(validate)
452 return patch_file_data_to_render
#define validate(booleanExpr)
Helper class to capture the important data coming from a patch file.
copy_data_from_parser_object(self, unknown_attributes)
pass in a UnknownAttributes object from PatchFileParser.py, steal everything and return
__init__(self, unknown_name, dimensions)
apply_renderer_to_data(self, renderer)
Pass in a renderer object which will modify everything in the way that the filter....
_is_data_associated_to_cell
Small class to capture all of the snapshots in a Patch meta file.
set_timestamp(self, timestamp)
include_file_counter(self)
Property to indicate number of patch files in this snapshot.
add_patch_file(self, patch_file_name)
The visualiser is first and foremost a persistency layer around datasets.
parse_snapshot(self, snapshot)
We rewrite "reload" from previous version of this file.
__init__(self, file_name, start, end, verbose=False)
Abstract superclass of a visualiser.
append_filter(self, filter)
read_metadata(self)
Read the patch file metadata.
display(self)
This is the one routine the visualisers typically do overwrite.
_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.