Python API Docs#
- routee.powertrain.io.load.list_available_models(registry: ModelRegistry | None = None, version_strategy: Literal['latest', 'all'] = 'latest') List[ModelId][source]#
Returns a list of model identifiers available in the registry.
This is a lightweight operation that returns only the model paths without fetching any metadata or binaries.
If no registry is provided, the default registry is used.
- Parameters:
registry -- a ModelRegistry instance; defaults to get_default_registry()
version_strategy --
"latest"(default) returns only the highest version per (make, model, year, config_slug) group;"all"returns every versioned identifier.
Returns: list of ModelId matching the strategy
- routee.powertrain.io.load.load_model(name_or_path: str | Path | ModelId, registry: ModelRegistry | None = None) Model[source]#
Load a pretrained model.
Supports two loading modes:
File path — pass a
Pathor string pointing to a model directory (containingmetadata.json),.ziparchive, or.tar.gzarchive on disk.Registry ModelId — pass a
ModelIdobject or model id path to fetch from a registry (uses the default registry if none is provided). String paths may omit thev<N>segment to load the latest version.
- Parameters:
name_or_path -- file/directory path or ModelId
registry -- optional ModelRegistry for remote loading
Returns: a routee-powertrain Model
Examples:
>>> import routee.powertrain as pt >>> >>> # load from a directory >>> model = pt.load_model("path/to/my_model/") >>> >>> # load from a zip >>> model = pt.load_model("MyModel.zip") >>> >>> # load via registry >>> from routee.powertrain.registry import ModelId >>> mid = ModelId("toyota", "camry", 2016, "rf_default", 1) >>> model = pt.load_model(mid) >>> >>> # explicit version >>> model = pt.load_model("toyota/camry/2016/rf_default/v1") >>> >>> # latest version (no version segment) >>> model = pt.load_model("toyota/camry/2016/rf_default")
- routee.powertrain.io.load.load_sample_route(name: str | None = None) DataFrame[source]#
A helper function to load sample routes
- Parameters:
name -- The name of the route. Defaults to "sample_route".
Returns: a pandas DataFrame representing the route
- routee.powertrain.io.load.query_available_models(make: str | None = None, model: str | None = None, year: int | None = None, config_slug: str | None = None, feature_names: Sequence[str] | None = None, powertrain_type: str | None = None, fuel_type: str | None = None, drivetrain: str | None = None, engine: str | None = None, trim: str | None = None, version: int | None = None, model_digest: str | None = None, version_strategy: Literal['latest', 'all'] = 'latest', custom_filters: Sequence[Callable[[ModelInfo], bool]] | None = None, registry: ModelRegistry | None = None, fuzzy: bool = True, fuzzy_threshold: int = 80) List[ModelInfo][source]#
Query available pretrained models from the registry with optional filters.
Returns full metadata and error metrics for each matching model. If no registry is provided, the default registry is used.
- Parameters:
make -- filter by vehicle make
model -- filter by vehicle model — matches the bare metadata model name (e.g. "camry") or the derived vehicle_slug (e.g. "camry_ice")
year -- filter by model year
config_slug -- filter by config slug (e.g. "rf_default", "cnn_5link")
feature_names -- filter to models whose feature set contains every listed feature column (subset match, exact names)
powertrain_type -- filter by powertrain type (e.g. "ICE", "BEV", "HEV")
fuel_type -- filter by fuel type (e.g. "GASOLINE", "DIESEL", "ELECTRICITY")
drivetrain -- filter by drivetrain (e.g. "FWD", "RWD", "AWD")
engine -- filter by engine specification (e.g. "4cyl", "2.0tdi")
trim -- filter by trim level (e.g. "sport", "active")
version -- pin results to an exact version (e.g. 2). When set,
version_strategyis ignored.model_digest -- pin results to an exact instance identity — the
model_digestfrom a model'smetadata.json(with or without thesha256:prefix; always matched exactly). Use this to resolve a model file in hand back to its registry entry. When set,version_strategyis ignored.version_strategy -- how to collapse multiple versions of the same model.
"latest"(default) keeps only the highest version per (make, model, year, config_slug) group;"all"returns every version. Ignored whenversionis specified.custom_filters -- optional list of callables that accept a ModelInfo and return True to keep the model or False to exclude it. For example:
[lambda m: m.mass_lbs is not None and m.mass_lbs > 10000]registry -- a ModelRegistry instance; defaults to get_default_registry()
fuzzy -- if True, use fuzzy string matching for string fields (default True)
fuzzy_threshold -- minimum score (0–100) for a fuzzy match (default 80)
Returns: list of ModelInfo with full metadata and error metrics
- class routee.powertrain.core.model.Model(estimator: Estimator, metadata: Metadata)[source]#
A RouteE-Powertrain vehicle model represents a single vehicle (i.e. a 2016 Toyota Camry with a 1.5 L gasoline engine).
- contour(x_feature: str, y_feature: str, n_samples: int | None = 100, output_path: str | None = None)[source]#
generates a contour plot of the two test features: x_feature and y_feature.
- Parameters:
x_feature -- one of the features used to generate the energy matrix and will be the x-axis feature
y_feature -- one of the features used to generate the energy matrix and will be the y-axis feature
n_samples -- the number of samples used to generate the plots
output_path -- an optional path to save the plots as png files.
- property digest: str | None#
This model's registry-independent instance identity.
The
sha256:<hex>content digest minted at train time (seeroutee.powertrain.core.digest). Unlikekey, which groups all retrains of the same configuration, the digest is unique per trained artifact — two models trained the same day on different data get distinct digests.Nonefor legacy models saved before digests existed.
- classmethod from_file(file: str | Path)[source]#
Load a vehicle model from a file or directory.
Supports directories (containing metadata.json + binary), .zip archives, and .tar.gz archives.
- Parameters:
file -- the path to the file or directory to load
Returns: a powertrain vehicle
- property key: ModelKey#
This model's intrinsic, version-less identity.
Derived from metadata (
make/model/year+ the derivedconfig_slug), so it is always available — even for a freshly-trained model that has never been placed in a registry. The registryversionis not part of this; it is assigned only by registry operations (save_to_registryreturns a fullModelId).
- predict(links_df: DataFrame) DataFrame[source]#
Predict absolute energy consumption for each link
- Parameters:
links_df -- a dataframe containing the links to predict on. Must contain every column in
self.feature_setplus the distance column, and (if the estimator'sinput_specdeclares a grouping column) that grouping column.
Returns: a dataframe containing the predicted energy consumption for each link
- save_to_registry(registry_root: str | Path, config_slug: str | None = None, version: int | None = None, schema_version: str = 'v2', overwrite: bool = False)[source]#
Save this model into a local registry directory tree.
Builds the canonical
<registry_root>/<schema_version>/<make>/<model>/<year>/<config_slug>/v<N>/layout fromself.metadata.config. Theconfig_slugis derived from metadata unless overridden, andversiondefaults to the next unused version. Seeroutee.powertrain.io.archive.save_to_registryfor full details.Returns: the
ModelIdthat was written.
- to_file(file: str | Path)[source]#
Save a vehicle model to a file or directory.
If file has no suffix, saves as a flat directory. If it ends with
.zip, saves as a ZIP archive. If it ends with.tar.gz, saves as a tar archive.- Parameters:
file -- the path to save to
- to_lookup_table(feature_parameters: list[dict], energy_target: str) DataFrame[source]#
Convert the the model to a lookup table for the given feature parameters.
- visualize_features(n_samples: int | None = 100, output_path: str | None = None, return_predictions: bool | None = False) Dict[str, 'Series'] | None[source]#
generates test links to independently test the model's features and creates plots of those predictions
- Parameters:
n_samples -- the number of samples used to generate the plots
output_path -- an optional path to save the plots as png files.
return_predictions -- if true, returns the dictionary containing the prediction values
Returns: optionally returns a dictionary containing the predictions where the key is the feature tested
- class routee.powertrain.core.model_config.Contract(*, feature_set: ~routee.powertrain.core.features.FeatureSet, distance: ~routee.powertrain.core.features.DataColumn, target: ~routee.powertrain.core.features.TargetSet, predict_method: ~routee.powertrain.core.predict_method.Annotated[~routee.powertrain.core.predict_method.PredictMethod, ~pydantic.functional_validators.BeforeValidator(func=~routee.powertrain.core.pydantic_fields._coerce_predict_method, json_schema_input_type=PydanticUndefined), ~pydantic.functional_serializers.PlainSerializer(func=~routee.powertrain.core.pydantic_fields.<lambda>, return_type=str, when_used=always)] = PredictMethod.RATE, real_world_adjustment_factor: float = 1.0)[source]#
A model's input/output contract — everything needed to interpret a prediction: the feature columns it consumes, the distance column, the energy target(s) it emits, how the raw estimator output maps to energy (
predict_method), and the real-world correction applied afterward.- model_config: ClassVar[ConfigDict] = {}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- real_world_adjustment_factor: float#
Multiplicative factor applied to predicted energy to correct for real-world conditions. Resolved on the source
ModelConfig(defaulting from the powertrain type) and stored concretely here.
- class routee.powertrain.core.model_config.FastSimSource(*, method: ~typing.Literal[TrainingMethod.FASTSIM_SIMULATION] = TrainingMethod.FASTSIM_SIMULATION, fastsim_vehicle_id: str | None = None, fastsim_vehicles_ref: str | None = None, fastsim_version: str | None = None, pipeline_version: str | None = None, pipeline_run_id: str | None = None, pipeline_repo_ref: str | None = None, dataset_run_ids: ~typing.List[str] = <factory>, data_sources: ~typing.List[str] = <factory>, notes: str | None = None)[source]#
Training data produced by simulating a FASTSim vehicle.
The standard path: a model pipeline runs drive cycles through FASTSim and trains on the resulting energy traces. Recording the vehicle, the simulator version, and the pipeline that drove them is what makes a published model reproducible.
The pipeline keeps its own provenance database, so this records keys, not copies.
pipeline_run_idanddataset_run_idsresolve there to the full configuration each run used — dataset filters, estimator settings, trip caps, the sampling seed, the identity of the assembled training frame, and everything else that would have to match to recreate the model. None of that is duplicated here: a copy drifts from the source of truth and can't be verified against it, while a key can't drift.What remains alongside the keys describes what was simulated rather than how the training data was assembled — the vehicle, the simulator version, the pipeline version. Those are cheap, stable, and readable at a glance.
This assumes the provenance database is reachable whenever a model needs to be reproduced. That is a deliberate trade, and a cheap one to revisit: provenance is excluded from
model_digest, so a field added here later is non-breaking and can even be backfilled onto already-published models without changing their identity.- data_sources: List[str]#
Dataset sources the training data was drawn from (e.g.
["wm1"]). Usually one, but a run can be configured to sample across several (e.g.["wm1", "wm2"]).
- fastsim_vehicle_id: str | None#
//github.com/NatLabRockies/fastsim-vehicles (e.g.
"v1/fastsim-3/conv/toyota/camry-4cyl-2wd/2016/base/r1").- Type:
Vehicle identifier in https
- fastsim_vehicles_ref: str | None#
Git tag / commit sha pinning the
fastsim-vehiclesrepo the vehicle definition was read from.
- fastsim_version: str | None#
Version of the FASTSim package that ran the simulation.
- model_config: ClassVar[ConfigDict] = {}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- pipeline_repo_ref: str | None#
Git commit sha of the pipeline repo at run time.
- pipeline_version: str | None#
Version of the model pipeline that orchestrated simulation and training.
- class routee.powertrain.core.model_config.LegacySource(*, method: Literal[TrainingMethod.LEGACY] = TrainingMethod.LEGACY, original_source: str | None = None, converted_from: str | None = None, dataset_name: str | None = None, dataset_hash: str | None = None, notes: str | None = None)[source]#
Provenance for models that predate this section.
Converted v1 archives record no simulator, pipeline, or dataset information — the honest answer is "we don't know", and this variant says so explicitly rather than leaving the source null.
- converted_from: str | None#
The format it was converted from (e.g.
"v1").
- dataset_hash: str | None#
Fingerprint of that data — see
routee.powertrain.hash_dataframe.
- dataset_name: str | None#
Human-readable identifier of the training data, when the pre-conversion format happened to record one.
- model_config: ClassVar[ConfigDict] = {}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- original_source: str | None#
Where the model came from before conversion (e.g. a library name).
- class routee.powertrain.core.model_config.ModelConfig(*, vehicle_description: str, powertrain_type: ~routee.powertrain.core.powertrain_type.Annotated[~routee.powertrain.core.powertrain_type.PowertrainType, ~pydantic.functional_validators.BeforeValidator(func=~routee.powertrain.core.pydantic_fields._coerce_powertrain, json_schema_input_type=PydanticUndefined), ~pydantic.functional_serializers.PlainSerializer(func=~routee.powertrain.core.pydantic_fields.<lambda>, return_type=str, when_used=always)], feature_set: ~routee.powertrain.core.features.FeatureSet, distance: ~routee.powertrain.core.features.DataColumn, target: ~routee.powertrain.core.features.TargetSet, make: str, model: str, year: ~typing.Annotated[int | tuple[int, int], ~pydantic.functional_validators.BeforeValidator(func=~routee.powertrain.core.year.parse_year, json_schema_input_type=PydanticUndefined)], variant: str | None = None, predict_method: ~routee.powertrain.core.predict_method.Annotated[~routee.powertrain.core.predict_method.PredictMethod, ~pydantic.functional_validators.BeforeValidator(func=~routee.powertrain.core.pydantic_fields._coerce_predict_method, json_schema_input_type=PydanticUndefined), ~pydantic.functional_serializers.PlainSerializer(func=~routee.powertrain.core.pydantic_fields.<lambda>, return_type=str, when_used=always)] = PredictMethod.RATE, test_size: float | None = None, validation_size: float | None = None, random_seed: int = 42, trip_column: str = 'trip_id', training_source: ~typing.Annotated[~routee.powertrain.core.provenance.FastSimSource | ~routee.powertrain.core.provenance.RealWorldSource | ~routee.powertrain.core.provenance.LegacySource, FieldInfo(annotation=NoneType, required=True, discriminator='method')] | None = None, real_world_adjustment_factor: float = 1.0, mass_lbs: float | None = None, fuel_type: ~routee.powertrain.core.fuel_type.Annotated[~routee.powertrain.core.fuel_type.FuelType, ~pydantic.functional_validators.BeforeValidator(func=~routee.powertrain.core.pydantic_fields._coerce_fuel_type, json_schema_input_type=PydanticUndefined), ~pydantic.functional_serializers.PlainSerializer(func=~routee.powertrain.core.pydantic_fields.<lambda>, return_type=str, when_used=always)] | None = None, drivetrain: ~routee.powertrain.core.drivetrain.Annotated[~routee.powertrain.core.drivetrain.Drivetrain, ~pydantic.functional_validators.BeforeValidator(func=~routee.powertrain.core.pydantic_fields._coerce_drivetrain, json_schema_input_type=PydanticUndefined), ~pydantic.functional_serializers.PlainSerializer(func=~routee.powertrain.core.pydantic_fields.<lambda>, return_type=str, when_used=always)] | None = None, engine: str | None = None, trim: str | None = None)[source]#
- property all_feature_names: List[str]#
Returns the list of feature names, including distance if predict method is RAW.
- property all_features: List[DataColumn]#
Returns the list of features, including distance if predict method is RAW.
- property feature_names: List[str]#
Returns the list of feature names from the feature set.
- model_config: ClassVar[ConfigDict] = {}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- real_world_adjustment_factor: float#
Multiplicative factor applied to predicted energy to correct for real-world conditions (e.g. temperature). Defaults to the powertrain-type factor in
ADJUSTMENT_FACTORS; set to1.0to apply no adjustment.
- training_source: TrainingSource | None#
What produced the training data — a
FastSimSource,RealWorldSource, orLegacySource. Carries the dataset labels (dataset_name/dataset_hash) alongside the source-specific fields. Stored in the persistedprovenancesection; descriptive, so it does not feed the model digest.
- variant: str | None#
Short label distinguishing configs that share the same architecture and feature set (e.g.
"steady"vs"warmup"thermal regimes). Feeds the derivedconfig_slug; leaveNonewhen no such distinction is needed.
- class routee.powertrain.core.model_config.Provenance(*, source: ~typing.Annotated[~routee.powertrain.core.provenance.FastSimSource | ~routee.powertrain.core.provenance.RealWorldSource | ~routee.powertrain.core.provenance.LegacySource, FieldInfo(annotation=NoneType, required=True, discriminator='method')] | None = None, training: ~routee.powertrain.core.provenance.TrainingConfig = <factory>)[source]#
Where a model came from and how it was built.
Two complementary answers:
source— what produced the training data (FASTSim simulation, real-world collection, or an unknown legacy origin), including the dataset labels for that data; andtraining— the hyperparameters the fit ran under.Deliberately excluded from
model_digest(seecore.digest). The estimator binary's sha256 already pins the exact data and hyperparameters a model was fit to, so making provenance identity-bearing would only make it uncorrectable — backfilling a FASTSim version onto a published model would change the model's identity.- property dataset_hash: str | None#
The training data's fingerprint, when the source records one.
Nonefor aFastSimSource, for the same reason asdataset_name, andNonewhen no source is set.
- property dataset_name: str | None#
The training dataset's label, when the source records one.
Nonefor aFastSimSource— simulated training data is described bydataset_run_idsagainst the pipeline's provenance database rather than by a label in the artifact — andNonewhen no source is set.
- property method: TrainingMethod | None#
The recorded training method, or
Nonewhen no source is set.
- model_config: ClassVar[ConfigDict] = {}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- source: TrainingSource | None#
What produced the training data.
Nonewhen nothing is recorded.
- class routee.powertrain.core.model_config.RealWorldSource(*, method: Literal[TrainingMethod.REAL_WORLD] = TrainingMethod.REAL_WORLD, data_source: str | None = None, fleet: str | None = None, collection_start: str | None = None, collection_end: str | None = None, n_vehicles: int | None = None, n_trips: int | None = None, dataset_name: str | None = None, dataset_hash: str | None = None, notes: str | None = None)[source]#
Training data collected from instrumented vehicles in the field.
- collection_start: str | None#
Collection window, as ISO
YYYY-MM-DDstrings.
- data_source: str | None#
Name of the data collection program or provider.
- dataset_hash: str | None#
Fingerprint of that data — see
routee.powertrain.hash_dataframe.
- dataset_name: str | None#
Human-readable identifier of the collected dataset the model was fit to.
- fleet: str | None#
Fleet the vehicles were drawn from, when the source spans several.
- model_config: ClassVar[ConfigDict] = {}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- n_vehicles: int | None#
Size of the underlying sample.
- class routee.powertrain.core.model_config.TrainingConfig(*, test_size: float | None = None, validation_size: float | None = None, random_seed: int = 42, trip_column: str = 'trip_id', trained_date: str | None = None)[source]#
Build-time hyperparameters — needed to reproduce training, not to use the model. Safe to drop from a shipped artifact without affecting prediction.
- model_config: ClassVar[ConfigDict] = {}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- trained_date: str | None#
Calendar date the model was trained, as an ISO
YYYY-MM-DDstring. Stamped at training time byTrainer.train;Nonewhen unknown (e.g. legacy models converted from the v1 format).
- class routee.powertrain.core.model_config.TrainingMethod(value)[source]#
How a model's training data was produced.
Doubles as the discriminator for the
TrainingSourceunion — each source variant pinsmethodto exactly one of these values.
- class routee.powertrain.core.model_config.Vehicle(*, vehicle_description: str, powertrain_type: ~routee.powertrain.core.powertrain_type.Annotated[~routee.powertrain.core.powertrain_type.PowertrainType, ~pydantic.functional_validators.BeforeValidator(func=~routee.powertrain.core.pydantic_fields._coerce_powertrain, json_schema_input_type=PydanticUndefined), ~pydantic.functional_serializers.PlainSerializer(func=~routee.powertrain.core.pydantic_fields.<lambda>, return_type=str, when_used=always)], make: str, model: str, year: ~typing.Annotated[int | tuple[int, int], ~pydantic.functional_validators.BeforeValidator(func=~routee.powertrain.core.year.parse_year, json_schema_input_type=PydanticUndefined)], variant: str | None = None, mass_lbs: float | None = None, fuel_type: ~routee.powertrain.core.fuel_type.Annotated[~routee.powertrain.core.fuel_type.FuelType, ~pydantic.functional_validators.BeforeValidator(func=~routee.powertrain.core.pydantic_fields._coerce_fuel_type, json_schema_input_type=PydanticUndefined), ~pydantic.functional_serializers.PlainSerializer(func=~routee.powertrain.core.pydantic_fields.<lambda>, return_type=str, when_used=always)] | None = None, drivetrain: ~routee.powertrain.core.drivetrain.Annotated[~routee.powertrain.core.drivetrain.Drivetrain, ~pydantic.functional_validators.BeforeValidator(func=~routee.powertrain.core.pydantic_fields._coerce_drivetrain, json_schema_input_type=PydanticUndefined), ~pydantic.functional_serializers.PlainSerializer(func=~routee.powertrain.core.pydantic_fields.<lambda>, return_type=str, when_used=always)] | None = None, engine: str | None = None, trim: str | None = None)[source]#
The vehicle a model describes — identity plus descriptive attributes.
make/model/year/variantfeed the derivedconfig_slugandModelKey; the remaining fields are descriptive and registry-filterable.- model_config: ClassVar[ConfigDict] = {}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class routee.powertrain.core.features.Constraints(*, lower: float | None = None, upper: float | None = None)[source]#
- model_config: ClassVar[ConfigDict] = {}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class routee.powertrain.core.features.DataColumn(*, name: str, units: str, dtype: str = 'float32', constraints: ~routee.powertrain.core.features.Constraints = <factory>)[source]#
- model_config: ClassVar[ConfigDict] = {}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class routee.powertrain.core.features.FeatureSet(*, features: List[DataColumn])[source]#
- property feature_name_list: List[str]#
Returns a list of feature names in the order they appear in the feature set.
Order is important since the underlying estimator might expect it.
- property features_id: str#
Returns a string that uniquely identifies this feature set. The names are sorted to provide a consistent id.
- model_config: ClassVar[ConfigDict] = {}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class routee.powertrain.core.features.TargetSet(*, targets: List[DataColumn])[source]#
- model_config: ClassVar[ConfigDict] = {}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- routee.powertrain.core.features.feature_id_to_names(feature_id: str) List[str][source]#
Returns a list of feature names from a feature set id.
- routee.powertrain.core.features.feature_names_to_id(feature_names: List[str]) str[source]#
Returns a string that uniquely identifies a feature set. The names are sorted to provide a consistent id.
- class routee.powertrain.core.metadata.EstimatorInfo(*, estimator_type: str, model_file: str, architecture_tag: str = 'unknown', input_spec: dict | None = None, estimator_sha256: str | None = None)[source]#
Describes the serialized estimator artifact: what to load and how to shape inputs. Everything a consumer needs to instantiate and run the binary, without cracking it open.
- architecture_tag: str#
Coarse architecture family (
"random_forest","cnn","ngboost"…). Used for registry-level filtering without parsingestimator_typestrings.
- estimator_sha256: str | None#
Bare lowercase-hex sha256 of the exact serialized estimator bytes (the file named by
model_file). A pure content address, stamped at train time and verified against the raw bytes on load.Nonefor legacy models saved before digests existed.
- input_spec: dict | None#
Serialized
Estimator.input_spec(lookback, grouping_column, pad_strategy). Allows a registry consumer to see lookback requirements before loading the binary.
- model_config: ClassVar[ConfigDict] = {}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class routee.powertrain.core.metadata.Metadata(*, vehicle: ~routee.powertrain.core.model_config.Vehicle, contract: ~routee.powertrain.core.model_config.Contract, estimator: ~routee.powertrain.core.metadata.EstimatorInfo, provenance: ~routee.powertrain.core.provenance.Provenance, errors: ~routee.powertrain.validation.errors.ModelErrors, routee_version: str = <factory>, schema_version: int = 2, model_digest: str | None = None)[source]#
Carries all model metadata that gets persisted alongside the estimator binary.
Serializes 1:1 with the
metadata.jsonfile inside a model archive. Fields are grouped by the job a reader needs them for:vehicle— the model's identity and descriptive attributescontract— the input/output contract needed to interpret a predictionestimator— how to load and run the serialized binaryprovenance— where the model came from and how it was builterrors— validation metrics
- property config: ModelConfig#
A flat
ModelConfigview reconstructed from the grouped sections.The identity/contract/provenance fields are stored decomposed, but many runtime consumers (estimators, error computation,
Model.predict) want the single flat object the model was trained from. This derives it on demand — nothing is stored twice.
- classmethod from_config(config: ModelConfig, errors: ModelErrors, estimator_type: str, model_file: str, architecture_tag: str = 'unknown', input_spec: dict | None = None, routee_version: str | None = None, trained_date: str | None = None) Metadata[source]#
Build grouped metadata from a flat
ModelConfigand estimator facts.The inverse of the
configproperty: decomposes the flat training config into thevehicle/contract/provenancesections and pairs them with theestimatordescriptor.routee_versiondefaults to the running package version; pass it explicitly to record the version that actually trained a model (e.g. when converting legacy archives).trained_date(ISOYYYY-MM-DD) is stamped ontoprovenance.training; leave itNonewhen the training date is unknown (e.g. converting legacy archives).
- model_config: ClassVar[ConfigDict] = {}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_digest: str | None#
Registry-independent instance identity, minted at train time:
sha256:<64 hex>over the frozen spec-1 identity payload (seecore.digest), which embedsestimator.estimator_sha256— so the digest pins the binary transitively while remaining recomputable from metadata alone. Registry versions (v<N>) are coordinates that map to this identity, never the reverse.Nonefor legacy models.
- property short_digest: str | None#
Truncated display form of
model_digest(sha256:<12 hex>).
- routee.powertrain.core.year.format_year(year: int | tuple[int, int]) str[source]#
Format a year for display and filesystem path usage.
- routee.powertrain.core.year.parse_year(value) int | tuple[int, int][source]#
Parse a year value from various formats.
- Accepts:
int: single year (e.g. 2020)
tuple/list of two ints: year range (e.g. (2020, 2026))
str: single year "2020" or range "2020-2026"
Returns: int for a single year, tuple[int, int] for a range.
- routee.powertrain.core.year.serialize_year(year: int | tuple[int, int])[source]#
Serialize year for JSON/dict storage.
Returns int for a single year, "YYYY-YYYY" string for a range.
- routee.powertrain.core.year.year_contains(year: int | tuple[int, int], query_year: int) bool[source]#
Check if a year value contains/matches a specific query year.
- class routee.powertrain.registry.model_id.ModelId(make: object = None, vehicle_slug: object = None, year: object = None, config_slug: object = None, version: object = None)[source]#
Uniquely identifies a model in the registry.
A
config_slugdisambiguates multiple models for the same vehicle/year — e.g.rf_steady_a1b2c3d4,ngb_96224f1f. The slug is derived from the model's metadata (architecture + optionalconfig.variant+ feature-set hash) viaderive_config_slug; it is not stored separately. The full feature composition and estimator architecture live in the archive'smetadata.json(and inindex.jsonfor registry-level search).A
ModelIdis aModelKey(the intrinsic, version-less identity, derivable from metadata) plus a registryversion(the only coordinate a registry assigns). Useid.keyto get the version-less identity, orModelId.from_key(key, version)/from_metadata(metadata, version)to attach a version.from_pathreconstructs one from the frozen registry path.- classmethod from_key(key: ModelKey, version: int) ModelId[source]#
Attach a registry
versionto a version-lessModelKey.
- classmethod from_metadata(metadata: Metadata, version: int) ModelId[source]#
Mint a ModelId from a model's metadata plus a registry version.
This is the canonical constructor: the version-less identity is derived from
metadata(viaModelKey.from_metadata), so the only registry-assigned coordinate isversion.- Parameters:
metadata -- the model metadata
version -- the registry version (positive integer)
Returns: a ModelId instance
- classmethod from_path(path: str) ModelId[source]#
Parse a ModelId from a path string.
Expected format:
make/vehicle_slug/year/config_slug/v<N>- Parameters:
path -- a
/-separated path string
Returns: a ModelId instance
- Raises:
ValueError -- if the path cannot be parsed as a valid model id
- model_config: ClassVar[ConfigDict] = {}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class routee.powertrain.registry.model_id.ModelInfo(*, model_id: ModelId, vehicle_model: str | None = None, estimator_type: str, feature_names: List[str], target_names: List[str], powertrain_type: str, vehicle_description: str, architecture_tag: str = 'unknown', input_spec: dict | None = None, path: str | None = None, mass_lbs: float | None = None, fuel_type: str | None = None, drivetrain: str | None = None, engine: str | None = None, trim: str | None = None, model_digest: str | None = None)[source]#
Lightweight model summary returned from registry queries (no binary data).
- model_config: ClassVar[ConfigDict] = {}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_digest: str | None#
The model's registry-independent instance identity (
sha256:<hex>), read frommetadata.json.Nonefor models published before digests existed.
- vehicle_model: str | None#
The bare metadata
vehicle.modelname (e.g."camry"), as distinct from the derivedmodel_id.vehicle_slug(e.g."camry_ice").query(model=...)matches either.Nonefor entries indexed before this field existed.
- class routee.powertrain.registry.model_id.ModelKey(*, make: str, vehicle_slug: str, year: Annotated[int | tuple[int, int], BeforeValidator(func=parse_year, json_schema_input_type=PydanticUndefined)], config_slug: str)[source]#
A model's intrinsic, version-less identity.
make/vehicle_slug/year/config_slugare all pure functions of a model's metadata, so aModelKeyis fully determined the moment a model is trained — unlikeversion, which is a registry coordinate assigned when the model is placed into a registry.vehicle_slugis derived (viaderive_vehicle_slug) as themodelname plus the coarse powertrain family — e.g.camry_ice,volt_phev.Model.keyexposes this, so every model self-describes its identity without needing a registry.Frozen (and therefore hashable) so it can be used as a grouping key that collapses the versions of one model.
- classmethod from_metadata(metadata: Metadata) ModelKey[source]#
Derive the version-less identity from a model's metadata.
- classmethod from_path(path: str) ModelKey[source]#
Parse a ModelKey from a
make/vehicle_slug/year/config_slugpath.
- model_config: ClassVar[ConfigDict] = {'frozen': True}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- routee.powertrain.registry.registry.INDEX_FILENAME = 'index.json'#
Filename of the catalog the remote backends read to answer queries without walking the whole store.
- exception routee.powertrain.registry.registry.IndexMissingError[source]#
Raised when
index.jsonis missing or unreadable at the schema root.
- class routee.powertrain.registry.registry.ModelRegistry[source]#
Abstract interface for a model registry backend.
Implementations provide model discovery (query) and retrieval (load). The registry is read-only from the package's perspective; publishing models is handled out-of-band by CI/scripts.
- find_by_digest(digest: str) List[ModelInfo][source]#
Find the registry entries holding a model with the given instance identity.
This is the coordinate lookup for a model you already have in hand: given the
model_digestfrom ametadata.json(orModel.digest), it returns every registry entry whose stored digest matches — normally one, but a byte-identical model legitimately published under multiple keys yields several.- Parameters:
digest -- the instance digest, with or without the
sha256:prefix
- Returns: matching ModelInfo entries (empty if the model was never
published to this registry)
- abstract get_metadata(model_id: str | ModelId) dict[source]#
Fetch only the metadata for a model (without downloading the binary).
- Parameters:
model_id -- unique identifier for the model. Can be a ModelId instance or a string path that will be parsed via
ModelId.from_path().
Returns: the parsed metadata dictionary from the archive
- abstract list_models(version_strategy: Literal['latest', 'all'] = 'latest') List[ModelId][source]#
List model identifiers in the registry.
This is a lightweight operation that returns only the model paths/identifiers without fetching any metadata or binaries.
- Parameters:
version_strategy --
"latest"(default) returns only the highest version per (make, model, year, config_slug) group;"all"returns every versioned identifier.
Returns: list of ModelId matching the strategy
- abstract load(model_id: str | ModelId) Model[source]#
Download and deserialize a specific model.
- Parameters:
model_id -- unique identifier for the model to load. Can be a ModelId instance or a string path that will be parsed via
ModelId.from_path().
Returns: a fully deserialized Model instance
- abstract query(make: str | None = None, model: str | None = None, year: int | None = None, config_slug: str | None = None, feature_names: Sequence[str] | None = None, powertrain_type: str | None = None, fuel_type: str | None = None, drivetrain: str | None = None, engine: str | None = None, trim: str | None = None, version: int | None = None, model_digest: str | None = None, version_strategy: Literal['latest', 'all'] = 'latest', custom_filters: Sequence[Callable[[ModelInfo], bool]] | None = None, fuzzy: bool = True, fuzzy_threshold: int = 80) List[ModelInfo][source]#
List models matching the given filters.
All parameters are optional; passing none returns all models. Returns lightweight metadata — no model binaries are downloaded.
- Parameters:
make -- filter by vehicle make
model -- filter by vehicle model — matches the bare metadata model name (e.g.
"camry") or the derivedvehicle_slugpath segment (e.g."camry_ice")year -- filter by model year
config_slug -- filter by config slug (e.g. "rf_default", "cnn_5link")
feature_names -- filter to models whose feature set contains every listed feature column (subset match, exact names)
powertrain_type -- filter by powertrain type (e.g. "ICE", "BEV", "HEV")
fuel_type -- filter by fuel type (e.g. "GASOLINE", "DIESEL", "ELECTRICITY")
drivetrain -- filter by drivetrain (e.g. "FWD", "RWD", "AWD")
engine -- filter by engine specification (e.g. "4cyl", "2.0tdi")
trim -- filter by trim level (e.g. "sport", "active")
version -- pin results to an exact version (e.g. 2). When set,
version_strategyis ignored.model_digest -- pin results to an exact instance identity — the
model_digestminted at train time and stored inmetadata.json(accepted with or without thesha256:prefix; always matched exactly, never fuzzily). Resolves a metadata file in hand back to its registry entry. When set,version_strategyis ignored.version_strategy -- how to collapse multiple versions of the same model.
"latest"(default) keeps only the highest version per (make, vehicle_slug, year, config_slug) group;"all"returns every version. Ignored whenversionis specified.custom_filters -- optional list of callables that accept a ModelInfo and return True to keep the model or False to exclude it
fuzzy -- if True, use fuzzy string matching for string fields (default True)
fuzzy_threshold -- minimum score (0–100) for a fuzzy match to be accepted (default 80)
- class routee.powertrain.estimators.estimator_interface.ColumnSpec(*, name: str, units: str | None = None, dtype: str | None = None)[source]#
Identity of one positional column in an estimator's input or output tensor.
Carries the column
nameplus itsunitsanddtypeso a consumer holding only the serialized binary can both order its inputs correctly and interpret/convert their values.- model_config: ClassVar[ConfigDict] = {'frozen': True}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class routee.powertrain.estimators.estimator_interface.Estimator[source]#
Abstract base class for all estimator backends.
- bind_io_contract(config: ModelConfig) None[source]#
Stamp the input/output contract derived from
configontoinput_spec.Preserves any windowing fields already set by the trainer and records the ordered input columns (features, plus distance for RAW), the ordered output columns, the predict method, and the distance column — so the serialized binary and metadata are self-describing and a consumer never has to guess the positional order.
- file_extension: str#
File extension used when serializing this estimator's binary in a ZIP archive.
- abstract classmethod from_bytes(data: bytes) Estimator[source]#
Deserialize an estimator from raw bytes.
- property input_spec: InputSpec#
The input/output contract this estimator implements.
Subclasses set the windowing fields at construction; the trainer stamps the ordered input/output columns via
bind_io_contract().
- output_column_specs(config: ModelConfig) List[ColumnSpec][source]#
Positional output tensor columns this estimator emits.
Default: one column per energy target, in order. Estimators that emit extra columns (e.g. per-target uncertainty) override this.
- abstract predict(links_df: DataFrame, config: ModelConfig) DataFrame[source]#
Predict absolute energy consumption for each link.
- Parameters:
links_df -- the input dataframe. Must contain every column in
config.feature_setplus (ifpredict_method == RAW) the distance column, and (ifinput_spec.grouping_columnis set) the grouping column.config -- the model's
ModelConfig. Estimators readfeature_set,distance,targetandpredict_methodfrom here.
- abstract to_bytes() bytes[source]#
Serialize the estimator to raw bytes (native binary format).
This is the estimator's only serialization primitive. Estimators are not independently persistable artifacts: a model on disk is always an estimator binary paired with its
metadata.jsonsidecar, and that pairing — along with the required input/output contract and the instance digest — is enforced exclusively at theModelsave/load choke points (seeroutee.powertrain.io.archive). Persist viaModel.to_file/Model.from_file, never by writing these bytes directly.
- class routee.powertrain.estimators.estimator_interface.InputSpec(*, lookback: int = 0, grouping_column: str | None = None, pad_strategy: Literal['zero', 'repeat_first'] = 'repeat_first', input_columns: List[ColumnSpec] | None = None, output_columns: List[ColumnSpec] | None = None, predict_method: str | None = None, distance_column: str | None = None)[source]#
The full input/output contract an estimator's serialized binary implements.
Beyond the windowing fields (
lookback/grouping_column/pad_strategy) it pins the positional order of the estimator's input and output tensors — the piece a downstream consumer (e.g. routee-compass) needs to feed columns in the right slots. The contract fields areOptionaland default toNoneso legacy artifacts minted before the contract existed still parse.- distance_column: str | None#
The distance column — the RATE multiplier / the RAW input position.
- grouping_column: str | None#
column used to bucket rows into independent sequences (e.g. "route_id"). Required whenever
lookback > 0so windows don't cross sequence boundaries.
- input_columns: List[ColumnSpec] | None#
the feature columns, plus the distance column appended when
predict_method == "raw".Noneon legacy artifacts that predate the contract.- Type:
Ordered positional columns of the input tensor
- lookback: int#
rows of prior context required per prediction. 0 = pointwise (classic tabular).
- model_config: ClassVar[ConfigDict] = {'frozen': True}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- output_columns: List[ColumnSpec] | None#
the energy target(s), in order. Estimators that emit uncertainty append their std columns.
- Type:
Ordered positional columns of the output tensor
- pad_strategy: PadStrategy#
how to pad the lookback window at the start of a group (first rows lack prior context).
- predict_method: str | None#
"rate"(multiply by distance) or"raw"(already absolute energy).- Type:
How the raw estimator output maps to energy
- class routee.powertrain.estimators.onnx.ONNXEstimator(onnx_model: ModelProto, input_spec: InputSpec = InputSpec(lookback=0, grouping_column=None, pad_strategy='repeat_first', input_columns=None, output_columns=None, predict_method=None, distance_column=None))[source]#
Runs any ONNX model via
onnxruntime.When
input_spec.lookback > 0the estimator wraps feature rows into a(N, lookback, F)windowed tensor grouped byinput_spec.grouping_column(with padding at sequence starts perinput_spec.pad_strategy) before inference. Whenlookback == 0the estimator feeds a plain(N, F)tabular tensor — the common case for tree ensembles converted viaskl2onnx.- file_extension: str = '.onnx'#
File extension used when serializing this estimator's binary in a ZIP archive.
- classmethod from_bytes(data: bytes) ONNXEstimator[source]#
Deserialize an estimator from raw bytes.
- predict(links_df: DataFrame, config: ModelConfig) DataFrame[source]#
Predict absolute energy consumption for each link.
- Parameters:
links_df -- the input dataframe. Must contain every column in
config.feature_setplus (ifpredict_method == RAW) the distance column, and (ifinput_spec.grouping_columnis set) the grouping column.config -- the model's
ModelConfig. Estimators readfeature_set,distance,targetandpredict_methodfrom here.
- to_bytes() bytes[source]#
Serialize the estimator to raw bytes (native binary format).
This is the estimator's only serialization primitive. Estimators are not independently persistable artifacts: a model on disk is always an estimator binary paired with its
metadata.jsonsidecar, and that pairing — along with the required input/output contract and the instance digest — is enforced exclusively at theModelsave/load choke points (seeroutee.powertrain.io.archive). Persist viaModel.to_file/Model.from_file, never by writing these bytes directly.
- class routee.powertrain.estimators.ngboost_estimator.NGBoostEstimator(ngboost)[source]#
- file_extension: str = '.joblib'#
File extension used when serializing this estimator's binary in a ZIP archive.
- classmethod from_bytes(data: bytes) NGBoostEstimator[source]#
Deserialize an estimator from raw bytes.
- output_column_specs(config: ModelConfig) List[ColumnSpec][source]#
NGBoost emits a point prediction plus a per-target standard deviation.
- predict(links_df: DataFrame, config: ModelConfig) DataFrame[source]#
Predict absolute energy consumption for each link.
- Parameters:
links_df -- the input dataframe. Must contain every column in
config.feature_setplus (ifpredict_method == RAW) the distance column, and (ifinput_spec.grouping_columnis set) the grouping column.config -- the model's
ModelConfig. Estimators readfeature_set,distance,targetandpredict_methodfrom here.
- to_bytes() bytes[source]#
Serialize the estimator to raw bytes (native binary format).
This is the estimator's only serialization primitive. Estimators are not independently persistable artifacts: a model on disk is always an estimator binary paired with its
metadata.jsonsidecar, and that pairing — along with the required input/output contract and the instance digest — is enforced exclusively at theModelsave/load choke points (seeroutee.powertrain.io.archive). Persist viaModel.to_file/Model.from_file, never by writing these bytes directly.
- class routee.powertrain.trainers.trainer.Trainer[source]#
- architecture_tag: str = 'unknown'#
Coarse architecture family, used in Metadata for registry-level filtering. Subclasses override (e.g.
"random_forest","cnn","ngboost").
- default_test_size: float = 0.2#
Default split sizes used when ModelConfig leaves them unspecified.
- abstract inner_train(features: DataFrame, target: DataFrame, config: ModelConfig, validation_features: DataFrame | None = None, validation_target: DataFrame | None = None) Estimator[source]#
Builds an estimator from the given data.
- property required_extra_columns: List[str]#
Columns the trainer needs beyond the declared feature set.
Example: a CNN trainer with lookback needs a grouping column (e.g.
route_id) so windows don't cross route boundaries.
- property split_grouping_column: str | None#
If set, the train/test split keeps all rows of a given group together.
Sequence-aware trainers (e.g. the 1D CNN) must set this so that a route's links stay contiguous within train or test — otherwise the per-group lookback windows built at both train and predict time stitch together non-consecutive rows and the temporal signal is lost.
- train(data: DataFrame, config: ModelConfig) Model[source]#
A wrapper for inner train that does some pre and post processing.
- class routee.powertrain.trainers.sklearn_random_forest.RandomForestTrainerOutput(value)[source]#
An enumeration.
- class routee.powertrain.trainers.sklearn_random_forest.SklearnRandomForestTrainer(max_depth: int = 10, min_samples_split: int = 10, n_estimators: int = 20, random_state: int = 52, cores: int = 4, output_type=RandomForestTrainerOutput.ONNX)[source]#
- architecture_tag: str = 'random_forest'#
Coarse architecture family, used in Metadata for registry-level filtering. Subclasses override (e.g.
"random_forest","cnn","ngboost").
- inner_train(features: DataFrame, target: DataFrame, config: ModelConfig, validation_features: DataFrame | None = None, validation_target: DataFrame | None = None) Estimator[source]#
Uses a random forest to predict the energy rate values
- class routee.powertrain.trainers.ngboost_trainer.NGBoostTrainer(n_estimators: int = 100, dist=<class 'ngboost.distns.normal.Normal'>, verbose: bool = True, verbose_eval: int = 20, learning_rate: float = 0.01, random_state: int = 52)[source]#
- architecture_tag: str = 'ngboost'#
Coarse architecture family, used in Metadata for registry-level filtering. Subclasses override (e.g.
"random_forest","cnn","ngboost").
- inner_train(features: DataFrame, target: DataFrame, config: ModelConfig, validation_features: DataFrame | None = None, validation_target: DataFrame | None = None) Estimator[source]#
Uses a ngboost model to predict the energy rate values
- routee.powertrain.validation.feature_visualization.contour_plot(model: Model, x_feature: str, y_feature: str, feature_ranges: Dict[str, Dict], output_path: str | Path | None = None)[source]#
takes a model and generates a contour plot of the two test features: x_feature and y_feature.
- Parameters:
model -- the model that will be used to generate the plots
x_feature -- one of the features used to generate the energy matrix and will be the x-axis feature
y_feature -- one of the features used to generate the energy matrix and will be the y-axis feature
feature_ranges -- a nested dictionary where each key should be a feature name and each value should be another dictionary containing "lower", "upper", and "n_sample" keys/values. These correspond to the lower/upper boundaries and n samples used to generate the plot. n_samples must be an integer and lower/upper are floats.
output_path -- an optional path to save the plot as a png file.
- routee.powertrain.validation.feature_visualization.visualize_features(model: Model, feature_ranges: Dict[str, dict], output_path: str | Path | None = None, return_predictions: bool | None = False) Dict[str, Series] | None[source]#
takes a model and generates test links to independently test the model's features and creates plots of those predictions
- Parameters:
model -- the model that will be used to generate the plots
feature_ranges -- a nested dictionary where each key should be a feature name and each value should be another dictionary containing "lower", "upper", and "n_sample" keys/values. These correspond to the lower/upper boundaries and n samples used to generate the plot. n_samples must be an integer and lower/upper are floats.
output_path -- an optional path to save the plots as png files.
return_predictions -- if true, returns the dictionary containing the prediction values
Returns: optionally returns a dictionary containing the predictions where the key is the feature tested