Architecture Overview#
MARIO is organized around a small number of layers with fairly clear responsibilities. For an advanced reader, the useful mental model is:
parse or build a database into a normalized internal state;
expose that state through
DatabaseandCoreModel;resolve matrices and derived views through the compute layer;
run structural operations and exports in
mario.ops;render user-facing tables and figures in
mario.views.
The important design choice is that MARIO is not only a collection of matrix formulas. It is also a stateful container for scenarios, metadata, units, index conventions, and parser-specific assumptions. Most modules are easier to understand once they are read in terms of that lifecycle instead of as isolated functions.
Reading the package top-down#
For most expert users, the best reading order is:
mario.__init__to see the public surface exported by the package;mario.api.databaseto understand the main object users interact with;mario.api.core_modelfor the lower-level matrix and index helpers shared byDatabase;mario.computeto see how derived matrices are specified and resolved;mario.parsersfor the ingestion path and source-specific readers;mario.opsandmario.viewsfor transformations, exports, and visualization.
Main package map#
mario.apiThe public surface centered on
DatabaseandCoreModel. This is the layer that translates internal storage and compute concepts into methods such ascalc_all(...),aggregate(...),plot(...)orto_excel(...).mario.computeThe authoritative catalog of matrix definitions plus the planner, resolver, formulas, operators, and ordering policies needed to materialize derived blocks. This is the main place to look when asking “where does matrix X come from?”.
mario.parsersParser entry points, parser validation helpers, and source-specific readers. Its job is to normalize many external data layouts into one MARIO state that can instantiate a
Database.mario.opsStructural operations, exports, aggregation, transformations, shocks, and add-sector workflows. In practice this is where most state-changing operations live once a database already exists.
mario.viewsPlotting and tabular views. This layer is intentionally downstream of the data model: it expects already normalized matrices or dataframes and focuses on presentation.
mario.internalandmario.storageSupporting layers for newer state/storage work. These packages matter most when tracing how parsed material is stored or serialized, but they are not usually the first stop for understanding user-facing workflows.
Core runtime objects#
DatabaseThe main user-facing object. It owns scenarios, metadata, clustering state, transformation methods, exports, plotting entry points, and higher-level convenience APIs.
CoreModelThe lower-level shared implementation for matrix access, index management, scenario bookkeeping, and many calculation helpers. When a
Databasemethod feels thin, the controlling logic is often here.- Scenario state
MARIO does not only store one table. It stores scenario-keyed matrices, indices, units, metadata, and auxiliary settings. That is why many helpers accept a scenario name and why operations often create or update scenario snapshots rather than overwriting one bare dataframe.
- Conventions and labels
The naming layer in
mario.modelandmario.settingsis central. Matrix names, axis labels, aliases, and table-dependent set names are not incidental strings spread around the package; they are part of the public model contract.
Typical end-to-end flow#
The most common runtime path is:
a parser entry point, direct dataframe constructor, or test fixture builds a
Database;parsed matrices and indices are normalized into the database state;
compute helpers resolve missing matrices lazily or via
calc_all(...);user operations in
mario.opscreate transformed scenarios or exported artifacts;mario.viewsandDatabase.plot(...)flatten or reshape data for human inspection.
This separation is useful when debugging. If a result is wrong, the first question is usually whether the issue belongs to ingestion, state normalization, matrix resolution, structural transformation, or presentation.
What changed in the recent restructure#
The current package layout reflects an explicit move away from a monolithic
core + tools organization. The newer structure tries to make the owning
abstraction obvious:
public object behaviour lives under
mario.api;matrix semantics and dependency logic live under
mario.compute;source normalization lives under
mario.parsers;transformations and exports live under
mario.ops;presentation lives under
mario.views.
That split is worth keeping in mind while reading the repository, because many files still implement historical workflows but now do so under a more explicit package boundary.