Skip to content

Foreign destination

ForeignDestination dataclass

Represents an international travel destination with associated infection risk. Uses model: P = 1 - exp(-β_base * R_country * D_stay)

Source code in june/groups/travel/foreign_destination.py
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
@dataclass
class ForeignDestination:
    """Represents an international travel destination with associated infection risk.
    Uses model: P = 1 - exp(-β_base * R_country * D_stay)

    """
    name: str
    risk_level: RiskLevel
    risk_multiplier: float
    region: Optional[str] = None
    _config: dict = None  # Cache config

    def __post_init__(self):
        """Load config after initialization"""
        config_path = configs_path / "defaults/geography/foreign_destinations.yaml"
        with open(config_path) as f:
            self._config = yaml.safe_load(f)

    def calculate_infection_risk(
        self, 
        duration_days: int,
        travel_purpose: TravelPurpose = TravelPurpose.BUSINESS,
    ) -> float:
        """Calculate infection risk based on destination risk and travel purpose.
        P = 1 - exp(-β_base * R_country * D_stay)

        Args:
            duration_days (int): Length of stay in days (D_stay)
            travel_purpose (TravelPurpose, optional): Purpose of travel affecting base transmission rate (Default value = TravelPurpose.BUSINESS)

        Returns:
            : Infection probability (0-1)

        """
        # Get base transmission rate and adjust by travel purpose
        beta_base = self._config["base_parameters"]["contact_rate"]
        duration_scaling = self._config["base_parameters"]["duration_scaling"]
        activity_multiplier = self._config["activity_intensities"][travel_purpose.name]
        beta_adjusted = beta_base * activity_multiplier

        # Calculate cumulative risk using the exponential model
        # P = 1 - exp(-β_base * R_country * D_stay)
        cumulative_risk = 1 - np.exp(
            -beta_adjusted * 
            self.risk_multiplier * 
            duration_days / duration_scaling  # Scale factor to keep probabilities reasonable
        )

        return cumulative_risk

__post_init__()

Load config after initialization

Source code in june/groups/travel/foreign_destination.py
33
34
35
36
37
def __post_init__(self):
    """Load config after initialization"""
    config_path = configs_path / "defaults/geography/foreign_destinations.yaml"
    with open(config_path) as f:
        self._config = yaml.safe_load(f)

calculate_infection_risk(duration_days, travel_purpose=TravelPurpose.BUSINESS)

Calculate infection risk based on destination risk and travel purpose. P = 1 - exp(-β_base * R_country * D_stay)

Parameters:

Name Type Description Default
duration_days int

Length of stay in days (D_stay)

required
travel_purpose TravelPurpose

Purpose of travel affecting base transmission rate (Default value = TravelPurpose.BUSINESS)

BUSINESS

Returns:

Type Description
float

Infection probability (0-1)

Source code in june/groups/travel/foreign_destination.py
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
def calculate_infection_risk(
    self, 
    duration_days: int,
    travel_purpose: TravelPurpose = TravelPurpose.BUSINESS,
) -> float:
    """Calculate infection risk based on destination risk and travel purpose.
    P = 1 - exp(-β_base * R_country * D_stay)

    Args:
        duration_days (int): Length of stay in days (D_stay)
        travel_purpose (TravelPurpose, optional): Purpose of travel affecting base transmission rate (Default value = TravelPurpose.BUSINESS)

    Returns:
        : Infection probability (0-1)

    """
    # Get base transmission rate and adjust by travel purpose
    beta_base = self._config["base_parameters"]["contact_rate"]
    duration_scaling = self._config["base_parameters"]["duration_scaling"]
    activity_multiplier = self._config["activity_intensities"][travel_purpose.name]
    beta_adjusted = beta_base * activity_multiplier

    # Calculate cumulative risk using the exponential model
    # P = 1 - exp(-β_base * R_country * D_stay)
    cumulative_risk = 1 - np.exp(
        -beta_adjusted * 
        self.risk_multiplier * 
        duration_days / duration_scaling  # Scale factor to keep probabilities reasonable
    )

    return cumulative_risk

ForeignDestinationRegistry

Registry of foreign destinations and their risk levels

Source code in june/groups/travel/foreign_destination.py
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
class ForeignDestinationRegistry:
    """Registry of foreign destinations and their risk levels"""

    def __init__(self):
        self.destinations: Dict[str, ForeignDestination] = {}
        self._load_destinations()

    def _load_destinations(self):
        """Load destination data from config"""
        config_path = configs_path / "defaults/geography/foreign_destinations.yaml"
        with open(config_path) as f:
            config = yaml.safe_load(f)

        # Get base risk multipliers for each level
        risk_multipliers = config["risk_multipliers"]

        # Create destinations from config
        for dest_name, dest_data in config["destinations"].items():
            # Get risk level and use corresponding multiplier
            risk_level = RiskLevel[dest_data["risk_level"]]

            # Use configured risk multiplier or base level multiplier
            risk_multiplier = dest_data.get(
                "risk_multiplier", 
                risk_multipliers[risk_level.name]
            )

            self.destinations[dest_name] = ForeignDestination(
                name=dest_name,
                risk_level=risk_level,
                risk_multiplier=risk_multiplier,
                region=dest_data.get("region")
            )

    def get_destination(self, name: str) -> Optional[ForeignDestination]:
        """Get destination by name

        Args:
            name (str): 

        """
        return self.destinations.get(name)

    def get_destinations_by_risk(self, risk_level: RiskLevel) -> List[ForeignDestination]:
        """Get all destinations with specified risk level

        Args:
            risk_level (RiskLevel): 

        """
        return [
            dest for dest in self.destinations.values() 
            if dest.risk_level == risk_level
        ]

    def get_destinations_by_region(self, region: str) -> List[ForeignDestination]:
        """Get all destinations in specified region

        Args:
            region (str): 

        """
        return [
            dest for dest in self.destinations.values() 
            if dest.region == region
        ]

get_destination(name)

Get destination by name

Parameters:

Name Type Description Default
name str
required
Source code in june/groups/travel/foreign_destination.py
105
106
107
108
109
110
111
112
def get_destination(self, name: str) -> Optional[ForeignDestination]:
    """Get destination by name

    Args:
        name (str): 

    """
    return self.destinations.get(name)

get_destinations_by_region(region)

Get all destinations in specified region

Parameters:

Name Type Description Default
region str
required
Source code in june/groups/travel/foreign_destination.py
126
127
128
129
130
131
132
133
134
135
136
def get_destinations_by_region(self, region: str) -> List[ForeignDestination]:
    """Get all destinations in specified region

    Args:
        region (str): 

    """
    return [
        dest for dest in self.destinations.values() 
        if dest.region == region
    ]

get_destinations_by_risk(risk_level)

Get all destinations with specified risk level

Parameters:

Name Type Description Default
risk_level RiskLevel
required
Source code in june/groups/travel/foreign_destination.py
114
115
116
117
118
119
120
121
122
123
124
def get_destinations_by_risk(self, risk_level: RiskLevel) -> List[ForeignDestination]:
    """Get all destinations with specified risk level

    Args:
        risk_level (RiskLevel): 

    """
    return [
        dest for dest in self.destinations.values() 
        if dest.risk_level == risk_level
    ]

RiskLevel

Bases: IntEnum

Source code in june/groups/travel/foreign_destination.py
15
16
17
18
19
class RiskLevel(IntEnum):
    """ """
    LOW = 1
    MEDIUM = 2 
    HIGH = 3

TravelPurpose

Bases: IntEnum

Source code in june/groups/travel/foreign_destination.py
10
11
12
13
class TravelPurpose(IntEnum):
    """ """
    BUSINESS = 1
    LEISURE = 2