-
Notifications
You must be signed in to change notification settings - Fork 38
Add two-hill activation function and refactor chamber elastance models with proper separation of concerns #213
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from 7 commits
Commits
Show all changes
23 commits
Select commit
Hold shift + click to select a range
b38a150
Initial plan
Copilot 7bf169e
Add ActivationFunction class and rename PiecewiseCosineChamber to Lin…
Copilot 980cec7
Refactor ChamberElastanceInductor and LinearElastanceChamber to use A…
Copilot 2f7c593
Add test cases for two hill activation function
Copilot 88e0ad1
Address code review comments: improve readability and documentation
Copilot 0b2ecf0
Add documentation for activation functions
Copilot b68ffd5
Support string activation_function_type and nested activation_functio…
Copilot 2a7a9d2
Refactor initialize_activation_function to use factory method in Acti…
Copilot 6c18357
Make activation function parameters members of ActivationFunction ins…
Copilot fbc1dc8
Store cardiac_period as member of ActivationFunction base class
Copilot 0f53d8c
Make PiecewiseCosineChamber an alias to LinearElastanceChamber for ba…
Copilot 7038e2d
Remove backward compatibility code and require activation_type parameter
Copilot aa4787d
Remove activation function parameters from LinearElastanceChamber and…
Copilot 5d80d12
Remove PiecewiseCosineChamber from factory registration and type checks
Copilot 8031791
Remove PiecewiseCosineChamber completely - no longer needed with acti…
Copilot 0ce3c32
Improve error reporting to list all missing parameters at once
Copilot 3c41770
Fix BlockType enum values to be sequential (piecewise_valve = 17, lin…
Copilot 6d09f57
Fix compilation error: use vector size check instead of non-existent …
Copilot b0aa76c
Make activation_type a required parameter for ChamberElastanceInductor
Copilot 0a9dc48
Remove backward compatibility for numeric activation_type parameter -…
Copilot fe33a80
Update chamber_elastance_inductor test case with activation function
aabrown100-git ffddd68
Update documentation to reflect mandatory string-based activation_fun…
Copilot 28d2faa
Add comprehensive validation for activation_function_type and activat…
Copilot File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| . |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,203 @@ | ||
| # Activation Functions for Chamber Models | ||
|
|
||
| ## Overview | ||
|
|
||
| Chamber models in svZeroDSolver support different activation functions to model the time-varying elastance of cardiac chambers. The activation function determines how the chamber contracts and relaxes over the cardiac cycle. | ||
|
|
||
| ## Available Activation Functions | ||
|
|
||
| ### 1. Half Cosine Activation (Type 0) | ||
|
|
||
| The default activation function for `ChamberElastanceInductor`. It uses a half cosine wave to model contraction: | ||
|
|
||
| ``` | ||
| A(t) = -0.5 * cos(2π * t_contract / t_twitch) + 0.5 if t_contract ≤ t_twitch | ||
| A(t) = 0 otherwise | ||
| ``` | ||
|
|
||
| where `t_contract = max(0, t - t_active)` | ||
|
|
||
| **Parameters:** | ||
| - `t_active`: Time when activation begins within the cardiac cycle | ||
| - `t_twitch`: Duration of the contraction twitch | ||
|
|
||
| **Example usage in JSON:** | ||
| ```json | ||
| { | ||
| "type": "ChamberElastanceInductor", | ||
| "name": "ventricle", | ||
| "values": { | ||
| "Emax": 1.057, | ||
| "Emin": 0.091, | ||
| "Vrd": 26.1, | ||
| "Vrs": 18.0, | ||
| "t_active": 0.2, | ||
| "t_twitch": 0.3, | ||
| "Impedance": 0.000351787 | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| Or with explicit activation function specification: | ||
| ```json | ||
| { | ||
| "type": "ChamberElastanceInductor", | ||
| "name": "ventricle", | ||
| "values": { | ||
| "Emax": 1.057, | ||
| "Emin": 0.091, | ||
| "Vrd": 26.1, | ||
| "Vrs": 18.0, | ||
| "Impedance": 0.000351787, | ||
| "activation_function_type": "half_cosine", | ||
| "activation_function_values": { | ||
| "t_active": 0.2, | ||
| "t_twitch": 0.3 | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ### 2. Piecewise Cosine Activation (Type 1) | ||
|
|
||
| The default activation function for `LinearElastanceChamber` (formerly `PiecewiseCosineChamber`). It models separate contraction and relaxation phases: | ||
|
|
||
| ``` | ||
| φ(t) = 0.5 * [1 - cos(π * (t - t_C) / T_C)] during contraction | ||
| φ(t) = 0.5 * [1 + cos(π * (t - t_R) / T_R)] during relaxation | ||
| φ(t) = 0 otherwise | ||
| ``` | ||
|
|
||
| **Parameters:** | ||
| - `contract_start`: Time when contraction starts | ||
| - `relax_start`: Time when relaxation starts | ||
| - `contract_duration`: Duration of contraction phase | ||
| - `relax_duration`: Duration of relaxation phase | ||
|
|
||
| **Example usage in JSON:** | ||
| ```json | ||
| { | ||
| "type": "LinearElastanceChamber", | ||
| "name": "left_atrium", | ||
| "values": { | ||
| "Emax": 199.95, | ||
| "Epass": 260.59, | ||
| "Vrest": 26.24, | ||
| "activation_function_type": "piecewise_cosine", | ||
| "activation_function_values": { | ||
| "contract_start": 0.025, | ||
| "relax_start": 0.08625, | ||
| "contract_duration": 0.06125, | ||
| "relax_duration": 0.18375 | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ### 3. Two Hill Activation (Type 2) | ||
|
|
||
| A more flexible and physiologically realistic activation function based on the two-hill model. This allows for more precise control over the activation waveform shape. | ||
|
|
||
| The activation is computed as: | ||
| ``` | ||
| A(t) = C * [g₁(t) / (1 + g₁(t))] * [1 / (1 + g₂(t))] | ||
| ``` | ||
|
|
||
| where: | ||
| ``` | ||
| g₁(t) = (t_shifted / τ₁)^m₁ | ||
| g₂(t) = (t_shifted / τ₂)^m₂ | ||
| t_shifted = (t - t_shift) mod T_cardiac | ||
| ``` | ||
|
|
||
| C is a normalization constant ensuring maximum activation is 1. | ||
|
|
||
| **Parameters:** | ||
| - `t_shift`: Time shift parameter to align activation with cardiac cycle | ||
| - `tau_1`: Time constant for first hill (controls rise) | ||
| - `tau_2`: Time constant for second hill (controls fall) | ||
| - `m1`: Exponent for first hill (controls steepness of rise) | ||
| - `m2`: Exponent for second hill (controls steepness of fall) | ||
|
|
||
| **Example usage in JSON:** | ||
| ```json | ||
| { | ||
| "type": "ChamberElastanceInductor", | ||
| "name": "ventricle", | ||
| "values": { | ||
| "Emax": 1.057, | ||
| "Emin": 0.091, | ||
| "Vrd": 26.1, | ||
| "Vrs": 18.0, | ||
| "Impedance": 0.000351787, | ||
| "activation_function_type": "two_hill", | ||
| "activation_function_values": { | ||
| "t_shift": 0.15, | ||
| "tau_1": 0.25, | ||
| "tau_2": 0.35, | ||
| "m1": 1.5, | ||
| "m2": 10.0 | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ## Switching Between Activation Functions | ||
|
|
||
| To use a specific activation function, add the `activation_function_type` parameter to your chamber configuration: | ||
|
|
||
| - `activation_function_type: "half_cosine"` - Half Cosine (default for ChamberElastanceInductor) | ||
| - `activation_function_type: "piecewise_cosine"` - Piecewise Cosine (default for LinearElastanceChamber) | ||
| - `activation_function_type: "two_hill"` - Two Hill | ||
|
|
||
| Group the activation function-specific parameters under `activation_function_values` as a nested dictionary. | ||
|
|
||
| ## Backward Compatibility | ||
|
|
||
| For backward compatibility, the old flat format is also supported: | ||
|
|
||
| ```json | ||
| { | ||
| "type": "ChamberElastanceInductor", | ||
| "name": "ventricle", | ||
| "values": { | ||
| "Emax": 1.057, | ||
| "Emin": 0.091, | ||
| "Vrd": 26.1, | ||
| "Vrs": 18.0, | ||
| "t_active": 0.2, | ||
| "t_twitch": 0.3, | ||
| "Impedance": 0.000351787 | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| This format will continue to work, with the activation function determined by which parameters are provided. | ||
|
|
||
| ## Elastance Calculation | ||
|
|
||
| For all activation functions, the time-varying elastance E(t) is computed as: | ||
|
|
||
| **For ChamberElastanceInductor:** | ||
| ``` | ||
| E(t) = (Emax - Emin) * A(t) + Emin | ||
| Vrest(t) = (1 - A(t)) * (Vrd - Vrs) + Vrs | ||
| ``` | ||
|
|
||
| **For LinearElastanceChamber:** | ||
| ``` | ||
| E(t) = Epass + Emax * φ(t) | ||
| ``` | ||
|
|
||
| ## References | ||
|
|
||
| The two-hill activation function is described in: | ||
| - Kaiser, A. D., et al. (2022). "A design-based model of the aortic valve for fluid-structure interaction." Biomechanics and Modeling in Mechanobiology. https://link.springer.com/article/10.1007/s10439-022-03047-3 | ||
|
|
||
| ## Backward Compatibility | ||
|
|
||
| Existing configuration files will continue to work without modification: | ||
| - `ChamberElastanceInductor` defaults to half cosine activation when `t_active` and `t_twitch` are provided | ||
| - `LinearElastanceChamber` defaults to piecewise cosine activation when contraction/relaxation parameters are provided | ||
| - The old numeric `activation_type` parameter (0, 1, 2) is still supported but deprecated in favor of the string format | ||
| - Parameters can be specified at the top level without using `activation_function_values` for backward compatibility | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot Update this now that activation_function_type is mandatory and must be provided as a string
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated documentation to remove all backward compatibility references and clarify that
activation_function_typeis mandatory and must be provided as a string. Changes in commit ffddd68.