flextool 4.2.0__tar.gz → 4.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {flextool-4.2.0 → flextool-4.2.2}/PKG-INFO +4 -4
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/input/_timeline.py +155 -25
- flextool-4.2.2/flextool/engine/preprocess/emit/_base_steps.py +74 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/emit/_inflow_scaling.py +234 -137
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/emit/_inflow_scaling_checks.py +56 -22
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/emit/_period_params.py +13 -3
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/params/_derived.py +6 -3
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/solve/_run_model.py +1 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/env_check.py +2 -2
- {flextool-4.2.0 → flextool-4.2.2}/flextool.egg-info/PKG-INFO +4 -4
- {flextool-4.2.0 → flextool-4.2.2}/flextool.egg-info/SOURCES.txt +1 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool.egg-info/requires.txt +3 -3
- {flextool-4.2.0 → flextool-4.2.2}/pyproject.toml +6 -6
- {flextool-4.2.0 → flextool-4.2.2}/LICENSE.txt +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/README.md +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/__init__.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/_allocator.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/_mem_sampler.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/_resources.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/_thread_budget.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/calibrate/__init__.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/calibrate/__main__.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/calibrate/_cli.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/calibrate/_db_alt.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/calibrate/_final_outputs.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/calibrate/_guard.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/calibrate/_loop.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/calibrate/_readers.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/calibrate/_report.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/calibrate/_sizing.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/calibrate/_solve.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/calibrate/_solve_status.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/cli/__init__.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/cli/_console.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/cli/_timing.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/cli/cmd_execute_flextool_workflow.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/cli/cmd_export_to_tabular.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/cli/cmd_import_sensitivities.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/cli/cmd_migrate_database.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/cli/cmd_open_results_db.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/cli/cmd_read_matpower.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/cli/cmd_read_old_flextool.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/cli/cmd_read_self_describing_tabular_input.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/cli/cmd_read_tabular_input.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/cli/cmd_run_flextool.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/cli/cmd_scenario_results.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/cli/cmd_solve_mps.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/cli/cmd_update_flextool.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/cli/cmd_write_outputs.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/common_utils/__init__.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/common_utils/plot_mem_shape.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/decomposition/__init__.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/decomposition/region_decomposition.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/decomposition/region_filter.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/__init__.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/_behaviour_changes.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/_csv_reload/__init__.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/_csv_reload/_field_seeds.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/_csv_reload/_meta.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/_csv_reload/_seed.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/_csv_reload/_stamp.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/_csv_reload/_topology.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/_csv_reload/load.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/_csv_reload/offline_outputs.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/autoscale/__init__.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/autoscale/_config.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/autoscale/_layer2.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/autoscale/_layer2_types.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/autoscale/_quantity_types.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/autoscale/_report.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/input/__init__.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/input/_axis_enums.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/input/_constants.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/input/_db_loader.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/input/_db_reader.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/input/_inmemory_reader.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/input/_input_source.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/input/_param_shapes.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/input/_solve_config.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/input/_solve_state.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/input/_spinedb_reader.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/input/_timeline_rules.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/model/__init__.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/model/_balance_terms.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/model/_coarse_flows.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/model/_commodity_ladder.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/model/_common.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/model/_cumulative_invest.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/model/_dc_power_flow.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/model/_delay.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/model/_exact.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/model/_group_slack.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/model/_lead_time.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/model/_non_anticipativity.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/model/_online.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/model/_pdt_join.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/model/_reserve.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/model/_self_discharge.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/model/_unit_floors.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/model/core.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/output/__init__.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/output/_coarse_flows.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/output/_dump_csvs.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/output/_horizon_dump.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/output/_parquet_bundle.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/output/_prices.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/output/_writer.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/__init__.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/_dump_stamp.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/_flex_data_provider.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/_input_writer.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/_invest_seeds.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/_provider_io.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/_provider_keys.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/_provider_translators.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/_reserve_methods.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/_solve_context.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/_stochastic_detect.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/emit/__init__.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/emit/_arc_unions.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/emit/_blocks.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/emit/_calc_params.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/emit/_chain_params.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/emit/_co2_accumulators.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/emit/_dispatchers.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/emit/_energy_margin.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/emit/_energy_margin_adder.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/emit/_entity_annual.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/emit/_leaf_sets.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/emit/_lp_scaling.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/emit/_mid_sets.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/emit/_pdt_lookup.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/emit/_pdt_params.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/emit/_per_solve.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/emit/_period_calc.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/emit/_reserve_sets.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/emit/_solve_time.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/emit/_solve_writers.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/emit/_vectorize.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/flex_data.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/params/__init__.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/params/_arithmetic.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/params/_block.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/params/_block_layout.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/params/_branch.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/params/_coarse.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/params/_direct.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/params/_existing.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/params/_mintime.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/params/_npv.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/params/_per_solve_sets.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/params/_profiles.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/params/_projection.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/params/_ramp_links.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/params/_retire_existing.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/params/_run_calendar.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/preprocess/params/_walks.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/solve/__init__.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/solve/_acceptance.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/solve/_benders.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/solve/_carry_routing.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/solve/_determinism.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/solve/_handoff.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/solve/_orchestration.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/solve/_realization.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/solve/_realized_overlap.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/solve/_recursive_solve.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/solve/_region_filter.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/solve/_solver_base.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/solve/_solver_dispatch.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/solve/_stochastic.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/solve/_subprocess_solve.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/solve/_warm.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine/solve/chain.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/engine_polars/__init__.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/export_to_tabular/__init__.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/export_to_tabular/db_reader.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/export_to_tabular/excel_writer.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/export_to_tabular/export_settings.yaml +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/export_to_tabular/export_to_excel.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/export_to_tabular/formatting.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/export_to_tabular/sheet_config.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/__init__.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/__main__.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/calibrate_commands.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/calibrate_jobs.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/check_tree.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/cli_format.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/config_parser.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/data_models.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/db_editor_integration.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/db_version_check.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/dialogs/__init__.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/dialogs/add_dialog.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/dialogs/calibrate_dialog.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/dialogs/file_picker.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/dialogs/group_picker.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/dialogs/migration_consent_dialog.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/dialogs/migration_progress_dialog.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/dialogs/plot_dialog.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/dialogs/plot_settings_picker.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/dialogs/project_dialog.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/dialogs/update_dialog.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/downsampling.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/error_handling.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/execution_manager.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/execution_window.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/hover_tooltip.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/input_sources.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/main_window.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/network_graph.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/output_actions.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/output_log_window.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/platform_utils.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/plot_cache.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/plot_canvas.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/plot_config_reader.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/project_utils.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/result_viewer.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/scenario_key.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/scenario_lists.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/settings_io.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/solve_reader.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/tree_reorder.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/gui/ui_metrics.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/input_derivation/__init__.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/input_derivation/_commodity_ladder.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/input_derivation/_commodity_ladder_sets.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/input_derivation/_dc_power_flow.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/input_derivation/_method_constants.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/input_derivation/_process_method.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/input_derivation/_specs.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/input_derivation/_validators.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/lean_parquet.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/model_builder/__init__.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/model_builder/build_model.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/model_builder/encoding.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/model_builder/names.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/model_builder/profiles.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/plot_outputs/__init__.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/plot_outputs/axis_helpers.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/plot_outputs/color_template.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/plot_outputs/config.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/plot_outputs/format_helpers.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/plot_outputs/legend_helpers.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/plot_outputs/orchestrator.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/plot_outputs/perf.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/plot_outputs/plan.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/plot_outputs/plot_bars.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/plot_outputs/plot_bars_detail.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/plot_outputs/plot_lines.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/plot_outputs/shared_manifest.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/plot_outputs/subplot_helpers.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_inputs/__init__.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_inputs/import_old_excel_input.json +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_inputs/read_matpower.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_inputs/read_old_flextool.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_inputs/read_self_describing_excel.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_inputs/read_tabular_with_specification.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_inputs/write_old_flextool_to_db.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_inputs/write_self_describing_to_db.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_inputs/write_to_input_db.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_outputs/__init__.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_outputs/_annualize.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_outputs/_fan_labels.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_outputs/_inmemory_helpers.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_outputs/_output_meta.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_outputs/_timeline_breaks.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_outputs/calc_capacity_flows.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_outputs/calc_connections.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_outputs/calc_costs.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_outputs/calc_group_flows.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_outputs/calc_slacks.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_outputs/calc_storage_vre.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_outputs/drop_levels.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_outputs/handoff_writers.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_outputs/out_ancillary.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_outputs/out_capacity.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_outputs/out_costs.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_outputs/out_flowgroup.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_outputs/out_flows.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_outputs/out_group.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_outputs/out_node.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_outputs/persist_realized_slice.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_outputs/process_results.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_outputs/read_highs_solution.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_outputs/read_parameters.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_outputs/read_sets.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_outputs/read_variables.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_outputs/solve_order.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_outputs/spinedb_replay.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_outputs/union_realized_slice.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_outputs/write_outputs.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/process_outputs/write_spinedb.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/representative_periods/__init__.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/representative_periods/clustering.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/representative_periods/force_include.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/representative_periods/netload.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/representative_periods/netload_inputs.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/representative_periods/netload_iterate.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/representative_periods/preprocess.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/representative_periods/scenario_stack.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/representative_periods/weights.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/run_options.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/scenario_comparison/__init__.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/scenario_comparison/config_builder.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/scenario_comparison/constants.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/scenario_comparison/data_models.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/scenario_comparison/db_reader.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/scenario_comparison/dispatch_data.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/scenario_comparison/dispatch_mappings.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/scenario_comparison/dispatch_plots.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/scenario_comparison/input_entity_colors.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/scenario_comparison/orchestrator.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/scenario_comparison/plan_union.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/scenario_comparison/plot_settings_seed.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/schemas/AXIS_CONTRACT.md +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/schemas/canonical_databases/howto_aggregate_output.json +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/schemas/canonical_databases/howto_connections.json +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/schemas/canonical_databases/howto_demand.json +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/schemas/canonical_databases/howto_hydro_reservoir.json +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/schemas/canonical_databases/howto_hydro_reservoir_with_pump.json +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/schemas/canonical_databases/howto_non_sync_and_curtailment.json +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/schemas/canonical_databases/howto_ramp_and_start_up.json +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/schemas/canonical_databases/howto_stochastics.json +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/schemas/canonical_databases/templates_examples.json +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/schemas/canonical_databases/templates_time_settings_only.json +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/schemas/comparison_settings_template.json +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/schemas/default_plot_settings.yaml +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/schemas/default_plots.yaml +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/schemas/flextool_axis_contract.json +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/schemas/flextool_axis_contract.schema.json +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/schemas/old_flextool_import_template.json +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/schemas/output_info_template.json +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/schemas/output_settings_template.json +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/schemas/pre_v26/flextool_template_constant_default.json +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/schemas/pre_v26/flextool_template_default_optional_output.json +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/schemas/pre_v26/flextool_template_default_value.json +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/schemas/pre_v26/flextool_template_drop_down.json +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/schemas/pre_v26/flextool_template_lifetime_method.json +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/schemas/pre_v26/flextool_template_optional_outputs.json +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/schemas/pre_v26/flextool_template_output_node_flows.json +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/schemas/pre_v26/flextool_template_results_master.json +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/schemas/pre_v26/flextool_template_rolling_start_remove.json +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/schemas/pre_v26/flextool_template_rolling_window.json +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/schemas/pre_v26/flextool_template_storage_binding_defaults.json +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/schemas/pre_v26/flextool_template_v2.json +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/schemas/pre_v26/flextool_template_v25.json +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/schemas/spinedb_results_schema.json +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/schemas/spinedb_schema.json +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/solver_config/copt.opt.template +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/solver_config/cplex.opt.template +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/solver_config/gurobi.opt.template +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/solver_config/highs.opt.template +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/solver_config/xpress.opt.template +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/spinedb_backend/__init__.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/spinedb_backend/_axis_enums.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/spinedb_backend/_backend.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/update_flextool/__init__.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/update_flextool/bundle_install.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/update_flextool/canonical_databases.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/update_flextool/db_handle.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/update_flextool/db_migration.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/update_flextool/ensure_settings_db.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/update_flextool/export_database.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/update_flextool/extend_tests_fixture.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/update_flextool/fixture_schema.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/update_flextool/generate_canonical.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/update_flextool/initialize_database.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/update_flextool/install_info.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/update_flextool/self_update.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/update_flextool/sync_master_json_template.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool/update_flextool/test_fixtures.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool.egg-info/dependency_links.txt +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool.egg-info/entry_points.txt +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/flextool.egg-info/top_level.txt +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/setup.cfg +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_bar_layout.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_bar_sub_pixel_labels.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_blocks.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_branch_weights.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_child_run_argv.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_ci_shard.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_color_template.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_commodity_ladder_rolling.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_comparison_excel.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_comparison_project_root.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_complete_period_share_reduction.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_connection_node_warnings.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_console_run_tool.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_cost_aggregation_semantics.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_cost_breakdown_by_entity.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_csv_dump_roundtrip.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_dc_power_flow.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_dispatch_consumer_and_connection_signs.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_dispatch_node_debug_and_tree.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_dispatch_order_specials.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_dispatch_scenario_tag.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_ensure_settings_db.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_entity_unitsize_invariant.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_entity_universe_carrier.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_env_check.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_env_knob_registry.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_export_to_tabular.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_extend_tests_fixture.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_flowgroup_indicators.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_force_include.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_group_output_warnings.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_handoff_writers.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_input_entity_colors.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_lh2_three_region.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_min_load_rolling.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_non_anticipativity.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_old_flextool_importer_schema_drift.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_open_results_db.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_output_column_metadata.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_output_csv_names.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_output_metadata_renderers.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_output_work_folder_isolation.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_parameter_group_coverage.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_plan_union.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_plot_draw_order.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_plot_pipeline.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_plot_plan_chunk_reconstruction.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_plot_plan_time_labels_roundtrip.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_plot_settings_seed.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_read_highs_solution.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_recourse_cost_reconciliation.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_regional_filter.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_representative_periods.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_rolling_online_carry.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_rolling_online_mintime_carry.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_rolling_online_minuptime.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_rp_alternative_name.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_rp_force_include_wiring.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_rp_solves_filter.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_run_options.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_scenario_colors.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_scenario_stack.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_scenarios.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_self_describing_reader.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_shared_axis_manifest.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_simple_bar_entity_color.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_solve_config.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_solve_reader.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_stream_concat_temp_cleanup.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_support_load.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_synthesize_invest_dual.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_thread_budget.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_timeline_breaks.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_timings_csv.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_unidirectional_connection.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_unit_online_dt_columns.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_v52_migration.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_v63_migration.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_v64_migration.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_v65_migration.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_v66_migration.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_v67_migration.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_v68_migration.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_v69_migration.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_v70_migration.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_workdir_empty_default.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_xlsx_v77_round_trip.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_xlsx_workflow.py +0 -0
- {flextool-4.2.0 → flextool-4.2.2}/tests/test_years_represented.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: flextool
|
|
3
|
-
Version: 4.2.
|
|
3
|
+
Version: 4.2.2
|
|
4
4
|
Summary: IRENA FlexTool is an energy and power systems model for understanding the role of variable power generation in future energy systems.
|
|
5
5
|
Author: IRENA FlexTool contributors
|
|
6
6
|
License: © International Renewable Energy Agency 2018-2022
|
|
@@ -39,9 +39,9 @@ Classifier: Topic :: Scientific/Engineering
|
|
|
39
39
|
Requires-Python: >=3.11
|
|
40
40
|
Description-Content-Type: text/markdown
|
|
41
41
|
License-File: LICENSE.txt
|
|
42
|
-
Requires-Dist: polar-high>=3.12.
|
|
42
|
+
Requires-Dist: polar-high>=3.12.3
|
|
43
43
|
Requires-Dist: highspy<1.16,>=1.15.1
|
|
44
|
-
Requires-Dist: polars<
|
|
44
|
+
Requires-Dist: polars<3,>=1.40
|
|
45
45
|
Requires-Dist: pandas<4,>=2.2.3
|
|
46
46
|
Requires-Dist: spinedb-api<0.37,>=0.36.5
|
|
47
47
|
Requires-Dist: openpyxl
|
|
@@ -60,7 +60,7 @@ Provides-Extra: viewer
|
|
|
60
60
|
Requires-Dist: tsdownsample>=0.1.3; extra == "viewer"
|
|
61
61
|
Requires-Dist: networkx>=3.0; extra == "viewer"
|
|
62
62
|
Provides-Extra: compat
|
|
63
|
-
Requires-Dist: polars[rtcompat]<
|
|
63
|
+
Requires-Dist: polars[rtcompat]<3,>=1.40; extra == "compat"
|
|
64
64
|
Provides-Extra: engine-polars
|
|
65
65
|
Provides-Extra: dev
|
|
66
66
|
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
@@ -62,6 +62,7 @@ from flextool.engine.input._solve_state import (
|
|
|
62
62
|
ActiveTimeEntry,
|
|
63
63
|
FlexToolConfigError,
|
|
64
64
|
)
|
|
65
|
+
from flextool.engine.preprocess.emit._base_steps import NEW_STEP_BASE_STEPS, NEW_STEP_BASE_STEPS_SCHEMA
|
|
65
66
|
from flextool.engine.preprocess._provider_io import (
|
|
66
67
|
_provider_key,
|
|
67
68
|
)
|
|
@@ -390,12 +391,18 @@ class TimelineConfig:
|
|
|
390
391
|
f"{ts} (representative_period_weights)": [str(b) for b in self.rp_weights[ts]]
|
|
391
392
|
for ts in tl_timesets if self.rp_weights.get(ts)
|
|
392
393
|
}
|
|
394
|
+
# The fit of the new step is checked only for solves the model
|
|
395
|
+
# runs: an unused solve must not stop the run.
|
|
396
|
+
used_by = [step_solve_in_model_of[ts] for ts in tl_timesets if ts in step_solve_in_model_of]
|
|
393
397
|
chunks, block_chunks = _aggregate_timeline_pieces(
|
|
394
398
|
old_steps,
|
|
395
399
|
{ts: raw_durations[ts] for ts in tl_timesets},
|
|
396
400
|
step_duration,
|
|
397
401
|
logger,
|
|
398
402
|
extra_cuts=base_cuts,
|
|
403
|
+
solve_name=used_by[0] if used_by else first_solve,
|
|
404
|
+
timeline_name=timeline_name,
|
|
405
|
+
check_fit=bool(used_by),
|
|
399
406
|
)
|
|
400
407
|
# Guard: every base start on the original timeline must start a step
|
|
401
408
|
# of the aggregated one, else the rp base chain would sort it last.
|
|
@@ -668,18 +675,24 @@ class TimelineConfig:
|
|
|
668
675
|
|
|
669
676
|
Aggregation rules (lines 405-422 of the flextool source):
|
|
670
677
|
|
|
678
|
+
Each new step combines the time steps of the original timeline
|
|
679
|
+
that it covers (any step length; see ``_base_steps_of_new_steps``):
|
|
680
|
+
the rows of those steps are read and combined into one row.
|
|
681
|
+
|
|
671
682
|
* ``pt_node_inflow.csv`` and ``pbt_node_inflow.csv`` →
|
|
672
|
-
``"sum"`` (inflow energies sum across coarsened steps).
|
|
683
|
+
``"sum"`` (inflow energies per step sum across coarsened steps).
|
|
673
684
|
* Every other ``pt_*.csv`` / ``pbt_*.csv``, plus ``pdt_process.csv`` / ``pdt_node.csv`` (the
|
|
674
685
|
genuine period × time maps — the group key includes their leading ``period`` column, found by
|
|
675
|
-
name like every other column before ``time``) → ``"average"
|
|
686
|
+
name like every other column before ``time``) → ``"average"``, weighted by the durations of
|
|
687
|
+
the combined steps (the plain mean when they are equally long), rounded to 6 decimals.
|
|
676
688
|
* Rows with parameter ``"storage_state_reference_value"`` are
|
|
677
689
|
ALWAYS bypassed (line 474) — they're per-step state targets
|
|
678
690
|
rather than time-integrated quantities.
|
|
679
691
|
|
|
680
692
|
After file aggregation, ``input/p_node``'s ``inflow`` rows
|
|
681
693
|
are appended to ``solve_data/pt_node_inflow`` as one entry
|
|
682
|
-
per new timestep,
|
|
694
|
+
per new timestep, times the number of time steps the new step
|
|
695
|
+
combines (a constant inflow is energy per time step).
|
|
683
696
|
|
|
684
697
|
Args:
|
|
685
698
|
solve: Active solve name.
|
|
@@ -722,6 +735,7 @@ class TimelineConfig:
|
|
|
722
735
|
solve in self.new_step_durations
|
|
723
736
|
and self.new_step_durations[solve] is not None
|
|
724
737
|
)
|
|
738
|
+
base_steps_key = _provider_key(wf / "solve_data" / NEW_STEP_BASE_STEPS)
|
|
725
739
|
if not create:
|
|
726
740
|
for timeseries in timeseries_map:
|
|
727
741
|
src_path = wf / "input" / timeseries
|
|
@@ -732,6 +746,13 @@ class TimelineConfig:
|
|
|
732
746
|
if frame is None:
|
|
733
747
|
continue
|
|
734
748
|
provider.put(dst_key, frame)
|
|
749
|
+
# Every solve step is one original step (an earlier coarsened
|
|
750
|
+
# solve's rows must not reach this solve).
|
|
751
|
+
provider.put(base_steps_key, pl.DataFrame(schema=NEW_STEP_BASE_STEPS_SCHEMA))
|
|
752
|
+
# No full-timeline inflow energy: scale_to_annual_flow uses the
|
|
753
|
+
# solve's own period share (not an earlier coarsened solve's).
|
|
754
|
+
provider.put(_provider_key(wf / "solve_data" / "node_full_timeline_flow.csv"),
|
|
755
|
+
pl.DataFrame(schema={"node": pl.Utf8, "value": pl.Float64}))
|
|
735
756
|
return
|
|
736
757
|
|
|
737
758
|
# All timesets used by *solve* must resolve to the same
|
|
@@ -751,14 +772,30 @@ class TimelineConfig:
|
|
|
751
772
|
logger.error(message)
|
|
752
773
|
raise FlexToolConfigError(message)
|
|
753
774
|
timelines_list.append(timeline)
|
|
754
|
-
#
|
|
755
|
-
|
|
775
|
+
# Durations of the original time steps each new step combines
|
|
776
|
+
# (O(1) access per row); a timeline that is not an aggregated
|
|
777
|
+
# one keeps one step per step.
|
|
778
|
+
base_durations: dict[str, list[float]] = {}
|
|
779
|
+
# (original step, the new step that combines it), in timeline order.
|
|
780
|
+
base_step_rows: list[tuple[str, str]] = []
|
|
756
781
|
for timeline in timelines_list:
|
|
757
782
|
new_timeline = self.timelines[timeline]
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
783
|
+
original = self.original_timeline.get(timeline)
|
|
784
|
+
if original is not None and original in self.timelines:
|
|
785
|
+
base_durations.update(_base_steps_of_new_steps(
|
|
786
|
+
self.timelines[original], new_timeline, logger,
|
|
787
|
+
solve_name=solve, timeline_name=timeline,
|
|
788
|
+
))
|
|
789
|
+
base_step_rows.extend(_new_step_of_base_steps(self.timelines[original], new_timeline))
|
|
790
|
+
else:
|
|
791
|
+
for timeline_row in new_timeline:
|
|
792
|
+
base_durations[timeline_row[0]] = [float(timeline_row[1])]
|
|
793
|
+
base_step_rows.append((timeline_row[0], timeline_row[0]))
|
|
794
|
+
# The scalings read how many original steps each solve step combines
|
|
795
|
+
# (inflow and peak_inflow are energy per original step).
|
|
796
|
+
provider.put(base_steps_key, pl.DataFrame(
|
|
797
|
+
[(t, s, float(len(base_durations[s]))) for t, s in base_step_rows],
|
|
798
|
+
schema=NEW_STEP_BASE_STEPS_SCHEMA, orient="row"))
|
|
762
799
|
|
|
763
800
|
# node-name → constant-inflow value (used to append per-step
|
|
764
801
|
# contributions to pt_node_inflow below).
|
|
@@ -799,10 +836,8 @@ class TimelineConfig:
|
|
|
799
836
|
try:
|
|
800
837
|
while True:
|
|
801
838
|
datain = next(rows_iter)
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
)
|
|
805
|
-
if timeline_step_duration is not None:
|
|
839
|
+
step_base_durations = base_durations.get(datain[time_index])
|
|
840
|
+
if step_base_durations is not None:
|
|
806
841
|
values: list[float] = []
|
|
807
842
|
params = list(datain[0:time_index])
|
|
808
843
|
row = list(datain[0 : time_index + 1])
|
|
@@ -811,7 +846,7 @@ class TimelineConfig:
|
|
|
811
846
|
time_index >= 2
|
|
812
847
|
and datain[1] != "storage_state_reference_value"
|
|
813
848
|
) or time_index < 2:
|
|
814
|
-
for _i in range(
|
|
849
|
+
for _i in range(len(step_base_durations) - 1):
|
|
815
850
|
try:
|
|
816
851
|
datain = next(rows_iter)
|
|
817
852
|
except StopIteration:
|
|
@@ -832,9 +867,17 @@ class TimelineConfig:
|
|
|
832
867
|
)
|
|
833
868
|
|
|
834
869
|
if timeseries_map[timeseries] == "average":
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
870
|
+
ds = step_base_durations[: len(values)]
|
|
871
|
+
if all(d == ds[0] for d in ds):
|
|
872
|
+
out_value = round(
|
|
873
|
+
sum(values) / len(values), 6
|
|
874
|
+
)
|
|
875
|
+
else:
|
|
876
|
+
# Rates per hour (profile, limits, prices):
|
|
877
|
+
# the new step keeps their time integral.
|
|
878
|
+
out_value = round(
|
|
879
|
+
sum(v * d for v, d in zip(values, ds)) / sum(ds), 6
|
|
880
|
+
)
|
|
838
881
|
else:
|
|
839
882
|
out_value = sum(values)
|
|
840
883
|
row.append(out_value)
|
|
@@ -884,15 +927,16 @@ class TimelineConfig:
|
|
|
884
927
|
pass
|
|
885
928
|
|
|
886
929
|
# Append per-step inflow contributions from p_node to
|
|
887
|
-
# pt_node_inflow only;
|
|
930
|
+
# pt_node_inflow only; times the number of time steps each new
|
|
931
|
+
# step combines (a constant inflow is energy per time step).
|
|
888
932
|
if timeseries == "pt_node_inflow.csv" and node__inflow:
|
|
889
933
|
for timeline in timelines_list:
|
|
890
934
|
new_timeline = self.timelines[timeline]
|
|
891
935
|
for node__value in node__inflow:
|
|
892
936
|
for timeline_row in new_timeline:
|
|
893
|
-
tl_step_duration = int(float(timeline_row[1]))
|
|
894
937
|
value = (
|
|
895
|
-
float(node__value[1])
|
|
938
|
+
float(node__value[1])
|
|
939
|
+
* len(base_durations[timeline_row[0]])
|
|
896
940
|
)
|
|
897
941
|
out_rows.append(
|
|
898
942
|
[node__value[0], timeline_row[0], value]
|
|
@@ -962,9 +1006,10 @@ class TimelineConfig:
|
|
|
962
1006
|
for n_name in dict.fromkeys(
|
|
963
1007
|
list(ts_sum) + list(const_for_node)
|
|
964
1008
|
):
|
|
1009
|
+
# A constant inflow is energy per time step: once per step.
|
|
965
1010
|
energy = (
|
|
966
1011
|
ts_sum.get(n_name, 0.0)
|
|
967
|
-
+ const_for_node.get(n_name, 0.0) *
|
|
1012
|
+
+ const_for_node.get(n_name, 0.0) * len(base_steps)
|
|
968
1013
|
)
|
|
969
1014
|
flow_rows.append([n_name, energy / duration_in_years])
|
|
970
1015
|
flow_path = wf / "solve_data" / "node_full_timeline_flow.csv"
|
|
@@ -992,12 +1037,59 @@ def _solves_in_model(solve_config: "SolveConfig") -> set[str]:
|
|
|
992
1037
|
return out
|
|
993
1038
|
|
|
994
1039
|
|
|
1040
|
+
def _base_steps_of_new_steps(
|
|
1041
|
+
old_steps: list, new_steps: list, logger: logging.Logger, *, solve_name: str, timeline_name: str,
|
|
1042
|
+
) -> dict[str, list[float]]:
|
|
1043
|
+
"""``{new step: [durations of the original steps it combines]}``.
|
|
1044
|
+
|
|
1045
|
+
The new steps (chunks of :func:`_aggregate_timeline_pieces`) partition
|
|
1046
|
+
the whole original timeline from its first step, each labelled by its
|
|
1047
|
+
first original step, so every original step belongs to the latest new
|
|
1048
|
+
step label seen on the walk.
|
|
1049
|
+
"""
|
|
1050
|
+
labels = {step[0] for step in new_steps}
|
|
1051
|
+
out: dict[str, list[float]] = {}
|
|
1052
|
+
current: list[float] | None = None
|
|
1053
|
+
for name, duration in old_steps:
|
|
1054
|
+
if name in labels:
|
|
1055
|
+
current = out.setdefault(name, [])
|
|
1056
|
+
if current is not None:
|
|
1057
|
+
current.append(float(duration))
|
|
1058
|
+
missing = [step[0] for step in new_steps if step[0] not in out]
|
|
1059
|
+
if missing:
|
|
1060
|
+
message = (
|
|
1061
|
+
f"Solve '{solve_name}': time steps {missing[:5]} of the aggregated timeline '{timeline_name}' are not "
|
|
1062
|
+
f"time steps of its original timeline."
|
|
1063
|
+
)
|
|
1064
|
+
logger.error(message)
|
|
1065
|
+
raise FlexToolConfigError(message)
|
|
1066
|
+
return out
|
|
1067
|
+
|
|
1068
|
+
|
|
1069
|
+
def _new_step_of_base_steps(old_steps: list, new_steps: list) -> list[tuple[str, str]]:
|
|
1070
|
+
"""``[(original step, the new step that combines it)]`` in timeline order: the walk of
|
|
1071
|
+
:func:`_base_steps_of_new_steps` (every original step belongs to the latest new step label seen)."""
|
|
1072
|
+
labels = {step[0] for step in new_steps}
|
|
1073
|
+
out: list[tuple[str, str]] = []
|
|
1074
|
+
current: str | None = None
|
|
1075
|
+
for name, _duration in old_steps:
|
|
1076
|
+
if name in labels:
|
|
1077
|
+
current = name
|
|
1078
|
+
if current is not None:
|
|
1079
|
+
out.append((name, current))
|
|
1080
|
+
return out
|
|
1081
|
+
|
|
1082
|
+
|
|
995
1083
|
def _aggregate_timeline_pieces(
|
|
996
1084
|
old_steps: list,
|
|
997
1085
|
timeset_blocks: dict[str, list],
|
|
998
1086
|
step_duration: float,
|
|
999
1087
|
logger: logging.Logger,
|
|
1000
1088
|
extra_cuts: dict[str, list[str]] | None = None,
|
|
1089
|
+
*,
|
|
1090
|
+
solve_name: str,
|
|
1091
|
+
timeline_name: str,
|
|
1092
|
+
check_fit: bool = True,
|
|
1001
1093
|
) -> tuple[list[tuple[str, str]], dict[str, list[tuple[str, int]]]]:
|
|
1002
1094
|
"""Aggregate a whole timeline to ``step_duration`` hours, piece by piece.
|
|
1003
1095
|
|
|
@@ -1005,12 +1097,23 @@ def _aggregate_timeline_pieces(
|
|
|
1005
1097
|
the runs between the block starts and block ends of ``timeset_blocks``
|
|
1006
1098
|
(``{timeset: [(start, count), ...]}``) and the steps in ``extra_cuts``
|
|
1007
1099
|
(``{owner: [step, ...]}``, e.g. representative base-period starts). Each piece is aggregated from its
|
|
1008
|
-
first step: a chunk closes
|
|
1100
|
+
first step: a chunk closes as soon as its steps add up to ``step_duration`` hours (within a relative
|
|
1101
|
+
tolerance of 1e-4, so steps entered with rounded fractions still fit), and a chunk always holds at least
|
|
1102
|
+
one step. The steps may have any length (0.5 h, 2 h, mixed). The
|
|
1103
|
+
tolerance is capped at half the shortest step, so a long new step still
|
|
1104
|
+
closes at the right step.
|
|
1009
1105
|
Returns the chunks ``[(first step, str(hours)), ...]`` in timeline order and
|
|
1010
1106
|
per timeset ``[(block start, number of chunks in the block), ...]`` (a block
|
|
1011
1107
|
whose start is not on the timeline is kept as given; ``get_active_time``
|
|
1012
1108
|
skips it). Logs a warning when a block ends with a shorter chunk, naming
|
|
1013
1109
|
the other timeset when its boundary is what cut the chunk short.
|
|
1110
|
+
|
|
1111
|
+
Raises :class:`FlexToolConfigError` (only with ``check_fit``, i.e. for a
|
|
1112
|
+
solve the model runs) when a chunk that starts inside a block
|
|
1113
|
+
would be longer than ``step_duration``: the new step is not a whole multiple
|
|
1114
|
+
of the timeline's steps, or (steps of different lengths) it would end inside
|
|
1115
|
+
a step. A gap chunk (outside every block, never active) may be longer, e.g.
|
|
1116
|
+
one long filler step between two blocks.
|
|
1014
1117
|
"""
|
|
1015
1118
|
index_of = {step[0]: i for i, step in enumerate(old_steps)}
|
|
1016
1119
|
n_steps = len(old_steps)
|
|
@@ -1033,6 +1136,12 @@ def _aggregate_timeline_pieces(
|
|
|
1033
1136
|
if label in index_of:
|
|
1034
1137
|
cut_owners.setdefault(index_of[label], set()).add(owner)
|
|
1035
1138
|
cuts = sorted(c for c in cut_owners if c < n_steps) + [n_steps]
|
|
1139
|
+
block_ranges = [(rng[1], rng[2]) for rngs in ranges.values() for rng in rngs if rng is not None]
|
|
1140
|
+
# Relative to the new step (rounded fractions like 0.333333 h still add
|
|
1141
|
+
# up), but below half a base step, so a long new step never closes one
|
|
1142
|
+
# base step early.
|
|
1143
|
+
positive = [float(step[1]) for step in old_steps if float(step[1]) > 0]
|
|
1144
|
+
tol = min(1e-4 * step_duration, 0.5 * min(positive)) if positive else 0.0
|
|
1036
1145
|
|
|
1037
1146
|
chunks: list[tuple[str, str]] = []
|
|
1038
1147
|
chunk_first: list[int] = []
|
|
@@ -1042,12 +1151,33 @@ def _aggregate_timeline_pieces(
|
|
|
1042
1151
|
while i < piece_end:
|
|
1043
1152
|
first = i
|
|
1044
1153
|
hours = 0.0
|
|
1045
|
-
while i < piece_end and (hours < step_duration or i == first):
|
|
1154
|
+
while i < piece_end and (hours < step_duration - tol or i == first):
|
|
1046
1155
|
hours += float(old_steps[i][1])
|
|
1047
1156
|
i += 1
|
|
1048
|
-
|
|
1157
|
+
label = old_steps[first][0]
|
|
1158
|
+
if (check_fit and hours > step_duration + tol
|
|
1159
|
+
and any(b_first <= first < b_end for b_first, b_end in block_ranges)):
|
|
1160
|
+
ds = [float(step[1]) for step in old_steps[first:i]]
|
|
1161
|
+
if all(d == ds[0] for d in ds):
|
|
1162
|
+
message = (
|
|
1163
|
+
f"Solve '{solve_name}': new_stepduration {step_duration:g} h is not a whole multiple of "
|
|
1164
|
+
f"the {ds[0]:g} h time steps of timeline '{timeline_name}' (the new time step starting "
|
|
1165
|
+
f"at '{label}' would be {hours:g} h long). Give a new_stepduration that is a whole "
|
|
1166
|
+
f"multiple of the timeline's time steps."
|
|
1167
|
+
)
|
|
1168
|
+
else:
|
|
1169
|
+
message = (
|
|
1170
|
+
f"Solve '{solve_name}': new_stepduration {step_duration:g} h does not fit the time steps "
|
|
1171
|
+
f"of timeline '{timeline_name}': the new time step starting at '{label}' would end inside "
|
|
1172
|
+
f"base time step '{old_steps[i - 1][0]}' ({hours:g} h in total). On a timeline with time "
|
|
1173
|
+
f"steps of different lengths, every new time step must end where a time step of the "
|
|
1174
|
+
f"timeline ends."
|
|
1175
|
+
)
|
|
1176
|
+
logger.error(message)
|
|
1177
|
+
raise FlexToolConfigError(message)
|
|
1178
|
+
chunks.append((label, str(hours)))
|
|
1049
1179
|
chunk_first.append(first)
|
|
1050
|
-
if hours < step_duration:
|
|
1180
|
+
if hours < step_duration - tol:
|
|
1051
1181
|
short_chunks.append((first, i, hours))
|
|
1052
1182
|
|
|
1053
1183
|
block_chunks: dict[str, list[tuple[str, int]]] = {}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""The original time steps behind each time step of a solve with ``new_stepduration``.
|
|
2
|
+
|
|
3
|
+
``TimelineConfig.create_averaged_timeseries`` writes ``solve_data/new_step_base_steps``: one row per original time
|
|
4
|
+
step of the coarsened timeline, ``time`` (the original step), ``new_step`` (the solve's time step that combines it;
|
|
5
|
+
its label is its first original step) and ``value`` (how many original steps that new step combines). A solve
|
|
6
|
+
without ``new_stepduration`` gets an empty frame, so a later uncoarsened solve never reads an earlier solve's
|
|
7
|
+
rows. An absent or empty frame means every solve step is one original step.
|
|
8
|
+
|
|
9
|
+
``inflow`` and ``peak_inflow`` are energy per original time step; a coarsened solve step carries the sum of its
|
|
10
|
+
original steps, so the inflow scaling divides by (or multiplies with) the number of steps it combines.
|
|
11
|
+
"""
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
import polars as pl
|
|
17
|
+
|
|
18
|
+
from flextool.engine.preprocess._provider_io import _provider_key
|
|
19
|
+
|
|
20
|
+
NEW_STEP_BASE_STEPS = "new_step_base_steps.csv"
|
|
21
|
+
NEW_STEP_BASE_STEPS_SCHEMA = {"time": pl.Utf8, "new_step": pl.Utf8, "value": pl.Float64}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def read_new_step_base_steps(solve_data_dir: Path, *, provider) -> tuple[dict[str, float], frozenset[str]]:
|
|
25
|
+
"""``({solve step: number of original steps it combines}, original steps absorbed into another step)``.
|
|
26
|
+
|
|
27
|
+
Both are empty when the solve has no ``new_stepduration``. The absorbed steps are the original steps that are
|
|
28
|
+
not a solve step themselves (their energy is in the solve step that combines them).
|
|
29
|
+
"""
|
|
30
|
+
df = provider.get(_provider_key(solve_data_dir / NEW_STEP_BASE_STEPS)) if provider is not None else None
|
|
31
|
+
if df is None or df.height == 0:
|
|
32
|
+
return {}, frozenset()
|
|
33
|
+
df = df.select(pl.col("time").cast(pl.Utf8), pl.col("new_step").cast(pl.Utf8),
|
|
34
|
+
pl.col("value").cast(pl.Float64))
|
|
35
|
+
n_of = {t: float(v) for t, s, v in df.iter_rows() if t == s}
|
|
36
|
+
absorbed = frozenset(t for t, s, _v in df.iter_rows() if t != s)
|
|
37
|
+
return n_of, absorbed
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def base_steps_of_solve_steps(solve_data_dir: Path, *, provider) -> dict[str, tuple[str, ...]]:
|
|
41
|
+
"""``{solve step: the original steps it combines, in timeline order}``; empty without ``new_stepduration``
|
|
42
|
+
(then every solve step is its own original step)."""
|
|
43
|
+
df = provider.get(_provider_key(solve_data_dir / NEW_STEP_BASE_STEPS)) if provider is not None else None
|
|
44
|
+
if df is None or df.height == 0:
|
|
45
|
+
return {}
|
|
46
|
+
out: dict[str, list[str]] = {}
|
|
47
|
+
for t, s in df.select(pl.col("time").cast(pl.Utf8), pl.col("new_step").cast(pl.Utf8)).iter_rows():
|
|
48
|
+
out.setdefault(s, []).append(t)
|
|
49
|
+
return {s: tuple(ts) for s, ts in out.items()}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def complete_steps_by_period(solve_data_dir: Path, periods: list[str], *, provider) -> list[tuple[str, str]]:
|
|
53
|
+
"""``[(period, complete step)]`` for every period in ``periods``: the steps of ``steps_complete_solve`` of the
|
|
54
|
+
periods ``d2`` with ``(d2, period)`` in ``period__branch`` — the mapping ``complete_hours_in_period`` sums the
|
|
55
|
+
hours of. A stochastic branch period has no complete steps of its own and gets its parent's; a period without a
|
|
56
|
+
``period__branch`` row keeps its own steps. When every period maps to itself the ``steps_complete_solve`` rows
|
|
57
|
+
are returned as they are (same order)."""
|
|
58
|
+
def _pairs(stem: str) -> list[tuple[str, str]]:
|
|
59
|
+
df = provider.get(_provider_key(solve_data_dir / stem)) if provider is not None else None
|
|
60
|
+
if df is None or df.height == 0 or df.width < 2:
|
|
61
|
+
return []
|
|
62
|
+
return [(str(a), str(b)) for a, b in df.select(df.columns[:2]).iter_rows()
|
|
63
|
+
if a is not None and b is not None and str(a) and str(b)]
|
|
64
|
+
|
|
65
|
+
complete = _pairs("steps_complete_solve.csv")
|
|
66
|
+
parents_of: dict[str, list[str]] = {}
|
|
67
|
+
for d2, d in _pairs("period__branch.csv"):
|
|
68
|
+
parents_of.setdefault(d, []).append(d2)
|
|
69
|
+
if all(parents_of.get(d, [d]) == [d] for d in periods):
|
|
70
|
+
return complete
|
|
71
|
+
steps_of: dict[str, list[str]] = {}
|
|
72
|
+
for d, t in complete:
|
|
73
|
+
steps_of.setdefault(d, []).append(t)
|
|
74
|
+
return [(d, t) for d in periods for d2 in parents_of.get(d, [d]) for t in steps_of.get(d2, ())]
|