Skip to content

Commit

Permalink
Set default logger to stdout and add output directory setting option …
Browse files Browse the repository at this point in the history
…for file loggers (#139)

* Set the default logger to a stdout stream, and add option to manually specify an output directory for file loggers

* Add default None in input parameters of the default logger definition in MicroManagerCoupling

* Set correct getter function name in the Config class and create the output dir before setting it in the handler

* Add sys.stdout in SystemHandler

* Add mock function of get_output_dir()

* Add formatting for date and time in the default stdout logger

* Add Changelog entry
  • Loading branch information
IshaanDesai authored Dec 30, 2024
1 parent 1f98505 commit 5bedd24
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 11 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## latest

- Set default logger to stdout and add output directory setting option for file loggers https://github.com/precice/micro-manager/pull/139
- Remove the `adaptivity_data` data structure and handle all adaptivity data internally https://github.com/precice/micro-manager/pull/137
- Improve logging by wrapping Python logger in a class https://github.com/precice/micro-manager/pull/133
- Refactor large parts of solve and adaptivity to group datasets and simplify handling https://github.com/precice/micro-manager/pull/135
Expand Down
15 changes: 12 additions & 3 deletions micro_manager/adaptivity/adaptivity.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from math import exp
from typing import Callable
from warnings import warn
import subprocess
from micro_manager.tools.logging_wrapper import Logger

import numpy as np
Expand Down Expand Up @@ -37,9 +38,17 @@ def __init__(self, configurator, rank) -> None:
configurator.get_adaptivity_similarity_measure()
)

self._metrics_logger = Logger(
"Adaptivity", "adaptivity-metrics.csv", rank, csv_logger=True
)
output_dir = configurator.get_output_dir()

if output_dir is not None:
subprocess.run(["mkdir", "-p", output_dir]) # Create output directory
self._metrics_logger = Logger(
__name__, output_dir + "/adaptivity-metrics.csv", rank, csv_logger=True
)
else:
self._metrics_logger = Logger(
__name__, "adaptivity-metrics.csv", rank=rank, csv_logger=True
)

self._metrics_logger.log_info_one_rank(
"Time Window,Avg Active Sims,Avg Inactive Sims,Max Active,Max Inactive"
Expand Down
20 changes: 20 additions & 0 deletions micro_manager/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ def __init__(self, config_file_name):
self._postprocessing_file_name = None
self._initialize_once = False

self._output_dir = None

def set_logger(self, logger):
"""
Set the logger for the Config class.
Expand Down Expand Up @@ -91,6 +93,13 @@ def _read_json(self, config_file_name):
.replace(".py", "")
)

try:
self._output_dir = self._data["output_dir"]
except BaseException:
self._logger.log_info_one_rank(
"No output directory provided. Output (including logging) will be saved in the current working directory."
)

try:
self._write_data_names = self._data["coupling_params"]["write_data_names"]
assert isinstance(
Expand Down Expand Up @@ -640,3 +649,14 @@ def create_single_sim_object(self):
True if initialization is done only once, False otherwise.
"""
return self._initialize_once

def get_output_dir(self):
"""
Get the name of the output directory.
Returns
-------
output_dir : string
Name of the output folder.
"""
return self._output_dir
4 changes: 1 addition & 3 deletions micro_manager/micro_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,7 @@ def __init__(self, config_file: str) -> None:
"""
super().__init__(config_file)

self._logger = Logger(
"MicroManagerCoupling", "micro-manager-coupling.log", self._rank
)
self._logger = Logger(__name__, None, self._rank)

self._config.set_logger(self._logger)
self._config.read_json_micro_manager()
Expand Down
18 changes: 13 additions & 5 deletions micro_manager/tools/logging_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@
Provides a logging wrapper for the Micro Manager classes.
"""
import logging
import sys


class Logger:
"""
Provides a logging wrapper for the Micro Manager classes.
"""

def __init__(self, name, log_file, rank=0, level=logging.INFO, csv_logger=False):
def __init__(
self, name, log_file=None, rank=0, level=logging.INFO, csv_logger=False
):
"""
Set up a logger.
Expand All @@ -19,7 +22,7 @@ def __init__(self, name, log_file, rank=0, level=logging.INFO, csv_logger=False)
name : string
Name of the logger.
log_file : string
Name of the log file.
Name of the log file (default is None).
rank : int, optional
Rank of the logger (default is 0).
level : int, optional
Expand All @@ -30,16 +33,21 @@ def __init__(self, name, log_file, rank=0, level=logging.INFO, csv_logger=False)

self._rank = rank

handler = logging.FileHandler(log_file)
if log_file is None:
handler = logging.StreamHandler(sys.stdout)
else:
handler = logging.FileHandler(log_file)

handler.setLevel(level)

if csv_logger:
formatter = logging.Formatter("%(message)s")
else:
formatter = logging.Formatter(
"["
"("
+ str(self._rank)
+ "] %(asctime)s - %(name)s - %(levelname)s - %(message)s"
+ ") %(asctime)s - %(name)s - %(levelname)s - %(message)s",
datefmt="%m/%d/%Y %I:%M:%S %p",
)

handler.setFormatter(formatter)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"micro_file_name": "micro_dummy",
"output_dir": "adaptivity_output",
"coupling_params": {
"precice_config_file_name": "precice-config.xml",
"macro_mesh_name": "macro-cube-mesh",
Expand Down
5 changes: 5 additions & 0 deletions tests/unit/test_adaptivity_parallel.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ def test_update_inactive_sims_global_adaptivity(self):

configurator = MagicMock()
configurator.get_adaptivity_similarity_measure = MagicMock(return_value="L1")
configurator.get_output_dir = MagicMock(return_value="output_dir")

adaptivity_controller = GlobalAdaptivityCalculator(
configurator, 5, global_ids, rank=self._rank, comm=self._comm
)
Expand Down Expand Up @@ -108,6 +110,7 @@ def test_update_all_active_sims_global_adaptivity(self):
configurator.get_adaptivity_refining_const = MagicMock(return_value=0.05)
configurator.get_adaptivity_coarsening_const = MagicMock(return_value=0.2)
configurator.get_adaptivity_similarity_measure = MagicMock(return_value="L2rel")
configurator.get_output_dir = MagicMock(return_value="output_dir")

adaptivity_controller = GlobalAdaptivityCalculator(
configurator, 5, global_ids, rank=self._rank, comm=self._comm
Expand Down Expand Up @@ -175,6 +178,8 @@ def test_communicate_micro_output(self):

configurator = MagicMock()
configurator.get_adaptivity_similarity_measure = MagicMock(return_value="L1")
configurator.get_output_dir = MagicMock(return_value="output_dir")

adaptivity_controller = GlobalAdaptivityCalculator(
configurator, 5, global_ids, rank=self._rank, comm=self._comm
)
Expand Down
8 changes: 8 additions & 0 deletions tests/unit/test_adaptivity_serial.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ def test_get_similarity_dists(self):
"""
configurator = MagicMock()
configurator.get_adaptivity_similarity_measure = MagicMock(return_value="L1")
configurator.get_output_dir = MagicMock(return_value="output_dir")

adaptivity_controller = AdaptivityCalculator(configurator, 0)
adaptivity_controller._hist_param = 0.5
adaptivity_controller._adaptivity_data_names = [
Expand Down Expand Up @@ -102,6 +104,8 @@ def test_update_active_sims(self):
"""
configurator = MagicMock()
configurator.get_adaptivity_similarity_measure = MagicMock(return_value="L1")
configurator.get_output_dir = MagicMock(return_value="output_dir")

adaptivity_controller = AdaptivityCalculator(configurator, 0)
adaptivity_controller._refine_const = self._refine_const
adaptivity_controller._coarse_const = self._coarse_const
Expand Down Expand Up @@ -208,6 +212,8 @@ def test_associate_active_to_inactive(self):
"""
configurator = MagicMock()
configurator.get_adaptivity_similarity_measure = MagicMock(return_value="L1")
configurator.get_output_dir = MagicMock(return_value="output_dir")

adaptivity_controller = AdaptivityCalculator(configurator, 0)
adaptivity_controller._refine_const = self._refine_const
adaptivity_controller._coarse_const = self._coarse_const
Expand Down Expand Up @@ -235,6 +241,8 @@ def test_update_inactive_sims_local_adaptivity(self):
"""
configurator = MagicMock()
configurator.get_adaptivity_similarity_measure = MagicMock(return_value="L1")
configurator.get_output_dir = MagicMock(return_value="output_dir")

adaptivity_controller = LocalAdaptivityCalculator(
configurator, 0, MagicMock(), 5
)
Expand Down

0 comments on commit 5bedd24

Please sign in to comment.