activitymodel
Occupant activity calendars for building energy simulation, built from the French time-use survey (INSEE Enquête Emploi du temps 2009-2010, PROGEDO-ADISP doi:10.13144/lil-0695).
activitymodel is a pure library: it never resolves a data path at import time
and never fetches data. It is used by three packages at three moments:
| moment | who imports it | what it does |
|---|---|---|
| dataset build (Snakemake, maintainers) | buildingdata pipeline |
activitymodel.pipeline.build_library turns the ADISP delivery into a diary library (four parquet tables) that buildingdata uploads to GCS |
| census dataset build | buildingdata pipeline / buildingmodel |
harmonise_census_individuals puts INSEE RP indcvi individuals in the same vocabulary the library was built with |
| simulation | building_eload |
assign_clusters + generate_calendar turn the occupants of a district into a year of 10-minute activity codes per occupant |
It replaces the two prototypes activity_clustering and
activity-occupant-association; doc/design.md records what was wrong with
them and why each part looks the way it does now.
Quick start
import polars as pl
import activitymodel as am
# 1. (pipeline) build the library from the survey files, once
from activitymodel.pipeline import LibraryBuildOptions, build_library
library = build_library("/data/edt2010", LibraryBuildOptions())
library.write("/data/buildingdata_pipeline/processed/activity_library")
# 2. (anywhere) load it back - buildingdata will serve the four tables
library = am.DiaryLibrary.read("/data/buildingdata_pipeline/processed/activity_library")
# 3. (simulation) harmonise census occupants and generate a year
occupants = am.harmonise_census_individuals(pl.read_parquet("indcvi_slice.parquet"))
occupants = occupants.with_row_index("occupant_id")
calendar = am.generate_calendar(library, occupants, year=2024, seed=42)
calendar.day_index.shape # (n_occupants, 366) int32 pointers into the day pool
codes = calendar.codes(0, 500) # (500, 52704) uint8, detailed activities, Europe/Paris clock
long = calendar.to_long(0, 500) # occupant-major polars frame with an Enum activity column
python -m activitymodel.pipeline /data/edt2010 out/ --weekday 16 --saturday 10 --sunday 10
What is in the box
activitymodel/
taxonomy.py the 24 detailed activities, their ACTPR codes, the coarser levels
(presence = building_eload's, macro, mid)
vocabulary.py shared socio-demographic categories, age bands, matching ladder
harmonise.py survey individuals / census individuals -> shared vocabulary
survey/ read the ADISP files, code the diaries (location and day-kind aware)
clustering.py one-hot + PCA + Ward (or weighted k-means), k-selection curves
library.py DiaryLibrary: the published dataset, its schema and validation
matching.py occupants -> (cluster_weekday, cluster_saturday, cluster_sunday)
calendar.py day sampling, French public holidays, AnnualCalendar
diagnostics/ activity profiles, matrix distances, association scores
pipeline.py build_library() and the command line
tests/ synthetic fixtures; `-m integration` runs on the real files
doc/
design.md gap analysis of the prototypes and the decisions taken
dataset_contract.md the four tables, their columns, dtypes and invariants
integration.md what changes in buildingdata, buildingmodel,
buildingcalibration and building_eload, in order
integration/ reference snippets for those changes
Measured on the real data (Paris, RP 2021, library 16/10/10 clusters)
| step | result |
|---|---|
| library build (26,056 diaries, Ward on 50 components) | 29 s wall |
assign_clusters on 663,781 occupants |
1.3 s; 95.3 % (weighted) matched at the finest level |
generate_calendar for 20,105 occupants, 2024 |
1.6 s, 28 MiB of day_index |
codes() for 500 occupant-years |
25 MiB, 0.01 s |
| total-variation distance, matched Paris weekday profile vs national weighted survey | 0.048 |
Install
uv venv --python 3.12 .venv
uv pip install -e ".[dev,survey,fast]"
.venv/bin/python -m pytest -q
Extras: survey (pandas, to read the Stata delivery), fast (fastcluster),
analysis (scikit-learn, matplotlib), dev.
Licence and data
Code: MIT. The survey is available on request from PROGEDO-ADISP and is not
redistributable; the diary library holds no survey row (days are detached from
people, people are aggregated into cells of at least five respondents). See
doc/dataset_contract.md.
Metadata
Release files for activitymodel 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| activitymodel-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Release files / activitymodel-0.2.0-py3-none-any.whl
| Download URL | activitymodel-0.2.0-py3-none-any.whl |
|---|---|
| Size | 46.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
60b5632e20d0f2ab66849768506ddf5e49e5fdd6775dc7e06f5fd26ab111804d
|
|
BLAKE2b-256 checksum How to use checksums |
ff1e36693c0728cf91720a392275b0465f2c35c20945d491649330c35ff06a32
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.30 {"installer":{"name":"uv","version":"0.9.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|