Show a patch.

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

{
    "id": 23005,
    "url": "https://patchwork.libcamera.org/api/patches/23005/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/23005/",
    "project": {
        "id": 1,
        "url": "https://patchwork.libcamera.org/api/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": "<20250324170803.103296-5-stefan.klug@ideasonboard.com>",
    "date": "2025-03-24T17:07:39",
    "name": "[4/5] libipa: histogram: Fix interQuantileMean() for small ranges",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": false,
    "hash": "20a25eae1ced3a7e066d6d5d49ce8658fd21b094",
    "submitter": {
        "id": 184,
        "url": "https://patchwork.libcamera.org/api/people/184/?format=api",
        "name": "Stefan Klug",
        "email": "stefan.klug@ideasonboard.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/23005/mbox/",
    "series": [
        {
            "id": 5077,
            "url": "https://patchwork.libcamera.org/api/series/5077/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=5077",
            "date": "2025-03-24T17:07:35",
            "name": "Fix histogram for some (corner) cases",
            "version": 1,
            "mbox": "https://patchwork.libcamera.org/series/5077/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/23005/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/23005/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 F00EBC3213\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 24 Mar 2025 17:08:27 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id AE3F76895F;\n\tMon, 24 Mar 2025 18:08:27 +0100 (CET)",
            "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 693CA6895D\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 24 Mar 2025 18:08:25 +0100 (CET)",
            "from ideasonboard.com (unknown\n\t[IPv6:2a00:6020:448c:6c00:854:5bc6:b2a7:e242])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id CDA5AA8F;\n\tMon, 24 Mar 2025 18:06:38 +0100 (CET)"
        ],
        "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"Vap0Xg5G\"; dkim-atps=neutral",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1742835998;\n\tbh=0uGFCAEhZMyiQcNIKO7XXs1LGnUKZrRebehhUvhFAsU=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=Vap0Xg5GjqNzJwi3qdv1hBSge11DQmlaes9qOJt6I/StWxsJqSgrl1x777XcLBnjL\n\tstuuF96Fr1ikPqVbeRePex/+DO5k+KGJ51IcLgRJ21P+u/oHqSwe5kQiMcowFUSEgY\n\tgbs6RFeGJ3pdvI6vnyQTTQuk4PEbmnjPtfLlxcnM=",
        "From": "Stefan Klug <stefan.klug@ideasonboard.com>",
        "To": "libcamera-devel@lists.libcamera.org",
        "Cc": "Stefan Klug <stefan.klug@ideasonboard.com>",
        "Subject": "[PATCH 4/5] libipa: histogram: Fix interQuantileMean() for small\n\tranges",
        "Date": "Mon, 24 Mar 2025 18:07:39 +0100",
        "Message-ID": "<20250324170803.103296-5-stefan.klug@ideasonboard.com>",
        "X-Mailer": "git-send-email 2.43.0",
        "In-Reply-To": "<20250324170803.103296-1-stefan.klug@ideasonboard.com>",
        "References": "<20250324170803.103296-1-stefan.klug@ideasonboard.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "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>",
        "Errors-To": "libcamera-devel-bounces@lists.libcamera.org",
        "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"
    },
    "content": "The interQuantileMean() is supposed to return a weighted mean value\nbetween two quantiles. This works for reasonably fine histograms, but\nfails for coarse histograms and small quantile ranges because the weight\nis always taken from the lower border of the bin.\n\nFix that by rewriting the algorithm to calculate a lower and upper bound\nfor every (partial) bin that goes into the mean calculation and weight\nthe bins by the middle of these bounds.\n\nSigned-off-by: Stefan Klug <stefan.klug@ideasonboard.com>\n---\n src/ipa/libipa/histogram.cpp | 20 +++++++++++---------\n 1 file changed, 11 insertions(+), 9 deletions(-)",
    "diff": "diff --git a/src/ipa/libipa/histogram.cpp b/src/ipa/libipa/histogram.cpp\nindex c19a4cbbf3cd..31f017af3458 100644\n--- a/src/ipa/libipa/histogram.cpp\n+++ b/src/ipa/libipa/histogram.cpp\n@@ -153,22 +153,24 @@ double Histogram::interQuantileMean(double lowQuantile, double highQuantile) con\n \tdouble lowPoint = quantile(lowQuantile);\n \t/* Proportion of pixels which lies below highQuantile */\n \tdouble highPoint = quantile(highQuantile, static_cast<uint32_t>(lowPoint));\n-\tdouble sumBinFreq = 0, cumulFreq = 0;\n+\tdouble sumBinFreq = 0;\n+\tdouble cumulFreq = 0;\n+\n+\tfor (int bin = std::floor(lowPoint); bin < std::ceil(highPoint); bin++) {\n+\t\tdouble lowBound = std::max(static_cast<double>(bin), lowPoint);\n+\t\tdouble highBound = std::min(static_cast<double>(bin + 1), highPoint);\n \n-\tfor (double p_next = floor(lowPoint) + 1.0;\n-\t     p_next <= ceil(highPoint);\n-\t     lowPoint = p_next, p_next += 1.0) {\n-\t\tint bin = floor(lowPoint);\n \t\tdouble freq = (cumulative_[bin + 1] - cumulative_[bin])\n-\t\t\t* (std::min(p_next, highPoint) - lowPoint);\n+\t\t\t* (highBound - lowBound);\n \n \t\t/* Accumulate weighted bin */\n-\t\tsumBinFreq += bin * freq;\n+\t\tsumBinFreq += 0.5 * (highBound + lowBound) * freq;\n+\n \t\t/* Accumulate weights */\n \t\tcumulFreq += freq;\n \t}\n-\t/* add 0.5 to give an average for bin mid-points */\n-\treturn sumBinFreq / cumulFreq + 0.5;\n+\n+\treturn sumBinFreq / cumulFreq;\n }\n \n } /* namespace ipa */\n",
    "prefixes": [
        "4/5"
    ]
}