Add two-hill activation function and refactor chamber elastance models with proper separation of concerns#213
Add two-hill activation function and refactor chamber elastance models with proper separation of concerns#213
Conversation
…earElastanceChamber Co-authored-by: aabrown100-git <71424733+aabrown100-git@users.noreply.github.com>
…ctivationFunction Co-authored-by: aabrown100-git <71424733+aabrown100-git@users.noreply.github.com>
Co-authored-by: aabrown100-git <71424733+aabrown100-git@users.noreply.github.com>
Co-authored-by: aabrown100-git <71424733+aabrown100-git@users.noreply.github.com>
Co-authored-by: aabrown100-git <71424733+aabrown100-git@users.noreply.github.com>
aabrown100-git
left a comment
There was a problem hiding this comment.
In the json file, can we have the activation function parameters in a nested dictionary. Also, the activation_function_type should be provided as a string rather than a number
For example
"activation_function_type": "two_hill"
activation_function_values: {
"tau1": xxx
"tau2": xxx
...
}
…n_values in JSON Co-authored-by: aabrown100-git <71424733+aabrown100-git@users.noreply.github.com>
Done! The JSON format now accepts:
Example: {
"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
}
}
}The old numeric format is still supported for backward compatibility. Changes in commit b68ffd5. |
…vationFunction Co-authored-by: aabrown100-git <71424733+aabrown100-git@users.noreply.github.com>
aabrown100-git
left a comment
There was a problem hiding this comment.
I want activation function parameters to be members of individual instances of ActivationFuction, rather than members of ChamberElastanceInductor or LinearElasanceChamber. We should separate these as much as possible.
…tances Co-authored-by: aabrown100-git <71424733+aabrown100-git@users.noreply.github.com>
Done! Activation function parameters are now:
This provides proper separation of concerns between chambers and activation functions. Changes in commit 6c18357. |
|
@copilot can you review the failing build and test CI workflows and address the bug |
…count() method Co-authored-by: ncdorn <126125269+ncdorn@users.noreply.github.com>
Fixed the compilation errors in commit 6d09f57. The issue was using Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
| act = -0.5 * cos(2 * M_PI * t_contract / t_twitch) + 0.5; | ||
| void ChamberElastanceInductor::initialize_activation_function( | ||
| std::vector<double>& parameters) { | ||
| // Check if activation_type parameter is provided (optional parameter) |
There was a problem hiding this comment.
@copilot activation_type should be a required parameter for this block
There was a problem hiding this comment.
Done! activation_type is now a required parameter (no default value) for ChamberElastanceInductor. The parameter must be explicitly specified in JSON configurations. Changes in commit b0aa76c.
Co-authored-by: aabrown100-git <71424733+aabrown100-git@users.noreply.github.com>
src/solve/SimulationParameters.cpp
Outdated
| } | ||
|
|
||
| // Replace string with numeric value for backward compatibility | ||
| chamber_values["activation_type"] = static_cast<int>(act_params.type); |
There was a problem hiding this comment.
@copilot Don't allow "activation_type". Let's just read and keep track of "activation_function_type" strings only.
There was a problem hiding this comment.
Removed backward compatibility for numeric activation_type. Now only string-based activation_function_type is supported. Changes in commit 0a9dc48.
… only support activation_function_type string Co-authored-by: aabrown100-git <71424733+aabrown100-git@users.noreply.github.com>
|
Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details. Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
docs/pages/activation_functions.md
Outdated
| { | ||
| "type": "ChamberElastanceInductor", | ||
| "name": "ventricle", | ||
| "values": { |
There was a problem hiding this comment.
@copilot Update this now that activation_function_type is mandatory and must be provided as a string
There was a problem hiding this comment.
Updated documentation to remove all backward compatibility references and clarify that activation_function_type is mandatory and must be provided as a string. Changes in commit ffddd68.
…ction_type parameter Co-authored-by: aabrown100-git <71424733+aabrown100-git@users.noreply.github.com>
src/solve/SimulationParameters.cpp
Outdated
| act_params.type = ActivationType::HALF_COSINE; // Default | ||
| act_params.cardiac_period = 0.0; // Will be set later from model | ||
|
|
||
| // Check if activation function type is specified as a string |
There was a problem hiding this comment.
@copilot We should check here that activation_function_type is specified. If it's not, we should throw an error here. Likewise, if any activation_function_values required for a particular activation_function_type are not provided, we should throw an error
There was a problem hiding this comment.
Added comprehensive validation in commit 28d2faa:
activation_function_typeis now required (throws error if missing or not a string)activation_function_valuesis now required (throws error if missing or not a dictionary)- All required parameters for each activation type are validated:
half_cosine: t_active, t_twitchpiecewise_cosine: contract_start, relax_start, contract_duration, relax_durationtwo_hill: t_shift, tau_1, tau_2, m1, m2
- Error messages list all missing parameters at once for easier debugging
…ion_function_values parameters Co-authored-by: aabrown100-git <71424733+aabrown100-git@users.noreply.github.com>
|
Closing. Too messy with all the comments to copilot. Will update issue and submit a new PR. |
Summary
This PR successfully implements support for the two-hill activation function in cardiac chamber models, with complete separation of concerns between chamber models and activation functions, plus improved error reporting for missing parameters.
Changes Made
Core Implementation (800+ lines added)
ActivationFunction Class Hierarchy (
src/model/ActivationFunction.h)ActivationFunctionwith polymorphic interfacecardiac_periodis now a protected member of the baseActivationFunctionclass, stored once rather than passed on every compute() callHalfCosineActivation: Original half-cosine from ChamberElastanceInductorPiecewiseCosineActivation: Piecewise cosine activationTwoHillActivation: New two-hill function from alexkaiser's branchChamber Model Refactoring
ChamberElastanceInductor: Added support for all three activation typesactivation_function_typeis now a required parameter (string only, no numeric support)LinearElastanceChamberto replacePiecewiseCosineChamberactivation_function_typeis a required parameterPiecewiseCosineChambercompletely removed - including source files, headers, and C++ type alias for cleaner separation between chamber models and activation functionsActivationFunction::create()factory methodinitialize_activation_function()codeChamberElastanceInductor: Emax, Emin, Vrd, Vrs, Impedance, activation_function_type (all required)LinearElastanceChamber: Emax, Epass, Vrest, activation_function_type (all required)set_activation_params()method to inject activation configuration into chamberscompute(time)without needing to passcardiac_periodeach timeNew JSON Configuration Format (Required)
activation_function_typeaccepts strings: "half_cosine", "piecewise_cosine", "two_hill"activation_function_typeis required for both chamber typesactivation_typeactivation_function_valuesnested dictionaryBuild System Updates
BlockType.h- removed deprecatedpiecewise_cosine_chamberenum, fixed enum values to be sequentialModel.cppto register onlyLinearElastanceChamberSimulationParameters.cppto parse new JSON format and extract activation parametersactivation_function_typeis supportedactivation_function_typeto be specified as a stringactivation_function_valuesnested dictionarySimulationParameters.hto include activation function headersCMakeLists.txt- removedPiecewiseCosineChambersource filescsv_writer.cppto useLinearElastanceChamberTesting & Documentation (410 lines added)
Test Cases
chamber_two_hill_activation.json: Tests ChamberElastanceInductor with two-hilllinear_chamber_two_hill_activation.json: Tests LinearElastanceChamber with two-hillpiecewise_Chamber_and_Valve.json: Updated to useLinearElastanceChamberwith new formatactivation_function_typestringDocumentation (
docs/pages/activation_functions.md)activation_function_typerequirementactivation_function_typeis required and must be a stringKey Features
✅ Comprehensive Parameter Validation
activation_function_typeas required - no default valueactivation_function_valuesis provided as a nested dictionaryhalf_cosine: t_active, t_twitchpiecewise_cosine: contract_start, relax_start, contract_duration, relax_durationtwo_hill: t_shift, tau_1, tau_2, m1, m2✅ Clean API - String-based only
activation_typeactivation_function_typewith string values ("half_cosine", "piecewise_cosine", "two_hill") is supported✅ CI Build Fixed
✅ Improved error reporting
✅ Complete removal of PiecewiseCosineChamber
LinearElastanceChamberis the only name for this chamber type✅ Consistent cardiac_period handling
cardiac_periodis stored as a protected member in theActivationFunctionbase classcardiac_periodin their constructorscompute()method signature simplified to only taketimeparameter✅ Complete separation of concerns
✅ Eliminated code duplication
ActivationFunctioncreates activation functions✅ New JSON format (required)
activation_function_typeis now required for both chamber types - no defaults, no numeric supportactivation_function_values✅ Three activation function types available
Usage Example
{ "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 } } }Breaking Changes
"type": "PiecewiseCosineChamber"is no longer supported - use"type": "LinearElastanceChamber"insteadPiecewiseCosineChamberclass completely removed from codebaseactivation_function_valuesnested dictionaryactivation_function_typeis now required for bothChamberElastanceInductorandLinearElastanceChamber(no defaults)activation_typeparameter is no longer supported - must use string-basedactivation_function_typeFiles Changed
References
Original prompt
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.