{"id":17904,"url":"https://patchwork.libcamera.org/api/1.1/patches/17904/?format=json","web_url":"https://patchwork.libcamera.org/patch/17904/","project":{"id":1,"url":"https://patchwork.libcamera.org/api/1.1/projects/1/?format=json","name":"libcamera","link_name":"libcamera","list_id":"libcamera_core","list_email":"libcamera-devel@lists.libcamera.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20221129053326.2858347-3-paul.elder@ideasonboard.com>","date":"2022-11-29T05:33:25","name":"[libcamera-devel,2/3] utils: libtuning: Replace eprint with Logger","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"31e29496c373fe90fc99e2dd6c3dcd8db4bfcd61","submitter":{"id":17,"url":"https://patchwork.libcamera.org/api/1.1/people/17/?format=json","name":"Paul Elder","email":"paul.elder@ideasonboard.com"},"delegate":null,"mbox":"https://patchwork.libcamera.org/patch/17904/mbox/","series":[{"id":3645,"url":"https://patchwork.libcamera.org/api/1.1/series/3645/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=3645","date":"2022-11-29T05:33:23","name":"utils: tuning: Add logging infrastructure","version":1,"mbox":"https://patchwork.libcamera.org/series/3645/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/17904/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/17904/checks/","tags":{},"headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id E2CEDBE08B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 29 Nov 2022 05:33:43 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 5CDA163326;\n\tTue, 29 Nov 2022 06:33:43 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 2658161F23\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 29 Nov 2022 06:33:40 +0100 (CET)","from pyrite.tail37cf.ts.net (h175-177-042-159.catv02.itscom.jp\n\t[175.177.42.159])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id E23204E6;\n\tTue, 29 Nov 2022 06:33:38 +0100 (CET)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1669700023;\n\tbh=shAWITXYnfjCp6AIytWBxVwOODCXOonvmVBZVd1MXR0=;\n\th=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:\n\tFrom;\n\tb=zCrMp0BwCHLV7f+lGDvZhfds+6seQCH+J84kMBnFcFqQipMV9RQ0uwF/uKaGfvMWq\n\txLTXZbDFTsZh9AAsZDtFqZVKbRdCSKJBT5Ds+/S1TldG3nFga3goasG3iHbcm2racR\n\tNcheMe5oeFZCWYyBqJhAGMjF76kqIyQcl3D21YU50k+kFPVr39yJCYUXgy4yXVhSng\n\tOUqF+XGixA1/a1b7Fpt8GapWCSt2JFtXRd5mVWS7gvjzr8krKBtT+cGb4dAifwYSEw\n\tTCgvZCNi7LEuKippxZIj/21oNwB+aJ2qYdZMG+pZAiiHiLF8sy9Uey1cQQMv2qm8Q6\n\tnGKKCaqZIPh9w==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1669700019;\n\tbh=shAWITXYnfjCp6AIytWBxVwOODCXOonvmVBZVd1MXR0=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=Y40TfRGc/DSj++wFoXlppaQdRabAaaVnlrYXf3vgOaG2dDKLOwmVaQ5Zcd5OAylnM\n\tLz3i74i3LrZ/y+Frkuuv/JFX/kcPk0pJXwAJQnomvBfL6ntuji5xgOfz2nGDaBOtd3\n\tH9HB0jLrx8GU4FbULVzevdiNN5Wb5AUBe9dWFrSg="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"Y40TfRGc\"; dkim-atps=neutral","To":"libcamera-devel@lists.libcamera.org","Date":"Tue, 29 Nov 2022 14:33:25 +0900","Message-Id":"<20221129053326.2858347-3-paul.elder@ideasonboard.com>","X-Mailer":"git-send-email 2.35.1","In-Reply-To":"<20221129053326.2858347-1-paul.elder@ideasonboard.com>","References":"<20221129053326.2858347-1-paul.elder@ideasonboard.com>","MIME-Version":"1.0","Content-Transfer-Encoding":"8bit","Subject":"[libcamera-devel] [PATCH 2/3] utils: libtuning: Replace eprint with\n\tLogger","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","From":"Paul Elder via libcamera-devel <libcamera-devel@lists.libcamera.org>","Reply-To":"Paul Elder <paul.elder@ideasonboard.com>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"},"content":"Replace all instances (including the definition) of eprint with Logger.\n\nSigned-off-by: Paul Elder <paul.elder@ideasonboard.com>\n---\n .../libtuning/generators/yaml_output.py       |  4 ++--\n utils/tuning/libtuning/image.py               |  6 +++---\n utils/tuning/libtuning/libtuning.py           | 20 +++++++++----------\n utils/tuning/libtuning/macbeth.py             | 12 ++++++-----\n .../libtuning/modules/lsc/raspberrypi.py      | 12 +++++------\n utils/tuning/libtuning/utils.py               | 17 ++++++++--------\n 6 files changed, 37 insertions(+), 34 deletions(-)","diff":"diff --git a/utils/tuning/libtuning/generators/yaml_output.py b/utils/tuning/libtuning/generators/yaml_output.py\nindex effb4fb3..9966cb4c 100644\n--- a/utils/tuning/libtuning/generators/yaml_output.py\n+++ b/utils/tuning/libtuning/generators/yaml_output.py\n@@ -9,7 +9,7 @@ from .generator import Generator\n from numbers import Number\n from pathlib import Path\n \n-import libtuning.utils as utils\n+from libtuning.logger import Logger\n \n \n class YamlOutput(Generator):\n@@ -112,7 +112,7 @@ class YamlOutput(Generator):\n                 continue\n \n             if not isinstance(output_dict[module], dict):\n-                utils.eprint(f'Error: Output of {module.type} is not a dictionary')\n+                Logger.log_error(self, f'Output of {module.type} is not a dictionary')\n                 continue\n \n             lines = self._stringify_dict(output_dict[module])\ndiff --git a/utils/tuning/libtuning/image.py b/utils/tuning/libtuning/image.py\nindex aa9d20b5..0a35f384 100644\n--- a/utils/tuning/libtuning/image.py\n+++ b/utils/tuning/libtuning/image.py\n@@ -12,7 +12,7 @@ import rawpy as raw\n import re\n \n import libtuning as lt\n-import libtuning.utils as utils\n+from libtuning.logger import Logger\n \n \n class Image:\n@@ -25,13 +25,13 @@ class Image:\n         try:\n             self._load_metadata_exif()\n         except Exception as e:\n-            utils.eprint(f'Failed to load metadata from {self.path}: {e}')\n+            Logger.log_error(self, f'Failed to load metadata from {self.path}: {e}')\n             raise e\n \n         try:\n             self._read_image_dng()\n         except Exception as e:\n-            utils.eprint(f'Failed to load image data from {self.path}: {e}')\n+            Logger.log_error(self, f'Failed to load image data from {self.path}: {e}')\n             raise e\n \n     @property\ndiff --git a/utils/tuning/libtuning/libtuning.py b/utils/tuning/libtuning/libtuning.py\nindex a1238bb1..d34d98ab 100644\n--- a/utils/tuning/libtuning/libtuning.py\n+++ b/utils/tuning/libtuning/libtuning.py\n@@ -8,8 +8,8 @@ import argparse\n from pathlib import Path\n \n import libtuning as lt\n+from libtuning.logger import Logger\n import libtuning.utils as utils\n-from libtuning.utils import eprint\n \n from enum import Enum, IntEnum\n \n@@ -109,10 +109,10 @@ class Tuner(object):\n         for module_type in output_order:\n             modules = [module for module in self.modules if module.type == module_type.type]\n             if len(modules) > 1:\n-                eprint(f'Multiple modules found for module type \"{module_type.type}\"')\n+                Logger.log_error(self, f'Multiple modules found for module type \"{module_type.type}\"')\n                 return False\n             if len(modules) < 1:\n-                eprint(f'No module found for module type \"{module_type.type}\"')\n+                Logger.log_error(self, f'No module found for module type \"{module_type.type}\"')\n                 return False\n             self.output_order.append(modules[0])\n \n@@ -121,19 +121,19 @@ class Tuner(object):\n     # \\todo Validate parser and generator at Tuner construction time?\n     def _validate_settings(self):\n         if self.parser is None:\n-            eprint('Missing parser')\n+            Logger.log_error(self, 'Missing parser')\n             return False\n \n         if self.generator is None:\n-            eprint('Missing generator')\n+            Logger.log_error(self, 'Missing generator')\n             return False\n \n         if len(self.modules) == 0:\n-            eprint('No modules added')\n+            Logger.log_error(self, 'No modules added')\n             return False\n \n         if len(self.output_order) != len(self.modules):\n-            eprint('Number of outputs does not match number of modules')\n+            Logger.log_error(self, 'Number of outputs does not match number of modules')\n             return False\n \n         return True\n@@ -208,7 +208,7 @@ class Tuner(object):\n         # Validate modules and set debug\n         for module in self.modules:\n             if not module.validate_config(self.config):\n-                eprint(f'Config is invalid for module {module.type}')\n+                Logger.log_error(self, f'Config is invalid for module {module.type}')\n                 return -1\n \n             if args.debug_dir is not None and \\\n@@ -224,14 +224,14 @@ class Tuner(object):\n \n         images = utils.load_images(args.input, self.config, not has_only_lsc, has_lsc)\n         if images is None or len(images) == 0:\n-            eprint(f'No images were found, or able to load')\n+            Logger.log_error(self, f'No images were found, or able to load')\n             return -1\n \n         # Do the tuning\n         for module in self.modules:\n             out = module.process(self.config, images, self.output)\n             if out is None:\n-                eprint(f'Module {module.name} failed to process, aborting')\n+                Logger.log_error(self, f'Module {module.name} failed to process, aborting')\n                 break\n             self.output[module] = out\n \ndiff --git a/utils/tuning/libtuning/macbeth.py b/utils/tuning/libtuning/macbeth.py\nindex 5faddf66..df16e868 100644\n--- a/utils/tuning/libtuning/macbeth.py\n+++ b/utils/tuning/libtuning/macbeth.py\n@@ -13,7 +13,9 @@ from pathlib import Path\n import numpy as np\n \n from libtuning.image import Image\n+from libtuning.logger import Logger\n \n+macbeth_log_str = 'Macbeth'\n \n # Reshape image to fixed width without distorting returns image and scale\n # factor\n@@ -369,7 +371,7 @@ def get_macbeth_chart(img, ref_data):\n \n     # Catch macbeth errors and continue with code\n     except MacbethError as error:\n-        eprint(error)\n+        Logger.log_error(macbeth_log_str, error)\n         return (0, None, None, False)\n \n \n@@ -486,7 +488,7 @@ def find_macbeth(img, mac_config):\n \n     coords_fit = coords\n     if cor < 0.75:\n-        eprint(f'Warning: Low confidence {cor:.3f} for macbeth chart in {img.path.name}')\n+        Logger.log_warn(macbeth_log_str, f'Low confidence {cor:.3f} for macbeth chart in {img.path.name}')\n \n     if show:\n         draw_macbeth_results(img, coords_fit)\n@@ -499,18 +501,18 @@ def locate_macbeth(image: Image, config: dict):\n     av_chan = (np.mean(np.array(image.channels), axis=0) / (2**16))\n     av_val = np.mean(av_chan)\n     if av_val < image.blacklevel_16 / (2**16) + 1 / 64:\n-        eprint(f'Image {image.path.name} too dark')\n+        Logger.log_error(macbeth_log_str, f'Image {image.path.name} too dark')\n         return None\n \n     macbeth = find_macbeth(av_chan, config['general']['macbeth'])\n \n     if macbeth is None:\n-        eprint(f'No macbeth chart found in {image.path.name}')\n+        Logger.log_error(macbeth_log_str, f'No macbeth chart found in {image.path.name}')\n         return None\n \n     mac_cen_coords = macbeth[1]\n     if not image.get_patches(mac_cen_coords):\n-        eprint(f'Macbeth patches have saturated in {image.path.name}')\n+        Logger.log_error(macbeth_log_str, f'Macbeth patches have saturated in {image.path.name}')\n         return None\n \n     return macbeth\ndiff --git a/utils/tuning/libtuning/modules/lsc/raspberrypi.py b/utils/tuning/libtuning/modules/lsc/raspberrypi.py\nindex a0298348..91aa56e3 100644\n--- a/utils/tuning/libtuning/modules/lsc/raspberrypi.py\n+++ b/utils/tuning/libtuning/modules/lsc/raspberrypi.py\n@@ -8,7 +8,7 @@\n from .lsc import LSC\n \n import libtuning as lt\n-import libtuning.utils as utils\n+from libtuning.logger import Logger\n \n from numbers import Number\n import numpy as np\n@@ -35,7 +35,7 @@ class ALSCRaspberryPi(LSC):\n \n     def validate_config(self, config: dict) -> bool:\n         if self not in config:\n-            utils.eprint(f'{self.type} not in config')\n+            Logger.log_error(self, f'{self.type} not in config')\n             return False\n \n         valid = True\n@@ -46,14 +46,14 @@ class ALSCRaspberryPi(LSC):\n         color_key = self.do_color.name\n \n         if lum_key not in conf and self.luminance_strength.required:\n-            utils.eprint(f'{lum_key} is not in config')\n+            Logger.log_error(self, f'{lum_key} is not in config')\n             valid = False\n \n         if lum_key in conf and (conf[lum_key] < 0 or conf[lum_key] > 1):\n-            utils.eprint(f'Warning: {lum_key} is not in range [0, 1]; defaulting to 0.5')\n+            Logger.log_warn(self, f'Warning: {lum_key} is not in range [0, 1]; defaulting to 0.5')\n \n         if color_key not in conf and self.do_color.required:\n-            utils.eprint(f'{color_key} is not in config')\n+            Logger.log_error(self, f'{color_key} is not in config')\n             valid = False\n \n         return valid\n@@ -236,7 +236,7 @@ class ALSCRaspberryPi(LSC):\n         if count == 1:\n             output['sigma'] = 0.005\n             output['sigma_Cb'] = 0.005\n-            utils.eprint('Warning: Only one alsc calibration found; standard sigmas used for adaptive algorithm.')\n+            Logger.log_warn(self, 'Only one alsc calibration found; standard sigmas used for adaptive algorithm.')\n             return output\n \n         # Obtain worst-case scenario residual sigmas\ndiff --git a/utils/tuning/libtuning/utils.py b/utils/tuning/libtuning/utils.py\nindex b60f2c9b..d33b9294 100644\n--- a/utils/tuning/libtuning/utils.py\n+++ b/utils/tuning/libtuning/utils.py\n@@ -6,6 +6,7 @@\n # utils.py - Utilities for libtuning\n \n import decimal\n+from inspect import currentframe, getframeinfo\n import math\n import numpy as np\n import os\n@@ -15,13 +16,13 @@ import sys\n \n import libtuning as lt\n from libtuning.image import Image\n+from libtuning.logger import Logger\n from libtuning.macbeth import locate_macbeth\n \n-# Utility functions\n \n+utils_log_str = 'Utils'\n \n-def eprint(*args, **kwargs):\n-    print(*args, file=sys.stderr, **kwargs)\n+# Utility functions\n \n \n def get_module_by_type_name(modules, name):\n@@ -45,7 +46,7 @@ def _list_image_files(directory):\n def _parse_image_filename(fn: Path):\n     result = re.search(r'^(alsc_)?(\\d+)[kK]_(\\d+)?[lLuU]?.\\w{3,4}$', fn.name)\n     if result is None:\n-        eprint(f'The file name of {fn.name} is incorrectly formatted')\n+        Logger.log_error(utils_log_str, f'The file name of {fn.name} is incorrectly formatted')\n         return None, None, None\n \n     color = int(result.group(2))\n@@ -72,7 +73,7 @@ def _validate_images(images):\n def load_images(input_dir: str, config: dict, load_nonlsc: bool, load_lsc: bool) -> list:\n     files = _list_image_files(input_dir)\n     if len(files) == 0:\n-        eprint(f'No images found in {input_dir}')\n+        Logger.log_error(utils_log_str, f'No images found in {input_dir}')\n         return None\n \n     images = []\n@@ -83,19 +84,19 @@ def load_images(input_dir: str, config: dict, load_nonlsc: bool, load_lsc: bool)\n \n         # Skip lsc image if we don't need it\n         if lsc_only and not load_lsc:\n-            eprint(f'Skipping {f.name} as this tuner has no LSC module')\n+            Logger.log_info(utils_log_str, f'Skipping {f.name} as this tuner has no LSC module')\n             continue\n \n         # Skip non-lsc image if we don't need it\n         if not lsc_only and not load_nonlsc:\n-            eprint(f'Skipping {f.name} as this tuner only has an LSC module')\n+            Logger.log_info(utils_log_str, f'Skipping {f.name} as this tuner only has an LSC module')\n             continue\n \n         # Load image\n         try:\n             image = Image(f)\n         except Exception as e:\n-            eprint(f'Failed to load image {f.name}: {e}')\n+            Logger.log_warn(utils_log_str, f'Failed to load image {f.name}: {e}')\n             continue\n \n         # Populate simple fields\n","prefixes":["libcamera-devel","2/3"]}