Plotting: 1D and 2D data#

This notebook show how to visualize 1D and 2d simulation data.

[1]:
import osyris
import numpy as np
import matplotlib.pyplot as plt

Plotting 1D data#

1D and 2D data are loaded in exactly the same way as 3D simulations, by creating a Dataset and calling the load() method.

[2]:
path = "osyrisdata/sod"
data1d = osyris.RamsesDataset(2, path=path).load()
data1d
Processing 4 files in osyrisdata/sod/output_00002
 25% : read         15 cells,          0 particles
 50% : read         47 cells,          0 particles
 75% : read         90 cells,          0 particles
Loaded: 142 cells, 0 particles.
[2]:
Dataset: osyrisdata/sod/output_00002: 7.95 KB

Datagroup: mesh 7.95 KB
'level' Min: 5 Max: 10 [] (142,)
'cpu' Min: 1 Max: 4 [] (142,)
'dx' Min: 9.766e-04 Max: 0.031 [cm] (142,)
'position_x' Min: 0.016 Max: 0.996 [cm] (142,)
'density' Min: 0.125 Max: 1.000 [g / cm ** 3] (142,)
'velocity_x' Min: -5.551e-17 Max: 0.929 [cm / s] (142,)
'pressure' Min: 0.1 Max: 1.000 [erg / cm ** 3] (142,)
'mass' Min: 5.853e-44 Max: 1.534e-38 [M_sun] (142,)

Line profile#

To plot a simple line profile of density as a function of position, Osyris provides the plot function which is analogous to Matplotlib’s plot function.

[3]:
data1d = data1d["mesh"]

osyris.plot(data1d["position_x"], data1d["density"])
[3]:
<osyris.core.plot.Plot at 0x72954c3b4670>
_images/plotting_1d_2d_5_1.png

It is also possible to send just a single array to the plot function, in which case it will use it as y values and replace the x axis with integer numbers spanning the length of the array:

[4]:
osyris.plot(data1d["density"])
[4]:
<osyris.core.plot.Plot at 0x72954c2a6800>
_images/plotting_1d_2d_7_1.png

Note that in this case, the order in which the data points are plotted is just the order in which they appear in the output files, i.e. it will most probably not make physical sense, as it depends (among other things) on load-balancing across cpus.

However, these plots can be useful for debugging purposes, when one wishes to visually inspect the range of values spanned by a variable.

Styling lines#

Because the function is based on Matplotlib’s implementation, it also supports Matplotlib’s styling arguments. For instance, to plot using red marker instead of a solid line, you can do

[5]:
osyris.plot(
    data1d["position_x"],
    data1d["density"],
    marker="o",
    ls="None",
    color="red",
)
[5]:
<osyris.core.plot.Plot at 0x72954a137010>
_images/plotting_1d_2d_9_1.png

Logarithmic scales#

Osyris does provide some convenience arguments in addition to Matplotlib’s functionalty. For example, to set a logarithmic scale on the x and y axes, use the logx and logy arguments

[6]:
osyris.plot(
    data1d["position_x"],
    data1d["density"],
    marker="o",
    ls="None",
    logx=True,
    logy=True,
)
[6]:
<osyris.core.plot.Plot at 0x72954a1aa1a0>
_images/plotting_1d_2d_11_1.png

Multiple lines#

It is also possible to over-plot multiple lines in one go, by supplying more than one array for the y values.

However, note that to be able to plot the variables on a single axis, they must all have the same unit.

[7]:
try:
    osyris.plot(
        data1d["position_x"],
        data1d["density"],
        data1d["pressure"],
    )
except Exception as e:
    print(e)
Different layers in 1D plots must all have the same unit.

To be able to show an example, we fake a new density variable.

[8]:
data1d["new_density"] = data1d["density"] * 2
osyris.plot(
    data1d["position_x"],
    data1d["density"],
    data1d["new_density"],
)
[8]:
<osyris.core.plot.Plot at 0x72954c2dbc70>
_images/plotting_1d_2d_15_1.png

By default, the same x coordinate will be used for both sets of y values. It is however possible to plot on the same axes two variables with different x coordinates.

In this case, the two entries must be dicts, and they must contain at least the entries 'x' and 'y'. This is useful in the case where one wishes to compare two outputs from different times, which do not contain the same number of mesh cells (and hence cannot have the same x coordinate).

[9]:
old1d = osyris.RamsesDataset(1, path=path).load()["mesh"]

osyris.plot(
    {"x": data1d["position_x"], "y": data1d["density"]},
    {"x": old1d["position_x"], "y": old1d["density"]},
    marker="o",
    ls="None",
)
Processing 4 files in osyrisdata/sod/output_00001
 25% : read          4 cells,          0 particles
 50% : read         29 cells,          0 particles
 75% : read         54 cells,          0 particles
Loaded: 58 cells, 0 particles.
[9]:
<osyris.core.plot.Plot at 0x729549ed81f0>
_images/plotting_1d_2d_17_2.png

Subplots / tiled plots#

Osyris has no built-in support for subplots (also known as tiled plots). Instead, we leverage Matplotlib’s ability to create such layouts. Osyris plots are then inserted into the Matplotlib axes, using the ax argument.

In the example below, we create four panels and insert various plots.

[10]:
fig, ax = plt.subplots(2, 2, figsize=(12, 9))

osyris.plot(
    data1d["position_x"],
    data1d["density"],
    marker="o",
    ls="None",
    ax=ax[0, 0],
)
osyris.plot(
    data1d["position_x"],
    data1d["velocity_x"],
    color="green",
    ax=ax[0, 1],
)
osyris.plot(data1d["position_x"], data1d["pressure"], color="red", ax=ax[1, 0])
osyris.plot(
    data1d["position_x"],
    data1d["level"],
    color="black",
    ls="dotted",
    ax=ax[1, 1],
)
[10]:
<osyris.core.plot.Plot at 0x729549d94520>
_images/plotting_1d_2d_19_1.png

Plotting 2D data#

This section briefly shows how to make images of 2D data with the map function. For a full description of all the options available, see Plotting: spatial maps.

[11]:
data2d = osyris.RamsesDataset(2, path="osyrisdata/sedov").load()
Processing 1 files in osyrisdata/sedov/output_00002
Loaded: 34198 cells, 0 particles.
[12]:
data2d["mesh"]
[12]:
Datagroup: mesh 2.46 MB
'level' Min: 4 Max: 10 [] (34198,)
'cpu' Min: 1 Max: 1 [] (34198,)
'dx' Min: 9.766e-04 Max: 0.062 [cm] (34198,)
'density' Min: 0.017 Max: 19.120 [g / cm ** 3] (34198,)
'pressure' Min: 1.000e-05 Max: 1.578 [erg / cm ** 3] (34198,)
'position' Min: 0.044 Max: 1.392 [cm] (34198,), {x,y}
'velocity' Min: 0.0 Max: 0.417 [cm / s] (34198,), {x,y}
'mass' Min: 4.683e-43 Max: 2.971e-38 [M_sun] (34198,)

To make an image of the gas density, simply use

[13]:
osyris.map(data2d["mesh"].layer("density"), norm="log", cmap="jet")
[13]:
<osyris.core.plot.Plot at 0x7295430ea830>
_images/plotting_1d_2d_24_1.png

A map of the AMR level is obtained with

[14]:
osyris.map(data2d["mesh"].layer("level"))
[14]:
<osyris.core.plot.Plot at 0x729542ffa2f0>
_images/plotting_1d_2d_26_1.png

The size of the viewport can be adjusted with the dx argument:

[15]:
osyris.map(
    data2d["mesh"].layer("density"),
    dx=2 * osyris.units("cm"),
    cmap="jet",
    norm="log",
)
[15]:
<osyris.core.plot.Plot at 0x729542e4bbb0>
_images/plotting_1d_2d_28_1.png

Finally, you can also use an additional layer to overlay velocity vectors

[16]:
osyris.map(
    data2d["mesh"].layer("density", norm="log"),
    data2d["mesh"].layer("velocity", mode="vec", color="black"),
    cmap="jet",
)
[16]:
<osyris.core.plot.Plot at 0x729549820280>
_images/plotting_1d_2d_30_1.png