emout


Nameemout JSON
Version 2.4.1 PyPI version JSON
download
home_pageNone
SummaryEmses output manager
upload_time2025-07-23 01:04:52
maintainerNone
docs_urlNone
authorNone
requires_python>=3.7
licenseNone
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"
}
        
Elapsed time: 2.28863s