Show a patch.

GET /api/1.1/patches/17904/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 17904,
    "url": "https://patchwork.libcamera.org/api/1.1/patches/17904/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/17904/",
    "project": {
        "id": 1,
        "url": "https://patchwork.libcamera.org/api/1.1/projects/1/?format=api",
        "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=api",
        "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=api",
            "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"
    ]
}