Skip to content

Commit

Permalink
Merge pull request #189 from imperialCHEPI/rm_dynamic_risk
Browse files Browse the repository at this point in the history
Remove dynamic risk factor mechanism
  • Loading branch information
jamesturner246 authored Jul 25, 2023
2 parents 48dfc7a + 3388abe commit aa71c14
Show file tree
Hide file tree
Showing 13 changed files with 37 additions and 182 deletions.
7 changes: 0 additions & 7 deletions example/France.Config.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,6 @@
"proxy": "ses",
"range": [-2.316299, 2.296689]
},
{
"name": "Carbohydrate",
"level": 0,
"proxy": "",
"range": [40.0, 400.0]
},
{
"name": "Sodium",
"level": 1,
Expand Down Expand Up @@ -91,7 +85,6 @@
"range": [13.88, 39.48983]
}
],
"dynamic_risk_factor": "",
"risk_factor_models": {
"static": "France.HLM.json",
"dynamic": "France.EBHLM.json"
Expand Down
36 changes: 4 additions & 32 deletions src/HealthGPS.Console/configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,24 +210,6 @@ Configuration load_configuration(CommandOptions &options) {
}
}

if (!config.modelling.dynamic_risk_factor.empty()) {
auto found_dynamic_factor = false;
for (auto &factor : config.modelling.risk_factors) {
if (core::case_insensitive::equals(factor.name,
config.modelling.dynamic_risk_factor)) {
found_dynamic_factor = true;
break;
}
}

if (!found_dynamic_factor) {
fmt::print(
fg(fmt::color::red),
"\nInvalid configuration, dynamic risk factor: {} is not a risk factor.\n",
config.modelling.dynamic_risk_factor);
}
}

// Run-time
opt["running"]["start_time"].get_to(config.start_time);
opt["running"]["stop_time"].get_to(config.stop_time);
Expand Down Expand Up @@ -353,21 +335,11 @@ ModelInput create_model_input(core::DataTable &input_table, core::Country countr

auto mapping = std::vector<MappingEntry>();
for (auto &item : config.modelling.risk_factors) {
if (core::case_insensitive::equals(item.name, config.modelling.dynamic_risk_factor)) {
if (item.range.empty()) {
mapping.emplace_back(
MappingEntry(item.name, item.level, core::Identifier{item.proxy}, true));
} else {
auto boundary = FactorRange{item.range[0], item.range[1]};
mapping.emplace_back(MappingEntry(item.name, item.level,
core::Identifier{item.proxy}, boundary, true));
}
} else if (!item.range.empty()) {
auto boundary = FactorRange{item.range[0], item.range[1]};
mapping.emplace_back(
MappingEntry{item.name, item.level, core::Identifier{item.proxy}, boundary});
if (item.range.empty()) {
mapping.emplace_back(item.name, item.level, item.proxy);
} else {
mapping.emplace_back(MappingEntry{item.name, item.level, core::Identifier{item.proxy}});
auto boundary = FactorRange{item.range[0], item.range[1]};
mapping.emplace_back(item.name, item.level, item.proxy, boundary);
}
}

Expand Down
2 changes: 0 additions & 2 deletions src/HealthGPS.Console/jsonparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,14 +127,12 @@ void from_json(const json &j, RiskFactorInfo &p) {

void to_json(json &j, const ModellingInfo &p) {
j = json{{"risk_factors", p.risk_factors},
{"dynamic_risk_factor", p.dynamic_risk_factor},
{"risk_factor_models", p.risk_factor_models},
{"baseline_adjustments", p.baseline_adjustment}};
}

void from_json(const json &j, ModellingInfo &p) {
j.at("risk_factors").get_to(p.risk_factors);
j.at("dynamic_risk_factor").get_to(p.dynamic_risk_factor);
j.at("risk_factor_models").get_to(p.risk_factor_models);
j.at("baseline_adjustments").get_to(p.baseline_adjustment);
}
Expand Down
3 changes: 1 addition & 2 deletions src/HealthGPS.Console/poco.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,13 @@ struct BaselineInfo {

struct RiskFactorInfo {
std::string name;
short level{};
int level{};
std::string proxy;
std::vector<double> range;
};

struct ModellingInfo {
std::vector<RiskFactorInfo> risk_factors;
std::string dynamic_risk_factor;
std::unordered_map<std::string, std::string> risk_factor_models;
BaselineInfo baseline_adjustment;
};
Expand Down
2 changes: 1 addition & 1 deletion src/HealthGPS.Console/riskmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ struct HierarchicalModelInfo {

struct VariableInfo {
std::string name;
short level{};
int level{};
std::string factor;
};

Expand Down
9 changes: 3 additions & 6 deletions src/HealthGPS.Tests/HealthGPS.Test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,9 @@ namespace fs = std::filesystem;

static std::vector<hgps::MappingEntry> create_mapping_entries() {
using namespace hgps;
return std::vector<MappingEntry>{MappingEntry("Year", 0, core::Identifier::empty(), true),
MappingEntry("Gender", 0, core::Identifier{"gender"}),
MappingEntry("Age", 0, core::Identifier{"age"}),
MappingEntry("SmokingStatus", 1),
MappingEntry("AlcoholConsumption", 1),
MappingEntry("BMI", 2)};
return {MappingEntry("Gender", 0, core::Identifier{"gender"}),
MappingEntry("Age", 0, core::Identifier{"age"}), MappingEntry("SmokingStatus", 1),
MappingEntry("AlcoholConsumption", 1), MappingEntry("BMI", 2)};
}

void create_test_datatable(hgps::core::DataTable &data) {
Expand Down
55 changes: 5 additions & 50 deletions src/HealthGPS.Tests/HierarchicalMapping.Test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,9 @@

static std::vector<hgps::MappingEntry> create_mapping_entries() {
using namespace hgps;
return std::vector<MappingEntry>{MappingEntry("Year", 0, core::Identifier::empty(), true),
MappingEntry("Gender", 0, core::Identifier{"gender"}),
MappingEntry("Age", 0, core::Identifier{"age"}),
MappingEntry("SmokingStatus", 1),
MappingEntry("AlcoholConsumption", 1),
MappingEntry("BMI", 2)};
return {MappingEntry("Gender", 0, core::Identifier{"gender"}),
MappingEntry("Age", 0, core::Identifier{"age"}), MappingEntry("SmokingStatus", 1),
MappingEntry("AlcoholConsumption", 1), MappingEntry("BMI", 2)};
}

TEST(TestHealthGPS_Mapping, CreateEmpty) {
Expand All @@ -36,7 +33,7 @@ TEST(TestHealthGPS_Mapping, CreateFull) {
ASSERT_EQ(exp_size, mapping.size());
ASSERT_EQ(2, mapping.max_level());

ASSERT_EQ(3, level_zero.size());
ASSERT_EQ(2, level_zero.size());
ASSERT_EQ(2, level_one.size());
ASSERT_EQ(1, level_two.size());
}
Expand Down Expand Up @@ -73,22 +70,6 @@ TEST(TestHealthGPS_Mapping, AccessByConstInterator) {
}
}

TEST(TestHealthGPS_Mapping, CanIdentifyDynamicFactor) {
using namespace hgps;

auto entries = create_mapping_entries();
auto mapping = HierarchicalMapping(std::move(entries));
auto dynamic_factor = core::Identifier{"year"};

for (auto &entry : mapping) {
if (entry.key() == dynamic_factor) {
ASSERT_TRUE(entry.is_dynamic_factor());
} else {
ASSERT_FALSE(entry.is_dynamic_factor());
}
}
}

TEST(TestHealthGPS_Mapping, AccessAllEntries) {
using namespace hgps;

Expand Down Expand Up @@ -129,22 +110,11 @@ TEST(TestHealthGPS_Mapping, AccessSingleEntryThrowForUnknowKey) {
}
}

TEST(TestHealthGPS_Mapping, AccessEntriesWithoutDynamicFactor) {
using namespace hgps;

auto entries = create_mapping_entries();
auto exp_size = entries.size() - 1u;
auto mapping = HierarchicalMapping(std::move(entries));
auto all_entries = mapping.entries_without_dynamic();

ASSERT_EQ(exp_size, all_entries.size());
}

TEST(TestHealthGPS_Mapping, AccessAllLevelEntries) {
using namespace hgps;

auto entries = create_mapping_entries();
std::vector<int> exp_size = {3, 2, 1};
std::vector<int> exp_size = {2, 2, 1};
auto mapping = HierarchicalMapping(std::move(entries));
auto level_0_entries = mapping.at_level(0);
auto level_1_entries = mapping.at_level(1);
Expand All @@ -154,18 +124,3 @@ TEST(TestHealthGPS_Mapping, AccessAllLevelEntries) {
ASSERT_EQ(exp_size[1], level_1_entries.size());
ASSERT_EQ(exp_size[2], level_2_entries.size());
}

TEST(TestHealthGPS_Mapping, AccessLevelEntriesWithoutDynamicFactor) {
using namespace hgps;

auto entries = create_mapping_entries();
std::vector<int> exp_size = {2, 2, 1};
auto mapping = HierarchicalMapping(std::move(entries));
auto level_0_entries = mapping.at_level_without_dynamic(0);
auto level_1_entries = mapping.at_level_without_dynamic(1);
auto level_2_entries = mapping.at_level_without_dynamic(2);

ASSERT_EQ(exp_size[0], level_0_entries.size());
ASSERT_EQ(exp_size[1], level_1_entries.size());
ASSERT_EQ(exp_size[2], level_2_entries.size());
}
3 changes: 2 additions & 1 deletion src/HealthGPS/analysis_module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ void AnalysisModule::initialise_output_channels(RuntimeContext &context) {
}

channels_.push_back("count");
for (auto &factor : context.mapping().entries_without_dynamic()) {
for (auto &factor : context.mapping().entries()) {
channels_.emplace_back(factor.key().to_string());
}

Expand Down Expand Up @@ -404,4 +404,5 @@ std::unique_ptr<AnalysisModule> build_analysis_module(Repository &repository,
config.settings().age_range(),
config.run().comorbidities);
}

} // namespace hgps
11 changes: 3 additions & 8 deletions src/HealthGPS/energy_balance_hierarchical_model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ void EnergyBalanceHierarchicalModel::update_risk_factors(RuntimeContext &context
continue;
}

auto current_risk_factors =
get_current_risk_factors(context.mapping(), entity, context.time_now());
auto current_risk_factors = get_current_risk_factors(context.mapping(), entity);

// Model calibrated on previous year's age
auto model_age = static_cast<int>(entity.age - 1);
Expand Down Expand Up @@ -107,15 +106,11 @@ void EnergyBalanceHierarchicalModel::update_risk_factors_exposure(

std::map<core::Identifier, double>
EnergyBalanceHierarchicalModel::get_current_risk_factors(const HierarchicalMapping &mapping,
Person &entity, int time_year) const {
Person &entity) const {
auto entity_risk_factors = std::map<core::Identifier, double>();
entity_risk_factors.emplace(InterceptKey, entity.get_risk_factor_value(InterceptKey));
for (const auto &factor : mapping) {
if (factor.is_dynamic_factor()) {
entity_risk_factors.emplace(factor.key(), time_year - 1);
} else {
entity_risk_factors.emplace(factor.key(), entity.get_risk_factor_value(factor.key()));
}
entity_risk_factors.emplace(factor.key(), entity.get_risk_factor_value(factor.key()));
}

return entity_risk_factors;
Expand Down
3 changes: 1 addition & 2 deletions src/HealthGPS/energy_balance_hierarchical_model.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,7 @@ class EnergyBalanceHierarchicalModel final : public HierarchicalLinearModel {
const std::map<core::Identifier, FactorDynamicEquation> &equations);

std::map<core::Identifier, double> get_current_risk_factors(const HierarchicalMapping &mapping,
Person &entity,
int time_year) const;
Person &entity) const;

double sample_normal_with_boundary(Random &random, double mean, double standard_deviation,
double boundary) const;
Expand Down
6 changes: 3 additions & 3 deletions src/HealthGPS/hierarchical_model_static.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ void StaticHierarchicalLinearModel::generate_risk_factors(RuntimeContext &contex
if (level_factors_cache.contains(level)) {
level_factors = level_factors_cache.at(level);
} else {
level_factors = context.mapping().at_level_without_dynamic(level);
level_factors = context.mapping().at_level(level);
level_factors_cache.emplace(level, level_factors);
}

Expand All @@ -54,7 +54,7 @@ void StaticHierarchicalLinearModel::update_risk_factors(RuntimeContext &context)
if (level_factors_cache.contains(level)) {
level_factors = level_factors_cache.at(level);
} else {
level_factors = context.mapping().at_level_without_dynamic(level);
level_factors = context.mapping().at_level(level);
level_factors_cache.emplace(level, level_factors);
}

Expand Down Expand Up @@ -96,7 +96,7 @@ void StaticHierarchicalLinearModel::generate_for_entity(RuntimeContext &context,
auto determ_risk_factors = std::map<core::Identifier, double>();
determ_risk_factors.emplace(InterceptKey, entity.get_risk_factor_value(InterceptKey));
for (const auto &item : context.mapping()) {
if (item.level() < level && !item.is_dynamic_factor()) {
if (item.level() < level) {
determ_risk_factors.emplace(item.key(),
entity.get_risk_factor_value(item.entity_key()));
}
Expand Down
41 changes: 8 additions & 33 deletions src/HealthGPS/mapping.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,37 +7,28 @@
#include <tuple>

namespace hgps {
hgps::MappingEntry::MappingEntry(std::string name, short level, core::Identifier entity_key,
FactorRange range, bool dynamic_factor)
: name_{name}, name_key_{core::Identifier{name}}, level_{level},
entity_key_{std::move(entity_key)}, range_{range}, dynamic_factor_{dynamic_factor} {}

MappingEntry::MappingEntry(std::string name, short level, core::Identifier entity_key,
bool dynamic_factor)
: MappingEntry(name, level, entity_key, FactorRange{}, dynamic_factor) {}

MappingEntry::MappingEntry(std::string name, short level, core::Identifier entity_key,
MappingEntry::MappingEntry(std::string name, int level, core::Identifier entity_key,
FactorRange range)
: MappingEntry(name, level, entity_key, range, false) {}
: name_{name}, name_key_{core::Identifier{name}}, level_{level},
entity_key_{std::move(entity_key)}, range_{range} {}

MappingEntry::MappingEntry(std::string name, short level, core::Identifier entity_key)
: MappingEntry(name, level, entity_key, FactorRange{}, false) {}
MappingEntry::MappingEntry(std::string name, int level, core::Identifier entity_key)
: MappingEntry(name, level, entity_key, FactorRange{}) {}

MappingEntry::MappingEntry(std::string name, short level)
: MappingEntry(name, level, core::Identifier::empty(), FactorRange{}, false) {}
MappingEntry::MappingEntry(std::string name, int level)
: MappingEntry(name, level, core::Identifier::empty(), FactorRange{}) {}

const std::string &MappingEntry::name() const noexcept { return name_; }

short MappingEntry::level() const noexcept { return level_; }
int MappingEntry::level() const noexcept { return level_; }

const core::Identifier &MappingEntry::entity_key() const noexcept {
return is_entity() ? entity_key_ : name_key_;
}

bool MappingEntry::is_entity() const noexcept { return !entity_key_.is_empty(); }

bool MappingEntry::is_dynamic_factor() const noexcept { return dynamic_factor_; }

const core::Identifier &MappingEntry::key() const noexcept { return name_key_; }

const FactorRange &MappingEntry::range() const noexcept { return range_; }
Expand Down Expand Up @@ -68,14 +59,6 @@ HierarchicalMapping::HierarchicalMapping(std::vector<MappingEntry> &&mapping)

const std::vector<MappingEntry> &HierarchicalMapping::entries() const noexcept { return mapping_; }

std::vector<MappingEntry> HierarchicalMapping::entries_without_dynamic() const noexcept {
std::vector<MappingEntry> result;
std::copy_if(mapping_.begin(), mapping_.end(), std::back_inserter(result),
[](const auto &elem) { return !elem.is_dynamic_factor(); });

return result;
}

std::size_t HierarchicalMapping::size() const noexcept { return mapping_.size(); }

int HierarchicalMapping::max_level() const noexcept {
Expand Down Expand Up @@ -105,12 +88,4 @@ std::vector<MappingEntry> HierarchicalMapping::at_level(int level) const noexcep
return result;
}

std::vector<MappingEntry> HierarchicalMapping::at_level_without_dynamic(int level) const noexcept {
std::vector<MappingEntry> result;
std::copy_if(
mapping_.cbegin(), mapping_.cend(), std::back_inserter(result),
[&level](const auto &elem) { return elem.level() == level && !elem.is_dynamic_factor(); });

return result;
}
} // namespace hgps
Loading

0 comments on commit aa71c14

Please sign in to comment.