Aller au contenu

xyt_gps - inventaire initial des fonctions et parametres

Archive de conception

Cette page est une note de travail initiale. Elle peut contenir des noms prévus ou déplacés. Pour l'API actuelle à utiliser, voir API Python et les guides de démarrage.

Date : 2026-06-09

Positionnement recommande

Le packaging est possible et pertinent, a condition de partir d'un perimetre resserre :

  1. xyt_gps doit d'abord automatiser le pipeline Declic actuel, fonde sur des exports GPS structurés deja structures.
  2. Le vieux package xyt peut fournir des idees, des fonctions utilitaires et des tests synthetiques, mais ne doit pas etre repris tel quel.
  3. La detection complete depuis des points GPS bruts non segmentes doit rester hors MVP, car le pipeline actuel part surtout de Storyline, Trips, Journeys et UserStatistics.

Éléments récupérables depuis archive/legacy-code/xyt-main-archive

Module archive Elements utiles Statut pour xyt_gps
fake_data_generator.py generation de legs, staypoints, waypoints synthetiques utile pour tests, a simplifier et rendre deterministe
gps_data_processor.py lissage, distance haversine, segmentation, detection de modes hors MVP Declic ; garder comme reference si on traite un jour des points bruts
gps_data_privacy.py obfuscation, agregation spatio-temporelle, utility metric module optionnel futur privacy
gps_analytics.py verify_columns, split overnight, clustering de lieux, metriques journalières certaines idees utiles, mais a refactoriser fortement
gps_to_graph.py graphes de motifs de mobilite module analytique futur, pas dans WP1/WP2 MVP
gps_to_actionspace.py espaces d'action, ellipses, covariance module analytique futur, pas dans MVP
xyt_plot.py carte Folium à fusionner plus tard avec archive/legacy-code/xyt_dynamite/xyt_to_map.py si nécessaire

Objets de configuration

ProjectConfig

Parametres :

Parametre Type Defaut propose Role
experiment_name str aucun nom analytique de l'etude
provider str "motiontag" fournisseur des exports
provider_project_name str aucun nom dans les fichiers MotionTag
period_start date aucun debut de periode d'import
period_end date aucun fin de periode d'import
timezone str "Europe/Zurich" fuseau local
raw_dir Path aucun dossier des exports bruts
work_dir Path "work" sorties intermediaires
export_dir Path "exports" livrables
target_crs str "EPSG:4326" CRS final
metric_crs str "EPSG:2056" CRS pour distances metriques
phase_dates dict[str, tuple[date, date]] {} phases avant, pendant, apres
tracking_thresholds TrackingThresholds seuils package jours minimum par phase et suivi total minimal
spatial_quality_thresholds SpatialQualityThresholds seuils package points aberrants, perte de signal, outliers par quantile
matching_thresholds MatchingThresholds seuils package tolerance de matching temporel et parametres map-matching
paths GpsExportPaths | None None chemins explicites si detection automatique impossible
external_geodata ExternalGeodataConfig | None None cantons, pays, zones excursions
sociodemo_path Path | None None donnees sociodemographiques
mappings MobilityMappings via mode_purpose_mapping() mappings package modes et motifs par source/table/niveau
save_intermediate bool False ecrire les etapes internes
overwrite bool False ecraser les sorties existantes

TrackingThresholds

Parametres :

Parametre Type Defaut propose Role
min_days_by_phase Mapping[str, int] {} seuils par phase, a definir selon le protocole
min_total_tracked_days int 7 seuil minimal livre dans le contexte Declic prefiguration
round_to_full_weeks bool True arrondir aux semaines completes

SpatialQualityThresholds

Parametres :

Parametre Type Defaut propose Role
max_consecutive_point_distance_m float | None None seuil de saut GPS aberrant, a completer par projet
max_relative_signal_loss float | None None seuil de perte de signal relative, a completer par projet
outlier_quantiles_by_mode tuple[float, ...] (0.98, 0.99) quantiles Q98 et Q99 par mode

MatchingThresholds

Parametres :

Parametre Type Defaut propose Role
leg_trip_journey_tolerance str "5s" tolerance temporelle pour les jointures legs/trips/journeys
osrm_max_points_per_chunk int 99 taille maximale des chunks OSRM
google_directions_fallback bool False fallback Google Directions desactive par defaut

RawSampleConfig

Parametres :

Parametre Type Defaut propose Role
mode "users" ou "rows" aucun strategie d'echantillonnage
n int aucun nombre d'utilisateurs ou de lignes par table
random_state int | None 42 reproductibilite du tirage
chunksize int 100_000 taille de lecture CSV pour by_users sur gros exports
user_id_column str "user_id" colonne identifiant personne, ou IDNO selon source
user_statistics_id_column str "id" colonne identifiant dans UserStatistics
storyline_type_column str "type" colonne permettant d'identifier les Track
track_type_value str "Track" valeur de type correspondant aux legs

Constructeurs pratiques :

xyt.RawSampleConfig.by_users(5, random_state=42, chunksize=100_000)
xyt.RawSampleConfig.random_rows(1000, random_state=42)

by_users lit d'abord les identifiants depuis storyline, puis filtre les CSV par chunks. random_rows reste un echantillonnage en memoire, utile pour inspecter rapidement le format mais moins coherent relationnellement.

mode_purpose_mapping() / MobilityMappings

mode_purpose_mapping() est le constructeur recommandé dans les notebooks. Il retourne une dataclass MobilityMappings.

Parametres :

Parametre Role
storyline_purpose_niv1 mapping des motifs des lignes Stay dans storyline
storyline_mode_niv1 agregation niveau 1 des modes MotionTag Mode::*
storyline_mode_niv2 agregation niveau 2 des modes MotionTag Mode::*
storyline_mode_mrmt nomenclature compatible MRMT pour les modes MotionTag
trip_purpose_mrmt mapping des motifs Trips / Journeys
trip_mode_niv1 agregation niveau 1 des modes Trips / Journeys
trip_mode_niv2 agregation niveau 2 des modes Trips / Journeys
trip_mode_mrmt nomenclature compatible MRMT pour Trips / Journeys
default_mode categorie de repli pour un mode inconnu
default_purpose categorie de repli pour un motif inconnu

Fonctions publiques MVP

Convention de nommage

Les noms publics doivent décrire l'objet produit ou l'action métier, pas l'implémentation interne.

Exemples :

Préférer Éviter Raison
build_user_selection_table() build_user_filter_matrix() l'utilisateur lit une table de sélection avant de filtrer ; "matrix" décrit mal l'usage
filter_mobility_dataset_by_users() filter_all_tables() le périmètre et la clé de filtrage sont explicites
add_signal_quality_flags() signal_quality() la fonction ajoute des colonnes de décision, pas seulement un calcul

Un ancien nom peut rester temporairement comme alias si un exemple ou un notebook l'a déjà utilisé, mais la documentation doit privilégier le nom le plus lisible.

Import

infer_gps_export_paths(config: ProjectConfig) -> GpsExportPaths
load_gps_export(config: ProjectConfig, *, sample: RawSampleConfig | None = None, validate: bool = True, must_exist: bool = True) -> RawGpsData
load_sample_gps(path: Path | None = None, *, user_id: str = "sample_user", max_rows: int | None = None) -> RawGpsData
load_gps_source(config: ProjectConfig, *, sample: RawSampleConfig | None = None, namespace_ids: bool = True) -> RawGpsData
load_gps_sources(configs: list[ProjectConfig], *, sample: RawSampleConfig | None = None, namespace_ids: bool = True) -> RawGpsData
concat_raw_gps_data(raws: list[RawGpsData]) -> RawGpsData
load_sociodemo(path: Path, *, user_id_col: str = "user_id") -> pd.DataFrame
load_external_geodata(config: ProjectConfig) -> ExternalGeodata

Parametres importants :

Fonction Parametres
load_gps_export config.csv_sep, sample, validate, must_exist
load_sample_gps path, user_id, max_rows, validate
load_gps_sources configs, namespace_ids, validate, must_exist, sample
infer_gps_export_paths provider_project_name, period_start, period_end, raw_dir, noms alternatifs StorylineWithTripId / StorylineWithUserAnnotations

Colonnes ajoutees lors d'un import multi-source :

Colonne Role
xyt_source_id identifiant stable de la source, construit a partir de experiment_name et period
experiment_name nom analytique de l'experimentation
motiontag_project_name nom du projet cote fournisseur GPS
period periode d'export
raw_id, raw_user_id, raw_trip_id identifiants originaux conserves avant namespacing

Validation

validate_columns(df: pd.DataFrame, required: list[str], *, dataset_name: str) -> None
validate_crs(gdf: gpd.GeoDataFrame, expected_crs: str, *, dataset_name: str) -> None
drop_nans_if_low_rate(df: pd.DataFrame, columns: list[str], *, threshold: float = 0.01) -> pd.DataFrame
validate_dataset(dataset: MobilityDataset, schema: MobilitySchema) -> ValidationReport

Parsing et harmonisation

parse_ewkb(value: str)
parse_date_columns(df: pd.DataFrame, columns: list[str], *, utc: bool = True) -> pd.DataFrame
assign_phase(value, phases: Iterable[Phase], *, default: str = "Other") -> str
mode_purpose_mapping(**kwargs) -> MobilityMappings
apply_storyline_mappings(storyline: pd.DataFrame, mappings: MobilityMappings) -> pd.DataFrame
apply_trip_journey_mappings(trips: pd.DataFrame, journeys: pd.DataFrame, mappings: MobilityMappings) -> tuple[pd.DataFrame, pd.DataFrame]

Préparation des données

prepare_storyline(storyline: pd.DataFrame, config: ProjectConfig) -> gpd.GeoDataFrame
prepare_trips(trips: pd.DataFrame, config: ProjectConfig) -> pd.DataFrame
prepare_journeys(journeys: pd.DataFrame, config: ProjectConfig) -> pd.DataFrame
prepare_mobility_dataset(raw: RawGpsData, config: ProjectConfig, **options) -> MobilityDataset
prepare_mobility_datasets(configs: list[ProjectConfig], *, sample: RawSampleConfig | None = None, namespace_ids: bool = True) -> MobilityDataset
concat_mobility_datasets(datasets: list[MobilityDataset]) -> MobilityDataset
split_storyline(storyline: gpd.GeoDataFrame) -> tuple[gpd.GeoDataFrame, gpd.GeoDataFrame]
clean_leg_geometries(legs: gpd.GeoDataFrame, *, drop_discontinuous: bool = True) -> gpd.GeoDataFrame
add_user_id_day(legs: pd.DataFrame) -> pd.DataFrame
build_track_trip_journey_map(legs, trips, journeys, *, tolerance: str = "5s") -> pd.DataFrame
build_legs_staypoints_map(legs, staypoints, *, tolerance: str = "5s") -> pd.DataFrame
build_user_stats(storyline: pd.DataFrame, config: ProjectConfig, *, user_statistics=None, sociodemo=None, weights=None, weight_col: str = "weight", default_weight: float = 1.0) -> pd.DataFrame
add_excursion_stats_to_user_stats(user_stats: pd.DataFrame, legs: pd.DataFrame, *, excursion_col: str = "excursion") -> pd.DataFrame

Qualite GPS et nettoyage spatial

calculate_user_tracking_stats(storyline: pd.DataFrame) -> pd.DataFrame
resample_missing_stays(storyline: gpd.GeoDataFrame, config: ProjectConfig) -> tuple[gpd.GeoDataFrame, pd.DataFrame]
calculate_tracking_periods(user_stats: pd.DataFrame, config: ProjectConfig) -> pd.DataFrame
flag_tracking_quality(user_stats: pd.DataFrame, config: ProjectConfig) -> pd.DataFrame
build_tracking_quality_report(user_stats: pd.DataFrame) -> pd.DataFrame
select_valid_tracking_users(user_stats: pd.DataFrame) -> pd.Index
build_user_selection_table(user_stats: pd.DataFrame, *, require_tracking_quality: bool = False, exclude_bad_signal_users: bool = True, max_low_quality_legs_share: float | None = None) -> pd.DataFrame
select_analysis_users(selection_table: pd.DataFrame, *, quality_column: str = "analysis_user_ok") -> pd.Index
filter_table_by_users(df: pd.DataFrame, user_ids, *, user_id_column: str = "user_id") -> pd.DataFrame
filter_mobility_dataset_by_users(dataset: MobilityDataset, user_ids) -> MobilityDataset
clean_leg_geometries(legs: gpd.GeoDataFrame, *, drop_discontinuous: bool = True) -> gpd.GeoDataFrame
add_signal_loss_metrics(legs: gpd.GeoDataFrame, config: ProjectConfig) -> gpd.GeoDataFrame
flag_low_quality_legs_by_mode(legs: gpd.GeoDataFrame, config: ProjectConfig, *, mode_col: str | None = None) -> gpd.GeoDataFrame
add_signal_quality_flags(legs: gpd.GeoDataFrame, config: ProjectConfig, *, mode_col: str | None = None) -> gpd.GeoDataFrame
add_signal_quality_to_user_stats(user_stats: pd.DataFrame, legs: pd.DataFrame, *, signal_quality_computed: bool | None = None) -> pd.DataFrame
identify_bad_signal_users(legs: gpd.GeoDataFrame, *, quantile_threshold: float = 0.995) -> pd.Index
add_spatial_zone_labels(table: pd.DataFrame, zones, *, zone_label_col: str, output_col: str) -> gpd.GeoDataFrame
add_leg_origin_destination_zones(legs: pd.DataFrame, zones, *, zone_label_col: str) -> gpd.GeoDataFrame
classify_leg_relation_to_area(legs: pd.DataFrame, *, area=None, area_path=None, center=None, radius_m=None) -> gpd.GeoDataFrame
add_trip_origin_destination_from_legs(trips, legs, map_track_trip_journey) -> pd.DataFrame
add_journey_origin_destination_from_trips(journeys, trips, map_track_trip_journey) -> pd.DataFrame

Filtres

filter_users_by_tracking(user_stats, *, min_days: dict[str, int]) -> pd.DataFrame
filter_legs(legs, user_stats, *, filters: FilterConfig) -> gpd.GeoDataFrame
build_filter_report(before, after, *, rules: FilterConfig) -> FilterReport

Parametres de FilterConfig :

Parametre Role
min_unique_days exclure suivis trop courts
min_coverage_ratio exclure couverture temporelle faible
min_segments_per_day exclure activite GPS insuffisante
exclude_bad_signal_users retirer utilisateurs a mauvais signal
exclude_low_quality_legs retirer legs signales
exclude_airplane retirer avion
outlier_rule None, quantile_98, quantile_99
territory None, "GE", "VD", "panel"
include_visitors inclure visiteurs non residents

Enrichissements

add_co2_occupancy_metrics(legs, *, journeys=None, map_track_trip_journey=None, config=None, mode_col="mode", distance_col=None, journey_purpose_col="main_purpose_mrmt", prefer_observed_occupancy=None, occupancy_col=None) -> pd.DataFrame
add_health_metrics(legs, *, health_config: HealthConfig) -> pd.DataFrame
map_match_osrm(legs, *, osrm_config: OSRMConfig) -> gpd.GeoDataFrame
map_match_google(legs, *, google_config: GoogleDirectionsConfig) -> gpd.GeoDataFrame

Parametres :

Config Parametres
CO2OccupancyConfig factors_g_per_km, occupancy_by_distance_and_purpose, default_occupancy, car_modes, apply_occupancy_to_car_modes, prefer_observed_occupancy, occupancy_col
HealthConfig weight_kg, walk_speed_thresholds, bike_speed_thresholds, mets_by_mode_intensity
OSRMConfig base_url_by_mode, profile_by_mode, max_points, request_timeout, retry_count, enabled
GoogleDirectionsConfig api_key, mode_by_motiontag_mode, request_timeout, retry_count, cost_guard_max_requests, enabled

Indicateurs de mobilité

build_person_day_indicators(dataset: MobilityDataset, *, mode_col: str = "mode_niv1", trips_mode_col: str | None = None, distance_col: str | None = None, include_zero_days: bool = True, include_excursions: bool = True, include_airplane: bool = False, config: ProjectConfig | None = None) -> pd.DataFrame
build_person_phase_indicators(person_day: pd.DataFrame, *, user_stats: pd.DataFrame | None = None, weight_col: str = "weight") -> pd.DataFrame
build_population_indicators(person_phase: pd.DataFrame, *, use_weights: bool = True, weight_col: str = "weight") -> pd.DataFrame
compute_mobility_indicators(dataset: MobilityDataset, *, mode_col: str = "mode_niv1", trips_mode_col: str | None = None, distance_col: str | None = None, include_zero_days: bool = True, include_excursions: bool = True, include_airplane: bool = False, use_weights: bool = True, weight_col: str = "weight", config: ProjectConfig | None = None) -> IndicatorResult
population_indicator_summary(indicators: IndicatorResult | pd.DataFrame) -> pd.DataFrame

Indicateurs initiaux :

Indicateur Unite Source Methode
distance_km km legs somme journaliere par mode, moyenne phase
travel_time_min min legs somme journaliere par mode, moyenne phase
trip_count nombre trips somme journaliere par mode principal, moyenne phase
leg_count nombre legs nombre d'étapes journalier par mode, moyenne phase
co2 kg futur module CO2 somme journaliere par mode, moyenne phase
co2_direct kg futur module CO2 somme journaliere par mode, moyenne phase
calories kcal futur module santé somme journaliere par mode, moyenne phase
mets METs futur module santé moyenne journaliere par mode, moyenne phase

Tables produites par compute_mobility_indicators() :

Table Grain Role
person_day utilisateur, date, phase, mode table de contrôle et de comparaison avec les notebooks
person_phase utilisateur, phase, mode moyenne journalière par utilisateur
population phase, mode synthèse population avec n_users

IndicatorResult.metadata conserve les options de calcul et quelques ordres de grandeur : nombre d’utilisateurs, jours-utilisateurs, nombre moyen d’étapes par jour-utilisateur, prise en compte des excursions, filtrage préalable, jours sans déplacement et pondération.

Export

write_mobility_dataset(dataset: MobilityDataset, output_dir: Path, *, formats: tuple[str, ...] = ("csv", "geojson"), extra_tables: Mapping[str, pd.DataFrame] | None = None, selection_table: pd.DataFrame | None = None) -> pd.DataFrame
export_mobility_tables(...) -> pd.DataFrame
write_indicator_result(indicators: IndicatorResult, output_dir: Path, *, formats: tuple[str, ...] = ("parquet", "csv")) -> pd.DataFrame

Formats pris en charge par write_mobility_dataset() : csv, geojson, parquet, pickle ou pkl, xlsx.

extra_tables permet d'écrire des tables de construction comme user_presence, participation_grid ou participation_summary sans modifier la structure de MobilityDataset.

Exports spatiaux pour dashboard

add_time_slices(table, *, time_slices=None, datetime_col="started_at", output_col="time_slice", timezone="Europe/Zurich") -> pd.DataFrame
legs_to_h3_points(legs, *, h3_resolution=9, sample_distance_m=None, max_points_per_leg=None) -> gpd.GeoDataFrame
aggregate_h3_frequencies(h3_points, *, group_cols=None) -> pd.DataFrame
build_h3_count_matrix(h3_points, *, dimension_sets=..., metrics=("point_count", "trip_count")) -> pd.DataFrame
build_spatial_analytics_tables(dataset_or_legs, *, h3_resolution=9, config=None, frequency_group_cols=None, count_dimension_sets=..., count_metrics=("point_count", "trip_count")) -> dict[str, pd.DataFrame]
write_spatial_analytics_tables(tables, output_dir, *, formats=("parquet", "csv")) -> pd.DataFrame
write_spatial_analytics_exports(dataset_or_legs, output_dir, *, h3_resolution=9, frequency_group_cols=None, sample_distance_m=None, formats=("parquet", "csv")) -> pd.DataFrame
write_duckdb_spatial_database(tables, database_path, *, load_spatial=True, require_spatial_extension=False) -> pd.DataFrame

Ces fonctions sont optionnelles et nécessitent requirements-analytics.txt pour H3 ou DuckDB. add_time_slices() ajoute les périodes HPM, HC, HPS ou des tranches horaires propres au projet. legs_to_h3_points() extrait les sommets des géométries de legs, ou échantillonne les lignes si sample_distance_m est défini. build_h3_count_matrix() produit une table large avec des colonnes de counts par mode, motif et tranche horaire. Le résultat sert à produire des cartes de fréquentation par cellule H3. GeoParquet reste le format recommandé pour conserver les tables, tandis que DuckDB sert aux requêtes SQL locales et aux prototypes de dashboard.

Visualisation de contrôle

plot_gps_traces(dataset_or_legs, *, staypoints=None, user_ids=None, sample_n=None, color_by="mode_niv1", save_path=None)
plot_h3_frequency_map(h3_frequency, *, h3_col="h3_cell", value_col="point_count", max_cells=2500, save_path=None)

Ces fonctions sont des outils d'inspection notebook. Elles dépendent de l'extra optionnel viz et ne font pas partie du pipeline obligatoire. plot_h3_frequency_map() dépend aussi de h3, donc de requirements-analytics.txt.

Formats initiaux :

Donnee Format interne Format livrable
legs Parquet GeoJSON
staypoints Parquet GeoJSON
trips Parquet CSV
journeys Parquet CSV
user_stats CSV ou Parquet CSV
occupancy_co2 Parquet CSV
health Parquet CSV
public_transport Parquet CSV
leg_points_h3 GeoParquet CSV ou DuckDB
h3_frequency Parquet CSV ou DuckDB
dictionnaire variables Parquet optionnel XLSX

Fonctions a differer

Ces fonctions sont utiles mais ne doivent pas bloquer le packaging initial :

generate_synthetic_declic_gps(...)
obfuscate_locations(...)
aggregate_privacy_grid(...)
split_overnight_staypoints(...)
cluster_activity_locations(...)
build_mobility_graphs(...)
compute_action_space(...)
plot_gps(...)
plot_action_space(...)

API publique courte visee

import xyt_gps as xyt

config = xyt.ProjectConfig(...)
raw = xyt.load_gps_export(config)
mobility = xyt.prepare_mobility_dataset(raw, config)
indicators = xyt.compute_mobility_indicators(mobility, mode_col="mode_niv2")
xyt.write_mobility_dataset(mobility, "Data/Output/2-transformed-data", formats=["parquet", "csv"])
xyt.write_indicator_result(indicators, "Data/Output/3-enriched-data", formats=["csv", "parquet"])