Skip to content

Commit

Permalink
Formatting Logging Output for Simulation (tardis-sn#1632)
Browse files Browse the repository at this point in the history
* Formatting Logging Output for Simulation runs via Notebook

* Reverting removed import

* Fixing decimal precision for luminosity values

* Formatting changes for the Plasma Stratification values displayed

* Allowing pandas dataframe to be displayed in Notebook as well as Terminal

* Removing redundant pandas setting

* Adding import for get_ipython()

* Moving simulation environment checking to another PR & made appropriate changes

* Added some more formatting changes to other logging messages for consistency

* Renamed check_simulation_env() to is_notebook(), Added better conditional checks for the environment using isinstance()

* Formatting changed for Simulation message about no of iterations & time taken

* Added Tests for checking the logging done while running the simulation
  • Loading branch information
DhruvSondhi authored Jun 17, 2021
1 parent 78b3457 commit dc3675e
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 25 deletions.
4 changes: 2 additions & 2 deletions tardis/io/atom_data/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,11 +186,11 @@ def from_hdf(cls, fname=None):
# ToDo: strore data sources as attributes in carsus

logger.info(
f"Read Atom Data with UUID={atom_data.uuid1} and MD5={atom_data.md5}."
f"\n\tReading Atom Data with:\n\tUUID = {atom_data.uuid1}\n\tMD5 = {atom_data.md5} "
)
if nonavailable:
logger.info(
f'Non provided atomic data: {", ".join(nonavailable)}'
f'\n\tNon provided atomic data:\n\t{", ".join(nonavailable)}'
)

return atom_data
Expand Down
2 changes: 1 addition & 1 deletion tardis/io/atom_data/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def resolve_atom_data_fname(fname):
fpath = os.path.join(os.path.join(get_data_dir(), fname))
if os.path.exists(fpath):
logger.info(
f"Atom Data {fname} not found in local path. Exists in TARDIS Data repo {fpath}"
f"\n\tAtom Data {fname} not found in local path.\n\tExists in TARDIS Data repo {fpath}"
)
return fpath

Expand Down
2 changes: 1 addition & 1 deletion tardis/plasma/standard_plasmas.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def assemble_plasma(config, model, atom_data=None):
else:
raise ValueError("No atom_data option found in the configuration.")

logger.info("Reading Atomic Data from %s", atom_data_fname)
logger.info(f"\n\tReading Atomic Data from {atom_data_fname}")

try:
atom_data = AtomData.from_hdf(atom_data_fname)
Expand Down
43 changes: 29 additions & 14 deletions tardis/simulation/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
from tardis.plasma.standard_plasmas import assemble_plasma
from tardis.io.util import HDFWriterMixin
from tardis.io.config_reader import ConfigurationError
from tardis.util.base import is_notebook
from tardis.montecarlo import montecarlo_configuration as mc_config_module
from IPython.display import display

# Adding logging support
logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -320,7 +322,7 @@ def advance_state(self):

def iterate(self, no_of_packets, no_of_virtual_packets=0, last_run=False):
logger.info(
f"Starting iteration {(self.iterations_executed + 1):d}/{self.iterations:d}"
f"\n\tStarting iteration {(self.iterations_executed + 1):d} of {self.iterations:d}"
)
self.runner.run(
self.model,
Expand Down Expand Up @@ -348,6 +350,7 @@ def run(self):
"""
run the simulation
"""

start_time = time.time()
while self.iterations_executed < self.iterations - 1:
self.store_plasma_state(
Expand Down Expand Up @@ -378,8 +381,8 @@ def run(self):
self.reshape_plasma_state_store(self.iterations_executed)

logger.info(
f"Simulation finished in {self.iterations_executed:d} iterations "
f"and took {(time.time() - start_time):.2f} s"
f"\n\tSimulation finished in {self.iterations_executed:d} iterations "
f"\n\tSimulation took {(time.time() - start_time):.2f} s\n"
)
self._call_back()

Expand Down Expand Up @@ -421,23 +424,35 @@ def log_plasma_state(
plasma_state_log["next_t_rad"] = next_t_rad
plasma_state_log["w"] = w
plasma_state_log["next_w"] = next_w
plasma_state_log.columns.name = "Shell No."

plasma_state_log.index.name = "Shell"

plasma_state_log = str(plasma_state_log[::log_sampling])
if is_notebook():
logger.info("\n\tPlasma stratification:")
logger.info(
display(
plasma_state_log.iloc[::log_sampling].style.format("{:.3g}")
)
)
else:
output_df = ""
plasma_output = plasma_state_log.iloc[::log_sampling].to_string(
float_format=lambda x: "{:.3g}".format(x),
justify="center",
)
for value in plasma_output.split("\n"):
output_df = output_df + "\t{}\n".format(value)
logger.info("\n\tPlasma stratification:")
logger.info(f"\n{output_df}")

plasma_state_log = "".join(
["\t%s\n" % item for item in plasma_state_log.split("\n")]
logger.info(
f"\n\tCurrent t_inner = {t_inner:.3f}\n\tExpected t_inner for next iteration = {next_t_inner:.3f}\n"
)

logger.info("Plasma stratification:\n%s\n", plasma_state_log)
logger.info(f"t_inner {t_inner:.3f} -- next t_inner {next_t_inner:.3f}")

def log_run_results(self, emitted_luminosity, absorbed_luminosity):
logger.info(
f"Luminosity emitted = {emitted_luminosity:.5e} "
f"Luminosity absorbed = {absorbed_luminosity:.5e} "
f"Luminosity requested = {self.luminosity_requested:.5e}"
f"\n\tLuminosity emitted = {emitted_luminosity:.3e}\n"
f"\tLuminosity absorbed = {absorbed_luminosity:.3e}\n"
f"\tLuminosity requested = {self.luminosity_requested:.3e}\n"
)

def _call_back(self):
Expand Down
19 changes: 19 additions & 0 deletions tardis/simulation/tests/test_simulation.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import os

import pytest
import logging

from tardis.io.config_reader import Configuration
from tardis.simulation import Simulation

Expand Down Expand Up @@ -153,3 +155,20 @@ def test_plasma_state_storer_reshape(

# assert_quantity_allclose(
# t_rad, simulation_compare_data['test1/t_rad'] * u.Unit('K'), atol=0.0 * u.Unit('K'))


def test_logging_simulation(atomic_data_fname, caplog):
"""
Testing the logs for simulations runs
"""
config = Configuration.from_yaml(
"tardis/io/tests/data/tardis_configv1_verysimple.yml"
)
config["atom_data"] = atomic_data_fname

simulation = Simulation.from_config(config)

simulation.run()

for record in caplog.records:
assert record.levelno >= logging.INFO
35 changes: 28 additions & 7 deletions tardis/util/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -542,23 +542,44 @@ def convert_abundances_format(fname, delimiter=r"\s+"):
return df


def check_simulation_env():
def is_notebook():
"""
Checking the environment where the simulation is run
Checking the shell environment where the simulation is run is Jupyter based
Returns
-------
True : if the environment is IPython Based
False : if the environment is Terminal or anything else
True : if the shell environment is IPython Based
False : if the shell environment is Terminal or anything else
"""
try:
shell = get_ipython().__class__.__name__
# Trying to import the ZMQInteractiveShell for Jupyter based environments
from ipykernel.zmqshell import ZMQInteractiveShell
except NameError:
# If the class cannot be imported then we are automatically return False Value
# Raised due to Name Error with the imported Class
return False

if shell == "ZMQInteractiveShell":
try:
# Trying to import Interactive Terminal based IPython shell
from IPython.core.interactiveshell import InteractiveShell
except NameError:
# If the class cannot be imported then we are automatically return False Value
# Raised due to Name Error with the imported Class
return False

try:
# Trying to get the value of the shell via the get_ipython() method
shell = get_ipython()
except NameError:
# Returns False if the shell name cannot be inferred correctly
return False

# Checking if the shell instance is Jupyter based & if True, returning True
if isinstance(shell, ZMQInteractiveShell):
return True
elif shell == "TerminalInteractiveShell":
# Checking if the shell instance is Terminal IPython based & if True, returning False
elif isinstance(shell, InteractiveShell):
return False
# All other shell instances are returned False
else:
return False

0 comments on commit dc3675e

Please sign in to comment.