Skip to content

Commit 381b6f2

Browse files
committed
Progress on documentation
1 parent ae9bd58 commit 381b6f2

File tree

47 files changed

+414
-919052
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+414
-919052
lines changed

configuration/demos_config.toml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,17 @@ initialize_empty_tables = [
1717
"rebalanced_persons",
1818
"rebalanced_households"
1919
]
20+
modules = [
21+
"aging",
22+
"employment",
23+
"household_reorg",
24+
# "kids_moving_model",
25+
# "fatality_model",
26+
# "birth_model",
27+
# "education_model",
28+
# "household_rebalancing",
29+
# "update_income"
30+
]
2031

2132
# Data sources
2233
## Synthetic population data
@@ -33,7 +44,6 @@ filepath = "../data/custom_mpo_06197001_model_data.h5"
3344
h5_key = "households"
3445

3546
## Other static data tables
36-
## Hide it?
3747
[[tables]]
3848
file_type = "csv"
3949
table_name = "relational_adjustment_mapping"

demos/TODO.md

Lines changed: 0 additions & 161 deletions
This file was deleted.

demos/config.py

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,16 +44,23 @@ class MortalityModuleConfig(BaseModel):
4444
class BirthModuleConfig(BaseModel):
4545
calibration_procedure: Optional[CalibrationConfig] = None
4646

47+
class AgingModuleConfig(BaseModel):
48+
"""
49+
"""
50+
#: Age at which a person qualifies as senior
51+
senior_age: int = 65
52+
53+
4754
class DEMOSConfig(BaseModel):
4855
"""
4956
Global configuration for DEMOS. Individual fields in this class control the configuration of each module.
5057
"""
5158
random_seed: int
5259

53-
#: Last year of simulation
54-
forecast_year: int = 2020
5560
#: Year represented in synthetic population input
5661
base_year: int
62+
#: Last year of simulation
63+
forecast_year: int = 2020
5764
#: Path to DEMOS outputs
5865
output_dir: str = "../data/output"
5966
#: Name of output HDF5 file. Defaults to `demos_output_{forecast_year}.h5`.
@@ -66,19 +73,19 @@ class DEMOSConfig(BaseModel):
6673
inconsistent_persons_table_behavior: Literal["error", "fix", "ignore"] = "error"
6774
#: Name of tables to be initialized as empty
6875
initialize_empty_tables: list[str] = None
69-
70-
# region_code: str
71-
# calibrated_folder: str = "custom"
7276

7377
#: List of tables to be loaded into orca
74-
tables: list[DataSourceModel] = Field(default_factory=list)
78+
tables: Optional[list[DataSourceModel]] = None
79+
#: List of modules to be run
80+
modules: Optional[list[str]] = None
7581

7682
# Module-specific config
77-
employment_module_config: EmploymentModuleConfig
78-
mortality_module_config: MortalityModuleConfig
79-
birth_module_config: BirthModuleConfig
80-
hh_reorg_module_config: HHReorgModuleConfig
81-
hh_rebalancing_module_config: HHRebalancingModuleConfig
83+
aging_module_config: AgingModuleConfig = Field(default_factory=AgingModuleConfig)
84+
employment_module_config: EmploymentModuleConfig = Field(default_factory=EmploymentModuleConfig)
85+
hh_reorg_module_config: HHReorgModuleConfig = Field(default_factory=HHReorgModuleConfig)
86+
mortality_module_config: MortalityModuleConfig = Field(default_factory=MortalityModuleConfig)
87+
birth_module_config: BirthModuleConfig = Field(default_factory=BirthModuleConfig)
88+
hh_rebalancing_module_config: HHRebalancingModuleConfig = Field(default_factory=HHRebalancingModuleConfig)
8289

8390
def model_post_init(self, __context) -> None:
8491
if self.output_fname is None:
@@ -99,6 +106,19 @@ def model_post_init(self, __context) -> None:
99106
for n in self.initialize_empty_tables:
100107
orca.add_table(n, pd.DataFrame())
101108

109+
if self.modules is None:
110+
self.modules = [
111+
"aging",
112+
"laborforce_model",
113+
"households_reorg",
114+
"kids_moving_model",
115+
"fatality_model",
116+
"birth_model",
117+
"education_model",
118+
"household_rebalancing",
119+
"update_income"
120+
]
121+
102122

103123
@model_validator(mode='after')
104124
def require_persons_and_households(self):
@@ -113,4 +133,6 @@ def load_config_file(dir: str) -> DEMOSConfig:
113133

114134
def get_config():
115135
global CONFIG
136+
if CONFIG is None:
137+
CONFIG = DEMOSConfig()
116138
return CONFIG

demos/datasources.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77

88
class CSVTableSource(BaseModel):
9+
""""""
910
file_type: Literal['csv']
1011
#: Path to source file
1112
filepath: str
@@ -26,7 +27,9 @@ def load_into_orca(self):
2627

2728

2829
class H5TableSource(BaseModel):
30+
""""""
2931
file_type: Literal['h5']
32+
#: Path to source file
3033
filepath: str
3134
#: key in the source HDF5 to be loaded
3235
h5_key: str

demos/logging_logic.py

Lines changed: 20 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,29 @@
11
import orca
22
import time
33
import pandas as pd
4-
import logging
5-
import inspect
64
from loguru import logger
5+
import sys, contextlib
76

8-
class InterceptHandler(logging.Handler):
9-
def __init__(self, target_name: str, prefix: str):
10-
super().__init__()
11-
self.target_name = target_name
12-
self.prefix = prefix
13-
14-
def emit(self, record: logging.LogRecord) -> None:
15-
# 1. map stdlib level to Loguru level
16-
try:
17-
level = logger.level(record.levelname).name
18-
except ValueError:
19-
level = record.levelno
20-
21-
# 2. compute correct stack depth so Loguru shows your caller, not the Handler
22-
frame, depth = inspect.currentframe(), 2
23-
while frame and frame.f_code.co_filename == logging.__file__:
24-
frame = frame.f_back
25-
depth += 1
26-
27-
# 3. optionally tag or prefix messages from your library
28-
msg = record.getMessage()
29-
if record.name == self.target_name:
30-
msg = f"{self.prefix} {msg}"
31-
32-
# 4. re-emit through Loguru
33-
logger.opt(depth=depth, exception=record.exc_info).log(level, msg)
34-
35-
def capture_orca_logs():
36-
LIB_NAME = "orca.orca"
37-
PREFIX = "[ORCA]"
38-
handler = InterceptHandler(target_name=LIB_NAME, prefix=PREFIX)
39-
40-
lib_logger = logging.getLogger(LIB_NAME)
41-
lib_logger.handlers = [handler]
42-
lib_logger.propagate = False
437

8+
class _StdoutToLoguru:
9+
def __init__(self, level="INFO", prefix="[external] "):
10+
self.level = level
11+
self.prefix = prefix
12+
self._buf = ""
13+
14+
def write(self, msg):
15+
# buffer to handle partial writes / no trailing newline
16+
self._buf += msg
17+
while "\n" in self._buf:
18+
line, self._buf = self._buf.split("\n", 1)
19+
line = line.rstrip()
20+
if line:
21+
logger.opt(depth=1).log(self.level, f"{self.prefix}{line}")
22+
23+
def flush(self):
24+
if self._buf.strip():
25+
logger.opt(depth=1).log(self.level, f"{self.prefix}{self._buf.rstrip()}")
26+
self._buf = ""
4427

4528
def log_execution_time(start_time, year, module_name):
4629
now = time.time()

demos/models/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from .data_fix import *
2-
from .aging import *
3-
from .laborforce import *
2+
from .aging import REQUIRED_COLUMNS as AGING_COLUMNS
3+
from .employment import *
44
from .household_reorg import *
55
from .marriage import *
66
from .kids_moving import *

0 commit comments

Comments
 (0)