~/Files/:
~/Files/hazelbean/hazelbean_dev~/Files/seals/seals_dev~/Files/, not inside site-packages:seals_dev/ holds more than the library — docs, tests, scriptsseals_dev/seals subdirectory. The nesting looks redundant but is how Python packaging works__init__.py is what makes the directory importable as a packageseals_main.py, seals_tasks.py, seals_generate_base_data.py — task functions, the actual model logicseals_initialize_project.py — the task-tree buildersseals_utils.py — helpersrun_seals_standard.py — the run fileseals_main.py directlyseals_dev/seals:
run_seals_standard.py — three scenarios, 2030 and 2050run_seals_standard_test.py — the same pipeline pared to a baseline, one BAU scenario, one year, Rwanda. Start hererun_seals_standard.py. It is about 60 lines and has three partsbuild_task_tree(p) answers one question: what is this pipeline?run_project(p) answers how is it executed? It takes only prun_project(p) sets what no variant ever changes — base data location, processing resolutiondef run_project(p):
p.run_in_parallel = 1 # before the tree: it has parallel iterators
build_task_tree(p)
p.skip_tasks(p.tasks_to_skip)
p.base_data_dir = os.path.join(p.user_dir, 'Files', 'base_data')
p.processing_resolution = 1.0
p.scenario_definitions_path = os.path.join(p.input_dir, p.scenario_definitions_filename)
seals_initialize_project.initialize_scenario_definitions(p)
seals_initialize_project.set_advanced_options(p)
p.execute()
return phb.ProjectFlow() is a class — a recipe for an object. Calling it produces an object, which we assign to pp carries the project’s attributes: p.base_data_dir, p.scenario_definitions_filename, and so onp.add_task(), p.skip_tasks(), p.get_path(), p.execute()p and reads its configuration from it. That is how configuration set in __main__ reaches code deep in the library~/Files/seals/projects/<project_name>/seals_devrun_mode decides how much prior work is reused:
'check' — reuse the stable dir, recompute only what is missing (the default)'fresh_intermediate' — redo all computation, keep input/ (test projects only)'full' — a fresh timestamped dir; everything re-runsp from the row it is on — which is why scenario-varying values belong in the CSV and not in the run fileinput_template/ beside the run file. ProjectFlow copies anything missing into the project’s input/ on first run and never overwrites your working copyscenario_type is a column in the CSV, not something a run file setsbaseline — the observed anchor; not downscaled, supplies base-year LULCpolicy — a trajectory to downscale, compared against a counterfactualbau — business-as-usual, being deprecated in favour of baseline; it still appears in shipped CSVsp.get_path(), which searches the project input/ dir, then base_data, then a cloud bucket, downloading what is missingp.base_data_dir is where those downloads land. Point it somewhere with room for very large files; the same base data serves every projectbase_data to match the bucket convention~/Files/seals/projects/seals_standard_test/intermediate/stitched_lulc_simplified_scenarios/, for example:lulc_esa_seals7_ssp2_rcp45_luh2-message_bau_2030.tif