femic.pipeline.bundle Module

The femic.pipeline.bundle module owns FEMIC’s canonical data/model_input_bundle table surface. It resolves the three bundle table paths, loads and writes them, constructs AU/curve tables from per-case/per-FMU VDYP and TIPSY outputs, and provides compatibility helpers for downstream consumers that need stable AU-to-curve mapping behavior.

If you are debugging why bundle tables were written to the wrong place, why a post-TIPSY rebuild produced missing AU mappings, or how downstream exporters decide which treated and untreated curve IDs to use, this is the first module to read. In practice it owns:

  • canonical bundle table paths and readiness checks

  • assembly of AU, curve, and curve-points tables from per-case/per-FMU curve surfaces

  • species-proportion curve emission for ordered species universes

  • compatibility helpers for AU mapping backfill and curve-id assignment

Start Here If…

Use this page first if you are trying to:

  • understand what lives under data/model_input_bundle/

  • inspect how Stage 01b outputs become export-ready bundle tables

  • debug missing AU/curve mappings during bundle assembly

  • trace how treated versus untreated curve IDs are assigned downstream

Typical maintenance path:

  1. Start with resolve_bundle_paths() and bundle_tables_ready() for basic path-contract questions.

  2. Read build_bundle_tables_from_curves() when the issue is in bundle assembly from per-case/per-FMU VDYP and TIPSY outputs.

  3. Inspect assign_curve_ids_from_au_table() when downstream consumers are attaching curve IDs back onto stand tables.

Typical Usage

The common maintenance pattern is to resolve canonical bundle paths first and then load the three-table surface as one unit:

import pandas as pd
from femic.pipeline.bundle import load_bundle_tables, resolve_bundle_paths

paths = resolve_bundle_paths(base_dir="data/model_input_bundle")
au_table, curve_table, curve_points_table = load_bundle_tables(
    paths=paths,
    pd_module=pd,
)

How This Fits Into The Pipeline

This module sits at the seam between post-TIPSY assembly and model export:

  1. upstream code produces per-case/per-FMU untreated VDYP curves and optional treated TIPSY curves

  2. this module compiles those surfaces into canonical bundle tables

  3. export/runtime layers such as femic.fmg.patchworks and related tools consume the bundle tables instead of rebuilding upstream curve logic

That makes this module the source-of-truth for the bundle table contract, even though it does not own the upstream curve generation algorithms.

Key Entry Surfaces

The highest-value entrypoints in this module are:

  • resolve_bundle_paths() Resolve canonical AU/curve/curve-points bundle table locations.

  • load_bundle_tables() Load bundle tables from CSV and optionally normalize legacy case/FMU codes carried through the tsa naming seam.

  • write_bundle_tables() Persist bundle tables to the canonical CSV surface.

  • build_bundle_tables_from_curves() Assemble the three canonical bundle tables from per-case/per-FMU VDYP and TIPSY outputs.

  • assign_curve_ids_from_au_table() Attach treated/untreated curve IDs back onto stand-like tables.

The main dataclasses are also important because they make the table/path contracts explicit:

  • BundlePaths

  • BundleAssemblyResult

Core Contracts

The most important runtime contracts in this module are:

  • the canonical bundle directory defaults to data/model_input_bundle

  • the required tables are au_table.csv, curve_table.csv, and curve_points_table.csv

  • AU identifiers are deterministically namespaced by case/FMU code through the legacy tsa_curve_id_prefix()

  • managed and unmanaged curve IDs are emitted together so downstream export layers can choose the right curve family without recomputing upstream logic

  • optional ordered-species support emits extra species-proportion curves for both untreated and treated surfaces

Failure Seams To Watch

The common failure boundaries in this module are:

  • missing AU mappings per-case/per-FMU curve combinations can be skipped if scsi_au lacks a required mapping

  • bundle-table naming drift downstream tools assume the canonical three-table contract and can break if filenames or key columns drift

  • treated/unmanaged compatibility confusion this module intentionally carries both current and backward-compatible column names so older exporters/checkpoints do not break

Cross-References

Guides and references that pair especially closely with this module:

Related API pages:

Helpers for model-input bundle table pathing and I/O.

class femic.pipeline.bundle.BundleAssemblyResult(au_table, curve_table, curve_points_table, missing_au_curve_mappings)[source]

Bases: object

Assembled model-input bundle tables and missing-mapping diagnostics.

Parameters:
  • au_table (Any)

  • curve_table (Any)

  • curve_points_table (Any)

  • missing_au_curve_mappings (Any)

au_table: Any
curve_points_table: Any
curve_table: Any
missing_au_curve_mappings: Any
class femic.pipeline.bundle.BundlePaths(bundle_dir, au_table, curve_table, curve_points_table)[source]

Bases: object

Resolved file paths for model input bundle tables.

Parameters:
  • bundle_dir (Path)

  • au_table (Path)

  • curve_table (Path)

  • curve_points_table (Path)

au_table: Path
bundle_dir: Path
curve_points_table: Path
curve_table: Path
femic.pipeline.bundle.assign_curve_ids_from_au_table(*, f_table, au_table, pd_module, np_module, au_col='au', proj_age_col='PROJ_AGE_1', managed_curve_col='treated_curve_id', unmanaged_curve_col='untreated_curve_id', curve1_col='curve1', curve2_col='curve2', managed_age_cutoff=60)[source]

Assign curve ids from AU table for treated/untreated curve slots.

Parameters:
  • f_table (Any)

  • au_table (Any)

  • pd_module (Any)

  • np_module (Any)

  • au_col (str)

  • proj_age_col (str)

  • managed_curve_col (str)

  • unmanaged_curve_col (str)

  • curve1_col (str)

  • curve2_col (str)

  • managed_age_cutoff (int)

Return type:

Any

femic.pipeline.bundle.build_bundle_tables_from_curves(*, tsa_list, vdyp_curves_smooth, tipsy_curves, scsi_au, canfi_species_fn, pd_module, species_universe=None, vdyp_species_proportions=None, tipsy_species_proportions=None, message_fn=<built-in function print>)[source]

Build AU/curve tables from per-TSA VDYP and TIPSY curve outputs.

Parameters:
  • tsa_list (list[str])

  • vdyp_curves_smooth (dict[str, Any])

  • tipsy_curves (dict[str, Any])

  • scsi_au (dict[str, dict[tuple[str, str], int]])

  • canfi_species_fn (Callable[[str], int])

  • pd_module (Any)

  • species_universe (list[str] | None)

  • vdyp_species_proportions (dict[str, dict[tuple[str, str], dict[str, float]]] | None)

  • tipsy_species_proportions (dict[str, Any] | None)

  • message_fn (Callable[[str], Any])

Return type:

BundleAssemblyResult

femic.pipeline.bundle.bundle_tables_ready(*, paths)[source]

Return True when all required bundle tables exist.

Parameters:

paths (BundlePaths)

Return type:

bool

femic.pipeline.bundle.emit_missing_au_curve_mapping_warning(*, missing_df, message_fn=<built-in function print>, top_n=10)[source]

Emit legacy warning text for missing AU/curve mapping diagnostics.

Parameters:
  • missing_df (Any)

  • message_fn (Callable[[str], Any])

  • top_n (int)

Return type:

None

femic.pipeline.bundle.ensure_au_table_index(*, au_table, au_id_col='au_id')[source]

Return AU table indexed by AU id when available.

Parameters:
  • au_table (Any)

  • au_id_col (str)

Return type:

Any

femic.pipeline.bundle.ensure_scsi_au_from_table(*, au_table, scsi_au, normalize_tsa_code_fn)[source]

Backfill scsi_au map from persisted AU table entries.

Parameters:
  • au_table (Any)

  • scsi_au (dict[str, dict[tuple[str, str], int]])

  • normalize_tsa_code_fn (Callable[[Any], str])

Return type:

None

femic.pipeline.bundle.load_bundle_tables(*, paths, pd_module, normalize_tsa_code_fn=None)[source]

Load bundle tables from CSV paths, optionally normalizing TSA codes.

Parameters:
  • paths (BundlePaths)

  • pd_module (Any)

  • normalize_tsa_code_fn (Callable[[Any], str] | None)

Return type:

tuple[Any, Any, Any]

femic.pipeline.bundle.resolve_bundle_paths(*, base_dir='data/model_input_bundle', ensure_dir=True)[source]

Resolve canonical model-input bundle table paths.

Parameters:
  • base_dir (str | Path)

  • ensure_dir (bool)

Return type:

BundlePaths

femic.pipeline.bundle.tsa_curve_id_prefix(tsa_code)[source]

Return deterministic AU/curve id prefix for numeric and named TSA codes.

Parameters:

tsa_code (str)

Return type:

int

femic.pipeline.bundle.validate_complete_au_curve_mappings(*, missing_df, top_n=10)[source]

Raise when bundle assembly leaves any VDYP strata without AU mapping.

Parameters:
  • missing_df (Any)

  • top_n (int)

Return type:

None

femic.pipeline.bundle.write_bundle_tables(*, paths, au_table, curve_table, curve_points_table)[source]

Persist bundle tables to their canonical CSV locations.

Parameters:
  • paths (BundlePaths)

  • au_table (Any)

  • curve_table (Any)

  • curve_points_table (Any)

Return type:

None