예제 #1
0
def test_readInfectionProbability_invalid_prob(prob):
    with pytest.raises(ValueError):
        loaders.readInfectionProbability(
            pd.DataFrame([{
                "Time": 0,
                "Value": prob
            }]))
def test_readInfectionProbability_invalid_time(t):
    with pytest.raises(ValueError):
        loaders.readInfectionProbability(
            pd.DataFrame([{
                "Date": t,
                "Value": 1.0
            }]))
예제 #3
0
def test_readInfectionProbability_no_zeroth_time():
    with pytest.raises(ValueError):
        loaders.readInfectionProbability(
            pd.DataFrame([{
                "Time": 3,
                "Value": 1.0
            }]))
def test_readInfectionProbability():
    df = pd.DataFrame([("2020-01-01", 0.3), ("2020-02-01", 0.7),
                       ("2020-12-31", 1.0)],
                      columns=["Date", "Value"])

    assert loaders.readInfectionProbability(df) == {
        dt.date(2020, 1, 1): 0.3,
        dt.date(2020, 2, 1): 0.7,
        dt.date(2020, 12, 31): 1.0
    }
예제 #5
0
def test_readInfectionProbability_empty():
    with pytest.raises(ValueError):
        loaders.readInfectionProbability(pd.DataFrame())
예제 #6
0
def test_readInfectionProbability():
    df = pd.DataFrame([(0, 0.3), (4, 0.7), (30, 1.0)],
                      columns=["Time", "Value"])

    assert loaders.readInfectionProbability(df) == {0: 0.3, 4: 0.7, 30: 1.0}
예제 #7
0
def createNetworkOfPopulation(
        compartment_transition_table: pd.DataFrame,
        population_table: pd.DataFrame,
        commutes_table: pd.DataFrame,
        mixing_matrix_table: pd.DataFrame,
        infectious_states: pd.DataFrame,
        infection_prob: pd.DataFrame,
        initial_infections: pd.DataFrame,
        trials: pd.DataFrame,
        movement_multipliers_table: pd.DataFrame = None,
        stochastic_mode: pd.DataFrame = None,
        random_seed: pd.DataFrame = None) -> NetworkOfPopulation:
    """Create the network of the population, loading data from files.

    :param compartment_transition_table: pd.Dataframe specifying the transition rates between infected compartments.
    :param population_table: pd.Dataframe with the population size in each region by gender and age.
    :param commutes_table: pd.Dataframe with the movements between regions.
    :param mixing_matrix_table: pd.Dataframe with the age infection matrix.
    :param movement_multipliers_table: pd.Dataframe with the movement multipliers. This may be None, in
    which case no multipliers are applied to the movements.
    :param infectious_states: States that are considered infectious
    :param infection_prob: Probability that a given contact will result in an infection
    :param initial_infections: Initial infections of the population at time 0
    :param trials: Number of trials for the model
    :param stochastic_mode: Use stochastic mode for the model
    :param random_seed: Random number generator seed used for stochastic mode
    :return: The constructed network
    """
    infection_prob = loaders.readInfectionProbability(infection_prob)

    infectious_states = loaders.readInfectiousStates(infectious_states)
    initial_infections = loaders.readInitialInfections(initial_infections)
    trials = loaders.readTrials(trials)
    stochastic_mode = loaders.readStochasticMode(stochastic_mode)
    random_seed = loaders.readRandomSeed(random_seed)

    # diseases progression matrix
    progression = loaders.readCompartmentRatesByAge(
        compartment_transition_table)

    # population census data
    population = loaders.readPopulationAgeStructured(population_table)

    # Check some requirements for this particular model to work with the progression matrix
    all_states = set()
    for states in progression.values():
        assert SUSCEPTIBLE_STATE not in states, "progression from susceptible state is not allowed"
        for state, nextStates in states.items():
            for nextState in nextStates:
                all_states.add(state)
                all_states.add(nextState)
                assert state == nextState or nextState != EXPOSED_STATE, \
                    "progression into exposed state is not allowed other than in self reference"
    assert (set(infectious_states) - all_states) == set(), \
        f"mismatched infectious states and states {infectious_states} {set(progression.keys())}"

    # people movement's graph
    graph = loaders.genGraphFromContactFile(commutes_table)

    # movement multipliers (dampening or heightening)
    if movement_multipliers_table is not None:
        movementMultipliers = loaders.readMovementMultipliers(
            movement_multipliers_table)
    else:
        movementMultipliers: Dict[int, loaders.Multiplier] = {}

    # age-based infection matrix
    mixingMatrix = loaders.MixingMatrix(mixing_matrix_table)

    agesInInfectionMatrix = set(mixingMatrix)
    for age in mixingMatrix:
        assert agesInInfectionMatrix == set(
            mixingMatrix[age]), "infection matrix columns/rows mismatch"

    # Checks across datasets
    assert agesInInfectionMatrix == set(
        progression.keys()), "infection matrix and progression ages mismatch"
    assert agesInInfectionMatrix == {age for region in population.values() for age in region}, \
        "infection matrix and population ages mismatch"
    assert set(graph.nodes()) == set(
        population.keys()), "regions mismatch between graph and population"

    state0: Dict[str, Dict[Tuple[str, str], float]] = {}
    for node in list(graph.nodes()):
        region = state0.setdefault(node, {})
        for age, compartments in progression.items():
            region[(age, SUSCEPTIBLE_STATE)] = population[node][age]
            for compartment in compartments:
                region[(age, compartment)] = 0

    logger.info("Nodes: %s, Ages: %s, States: %s", len(state0),
                agesInInfectionMatrix, all_states)
    return NetworkOfPopulation(progression=progression,
                               graph=graph,
                               initialState=state0,
                               mixingMatrix=mixingMatrix,
                               movementMultipliers=movementMultipliers,
                               infectiousStates=infectious_states,
                               infectionProb=infection_prob,
                               initialInfections=initial_infections,
                               trials=trials,
                               stochastic=stochastic_mode,
                               randomState=np.random.default_rng(random_seed))
예제 #8
0
def createNetworkOfPopulation(
    compartment_transition_table: pd.DataFrame,
    population_table: pd.DataFrame,
    commutes_table: pd.DataFrame,
    mixing_matrix_table: pd.DataFrame,
    infectious_states: pd.DataFrame,
    infection_prob: pd.DataFrame,
    initial_infections: pd.DataFrame,
    trials: pd.DataFrame,
    start_end_date: pd.DataFrame,
    movement_multipliers_table: pd.DataFrame = None,
    stochastic_mode: pd.DataFrame = None,
) -> Tuple[NetworkOfPopulation, List[standard_api.Issue]]:
    """Create the network of the population, loading data from files.

    :param compartment_transition_table: pd.Dataframe specifying the transition rates between infected compartments.
    :param population_table: pd.Dataframe with the population size in each region by gender and age.
    :param commutes_table: pd.Dataframe with the movements between regions.
    :param mixing_matrix_table: pd.Dataframe with the age infection matrix.
    :param infectious_states: States that are considered infectious
    :param infection_prob: Probability that a given contact will result in an infection
    :param initial_infections: Initial infections of the population at time 0
    :param trials: Number of trials for the model
    :param start_end_date: Starting and ending dates of the model
    :param movement_multipliers_table: pd.Dataframe with the movement multipliers. This may be None, in
                                       which case no multipliers are applied to the movements.
    :param stochastic_mode: Use stochastic mode for the model
    :return: A tuple with the constructed network and a list of any issues found. Although it may look convenient,
             storing this list inside of NetworkOfPopulation is not a good idea, as that may give the functions that
             receive it the false impression they can just append new issues there
    """
    issues: List[standard_api.Issue] = []
    infection_prob = loaders.readInfectionProbability(infection_prob)

    infectious_states = loaders.readInfectiousStates(infectious_states)
    initial_infections = loaders.readInitialInfections(initial_infections)
    trials = loaders.readTrials(trials)
    start_date, end_date = loaders.readStartEndDate(start_end_date)
    stochastic_mode = loaders.readStochasticMode(stochastic_mode)

    # diseases progression matrix
    progression = loaders.readCompartmentRatesByAge(
        compartment_transition_table)

    # population census data
    population = loaders.readPopulationAgeStructured(population_table)

    # Check some requirements for this particular model to work with the progression matrix
    all_states = set()
    for states in progression.values():
        assert SUSCEPTIBLE_STATE not in states, "progression from susceptible state is not allowed"
        for state, nextStates in states.items():
            for nextState in nextStates:
                all_states.add(state)
                all_states.add(nextState)
                assert state == nextState or nextState != EXPOSED_STATE, \
                    "progression into exposed state is not allowed other than in self reference"
    assert (set(infectious_states) - all_states) == set(), \
        f"mismatched infectious states and states {infectious_states} {all_states}"

    # people movement's graph
    graph = loaders.genGraphFromContactFile(commutes_table)

    # movement multipliers (dampening or heightening)
    if movement_multipliers_table is not None:
        movementMultipliers = loaders.readMovementMultipliers(
            movement_multipliers_table)
    else:
        movementMultipliers = {}

    # age-based infection matrix
    mixingMatrix = loaders.MixingMatrix(mixing_matrix_table)

    agesInInfectionMatrix = set(mixingMatrix)
    for age in mixingMatrix:
        assert agesInInfectionMatrix == set(
            mixingMatrix[age]), "infection matrix columns/rows mismatch"

    # Checks across datasets
    assert agesInInfectionMatrix == set(
        progression.keys()), "infection matrix and progression ages mismatch"
    assert agesInInfectionMatrix == {age for region in population.values() for age in region}, \
        "infection matrix and population ages mismatch"
    disconnected_nodes = set(population.keys()) - set(graph.nodes())
    if disconnected_nodes:
        log_issue(
            logger,
            f"These nodes have no contacts in the current network: {','.join(disconnected_nodes)}",
            IssueSeverity.MEDIUM,
            issues,
        )

    state0: Dict[str, Dict[Tuple[str, str], float]] = {}
    for node in list(graph.nodes()):
        region = state0.setdefault(node, {})
        for age, compartments in progression.items():
            if node not in population:
                log_issue(
                    logger,
                    f"Node {node} is not in the population table, assuming population of 0 for all ages",
                    IssueSeverity.MEDIUM,
                    issues,
                )
                pop = 0.0
            else:
                pop = population[node][age]
            region[(age, SUSCEPTIBLE_STATE)] = pop
            for compartment in compartments:
                region[(age, compartment)] = 0

    logger.info("Nodes: %s, Ages: %s, States: %s", len(state0),
                agesInInfectionMatrix, all_states)
    nop = NetworkOfPopulation(
        progression=progression,
        graph=graph,
        initialState=state0,
        mixingMatrix=mixingMatrix,
        movementMultipliers=movementMultipliers,
        infectiousStates=infectious_states,
        infectionProb=infection_prob,
        initialInfections=initial_infections,
        trials=trials,
        startDate=start_date,
        endDate=end_date,
        stochastic=stochastic_mode,
    )
    return (nop, issues)