Skip to content

Prior transformation with jacobian#1495

Draft
Andrea-Havron-NOAA wants to merge 4 commits into
mainfrom
prior-transformation-with-jacobian
Draft

Prior transformation with jacobian#1495
Andrea-Havron-NOAA wants to merge 4 commits into
mainfrom
prior-transformation-with-jacobian

Conversation

@Andrea-Havron-NOAA

@Andrea-Havron-NOAA Andrea-Havron-NOAA commented May 30, 2026

Copy link
Copy Markdown
Collaborator

What is the feature?

How have you implemented the solution?

  • Sets up an interface that allows users to input priors using a formula interface
  • Stores input and prior transformation metadata in a modified variable_map struct
  • Adds new functions in the interface to parse the formula and pass prior and transformation information to the backend
  • Adds new functions in a fims_transformation.hpp files that applies transformations and evaluates the Jacobian adjustment
  • Adds a Prepare function to distribution_base to evaluate the prior transformation
  • Add code to model.hpp to apply the Jacobian adjustment when the do_mcmc flag is true

Does the PR impact any other area of the project, maybe another repo?

  • restructures variable_map which affects the Rcpp interface

Instructions for code reviewer

👋Hello reviewer👋, thank you for taking the time to review this PR!

  • Please use this checklist during your review, checking off items that you have verified are complete but feel free to skip over items that are not relevant!
  • See the GitHub documentation for how to comment on a PR to indicate where you have questions or changes are needed before approving the PR.
  • Please use standard conventional messages for both commit messages and comments
  • PR reviews are a great way to learn so feel free to share your tips and tricks. However, when suggesting changes to the PR that are optional please include nit: (for nitpicking) as the comment type. For example, nit: I prefer using a data.frame() instead of a matrix because ...
  • Engage with the developer. Make it clear when the PR is approved by selecting the approved status, and potentially commenting on the PR with something like This PR is now ready to be merged.

Checklist

  • The PR requests the appropriate base branch (dev for features and main for hot fixes)
  • The code is well-designed
  • The code is designed well for both users and developers
  • Code coverage remains high- [ ] Comments are clear, useful, and explain why instead of what
  • Code is appropriately documented (doxygen and roxygen)

Andrea-Havron-NOAA and others added 3 commits May 29, 2026 16:32
C++ changes
- create transformation enum struct and distribution enum struct in common/types.hpp
- create common/fims_transformations.hpp with transformation functions
    - ApplyTransformation, ApplyBackTransformation, TransformPrior, AddLogJacobian
- restructure variable_map to hold transformation metadata for parameters
- add AddLogJacobian call to model.hpp and create do_mcmc flag
- add Prepare function to distributions_base to calculate prior transform for each iteration

Interface Changes
- add new functions: add_prior to ParameterVector and add_shared_prior to rcpp_interface.hpp
- add code to parse R formula and pass transformation information and prior informationinto the backend
- add set_variable_map function to pass values and transformation metadata from Rcpp to C++
- modify calls to variable_map and set input transformations if parameters are not logged

Tests
- add C++ tests for fims_transformation.hpp
- update R tests and vignettes

cleanup code
- remove min/max field and functions
- remove changes that were pulled over from surplus production
@codecov

codecov Bot commented May 30, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.67925% with 30 lines in your changes missing coverage. Please review.
✅ Project coverage is 83.68%. Comparing base (c57cf29) to head (fcdc1e2).

Files with missing lines Patch % Lines
inst/include/common/types.hpp 18.18% 18 Missing ⚠️
...distributions/functors/density_components_base.hpp 47.05% 5 Missing and 4 partials ⚠️
inst/include/common/fims_transformations.hpp 96.66% 0 Missing and 2 partials ⚠️
...gtest/test_fims_transformations_TransformPrior.cpp 98.36% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1495      +/-   ##
==========================================
+ Coverage   82.97%   83.68%   +0.71%     
==========================================
  Files          54       58       +4     
  Lines        2214     2464     +250     
  Branches      579      614      +35     
==========================================
+ Hits         1837     2062     +225     
- Misses        279      340      +61     
+ Partials       98       62      -36     

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

@Andrea-Havron-NOAA

Copy link
Copy Markdown
Collaborator Author

See #431 for remaining tasks on draft PR

* - `exp`: Exponential transformation, parameter is on the log scale.
* - `log`: Log transformation, parameter is on the natural scale.
* - `logit`: Logit transformation with optional bounds.
* - `square`: Square transformation.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We could replace the square and sqrt transform options with a power option that takes an input value for the power square=2, sqrt=1/2 and this is then extendable to other powers.

* | log | log(x) |
* | exp | exp(x) |
* | logit | logit(x, lo, hi) |
* | square | x^2 |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

| power | power(x, power_value) |

* specified by the transformation argument. The forward transformations
* and are:
*
* | Label | Forward |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I use x in the comment below for consistency with the other functions but we shouldn't use 'x' or any other similarly small variable names in the codebase as it makes interpretation and future refactors really difficult. Particularly with something like x being used to mean different things throughout the codebase.

* @param prior The transformation applied to the parameter in prior space
* (e.g. square if the prior is on variance = sd^2).
* @return A vector of parameter values transformed to prior space.
*/

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This could be extended to be more generalized and save compute time if it stores the input, natural, and prior transformed values somewhere for when they are needed throughout the code rather than calculating every time.

* (e.g. square if the prior is on variance = sd^2).
* @return A vector of parameter values transformed to prior space.
*/
template <typename Type>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It would also make sense to extend this to simply a likelihood transformation rather than just limiting it to priors. For that we would need to tie the transformed values to the likelihood component of interest.

@@ -139,10 +139,54 @@ class Information {
uint32_t, std::shared_ptr<fims_popdy::FisheryModelBase<Type>>>::iterator
model_map_iterator; /**< iterator for variable map>*/

@nathanvaughan-NOAA nathanvaughan-NOAA Jun 8, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

To extend this to all likelihood components we would have to have one map linked to the input variables like this that holds the input transformation type and the input and natural values. It could also be helpful here to have a reporting transformation and value specified so that use gets things out in the desired way.

We would then need a second map linked to the likelihood components that specifies the transformation type and transformed values needed for each likelihood component. This allows parameters to have multiple transformations such as one for a prior and one for fit to observed data.

This approach would replace the manual log and natural parameters we currently specify manually in FIMS like log_F_mort and F_mort we would just specify which transformation is used in a specific internal calculation.

return "unknown";
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This section on the distribution functions doesn't seem to fit with the rest of the refactor.

@nathanvaughan-NOAA nathanvaughan-NOAA left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Some initial comments. Don't need to address this stuff for this pull request but thoughts for how to improve on this in the future.

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.

[Feature]: Parameter prior specification

3 participants