Skip to content

Reference ranges#3567

Closed
gigincg wants to merge 2 commits intodevelopfrom
reference_ranges
Closed

Reference ranges#3567
gigincg wants to merge 2 commits intodevelopfrom
reference_ranges

Conversation

@gigincg
Copy link
Member

@gigincg gigincg commented Mar 9, 2026

  • Brief of changes made.

refactors how reference ranges and interpretations are assigned in observation evaluation logic, aiming for more consistent and reliable handling of these values

Associated Issue

Merge Checklist

  • Tests added/fixed
  • Update docs in /docs
  • Linting Complete
  • Any other necessary step

Only PR's with test cases included and passing lint and test pipelines will be reviewed

@ohcnetwork/care-backend-maintainers @ohcnetwork/care-backend-admins

Summary by CodeRabbit

  • Bug Fixes
    • Improved consistency in how medical observation reference ranges and interpretations are processed, ensuring reference ranges are always properly populated regardless of interpretation status.

@gigincg gigincg requested a review from a team as a code owner March 9, 2026 14:03
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 9, 2026

📝 Walkthrough

Walkthrough

Refactors observation reference range assignment to execute unconditionally before interpretation evaluation, and restructures the interpretation evaluator to use forward-chained Valueset checks instead of nested conditional branching logic.

Changes

Cohort / File(s) Summary
Reference Range Assignment
care/emr/utils/compute_observation_interpretation.py
Unconditionally assigns model_instance.reference_range and component["reference_range"] after evaluation, removing conditional logic that previously wrote these fields only within interpretation branches.
Interpretation Evaluation Flow
care/utils/evaluators/interpretation_evaluator.py
Restructures control flow to sequentially evaluate ranges, then explicitly check coded value sets (normal_coded_value_set, critical_coded_value_set, abnormal_coded_value_set), followed by valueset iteration. Now returns (None, ranges) when rules match but yield no interpretation, preserving discovered ranges.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is incomplete, with placeholder text ('Brief of changes made.') and missing detailed explanation of the refactoring work despite having the template structure. Replace placeholder text with concrete details about the refactoring changes, explain the motivation behind them, and clarify how the associated issue is resolved.
Title check ❓ Inconclusive The title 'Reference ranges' is vague and overly generic, failing to convey the specific nature of the refactoring work described in the PR. Consider a more descriptive title like 'Refactor reference range assignment in observation evaluation' to better communicate the core changes.
✅ Passed checks (1 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch reference_ranges

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
care/emr/utils/compute_observation_interpretation.py (1)

51-52: The exception handling here doesn't add anything, just so you know.

Catching an exception only to immediately re-raise it without any modification, logging, or cleanup is effectively a no-op. It makes the code slightly harder to read without providing any benefit.

♻️ Proposed simplification
-    except Exception as e:
-        raise e
+    except Exception:
+        raise

Or, if no special handling is needed, consider removing the try/except entirely and letting exceptions propagate naturally.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@care/emr/utils/compute_observation_interpretation.py` around lines 51 - 52,
No-op exception re-raise: the "except Exception as e: raise e" adds no value and
should be removed. Edit the try/except block in
compute_observation_interpretation.py (inside the
compute_observation_interpretation function or the surrounding helper where this
snippet appears) and either delete the except clause so the exception propagates
naturally, or replace it with meaningful handling (e.g.,
processLogger.error(...) and re-raise) if you intend to log/contextualize
errors.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@care/utils/evaluators/interpretation_evaluator.py`:
- Around line 63-65: The check assumes value is a dict and does "if 'coding' not
in value" which can raise TypeError for non-dict values; update the
Valueset-based interpretation branch (the block under the comment "Handle
Valueset based interpretation" that inspects variable value) to first verify
isinstance(value, dict) and raise a clear ValueError if it's not a dict, then
check for the 'coding' key and raise a distinct, descriptive ValueError if
missing (use a full sentence message rather than an inline snippet to satisfy
the TRY003 style flag).

---

Nitpick comments:
In `@care/emr/utils/compute_observation_interpretation.py`:
- Around line 51-52: No-op exception re-raise: the "except Exception as e: raise
e" adds no value and should be removed. Edit the try/except block in
compute_observation_interpretation.py (inside the
compute_observation_interpretation function or the surrounding helper where this
snippet appears) and either delete the except clause so the exception propagates
naturally, or replace it with meaningful handling (e.g.,
processLogger.error(...) and re-raise) if you intend to log/contextualize
errors.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 3635ab79-77b0-447e-8d3a-337ccfb6b875

📥 Commits

Reviewing files that changed from the base of the PR and between 924ca74 and c762557.

📒 Files selected for processing (2)
  • care/emr/utils/compute_observation_interpretation.py
  • care/utils/evaluators/interpretation_evaluator.py

Comment on lines +63 to +65
# Handle Valueset based interpretation
if "coding" not in value:
raise ValueError("Coding not found")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Consider a more defensive check before accessing value.

If value is not a dict (e.g., an unexpected primitive type that didn't match any range conditions), the "coding" not in value check on line 64 could raise a TypeError. While this path should only be reached for coded values, a defensive type check would be safer.

Additionally, the static analysis tool flags the inline message as a minor style issue (TRY003).

🛡️ Proposed defensive fix
         # Handle Valueset based interpretation
+        if not isinstance(value, dict) or "coding" not in value:
+            raise ValueError("Coding not found")
-        if "coding" not in value:
-            raise ValueError("Coding not found")
🧰 Tools
🪛 Ruff (0.15.4)

[warning] 65-65: Avoid specifying long messages outside the exception class

(TRY003)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@care/utils/evaluators/interpretation_evaluator.py` around lines 63 - 65, The
check assumes value is a dict and does "if 'coding' not in value" which can
raise TypeError for non-dict values; update the Valueset-based interpretation
branch (the block under the comment "Handle Valueset based interpretation" that
inspects variable value) to first verify isinstance(value, dict) and raise a
clear ValueError if it's not a dict, then check for the 'coding' key and raise a
distinct, descriptive ValueError if missing (use a full sentence message rather
than an inline snippet to satisfy the TRY003 style flag).

@codecov
Copy link

codecov bot commented Mar 9, 2026

Codecov Report

❌ Patch coverage is 0% with 24 lines in your changes missing coverage. Please review.
✅ Project coverage is 76.22%. Comparing base (924ca74) to head (c762557).
⚠️ Report is 7 commits behind head on develop.

Files with missing lines Patch % Lines
care/utils/evaluators/interpretation_evaluator.py 0.00% 22 Missing ⚠️
...re/emr/utils/compute_observation_interpretation.py 0.00% 2 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff            @@
##           develop    #3567   +/-   ##
========================================
  Coverage    76.22%   76.22%           
========================================
  Files          474      474           
  Lines        22270    22270           
  Branches      2325     2325           
========================================
  Hits         16976    16976           
  Misses        4765     4765           
  Partials       529      529           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants