Skip to content

Conversation

@rochSmets
Copy link
Contributor

To plot a dis_plot using a point per particle (and not a pcolormesh of a given binning of the phase space), the command line could be

p,f = ions.dist_plot(axis=("x", "Vx"),
                     ax=ax,
                     norm = 0.4,
                     finest=True,
                     plain=True,
                     stride=10,
                     color='tab:gray',
                     alpha=1,
                     markersize=2,
                     vmin=-1,vmax=1,
                     title="weak perturbation at time : {:.2f}".format(time),
                    )

where plain says we want a point per particle, stride says that we plot 1 over stride particle, color, alpha and markersize being straightforward.

It could also be

p,(f, a) = ions.dist_plot(axis=("Vx",),
                          drawstyle="default",
                          ax=ax,
                          finest=True,
                          cuts=((40, 80),),
                          vmin=-0.6,vmax=0.6,
                          dv=0.02,
                          title="weak perturbation at time : {:.2f}".format(time),
                         )

to have a 1-D distribution (that is f(v_x) in this example). By default, drawstyle="mid-steps" to make sure that the choice for the binning is explicit, so that drawstyle="default" can be a kwargs. Hence, cuts is a tuple of dim ndim, where each element is a tuple of 2 elements containg lower and upper values of the cutting box for the iven direction. By default, cuts=None, meaning that all the particles are considered.

It has to be clear that even if the kwarg name is cut, this is a cut in position space, but not in velocity space. It means that in the plot of f(v_x) for example, we have an implicit summation over v_y and v_z.

@coderabbitai
Copy link

coderabbitai bot commented Jan 8, 2026

📝 Walkthrough

Walkthrough

Distribution plotting logic was split between 1D and 2D based on len(axis). 2D now computes explicit 2D histograms, adds optional Gaussian/median filtering and two rendering modes. 1D supports particle-subset cuts, adjusted histogram/averaging flows, and updated axis labels/defaults.

Changes

Cohort / File(s) Summary
Axis length handling
pyphare/pyphare/pharesee/hierarchy/hierarchy.py, pyphare/pyphare/pharesee/plotting.py
Branch on len(axis) to distinguish 1D vs 2D behavior; avoid indexing axis[0] for single-element axis inputs and set bins accordingly.
2D histogram, filtering and rendering
pyphare/pyphare/pharesee/plotting.py
Adds explicit 2D histogram creation (histogram2d) with weights, optional Gaussian or median filtering (mutually exclusive), and two render modes: color-mapped image with colorbar or plain line/marker plotting with stride/markersize/alpha.
1D histogram and particle selection (cuts)
pyphare/pyphare/pharesee/plotting.py
Supports single-axis distributions with optional cuts (Box) to create new_particles subset used for histogramming, averages/bulk lines, and plotting; enforces velocity-axis checks for certain abscissas.
Labels and defaults
pyphare/pyphare/pharesee/plotting.py
Updates default labels and ylabel behavior (e.g., default f for 1D, "$x \\ (d_p)$"/"$y \\ (d_p)$" for spatial axes) and adjusts axis labeling across 1D/2D and plain/non-plain rendering modes.

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant dist_plot
  participant HistEngine as Histogram Engine
  participant Filter as Filter (Gaussian/Median)
  participant Renderer as Matplotlib Renderer

  Caller->>dist_plot: call with axis, vbins, weights, cuts, options
  dist_plot->>dist_plot: evaluate len(axis)
  alt 2D path
    dist_plot->>HistEngine: compute 2D histogram (histogram2d) with weights
    HistEngine-->>dist_plot: hist, xedges, yedges
    alt filtering requested
      dist_plot->>Filter: apply gaussian or median filter
      Filter-->>dist_plot: filtered_hist
    end
    dist_plot->>Renderer: render image (colormap + colorbar) or plain markers/lines
    Renderer-->>Caller: display/return figure
  else 1D path
    dist_plot->>dist_plot: apply cuts -> new_particles (optional)
    dist_plot->>HistEngine: compute 1D histogram from (new_)particles
    HistEngine-->>dist_plot: hist, edges
    dist_plot->>Renderer: plot line (drawstyle) and averages/bulk lines
    Renderer-->>Caller: display/return figure
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title directly describes the main changes: adding plain plotting mode (point per particle) and cuts functionality to dist_plot.
Description check ✅ Passed The description provides concrete examples and explains both new features (plain=True mode and cuts parameter) with usage context.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

stride = kwargs.get("stride", 1)
markersize = kwargs.get("markersize", 0.5)
alpha = kwargs.get("alpha", 0.5)
im = ax.plot(x[::stride], y[::stride],

Check notice

Code scanning / CodeQL

Unused local variable Note

Variable im is not used.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, like the one defined with the previous pcolormesh. But lets keep this handle around !

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, but let's keep it,

cmin = kwargs.get("color_min", h.min())
cmin = max(cmin, 1e-4)
xh_ = 0.5*(xh[:-1]+xh[1:])
im = ax.plot(xh_, h, drawstyle=drawstyle)

Check notice

Code scanning / CodeQL

Unused local variable Note

Variable im is not used.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see above

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the same,

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
pyphare/pyphare/pharesee/plotting.py (3)

167-184: new_particles undefined in 2D axis mode, causing NameError when bulk=True.

The variable new_particles is only assigned in the len(axis) == 1 branch (lines 124-136). When len(axis) == 2 and bulk=True, this code will raise NameError.

Additionally, the reference to axis[1] at line 177 will cause IndexError in 1D mode.

🐛 Proposed fix
     if "bulk" in kwargs:
         if kwargs["bulk"] is True:
+            # Use particles for 2D, new_particles for 1D
+            bulk_particles = new_particles if len(axis) == 1 else particles
             if axis[0] in vaxis:
                 ax.axvline(
                     np.average(
-                        new_particles.v[:, vaxis[axis[0]]], weights=new_particles.weights
+                        bulk_particles.v[:, vaxis[axis[0]]], weights=bulk_particles.weights
                     ),
                     color="w",
                     ls="--",
                 )
-            if axis[1] in vaxis:
+            if len(axis) > 1 and axis[1] in vaxis:
                 ax.axhline(
                     np.average(
-                        new_particles.v[:, vaxis[axis[1]]], weights=new_particles.weights
+                        bulk_particles.v[:, vaxis[axis[1]]], weights=bulk_particles.weights
                     ),
                     color="w",
                     ls="--",
                 )

189-197: interp feature uses variables only defined in 2D mode.

The interpolation logic references yh and image, which are only defined when len(axis) == 2. If interp=True with a 1D axis specification, this will raise NameError.

🐛 Proposed fix: guard interp block for 2D only
     interp = kwargs.get("interp", False)

-    if interp:
+    if interp and len(axis) == 2:
         xbins = 0.5 * (xh[1:] + xh[:-1])
         ybins = 0.5 * (yh[1:] + yh[:-1])
         xx, yy = np.meshgrid(xbins, ybins, indexing="ij")
         coords = np.array([xx.flatten(), yy.flatten()]).T
         interpdist = LinearNDInterpolator(coords, image.T.flatten())
         return fig, ax, interpdist, xbins, ybins
+    elif interp and len(axis) == 1:
+        raise ValueError("interp=True is not supported for 1D axis plots")

154-157: KDE feature uses y which is undefined in 1D mode.

The kde block references both x and y, but in the 1D axis branch, y is never defined. This will cause NameError when kde=True with a single-axis specification.

🐛 Proposed fix: guard KDE for 2D only
-    if kwargs.get("kde", False) is True:
+    if kwargs.get("kde", False) is True and len(axis) == 2:
         import seaborn as sns

         sns.kdeplot(x=x, y=y, ax=ax, color="w")
🤖 Fix all issues with AI agents
In @pyphare/pyphare/pharesee/plotting.py:
- Around line 95-101: The code sets norm only for "log" and "linear" color_scale
values, so if color_scale is anything else norm remains uninitialized and
ax.pcolormesh will raise UnboundLocalError; fix by adding an explicit else
branch after the existing if/elif to either (a) raise a clear ValueError
mentioning the unsupported color_scale, or (b) fall back to a default (e.g., set
norm = Normalize(cmin, cmax)); update the block around
color_scale/LogNorm/Normalize and the ax.pcolormesh call so norm is always
defined or an exception is raised with a helpful message.
- Around line 56-67: The code in the block handling len(axis)==2 can leave x or
y undefined (used later in np.histogram2d) when axis values aren't matched;
ensure x and y are always assigned before the histogram call by handling all
expected axis name cases (e.g., check axis[0]/axis[1] for vaxis entries and for
explicit spatial names like "x","y","z"), and if an unknown axis is passed raise
a clear ValueError; update the branch logic around vaxis, axis, and particles
(the symbols vaxis, axis, particles, and the histogram2d call) so x and y are
initialized for every valid input path or an explicit error is thrown.
🧹 Nitpick comments (1)
pyphare/pyphare/pharesee/plotting.py (1)

387-388: LaTeX string uses \\ which renders as a line break, not a space.

The double backslash in LaTeX ($x \\ (d_p)$) creates a line break. For a space between x and (d_p), use \ (backslash-space) or a regular space.

♻️ Suggested fix
-    ax.set_xlabel(kwargs.get("xlabel", "$x \\ (d_p)$"))
-    ax.set_ylabel(kwargs.get("ylabel", "$y \\ (d_p)$"))
+    ax.set_xlabel(kwargs.get("xlabel", r"$x\ (d_p)$"))
+    ax.set_ylabel(kwargs.get("ylabel", r"$y\ (d_p)$"))

Using raw strings (r"...") avoids escaping issues with backslashes.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8cd180f and 7c0c1a8.

📒 Files selected for processing (2)
  • pyphare/pyphare/pharesee/hierarchy/hierarchy.py
  • pyphare/pyphare/pharesee/plotting.py
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2024-10-18T13:23:32.074Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 910
File: pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py:7-7
Timestamp: 2024-10-18T13:23:32.074Z
Learning: In the `pyphare.pharesee.hierarchy` module, importing `PatchHierarchy` and `format_timestamp` from `hierarchy.py` into `hierarchy_utils.py` is acceptable as long as `hierarchy.py` does not import `hierarchy_utils.py`, thereby avoiding a cyclic import.

Applied to files:

  • pyphare/pyphare/pharesee/hierarchy/hierarchy.py
🧬 Code graph analysis (1)
pyphare/pyphare/pharesee/plotting.py (2)
pyphare/pyphare/pharesee/particles.py (4)
  • x (46-49)
  • y (52-55)
  • size (75-76)
  • select (102-135)
pyphare/pyphare/core/box.py (1)
  • Box (5-69)
🪛 GitHub Check: CodeQL
pyphare/pyphare/pharesee/plotting.py

[failure] 66-66: Potentially uninitialized local variable
Local variable 'x' may be used before it is initialized.


[failure] 66-66: Potentially uninitialized local variable
Local variable 'y' may be used before it is initialized.


[failure] 101-101: Potentially uninitialized local variable
Local variable 'norm' may be used before it is initialized.


[failure] 145-145: Potentially uninitialized local variable
Local variable 'x' may be used before it is initialized.


[notice] 109-109: Unused local variable
Variable im is not used.


[notice] 149-149: Unused local variable
Variable im is not used.

🪛 Ruff (0.14.10)
pyphare/pyphare/pharesee/plotting.py

82-84: Avoid specifying long messages outside the exception class

(TRY003)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Analyze (python)
  • GitHub Check: Analyze (cpp)
  • GitHub Check: build (macos-latest)
  • GitHub Check: build (macos-14)
  • GitHub Check: build (ubuntu-latest, gcc)
  • GitHub Check: build (ubuntu-latest, clang)
🔇 Additional comments (1)
pyphare/pyphare/pharesee/hierarchy/hierarchy.py (1)

586-594: LGTM!

The axis length branching logic correctly handles both 2D and 1D axis specifications. The 2D case preserves the original behavior, and the 1D case appropriately assigns vbins directly without attempting to access axis[0].

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
pyphare/pyphare/pharesee/plotting.py (3)

162-165: NameError when kde=True with 1D axis.

In the 1D branch (len(axis) == 1), only x is defined. The KDE section references y which will raise NameError. KDE plotting should be guarded to only run for 2D cases.

🐛 Proposed fix
-    if kwargs.get("kde", False) is True:
+    if kwargs.get("kde", False) is True and len(axis) == 2:
         import seaborn as sns
 
         sns.kdeplot(x=x, y=y, ax=ax, color="w")

175-192: NameError and IndexError in bulk velocity section.

Two issues here:

  1. new_particles undefined in 2D branch: new_particles is only assigned in the 1D branch (lines 134-142). When using bulk=True with a 2D axis, lines 180 and 188 will raise NameError.

  2. IndexError on axis[1] in 1D case: Line 185 accesses axis[1], but when len(axis) == 1, this will raise IndexError.

🐛 Proposed fix
     if "bulk" in kwargs:
         if kwargs["bulk"] is True:
+            # Use appropriate particles reference based on branch
+            bulk_particles = new_particles if len(axis) == 1 else particles
             if axis[0] in vaxis:
                 ax.axvline(
                     np.average(
-                        new_particles.v[:, vaxis[axis[0]]], weights=new_particles.weights
+                        bulk_particles.v[:, vaxis[axis[0]]], weights=bulk_particles.weights
                     ),
                     color="w",
                     ls="--",
                 )
-            if axis[1] in vaxis:
+            if len(axis) == 2 and axis[1] in vaxis:
                 ax.axhline(
                     np.average(
-                        new_particles.v[:, vaxis[axis[1]]], weights=new_particles.weights
+                        bulk_particles.v[:, vaxis[axis[1]]], weights=bulk_particles.weights
                     ),
                     color="w",
                     ls="--",
                 )

197-205: NameError when interp=True with 1D axis.

Variables yh and image are only defined in the 2D branch. Using interp=True with a 1D axis will raise NameError. The interpolation feature is inherently 2D, so it should be guarded.

🐛 Proposed fix
     interp = kwargs.get("interp", False)
 
-    if interp:
+    if interp and len(axis) == 2:
         xbins = 0.5 * (xh[1:] + xh[:-1])
         ybins = 0.5 * (yh[1:] + yh[:-1])
         xx, yy = np.meshgrid(xbins, ybins, indexing="ij")
         coords = np.array([xx.flatten(), yy.flatten()]).T
         interpdist = LinearNDInterpolator(coords, image.T.flatten())
         return fig, ax, interpdist, xbins, ybins
+    elif interp and len(axis) == 1:
+        raise ValueError("interp=True is only supported for 2D axis")
🤖 Fix all issues with AI agents
In `@pyphare/pyphare/pharesee/plotting.py`:
- Around line 130-140: The cuts are meant to be in position space but
particles.select(box_new) defaults to cell indices; update the ndim==1 branch in
plotting.py to call particles.select(box_new, box_type="pos") so the Box bounds
are interpreted as positions (use symbols cuts, Box, particles.select, ndim); do
not change the 2D/3D branches until particles.select supports box_type="pos" for
ndim>1 (or add an explicit guard/clear TODO comment/assert there).
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7c0c1a8 and a752c9d.

📒 Files selected for processing (2)
  • pyphare/pyphare/pharesee/hierarchy/hierarchy.py
  • pyphare/pyphare/pharesee/plotting.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • pyphare/pyphare/pharesee/hierarchy/hierarchy.py
🧰 Additional context used
🧬 Code graph analysis (1)
pyphare/pyphare/pharesee/plotting.py (2)
pyphare/pyphare/pharesee/particles.py (3)
  • x (46-49)
  • y (52-55)
  • select (102-135)
pyphare/pyphare/core/box.py (1)
  • Box (5-69)
🪛 Ruff (0.14.11)
pyphare/pyphare/pharesee/plotting.py

62-62: Avoid specifying long messages outside the exception class

(TRY003)


66-66: Avoid specifying long messages outside the exception class

(TRY003)


86-88: Avoid specifying long messages outside the exception class

(TRY003)


105-105: Avoid specifying long messages outside the exception class

(TRY003)


149-149: Avoid specifying long messages outside the exception class

(TRY003)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: build (macos-latest)
  • GitHub Check: build (macos-14)
  • GitHub Check: build (ubuntu-latest, clang)
  • GitHub Check: build (ubuntu-latest, gcc)
  • GitHub Check: Analyze (python)
  • GitHub Check: Analyze (cpp)
🔇 Additional comments (3)
pyphare/pyphare/pharesee/plotting.py (3)

56-71: LGTM for axis extraction and error handling.

The uninitialized variable issues flagged in previous reviews are now properly addressed with explicit ValueError raises for unsupported axis combinations.


73-88: Well-structured filter handling with proper mutual exclusion.

The logic correctly ensures gaussian and median filters cannot be applied simultaneously, with a clear error message when both are specified.


395-396: Good improvement to default axis labels with units.

The updated default labels with proper LaTeX formatting and units ($d_p$) improve clarity for users.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
pyphare/pyphare/pharesee/plotting.py (3)

162-165: NameError when kde=True with 1D axis.

The KDE plot uses both x and y, but y is only defined in the 2D branch. Using kde=True with len(axis) == 1 will crash.

🐛 Proposed fix to guard KDE for 2D only
-    if kwargs.get("kde", False) is True:
+    if kwargs.get("kde", False) is True and len(axis) == 2:
         import seaborn as sns

         sns.kdeplot(x=x, y=y, ax=ax, color="w")

175-192: NameError when bulk=True with 2D axis.

new_particles is only assigned in the 1D branch (inside len(axis) == 1). For 2D plots, this code path will crash because new_particles is undefined.

🐛 Proposed fix to use correct particle reference
     if "bulk" in kwargs:
         if kwargs["bulk"] is True:
+            # Use new_particles if defined (1D with cuts), otherwise use particles
+            p = new_particles if 'new_particles' in dir() else particles
             if axis[0] in vaxis:
                 ax.axvline(
                     np.average(
-                        new_particles.v[:, vaxis[axis[0]]], weights=new_particles.weights
+                        p.v[:, vaxis[axis[0]]], weights=p.weights
                     ),
                     color="w",
                     ls="--",
                 )
-            if axis[1] in vaxis:
+            if len(axis) == 2 and axis[1] in vaxis:
                 ax.axhline(
                     np.average(
-                        new_particles.v[:, vaxis[axis[1]]], weights=new_particles.weights
+                        p.v[:, vaxis[axis[1]]], weights=p.weights
                     ),
                     color="w",
                     ls="--",
                 )

Alternatively, define new_particles = particles at the start of dist_plot and only reassign when cuts are applied.


197-205: NameError when interp=True with 1D axis.

Variables yh and image are only defined in the 2D branch. The interpolation feature will crash for 1D plots.

🐛 Proposed fix to guard interp for 2D only
     interp = kwargs.get("interp", False)

-    if interp:
+    if interp and len(axis) == 2:
         xbins = 0.5 * (xh[1:] + xh[:-1])
         ybins = 0.5 * (yh[1:] + yh[:-1])
         xx, yy = np.meshgrid(xbins, ybins, indexing="ij")
         coords = np.array([xx.flatten(), yy.flatten()]).T
         interpdist = LinearNDInterpolator(coords, image.T.flatten())
         return fig, ax, interpdist, xbins, ybins
+    elif interp and len(axis) == 1:
+        raise ValueError("interp=True is only supported for 2D distribution plots")
🧹 Nitpick comments (1)
pyphare/pyphare/pharesee/plotting.py (1)

126-126: Dead code: bins is reassigned before use.

This assignment is immediately overwritten at line 151 before bins is ever used. Remove this line to avoid confusion.

♻️ Suggested fix
     elif len(axis) == 1:
-        bins = kwargs.get("bins", (50))
         cuts = kwargs.get("cuts", None)
         ndim = particles.ndim
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a752c9d and 004ff09.

📒 Files selected for processing (2)
  • pyphare/pyphare/pharesee/hierarchy/hierarchy.py
  • pyphare/pyphare/pharesee/plotting.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • pyphare/pyphare/pharesee/hierarchy/hierarchy.py
🧰 Additional context used
🧬 Code graph analysis (1)
pyphare/pyphare/pharesee/plotting.py (2)
pyphare/pyphare/pharesee/particles.py (3)
  • x (46-49)
  • y (52-55)
  • select (102-135)
pyphare/pyphare/core/box.py (1)
  • Box (5-69)
🪛 Ruff (0.14.11)
pyphare/pyphare/pharesee/plotting.py

62-62: Avoid specifying long messages outside the exception class

(TRY003)


66-66: Avoid specifying long messages outside the exception class

(TRY003)


86-88: Avoid specifying long messages outside the exception class

(TRY003)


105-105: Avoid specifying long messages outside the exception class

(TRY003)


149-149: Avoid specifying long messages outside the exception class

(TRY003)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: build (ubuntu-latest, gcc)
  • GitHub Check: build (ubuntu-latest, clang)
  • GitHub Check: Analyze (cpp)
  • GitHub Check: build (macos-14)
  • GitHub Check: build (macos-latest)
  • GitHub Check: Analyze (python)
🔇 Additional comments (2)
pyphare/pyphare/pharesee/plotting.py (2)

56-71: LGTM - Axis handling properly guards against uninitialized variables.

The ValueError raises for unsupported axis combinations correctly address the static analysis warnings from previous reviews. The explicit error messages make the supported axis combinations clear.


395-396: LGTM - Axis labels updated to use ion inertial length units.

The label change from $x c / \omega_p$ to $x \ (d_p)$ provides cleaner notation using the ion inertial length normalization.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment on lines +135 to +140
elif ndim == 2:
box_new = Box((cuts[0][0], cuts[1][0]), (cuts[0][1], cuts[1][1])) # TODO need to be tested
new_particles = particles.select(box_new, box_type="pos")
else:
box_new = Box((cuts[0][0], cuts[1][0], cuts[2][0]), (cuts[0][1], cuts[1][1], cuts[2][1])) # TODO need to be tested
new_particles = particles.select(box_new, box_type="pos")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

box_type="pos" will fail for ndim > 1.

The particles.select() method asserts self.ndim == 1 when box_type="pos" is used. The 2D and 3D branches here will raise AssertionError at runtime.

Since these branches are marked TODO, consider adding explicit guards or raising NotImplementedError until select() is extended.

🐛 Proposed fix to prevent runtime assertion failures
         if cuts is not None:
             from pyphare.core.box import Box
             if ndim == 1:
                 box_new = Box(cuts[0][0], cuts[0][1])
                 new_particles = particles.select(box_new, box_type="pos")
             elif ndim == 2:
-                box_new = Box((cuts[0][0], cuts[1][0]), (cuts[0][1], cuts[1][1]))  # TODO need to be tested
-                new_particles = particles.select(box_new, box_type="pos")
+                raise NotImplementedError("Position-space cuts for 2D simulations not yet supported")
             else:
-                box_new = Box((cuts[0][0], cuts[1][0], cuts[2][0]), (cuts[0][1], cuts[1][1], cuts[2][1]))  # TODO need to be tested
-                new_particles = particles.select(box_new, box_type="pos")
+                raise NotImplementedError("Position-space cuts for 3D simulations not yet supported")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant