Name | emout JSON |
Version |
2.4.1
JSON |
| download |
home_page | None |
Summary | Emses output manager |
upload_time | 2025-07-23 01:04:52 |
maintainer | None |
docs_url | None |
author | None |
requires_python | >=3.7 |
license | None |
keywords |
visualization
simulation
emses
|
VCS |
 |
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# emout
A Python library for parsing and visualizing output files generated by [EMSES](https://github.com/Nkzono99/MPIEMSES3D) simulations.
- **Documentation:** [https://nkzono99.github.io/emout/](https://nkzono99.github.io/emout/)
## Installation
```bash
pip install emout
```
## Example
- [Visualization of simulation results for lunar surface charging](https://nbviewer.org/github/Nkzono99/examples/blob/main/examples/emout/example.ipynb)
## Overview
When you run EMSES simulations, the results (e.g., potentials, densities, currents) are output in `.h5` files, and a parameter file (`plasma.inp`) contains the simulation settings. **emout** helps you:
- [emout](#emout)
- [Installation](#installation)
- [Example](#example)
- [Overview](#overview)
- [Usage](#usage)
- [Loading Data](#loading-data)
- [Retrieving the Parameter File (plasma.inp)](#retrieving-the-parameter-file-plasmainp)
- [Plotting Data](#plotting-data)
- [Working with Units](#working-with-units)
- [Handling Appended Simulation Outputs](#handling-appended-simulation-outputs)
- [Data Masking](#data-masking)
- [Creating Animations](#creating-animations)
- [Solving Poisson’s Equation (Experimental)](#solving-poissons-equation-experimental)
- [Backtrace Usage Examples (Experimental)](#backtrace-usage-examples-experimental)
- [Install vdist-solver-fortran](#install-vdist-solver-fortran)
- [Running backtrace on HPC computational nodes with Dask (\>= Python3.10)](#running-backtrace-on-hpc-computational-nodes-with-dask--python310)
- [1. Perform a batch backtrace and plot sampled trajectories](#1-perform-a-batch-backtrace-and-plot-sampled-trajectories)
- [2. Compute a velocity–space probability distribution and plot $v\_x$ vs $v\_z$](#2-compute-a-velocityspace-probability-distribution-and-plot-v_x-vs-v_z)
- [3. Backtrace using the particles from a previous probability calculation, then plot $x$–$z$ trajectories with probability as transparency](#3-backtrace-using-the-particles-from-a-previous-probability-calculation-then-plot-xz-trajectories-with-probability-as-transparency)
Below, you will find usage examples that assume the following directory structure:
```
.
└── output_dir
├── plasma.inp
├── phisp00_0000.h5
├── nd1p00_0000.h5
├── nd2p00_0000.h5
├── j1x00_0000.h5
├── j1y00_0000.h5
...
└── bz00_0000.h5
```
---
## Usage
### Loading Data
```python
import emout
# Initialize Emout with the path to the output directory
data = emout.Emout('output_dir')
# Access arrays by their variable names (derived from EMSES filename)
data.phisp # Data from phisp00_0000.h5
len(data.phisp) # Number of time steps
data.phisp[0].shape
data.j1x
data.bz
data.j1xy # Vector data from "j1x00_0000.h5" + "j1y00_0000.h5"
# Data created by "relocating" ex00_0000.h5
data.rex
# Access data as a pandas DataFrame
data.icur
data.pbody
```
---
### Retrieving the Parameter File (plasma.inp)
```python
# The namelist is parsed into a dictionary-like structure
data.inp
data.inp['tmgrid']['nx'] # Access via group name and parameter name
data.inp['nx'] # Group name can be omitted if not ambiguous
data.inp.tmgrid.nx # Access like object attributes
data.inp.nx # Still valid
```
---
### Plotting Data
```python
x, y, z = 32, 32, 100
# Basic 2D plot (xy-plane at z=100 for the last timestep)
data.phisp[-1, z, :, :].plot()
# Line plot along z-axis at x=32, y=32
data.phisp[-1, :, y, x].plot()
# Plot using SI units
data.phisp[-1, z, :, :].plot(use_si=True) # Default is True
# Show or save plot
data.phisp[-1, z, :, :].plot(show=True)
data.phisp[-1, z, :, :].plot(savefilename='phisp.png')
# Plot vector field as a streamline
data.j1xy[-1, z, :, :].plot()
```
---
### Working with Units
> **Note**
> EMSES → SI conversion is supported only when the first line of `plasma.inp` includes something like:
> ```text
> !!key dx=[0.5],to_c=[10000.0]
> ```
> where `dx` is the grid spacing [m], and `to_c` is the (normalized) speed of light used internally by EMSES.
```python
# Converting between physical (SI) and EMSES units
data.unit.v.trans(1) # Convert 1 m/s to EMSES velocity unit
data.unit.v.reverse(1) # Convert 1 EMSES velocity unit to m/s
# Access converted data in SI units
phisp_volt = data.phisp[-1, :, :, :].val_si # Potential in volts [V]
j1z_A_per_m2 = data.j1z[-1, :, :, :].val_si # Current density [A/m^2]
nd1p_per_cc = data.nd1p[-1, :, :, :].val_si # Number density [1/cm^3]
```
<details>
<summary>Unit Name List</summary>
```
B = Magnetic flux density [T]
C = Capacitance [F]
E = Electric field [V/m]
F = Force [N]
G = Conductance [S]
J = Current density [A/m^2]
L = Inductance [H]
N = Flux [/m^2s]
P = Power [W]
T = Temperature [K]
W = Energy [J]
a = Acceleration [m/s^2]
c = Light Speed [m/s]
e = Napiers constant []
e0 = FS-Permttivity [F/m]
eps = Permittivity [F/m]
f = Frequency [Hz]
i = Current [A]
kB = Boltzmann constant [J/K]
length = Sim-to-Real length ratio [m]
m = Mass [kg]
m0 = FS-Permeablity [N/A^2]
mu = Permiability [H/m]
n = Number density [/m^3]
phi = Potential [V]
pi = Circular constant []
q = Charge [C]
q_m = Charge-to-mass ratio [C/kg]
qe = Elementary charge [C]
qe_me = Electron charge-to-mass ratio [C/kg]
rho = Charge density [C/m^3]
t = Time [s]
v = Velocity [m/s]
w = Energy density [J/m^3]
```
</details>
---
### Handling Appended Simulation Outputs
<details>
<summary>Examples</summary>
If your simulation continues and creates new directories:
```python
import emout
# Merge multiple output directories into one Emout object
data = emout.Emout('output_dir', append_directories=['output_dir_2', 'output_dir_3'])
# Same as above if 'ad="auto"' is specified (detects appended outputs automatically)
data = emout.Emout('output_dir', ad='auto')
```
</details>
---
### Data Masking
<details>
<summary>Examples</summary>
```python
# Mask values below the average
data.phisp[1].masked(lambda phi: phi < phi.mean())
# Equivalent manual approach
phi = data.phisp[1].copy()
phi[phi < phi.mean()] = float('nan')
```
</details>
---
### Creating Animations
<details>
<summary>Examples</summary>
```python
# Create a time-series animation along the first axis (time = 0)
x, y, z = 32, 32, 100
data.phisp[:, z, :, :].gifplot()
# Specify a different axis (default is axis=0)
data.phisp[:, z, :, :].gifplot(axis=0)
# Save animation as a GIF
data.phisp[:, z, :, :].gifplot(action='save', filename='phisp.gif')
# Display the animation inline in a Jupyter notebook
data.phisp[:, z, :, :].gifplot(action='to_html')
# Combining multiple frames for a single animation
updater0 = data.phisp[:, z, :, :].gifplot(action='frames', mode='cmap')
updater1 = data.phisp[:, z, :, :].build_frame_updater(mode='cont')
updater2 = data.nd1p[:, z, :, :].build_frame_updater(mode='cmap', vmin=1e-3, vmax=20, norm='log')
updater3 = data.nd2p[:, z, :, :].build_frame_updater(mode='cmap', vmin=1e-3, vmax=20, norm='log')
updater4 = data.j2xy[:, z, :, :].build_frame_updater(mode='stream')
layout = [
[
[updater0, updater1],
[updater2],
[updater3, updater4]
]
]
animator = updater0.to_animator(layout=layout)
animator.plot(action='to_html') # or 'save', 'show', etc.
```
</details>
---
### Solving Poisson’s Equation (Experimental)
You can solve Poisson’s equation from 3D charge distributions using `emout.poisson` (depends on `scipy`):
<details>
<summary>Examples</summary>
```python
import numpy as np
import scipy.constants as cn
from emout import Emout, poisson
data = Emout('output_dir')
dx = data.inp.dx # [m] Grid spacing
rho = data.rho[-1].val_si # [C/m^3] Charge distribution
btypes = ["pdn"[i] for i in data.inp.mtd_vbnd] # Boundary conditions
# Solve Poisson’s equation for potential
phisp = poisson(rho, dx=dx, btypes=btypes, epsilon_0=cn.epsilon_0)
# Compare with EMSES potential
np.allclose(phisp, data.phisp[-1]) # Should be True (within numerical tolerance)
```
</details>
---
### Backtrace Usage Examples (Experimental)
<details>
<summary>Examples</summary>
#### Install vdist-solver-fortran
```bash
pip install git+https://github.com/Nkzono99/vdist-solver-fortran.git
```
Below are three example workflows demonstrating how to use the `data.backtrace` interface. All examples assume you have already created an `Emout` object named `data`.
<details>
<summary>with Dask</summary>
#### Running backtrace on HPC computational nodes with Dask (>= Python3.10)
If you’ve set up a Dask cluster via `emout.distributed`, all of the `data.backtrace` calls below will actually run on your computational nodes instead of your login node.
```python
from emout.distributed import start_cluster, stop_cluster
import emout
# ① Dask クラスタを起動(SLURM ジョブを一時的に作成して Worker を常駐させる)
client = start_cluster(
partition="gr20001a", # 使用するキュー
processes=1, # プロセス数
cores=112, # コア数
memory="60G", # メモリ
walltime="03:00:00", # 最大実行時間
scheduler_ip=None, # ログインノード上の Scheduler IP (e.g. "10.10.64.1", Noneで自動検索)
scheduler_port=32332, # Scheduler ポート
)
# ② 通常の data.backtrace API を呼び出すだけで、
# 図のようにバックトレース関数群が計算ノード上で実行されます
data = emout.Emout("output_dir")
result = data.backtrace.get_probabilities(
128, 128, 200,
(-data.inp.path[0]*3, data.inp.path[0]*3, 500),
1,
(-data.inp.path[0]*4, data.inp.path[0]*3, 500),
ispec=0,
istep=-1,
dt=data.inp.dt,
max_step=100000,
n_threads=112,
)
result.vxvz.plot()
# ③ 終了後はクライアントを閉じて Scheduler を停止
stop_cluster()
```
</details>
#### 1. Perform a batch backtrace and plot sampled trajectories
In this example, we generate 10 particles with varying initial positions and velocities, compute their backtraces, randomly sample 5 backtrace trajectories, and then plot the $x–y$ projection of each sampled trajectory.
```python
import numpy as np
import matplotlib.pyplot as plt
# 1) Prepare 10 initial positions and velocities
# Positions: (128, 128, 60 + i*2) for i = 0, 1, …, 9
# Velocities: (0, 0, -10*i) for i = 0, 1, …, 9
positions = np.array([[128, 128, 60 + 2 * i] for i in range(10)])
velocities = np.array([[0, 0, -10 * i] for i in range(10)])
# 2) Compute backtraces for all 10 particles
# This returns a MultiBacktraceResult object
backtrace_result = data.backtrace.get_backtraces(positions, velocities)
# 3) Sample 5 trajectories. Then plot the x vs y projection.
sampled_result = backtrace_result.sample(5)
ax = sampled_result.xy.plot()
ax.set_title("Backtrace: Sampled 10 Trajectories (x vs y)")
plt.show()
```
#### 2. Compute a velocity–space probability distribution and plot $v_x$ vs $v_z$
Here, we call `get_probabilities(...)` to generate a 6D phase grid $(x, y, z, vx, vy, vz)$, invoke the backend solver to compute the probability for each $(x,y,z,v_x,v_y,v_z)$ cell, and then plot the 2D slice in $(v_x, v_z)$ space.
```python
# 1) Call get_probabilities on a 1×1×1 (x,y,z) cell at (128,128,60),
# with vx in [-3*dx, +3*dx] sampled over 10 points,
# vy fixed at 0, and vz in [-3*dx, 0] sampled over 10 points.
# ispec=0 indicates electron species.
probability_result = data.backtrace.get_probabilities(
128, # x = constant 128 (single cell)
128, # y = constant 128
60, # z = constant 60
(-data.inp.path[0] * 3, # vx from –3*dx
+data.inp.path[0] * 3, 10), # to +3*dx in 10 steps
0, # vy = 0
(-data.inp.path[0] * 3, # vz from –3*dx
0, 10), # to 0 in 10 steps
ispec=0, # electron species
)
# 2) Plot the resulting probability on the vx–vz plane
ax = probability_result.vxvz.plot(shading="auto", cmap="plasma")
ax.set_title("Probability Distribution: vx vs vz (ispec=0)")
plt.show()
```
#### 3. Backtrace using the particles from a previous probability calculation, then plot $x$–$z$ trajectories with probability as transparency
In this final example, we take the `particles` array produced internally by `get_probabilities(...)`, run backtraces on each of those particles, and then plot the $x$–$z$ projections of all backtraced trajectories.
We normalize each trajectory’s probability to the maximum probability across all phase‐grid cells, and pass that normalized array to `alpha`, so that high‐probability trajectories appear more opaque and low‐probability trajectories more transparent.
```python
# 1) Reuse the ProbabilityResult from Example 2:
probability_result = data.backtrace.get_probabilities(
128,
128,
60,
(-data.inp.path[0] * 3, data.inp.path[0] * 3, 10),
0,
(-data.inp.path[0] * 3, 0, 10),
ispec=0,
)
# 2) Extract the `particles` array and their associated `probabilities`
particles = probability_result.particles # Sequence of Particle objects
prob_flat = probability_result.probabilities # 2D array of shape (nvz, nvx)
# 3) Flatten the 2D probability grid back into the 1D array matching `particles` order
prob_1d = prob_flat.ravel()
# 4) Normalize probabilities to [0,1] by dividing by the global maximum
alpha_values = prob_1d / prob_1d.max()
# 5) Compute backtraces for all particles
backtrace_result = data.backtrace.get_backtraces_from_particles(
particles,
ispec=0,
)
# 6) Plot x vs z for every trajectory, using the normalized probabilities as alpha
ax = backtrace_result.xz.plot(alpha=alpha_values)
ax.set_title("Backtrace Trajectories (x vs z) with Probability Transparency")
plt.show()
```
**Notes on the above examples:**
* In Example 1, `get_backtraces(positions, velocities)` returns a `MultiBacktraceResult` whose `xy` property is a `MultiXYData` object. You can sample, reorder, or subset the trajectories and then call `.plot()` on `.xy`, `.vxvy`, `.xz`, etc.
* In Example 2, `get_probabilities(...)` returns a `ProbabilityResult` whose `.vxvz`, `.xy`, `.xz`, etc. are all `HeatmapData` objects. Calling `.plot()` on any of these displays a 2D probability heatmap for the chosen pair of axes.
* In Example 3, `probability_result.particles` is the list of `Particle` objects used internally to compute the 6D probability grid. We pass that list to `get_backtraces_from_particles(...)` to compute backtraced trajectories for exactly those same particles. Normalizing their probabilities to `[0,1]` and passing that array into `alpha` makes high‐probability trajectories draw more opaquely.
These three patterns demonstrate the flexibility of the `data.backtrace` facade for:
1. **Direct backtracing** from arbitrary $(\mathbf{r}, \mathbf{v})$ arrays,
2. **Probability‐space calculations** on a structured phase grid, and
3. **Combining the two** so that you can visualize backtraced trajectories with opacity weighted by their computed probabilities.
</details>
---
Feel free to explore the documentation for more details and advanced usage:
[emout Documentation](https://nkzono99.github.io/emout/)
Happy analyzing!
Raw data
{
"_id": null,
"home_page": null,
"name": "emout",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": "Nkzono99 <j-nakazono@stu.kobe-u.ac.jp>",
"keywords": "Visualization, Simulation, EMSES",
"author": null,
"author_email": "Nkzono99 <j-nakazono@stu.kobe-u.ac.jp>",
"download_url": "https://files.pythonhosted.org/packages/4c/84/777eedee2671bf066de165f83a261300a02dc386c2f26865d59221f28197/emout-2.4.1.tar.gz",
"platform": null,
"description": "# emout\n\nA Python library for parsing and visualizing output files generated by [EMSES](https://github.com/Nkzono99/MPIEMSES3D) simulations.\n\n- **Documentation:** [https://nkzono99.github.io/emout/](https://nkzono99.github.io/emout/)\n\n## Installation\n\n```bash\npip install emout\n```\n\n## Example\n\n- [Visualization of simulation results for lunar surface charging](https://nbviewer.org/github/Nkzono99/examples/blob/main/examples/emout/example.ipynb)\n\n## Overview\n\nWhen you run EMSES simulations, the results (e.g., potentials, densities, currents) are output in `.h5` files, and a parameter file (`plasma.inp`) contains the simulation settings. **emout** helps you:\n\n- [emout](#emout)\n - [Installation](#installation)\n - [Example](#example)\n - [Overview](#overview)\n - [Usage](#usage)\n - [Loading Data](#loading-data)\n - [Retrieving the Parameter File (plasma.inp)](#retrieving-the-parameter-file-plasmainp)\n - [Plotting Data](#plotting-data)\n - [Working with Units](#working-with-units)\n - [Handling Appended Simulation Outputs](#handling-appended-simulation-outputs)\n - [Data Masking](#data-masking)\n - [Creating Animations](#creating-animations)\n - [Solving Poisson\u2019s Equation (Experimental)](#solving-poissons-equation-experimental)\n - [Backtrace Usage Examples (Experimental)](#backtrace-usage-examples-experimental)\n - [Install vdist-solver-fortran](#install-vdist-solver-fortran)\n - [Running backtrace on HPC computational nodes with Dask (\\>= Python3.10)](#running-backtrace-on-hpc-computational-nodes-with-dask--python310)\n - [1. Perform a batch backtrace and plot sampled trajectories](#1-perform-a-batch-backtrace-and-plot-sampled-trajectories)\n - [2. Compute a velocity\u2013space probability distribution and plot $v\\_x$ vs $v\\_z$](#2-compute-a-velocityspace-probability-distribution-and-plot-v_x-vs-v_z)\n - [3. Backtrace using the particles from a previous probability calculation, then plot $x$\u2013$z$ trajectories with probability as transparency](#3-backtrace-using-the-particles-from-a-previous-probability-calculation-then-plot-xz-trajectories-with-probability-as-transparency)\n\nBelow, you will find usage examples that assume the following directory structure:\n\n```\n.\n\u2514\u2500\u2500 output_dir\n \u251c\u2500\u2500 plasma.inp\n \u251c\u2500\u2500 phisp00_0000.h5\n \u251c\u2500\u2500 nd1p00_0000.h5\n \u251c\u2500\u2500 nd2p00_0000.h5\n \u251c\u2500\u2500 j1x00_0000.h5\n \u251c\u2500\u2500 j1y00_0000.h5\n ...\n \u2514\u2500\u2500 bz00_0000.h5\n```\n\n---\n\n## Usage\n\n### Loading Data\n\n```python\nimport emout\n\n# Initialize Emout with the path to the output directory\ndata = emout.Emout('output_dir')\n\n# Access arrays by their variable names (derived from EMSES filename)\ndata.phisp # Data from phisp00_0000.h5\nlen(data.phisp) # Number of time steps\ndata.phisp[0].shape\n\ndata.j1x\ndata.bz\ndata.j1xy # Vector data from \"j1x00_0000.h5\" + \"j1y00_0000.h5\"\n\n# Data created by \"relocating\" ex00_0000.h5\ndata.rex\n\n# Access data as a pandas DataFrame\ndata.icur\ndata.pbody\n```\n\n---\n\n### Retrieving the Parameter File (plasma.inp)\n\n```python\n# The namelist is parsed into a dictionary-like structure\ndata.inp\ndata.inp['tmgrid']['nx'] # Access via group name and parameter name\ndata.inp['nx'] # Group name can be omitted if not ambiguous\ndata.inp.tmgrid.nx # Access like object attributes\ndata.inp.nx # Still valid\n```\n\n---\n\n### Plotting Data\n\n```python\nx, y, z = 32, 32, 100\n\n# Basic 2D plot (xy-plane at z=100 for the last timestep)\ndata.phisp[-1, z, :, :].plot()\n\n# Line plot along z-axis at x=32, y=32\ndata.phisp[-1, :, y, x].plot()\n\n# Plot using SI units\ndata.phisp[-1, z, :, :].plot(use_si=True) # Default is True\n\n# Show or save plot\ndata.phisp[-1, z, :, :].plot(show=True)\ndata.phisp[-1, z, :, :].plot(savefilename='phisp.png')\n\n# Plot vector field as a streamline\ndata.j1xy[-1, z, :, :].plot()\n```\n\n---\n\n### Working with Units\n\n> **Note** \n> EMSES \u2192 SI conversion is supported only when the first line of `plasma.inp` includes something like:\n> ```text\n> !!key dx=[0.5],to_c=[10000.0]\n> ```\n> where `dx` is the grid spacing [m], and `to_c` is the (normalized) speed of light used internally by EMSES.\n\n```python\n# Converting between physical (SI) and EMSES units\ndata.unit.v.trans(1) # Convert 1 m/s to EMSES velocity unit\ndata.unit.v.reverse(1) # Convert 1 EMSES velocity unit to m/s\n\n# Access converted data in SI units\nphisp_volt = data.phisp[-1, :, :, :].val_si # Potential in volts [V]\nj1z_A_per_m2 = data.j1z[-1, :, :, :].val_si # Current density [A/m^2]\nnd1p_per_cc = data.nd1p[-1, :, :, :].val_si # Number density [1/cm^3]\n```\n\n\n<details>\n \n<summary>Unit Name List</summary>\n\n```\nB = Magnetic flux density [T]\nC = Capacitance [F]\nE = Electric field [V/m]\nF = Force [N]\nG = Conductance [S]\nJ = Current density [A/m^2]\nL = Inductance [H]\nN = Flux [/m^2s]\nP = Power [W]\nT = Temperature [K]\nW = Energy [J]\na = Acceleration [m/s^2]\nc = Light Speed [m/s]\ne = Napiers constant []\ne0 = FS-Permttivity [F/m]\neps = Permittivity [F/m]\nf = Frequency [Hz]\ni = Current [A]\nkB = Boltzmann constant [J/K]\nlength = Sim-to-Real length ratio [m]\nm = Mass [kg]\nm0 = FS-Permeablity [N/A^2]\nmu = Permiability [H/m]\nn = Number density [/m^3]\nphi = Potential [V]\npi = Circular constant []\nq = Charge [C]\nq_m = Charge-to-mass ratio [C/kg]\nqe = Elementary charge [C]\nqe_me = Electron charge-to-mass ratio [C/kg]\nrho = Charge density [C/m^3]\nt = Time [s]\nv = Velocity [m/s]\nw = Energy density [J/m^3]\n```\n\n</details>\n\n---\n\n### Handling Appended Simulation Outputs\n\n<details>\n\n<summary>Examples</summary>\n\nIf your simulation continues and creates new directories:\n\n```python\nimport emout\n\n# Merge multiple output directories into one Emout object\ndata = emout.Emout('output_dir', append_directories=['output_dir_2', 'output_dir_3'])\n\n# Same as above if 'ad=\"auto\"' is specified (detects appended outputs automatically)\ndata = emout.Emout('output_dir', ad='auto')\n```\n\n</details>\n\n---\n\n### Data Masking\n\n<details>\n\n<summary>Examples</summary>\n\n```python\n# Mask values below the average\ndata.phisp[1].masked(lambda phi: phi < phi.mean())\n\n# Equivalent manual approach\nphi = data.phisp[1].copy()\nphi[phi < phi.mean()] = float('nan')\n```\n \n</details>\n\n---\n\n### Creating Animations\n\n<details>\n\n<summary>Examples</summary>\n\n```python\n# Create a time-series animation along the first axis (time = 0)\nx, y, z = 32, 32, 100\ndata.phisp[:, z, :, :].gifplot()\n\n# Specify a different axis (default is axis=0)\ndata.phisp[:, z, :, :].gifplot(axis=0)\n\n# Save animation as a GIF\ndata.phisp[:, z, :, :].gifplot(action='save', filename='phisp.gif')\n\n# Display the animation inline in a Jupyter notebook\ndata.phisp[:, z, :, :].gifplot(action='to_html')\n\n# Combining multiple frames for a single animation\nupdater0 = data.phisp[:, z, :, :].gifplot(action='frames', mode='cmap')\nupdater1 = data.phisp[:, z, :, :].build_frame_updater(mode='cont')\nupdater2 = data.nd1p[:, z, :, :].build_frame_updater(mode='cmap', vmin=1e-3, vmax=20, norm='log')\nupdater3 = data.nd2p[:, z, :, :].build_frame_updater(mode='cmap', vmin=1e-3, vmax=20, norm='log')\nupdater4 = data.j2xy[:, z, :, :].build_frame_updater(mode='stream')\n\nlayout = [\n [\n [updater0, updater1],\n [updater2],\n [updater3, updater4]\n ]\n]\nanimator = updater0.to_animator(layout=layout)\nanimator.plot(action='to_html') # or 'save', 'show', etc.\n```\n\n</details>\n\n---\n\n### Solving Poisson\u2019s Equation (Experimental)\n\nYou can solve Poisson\u2019s equation from 3D charge distributions using `emout.poisson` (depends on `scipy`):\n\n<details>\n\n<summary>Examples</summary>\n \n```python\nimport numpy as np\nimport scipy.constants as cn\nfrom emout import Emout, poisson\n\ndata = Emout('output_dir')\ndx = data.inp.dx # [m] Grid spacing\nrho = data.rho[-1].val_si # [C/m^3] Charge distribution\nbtypes = [\"pdn\"[i] for i in data.inp.mtd_vbnd] # Boundary conditions\n\n# Solve Poisson\u2019s equation for potential\nphisp = poisson(rho, dx=dx, btypes=btypes, epsilon_0=cn.epsilon_0)\n\n# Compare with EMSES potential\nnp.allclose(phisp, data.phisp[-1]) # Should be True (within numerical tolerance)\n```\n\n</details>\n\n---\n\n### Backtrace Usage Examples (Experimental)\n\n<details>\n \n<summary>Examples</summary>\n\n#### Install vdist-solver-fortran\n\n```bash\npip install git+https://github.com/Nkzono99/vdist-solver-fortran.git\n```\n\nBelow are three example workflows demonstrating how to use the `data.backtrace` interface. All examples assume you have already created an `Emout` object named `data`.\n\n\n<details>\n\n<summary>with Dask</summary>\n\n#### Running backtrace on HPC computational nodes with Dask (>= Python3.10)\n\nIf you\u2019ve set up a Dask cluster via `emout.distributed`, all of the `data.backtrace` calls below will actually run on your computational nodes instead of your login node.\n\n```python\nfrom emout.distributed import start_cluster, stop_cluster\nimport emout\n\n# \u2460 Dask \u30af\u30e9\u30b9\u30bf\u3092\u8d77\u52d5\uff08SLURM \u30b8\u30e7\u30d6\u3092\u4e00\u6642\u7684\u306b\u4f5c\u6210\u3057\u3066 Worker \u3092\u5e38\u99d0\u3055\u305b\u308b\uff09\nclient = start_cluster(\n partition=\"gr20001a\", # \u4f7f\u7528\u3059\u308b\u30ad\u30e5\u30fc\n processes=1, # \u30d7\u30ed\u30bb\u30b9\u6570\n cores=112, # \u30b3\u30a2\u6570\n memory=\"60G\", # \u30e1\u30e2\u30ea\n walltime=\"03:00:00\", # \u6700\u5927\u5b9f\u884c\u6642\u9593\n scheduler_ip=None, # \u30ed\u30b0\u30a4\u30f3\u30ce\u30fc\u30c9\u4e0a\u306e Scheduler IP (e.g. \"10.10.64.1\", None\u3067\u81ea\u52d5\u691c\u7d22)\n scheduler_port=32332, # Scheduler \u30dd\u30fc\u30c8\n)\n\n# \u2461 \u901a\u5e38\u306e data.backtrace API \u3092\u547c\u3073\u51fa\u3059\u3060\u3051\u3067\u3001\n# \u56f3\u306e\u3088\u3046\u306b\u30d0\u30c3\u30af\u30c8\u30ec\u30fc\u30b9\u95a2\u6570\u7fa4\u304c\u8a08\u7b97\u30ce\u30fc\u30c9\u4e0a\u3067\u5b9f\u884c\u3055\u308c\u307e\u3059\ndata = emout.Emout(\"output_dir\")\nresult = data.backtrace.get_probabilities(\n 128, 128, 200,\n (-data.inp.path[0]*3, data.inp.path[0]*3, 500),\n 1,\n (-data.inp.path[0]*4, data.inp.path[0]*3, 500),\n ispec=0,\n istep=-1,\n dt=data.inp.dt,\n max_step=100000,\n n_threads=112,\n)\nresult.vxvz.plot()\n\n# \u2462 \u7d42\u4e86\u5f8c\u306f\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u3092\u9589\u3058\u3066 Scheduler \u3092\u505c\u6b62\nstop_cluster()\n```\n\n</details>\n\n#### 1. Perform a batch backtrace and plot sampled trajectories\n\nIn this example, we generate 10 particles with varying initial positions and velocities, compute their backtraces, randomly sample 5 backtrace trajectories, and then plot the $x\u2013y$ projection of each sampled trajectory.\n\n```python\nimport numpy as np\nimport matplotlib.pyplot as plt\n\n# 1) Prepare 10 initial positions and velocities\n# Positions: (128, 128, 60 + i*2) for i = 0, 1, \u2026, 9\n# Velocities: (0, 0, -10*i) for i = 0, 1, \u2026, 9\npositions = np.array([[128, 128, 60 + 2 * i] for i in range(10)])\nvelocities = np.array([[0, 0, -10 * i] for i in range(10)])\n\n# 2) Compute backtraces for all 10 particles\n# This returns a MultiBacktraceResult object\nbacktrace_result = data.backtrace.get_backtraces(positions, velocities)\n\n# 3) Sample 5 trajectories. Then plot the x vs y projection.\nsampled_result = backtrace_result.sample(5)\nax = sampled_result.xy.plot()\nax.set_title(\"Backtrace: Sampled 10 Trajectories (x vs y)\")\nplt.show()\n```\n\n\n#### 2. Compute a velocity\u2013space probability distribution and plot $v_x$ vs $v_z$\n\nHere, we call `get_probabilities(...)` to generate a 6D phase grid $(x, y, z, vx, vy, vz)$, invoke the backend solver to compute the probability for each $(x,y,z,v_x,v_y,v_z)$ cell, and then plot the 2D slice in $(v_x, v_z)$ space.\n\n```python\n# 1) Call get_probabilities on a 1\u00d71\u00d71 (x,y,z) cell at (128,128,60),\n# with vx in [-3*dx, +3*dx] sampled over 10 points,\n# vy fixed at 0, and vz in [-3*dx, 0] sampled over 10 points.\n# ispec=0 indicates electron species.\nprobability_result = data.backtrace.get_probabilities(\n 128, # x = constant 128 (single cell)\n 128, # y = constant 128\n 60, # z = constant 60\n (-data.inp.path[0] * 3, # vx from \u20133*dx\n +data.inp.path[0] * 3, 10), # to +3*dx in 10 steps\n 0, # vy = 0\n (-data.inp.path[0] * 3, # vz from \u20133*dx\n 0, 10), # to 0 in 10 steps\n ispec=0, # electron species\n)\n\n# 2) Plot the resulting probability on the vx\u2013vz plane\nax = probability_result.vxvz.plot(shading=\"auto\", cmap=\"plasma\")\nax.set_title(\"Probability Distribution: vx vs vz (ispec=0)\")\nplt.show()\n```\n\n\n#### 3. Backtrace using the particles from a previous probability calculation, then plot $x$\u2013$z$ trajectories with probability as transparency\n\nIn this final example, we take the `particles` array produced internally by `get_probabilities(...)`, run backtraces on each of those particles, and then plot the $x$\u2013$z$ projections of all backtraced trajectories.\n\n We normalize each trajectory\u2019s probability to the maximum probability across all phase\u2010grid cells, and pass that normalized array to `alpha`, so that high\u2010probability trajectories appear more opaque and low\u2010probability trajectories more transparent.\n\n```python\n# 1) Reuse the ProbabilityResult from Example 2:\nprobability_result = data.backtrace.get_probabilities(\n 128,\n 128,\n 60,\n (-data.inp.path[0] * 3, data.inp.path[0] * 3, 10),\n 0,\n (-data.inp.path[0] * 3, 0, 10),\n ispec=0,\n)\n\n# 2) Extract the `particles` array and their associated `probabilities`\nparticles = probability_result.particles # Sequence of Particle objects\nprob_flat = probability_result.probabilities # 2D array of shape (nvz, nvx)\n\n# 3) Flatten the 2D probability grid back into the 1D array matching `particles` order\nprob_1d = prob_flat.ravel()\n\n# 4) Normalize probabilities to [0,1] by dividing by the global maximum\nalpha_values = prob_1d / prob_1d.max()\n\n# 5) Compute backtraces for all particles\nbacktrace_result = data.backtrace.get_backtraces_from_particles(\n particles,\n ispec=0,\n)\n\n# 6) Plot x vs z for every trajectory, using the normalized probabilities as alpha\nax = backtrace_result.xz.plot(alpha=alpha_values)\nax.set_title(\"Backtrace Trajectories (x vs z) with Probability Transparency\")\nplt.show()\n```\n\n\n**Notes on the above examples:**\n\n* In Example 1, `get_backtraces(positions, velocities)` returns a `MultiBacktraceResult` whose `xy` property is a `MultiXYData` object. You can sample, reorder, or subset the trajectories and then call `.plot()` on `.xy`, `.vxvy`, `.xz`, etc.\n\n* In Example 2, `get_probabilities(...)` returns a `ProbabilityResult` whose `.vxvz`, `.xy`, `.xz`, etc. are all `HeatmapData` objects. Calling `.plot()` on any of these displays a 2D probability heatmap for the chosen pair of axes.\n\n* In Example 3, `probability_result.particles` is the list of `Particle` objects used internally to compute the 6D probability grid. We pass that list to `get_backtraces_from_particles(...)` to compute backtraced trajectories for exactly those same particles. Normalizing their probabilities to `[0,1]` and passing that array into `alpha` makes high\u2010probability trajectories draw more opaquely.\n\nThese three patterns demonstrate the flexibility of the `data.backtrace` facade for:\n\n1. **Direct backtracing** from arbitrary $(\\mathbf{r}, \\mathbf{v})$ arrays,\n2. **Probability\u2010space calculations** on a structured phase grid, and\n3. **Combining the two** so that you can visualize backtraced trajectories with opacity weighted by their computed probabilities.\n\n</details>\n\n---\n\nFeel free to explore the documentation for more details and advanced usage:\n\n[emout Documentation](https://nkzono99.github.io/emout/)\n\nHappy analyzing!\n",
"bugtrack_url": null,
"license": null,
"summary": "Emses output manager",
"version": "2.4.1",
"project_urls": {
"Repository": "https://github.com/Nkzono99/emout.git"
},
"split_keywords": [
"visualization",
" simulation",
" emses"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "369ea59f78f5d64003cdef16adcd9e28fe7dfa7875975e10bd96f60e14f24c2e",
"md5": "b8b691d4cc523dd8aae9d1b655c9cc49",
"sha256": "ff486f4820ed9e6dd2cdfb024430ed04b8b827865303ac17669acceef8e101ee"
},
"downloads": -1,
"filename": "emout-2.4.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "b8b691d4cc523dd8aae9d1b655c9cc49",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7",
"size": 75241,
"upload_time": "2025-07-23T01:04:50",
"upload_time_iso_8601": "2025-07-23T01:04:50.987045Z",
"url": "https://files.pythonhosted.org/packages/36/9e/a59f78f5d64003cdef16adcd9e28fe7dfa7875975e10bd96f60e14f24c2e/emout-2.4.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "4c84777eedee2671bf066de165f83a261300a02dc386c2f26865d59221f28197",
"md5": "aadc749b47c15fdd24b4af8b96d4e5c5",
"sha256": "4eb2f0f8c7ebdc17bb741ca1e77f2f39191aaf9ae3d4b09109265ab718655678"
},
"downloads": -1,
"filename": "emout-2.4.1.tar.gz",
"has_sig": false,
"md5_digest": "aadc749b47c15fdd24b4af8b96d4e5c5",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 66321,
"upload_time": "2025-07-23T01:04:52",
"upload_time_iso_8601": "2025-07-23T01:04:52.335704Z",
"url": "https://files.pythonhosted.org/packages/4c/84/777eedee2671bf066de165f83a261300a02dc386c2f26865d59221f28197/emout-2.4.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-23 01:04:52",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "Nkzono99",
"github_project": "emout",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "emout"
}