Quick-start guide¶
This quick-start guide will walk you into the main steps to document your numerical project. If you want to skip the tour and directly see an example, see Full example script.
Project and study¶
Creation and persistency¶
To create a Project
and save it into a SimulationStudy
HDF5 file, you may run this minimal Python script :
>>> from astrophysix.simdm import SimulationStudy, Project, ProjectCategory
>>> proj = Project(category=ProjectCategory.Cosmology, project_title="Extreme Horizons cosmology project")
>>> study = SimulationStudy(project=proj)
>>> study.save_HDF5("./EH_study.h5")
Loading a study¶
To read the SimulationStudy
from your HDF5 file, update it and save the updated study back
in its original file :
>>> from astrophysix.simdm import SimulationStudy
>>> study = SimualationStudy.load_HDF5("./EH_study.h5")
>>> proj = study.project
>>> proj.short_description = "This is a short description (one-liner) of my project."
>>> # Saves your updated study back in the same file './EH_study.h5'
>>> study.save_HDF5()
Study information¶
A SimulationStudy
object contains details on when it has been created
(creation_time
property) and last modified (last_modification_time
property) :
>>> study.creation_time
datetime.datetime(2020, 9, 4, 14, 05, 21, 84601, tzinfo=datetime.timezone.utc)
>>> study.last_modification_time
datetime.datetime(2020, 9, 18, 15, 12, 27, 14512, tzinfo=datetime.timezone.utc)
Full project initialization example¶
To initialize a Project
, you only need to set category
and
project_title
properties. Here is a more complete example of a
Project
initialization with all optional attributes :
>>> proj = Project(category=ProjectCategory.StarFormation, alias="FRIG",
... project_title="Self-regulated magnetised ISM modelisation",
... short_description="Short description of my 'FRIG' project",
... general_description="""This is a pretty long description for my project spanning over multiple lines
... if necessary""",
... data_description="The data available in this project...",
... directory_path="/path/to/project/data/")
Warning
Setting the alias
property is necessary only if you wish to upload your study on
the Galactica simulation database. See Why an alias ? and How can I check validity for Galactica ?
See also
SimulationStudy
,Project
andProjectCategory
API references.
Simulation codes and runs¶
To add a simulation run into your project, the definition of a SimulationCode
is mandatory.
Once defined, you can create a Simulation
based on that simulation code:
>>> from astrophysix.simdm.protocol import SimulationCode
>>> from astrophysix.simdm.experiment import Simulation
>>> ramses = SimulationCode(name="Ramses 3.1 (MHD)", code_name="RAMSES")
>>> simu = Simulation(simu_code=ramses, name="Hydro run full resolution")
To add the simulation to the project, use the Project.simulations
property
(ObjectList
):
>>> proj.simulations.add(simu)
>>> proj.simulations
Simulation list :
+---+---------------------------+----------------------------------------+
| # | Index | Item |
+---+---------------------------+----------------------------------------+
| 0 | Hydro run full resolution | 'Hydro run full resolution' simulation |
+---+---------------------------+----------------------------------------+
| 1 | Hydro run full resolution | 'MHD run full resolution' simulation |
+---+---------------------------+----------------------------------------+
See also
Simulation
,SimulationCode
API references,Protocols detailed section.
Experiments detailed section.
ObjectList
API reference.
Post-processing runs¶
Optionally, you can add PostProcessingRun
into a Simulation
using the Simulation.post_processing_runs
property
(ObjectList
).
To create a PostProcessingRun
, you must first define a
PostProcessingCode
:
from astrophysix.simdm.protocol import PostProcessingCode
from astrophysix.simdm.experiment import PostProcessingCodeRun
radmc = PostProcessingCode(name="RADMC-3D", code_name="RADMC-3D", code_version="2.0")
pprun = PostProcessingCodeRun(ppcode=radmc, name="Synthetic observable creation of pre-stellar cores")
# Add post-pro run into the simulation
simu.post_processing_runs.add(pprun)
See also
PostProcessingRun
,PostProcessingCode
API references,Protocols detailed section.
Experiments detailed section.
ObjectList
API reference.
Results and snapshots¶
Experiment-wide¶
You can add results into any simulation or post-processing run. If it is an experiment-wide result, create a
GenericResult
and use the Simulation.generic_results
or PostProcessingRun.generic_results
property
(ObjectList
) to add it into your run :
from astrophysix.simdm.results import GenericResult
res1 = GenericResult(name="Star formation history", directory_path="/my/path/to/result",
description="""This is the star formation history during the 2
Myr of the galaxy major merger""")
simu.generic_results.add(res1)
Time-specific¶
Otherwise, if it is time-specific result, create a Snapshot
and use the
Simulation.snapshots
or
PostProcessingRun.snapshots
property
(ObjectList
) to add it into your run :
from astrophysix.simdm.results import Snapshot
from astrophysix import units as U
sn34 = Snapshot(name="Third pericenter", time=(254.7, U.Myr),
directory_path="/my/path/to/simu/outputs/output_00034")
simu.snapshots.add(sn34)
See also
GenericResult
,Snapshot
API references,Experiments detailed section.
Results and associated datafiles detailed section.
ObjectList
API reference.
Datafiles¶
You can add Datafile
objects into any
Snapshot
or GenericResult
:
>>> from astrophysix.simdm.datafiles import Datafile
>>>
>>> # Add a datafile into a snapshot
>>> imf_df = Datafile(name="Initial mass function",
... description="This is my IMF plot detailed description...")
>>> sn34.datafiles.add(imf_df)
And then embed files from your local filesystem into the Datafile
(the file raw byte
array will be imported along with the original file name and last modification date):
>>> from astrophysix.simdm.datafiles import image
>>> from astrophysix.utils.file import FileType
>>>
>>> # Attach files to datafile
>>> imf_df[FileType.PNG_FILE] = os.path.join("/data", "io", "datafiles", "plot_image_IMF.png")
>>> jpg_fpath = os.path.join("/data", "io", "datafiles", "plot_with_legend.jpg")
>>> imf_df[FileType.JPEG_FILE] = image.JpegImageFile.load_file(jpg_fpath)
>>> imf_df[FileType.HDF5_FILE] = os.path.join("/data", "io", "HDF5", "stars.h5")
Anyone can reopen your SimulationStudy
HDF5 file, read the attached files and re-export them
on their local filesystem to retrieve a carbon copy of your original file:
>>> imf_df[FileType.JPEG_FILE].save_to_disk("/home/user/Desktop/export_plot.jpg")
File '/home/user/Desktop/export_plot.jpg' saved
See also
Datafile
API references,Results and associated datafiles detailed section.
Full example script¶
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# This file is part of the 'astrophysix' Python package.
#
# Copyright © Commissariat a l'Energie Atomique et aux Energies Alternatives (CEA)
#
# FREE SOFTWARE LICENCING
# -----------------------
# This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free
# software. You can use, modify and/or redistribute the software under the terms of the CeCILL license as circulated by
# CEA, CNRS and INRIA at the following URL: "http://www.cecill.info". As a counterpart to the access to the source code
# and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty
# and the software's author, the holder of the economic rights, and the successive licensors have only limited
# liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying
# and/or developing or reproducing the software by the user in light of its specific status of free software, that may
# mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and
# experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the
# software's suitability as regards their requirements in conditions enabling the security of their systems and/or data
# to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that
# you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms.
#
#
# COMMERCIAL SOFTWARE LICENCING
# -----------------------------
# You can obtain this software from CEA under other licencing terms for commercial purposes. For this you will need to
# negotiate a specific contract with a legal representative of CEA.
#
from __future__ import print_function, unicode_literals
import os
import numpy as N
from astrophysix.simdm import SimulationStudy, Project, ProjectCategory
from astrophysix.simdm.experiment import Simulation, AppliedAlgorithm, ParameterSetting, ParameterVisibility,\
ResolvedPhysicalProcess
from astrophysix.simdm.protocol import SimulationCode, AlgoType, Algorithm, InputParameter, PhysicalProcess, Physics
from astrophysix.simdm.results import GenericResult, Snapshot
from astrophysix.simdm.datafiles import Datafile, PlotType, PlotInfo
from astrophysix.utils.file import FileType
from astrophysix import units as U
# ----------------------------------------------- Project creation --------------------------------------------------- #
# Available project categories are :
# - ProjectCategory.SolarMHD
# - ProjectCategory.PlanetaryAtmospheres
# - ProjectCategory.StarPlanetInteractions
# - ProjectCategory.StarFormation
# - ProjectCategory.Supernovae
# - ProjectCategory.GalaxyFormation
# - ProjectCategory.GalaxyMergers
# - ProjectCategory.Cosmology
proj = Project(category=ProjectCategory.StarFormation, project_title="Frig",
alias="FRIG", short_description="Short description of my 'FRIG' project",
general_description="""This is a pretty long description for my project""",
data_description="The data available in this project...", directory_path="/path/to/project/data/")
print(proj) # "[Star formation] 'Frig' project"
# -------------------------------------------------------------------------------------------------------------------- #
# --------------------------------------- Simulation code definition ------------------------------------------------- #
ramses = SimulationCode(name="Ramses 3 (MHD)", code_name="Ramses", code_version="3.10.1", alias="RAMSES_3",
url="https://www.ics.uzh.ch/~teyssier/ramses/RAMSES.html",
description="This is a fair description of the Ramses code")
# => Add algorithms : available algorithm types are :
# - AlgoType.AdaptiveMeshRefinement
# - AlgoType.VoronoiMovingMesh
# - AlgoType.SmoothParticleHydrodynamics
# - AlgoType.Godunov
# - AlgoType.PoissonMultigrid
# - AlgoType.PoissonConjugateGradient
# - AlgoType.ParticleMesh
# - AlgoType.FriendOfFriend
# - AlgoType.HLLCRiemann
# - AlgoType.RayTracer
amr = ramses.algorithms.add(Algorithm(algo_type=AlgoType.AdaptiveMeshRefinement, description="AMR descr"))
ramses.algorithms.add(Algorithm(algo_type=AlgoType.Godunov, description="Godunov scheme"))
ramses.algorithms.add(Algorithm(algo_type=AlgoType.HLLCRiemann, description="HLLC Riemann solver"))
ramses.algorithms.add(Algorithm(algo_type=AlgoType.PoissonMultigrid, description="Multigrid Poisson solver"))
ramses.algorithms.add(Algorithm(algo_type=AlgoType.ParticleMesh, description="PM solver"))
# => Add input parameters
ramses.input_parameters.add(InputParameter(key="levelmin", name="Lmin",
description="min. level of AMR refinement"))
lmax = ramses.input_parameters.add(InputParameter(key="levelmax", name="Lmax",
description="max. level of AMR refinement"))
# => Add physical processes : available physics are :
# - Physics.SelfGravity
# - Physics.Hydrodynamics
# - Physics.MHD
# - Physics.StarFormation
# - Physics.SupernovaeFeedback
# - Physics.AGNFeedback
# - Physics.MolecularCooling
ramses.physical_processes.add(PhysicalProcess(physics=Physics.StarFormation, description="descr sf"))
ramses.physical_processes.add(PhysicalProcess(physics=Physics.Hydrodynamics, description="descr hydro"))
grav = ramses.physical_processes.add(PhysicalProcess(physics=Physics.SelfGravity, description="descr self G"))
ramses.physical_processes.add(PhysicalProcess(physics=Physics.SupernovaeFeedback, description="SN feedback"))
# -------------------------------------------------------------------------------------------------------------------- #
# -------------------------------------------- Simulation setup ------------------------------------------------------ #
simu = Simulation(simu_code=ramses, name="My most important simulation", alias="SIMU_1", description="Simu description",
execution_time="2020-03-01 18:45:30", directory_path="/path/to/my/project/simulation/data/")
proj.simulations.add(simu)
# Add applied algorithms implementation details. Warning : corresponding algorithms must have been added in the 'ramses'
# simulation code.
simu.applied_algorithms.add(AppliedAlgorithm(algorithm=amr, details="My AMR implementation [Teyssier 2002]"))
simu.applied_algorithms.add(AppliedAlgorithm(algorithm=ramses.algorithms[AlgoType.HLLCRiemann.name],
details="My Riemann solver implementation [Teyssier 2002]"))
# Add parameter setting. Warning : corresponding input parameter must have been added in the 'ramses' simulation code.
# Available parameter visibility options are :
# - ParameterVisibility.NOT_DISPLAYED
# - ParameterVisibility.ADVANCED_DISPLAY
# - ParameterVisibility.BASIC_DISPLAY
simu.parameter_settings.add(ParameterSetting(input_param=ramses.input_parameters["Lmin"], value=8,
visibility=ParameterVisibility.BASIC_DISPLAY))
simu.parameter_settings.add(ParameterSetting(input_param=lmax, value=12,
visibility=ParameterVisibility.BASIC_DISPLAY))
# Add resolved physical process implementation details. Warning : corresponding physical process must have been added to
# the 'ramses' simulation code
simu.resolved_physics.add(ResolvedPhysicalProcess(physics=ramses.physical_processes[Physics.StarFormation.name],
details="Star formation specific implementation"))
simu.resolved_physics.add(ResolvedPhysicalProcess(physics=grav, details="self-gravity specific implementation"))
# -------------------------------------------------------------------------------------------------------------------- #
# -------------------------------------- Simulation generic result and snapshots ------------------------------------- #
# Generic result
gres = GenericResult(name="Key result 1 !", description="My description", directory_path="/my/path/to/result")
simu.generic_results.add(gres)
# Simulation snapshot
# In one-line
sn = simu.snapshots.add(Snapshot(name="My best snapshot !", description="My first snapshot description",
time=(125, U.kyr), physical_size=(250.0, U.kpc), directory_path="/path/to/snapshot1",
data_reference="OUTPUT_00056"))
# Or create snapshot, then add it to the simulation
sn2 = Snapshot(name="My second best snapshot !", description="My second snapshot description", time=(0.26, U.Myr),
physical_size=(0.25, U.Mpc), directory_path="/path/to/snapshot2", data_reference="OUTPUT_00158")
simu.snapshots.add(sn2)
# -------------------------------------------------------------------------------------------------------------------- #
# ---------------------------------------------------- Result datafiles ---------------------------------------------- #
# Datafile creation
imf_df = sn.datafiles.add(Datafile(name="Initial mass function plot",
description="This is my plot detailed description"))
# Add attached files to a datafile (1 per file type). Available file types are :
# - FileType.HDF5_FILE
# - FileType.PNG_FILE
# - FileType.JPEG_FILE
# - FileType.FITS_FILE
# - FileType.TARGZ_FILE
# - FileType.PICKLE_FILE
# - FileType.JSON_FILE
# - FileType.CSV_FILE
# - FileType.ASCII_FILE
imf_df[FileType.PNG_FILE] = os.path.join("/data", "io", "datafiles", "plot_image_IMF.png")
imf_df[FileType.JPEG_FILE] = os.path.join("/data", "io", "datafiles", "plot_with_legend.jpg")
imf_df[FileType.FITS_FILE] = os.path.join("/data", "io", "datafiles", "cassiopea_A_0.5-1.5keV.fits")
imf_df[FileType.TARGZ_FILE] = os.path.join("/data", "io", "datafiles", "archive.tar.gz")
imf_df[FileType.JSON_FILE] = os.path.join("/data", "io", "datafiles", "test_header_249.json")
imf_df[FileType.ASCII_FILE] = os.path.join("/data", "io", "datafiles", "abstract.txt")
imf_df[FileType.HDF5_FILE] = os.path.join("/data", "io", "HDF5", "study.h5")
imf_df[FileType.PICKLE_FILE] = os.path.join("/data", "io", "datafiles", "dict_saved.pkl")
# Datafile plot information (for plot future updates and online interactive visualisation on Galactica web pages).
# Available plot types are :
# - LINE_PLOT
# - SCATTER_PLOT
# - HISTOGRAM
# - HISTOGRAM_2D
# - IMAGE
# - MAP_2D
imf_df.plot_info = PlotInfo(plot_type=PlotType.LINE_PLOT, xaxis_values=N.array([10.0, 20.0, 30.0, 40.0, 50.0]),
yaxis_values=N.array([1.256, 2.456, 3.921, 4.327, 5.159]), xaxis_log_scale=False,
yaxis_log_scale=False, xaxis_label="Mass", yaxis_label="Probability", xaxis_unit=U.Msun,
plot_title="Initial mass function", yaxis_unit=U.Mpc)
# -------------------------------------------------------------------------------------------------------------------- #
# Save study in HDF5 file
study = SimulationStudy(project=proj)
study.save_HDF5("./frig_study.h5")
# Eventually reload it from HDF5 file to edit its content
# study = SimulationStudy.load_HDF5("./frig_study.h5")