From bd9915e1e3c5b127e1a72ff130352d5a40c2b11b Mon Sep 17 00:00:00 2001 From: Marcus Baw Date: Thu, 27 Aug 2026 13:43:08 +0100 Subject: [PATCH 1/6] fix: include exact gestational chart boundaries --- rcpchgrowth/constants/reference_constants.py | 12 ++++-- rcpchgrowth/global_functions.py | 4 +- rcpchgrowth/tests/test_chart_boundary_ages.py | 42 +++++++++++++++++++ 3 files changed, 53 insertions(+), 5 deletions(-) create mode 100644 rcpchgrowth/tests/test_chart_boundary_ages.py diff --git a/rcpchgrowth/constants/reference_constants.py b/rcpchgrowth/constants/reference_constants.py index 435d476..398452e 100644 --- a/rcpchgrowth/constants/reference_constants.py +++ b/rcpchgrowth/constants/reference_constants.py @@ -2,6 +2,12 @@ Reference constants """ +from .age_constants import ( + FORTY_TWO_WEEKS_GESTATION, + TWENTY_FIVE_WEEKS_GESTATION, + TWENTY_THREE_WEEKS_GESTATION, +) + # Trisomy 21 constants TRISOMY_21 = "trisomy-21" TRISOMY_21_AAP = "trisomy-21-aap" @@ -111,8 +117,8 @@ ] EXTENDED_WHO_CENTILES_COLLECTION = [1, 3, 5, 10, 15, 50, 85, 90, 95, 97, 99] -UK_90_PRETERM_AGES = [-0.325804244, -0.306639288, -0.287474333, -0.268309377, -0.249144422, -0.229979466, -0.210814511, -0.191649555, -0.1724846, -0.153319644, -0.134154689, -0.114989733, -0.095824778, -0.076659822, -0.057494867, -0.038329911, -0.019164956, 0, 0.019164956, 0.038329911] -WHO_2006_UNDER_TWOS_AGES = [0.038329911, 0.057494867, 0.076659822, 0.083333333, 0.095824778, 0.114989733, 0.134154689, 0.153319644, 0.166666667, 0.1724846, 0.191649555, 0.210814511, 0.229979466, 0.249144422, 0.25, 0.333333333, 0.416666667, 0.5, 0.583333333, 0.666666667, 0.75, 0.833333333, 0.916666667, 1, 1.083333333, 1.166666667, 1.25, 1.333333333, 1.416666667, 1.5, 1.583333333, 1.666666667, 1.75, 1.833333333, 1.916666667, 2] +UK_90_PRETERM_AGES = [TWENTY_THREE_WEEKS_GESTATION, -0.306639288, TWENTY_FIVE_WEEKS_GESTATION, -0.268309377, -0.249144422, -0.229979466, -0.210814511, -0.191649555, -0.1724846, -0.153319644, -0.134154689, -0.114989733, -0.095824778, -0.076659822, -0.057494867, -0.038329911, -0.019164956, 0, 0.019164956, FORTY_TWO_WEEKS_GESTATION] +WHO_2006_UNDER_TWOS_AGES = [FORTY_TWO_WEEKS_GESTATION, 0.057494867, 0.076659822, 0.083333333, 0.095824778, 0.114989733, 0.134154689, 0.153319644, 0.166666667, 0.1724846, 0.191649555, 0.210814511, 0.229979466, 0.249144422, 0.25, 0.333333333, 0.416666667, 0.5, 0.583333333, 0.666666667, 0.75, 0.833333333, 0.916666667, 1, 1.083333333, 1.166666667, 1.25, 1.333333333, 1.416666667, 1.5, 1.583333333, 1.666666667, 1.75, 1.833333333, 1.916666667, 2] UK_WHO_2006_OVER_TWOS_AGES = [2, 2.083333333, 2.166666667, 2.25, 2.333333333, 2.416666667, 2.5, 2.583333333, 2.666666667, 2.75, 2.833333333, 2.916666667, 3, 3.083333333, 3.166666667, 3.25, 3.333333333, 3.416666667, 3.5, 3.583333333, 3.666666667, 3.75, 3.833333333, 3.916666667, 4] WHO_2006_OVER_TWOS_AGES = [2, 2.083333333, 2.166666667, 2.25, 2.333333333, 2.416666667, 2.5, 2.583333333, 2.666666667, 2.75, 2.833333333, 2.916666667, 3, 3.083333333, 3.166666667, 3.25, 3.333333333, 3.416666667, 3.5, 3.583333333, 3.666666667, 3.75, 3.833333333, 3.916666667, 4, 4.083333333, 4.166666667, 4.25, 4.333333333, 4.416666667, 4.5, 4.583333333, 4.666666667, 4.75, 4.833333333, 4.916666667, 5.0] WHO_2007_AGES = [5.0, 5.08,5.17,5.25,5.33,5.42, 5.5,5.58,5.67,5.75,5.83,5.92,6,6.08,6.17,6.25,6.33,6.42, 6.5,6.58,6.67,6.75,6.83,6.92,7,7.08,7.17,7.25,7.33,7.42, 7.5,7.58,7.67,7.75,7.83,7.92,8,8.08,8.17,8.25,8.33,8.42, 8.5,8.58,8.67,8.75,8.83,8.92,9,9.08,9.17,9.25,9.33,9.42, 9.5,9.58,9.67,9.75,9.83,9.92,10,10.08,10.17,10.25,10.33,10.42, 10.5,10.58,10.67,10.75,10.83,10.92,11,11.08,11.17,11.25,11.33,11.42, 11.5,11.58,11.67,11.75,11.83,11.92,12,12.08,12.17,12.25,12.33,12.42, 12.5,12.58,12.67,12.75,12.83,12.92,13,13.08,13.17,13.25,13.33,13.42, 13.5,13.58,13.67,13.75,13.83,13.92,14,14.08,14.17,14.25,14.33,14.42, 14.5,14.58,14.67,14.75,14.83,14.92,15,15.08,15.17,15.25,15.33,15.42, 15.5,15.58,15.67,15.75,15.83,15.92,16,16.08,16.17,16.25,16.33,16.42, 16.5,16.58,16.67,16.75,16.83,16.92,17,17.08,17.17,17.25,17.33,17.42, 17.5,17.58,17.67,17.75,17.83,17.92, 18,18.08,18.17,18.25,18.33,18.42, 18.5,18.58,18.67,18.75,18.83,18.92,19] @@ -123,4 +129,4 @@ TURNER_AGES=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] TRISOMY_21_AGES=[0, 0.08, 0.17, 0.25, 0.33, 0.42, 0.5, 0.58, 0.67, 0.75, 0.83, 0.92, 1, 1.08, 1.17, 1.25, 1.33, 1.42, 1.5, 1.58, 1.67, 1.75, 1.83, 1.92, 2, 2.08, 2.17, 2.25, 2.33, 2.42, 2.5, 2.58, 2.67, 2.75, 2.83, 2.92, 3, 3.08, 3.17, 3.25, 3.33, 3.42, 3.5, 3.58, 3.67, 3.75, 3.83, 3.92, 4, 4.08, 4.17, 4.25, 4.33, 4.42, 4.5, 4.58, 4.67, 4.75, 4.83, 4.92, 5, 5.08, 5.17, 5.25, 5.33, 5.42, 5.5, 5.58, 5.67, 5.75, 5.83, 5.92, 6, 6.08, 6.17, 6.25, 6.33, 6.42, 6.5, 6.58, 6.67, 6.75, 6.83, 6.92, 7, 7.08, 7.17, 7.25, 7.33, 7.42, 7.5, 7.58, 7.67, 7.75, 7.83, 7.92, 8, 8.08, 8.17, 8.25, 8.33, 8.42, 8.5, 8.58, 8.67, 8.75, 8.83, 8.92, 9, 9.08, 9.17, 9.25, 9.33, 9.42, 9.5, 9.58, 9.67, 9.75, 9.83, 9.92, 10, 10.08, 10.17, 10.25, 10.33, 10.42, 10.5, 10.58, 10.67, 10.75, 10.83, 10.92, 11, 11.08, 11.17, 11.25, 11.33, 11.42, 11.5, 11.58, 11.67, 11.75, 11.83, 11.92, 12, 12.08, 12.17, 12.25, 12.33, 12.42, 12.5, 12.58, 12.67, 12.75, 12.83, 12.92, 13, 13.08, 13.17, 13.25, 13.33, 13.42, 13.5, 13.58, 13.67, 13.75, 13.83, 13.92, 14, 14.08, 14.17, 14.25, 14.33, 14.42, 14.5, 14.58, 14.67, 14.75, 14.83, 14.92, 15, 15.08, 15.17, 15.25, 15.33, 15.42, 15.5, 15.58, 15.67, 15.75, 15.83, 15.92, 16, 16.08, 16.17, 16.25, 16.33, 16.42, 16.5, 16.58, 16.67, 16.75, 16.83, 16.92, 17, 17.08, 17.17, 17.25, 17.33, 17.42, 17.5, 17.58, 17.67, 17.75, 17.83, 17.92, 18, 18.08, 18.17, 18.25, 18.33, 18.42, 18.5, 18.58, 18.67, 18.75, 18.83, 18.92, 19, 19.08, 19.17, 19.25, 19.33, 19.42, 19.5, 19.58, 19.67, 19.75, 19.83, 19.92, 20] TRISOMY_21_AAP_INFANT_AGES=[0.083333333, 0.166666667, 0.25, 0.333333333, 0.416666667, 0.5, 0.583333333, 0.666666667, 0.75, 0.833333333, 0.916666667, 1, 1.083333333, 1.166666667, 1.25, 1.333333333, 1.416666667, 1.5, 1.583333333, 1.666666667, 1.75, 1.833333333, 1.916666667, 2, 2.083333333, 2.166666667, 2.25, 2.333333333, 2.416666667, 2.5, 2.583333333, 2.666666667, 2.75, 2.833333333, 2.916666667, 3] -TRISOMY_21_AAP_CHILD_AGES=[3, 3.5, 4, 4.5, 5, 5.5, 6, 6.5, 7, 7.5, 8, 8.5, 9, 9.5, 10, 10.5, 11, 11.5, 12, 12.5, 13, 13.5, 14, 14.5, 15, 15.5, 16, 16.5, 17, 17.5, 18, 18.5, 19, 19.5, 20] \ No newline at end of file +TRISOMY_21_AAP_CHILD_AGES=[3, 3.5, 4, 4.5, 5, 5.5, 6, 6.5, 7, 7.5, 8, 8.5, 9, 9.5, 10, 10.5, 11, 11.5, 12, 12.5, 13, 13.5, 14, 14.5, 15, 15.5, 16, 16.5, 17, 17.5, 18, 18.5, 19, 19.5, 20] diff --git a/rcpchgrowth/global_functions.py b/rcpchgrowth/global_functions.py index 1390676..387c1bb 100644 --- a/rcpchgrowth/global_functions.py +++ b/rcpchgrowth/global_functions.py @@ -308,7 +308,7 @@ def generate_centile( def should_default_to_youngest_reference(age: float, reference_name: str): if reference_name == UK90_PRETERM: - if age == 0.038329911: + if age == FORTY_TWO_WEEKS_GESTATION: return True if reference_name == UK_WHO_INFANT: if age == 2: @@ -783,4 +783,4 @@ def lms_value_array_for_measurement_for_reference( raise LookupError(error) else: raise ValueError("No or incorrect reference supplied") - return lms_value_array_for_measurement \ No newline at end of file + return lms_value_array_for_measurement diff --git a/rcpchgrowth/tests/test_chart_boundary_ages.py b/rcpchgrowth/tests/test_chart_boundary_ages.py new file mode 100644 index 0000000..b2cf9b0 --- /dev/null +++ b/rcpchgrowth/tests/test_chart_boundary_ages.py @@ -0,0 +1,42 @@ +"""Regression tests for valid gestational boundary points in UK-WHO charts.""" + +import pytest + +from rcpchgrowth.chart_functions import create_chart +from rcpchgrowth.constants import ( + BMI, + FORTY_TWO_WEEKS_GESTATION, + HEAD_CIRCUMFERENCE, + HEIGHT, + TWENTY_FIVE_WEEKS_GESTATION, + TWENTY_THREE_WEEKS_GESTATION, + UK90_PRETERM, + UK_WHO, + UK_WHO_INFANT, + WEIGHT, +) + + +@pytest.mark.parametrize( + ("measurement_method", "component", "expected_first_age"), + [ + (WEIGHT, UK90_PRETERM, TWENTY_THREE_WEEKS_GESTATION), + (HEAD_CIRCUMFERENCE, UK90_PRETERM, TWENTY_THREE_WEEKS_GESTATION), + (HEIGHT, UK90_PRETERM, TWENTY_FIVE_WEEKS_GESTATION), + (BMI, UK_WHO_INFANT, FORTY_TWO_WEEKS_GESTATION), + ], +) +def test_chart_includes_first_valid_gestational_boundary( + measurement_method, + component, + expected_first_age, +): + chart = create_chart( + reference=UK_WHO, + measurement_method=measurement_method, + sex="female", + ) + component_data = next(item[component] for item in chart if component in item) + first_centile = component_data["female"][measurement_method][0]["data"] + + assert first_centile[0]["x"] == round(expected_first_age, 4) From c50e4635b6a52a2260b45cb7f99dddd1fb6b012a Mon Sep 17 00:00:00 2001 From: Marcus Baw Date: Sat, 12 Sep 2026 11:15:39 +0100 Subject: [PATCH 2/6] docs: note unused WHO threshold review --- spec/roadmap.md | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/roadmap.md b/spec/roadmap.md index 8ad2781..f987b3d 100644 --- a/spec/roadmap.md +++ b/spec/roadmap.md @@ -38,6 +38,7 @@ Complete these items before broad formatting, import cleanup, packaging reductio ## Medium priority - [ ] **R25 - Derive accepted age domains from reference metadata and table extents.** Replace duplicated age-limit literals with a central domain model for every reference segment, measurement, and sex. Distinguish observed table extent from clinically supported applicability, including endpoint inclusivity and overlap precedence for hybrid references such as UK-WHO and WHO. Add build-time checks against canonical source material in `rcpch/growth-references`, prohibit extrapolation beyond selected series, and test every first/last accepted endpoint plus `math.nextafter()` immediately outside it. Track implementation in issue #109. +- [ ] **R26 - Ask whether the unused WHO 2007 lower-threshold constant can be removed.** Open a small PR for Simon to review `WHO_2007_REFERENCE_LOWER_THRESHOLD`: it has no repository consumers and its expression `(61 / 30.4375) / 365.25` evaluates to about `0.00549` years rather than the documented 61 months (`61 / 12`, about `5.08333` years). Confirm that no external consumer relies on this wildcard-exported name before removing it; do not silently correct an unused public constant and create a new behavior without an identified consumer. - [ ] **R3 - Decide the future of the unusable `BoneAge` class.** `rcpchgrowth/bone_age.py:12-48` returns a dictionary from `__init__`, so construction raises `TypeError: __init__() should return None`. The class has no internal consumers and is not exported from the package root, although related fields are supported by `Measurement`. Either implement and test a coherent object API or remove the module after checking external compatibility. - [ ] **R4 - Define an explicit runtime package-data allowlist.** The published installation occupies roughly 15 MB and ships spreadsheets, a PDF, VBA source, validation CSVs, old WHO tables, experimental LMS tables, and other provenance material because `pyproject.toml:68-69` broadly includes file extensions beneath `data_tables`. Identify the JSON and correlation resources required at runtime, package only those files, and verify wheel and sdist contents in CI. - [ ] **R5 - Exclude the test package from release wheels.** `pyproject.toml:60-62` discovers `rcpchgrowth*`, which includes 19 modules beneath `rcpchgrowth/tests` in the published wheel. Exclude `rcpchgrowth.tests` and its subpackages while retaining all tests in the source repository and sdist if deliberately required there. From 5ddd277f4706e24ff13ffff198c3fe4e262f5bb2 Mon Sep 17 00:00:00 2001 From: Marcus Baw Date: Thu, 24 Sep 2026 14:36:47 +0100 Subject: [PATCH 3/6] test: cover plotting below Turner age floor --- rcpchgrowth/tests/test_chart_boundary_ages.py | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/rcpchgrowth/tests/test_chart_boundary_ages.py b/rcpchgrowth/tests/test_chart_boundary_ages.py index 0d44f38..d35c8ee 100644 --- a/rcpchgrowth/tests/test_chart_boundary_ages.py +++ b/rcpchgrowth/tests/test_chart_boundary_ages.py @@ -19,6 +19,7 @@ UK_WHO, UK_WHO_CHILD, UK_WHO_INFANT, + TURNERS, WEIGHT, ) @@ -91,3 +92,28 @@ def test_observation_below_reference_floor_remains_plottable_without_sds(): assert point["observation_value_error"] == ( "There is no UK90 reference data below 23 weeks gestation" ) + + +def test_turner_observation_before_one_year_remains_plottable_without_sds(): + measurement = Measurement( + birth_date=date(2025, 1, 1), + observation_date=date(2025, 7, 1), + measurement_method=HEIGHT, + observation_value=60.0, + reference=TURNERS, + sex="female", + ).measurement + point = measurement["plottable_data"]["centile_data"][ + "chronological_decimal_age_data" + ] + + assert point["x"] == measurement["measurement_dates"][ + "chronological_decimal_age" + ] + assert point["x"] < 1 + assert point["y"] == 60.0 + assert point["sds"] is None + assert point["centile"] is None + assert point["observation_value_error"] == ( + "There is no reference data below 1 year." + ) From 41e3604f83a4b29d8ebcfeee78d0b3a27c6a4146 Mon Sep 17 00:00:00 2001 From: Marcus Baw Date: Thu, 24 Sep 2026 14:54:41 +0100 Subject: [PATCH 4/6] docs: roadmap UK90 and coverage follow-ups --- spec/roadmap.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spec/roadmap.md b/spec/roadmap.md index 1121b1d..997dfa3 100644 --- a/spec/roadmap.md +++ b/spec/roadmap.md @@ -39,6 +39,8 @@ Complete these items before broad formatting, import cleanup, packaging reductio - [ ] **R25 - Derive accepted age domains from reference metadata and table extents.** Replace duplicated age-limit literals with a central domain model for every reference segment, measurement, and sex. Distinguish observed table extent from clinically supported applicability, including endpoint inclusivity and overlap precedence for hybrid references such as UK-WHO and WHO. Add build-time checks against canonical source material in `rcpch/growth-references`, prohibit extrapolation beyond selected series, and test every first/last accepted endpoint plus `math.nextafter()` immediately outside it. Track implementation in issue #109. - [ ] **R26 - Ask whether the unused WHO 2007 lower-threshold constant can be removed.** Open a small PR for Simon to review `WHO_2007_REFERENCE_LOWER_THRESHOLD`: it has no repository consumers and its expression `(61 / 30.4375) / 365.25` evaluates to about `0.00549` years rather than the documented 61 months (`61 / 12`, about `5.08333` years). Confirm that no external consumer relies on this wildcard-exported name before removing it; do not silently correct an unused public constant and create a new behavior without an identified consumer. +- [ ] **R27 - Assess daily UK90 LMS references. (GitHub #79)** Determine whether an authoritative, redistributable daily UK90 LMS source exists for the currently supported age and measurement domains. Document provenance and validation requirements before deciding whether to generate daily tables; preserve existing reference outputs until independently validated. +- [ ] **R28 - Add test-coverage reporting. (GitHub #128)** Decide whether CI should publish coverage, enforce a threshold, or both. Start with a report-only baseline and avoid a blocking threshold until maintainers agree that the metric is meaningful for this suite. - [ ] **R3 - Decide the future of the unusable `BoneAge` class.** `rcpchgrowth/bone_age.py:12-48` returns a dictionary from `__init__`, so construction raises `TypeError: __init__() should return None`. The class has no internal consumers and is not exported from the package root, although related fields are supported by `Measurement`. Either implement and test a coherent object API or remove the module after checking external compatibility. - [x] **R4 - Define an explicit runtime package-data allowlist.** Packaging now includes only the 15 JSON resources traced to production loads, and the artifact checkers reject every unapproved package resource. - [x] **R5 - Exclude the test package from release wheels.** Package discovery excludes `rcpchgrowth.tests` and its subpackages, and the wheel checker rejects packaged test modules. From 88f486a6f401807b1424ef713306668807902b34 Mon Sep 17 00:00:00 2001 From: Marcus Baw Date: Thu, 24 Sep 2026 15:00:56 +0100 Subject: [PATCH 5/6] docs: roadmap measurement response review --- spec/roadmap.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/roadmap.md b/spec/roadmap.md index 997dfa3..19d140a 100644 --- a/spec/roadmap.md +++ b/spec/roadmap.md @@ -31,7 +31,7 @@ Complete these items before broad formatting, import cleanup, packaging reductio ## High priority -- [ ] **R1 - Resolve the broken public `create_thrive_lines` API.** `rcpchgrowth/dynamic_growth.py:226-294` uses undefined `plt`, has its output-producing plotting code commented out, and returns nothing, while `rcpchgrowth/__init__.py:8` exports it publicly. Decide whether plotting remains supported; either restore it with an optional matplotlib dependency and tests, or remove the export through an explicitly managed breaking change. +- [ ] **R1 - Resolve the broken public `create_thrive_lines` API. (GitHub #21)** `rcpchgrowth/dynamic_growth.py:226-294` uses undefined `plt`, has its output-producing plotting code commented out, and returns nothing, while `rcpchgrowth/__init__.py:8` exports it publicly. Decide whether plotting remains supported; either restore it with an optional matplotlib dependency and tests, or remove the export through an explicitly managed breaking change. - [x] **R2 - Restore executable notebooks and expose package version metadata consistently.** The package root and measurement provenance now share `rcpchgrowth.__version__`, all four notebooks execute from fresh kernels, and Python 3.13 CI executes them headlessly. - [x] **R24 - Automate the post-merge release cascade.** A same-repository `release/vX.Y.Z` PR merged into `live` with a merge commit is validated against its exact files, parent commits, supported bump, and synchronized metadata before CI creates or reuses the annotated tag and GitHub Release. The cascade calls the least-privilege reusable package workflow for the Python 3.10-3.13 gate and one exact commit-stamped artifact build, then publishes those verified artifacts from the top-level workflow identity supported by PyPI Trusted Publishing. `workflow_dispatch` accepts a merged release PR number for a non-publishing validation/build dry run or explicit recovery of a failed PyPI publication. @@ -41,6 +41,7 @@ Complete these items before broad formatting, import cleanup, packaging reductio - [ ] **R26 - Ask whether the unused WHO 2007 lower-threshold constant can be removed.** Open a small PR for Simon to review `WHO_2007_REFERENCE_LOWER_THRESHOLD`: it has no repository consumers and its expression `(61 / 30.4375) / 365.25` evaluates to about `0.00549` years rather than the documented 61 months (`61 / 12`, about `5.08333` years). Confirm that no external consumer relies on this wildcard-exported name before removing it; do not silently correct an unused public constant and create a new behavior without an identified consumer. - [ ] **R27 - Assess daily UK90 LMS references. (GitHub #79)** Determine whether an authoritative, redistributable daily UK90 LMS source exists for the currently supported age and measurement domains. Document provenance and validation requirements before deciding whether to generate daily tables; preserve existing reference outputs until independently validated. - [ ] **R28 - Add test-coverage reporting. (GitHub #128)** Decide whether CI should publish coverage, enforce a threshold, or both. Start with a report-only baseline and avoid a blocking threshold until maintainers agree that the metric is meaningful for this suite. +- [ ] **R29 - Review the `Measurement.plottable_data` response shape for a future major version. (GitHub #24)** Keep the current public shape until the Python API, downstream server, and chart clients have an agreed migration plan. If simplifying the response, characterize compatibility and remove the redundant nested field only in a coordinated major-version change. - [ ] **R3 - Decide the future of the unusable `BoneAge` class.** `rcpchgrowth/bone_age.py:12-48` returns a dictionary from `__init__`, so construction raises `TypeError: __init__() should return None`. The class has no internal consumers and is not exported from the package root, although related fields are supported by `Measurement`. Either implement and test a coherent object API or remove the module after checking external compatibility. - [x] **R4 - Define an explicit runtime package-data allowlist.** Packaging now includes only the 15 JSON resources traced to production loads, and the artifact checkers reject every unapproved package resource. - [x] **R5 - Exclude the test package from release wheels.** Package discovery excludes `rcpchgrowth.tests` and its subpackages, and the wheel checker rejects packaged test modules. From 58f0a3abf93c0f291970aa2220632563a5e61fbf Mon Sep 17 00:00:00 2001 From: Marcus Baw Date: Thu, 24 Sep 2026 15:08:42 +0100 Subject: [PATCH 6/6] docs: route UK90 daily LMS work to references repo --- spec/roadmap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/roadmap.md b/spec/roadmap.md index 19d140a..2132e84 100644 --- a/spec/roadmap.md +++ b/spec/roadmap.md @@ -39,7 +39,7 @@ Complete these items before broad formatting, import cleanup, packaging reductio - [ ] **R25 - Derive accepted age domains from reference metadata and table extents.** Replace duplicated age-limit literals with a central domain model for every reference segment, measurement, and sex. Distinguish observed table extent from clinically supported applicability, including endpoint inclusivity and overlap precedence for hybrid references such as UK-WHO and WHO. Add build-time checks against canonical source material in `rcpch/growth-references`, prohibit extrapolation beyond selected series, and test every first/last accepted endpoint plus `math.nextafter()` immediately outside it. Track implementation in issue #109. - [ ] **R26 - Ask whether the unused WHO 2007 lower-threshold constant can be removed.** Open a small PR for Simon to review `WHO_2007_REFERENCE_LOWER_THRESHOLD`: it has no repository consumers and its expression `(61 / 30.4375) / 365.25` evaluates to about `0.00549` years rather than the documented 61 months (`61 / 12`, about `5.08333` years). Confirm that no external consumer relies on this wildcard-exported name before removing it; do not silently correct an unused public constant and create a new behavior without an identified consumer. -- [ ] **R27 - Assess daily UK90 LMS references. (GitHub #79)** Determine whether an authoritative, redistributable daily UK90 LMS source exists for the currently supported age and measurement domains. Document provenance and validation requirements before deciding whether to generate daily tables; preserve existing reference outputs until independently validated. +- [x] **R27 - Route daily UK90 LMS generation to the reference-data project. (GitHub #79)** Daily table generation, source provenance, and validation belong in `rcpch/growth-references`; this Python package should consume an approved generated table. Issue #79 was closed with this decision. - [ ] **R28 - Add test-coverage reporting. (GitHub #128)** Decide whether CI should publish coverage, enforce a threshold, or both. Start with a report-only baseline and avoid a blocking threshold until maintainers agree that the metric is meaningful for this suite. - [ ] **R29 - Review the `Measurement.plottable_data` response shape for a future major version. (GitHub #24)** Keep the current public shape until the Python API, downstream server, and chart clients have an agreed migration plan. If simplifying the response, characterize compatibility and remove the redundant nested field only in a coordinated major-version change. - [ ] **R3 - Decide the future of the unusable `BoneAge` class.** `rcpchgrowth/bone_age.py:12-48` returns a dictionary from `__init__`, so construction raises `TypeError: __init__() should return None`. The class has no internal consumers and is not exported from the package root, although related fields are supported by `Measurement`. Either implement and test a coherent object API or remove the module after checking external compatibility.