Skip to content

Commit 446d687

Browse files
authored
Merge pull request #31 from nvaytet/bug_in_plane_plots
Fix bug in plane plots
2 parents d1b6670 + 83075b1 commit 446d687

File tree

2 files changed

+68
-63
lines changed

2 files changed

+68
-63
lines changed

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[metadata]
22
name = osyris
3-
version = 2.2.1
3+
version = 2.2.2
44
author = Neil Vaytet
55
author_email = [email protected]
66
description = A package to visualize AMR data from the RAMSES code

src/osyris/plot/plane.py

Lines changed: 67 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@
1313
from scipy.stats import binned_statistic_2d
1414

1515

16-
def _add_scatter(datax, datay, to_scatter, origin, datadx, dir_vecs, dx, dy, ax):
16+
def _add_scatter(to_scatter, origin, dir_vecs, dx, dy, ax):
1717
xyz = to_scatter[0]["data"] - origin
1818
viewport = max(dx.magnitude, dy.magnitude)
1919
radius = None
2020
if "s" in to_scatter[0]["params"]:
2121
size = to_scatter[0]["params"]["s"]
2222
if isinstance(size, Array) or isinstance(size, Quantity):
23-
radius = size.to(datax.unit.units)
23+
radius = size.to(dx.units)
2424
to_scatter[0]["params"]["s"] = radius
2525
if radius is None:
2626
# Fudge factor to select sinks close to the plane
@@ -115,65 +115,64 @@ def plane(*layers,
115115

116116
# Distance to the plane
117117
xyz = dataset["amr"]["xyz"] - origin
118-
diagonal = dataset["amr"]["dx"] * np.sqrt(dataset.meta["ndim"]) * 0.5
119-
dist1 = np.sum(xyz * dir_vecs[0], axis=1)
118+
diagonal_close = dataset["amr"]["dx"] * 0.5 * np.sqrt(dataset.meta["ndim"])
119+
dist_close = np.sum(xyz * dir_vecs[0], axis=1)
120120
# Create an array of indices to allow further narrowing of the selection below
121-
global_selection = np.arange(len(dataset["amr"]["dx"]))
122-
123-
# Select cells in contact with plane
124-
select = np.ravel(np.where(np.abs(dist1) <= diagonal))
125-
global_selection = global_selection[select]
121+
global_indices = np.arange(len(dataset["amr"]["dx"]))
122+
# Select cells in close to the plane, including factor of sqrt(ndim)
123+
close_to_plane = np.ravel(np.where(np.abs(dist_close) <= diagonal_close))
124+
indices_close_to_plane = global_indices[close_to_plane]
126125

127-
if len(select) == 0:
126+
if len(indices_close_to_plane) == 0:
128127
raise RuntimeError("No cells were selected to construct the plane. "
129128
"The resulting figure would be empty.")
130129

131-
# Project coordinates onto the plane by taking dot product with axes vectors
132-
coords = xyz[select]
133-
datax = np.inner(coords, dir_vecs[1])
134-
datay = np.inner(coords, dir_vecs[2])
135-
datadx = 0.5 * dataset["amr"]["dx"][select]
136-
137-
# Get limits
138-
limits = {
139-
'xmin': np.amin(datax - datadx).values,
140-
'xmax': np.amax(datax + datadx).values,
141-
'ymin': np.amin(datay - datadx).values,
142-
'ymax': np.amax(datay + datadx).values
143-
}
144-
145-
# Define slice extent
146-
if dx is None:
147-
xmin = limits['xmin']
148-
xmax = limits['xmax']
149-
ymin = limits['ymin']
150-
ymax = limits['ymax']
151-
else:
130+
xmin = None
131+
if dx is not None:
152132
xmin = -0.5 * dx.magnitude
153133
xmax = xmin + dx.magnitude
154134
ymin = -0.5 * dy.magnitude
155135
ymax = ymin + dy.magnitude
156136
# Limit selection further by using distance from center
157-
dist2 = coords - datadx * np.sqrt(dataset.meta["ndim"])
158-
select2 = np.ravel(
137+
radial_distance = xyz[indices_close_to_plane] - 0.5 * dataset["amr"]["dx"][
138+
indices_close_to_plane] * np.sqrt(dataset.meta["ndim"])
139+
radial_selection = np.ravel(
159140
np.where(
160-
np.abs(dist2.norm.values) <= max(dx.magnitude, dy.magnitude) * 0.6 *
161-
np.sqrt(2.0)))
162-
coords = coords[select2]
163-
datax = datax[select2]
164-
datay = datay[select2]
165-
datadx = datadx[select2]
166-
global_selection = global_selection[select2]
141+
np.abs(radial_distance.norm.values) <= max(dx.magnitude, dy.magnitude) *
142+
0.6 * np.sqrt(2.0)))
143+
indices_close_to_plane = indices_close_to_plane[radial_selection]
144+
145+
# Select cells touching the plane, excluding factor of sqrt(ndim)
146+
dist_touching = np.sum(xyz[indices_close_to_plane] * dir_vecs[0], axis=1)
147+
diagonal_touching = dataset["amr"]["dx"][indices_close_to_plane] * 0.5
148+
touching_plane = np.ravel(np.where(np.abs(dist_touching) <= diagonal_touching))
149+
150+
# Project coordinates onto the plane by taking dot product with axes vectors
151+
coords_close = xyz[indices_close_to_plane]
152+
datax_close = np.inner(coords_close, dir_vecs[1])
153+
datay_close = np.inner(coords_close, dir_vecs[2])
154+
datadx_close = diagonal_touching
155+
156+
if xmin is None:
157+
xmin = (datax_close - datadx_close).min().values
158+
xmax = (datax_close + datadx_close).max().values
159+
ymin = (datay_close - datadx_close).min().values
160+
ymax = (datay_close + datadx_close).max().values
161+
162+
datax_touching = datax_close[touching_plane]
163+
datay_touching = datay_close[touching_plane]
167164

168165
scalar_layer = []
169-
to_binning = []
166+
cell_variables = [] # contains the variables in cells close to the plane
167+
to_binning = [] # a subset of cell_variables for only cells actually touching plane
170168
for ind in range(len(to_process)):
171169
if to_render[ind]["mode"] in ["vec", "stream"]:
172170
if to_process[ind].ndim < 3:
173-
uv = to_process[ind].array[global_selection]
171+
uv = to_process[ind].array[indices_close_to_plane]
174172
else:
175-
uv = np.inner(to_process[ind].array.take(global_selection, axis=0),
176-
dir_vecs[1:])
173+
uv = np.inner(
174+
to_process[ind].array.take(indices_close_to_plane, axis=0),
175+
dir_vecs[1:])
177176
w = None
178177
if "color" in to_render[ind]["params"]:
179178
if isinstance(to_render[ind]["params"]["color"], Array):
@@ -183,14 +182,22 @@ def plane(*layers,
183182
if w is None:
184183
w = np.linalg.norm(uv, axis=1)
185184
else:
186-
w = w.take(global_selection, axis=0)
187-
to_binning.append(apply_mask(uv[:, 0]))
188-
to_binning.append(apply_mask(uv[:, 1]))
189-
to_binning.append(apply_mask(w))
185+
w = w.take(indices_close_to_plane, axis=0)
186+
vec_u = apply_mask(uv[:, 0])
187+
vec_v = apply_mask(uv[:, 1])
188+
vec_w = apply_mask(w)
189+
cell_variables.append(vec_u)
190+
cell_variables.append(vec_v)
191+
cell_variables.append(vec_w)
190192
scalar_layer.append(False)
193+
to_binning.append(vec_u[touching_plane])
194+
to_binning.append(vec_v[touching_plane])
195+
to_binning.append(vec_w[touching_plane])
191196
else:
192-
to_binning.append(apply_mask(to_process[ind].norm.values[global_selection]))
197+
var = apply_mask(to_process[ind].norm.values[indices_close_to_plane])
198+
cell_variables.append(var)
193199
scalar_layer.append(True)
200+
to_binning.append(var[touching_plane])
194201

195202
# Buffer for counts
196203
to_binning.append(np.ones_like(to_binning[0]))
@@ -206,8 +213,8 @@ def plane(*layers,
206213
ycenters = to_bin_centers(yedges)
207214

208215
# First histogram the cell centers into the grid bins
209-
binned, _, _, _ = binned_statistic_2d(x=apply_mask(datay.array),
210-
y=apply_mask(datax.array),
216+
binned, _, _, _ = binned_statistic_2d(x=apply_mask(datay_touching.array),
217+
y=apply_mask(datax_touching.array),
211218
values=to_binning,
212219
statistic="mean",
213220
bins=[yedges, xedges])
@@ -224,10 +231,11 @@ def plane(*layers,
224231
ygrid.shape + (1, )) * dir_vecs[2]
225232
# We only need to search in the cells above a certain size
226233
large_cells = np.ravel(
227-
np.where(datadx >= 0.25 * (min(xedges[1] - xedges[0], yedges[1] - yedges[0]))))
228-
coords = coords[large_cells]
229-
large_cells_dx = datadx.array[large_cells]
230-
global_indices = np.arange(len(datadx))[large_cells]
234+
np.where(datadx_close >= 0.25 *
235+
(min(xedges[1] - xedges[0], yedges[1] - yedges[0]))))
236+
coords = coords_close[large_cells]
237+
large_cells_dx = datadx_close.array[large_cells]
238+
large_cells_indices = np.arange(len(datadx_close))[large_cells]
231239

232240
# To keep memory usage down to a minimum, we process the image one column at a time
233241
for i in range(indices.shape[-1]):
@@ -255,7 +263,7 @@ def plane(*layers,
255263
inds = np.logical_and.reduce(
256264
[np.abs(d) <= large_cells_dx[column] for d in distance_to_cell])
257265
index_found = inds.max(axis=-1)
258-
index_value = global_indices[column][inds.argmax(axis=-1)]
266+
index_value = large_cells_indices[column][inds.argmax(axis=-1)]
259267
indices[:, i][index_found] = index_value[index_found]
260268
mask[:, i][np.logical_and(~index_found, condition[:, i])] = True
261269
else:
@@ -266,13 +274,13 @@ def plane(*layers,
266274
# Now we fill the arrays to be sent to the renderer, also constructing vectors
267275
counter = 0
268276
for ind in range(len(to_render)):
269-
binned[counter][condition] = to_binning[counter][indices][condition]
277+
binned[counter][condition] = cell_variables[counter][indices][condition]
270278
if scalar_layer[ind]:
271279
to_render[ind]["data"] = ma.masked_where(mask, binned[counter], copy=False)
272280
counter += 1
273281
else:
274282
for j in range(counter + 1, counter + 3):
275-
binned[j][condition] = to_binning[j][indices][condition]
283+
binned[j][condition] = cell_variables[j][indices][condition]
276284
to_render[ind]["data"] = ma.masked_where(mask_vec,
277285
np.array([
278286
binned[counter].T,
@@ -293,11 +301,8 @@ def plane(*layers,
293301

294302
# Add scatter layer
295303
if len(to_scatter) > 0:
296-
_add_scatter(datax=datax,
297-
datay=datay,
298-
to_scatter=to_scatter,
304+
_add_scatter(to_scatter=to_scatter,
299305
origin=origin,
300-
datadx=datadx,
301306
dir_vecs=dir_vecs,
302307
dx=dx,
303308
dy=dy,

0 commit comments

Comments
 (0)