fdsreader 1.2.8__tar.gz → 1.3.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {fdsreader-1.2.8 → fdsreader-1.3.7}/LICENSE +0 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/MANIFEST.in +0 -0
- {fdsreader-1.2.8/fdsreader.egg-info → fdsreader-1.3.7}/PKG-INFO +2 -2
- {fdsreader-1.2.8 → fdsreader-1.3.7}/README.md +0 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/__init__.py +0 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/_version.py +1 -1
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/bndf/ObstructionCollection.py +0 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/bndf/__init__.py +0 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/bndf/obstruction.py +7 -3
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/bndf/utils.py +0 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/evac/EvacCollection.py +1 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/evac/__init__.py +0 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/evac/evacuation.py +1 -1
- fdsreader-1.3.7/fdsreader/export/__init__.py +3 -0
- fdsreader-1.3.7/fdsreader/export/obst_exporter.py +116 -0
- fdsreader-1.3.7/fdsreader/export/slcf_exporter.py +63 -0
- fdsreader-1.3.7/fdsreader/export/smoke3d_exporter.py +70 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/fds_classes/MeshCollection.py +0 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/fds_classes/__init__.py +0 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/fds_classes/mesh.py +21 -1
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/fds_classes/surface.py +0 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/fds_classes/ventilation.py +0 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/geom/GeometryCollection.py +0 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/geom/__init__.py +0 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/geom/geometry.py +0 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/isof/IsosurfaceCollection.py +0 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/isof/__init__.py +0 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/isof/isosurface.py +0 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/part/ParticleCollection.py +0 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/part/__init__.py +0 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/part/particle.py +0 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/pl3d/Plot3DCollection.py +0 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/pl3d/__init__.py +0 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/pl3d/pl3d.py +6 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/settings.py +0 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/simulation.py +7 -7
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/slcf/GeomSliceCollection.py +0 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/slcf/SliceCollection.py +1 -1
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/slcf/__init__.py +0 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/slcf/geomslice.py +0 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/slcf/slice.py +67 -6
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/smoke3d/Smoke3DCollection.py +1 -1
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/smoke3d/__init__.py +0 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/smoke3d/smoke3d.py +4 -49
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/utils/__init__.py +0 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/utils/data.py +0 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/utils/dimension.py +0 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/utils/extent.py +2 -2
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/utils/fortran_data.py +0 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader/utils/misc.py +0 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7/fdsreader.egg-info}/PKG-INFO +2 -2
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader.egg-info/SOURCES.txt +4 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader.egg-info/dependency_links.txt +0 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader.egg-info/requires.txt +0 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/fdsreader.egg-info/top_level.txt +0 -0
- fdsreader-1.3.7/requirements.txt +118 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/setup.cfg +0 -0
- {fdsreader-1.2.8 → fdsreader-1.3.7}/setup.py +2 -2
- fdsreader-1.2.8/requirements.txt +0 -113
|
File without changes
|
|
File without changes
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: fdsreader
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.7
|
|
4
4
|
Summary: Python reader for data generated by FDS.
|
|
5
|
-
Home-page: https://github.com/
|
|
5
|
+
Home-page: https://github.com/FireDynamics/fdsreader
|
|
6
6
|
Author: FZJ IAS-7 (Prof. Dr. Lukas Arnold, Jan Vogelsang)
|
|
7
7
|
Author-email: j.vogelsang@fz-juelich.de
|
|
8
8
|
License: UNKNOWN
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -149,7 +149,7 @@ class SubObstruction:
|
|
|
149
149
|
|
|
150
150
|
:ivar extent: :class:`Extent` object containing 3-dimensional extent information.
|
|
151
151
|
:ivar bound_indices: Indices used to define obstruction bounds in terms of mesh locations.
|
|
152
|
-
:ivar side_surfaces: Tuple of six :class:`Surface`s for each side of the cuboid.
|
|
152
|
+
:ivar side_surfaces: Tuple of six :class:`Surface` s for each side of the cuboid.
|
|
153
153
|
:ivar hide_times: List with points in time from when on the SubObstruction will be hidden.
|
|
154
154
|
:ivar show_times: List with points in time from when on the SubObstruction will be shown.
|
|
155
155
|
"""
|
|
@@ -177,6 +177,10 @@ class SubObstruction:
|
|
|
177
177
|
if not settings.LAZY_LOAD:
|
|
178
178
|
_ = self._boundary_data[bid].data
|
|
179
179
|
|
|
180
|
+
@property
|
|
181
|
+
def has_boundary_data(self):
|
|
182
|
+
return len(self._boundary_data) != 0
|
|
183
|
+
|
|
180
184
|
def get_data(self, quantity: Union[str, Quantity]):
|
|
181
185
|
if type(quantity) == Quantity:
|
|
182
186
|
quantity = quantity.name
|
|
@@ -304,7 +308,7 @@ class Obstruction:
|
|
|
304
308
|
if type(quantity) == Quantity:
|
|
305
309
|
quantity = quantity.name
|
|
306
310
|
|
|
307
|
-
ret = [subobst.get_data(quantity) for subobst in self._subobstructions]
|
|
311
|
+
ret = [subobst.get_data(quantity) for subobst in self._subobstructions if subobst.has_boundary_data]
|
|
308
312
|
if orientation == 0:
|
|
309
313
|
return ret
|
|
310
314
|
return [bndf for bndf in ret if orientation in bndf.data.keys()]
|
|
@@ -313,7 +317,7 @@ class Obstruction:
|
|
|
313
317
|
def has_boundary_data(self):
|
|
314
318
|
"""Whether boundary data has been output in the simulation.
|
|
315
319
|
"""
|
|
316
|
-
return
|
|
320
|
+
return any(subobst.has_boundary_data for subobst in self._subobstructions)
|
|
317
321
|
|
|
318
322
|
def clear_cache(self):
|
|
319
323
|
"""Remove all data from the internal cache that has been loaded so far to free memory.
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
import numpy as np
|
|
4
|
+
from typing_extensions import Literal
|
|
5
|
+
from ..bndf import Obstruction
|
|
6
|
+
from ..bndf.utils import sort_patches_cartesian
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def export_obst_raw(obst: Obstruction, output_dir: str, ordering: Literal['C', 'F'] = 'C'):
|
|
10
|
+
"""Exports the 3d arrays to raw binary files with corresponding .yaml meta files.
|
|
11
|
+
|
|
12
|
+
:param smoke3d: The :class:`Smoke3D` object to export.
|
|
13
|
+
:param output_dir: The directory in which to save all files.
|
|
14
|
+
:param ordering: Whether to write the data in C or Fortran ordering.
|
|
15
|
+
"""
|
|
16
|
+
from pathos.pools import ProcessPool as Pool
|
|
17
|
+
from multiprocess import Lock, Manager
|
|
18
|
+
filename_base = "obst-" + str(obst.id)
|
|
19
|
+
# Create all requested directories if they don't exist yet
|
|
20
|
+
Path(os.path.join(output_dir, filename_base + "-data")).mkdir(parents=True, exist_ok=True)
|
|
21
|
+
|
|
22
|
+
meta = {"BoundingBox": obst.bounding_box.as_list(), "QuantityNum": len(obst.quantities)}
|
|
23
|
+
m = Manager()
|
|
24
|
+
lock = m.Lock()
|
|
25
|
+
meta["Quantities"] = m.list()
|
|
26
|
+
|
|
27
|
+
def worker(quantity, bndf_data):
|
|
28
|
+
quantity_name = quantity.name.replace(" ", "_").replace(".", "-")
|
|
29
|
+
filename = filename_base + "_quantity-" + quantity_name + ".dat"
|
|
30
|
+
|
|
31
|
+
out = {"Quantity": quantity.name.replace(" ", "_").replace(".", "-"), "DataValMax": -100000.,
|
|
32
|
+
"DataValMin": 100000., "ScaleFactor": 1, "DataFile": os.path.join(filename_base + "-data", filename),
|
|
33
|
+
"Orientations": list()}
|
|
34
|
+
for bndf in bndf_data:
|
|
35
|
+
out["DataValMax"] = max(out["DataValMax"], np.max(bndf.upper_bounds))
|
|
36
|
+
out["DataValMin"] = min(out["DataValMin"], np.min(bndf.lower_bounds))
|
|
37
|
+
out["DataValMax"] = float(out["DataValMax"])
|
|
38
|
+
out["DataValMin"] = float(out["DataValMin"])
|
|
39
|
+
out["ScaleFactor"] = 255.0 / out["DataValMax"]
|
|
40
|
+
|
|
41
|
+
# Abort if no useful data is available
|
|
42
|
+
if meta[quantity]["DataValMax"] <= 0:
|
|
43
|
+
return
|
|
44
|
+
|
|
45
|
+
with open(os.path.join(output_dir, quantity_name, filename_base + "-data", filename), 'wb') as rawfile:
|
|
46
|
+
orientations = set()
|
|
47
|
+
for orientation in (-3, -2, -1, 1, 2, 3):
|
|
48
|
+
patches = list()
|
|
49
|
+
for bndf in bndf_data:
|
|
50
|
+
if orientation in bndf.data:
|
|
51
|
+
orientations.add(orientation)
|
|
52
|
+
patches.append(bndf.data[orientation])
|
|
53
|
+
|
|
54
|
+
if len(patches) == 0:
|
|
55
|
+
continue
|
|
56
|
+
|
|
57
|
+
# Combine patches to a single face for plotting
|
|
58
|
+
patches = sort_patches_cartesian(patches)
|
|
59
|
+
|
|
60
|
+
shape_dim1 = sum([patch_row[0].shape[0] for patch_row in patches])
|
|
61
|
+
shape_dim2 = sum([patch.shape[1] for patch in patches[0]])
|
|
62
|
+
n_t = patches[0][0].n_t # Number of timesteps
|
|
63
|
+
|
|
64
|
+
face = np.empty(shape=(n_t, shape_dim1, shape_dim2))
|
|
65
|
+
dim1_pos = 0
|
|
66
|
+
dim2_pos = 0
|
|
67
|
+
for patch_row in patches:
|
|
68
|
+
d1 = patch_row[0].shape[0]
|
|
69
|
+
for patch in patch_row:
|
|
70
|
+
d2 = patch.shape[1]
|
|
71
|
+
face[:, dim1_pos:dim1_pos + d1, dim2_pos:dim2_pos + d2] = patch.data
|
|
72
|
+
dim2_pos += d2
|
|
73
|
+
dim1_pos += d1
|
|
74
|
+
dim2_pos = 0
|
|
75
|
+
|
|
76
|
+
face = (face * meta["ScaleFactor"]).astype(np.uint8)
|
|
77
|
+
|
|
78
|
+
if abs(orientation) == 1:
|
|
79
|
+
spacing1 = (meta["BoundingBox"][3] - meta["BoundingBox"][2]) / face.shape[1]
|
|
80
|
+
spacing2 = (meta["BoundingBox"][5] - meta["BoundingBox"][4]) / face.shape[2]
|
|
81
|
+
elif abs(orientation) == 2:
|
|
82
|
+
spacing1 = (meta["BoundingBox"][1] - meta["BoundingBox"][0]) / face.shape[0]
|
|
83
|
+
spacing2 = (meta["BoundingBox"][5] - meta["BoundingBox"][4]) / face.shape[2]
|
|
84
|
+
else:
|
|
85
|
+
spacing1 = (meta["BoundingBox"][1] - meta["BoundingBox"][0]) / face.shape[0]
|
|
86
|
+
spacing2 = (meta["BoundingBox"][3] - meta["BoundingBox"][2]) / face.shape[1]
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
out["Orientations"].append({
|
|
90
|
+
"Orientation": orientation,
|
|
91
|
+
"MeshPos": f"{meta['BoundingBox'][0]:.6} {meta['BoundingBox'][2]:.6} {meta['BoundingBox'][4]:.6}",
|
|
92
|
+
"Spacing": f"{bndf_data[0].times[1] - bndf_data[0].times[0]:.6} {spacing1:.6} {spacing2:.6}",
|
|
93
|
+
"DimSize": f"{face.shape[2]} {face.shape[1]} {face.shape[2]}"
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
for d in face[:, [2, 0, 1]]: # Make time the first dimension so we can easily iterate over it
|
|
97
|
+
if ordering == 'F':
|
|
98
|
+
d = d.T
|
|
99
|
+
d.tofile(rawfile)
|
|
100
|
+
|
|
101
|
+
out["NumOrientations"] = len(orientations)
|
|
102
|
+
|
|
103
|
+
with lock:
|
|
104
|
+
meta["Quantities"].append(out)
|
|
105
|
+
|
|
106
|
+
worker_args = list()
|
|
107
|
+
for i, quantity in enumerate(obst.quantities):
|
|
108
|
+
bndf_data = obst.get_boundary_data(quantity)
|
|
109
|
+
worker_args.append((quantity, bndf_data))
|
|
110
|
+
Pool(8).map(lambda args: worker(*args), worker_args)
|
|
111
|
+
|
|
112
|
+
meta["Quantities"] = list(meta["Quantities"])
|
|
113
|
+
|
|
114
|
+
with open(os.path.join(output_dir, filename_base + ".yaml"), 'w') as metafile:
|
|
115
|
+
import yaml
|
|
116
|
+
yaml.dump(meta, metafile)
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
import numpy as np
|
|
4
|
+
from typing_extensions import Literal
|
|
5
|
+
from ..slcf import Slice
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def export_slcf_raw(slc: Slice, output_dir: str, ordering: Literal['C', 'F'] = 'C'):
|
|
9
|
+
"""Exports the 3d arrays to raw binary files with corresponding .yaml meta files.
|
|
10
|
+
|
|
11
|
+
:param slc: The :class:`Slice` object to export.
|
|
12
|
+
:param output_dir: The directory in which to save all files.
|
|
13
|
+
:param ordering: Whether to write the data in C or Fortran ordering.
|
|
14
|
+
"""
|
|
15
|
+
from pathos.pools import ProcessPool as Pool
|
|
16
|
+
from multiprocess import Lock, Manager
|
|
17
|
+
slc2d = slc.type == '2D'
|
|
18
|
+
meta = {"DataValMax": float(slc.vmax), "DataValMin": float(slc.vmin), "ScaleFactor": 255. / (float(slc.vmax) - float(slc.vmin)),
|
|
19
|
+
"MeshNum": len(slc.subslices), "Quantity": slc.quantity.name}
|
|
20
|
+
|
|
21
|
+
filename_base = ("slice" + ("2D-" if slc2d else "3D-") + slc.id.lower()).replace(" ", "_").replace(".", "-")
|
|
22
|
+
# Create all requested directories if they don't exist yet
|
|
23
|
+
Path(os.path.join(output_dir, filename_base + "-data")).mkdir(parents=True, exist_ok=True)
|
|
24
|
+
|
|
25
|
+
m = Manager()
|
|
26
|
+
meta["Meshes"] = m.list()
|
|
27
|
+
lock = m.Lock()
|
|
28
|
+
|
|
29
|
+
def worker(mesh, subslice):
|
|
30
|
+
mesh_id = mesh.id.replace(" ", "_").replace(".", "-")
|
|
31
|
+
filename = filename_base + "_mesh-" + mesh_id + ".dat"
|
|
32
|
+
|
|
33
|
+
data = ((subslice.data - meta["DataValMin"]) * meta["ScaleFactor"]).astype(np.uint8)
|
|
34
|
+
shape = data.shape
|
|
35
|
+
if slc2d:
|
|
36
|
+
shape = shape[:subslice.orientation] + (1,) + shape[subslice.orientation:]
|
|
37
|
+
|
|
38
|
+
with open(os.path.join(output_dir, filename_base + "-data", filename), 'wb') as rawfile:
|
|
39
|
+
for d in data:
|
|
40
|
+
if ordering == 'F':
|
|
41
|
+
d = d.T
|
|
42
|
+
d.tofile(rawfile)
|
|
43
|
+
|
|
44
|
+
spacing = [slc.times[1] - slc.times[0],
|
|
45
|
+
mesh.coordinates['x'][1] - mesh.coordinates['x'][0],
|
|
46
|
+
mesh.coordinates['y'][1] - mesh.coordinates['y'][0],
|
|
47
|
+
mesh.coordinates['z'][1] - mesh.coordinates['z'][0]]
|
|
48
|
+
with lock:
|
|
49
|
+
meta["Meshes"].append({
|
|
50
|
+
"Mesh": mesh_id,
|
|
51
|
+
"DataFile": os.path.join(filename_base + "-data", filename),
|
|
52
|
+
"MeshPos": f"{mesh.coordinates['x'][0]:.6} {mesh.coordinates['y'][0]:.6} {mesh.coordinates['z'][0]:.6}",
|
|
53
|
+
"Spacing": f"{spacing[0]:.6} {spacing[1]:.6} {spacing[2]:.6} {spacing[3]:.6}",
|
|
54
|
+
"DimSize": f"{shape[0]} {shape[1]} {shape[2]} {shape[3]}"
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
Pool(8).map(lambda args: worker(*args), list(slc._subslices.items()))
|
|
58
|
+
|
|
59
|
+
meta["Meshes"] = list(meta["Meshes"])
|
|
60
|
+
|
|
61
|
+
with open(os.path.join(output_dir, filename_base + ".yaml"), 'w') as metafile:
|
|
62
|
+
import yaml
|
|
63
|
+
yaml.dump(meta, metafile)
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
import numpy as np
|
|
4
|
+
from typing_extensions import Literal
|
|
5
|
+
from ..smoke3d import Smoke3D
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def export_smoke_raw(smoke3d: Smoke3D, output_dir: str, ordering: Literal['C', 'F'] = 'C'):
|
|
9
|
+
"""Exports the 3d arrays to raw binary files with corresponding .yaml meta files.
|
|
10
|
+
|
|
11
|
+
:param smoke3d: The :class:`Smoke3D` object to export.
|
|
12
|
+
:param output_dir: The directory in which to save all files.
|
|
13
|
+
:param ordering: Whether to write the data in C or Fortran ordering.
|
|
14
|
+
"""
|
|
15
|
+
from pathos.pools import ProcessPool as Pool
|
|
16
|
+
from multiprocess import Lock, Manager
|
|
17
|
+
filename_base = ("smoke-" + smoke3d.quantity.name.lower()).replace(" ", "_").replace(".", "-")
|
|
18
|
+
# Create all requested directories if they don't exist yet
|
|
19
|
+
Path(os.path.join(output_dir, filename_base + "-data")).mkdir(parents=True, exist_ok=True)
|
|
20
|
+
|
|
21
|
+
meta = {"DataValMax": -100000., "DataValMin": 100000., "ScaleFactor": 1, "MeshNum": len(smoke3d.subsmokes),
|
|
22
|
+
"Quantity": smoke3d.quantity.name}
|
|
23
|
+
|
|
24
|
+
for subsmoke in smoke3d._subsmokes.values():
|
|
25
|
+
meta["DataValMax"] = max(meta["DataValMax"], np.max(subsmoke.data))
|
|
26
|
+
meta["DataValMin"] = min(meta["DataValMin"], np.min(subsmoke.data))
|
|
27
|
+
meta["DataValMax"] = float(meta["DataValMax"])
|
|
28
|
+
meta["DataValMin"] = float(meta["DataValMin"])
|
|
29
|
+
meta["ScaleFactor"] = 255.0 / meta["DataValMax"]
|
|
30
|
+
|
|
31
|
+
# Abort if no useful data is available
|
|
32
|
+
if meta["DataValMax"] <= 0:
|
|
33
|
+
return
|
|
34
|
+
|
|
35
|
+
m = Manager()
|
|
36
|
+
meta["Meshes"] = m.list()
|
|
37
|
+
lock = m.Lock()
|
|
38
|
+
|
|
39
|
+
def worker(mesh, subsmoke):
|
|
40
|
+
mesh_id = mesh.id.replace(" ", "_").replace(".", "-")
|
|
41
|
+
filename = filename_base + "_mesh-" + mesh_id + ".dat"
|
|
42
|
+
|
|
43
|
+
data = (subsmoke.data * meta["ScaleFactor"]).astype(np.uint8)
|
|
44
|
+
|
|
45
|
+
with open(os.path.join(output_dir, filename_base + "-data", filename), 'wb') as rawfile:
|
|
46
|
+
for d in data:
|
|
47
|
+
if ordering == 'F':
|
|
48
|
+
d = d.T
|
|
49
|
+
d.tofile(rawfile)
|
|
50
|
+
|
|
51
|
+
spacing = [smoke3d.times[1] - smoke3d.times[0],
|
|
52
|
+
mesh.coordinates['x'][1] - mesh.coordinates['x'][0],
|
|
53
|
+
mesh.coordinates['y'][1] - mesh.coordinates['y'][0],
|
|
54
|
+
mesh.coordinates['z'][1] - mesh.coordinates['z'][0]]
|
|
55
|
+
with lock:
|
|
56
|
+
meta["Meshes"].append({
|
|
57
|
+
"Mesh": mesh_id,
|
|
58
|
+
"DataFile": os.path.join(filename_base + "-data", filename),
|
|
59
|
+
"MeshPos": f"{mesh.coordinates['x'][0]:.6} {mesh.coordinates['y'][0]:.6} {mesh.coordinates['z'][0]:.6}",
|
|
60
|
+
"Spacing": f"{spacing[0]:.6} {spacing[1]:.6} {spacing[2]:.6} {spacing[3]:.6}",
|
|
61
|
+
"DimSize": f"{data.shape[0]} {data.shape[1]} {data.shape[2]} {data.shape[3]}"
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
Pool(8).map(lambda args: worker(*args), list(smoke3d._subsmokes.items()))
|
|
65
|
+
|
|
66
|
+
meta["Meshes"] = list(meta["Meshes"])
|
|
67
|
+
|
|
68
|
+
with open(os.path.join(output_dir, filename_base + ".yaml"), 'w') as metafile:
|
|
69
|
+
import yaml
|
|
70
|
+
yaml.dump(meta, metafile)
|
|
File without changes
|
|
File without changes
|
|
@@ -68,7 +68,7 @@ class Mesh:
|
|
|
68
68
|
as obstructions may be hidden as specific points in time.
|
|
69
69
|
"""
|
|
70
70
|
orientation = subslice.orientation
|
|
71
|
-
value = subslice.extent[orientation
|
|
71
|
+
value = subslice.extent[orientation][0]
|
|
72
72
|
cell_centered = subslice.cell_centered
|
|
73
73
|
|
|
74
74
|
slc_index = self.coordinate_to_index((value,), dimension=(orientation,), cell_centered=cell_centered)[0]
|
|
@@ -87,6 +87,7 @@ class Mesh:
|
|
|
87
87
|
:param coordinate: Tuple of 3 floats. If the dimension parameter is supplied, up to 2
|
|
88
88
|
dimensions can be left out from the tuple.
|
|
89
89
|
:param dimension: The dimensions in which to return the indices (1=x, 2=y, 3=z).
|
|
90
|
+
:param cell_centered: Instead of finding the nearest point on the mesh, find the center of the nearest cell.
|
|
90
91
|
"""
|
|
91
92
|
# Convert possible integer input to chars
|
|
92
93
|
dimension = tuple(('x', 'y', 'z')[dim - 1] if type(dim) == int else dim for dim in dimension)
|
|
@@ -105,6 +106,25 @@ class Mesh:
|
|
|
105
106
|
ret.append(idx)
|
|
106
107
|
return tuple(ret)
|
|
107
108
|
|
|
109
|
+
def get_nearest_coordinate(self, coordinate: Tuple[float, ...],
|
|
110
|
+
dimension: Tuple[Literal[1, 2, 3, 'x', 'y', 'z'], ...] = ('x', 'y', 'z'),
|
|
111
|
+
cell_centered=False) -> Tuple[float, ...]:
|
|
112
|
+
"""Finds the nearest point in the mesh's grid.
|
|
113
|
+
|
|
114
|
+
:param coordinate: Tuple of 3 floats. If the dimension parameter is supplied, up to 2
|
|
115
|
+
dimensions can be left out from the tuple.
|
|
116
|
+
:param dimension: The dimensions in which to return the indices (1=x, 2=y, 3=z).
|
|
117
|
+
:param cell_centered: Instead of finding the nearest point on the mesh, find the center of the nearest cell.
|
|
118
|
+
"""
|
|
119
|
+
indices = self.coordinate_to_index(coordinate, dimension, cell_centered)
|
|
120
|
+
ret = list()
|
|
121
|
+
for i, dim in enumerate(dimension):
|
|
122
|
+
coords = self.coordinates[dim]
|
|
123
|
+
if cell_centered:
|
|
124
|
+
coords = coords[:-1] + (coords[1] - coords[0]) / 2
|
|
125
|
+
ret.append(coords[indices[i]])
|
|
126
|
+
return tuple(ret)
|
|
127
|
+
|
|
108
128
|
def _add_patches(self, bid: int, cell_centered: bool, quantity: str, short_name: str, unit: str,
|
|
109
129
|
patches: List[Patch], times: np.ndarray, n_t: int, lower_bounds: np.ndarray,
|
|
110
130
|
upper_bounds: np.ndarray):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -88,6 +88,12 @@ class Plot3D(np.lib.mixins.NDArrayOperatorsMixin):
|
|
|
88
88
|
"""
|
|
89
89
|
return self._subplots[mesh]
|
|
90
90
|
|
|
91
|
+
def get_quantity_index(self, quantity: str):
|
|
92
|
+
"""Returns the index of the quantity for the fourth dimension of the data array.
|
|
93
|
+
"""
|
|
94
|
+
return next(i for i, q in enumerate(self.quantities) if
|
|
95
|
+
q.name.lower() == quantity.lower() or q.short_name.lower() == quantity.lower())
|
|
96
|
+
|
|
91
97
|
@implements(np.mean)
|
|
92
98
|
def mean(self) -> np.ndarray:
|
|
93
99
|
"""Calculates the mean for each quantity individually of the whole Plot3D.
|
|
File without changes
|
|
@@ -43,8 +43,8 @@ class Simulation:
|
|
|
43
43
|
:ivar isosurfaces: All defined isosurfaces combined into a :class:`IsosurfaceCollection`.
|
|
44
44
|
:ivar particles: All defined particles combined into a :class:`ParticleCollection`.
|
|
45
45
|
:ivar evacs: All defined evacuations combined into a :class:`EvacCollection`.
|
|
46
|
-
:ivar devices: List containing all :class:`Device`s defined in this simulation.
|
|
47
|
-
:ivar profiles: Dictionary mapping profile ids to the corresponding :class:`Profile`s defined in this simulation.
|
|
46
|
+
:ivar devices: List containing all :class:`Device` s defined in this simulation.
|
|
47
|
+
:ivar profiles: Dictionary mapping profile ids to the corresponding :class:`Profile` s defined in this simulation.
|
|
48
48
|
:ivar geoms: List containing all geometries (:class:`Geometry`) defined in this simulation.
|
|
49
49
|
:ivar geom_data: All geometry data by quantity combined into a :class:`GeometryCollection`.
|
|
50
50
|
:ivar cpu: Dictionary mapping .csv header keys to numpy arrays containing cpu data.
|
|
@@ -924,7 +924,7 @@ class Simulation:
|
|
|
924
924
|
def _load_DEVC_data(self, file_path: str):
|
|
925
925
|
with open(file_path, 'r') as infile:
|
|
926
926
|
units = infile.readline().split(',')
|
|
927
|
-
names = [name.replace('"', '').replace('\n', '').strip() for name in infile.readline().split(',')]
|
|
927
|
+
names = [name.replace('"', '').replace('\n', '').strip() for name in infile.readline().split(',"')]
|
|
928
928
|
values = np.genfromtxt(infile, delimiter=',', dtype=np.float32, autostrip=True)
|
|
929
929
|
for k in range(len(names)):
|
|
930
930
|
devc = self.devices[names[k]]
|
|
@@ -938,7 +938,7 @@ class Simulation:
|
|
|
938
938
|
if os.path.exists(line_path):
|
|
939
939
|
with open(line_path, 'r') as infile:
|
|
940
940
|
units = infile.readline()
|
|
941
|
-
names = [name.replace('"', '').replace('\n', '').strip() for name in infile.readline().split(',')]
|
|
941
|
+
names = [name.replace('"', '').replace('\n', '').strip() for name in infile.readline().split(',"')]
|
|
942
942
|
data = np.genfromtxt(infile, delimiter=',', dtype=np.float32, autostrip=True)
|
|
943
943
|
for k, key in enumerate(names):
|
|
944
944
|
if key in self.devices:
|
|
@@ -953,7 +953,7 @@ class Simulation:
|
|
|
953
953
|
def _load_HRR_data(self, file_path: str) -> Dict[str, np.ndarray]:
|
|
954
954
|
with open(file_path, 'r') as infile:
|
|
955
955
|
infile.readline()
|
|
956
|
-
keys = infile.readline().split(',')
|
|
956
|
+
keys = [name.replace('"', '').replace('\n', '').strip() for name in infile.readline().split(',')]
|
|
957
957
|
values = np.genfromtxt(infile, delimiter=',', dtype=np.float32, autostrip=True)
|
|
958
958
|
return self._transform_csv_data(keys, values, [np.float32] * len(keys))
|
|
959
959
|
|
|
@@ -961,7 +961,7 @@ class Simulation:
|
|
|
961
961
|
def _load_step_data(self, file_path: str) -> Dict[str, np.ndarray]:
|
|
962
962
|
with open(file_path, 'r') as infile:
|
|
963
963
|
infile.readline()
|
|
964
|
-
keys = infile.readline().split(',')
|
|
964
|
+
keys = [name.replace('"', '').replace('\n', '').strip() for name in infile.readline().split(',')]
|
|
965
965
|
dtypes = [np.float32] * len(keys)
|
|
966
966
|
dtypes[0] = int
|
|
967
967
|
dtypes[1] = np.dtype("datetime64[ms]")
|
|
@@ -973,7 +973,7 @@ class Simulation:
|
|
|
973
973
|
file_path = os.path.join(self.root_path, self.chid + "_cpu.csv")
|
|
974
974
|
if os.path.exists(file_path):
|
|
975
975
|
with open(file_path, 'r') as infile:
|
|
976
|
-
keys = infile.readline().split(
|
|
976
|
+
keys = [name.replace('"', '').replace('\n', '').strip() for name in infile.readline().split(',')]
|
|
977
977
|
dtypes = [np.float32] * len(keys)
|
|
978
978
|
dtypes[0] = int
|
|
979
979
|
values = np.genfromtxt(infile, delimiter=',', dtype=dtypes, autostrip=True)
|
|
File without changes
|
|
@@ -16,7 +16,7 @@ class SliceCollection(FDSDataCollection):
|
|
|
16
16
|
|
|
17
17
|
@property
|
|
18
18
|
def quantities(self) -> List[Quantity]:
|
|
19
|
-
return list({slc.name for slc in self})
|
|
19
|
+
return list({slc.quantity.name for slc in self})
|
|
20
20
|
|
|
21
21
|
def filter_by_quantity(self, quantity: Union[str, Quantity]):
|
|
22
22
|
"""Filters all slices by a specific quantity.
|
|
File without changes
|
|
File without changes
|
|
@@ -58,7 +58,7 @@ class SubSlice:
|
|
|
58
58
|
return shape
|
|
59
59
|
|
|
60
60
|
@property
|
|
61
|
-
def orientation(self) -> Literal[1, 2, 3]:
|
|
61
|
+
def orientation(self) -> Literal[0, 1, 2, 3]:
|
|
62
62
|
"""Orientation [1,2,3] of the slice in case it is 2D, 0 otherwise.
|
|
63
63
|
"""
|
|
64
64
|
return self._parent_slice.orientation
|
|
@@ -147,7 +147,7 @@ class Slice(np.lib.mixins.NDArrayOperatorsMixin):
|
|
|
147
147
|
"""Slice file data container including metadata. Consists of multiple subslices, one for each
|
|
148
148
|
mesh the slice cuts through. In case a slice cuts right through the border of two meshes, the generated data
|
|
149
149
|
would be duplicated. For edge-centered slices a random of both generated slices will be discarded as the data
|
|
150
|
-
is completely identical. For cell-centered slices the data of both slices will be saved as :class:`SubSlice`s,
|
|
150
|
+
is completely identical. For cell-centered slices the data of both slices will be saved as :class:`SubSlice` s,
|
|
151
151
|
therefore it might seem as if all slices would be duplicated, in reality however the slices might contain
|
|
152
152
|
different data.
|
|
153
153
|
|
|
@@ -258,8 +258,7 @@ class Slice(np.lib.mixins.NDArrayOperatorsMixin):
|
|
|
258
258
|
return list(self._subslices.values())
|
|
259
259
|
|
|
260
260
|
@property
|
|
261
|
-
def extent_dirs(self) -> Tuple[
|
|
262
|
-
Literal['x', 'y', 'z'], Literal['x', 'y', 'z'], Literal['x', 'y', 'z']]:
|
|
261
|
+
def extent_dirs(self) -> Tuple[Literal['x', 'y', 'z'], Literal['x', 'y', 'z'], Literal['x', 'y', 'z']]:
|
|
263
262
|
"""The directions in which there is an extent. All three dimensions in case the slice is 3D.
|
|
264
263
|
"""
|
|
265
264
|
ior = self.orientation
|
|
@@ -333,8 +332,67 @@ class Slice(np.lib.mixins.NDArrayOperatorsMixin):
|
|
|
333
332
|
for subslice in self._subslices.values():
|
|
334
333
|
subslice.clear_cache()
|
|
335
334
|
|
|
335
|
+
def get_2d_slice_from_3d(self, slice_direction: Literal['x', 'y', 'z', 1, 2, 3], value: float):
|
|
336
|
+
"""Creates a 2D-Slice from a 3D-Slice by slicing the Slice.
|
|
337
|
+
:param slice_direction: The direction in which to cut through the slice.
|
|
338
|
+
:param value: The position at which to start cutting through the slice.
|
|
339
|
+
"""
|
|
340
|
+
if type(slice_direction) == str:
|
|
341
|
+
slice_dim = {'x': 1, 'y': 2, 'z': 3}[slice_direction]
|
|
342
|
+
else:
|
|
343
|
+
slice_dim = slice_direction
|
|
344
|
+
slice_direction = ('x', 'y', 'z')[slice_dim - 1]
|
|
345
|
+
new_slice = deepcopy(self)
|
|
346
|
+
|
|
347
|
+
to_remove = list()
|
|
348
|
+
for mesh in new_slice._subslices.keys():
|
|
349
|
+
subslc = new_slice._subslices[mesh]
|
|
350
|
+
# Check if the new slice cuts through the subslice
|
|
351
|
+
cut_index = mesh.coordinate_to_index((value,), (slice_direction,),
|
|
352
|
+
cell_centered=self.cell_centered)
|
|
353
|
+
cut_value = mesh.get_nearest_coordinate((value,), (slice_direction,),
|
|
354
|
+
cell_centered=self.cell_centered)[0]
|
|
355
|
+
if mesh.coordinates[slice_direction][0] <= value <= mesh.coordinates[slice_direction][-1] and subslc.extent[slice_dim - 1][0] <= cut_value <= subslc.extent[slice_dim - 1][1]:
|
|
356
|
+
shape = subslc.dimension.shape(cell_centered=self.cell_centered)
|
|
357
|
+
indices = [slice(subslc.n_t)]
|
|
358
|
+
|
|
359
|
+
if subslc.dimension.x == 1 or subslc.dimension.y == 1 or subslc.dimension.z == 1:
|
|
360
|
+
indices.extend((slice(shape[0]), slice(shape[1])))
|
|
361
|
+
else:
|
|
362
|
+
indices.extend((slice(shape[0]), slice(shape[1]), slice(shape[2])))
|
|
363
|
+
indices[slice_dim - 1] = slice(cut_index[0], cut_index[0] + 1, 1)
|
|
364
|
+
|
|
365
|
+
subslc._data = subslc.data[tuple(indices)]
|
|
366
|
+
for direction in subslc.vector_filenames.keys():
|
|
367
|
+
subslc._vector_data[direction] = subslc.vector_data[direction][tuple(indices)]
|
|
368
|
+
subslc.extent._extents[slice_dim - 1] = (0, 0)
|
|
369
|
+
else:
|
|
370
|
+
to_remove.append(mesh)
|
|
371
|
+
|
|
372
|
+
for mesh in to_remove:
|
|
373
|
+
del new_slice._subslices[mesh]
|
|
374
|
+
|
|
375
|
+
vals = new_slice._subslices.values()
|
|
376
|
+
new_slice.extent = Extent(min(vals, key=lambda e: e.extent.x_start).extent.x_start,
|
|
377
|
+
max(vals, key=lambda e: e.extent.x_end).extent.x_end,
|
|
378
|
+
min(vals, key=lambda e: e.extent.y_start).extent.y_start,
|
|
379
|
+
max(vals, key=lambda e: e.extent.y_end).extent.y_end,
|
|
380
|
+
min(vals, key=lambda e: e.extent.z_start).extent.z_start,
|
|
381
|
+
max(vals, key=lambda e: e.extent.z_end).extent.z_end)
|
|
382
|
+
|
|
383
|
+
if new_slice.extent.x_start == new_slice.extent.x_end:
|
|
384
|
+
new_slice.orientation = 1
|
|
385
|
+
elif new_slice.extent.y_start == new_slice.extent.y_end:
|
|
386
|
+
new_slice.orientation = 2
|
|
387
|
+
elif new_slice.extent.z_start == new_slice.extent.z_end:
|
|
388
|
+
new_slice.orientation = 3
|
|
389
|
+
else:
|
|
390
|
+
new_slice.orientation = 0
|
|
391
|
+
|
|
392
|
+
return new_slice
|
|
393
|
+
|
|
336
394
|
def sort_subslices_cartesian(self):
|
|
337
|
-
"""Returns all subslices sorted in cartesian coordinates
|
|
395
|
+
"""Returns all subslices sorted in cartesian coordinates.
|
|
338
396
|
"""
|
|
339
397
|
slices = list(self._subslices.values())
|
|
340
398
|
slices_cart = [[slices[0]]]
|
|
@@ -403,6 +461,9 @@ class Slice(np.lib.mixins.NDArrayOperatorsMixin):
|
|
|
403
461
|
return slc_array
|
|
404
462
|
|
|
405
463
|
def to_global_nonuniform(self) -> np.ndarray:
|
|
464
|
+
"""Creates a global 2D-numpy ndarray from all subslices (2D-slices only).
|
|
465
|
+
Beware, this method might create sparse np-arrays that consume lots of memory.
|
|
466
|
+
"""
|
|
406
467
|
# The global grid will use the finest mesh as base and duplicate values of the coarser meshes
|
|
407
468
|
# Therefore we first find the finest mesh and calculate the step size in each dimension
|
|
408
469
|
coords = self.coordinates
|
|
@@ -437,7 +498,7 @@ class Slice(np.lib.mixins.NDArrayOperatorsMixin):
|
|
|
437
498
|
end_idx[dim] = int((mesh.coordinates[dim][-1] - start_coordinates[dim]) / step_sizes[dim]) + n_repeat
|
|
438
499
|
|
|
439
500
|
if n_repeat > 1:
|
|
440
|
-
slc_data = np.repeat(slc_data, n_repeat, axis=axis+1)
|
|
501
|
+
slc_data = np.repeat(slc_data, n_repeat, axis=axis + 1)
|
|
441
502
|
|
|
442
503
|
grid[:, start_idx['x']: end_idx['x'], start_idx['y']: end_idx['y'],
|
|
443
504
|
start_idx['z']: end_idx['z']] = slc_data.reshape(
|
|
@@ -6,7 +6,7 @@ from fdsreader.utils.data import FDSDataCollection, Quantity
|
|
|
6
6
|
|
|
7
7
|
class Smoke3DCollection(FDSDataCollection):
|
|
8
8
|
"""Collection of :class:`Smoke3D` objects. Offers extensive functionality for filtering and
|
|
9
|
-
using Smoke3Ds as well as its subclasses such as :class:`SubSmoke3D
|
|
9
|
+
using Smoke3Ds as well as its subclasses such as :class:`SubSmoke3D` .
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
12
|
def __init__(self, *smoke3ds: Iterable[Smoke3D]):
|
|
File without changes
|
|
@@ -52,7 +52,7 @@ class SubSmoke3D:
|
|
|
52
52
|
nx, ny, nz = int(header[3]), int(header[5]), int(header[7])
|
|
53
53
|
data_shape = (nx + 1, ny + 1, nz + 1)
|
|
54
54
|
|
|
55
|
-
self._data = np.empty((self.times.size,) + data_shape)
|
|
55
|
+
self._data = np.empty((self.times.size,) + data_shape, dtype=np.float32)
|
|
56
56
|
|
|
57
57
|
for t in range(self.times.size):
|
|
58
58
|
fdtype.read(infile, fdtype.FLOAT, 1) # Skip time value
|
|
@@ -127,54 +127,9 @@ class Smoke3D(np.lib.mixins.NDArrayOperatorsMixin):
|
|
|
127
127
|
"""
|
|
128
128
|
return self._subsmokes[mesh]
|
|
129
129
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
:param output_dir: The directory in which to save all files.
|
|
134
|
-
:param bytesize: The number of bytes used to save the data.
|
|
135
|
-
:param ordering: Whether to write the data in C or Fortran ordering.
|
|
136
|
-
"""
|
|
137
|
-
if bytesize == 1:
|
|
138
|
-
dtype = np.uint8
|
|
139
|
-
dtype_str = "uchar"
|
|
140
|
-
elif bytesize == 2:
|
|
141
|
-
dtype = np.uint16
|
|
142
|
-
dtype_str = "ushort"
|
|
143
|
-
else:
|
|
144
|
-
dtype = np.uint32
|
|
145
|
-
dtype_str = "uint"
|
|
146
|
-
|
|
147
|
-
meta = {"DataType": dtype_str, "Meshes": str(len(self._subsmokes)), "MeshData": list()}
|
|
148
|
-
|
|
149
|
-
filename_base = "smoke-" + self.quantity.name.lower()
|
|
150
|
-
for mesh, subsmoke in self._subsmokes.items():
|
|
151
|
-
filename = filename_base + "_mesh-" + mesh.id
|
|
152
|
-
filename = filename.replace(" ", "_").replace(".", "-")
|
|
153
|
-
filename += ".dat"
|
|
154
|
-
|
|
155
|
-
data = subsmoke.data.astype(dtype)
|
|
156
|
-
|
|
157
|
-
with open(os.path.join(output_dir, filename), 'wb') as rawfile:
|
|
158
|
-
for d in data:
|
|
159
|
-
if ordering == 'F':
|
|
160
|
-
d = d.T
|
|
161
|
-
d.tofile(rawfile)
|
|
162
|
-
|
|
163
|
-
spacing = [self.times[1] - self.times[0],
|
|
164
|
-
mesh.coordinates['x'][1] - mesh.coordinates['x'][0],
|
|
165
|
-
mesh.coordinates['y'][1] - mesh.coordinates['y'][0],
|
|
166
|
-
mesh.coordinates['z'][1] - mesh.coordinates['z'][0]]
|
|
167
|
-
meta["MeshData"].append({
|
|
168
|
-
"Mesh": mesh.id.replace(" ", "_").replace(".", "-"),
|
|
169
|
-
"DataFile": filename,
|
|
170
|
-
"MeshPos": f"{mesh.coordinates['x'][0]:.6} {mesh.coordinates['y'][0]:.6} {mesh.coordinates['z'][0]:.6}",
|
|
171
|
-
"Spacing": f"{spacing[0]:.6} {spacing[1]:.6} {spacing[2]:.6} {spacing[3]:.6}",
|
|
172
|
-
"DimSize": f"{subsmoke.data.shape[0]} {subsmoke.data.shape[1]} {subsmoke.data.shape[2]} {subsmoke.data.shape[3]}"
|
|
173
|
-
})
|
|
174
|
-
|
|
175
|
-
import yaml
|
|
176
|
-
with open(os.path.join(output_dir, filename_base + ".yaml"), 'w') as metafile:
|
|
177
|
-
yaml.dump(meta, metafile)
|
|
130
|
+
@property
|
|
131
|
+
def subsmokes(self):
|
|
132
|
+
return self._subsmokes.items()
|
|
178
133
|
|
|
179
134
|
@property
|
|
180
135
|
def vmax(self):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -30,14 +30,14 @@ class Extent:
|
|
|
30
30
|
self.y_start, self.y_end,
|
|
31
31
|
self.z_start, self.z_end)
|
|
32
32
|
|
|
33
|
-
def __getitem__(self, item: Union[
|
|
33
|
+
def __getitem__(self, item: Union[Literal['x', 'y', 'z', 1, 2, 3]]):
|
|
34
34
|
if item == 'x':
|
|
35
35
|
return self.x_start, self.x_end
|
|
36
36
|
elif item == 'y':
|
|
37
37
|
return self.y_start, self.y_end
|
|
38
38
|
elif item == 'z':
|
|
39
39
|
return self.z_start, self.z_end
|
|
40
|
-
return self._extents[item]
|
|
40
|
+
return self._extents[item - 1]
|
|
41
41
|
|
|
42
42
|
@property
|
|
43
43
|
def x_start(self):
|
|
File without changes
|
|
File without changes
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: fdsreader
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.7
|
|
4
4
|
Summary: Python reader for data generated by FDS.
|
|
5
|
-
Home-page: https://github.com/
|
|
5
|
+
Home-page: https://github.com/FireDynamics/fdsreader
|
|
6
6
|
Author: FZJ IAS-7 (Prof. Dr. Lukas Arnold, Jan Vogelsang)
|
|
7
7
|
Author-email: j.vogelsang@fz-juelich.de
|
|
8
8
|
License: UNKNOWN
|
|
@@ -19,6 +19,10 @@ fdsreader/bndf/utils.py
|
|
|
19
19
|
fdsreader/evac/EvacCollection.py
|
|
20
20
|
fdsreader/evac/__init__.py
|
|
21
21
|
fdsreader/evac/evacuation.py
|
|
22
|
+
fdsreader/export/__init__.py
|
|
23
|
+
fdsreader/export/obst_exporter.py
|
|
24
|
+
fdsreader/export/slcf_exporter.py
|
|
25
|
+
fdsreader/export/smoke3d_exporter.py
|
|
22
26
|
fdsreader/fds_classes/MeshCollection.py
|
|
23
27
|
fdsreader/fds_classes/__init__.py
|
|
24
28
|
fdsreader/fds_classes/mesh.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
alabaster~=0.7.12
|
|
2
|
+
appdirs~=1.4.4
|
|
3
|
+
argon2-cffi~=20.1.0
|
|
4
|
+
async-generator~=1.10
|
|
5
|
+
attrs~=20.3.0
|
|
6
|
+
autodocsumm~=0.2.2
|
|
7
|
+
Automat~=20.2.0
|
|
8
|
+
Babel~=2.9.0
|
|
9
|
+
backcall~=0.2.0
|
|
10
|
+
bcrypt~=3.2.0
|
|
11
|
+
bleach~=3.3.0
|
|
12
|
+
brotlipy~=0.7.0
|
|
13
|
+
certifi~=2020.12.5
|
|
14
|
+
cffi~=1.14.5
|
|
15
|
+
chardet~=4.0.0
|
|
16
|
+
click~=7.1.2
|
|
17
|
+
colorama~=0.4.4
|
|
18
|
+
constantly~=15.1.0
|
|
19
|
+
cryptography~=3.4.7
|
|
20
|
+
cycler~=0.10.0
|
|
21
|
+
decorator~=5.0.6
|
|
22
|
+
defusedxml~=0.7.1
|
|
23
|
+
docutils~=0.16
|
|
24
|
+
entrypoints~=0.3
|
|
25
|
+
environment-kernels~=1.1.1
|
|
26
|
+
hyperlink~=21.0.0
|
|
27
|
+
idna~=2.10
|
|
28
|
+
imageio~=2.9.0
|
|
29
|
+
imageio-ffmpeg~=0.4.3
|
|
30
|
+
imagesize~=1.2.0
|
|
31
|
+
importlib-metadata~=3.10.0
|
|
32
|
+
incremental~=21.3.0
|
|
33
|
+
ipykernel~=5.3.4
|
|
34
|
+
ipython~=7.22.0
|
|
35
|
+
ipython-genutils~=0.2.0
|
|
36
|
+
jedi~=0.17.0
|
|
37
|
+
Jinja2~=2.11.3
|
|
38
|
+
jsonschema~=3.2.0
|
|
39
|
+
jupyter-client~=6.1.12
|
|
40
|
+
jupyter-core~=4.7.1
|
|
41
|
+
jupyterlab-pygments~=0.1.2
|
|
42
|
+
kiwisolver~=1.3.1
|
|
43
|
+
MarkupSafe~=1.1.1
|
|
44
|
+
matplotlib~=3.4.1
|
|
45
|
+
meshio~=4.3.13
|
|
46
|
+
mistune~=0.8.4
|
|
47
|
+
mkl-fft~=1.3.0
|
|
48
|
+
mkl-random~=1.1.1
|
|
49
|
+
mkl-service~=2.3.0
|
|
50
|
+
nbclient~=0.5.3
|
|
51
|
+
nbconvert~=6.0.7
|
|
52
|
+
nbformat~=5.1.3
|
|
53
|
+
nbsphinx~=0.8.3
|
|
54
|
+
nest-asyncio~=1.5.1
|
|
55
|
+
notebook~=6.3.0
|
|
56
|
+
numpy~=1.20.2
|
|
57
|
+
olefile~=0.46
|
|
58
|
+
packaging~=20.9
|
|
59
|
+
pandocfilters~=1.4.3
|
|
60
|
+
parso~=0.8.2
|
|
61
|
+
pickleshare~=0.7.5
|
|
62
|
+
Pillow~=8.2.0
|
|
63
|
+
pip~=21.0.1
|
|
64
|
+
prometheus-client~=0.10.1
|
|
65
|
+
prompt-toolkit~=3.0.17
|
|
66
|
+
pyasn1~=0.4.8
|
|
67
|
+
pyasn1-modules~=0.2.8
|
|
68
|
+
pycparser~=2.20
|
|
69
|
+
Pygments~=2.8.1
|
|
70
|
+
PyHamcrest~=2.0.2
|
|
71
|
+
pyOpenSSL~=20.0.1
|
|
72
|
+
pyparsing~=2.4.7
|
|
73
|
+
pyrsistent~=0.17.3
|
|
74
|
+
PySocks~=1.7.1
|
|
75
|
+
python-dateutil~=2.8.1
|
|
76
|
+
pytz~=2021.1
|
|
77
|
+
pyvista~=0.29.1
|
|
78
|
+
pywin32~=227
|
|
79
|
+
pywinpty~=0.5.7
|
|
80
|
+
pyzmq~=20.0.0
|
|
81
|
+
requests~=2.25.1
|
|
82
|
+
rise~=5.7.1
|
|
83
|
+
scooby~=0.5.7
|
|
84
|
+
Send2Trash~=1.5.0
|
|
85
|
+
service-identity~=18.1.0
|
|
86
|
+
setuptools~=58.0.0
|
|
87
|
+
six~=1.15.0
|
|
88
|
+
snowballstemmer~=2.1.0
|
|
89
|
+
Sphinx~=3.5.4
|
|
90
|
+
sphinx-rtd-theme~=0.5.2
|
|
91
|
+
sphinxcontrib-applehelp~=1.0.2
|
|
92
|
+
sphinxcontrib-devhelp~=1.0.2
|
|
93
|
+
sphinxcontrib-htmlhelp~=1.0.3
|
|
94
|
+
sphinxcontrib-jsmath~=1.0.1
|
|
95
|
+
sphinxcontrib-qthelp~=1.0.3
|
|
96
|
+
sphinxcontrib-serializinghtml~=1.1.4
|
|
97
|
+
terminado~=0.9.4
|
|
98
|
+
testpath~=0.4.4
|
|
99
|
+
tornado~=6.1
|
|
100
|
+
traitlets~=5.0.5
|
|
101
|
+
transforms3d~=0.3.1
|
|
102
|
+
Twisted~=21.2.0
|
|
103
|
+
twisted-iocpsupport~=1.0.1
|
|
104
|
+
typing-extensions~=3.7.4.3
|
|
105
|
+
urllib3~=1.26.4
|
|
106
|
+
vtk~=9.0.1
|
|
107
|
+
wcwidth~=0.2.5
|
|
108
|
+
webencodings~=0.5.1
|
|
109
|
+
wheel~=0.36.2
|
|
110
|
+
win-inet-pton~=1.1.0
|
|
111
|
+
wincertstore~=0.2
|
|
112
|
+
pyyaml~=5.4.1
|
|
113
|
+
zipp~=3.4.1
|
|
114
|
+
zope.interface~=5.3.0
|
|
115
|
+
pyvistaqt~=0.4.0
|
|
116
|
+
typing_extensions~=3.7.4.3
|
|
117
|
+
pathos~=0.2.8
|
|
118
|
+
multiprocess~=0.70.12.2
|
|
File without changes
|
|
@@ -4,7 +4,7 @@ import setuptools
|
|
|
4
4
|
|
|
5
5
|
base_dir = os.path.dirname(os.path.realpath(__file__))
|
|
6
6
|
|
|
7
|
-
with open(os.path.join(base_dir, "README.md"), 'r') as f:
|
|
7
|
+
with open(os.path.join(base_dir, "README.md"), 'r', encoding="utf-8") as f:
|
|
8
8
|
long_description = f.read()
|
|
9
9
|
|
|
10
10
|
setuptools.setup(
|
|
@@ -16,7 +16,7 @@ setuptools.setup(
|
|
|
16
16
|
description="Python reader for data generated by FDS.",
|
|
17
17
|
long_description=long_description,
|
|
18
18
|
long_description_content_type="text/markdown",
|
|
19
|
-
url="https://github.com/
|
|
19
|
+
url="https://github.com/FireDynamics/fdsreader",
|
|
20
20
|
packages=setuptools.find_packages(),
|
|
21
21
|
classifiers=[
|
|
22
22
|
"Programming Language :: Python :: 3",
|
fdsreader-1.2.8/requirements.txt
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
alabaster==0.7.12
|
|
2
|
-
appdirs==1.4.4
|
|
3
|
-
argon2-cffi==20.1.0
|
|
4
|
-
async-generator==1.10
|
|
5
|
-
attrs==20.3.0
|
|
6
|
-
autodocsumm==0.2.2
|
|
7
|
-
Automat==20.2.0
|
|
8
|
-
Babel==2.9.0
|
|
9
|
-
backcall==0.2.0
|
|
10
|
-
bcrypt==3.2.0
|
|
11
|
-
bleach==3.3.0
|
|
12
|
-
brotlipy==0.7.0
|
|
13
|
-
certifi==2020.12.5
|
|
14
|
-
cffi==1.14.5
|
|
15
|
-
chardet==4.0.0
|
|
16
|
-
click==7.1.2
|
|
17
|
-
colorama==0.4.4
|
|
18
|
-
constantly==15.1.0
|
|
19
|
-
cryptography==3.4.7
|
|
20
|
-
cycler==0.10.0
|
|
21
|
-
decorator==5.0.6
|
|
22
|
-
defusedxml==0.7.1
|
|
23
|
-
docutils==0.16
|
|
24
|
-
entrypoints==0.3
|
|
25
|
-
environment-kernels==1.1.1
|
|
26
|
-
hyperlink==21.0.0
|
|
27
|
-
idna==2.10
|
|
28
|
-
imageio==2.9.0
|
|
29
|
-
imageio-ffmpeg==0.4.3
|
|
30
|
-
imagesize==1.2.0
|
|
31
|
-
importlib-metadata==3.10.0
|
|
32
|
-
incremental==21.3.0
|
|
33
|
-
ipykernel==5.3.4
|
|
34
|
-
ipython==7.22.0
|
|
35
|
-
ipython-genutils==0.2.0
|
|
36
|
-
jedi==0.17.0
|
|
37
|
-
Jinja2==2.11.3
|
|
38
|
-
jsonschema==3.2.0
|
|
39
|
-
jupyter-client==6.1.12
|
|
40
|
-
jupyter-core==4.7.1
|
|
41
|
-
jupyterlab-pygments==0.1.2
|
|
42
|
-
kiwisolver==1.3.1
|
|
43
|
-
MarkupSafe==1.1.1
|
|
44
|
-
matplotlib==3.4.1
|
|
45
|
-
meshio==4.3.13
|
|
46
|
-
mistune==0.8.4
|
|
47
|
-
mkl-fft==1.3.0
|
|
48
|
-
mkl-random==1.1.1
|
|
49
|
-
mkl-service==2.3.0
|
|
50
|
-
nbclient==0.5.3
|
|
51
|
-
nbconvert==6.0.7
|
|
52
|
-
nbformat==5.1.3
|
|
53
|
-
nbsphinx==0.8.3
|
|
54
|
-
nest-asyncio==1.5.1
|
|
55
|
-
notebook==6.3.0
|
|
56
|
-
numpy==1.20.2
|
|
57
|
-
olefile==0.46
|
|
58
|
-
packaging==20.9
|
|
59
|
-
pandocfilters==1.4.3
|
|
60
|
-
parso==0.8.2
|
|
61
|
-
pickleshare==0.7.5
|
|
62
|
-
Pillow==8.2.0
|
|
63
|
-
pip==21.0.1
|
|
64
|
-
prometheus-client==0.10.1
|
|
65
|
-
prompt-toolkit==3.0.17
|
|
66
|
-
pyasn1==0.4.8
|
|
67
|
-
pyasn1-modules==0.2.8
|
|
68
|
-
pycparser==2.20
|
|
69
|
-
Pygments==2.8.1
|
|
70
|
-
PyHamcrest==2.0.2
|
|
71
|
-
pyOpenSSL==20.0.1
|
|
72
|
-
pyparsing==2.4.7
|
|
73
|
-
pyrsistent==0.17.3
|
|
74
|
-
PySocks==1.7.1
|
|
75
|
-
python-dateutil==2.8.1
|
|
76
|
-
pytz==2021.1
|
|
77
|
-
pyvista==0.29.1
|
|
78
|
-
pywin32==227
|
|
79
|
-
pywinpty==0.5.7
|
|
80
|
-
pyzmq==20.0.0
|
|
81
|
-
requests==2.25.1
|
|
82
|
-
rise==5.7.1
|
|
83
|
-
scooby==0.5.7
|
|
84
|
-
Send2Trash==1.5.0
|
|
85
|
-
service-identity==18.1.0
|
|
86
|
-
setuptools==52.0.0.post20210125
|
|
87
|
-
six==1.15.0
|
|
88
|
-
snowballstemmer==2.1.0
|
|
89
|
-
Sphinx==3.5.4
|
|
90
|
-
sphinx-rtd-theme==0.5.2
|
|
91
|
-
sphinxcontrib-applehelp==1.0.2
|
|
92
|
-
sphinxcontrib-devhelp==1.0.2
|
|
93
|
-
sphinxcontrib-htmlhelp==1.0.3
|
|
94
|
-
sphinxcontrib-jsmath==1.0.1
|
|
95
|
-
sphinxcontrib-qthelp==1.0.3
|
|
96
|
-
sphinxcontrib-serializinghtml==1.1.4
|
|
97
|
-
terminado==0.9.4
|
|
98
|
-
testpath==0.4.4
|
|
99
|
-
tornado==6.1
|
|
100
|
-
traitlets==5.0.5
|
|
101
|
-
transforms3d==0.3.1
|
|
102
|
-
Twisted==21.2.0
|
|
103
|
-
twisted-iocpsupport==1.0.1
|
|
104
|
-
typing-extensions==3.7.4.3
|
|
105
|
-
urllib3==1.26.4
|
|
106
|
-
vtk==9.0.1
|
|
107
|
-
wcwidth==0.2.5
|
|
108
|
-
webencodings==0.5.1
|
|
109
|
-
wheel==0.36.2
|
|
110
|
-
win-inet-pton==1.1.0
|
|
111
|
-
wincertstore==0.2
|
|
112
|
-
zipp==3.4.1
|
|
113
|
-
zope.interface==5.3.0
|