Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
7f66ca4
Change TestType to enum class and create TestData struct to extract T…
khoanguyen-dev Apr 23, 2024
c35e436
Add test to get default TestParameters
khoanguyen-dev Apr 23, 2024
fbad78f
Modify TestingScheme in Pycode to include TestParameters instead of T…
khoanguyen-dev Apr 23, 2024
f467d9e
Modify TestingScheme in Pycode to include TestParameters instead of T…
khoanguyen-dev Apr 23, 2024
46b12b6
Put TestType to another file and small improvement for the tests
khoanguyen-dev Apr 24, 2024
fbeb1ee
Change Pycode test_abm to call world.parameters instead of abm.parame…
khoanguyen-dev Apr 24, 2024
e40251a
Small modifications according to Rene's comments
khoanguyen-dev Apr 25, 2024
09de0aa
Change from using world.parameters to use abm.TestParameters in test_…
khoanguyen-dev Apr 25, 2024
a8dd034
Change from using world.parameters to use abm.TestParameters in test_…
khoanguyen-dev Apr 25, 2024
ef63427
Some change to blind TestParameters to world.parameters
khoanguyen-dev Apr 25, 2024
2bf21c7
Try to fix pybinds of custom_index_array for non-double types.
DavidKerkmann Apr 29, 2024
e21de5b
Add a test for draw_infection_course_forward() to pass the coverage test
DavidKerkmann Apr 29, 2024
2df1438
Merge remote-tracking branch 'refs/remotes/origin/1012-bug-in-getting…
khoanguyen-dev Apr 29, 2024
684e55b
Try fix #2
DavidKerkmann Apr 29, 2024
8dcc843
Merge branch '1012-bug-in-getting-testparameters-in-specific-test-der…
DavidKerkmann Apr 29, 2024
115e897
Try seconds fix for pybinds
DavidKerkmann Apr 29, 2024
60db2ad
Add a test for draw_infection_course_forward() to pass the coverage test
DavidKerkmann Apr 29, 2024
d28fd2c
Merge branch '1012-bug-in-getting-testparameters-in-specific-test-der…
DavidKerkmann Apr 29, 2024
7c5c0ea
Fix error in added test
khoanguyen-dev Apr 29, 2024
d88d3a4
Merge branch 'main' into 1012-bug-in-getting-testparameters-in-specif…
khoanguyen-dev Jun 6, 2024
747b31b
Try fix for python bindings
DavidKerkmann Jun 30, 2024
c837eb9
Add serialize and deserialize for TestParameters
DavidKerkmann Jun 30, 2024
3f7e974
small cleanup
DavidKerkmann Jul 3, 2024
85b6a2b
Apply suggestions from code review
DavidKerkmann Jul 19, 2024
ab37669
Merge main
DavidKerkmann Jul 19, 2024
a02e583
Fix small errors from previous update of main
DavidKerkmann Jul 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cpp/benchmarks/abm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ mio::abm::Simulation make_simulation(size_t num_persons, std::initializer_list<u
auto age = mio::AgeGroup(mio::UniformIntDistribution<size_t>::get_instance()(
world.get_rng(), size_t(0), world.parameters.get_num_groups() - 1));
auto person = world.add_person(home, age);
world.get_person(person).set_assigned_location(home);
world.assign_location(person, home);
home_size++;
}

Expand All @@ -43,7 +43,7 @@ mio::abm::Simulation make_simulation(size_t num_persons, std::initializer_list<u
for (auto& person : world.get_persons()) {
auto loc_idx =
mio::UniformIntDistribution<size_t>::get_instance()(world.get_rng(), size_t(0), num_locs - 1);
person.set_assigned_location(locs[loc_idx]);
world.assign_location(person.get_id(), locs[loc_idx]);
}
}

Expand Down
7 changes: 4 additions & 3 deletions cpp/examples/abm_history_object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,11 @@ int main()
auto probability = 0.5;
auto start_date = mio::abm::TimePoint(0);
auto end_date = mio::abm::TimePoint(0) + mio::abm::days(30);
auto test_type = mio::abm::AntigenTest();
auto test_type = mio::abm::TestType::Antigen;
auto test_parameters = world.parameters.get<mio::abm::TestData>()[test_type];
auto testing_criteria_work = mio::abm::TestingCriteria();
auto testing_scheme_work =
mio::abm::TestingScheme(testing_criteria_work, testing_min_time, start_date, end_date, test_type, probability);
auto testing_scheme_work = mio::abm::TestingScheme(testing_criteria_work, testing_min_time, start_date, end_date,
test_parameters, probability);
world.get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme_work);

// Assign infection state to each person.
Expand Down
8 changes: 5 additions & 3 deletions cpp/examples/abm_minimal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ int main()
world.parameters.get<mio::abm::IncubationPeriod>() = 4.;

// Set the age group the can go to school is AgeGroup(1) (i.e. 5-14)
world.parameters.get<mio::abm::AgeGroupGotoSchool>() = false;
world.parameters.get<mio::abm::AgeGroupGotoSchool>()[age_group_5_to_14] = true;
// Set the age group the can go to work is AgeGroup(2) and AgeGroup(3) (i.e. 15-34 and 35-59)
world.parameters.get<mio::abm::AgeGroupGotoWork>().set_multiple({age_group_15_to_34, age_group_35_to_59}, true);
Expand Down Expand Up @@ -107,10 +108,11 @@ int main()
auto probability = 0.5;
auto start_date = mio::abm::TimePoint(0);
auto end_date = mio::abm::TimePoint(0) + mio::abm::days(10);
auto test_type = mio::abm::AntigenTest();
auto test_type = mio::abm::TestType::Antigen;
auto test_parameters = world.parameters.get<mio::abm::TestData>()[test_type];
auto testing_criteria_work = mio::abm::TestingCriteria();
auto testing_scheme_work =
mio::abm::TestingScheme(testing_criteria_work, testing_min_time, start_date, end_date, test_type, probability);
auto testing_scheme_work = mio::abm::TestingScheme(testing_criteria_work, testing_min_time, start_date, end_date,
test_parameters, probability);
world.get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme_work);

// Assign infection state to each person.
Expand Down
75 changes: 42 additions & 33 deletions cpp/models/abm/parameters.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "abm/time.h"
#include "abm/virus_variant.h"
#include "abm/vaccine.h"
#include "abm/test_type.h"
#include "memilio/utils/custom_index_array.h"
#include "memilio/utils/uncertain_value.h"
#include "memilio/utils/parameter_set.h"
Expand Down Expand Up @@ -312,47 +313,54 @@ struct HighViralLoadProtectionFactor {
struct TestParameters {
UncertainValue<> sensitivity;
UncertainValue<> specificity;
};

struct GenericTest {
using Type = TestParameters;
static Type get_default()
{
return Type{0.9, 0.99};
}
static std::string name()
{
return "GenericTest";
}
/**
* serialize this.
* @see mio::serialize
*/
template <class IOContext>
void serialize(IOContext& io) const
{
auto obj = io.create_object("TestParameters");
obj.add_element("Sensitivity", sensitivity);
obj.add_element("Specificity", specificity);
}

/**
* deserialize an object of this class.
* @see mio::deserialize
*/
template <class IOContext>
static IOResult<TestParameters> deserialize(IOContext& io)
{
auto obj = io.expect_object("TestParameters");
auto sens = obj.expect_element("Sensitivity", mio::Tag<UncertainValue<>>{});
auto spec = obj.expect_element("Specificity", mio::Tag<UncertainValue<>>{});
return apply(
io,
[](auto&& sens_, auto&& spec_) {
return TestParameters{sens_, spec_};
},
sens, spec);
}
};

/**
* @brief Reliability of an AntigenTest.
* @brief Store a map from the TestTypes to their TestParameters.
*/
struct AntigenTest : public GenericTest {
using Type = TestParameters;
static Type get_default()
{
return Type{0.8, 0.88};
}
static std::string name()
{
return "AntigenTest";
}
};

/**
* @brief Reliability of a PCRTest.
*/
struct PCRTest : public GenericTest {
using Type = TestParameters;
static Type get_default()
struct TestData {
Comment thread
khoanguyen-dev marked this conversation as resolved.
using Type = CustomIndexArray<TestParameters, TestType>;
static auto get_default(AgeGroup /*size*/)
{
return Type{0.9, 0.99};
Type default_val = Type({TestType::Count});
default_val[{TestType::Generic}] = TestParameters{0.9, 0.99};
default_val[{TestType::Antigen}] = TestParameters{0.8, 0.88};
default_val[{TestType::PCR}] = TestParameters{0.9, 0.99};
return default_val;
}
static std::string name()
{
return "PCRTest";
return "TestData";
}
};

Expand Down Expand Up @@ -543,7 +551,8 @@ using ParametersBase =
InfectivityDistributions, DetectInfection, MaskProtection, AerosolTransmissionRates, LockdownDate,
QuarantineDuration, SocialEventRate, BasicShoppingRate, WorkRatio, SchoolRatio, GotoWorkTimeMinimum,
GotoWorkTimeMaximum, GotoSchoolTimeMinimum, GotoSchoolTimeMaximum, AgeGroupGotoSchool,
AgeGroupGotoWork, InfectionProtectionFactor, SeverityProtectionFactor, HighViralLoadProtectionFactor>;
AgeGroupGotoWork, InfectionProtectionFactor, SeverityProtectionFactor, HighViralLoadProtectionFactor,
TestData>;

/**
* @brief Maximum number of Person%s an infectious Person can infect at the respective Location.
Expand Down
46 changes: 46 additions & 0 deletions cpp/models/abm/test_type.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright (C) 2020-2024 MEmilio
*
* Authors: Khoa Nguyen
*
* Contact: Martin J. Kuehn <[email protected]>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef MIO_ABM_TEST_TYPE_H
#define MIO_ABM_TEST_TYPE_H

#include <cstdint>

namespace mio
{
namespace abm
{

/**
* @brief Type of a Test.
*/
enum class TestType : std::uint32_t
{
Generic = 0,
Antigen,
PCR,

Count
};

} // namespace abm
} // namespace mio

#endif
11 changes: 6 additions & 5 deletions cpp/models/abm/testing_strategy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,13 @@ bool TestingCriteria::evaluate(const Person& p, TimePoint t) const
}

TestingScheme::TestingScheme(const TestingCriteria& testing_criteria, TimeSpan minimal_time_since_last_test,
TimePoint start_date, TimePoint end_date, const GenericTest& test_type, double probability)
TimePoint start_date, TimePoint end_date, TestParameters test_parameters,
double probability)
: m_testing_criteria(testing_criteria)
, m_minimal_time_since_last_test(minimal_time_since_last_test)
, m_start_date(start_date)
, m_end_date(end_date)
, m_test_type(test_type)
, m_test_parameters(test_parameters)
, m_probability(probability)
{
}
Expand All @@ -86,8 +87,8 @@ bool TestingScheme::operator==(const TestingScheme& other) const
return this->m_testing_criteria == other.m_testing_criteria &&
this->m_minimal_time_since_last_test == other.m_minimal_time_since_last_test &&
this->m_start_date == other.m_start_date && this->m_end_date == other.m_end_date &&
this->m_test_type.get_default().sensitivity == other.m_test_type.get_default().sensitivity &&
this->m_test_type.get_default().specificity == other.m_test_type.get_default().specificity &&
this->m_test_parameters.sensitivity == other.m_test_parameters.sensitivity &&
this->m_test_parameters.specificity == other.m_test_parameters.specificity &&
this->m_probability == other.m_probability;
//To be adjusted and also TestType should be static.
}
Expand All @@ -108,7 +109,7 @@ bool TestingScheme::run_scheme(PersonalRandomNumberGenerator& rng, Person& perso
if (m_testing_criteria.evaluate(person, t)) {
double random = UniformDistribution<double>::get_instance()(rng);
if (random < m_probability) {
return !person.get_tested(rng, t, m_test_type.get_default());
return !person.get_tested(rng, t, m_test_parameters);
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions cpp/models/abm/testing_strategy.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,11 @@ class TestingScheme
* performed after a Person's last test.
* @param start_date Starting date of the scheme.
* @param end_date Ending date of the scheme.
* @param test_type The type of test to be performed.
* @param test_parameters The parameters of test to be performed.
* @param probability Probability of the test to be performed if a testing rule applies.
*/
TestingScheme(const TestingCriteria& testing_criteria, TimeSpan minimal_time_since_last_test, TimePoint start_date,
TimePoint end_date, const GenericTest& test_type, ScalarType probability);
TimePoint end_date, TestParameters test_parameters, ScalarType probability);

/**
* @brief Compares two TestingScheme%s for functional equality.
Expand Down Expand Up @@ -149,7 +149,7 @@ class TestingScheme
TimeSpan m_minimal_time_since_last_test; ///< Shortest period of time between two tests.
TimePoint m_start_date; ///< Starting date of the scheme.
TimePoint m_end_date; ///< Ending date of the scheme.
GenericTest m_test_type; ///< Type of the test.
TestParameters m_test_parameters; ///< Parameters of the test.
ScalarType m_probability; ///< Probability of performing the test.
bool m_is_active = false; ///< Whether the scheme is currently active.
};
Expand Down
1 change: 1 addition & 0 deletions cpp/models/abm/trip_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "abm/movement_data.h"
#include "abm/person_id.h"
#include "abm/time.h"
#include <vector>

namespace mio
{
Expand Down
8 changes: 4 additions & 4 deletions cpp/simulations/abm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -331,8 +331,8 @@ void create_assign_locations(mio::abm::World& world)
auto probability = mio::UncertainValue<>();
assign_uniform_distribution(probability, 0.5, 1.0);

auto test_type = mio::abm::AntigenTest();
auto testing_scheme = mio::abm::TestingScheme(testing_criteria, testing_min_time, start_date, end_date, test_type,
auto test_params = world.parameters.get<mio::abm::TestData>()[mio::abm::TestType::Antigen];
auto testing_scheme = mio::abm::TestingScheme(testing_criteria, testing_min_time, start_date, end_date, test_params,
probability.draw_sample());

world.get_testing_strategy().add_testing_scheme(mio::abm::LocationType::SocialEvent, testing_scheme);
Expand Down Expand Up @@ -429,7 +429,7 @@ void create_assign_locations(mio::abm::World& world)

testing_min_time = mio::abm::days(7);
auto testing_scheme_school = mio::abm::TestingScheme(testing_criteria_school, testing_min_time, start_date,
end_date, test_type, probability.draw_sample());
end_date, test_params, probability.draw_sample());
world.get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, testing_scheme_school);

auto test_at_work = std::vector<mio::abm::LocationType>{mio::abm::LocationType::Work};
Expand All @@ -438,7 +438,7 @@ void create_assign_locations(mio::abm::World& world)
assign_uniform_distribution(probability, 0.1, 0.5);
testing_min_time = mio::abm::days(1);
auto testing_scheme_work = mio::abm::TestingScheme(testing_criteria_work, testing_min_time, start_date, end_date,
test_type, probability.draw_sample());
test_params, probability.draw_sample());
world.get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme_work);
}

Expand Down
26 changes: 18 additions & 8 deletions cpp/tests/test_abm_infection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,24 @@ TEST(TestInfection, init)

TEST(TestInfection, getInfectionState)
{
auto counter = mio::Counter<uint32_t>(0);
auto rng = mio::abm::PersonalRandomNumberGenerator(mio::Key<uint64_t>{0}, mio::abm::PersonId(0), counter);
auto params = mio::abm::Parameters(num_age_groups);
auto t = mio::abm::TimePoint(0);
auto infection = mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, age_group_15_to_34, params, t,
mio::abm::InfectionState::Exposed, {}, true);
EXPECT_EQ(infection.get_infection_state(t), mio::abm::InfectionState::Exposed);
EXPECT_EQ(infection.get_infection_state(t - mio::abm::TimeSpan(1)), mio::abm::InfectionState::Susceptible);
auto counter = mio::Counter<uint32_t>(0);
auto rng = mio::abm::PersonalRandomNumberGenerator(mio::Key<uint64_t>{0}, mio::abm::PersonId(0), counter);
auto params = mio::abm::Parameters(num_age_groups);
auto t = mio::abm::TimePoint(0);
auto infection1 = mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, age_group_15_to_34, params, t,
mio::abm::InfectionState::Exposed, {}, true);
EXPECT_EQ(infection1.get_infection_state(t), mio::abm::InfectionState::Exposed);
EXPECT_EQ(infection1.get_infection_state(t - mio::abm::TimeSpan(1)), mio::abm::InfectionState::Susceptible);

params.get<mio::abm::CriticalToRecovered>()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 1;
ScopedMockDistribution<testing::StrictMock<MockDistribution<mio::UniformDistribution<double>>>> mock_uniform_dist;
EXPECT_CALL(mock_uniform_dist.get_mock(), invoke)
.Times(testing::AtLeast(1))
.WillRepeatedly(testing::Return(0.8)); // Recovered
auto infection2 = mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, age_group_15_to_34, params, t,
mio::abm::InfectionState::InfectedCritical, {}, true);
EXPECT_EQ(infection2.get_infection_state(t), mio::abm::InfectionState::InfectedCritical);
EXPECT_EQ(infection2.get_infection_state(t + mio::abm::days(1)), mio::abm::InfectionState::Recovered);
}

TEST(TestInfection, drawInfectionCourseBackward)
Expand Down
21 changes: 10 additions & 11 deletions cpp/tests/test_abm_person.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,8 @@ TEST(TestPerson, get_tested)
auto susceptible = mio::abm::Person(rng, loc.get_type(), loc.get_id(), age_group_15_to_34);
auto rng_suscetible = mio::abm::PersonalRandomNumberGenerator(rng, susceptible);

auto pcr_test = mio::abm::PCRTest();
auto antigen_test = mio::abm::AntigenTest();

auto pcr_parameters = params.get<mio::abm::TestData>()[mio::abm::TestType::PCR];
auto antigen_parameters = params.get<mio::abm::TestData>()[mio::abm::TestType::Antigen];
// Test pcr test
ScopedMockDistribution<testing::StrictMock<MockDistribution<mio::UniformDistribution<double>>>>
mock_uniform_dist_pcr;
Expand All @@ -157,14 +156,14 @@ TEST(TestPerson, get_tested)
.WillOnce(Return(0.95))
.WillOnce(Return(0.6))
.WillOnce(Return(0.999));
EXPECT_EQ(infected.get_tested(rng_infected, t, pcr_test.get_default()), true);
EXPECT_EQ(infected.get_tested(rng_infected, t, pcr_parameters), true);
EXPECT_EQ(infected.is_in_quarantine(t, params), true);
infected.remove_quarantine();
EXPECT_EQ(infected.get_tested(rng_infected, t, pcr_test.get_default()), false);
EXPECT_EQ(infected.get_tested(rng_infected, t, pcr_parameters), false);
EXPECT_EQ(infected.is_in_quarantine(t, params), false);
EXPECT_EQ(susceptible.get_tested(rng_suscetible, t, pcr_test.get_default()), false);
EXPECT_EQ(susceptible.get_tested(rng_suscetible, t, pcr_parameters), false);
EXPECT_EQ(susceptible.is_in_quarantine(t, params), false);
EXPECT_EQ(susceptible.get_tested(rng_suscetible, t, pcr_test.get_default()), true);
EXPECT_EQ(susceptible.get_tested(rng_suscetible, t, pcr_parameters), true);
EXPECT_EQ(susceptible.is_in_quarantine(t, params), true);
EXPECT_EQ(susceptible.get_time_of_last_test(), mio::abm::TimePoint(0));

Expand All @@ -177,10 +176,10 @@ TEST(TestPerson, get_tested)
.WillOnce(Return(0.95))
.WillOnce(Return(0.6))
.WillOnce(Return(0.999));
EXPECT_EQ(infected.get_tested(rng_infected, t, antigen_test.get_default()), true);
EXPECT_EQ(infected.get_tested(rng_infected, t, antigen_test.get_default()), false);
EXPECT_EQ(susceptible.get_tested(rng_suscetible, t, antigen_test.get_default()), false);
EXPECT_EQ(susceptible.get_tested(rng_suscetible, t, antigen_test.get_default()), true);
EXPECT_EQ(infected.get_tested(rng_infected, t, antigen_parameters), true);
EXPECT_EQ(infected.get_tested(rng_infected, t, antigen_parameters), false);
EXPECT_EQ(susceptible.get_tested(rng_suscetible, t, antigen_parameters), false);
EXPECT_EQ(susceptible.get_tested(rng_suscetible, t, antigen_parameters), true);
EXPECT_EQ(susceptible.get_time_of_last_test(), mio::abm::TimePoint(0));
}

Expand Down
Loading