Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
ca40e04
Fixed slice bound issues
Simske Sep 30, 2021
2e46a3f
Setup testing with tox and pytest
Simske Oct 1, 2021
4c9a665
Fix normalize_slice() and add tests
Simske Oct 1, 2021
a32ea2f
Added Github workflow for tox
Simske Oct 1, 2021
3205350
Test for multiple Python versions
Simske Oct 1, 2021
f7c2e58
Fix lru_cache invocation for Python <3.8
Simske Oct 1, 2021
8479379
gh-actions: only run pull request or push on main/dev branch
Simske Oct 1, 2021
764a95d
Match SimulationSlice & PlutoDataSlice interface
Simske Oct 2, 2021
97b0c3b
Plotting function cleanup
Simske Oct 2, 2021
5a0b054
Update setup.cfg for distribution on Pypi
Simske Oct 3, 2021
a8d69ce
README: cleanup outdated and added badges
Simske Oct 3, 2021
ad770ae
rename testing workflow for badge
Simske Oct 3, 2021
c139e11
add testing badge
Simske Oct 3, 2021
46cebed
Setup mkdocs
Simske Oct 3, 2021
9116f64
pluto-info: don't show path to data dir
Simske Oct 4, 2021
1d61b4b
Updated README with quick start
Simske Oct 4, 2021
5c9f657
Minor plotting fixes
Simske Oct 4, 2021
65c8ea7
Docs: add script for example plots
Simske Oct 4, 2021
084cd1e
Docs: filled index and added quickstart
Simske Oct 5, 2021
8a4f3b3
Switch installer to Poetry
Simske Nov 4, 2021
e2e7233
Add numpy versions to tox tests
Simske Nov 4, 2021
31fac7b
Added some documentation
Simske Nov 24, 2021
32ac4a6
Adjust colorbar size in plots
Simske Nov 24, 2021
c49d274
Fix Simulation.__str__ and Grid.__str__
Simske Dec 16, 2021
dde75f5
mkdocs: add Mathjax
Simske Dec 16, 2021
1254f25
Updated documentation
Simske Dec 16, 2021
8a34c7e
Automatically build and push to PyPI on release creation
Simske Dec 16, 2021
dea1184
Fix Pluto_ini __setitem__
Simske Dec 16, 2021
7bd4e2b
Some doc additions
Simske Mar 31, 2022
3ec05db
Updated pre-commit hooks and GH actions
Simske Mar 31, 2022
8c68922
Fix black formattting
Simske Mar 31, 2022
7a68be3
testing: add Python 3.10 to test matrix
Simske Mar 31, 2022
4df251c
Merge branch 'poetry'
Simske Mar 31, 2022
f405464
Update and fix tox and GH actions testing
Simske Mar 31, 2022
70fc2f4
Get to more consistent dependency state
Simske Mar 31, 2022
446b790
Simplify testing matrix
Simske Mar 31, 2022
731d7f5
Convert __version__ to poetry method
Simske Mar 31, 2022
d1be87d
Add mypy to environment
Simske Apr 1, 2022
0f27a8d
Add pre-commit to environment
Simske Apr 1, 2022
a060fc7
Add some type annotations in coordinates.py and grid.py
Simske Apr 1, 2022
47d4306
Use functools.cached_property for Python >=3.8
Simske Apr 1, 2022
deb0ad8
Some type annotations
Simske Apr 1, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .gitattributes

This file was deleted.

6 changes: 3 additions & 3 deletions .github/workflows/pre-commit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
- uses: pre-commit/action@v2.0.0
- uses: actions/checkout@v3
- uses: actions/setup-python@v3
- uses: pre-commit/action@v2.0.3
31 changes: 31 additions & 0 deletions .github/workflows/publish-pypi.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Build package and upload to PyPI

on:
release:
types: [created]

jobs:
deploy:
runs-on: ubuntu-20.04

steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v3
- name: Install build dependencies
run: |
python -m pip install --upgrade pip
pip install build twine
- name: Build package
run: |
python -m build .
- name: Upload package to PyPI
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
run: twine upload dist/*
- name: Upload package to Github release
uses: alexellis/upload-assets@0.3.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
asset_paths: '["./dist/*"]'
31 changes: 31 additions & 0 deletions .github/workflows/tox.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
name: testing

on:
push:
branches:
- main
- dev
pull_request:

jobs:
tox:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: [3.7, 3.8, 3.9, "3.10"]

steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install poetry
poetry install
- name: Test with tox
run: poetry run tox
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ build/
dist/
.vscode/
test.ipynb
.tox
6 changes: 3 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.0.1
rev: v4.1.0
hooks:
- id: check-added-large-files
- id: check-case-conflict
Expand All @@ -11,11 +11,11 @@ repos:
- id: trailing-whitespace
args: ["--markdown-linebreak-ext=md"]
- repo: https://github.com/psf/black
rev: 21.9b0
rev: 22.3.0
hooks:
- id: black
- repo: https://github.com/pycqa/isort
rev: "5.9.3"
rev: "5.10.1"
hooks:
- id: isort
args: ["--profile", "black"]
11 changes: 11 additions & 0 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
version: 2

mkdocs:
configuration: docs/mkdocs.yml

python:
version: "3.8"
install:
- method: pip
path: .
- requirements: docs/requirements.txt
2 changes: 0 additions & 2 deletions MANIFEST.in

This file was deleted.

221 changes: 139 additions & 82 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,114 +1,171 @@
# plutoplot - Plutocode Plotting library
# plutoplot - Plutocode data loading and plotting library
![GitHub release](https://img.shields.io/github/v/release/simske/plutoplot?include_prereleases&label=Github%20Release)
![PyPI](https://img.shields.io/pypi/v/plutoplot)
[![Documentation](https://readthedocs.org/projects/plutoplot/badge/?version=latest)](https://plutoplot.readthedocs.io/en/latest/?badge=latest)
[![pre-commit](https://github.com/Simske/plutoplot/actions/workflows/pre-commit.yml/badge.svg)](https://github.com/Simske/plutoplot/actions/workflows/pre-commit.yml)
[![testing](https://github.com/Simske/plutoplot/actions/workflows/tox.yml/badge.svg)](https://github.com/Simske/plutoplot/actions/workflows/tox.yml)
![License](https://img.shields.io/github/license/simske/plutoplot)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
[![Imports: isort](https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat&labelColor=ef8336)](https://pycqa.github.io/isort/)

`plutoplot` is a Python package for loading, analyzing and plotting data from the [astrophysical gas dynamics simulation code PLUTO](http://plutocode.ph.unito.it/).
By handling simulations as a whole and loading data only when needed (lazy loading), it is fast and easy to use.

It features:
- Loading on data actually needed (by lazy loading in memory mapping)
- easy slicing into large datasets (e.g. plotting 2D slice of 3D dataset)
- plotting non-cartesian coordinates projected into cartesian space
- interactive plotting in Jupyter Notebooks
- CLI tool to quickly acquire information about simulations
- Access to parameters set in `definitions.h` and `pluto.ini`
- Access to simulation metadata and grid properties
- Indexing with `ijk` (like `pyPLUTO`) and `kji` (like PLUTO internally) schemes

There is currently no support for:
- Particles
- Adaptive grids (AMR)
- 3D plotting (only plotting 2D slices of 3D data is supported.)

To get started with `plutoplot` check out the [documentation](https://plutoplot.readthedocs.io/en/latest/) and [examples](https://github.com/Simske/plutoplot/tree/main/test).

This is a Python 3 library for plotting output data from the [PLUTO code](http://plutocode.ph.unito.it/)

This library is under development and mostly specialized on the functionality I personally need. Nonetheless I will try to make the code as widely applicable and documented as possible.
## Installation
`plutoplot` requires Python >=3.6. Make sure for installation to install in the right environment, and/or adapt the pip commands accordingly (e.g. `pip3`).

## Requirements
```
Python >=3.6
numpy
matplotlib
The base version of plutoplot can be installed from Pypi with:
```bash
pip install --upgrade plutoplot
```

## Installation
Install it with pip:
To keep the installation size small the dependencies for interactive plotting and loading of HDF5 data are declared as optional dependencies.
To install the optional dependencies use either of the following, depeding on your needs:
```bash
pip install --upgrade plutoplot[interactive]
pip install --upgrade plutoplot[hdf5]
pip install --upgrade plutoplot[interactive,hdf5]
```
pip install git+https://gitlab.mpcdf.mpg.de/sdoetsch/plutoplot.git

To install the current development version from this branch:
```bash
pip install --upgrade "plutoplot @ git+https://github.com/simske/plutoplot"
```

Or download repository (as archive or with git)
## Quick Start
### CLI: check simulation info
To quickly check the status of a PLUTO simulation, you can use the `pluto-info` command line tool:
```bash
pluto-info /path/to/simulation
```
python setup.py install
Sample:
```
>> pluto-info test-problems/HD/Jet/01/
PLUTO simulation at 'test-problems/HD/Jet/01'
Polar grid with dimensions (160, 1, 640)
Domain: x1: 0.00e+00 .. 1.00e+01 (Lx1 = 1.00e+01)
x2: 0.00e+00 .. 1.00e+00 (Lx2 = 1.00e+00)
x2: 0.00e+00 .. 4.00e+01 (Lx3 = 4.00e+01)
Available variables: rho vx1 vx2 vx3 prs
Data files:
Format dbl: 16 files, last time 15.0, data timestep 1.00e+00
Format flt: 61 files, last time 15.0, data timestep 2.50e-01

If you downloaded via git and want to keep updating via git, you can also use
```
python setup.py develop
```
This way the package is always read in from the git directory.
(note: depending on your Python environment, the entrypoint `pluto-info` might not be installed correctly. Check the [documentation for more details](https://plutoplot.readthedocs.io/en/latest/cli-tools)).

## Example
### Quick start in Python scripts / Jupyter notebooks
```python
import plutoplot as pp
```
#### Basics
Simulations can be loaded by just providing the path to the simulation directory (directory with `definitions.h` and `pluto.ini`).
The data directory is the found automatically, as well as the grid geometry.
The formats are searched in the order (dbl, flt, vtk, dbl.h5, flt.h5) and the first found loaded, this can be overriden.
```python
sim = pp.Simulation("/path/to/simulation", format="flt")
```
The simulation object provides access to all outputs (of this format), the grid and simulation metadata.
A few examples of accesible attributes:
```python
sim.dims # domain resolution
sim.x1, sim.x2, sim.x3 # cell centered coordinates, redirect to sim.grid.x{1,2,3}
sim.x1i, sim.x2i, sim.x3i # cell interface coordinates
sim.Lx1, sim.Lx2, sim.Lx3

sim = pp.Simulation("path_to_simulation")
print(sim.grid)

# Access to grid coordinates
sim.x1
sim.vx1

# Access to simulation steps
sim[3].rho

# time evolution of mean pressure
mean_prs = sim.reduce(lambda D : D.prs.mean())
sim.t # simulation output times
sim.vars # simulation output variables
```

## Concepts
`plutoplot` offers three main classes for handling simulation data:
- `Simulation`: for a simulation
- `PlutoData`: for a single simulation data frame
- `Grid`: for the PLUTO domain grid
The data at the specific output steps can be accessed with the `sim[n]` syntax.
This results in a `PlutoData` object, which can be used to access the data:
```python
sim[-1].rho
```
The data object as well as the data array are generated when needed, and the data arrays are memory mapped, which means only data actually accessed is read from disk.
The names of the data variables can be found with `sim.vars`.

For data loading the user only has to instantiate a `Simulation`, the grid
and the `PlutoData` objects are created from the `Simulation` when needed.
`PlutoData` uses lazy loading for the actual data, which means the data is
loaded when is first needed, not on object instantiation.
Each variable is loaded seperately (independent of PLUTO save format),
e.g. when only density is needed, pressure is never put into memory.
Be aware that data arrays are always 3-dimensional, even if the domain has a resolution of 1 in some directions.
This is for clarity and consistency, so that an axis always has a direct correspondence to its coordinates in the grid.

## Simulation instantiation
A `Simulation` can be instantiated with:
Simulations are iterable:
```python
Simulation(sim_dir='', format=None, coordinates=None)
```
- `sim_dir`: Simulation directory (directory with `pluto.ini` and `definitions.h`).
plutoplot searchs for the gridfile and simulation data first in `sim_dir`,
then in `sim_dir/data`, and then looks up the data directory in `pluto.ini`.
Default: Current working directory
- `format`: file format of the simulation data, currently supports `dbl`, `flt`, `vtk`
in both `single_file` and `multiple_files` mode.
Default: `dbl`, `flt`, `vtk`, are tried in that order
- `coordinates`: coordinate system of the simulation grid.
Supports `cartesian`, `spherical`, `polar`, `cylindrical`.
Only necessary for projecting the grind into a cartesian system (e.g. for plotting).
Default: Read coordinate system from `definitions.h`, using `cartesian` as fallback

## Access `pluto.ini` and `definitions.h`
`plutoplot` can load the PLUTO configuration files:
for step in sim:
print("Total mean squared velocity at t={step.t}: ", (step.vx1**2 + step.vx2**2 + step.vx3**2).mean())
```
And also provide a `reduce()` function to run over the whole simulation:
```python
sim = Simulation('sim_dir')
sim.ini['section']['option']
sim.definitions['options']
prs_mean = sim.reduce(lambda step: step.prs.mean())
```
The returned objects for `pluto.ini` (`Pluto_ini`) and `definitions.h` (`Definitions_H`)
are thin wrappers around `OrderedDict`s.
This results in an array containing the output of the supplied function for each step, in the example the mean pressure.

## Data access
The simulation steps can be optained from the `Simulation` object with the subscript syntax:
#### Working with simulation slices
To only look at a part of a simulation we can slice into it.
This can be particularly useful for analyzing and plotting 2D slices of 3D data, as full 3D plotting is not supported yet.
To slice into a simulation the usual slicing syntax on `Simulation.slicer`:
```python
sim = Simulation('sim_dir')
initial = sim[0]
last = sim[-1]
sliced_sim = sim.slicer[:,0,32:64]
```
It supports the Python conventions for indexing (zero indexed, negative numbers
are handled as `len(sim)-i`)
This sliced simulation object can now be used as the normal simulation object.
The grid and data arrays will automatically return the data for this slice.
(Note: for clarity a 3D slice is always required. The data arrays will still always be 3D, see above).

Which variables are saved by PLUTO are accesible with
#### Plotting
`plutoplot` provides automatic plotting for 1D & 2D simulations.
To plot slices of 3D simulations, first create a simulation slice (section above), then just follow normally.

The PlutoData object provides a `plot()` function, which will automatically project the data onto a cartesian grid, and annotating the axes and colorbar correctly:
```python
sim.vars
# or
sim[i].vars
# e.g. ['rho', 'vx1', 'vx2', 'vx3', 'prs']
sim[-1].plot('rho')
```
![Density plot](docs/docs/img/quick_start_plot_projected.jpg)

The variable names in this list can be then accessed from the `PlutoData` objects:
The projection can also be turned off, an arbitrary options which will be passed to matplotlib can be given:
```python
sim[0].rho
sim[-1].vx1
sim[-1].plot('rho', projection=False)
```
The data is then returned as Numpy arrays, and can be used as usual.
![Density plot](docs/docs/img/quick_start_plot_not-projected.jpg)

If a plot of a custom quantitity is needed, a array instead of a variable name can be given:
```
step = sim[-1]
step.plot(step.prs / step.rho, label="T")
```

In Jupyter Notebooks interactive plotting can be used to step through the simulation steps.
`Simulation.iplot()` has the same interface as `PlutoData.plot()`, but it will show a slider to step through simulation steps:
```
sim.iplot("rho")
```
![Interactive plot](docs/docs/img/quick_start_iplot.gif)

## Testing
The test suite for `plutoplot` can be found in `test/` and is run by Github actions using `tox` and `pytest`.

The test suite is currently minimal and has low code coverage. It will be expanded in the future to ensure correctness.

## Contributing
If you have any questions, suggestions or find a bug, feel free to open an [issue](https://github.com/Simske/plutoplot/issues)
or [Pull Request](https://github.com/Simske/plutoplot/pulls), I am happy to accept contributions to make plutoplot better.

`plutoplot` uses [pre-commit](https://pre-commit.com/) to ensure a consistend code style, please use it when opening a Pull Request.

## Plotting
## License
GPLv3
1 change: 1 addition & 0 deletions docs/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
site/
Loading