Thank you for your interest in contributing to composableIDModelR! This document provides guidelines for contributing to the project.
Code of Conduct
By participating in this project, you agree to maintain a respectful and inclusive environment for all contributors.
Types of Contributions
Bug Reports
If you find a bug, please open an issue with:
- A clear, descriptive title
- A minimal reproducible example
- Your R and Julia versions (
sessionInfo() output)
- Expected vs. actual behavior
Feature Requests
We welcome suggestions for new features! Please:
- Check if the feature already exists in ComposableTuringIDModels.jl
- Describe the use case and expected behavior
- Consider whether it should be a dedicated R wrapper or reached via
component() or julia()
Code Contributions
-
Fork and clone the repository
-
Create a branch for your changes:
git checkout -b feature/my-feature
-
Make your changes following the code style below
-
Add tests for any new functionality
-
Update documentation including roxygen2 comments
-
Run checks:
devtools::check()
-
Submit a pull request with a clear description
Development Setup
Prerequisites
- R >= 4.0.0
- Julia >= 1.9.0
- Development tools:
-
devtools: install.packages("devtools")
-
roxygen2: install.packages("roxygen2")
-
testthat: install.packages("testthat")
Setup
# Clone the repository
git clone https://github.com/CDCgov/Rt-without-renewal.git
cd Rt-without-renewal/composableIDModelR
# Load package for development
devtools::load_all()
# Set up Julia
cidm_setup_julia()
Code Style
R Code Style
Follow standard R conventions:
-
Function names:
snake_case for user-facing functions
-
Internal functions: Prefix with
. (e.g., .internal_helper)
-
Variable names:
snake_case
-
Constants:
SCREAMING_SNAKE_CASE
-
Line length: Maximum 80 characters when practical
-
Indentation: 2 spaces (no tabs)
Documentation
All exported functions must have roxygen2 documentation:
#' Brief Title
#'
#' Detailed description of what the function does.
#'
#' @param param1 Description of param1
#' @param param2 Description of param2
#'
#' @return Description of return value
#'
#' @examples
#' \dontrun{
#' # Example usage
#' result <- my_function(param1 = 1, param2 = 2)
#' }
#'
#' @export
my_function <- function(param1, param2) {
# Implementation
}
S3 Classes
composableIDModelR uses S3 classes for simplicity:
-
Constructor pattern: Validate inputs, call Julia, return structured list with
julia_ref
-
Class inheritance: Use multiple inheritance (e.g.,
c("cidm_ar", "cidm_latent", "cidm_model"))
-
Print methods: Always provide informative
print() methods
Testing
Writing Tests
- Place tests in
tests/testthat/test-*.R
- Use descriptive test names:
test_that("function validates inputs", { ... })
- Test edge cases and error conditions
- Skip long-running tests with
skip_on_cran()
- Skip tests requiring Julia with
skip_if_not(cidm_available())
Running Tests
# Run all tests
devtools::test()
# Run specific test file
testthat::test_file("tests/testthat/test-components.R")
# Check package
devtools::check()
Adding New Components
Adding a New Wrapped Component
-
Create constructor function in appropriate file (e.g.,
R/latent-models.R)
-
Validate inputs in R
-
Convert distributions using
.to_julia_dist()
-
Call Julia constructor using
.call_julia_function()
-
Return S3 object with proper class inheritance
- Add print method
-
Write tests in
tests/testthat/
-
Update documentation in README and vignettes
-
Add examples to function documentation
Example structure:
#' My New Model
#'
#' @param param1 Description
#' @export
MyNewModel <- function(param1) {
# Validate
if (!is.numeric(param1)) stop("param1 must be numeric")
# Convert to Julia
julia_obj <- .call_julia_function("MyNewModel", param1 = param1)
# Return S3 object
structure(
list(julia_ref = julia_obj, spec = list(param1 = param1)),
class = c("cidm_mynew", "cidm_latent", "cidm_model")
)
}
#' @export
print.cidm_mynew <- function(x, ...) {
cat("<My New Model>\n")
cat(" Param1:", x$spec$param1, "\n")
invisible(x)
}
Adding Access to Julia Features
For features not yet wrapped, users can use cidm_call():
custom_model <- cidm_call("JuliaFunction", param1 = value1)
Document these in the function reference with guidance on when explicit wrappers are warranted.
Documentation
Regenerating Documentation
# Update roxygen documentation
devtools::document()
# Build vignettes
devtools::build_vignettes()
Building README
If README.Rmd exists:
# Knit README
knitr::knit("README.Rmd")
Release Process
- Update version in
DESCRIPTION
- Update
NEWS.md with changes
- Run
devtools::check() with no errors, warnings, or notes
- Build and check package:
devtools::check()
- Submit to CRAN or create GitHub release
Questions?
If you have questions about contributing:
License
By contributing, you agree that your contributions will be licensed under the MIT License.