Skip to content

Conversation

@cdc-mitzimorris
Copy link
Collaborator

This PR adds work that was done in https://github.com/cdcent/cfa-pyrenew-hierarchical/pull/4 to PyRenew.

It adds the base observation process class, concrete implementations for Count processes and the abstract base class for Measurement processes, together with unit tests and two new tutorials for count and measurement observation processes respectively.

Once this PR and the work done in https://github.com/cdcent/cfa-pyrenew-hierarchical/pull/5 have been added to PyRenew, subsequent PRs will deprecate unused features and harmonize the documentation and tutorials.

@codecov
Copy link

codecov bot commented Dec 23, 2025

Codecov Report

❌ Patch coverage is 98.40426% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 97.26%. Comparing base (02446c5) to head (f932712).
⚠️ Report is 3 commits behind head on main.

Files with missing lines Patch % Lines
pyrenew/observation/count_observations.py 96.66% 2 Missing ⚠️
pyrenew/observation/noise.py 98.38% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #644      +/-   ##
==========================================
+ Coverage   96.98%   97.26%   +0.28%     
==========================================
  Files          42       47       +5     
  Lines        1094     1282     +188     
==========================================
+ Hits         1061     1247     +186     
- Misses         33       35       +2     
Flag Coverage Δ
unittests 97.26% <98.40%> (+0.28%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ 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.

@github-actions
Copy link

github-actions bot commented Dec 23, 2025

Thank you for your contribution @cdc-mitzimorris 🚀! Your github-pages is ready for download 👉 here 👈!
(The artifact expires on 2026-02-02T15:33:42Z. You can re-generate it by re-running the workflow here.)

@cdc-mitzimorris
Copy link
Collaborator Author

In preparing to add the model_builder class for component composition, it became clear that the noise model shouldn't manage the plates directly - this is the responsibility of the RV.
The utility class VectorizedRV wraps simple distributions in a plate, while hierarchical priors (e.g., HierarchicalNormalPrior) use internal plates with partial pooling. The noise model works with either because it only depends on the interface, not the implementation.
Updated file observation/noise.py and the corresponding notebook.

expected_counts_safe = jnp.nan_to_num(expected_counts, nan=0.0)
predicted_counts = self._predicted_obs(infections)
self._deterministic("predicted_counts", predicted_counts)
predicted_counts_safe = jnp.nan_to_num(predicted_counts, nan=0.0)
Copy link
Collaborator

Choose a reason for hiding this comment

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

^ This feels dangerous to do automatically and without warning. I think I would rather force the user to do it themself in _predicted_obs, where appropriate. Is there a good reason not to?

Copy link
Collaborator

Choose a reason for hiding this comment

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

@cdc-mitzimorris flagging this

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The nan_to_num is applied to predicted_counts from the latent infection process, not to user-provided observations. The NaN values are a structural artifact of the convolution burn-in (first len(delay_pmf)-1 days).
cf

Notes
-----
Output preserves input timeline. First len(delay_pmf)-1 days return
-1 or ~0 (depending on noise model) due to NaN padding.

The nan_to_num is a pragmatic choice: the model doesn't crash, and the behavior is noted in the docstring. It's not a safeguard against misuse — it's just handling a structural artifact so the code runs.

Copy link
Collaborator

@dylanhmorris dylanhmorris left a comment

Choose a reason for hiding this comment

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

Thanks @cdc-mitzimorris! A few things to address and then I can re-review.

@cdc-mitzimorris
Copy link
Collaborator Author

@dylanhmorris - ready for re-review - made all suggested changes to the tutorials and added arg "name" to observation processes so that user specifies the signal name.

Copy link
Collaborator

@dylanhmorris dylanhmorris left a comment

Choose a reason for hiding this comment

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

Thanks @cdc-mitzimorris! Just a couple remaining questions.

@cdc-mitzimorris
Copy link
Collaborator Author

changes made.

@cdc-mitzimorris
Copy link
Collaborator Author

@dylanhmorris - conversation resolved.

Copy link
Collaborator

@dylanhmorris dylanhmorris left a comment

Choose a reason for hiding this comment

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

Still need the separate noise module.

Copy link
Collaborator

Choose a reason for hiding this comment

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

@cdc-mitzimorris this still needs to be implemented.

Comment on lines +155 to +156
Output preserves input timeline. First len(delay_pmf)-1 days return
-1 or ~0 (depending on noise model) due to NaN padding.
Copy link
Collaborator

Choose a reason for hiding this comment

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

What is meant by ~0? and why does the padding change depending on the noise model?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think we should discuss this f2f in our upcoming meeting.

Comment on lines +198 to +199
times : ArrayLike | None
Day indices for sparse observations. None for dense observations.
Copy link
Collaborator

Choose a reason for hiding this comment

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

index relative to what vector?

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.

4 participants