From f61b950f3830506a6d4b92664928b5b2bea4bf7c Mon Sep 17 00:00:00 2001 From: fdobad <29801096+fdobad@users.noreply.github.com> Date: Mon, 26 May 2025 20:43:46 -0400 Subject: [PATCH 1/4] new setup logger checks for existing handlers --- src/fire2a/__init__.py | 44 ++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/src/fire2a/__init__.py b/src/fire2a/__init__.py index 2aabea7..0ec9f45 100644 --- a/src/fire2a/__init__.py +++ b/src/fire2a/__init__.py @@ -17,8 +17,8 @@ """ __author__ = "Fernando Badilla" __revision__ = "$Format:%H$" - import logging +import sys from importlib.metadata import PackageNotFoundError, distribution from pathlib import Path from typing import Any, Dict, List, Tuple, Union @@ -69,16 +69,28 @@ def setup_logger(name: str = __name__, verbosity: int = 0, logfile: Path = None) # root logger logger = logging.getLogger() - # Create a stream handler - import sys - - stream_handler = logging.StreamHandler(sys.stdout) - - # Create a rotating file handler + # Find or create StreamHandler + stream_handler = None + for h in logger.handlers: + if isinstance(h, logging.StreamHandler): + stream_handler = h + break + if stream_handler is None: + stream_handler = logging.StreamHandler(sys.stdout) + logger.addHandler(stream_handler) + + # Find or create RotatingFileHandler + rf_handler = None if logfile: from logging.handlers import RotatingFileHandler - rf_handler = RotatingFileHandler(logfile, maxBytes=25 * 1024, backupCount=5) + for h in logger.handlers: + if isinstance(h, RotatingFileHandler): + rf_handler = h + break + if rf_handler is None: + rf_handler = RotatingFileHandler(logfile, maxBytes=25 * 1024, backupCount=5) + logger.addHandler(rf_handler) # Set the logs level if verbosity in ["CRITICAL", "FATAL"] or verbosity == -1: @@ -93,9 +105,11 @@ def setup_logger(name: str = __name__, verbosity: int = 0, logfile: Path = None) level = logging.DEBUG else: level = logging.DEBUG + logger.setLevel(level) - stream_handler.setLevel(level) - if logfile: + if stream_handler: + stream_handler.setLevel(level) + if logfile and rf_handler: rf_handler.setLevel(level) # formatter @@ -104,13 +118,15 @@ def setup_logger(name: str = __name__, verbosity: int = 0, logfile: Path = None) "%(asctime)s %(levelname)s %(name)s %(message)s", datefmt="%Y-%m-%d %H:%M:%S", ) - stream_handler.setFormatter(formatter) - if logfile: + if stream_handler: + stream_handler.setFormatter(formatter) + if logfile and rf_handler: rf_handler.setFormatter(formatter) # Add the handlers to the logger - logger.addHandler(stream_handler) - if logfile: + if stream_handler: + logger.addHandler(stream_handler) + if logfile and rf_handler: logger.addHandler(rf_handler) logger.debug("Logger initialized @level %s", logging.getLevelName(level)) From 1ac3431258905b791e22c3481ce7453cdfff967c Mon Sep 17 00:00:00 2001 From: fdobad <29801096+fdobad@users.noreply.github.com> Date: Mon, 26 May 2025 20:44:33 -0400 Subject: [PATCH 2/4] add argument to check properly --- src/fire2a/agglomerative_clustering.py | 2 +- src/fire2a/cell2fire.py | 2 +- src/fire2a/downstream_protection_value.py | 2 +- src/fire2a/knapsack.py | 2 +- src/fire2template/documenting.py | 2 +- src/fire2template/template.py | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/fire2a/agglomerative_clustering.py b/src/fire2a/agglomerative_clustering.py index 8bdf852..6e92154 100644 --- a/src/fire2a/agglomerative_clustering.py +++ b/src/fire2a/agglomerative_clustering.py @@ -709,7 +709,7 @@ def main(argv=None): global logger from fire2a import setup_logger - logger = setup_logger(verbosity=args.verbose) + logger = setup_logger(name=__name__, verbosity=args.verbose) logger.info("args %s", args) diff --git a/src/fire2a/cell2fire.py b/src/fire2a/cell2fire.py index f6ae8e3..0f32e74 100644 --- a/src/fire2a/cell2fire.py +++ b/src/fire2a/cell2fire.py @@ -773,7 +773,7 @@ def main(argv=None): global logger from fire2a import setup_logger - logger = setup_logger(verbosity=args.verbose, logfile=args.logfile) + logger = setup_logger(name=__name__, verbosity=args.verbose, logfile=args.logfile) # set other modules logging level logging.getLogger("asyncio").setLevel(logging.INFO) diff --git a/src/fire2a/downstream_protection_value.py b/src/fire2a/downstream_protection_value.py index 3885700..3c9df52 100644 --- a/src/fire2a/downstream_protection_value.py +++ b/src/fire2a/downstream_protection_value.py @@ -450,7 +450,7 @@ def main(argv=None): if argv is None: argv = sys.argv[1:] args = argument_parser(argv) - logger = setup_logger(__name__, args.verbosity, args.logfile) + logger = setup_logger(name=__name__, args.verbosity, args.logfile) logger.info(f"{args=}") logger.debug("debugging...") diff --git a/src/fire2a/knapsack.py b/src/fire2a/knapsack.py index dd1ccbf..274bafa 100644 --- a/src/fire2a/knapsack.py +++ b/src/fire2a/knapsack.py @@ -299,7 +299,7 @@ def pre_solve(argv): global logger from fire2a import setup_logger - logger = setup_logger(verbosity=args.verbose) + logger = setup_logger(name=__name__, verbosity=args.verbose) logger.info("args %s", args) diff --git a/src/fire2template/documenting.py b/src/fire2template/documenting.py index 1550f75..f7481f3 100644 --- a/src/fire2template/documenting.py +++ b/src/fire2template/documenting.py @@ -133,7 +133,7 @@ def do_something(self, *args, **kwargs): def main(argv): """This is a function docstring that describes a function""" - logger = setup_logger(__name__, 2, None) + logger = setup_logger(name=__name__, 2, None) logger.info("Hello world!") logger.info(f"argv:{argv}") returns = b_method((1, "a"), "b", "c", an_optional_argument=2, d="e", f="g") diff --git a/src/fire2template/template.py b/src/fire2template/template.py index 0d0c84e..a3c94ac 100644 --- a/src/fire2template/template.py +++ b/src/fire2template/template.py @@ -143,7 +143,7 @@ def main(argv=None): global logger from fire2template import setup_logger - logger = setup_logger(verbosity=args.verbose, logfile=args.logfile) + logger = setup_logger(name=__name__, verbosity=args.verbose, logfile=args.logfile) # set other modules logging level logging.getLogger("asyncio").setLevel(logging.INFO) From a2c492844ede640d96f74dc6204d5507def1269f Mon Sep 17 00:00:00 2001 From: fdobad <29801096+fdobad@users.noreply.github.com> Date: Mon, 26 May 2025 20:44:48 -0400 Subject: [PATCH 3/4] formatting --- src/fire2a/cell2fire.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/fire2a/cell2fire.py b/src/fire2a/cell2fire.py index 0f32e74..cccbbed 100644 --- a/src/fire2a/cell2fire.py +++ b/src/fire2a/cell2fire.py @@ -366,7 +366,7 @@ def final_scar_step(i, data, afile, scar_raster, scar_raster_ds, burn_prob, burn if burn_prob: if np_any(data == -1): mask = data != -1 - burn_prob_arr[ mask ] += data[ mask ] + burn_prob_arr[mask] += data[mask] else: burn_prob_arr += data @@ -566,8 +566,7 @@ def build_stats( callback=None, feedback=None, ): - """Builds final statistics raster (1 band per-simulation) and summary raster (2 bands: mean against pixel burn count and stdev against total number of simulations) files - """ + """Builds final statistics raster (1 band per-simulation) and summary raster (2 bands: mean against pixel burn count and stdev against total number of simulations) files""" from numpy import float32 as np_float32 from numpy import loadtxt as np_loadtxt from numpy import sqrt as np_sqrt @@ -635,7 +634,7 @@ def build_stats( mask = data != -9999 tmp = data[mask] summed[mask] += tmp - sumsquared[mask] += tmp ** 2 + sumsquared[mask] += tmp**2 burncount[mask & (data != 0)] += 1 if callback: @@ -668,7 +667,7 @@ def build_stats( # std # from all simulations N = len(files) - stddev = np_sqrt(sumsquared / N - (summed/N)**2) + stddev = np_sqrt(sumsquared / N - (summed / N) ** 2) # beacause this is always zero: # stddev = np_zeros((H, W), dtype=np_float32) - 9999 # zero_mask = burncount == 0 From 3c17ee1b4379ae89a4c02879faa1a09a22d9fb0c Mon Sep 17 00:00:00 2001 From: fdobad Date: Tue, 3 Jun 2025 17:31:42 -0400 Subject: [PATCH 4/4] logger harcoded name in case is run from main --- src/fire2a/agglomerative_clustering.py | 3 ++- src/fire2a/cell2fire.py | 3 ++- src/fire2a/downstream_protection_value.py | 3 ++- src/fire2template/documenting.py | 3 ++- src/fire2template/template.py | 3 ++- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/fire2a/agglomerative_clustering.py b/src/fire2a/agglomerative_clustering.py index 6e92154..01249f3 100644 --- a/src/fire2a/agglomerative_clustering.py +++ b/src/fire2a/agglomerative_clustering.py @@ -709,7 +709,8 @@ def main(argv=None): global logger from fire2a import setup_logger - logger = setup_logger(name=__name__, verbosity=args.verbose) + name = __name__ if __name__ != "__main__" else "fire2a.agglomerative_clustering" + logger = setup_logger(name, verbosity=args.verbose) logger.info("args %s", args) diff --git a/src/fire2a/cell2fire.py b/src/fire2a/cell2fire.py index cccbbed..86fda55 100644 --- a/src/fire2a/cell2fire.py +++ b/src/fire2a/cell2fire.py @@ -772,7 +772,8 @@ def main(argv=None): global logger from fire2a import setup_logger - logger = setup_logger(name=__name__, verbosity=args.verbose, logfile=args.logfile) + name = __name__ if __name__ != "__main__" else "fire2a.cell2fire" + logger = setup_logger(name, verbosity=args.verbose, logfile=args.logfile) # set other modules logging level logging.getLogger("asyncio").setLevel(logging.INFO) diff --git a/src/fire2a/downstream_protection_value.py b/src/fire2a/downstream_protection_value.py index 3c9df52..89f1880 100644 --- a/src/fire2a/downstream_protection_value.py +++ b/src/fire2a/downstream_protection_value.py @@ -450,7 +450,8 @@ def main(argv=None): if argv is None: argv = sys.argv[1:] args = argument_parser(argv) - logger = setup_logger(name=__name__, args.verbosity, args.logfile) + name = __name__ if __name__ != "__main__" else "fire2a.downstream_protection_value" + logger = setup_logger(name, args.verbosity, args.logfile) logger.info(f"{args=}") logger.debug("debugging...") diff --git a/src/fire2template/documenting.py b/src/fire2template/documenting.py index f7481f3..4728e41 100644 --- a/src/fire2template/documenting.py +++ b/src/fire2template/documenting.py @@ -133,7 +133,8 @@ def do_something(self, *args, **kwargs): def main(argv): """This is a function docstring that describes a function""" - logger = setup_logger(name=__name__, 2, None) + name = __name__ if __name__ != "__main__" else "fire2a.documenting" + logger = setup_logger(name, 2, None) logger.info("Hello world!") logger.info(f"argv:{argv}") returns = b_method((1, "a"), "b", "c", an_optional_argument=2, d="e", f="g") diff --git a/src/fire2template/template.py b/src/fire2template/template.py index a3c94ac..a57e6d6 100644 --- a/src/fire2template/template.py +++ b/src/fire2template/template.py @@ -143,7 +143,8 @@ def main(argv=None): global logger from fire2template import setup_logger - logger = setup_logger(name=__name__, verbosity=args.verbose, logfile=args.logfile) + name = __name__ if __name__ != "__main__" else "fire2a.template" + logger = setup_logger(name, verbosity=args.verbose, logfile=args.logfile) # set other modules logging level logging.getLogger("asyncio").setLevel(logging.INFO)