Project workflow — RunBatch()
A project is a list of Settings snapshots — each snapshot a
frozen configuration for one analysis. The project workflow lets you
save many configurations to a single file, then execute all of them
sequentially with one call to una.RunBatch(). This is the tool of
choice when you need to run the same analysis with different parameters
(multiple radii, multiple destination categories, multiple scenarios)
without editing UNA_Workspace.py by hand.
When to use the project workflow
Reach for RunBatch() when:
You want to run the same analysis on many destination categories — schools, jobs, transit, retail, healthcare, parks — with different search radii, weights, or decay parameters per category.
You want to run scenario comparisons — same OD layers, different turn/elevation settings; or same settings, different network files representing before/after conditions.
You want your analysis to be reproducible — a project file is a self-contained, reviewable, version-controllable record of every parameter used.
For a single one-off analysis, RunAccessibility() /
RunFlow() / RunODM() directly are simpler.
The Project object
The UNA instance carries a projects list — initially empty. You
populate it with SaveSettingsToProject(), which appends a deep copy
of the current una.settings to the list. Because it’s a deep copy,
subsequent edits to una.settings do not affect the saved entries.
from urban_network_analysis import UNA
una = UNA()
# Build a project in code
una.settings.data_folder = r"Boston"
una.settings.network_file = "20260703_PercLenNetwork_InnerCore.geojson"
una.settings.origins_file = "Cambridge_building_centroids.geojson"
una.settings.destinations_file = "MA_bus_stops.geojson"
una.settings.search_radius = 500
una.settings.name = "bus_500m"
una.SaveSettingsToProject()
una.settings.search_radius = 1500
una.settings.name = "bus_1500m"
una.SaveSettingsToProject()
una.settings.destinations_file = "schools_cambridge.geojson"
una.settings.search_radius = 800
una.settings.name = "schools_800m"
una.SaveSettingsToProject()
The una.settings.name field is the human-readable label for each
snapshot. It becomes the output_file_name when the row runs, so
outputs are self-labeled.
You can inspect the project list at any time — it’s just a list of
Settings objects.
Exporting a project to file
Two formats are supported:
# JSON — human-readable, git-friendly
una.ExportProjectAsJSON(folder=r"./Settings", file_name="boston_walkscore.json")
# CSV — spreadsheet-editable
una.ExportProjectAsCSV(file_name="boston_walkscore.csv")
The compact mode of both writers omits fields that match their defaults, keeping the file to only the fields you actually changed. This is the recommended default — you get a diff-friendly artifact listing exactly what varies per row.
una.ExportProjectAsJSON(folder=r"./Settings", file_name="boston.json",
compact=True) # default: only non-default fields
una.ExportProjectAsJSON(folder=r"./Settings", file_name="boston_full.json",
compact=False) # every field written out
Note
ExportProjectAsCSV() writes to settings.data_folder so the
project file sits next to the data files it references. Set
data_folder before calling if you need a specific output
location. The CSV export also drops the data_folder column
itself, because on load it’s recovered from the CSV file’s
directory.
Running a project
Two modes: run whatever’s already in self.projects, or load a file
and run it in one call.
# Mode 1: run whatever was populated in code
una.RunBatch("accessibility")
# Mode 2: load from file, then run
una.RunBatch("accessibility", pairing_file=r"./Settings/boston.json")
una.RunBatch("flow", pairing_file=r"Boston/Boston_Flow_pairings.csv")
The first argument tells UNA which run method to invoke per row —
"accessibility" calls RunAccessibility(), "flow" calls
RunFlow(). Rows are executed sequentially. Each row’s output lands
under its own timestamped subfolder inside
<data_folder>/Results/, labeled with the row’s name.
When pairing_file is provided, self.projects is replaced by the
loaded entries — the file is authoritative.
Loading a CSV/TSV/JSON project
Column names in a CSV must match Settings field names exactly.
Unknown columns are silently ignored, so extra bookkeeping columns
(flow_name, notes, owner) can live alongside real settings
without breaking the loader. Empty cells and nan values are treated
as “use the default” for that field.
A minimal three-column pairing CSV:
name,destinations_file,search_radius
bus_500m,MA_bus_stops.geojson,500
schools_800m,schools_cambridge.geojson,800
metro_1500m,MA_metro_stations.geojson,1500
When loaded via pairing_file="pairings.csv", UNA:
Creates a fresh
Settingsobject per row.Calls
settings.ApplyRow(row)to apply each column onto its matching field.Fills
data_folderfrom the CSV file’s directory if not present.Appends the configured Settings object to
self.projects.When you then call
RunBatch("accessibility"), iterates the list and dispatches to the appropriate run method.
Important
Row file paths resolve relative to the pairing CSV’s own
directory. When a row leaves data_folder blank (the usual
case), UNA sets it to the folder containing the CSV — so
network_file, origins_file, and destinations_file are
found relative to the CSV’s location, including relative paths like
../network/streets.geojson. This makes a pairing table
portable: keep the CSV in a fixed position relative to the data and
the same file runs unchanged on any machine, regardless of where
the drive or sync folder is mounted. A row can opt out by filling
its own data_folder column or by using absolute file paths.
The driver script does not override this: setting
data_folder on una.settings before RunBatch has no
effect on rows. The only script-level path RunBatch honors is
output_folder, used as a fallback for rows whose
output_folder is blank — that is the per-machine knob for
directing results.
The JSON format is functionally identical — a top-level JSON array of settings objects. Use it when you want git-friendly diffs or programmatic generation from another tool.
Converting old CSVs to JSON
If you have a CSV project and want to convert it to JSON without running:
una.ConvertProject_csv_to_json(
csv_file="pairings.csv",
json_file="pairings.json",
compact=True, # only fields that differ from defaults
)
Composite output — merging rows into joint files
Beyond per-row outputs, RunBatch() can merge the results of many
rows into composite files with a sum column — the mechanism behind
WalkScore-style indices. Any row with
settings_reference:batch_composite_output = TRUE has its
result column (chosen by
settings_reference:batch_composite_result_column) captured
as the batch runs; after the last row, UNA joins the captured columns
onto their layer and writes the result to a
composite_<timestamp> folder under Results/.
Join targets. Per-origin metrics (reach, gravity_*,
knn_access) join onto the row’s origins layer — one value per
origin point. edge_flow joins onto the network layer;
node_flow onto network nodes.
Grouping by join layer. Rows are grouped by their join layer, and
one composite file is written per group. A WalkScore-style project
where every row shares the same origins file yields a single
composite file: one column per row (named
<metric>_<row name>) plus a final
settings_reference:batch_composite_sum_column_name column
(default composite_sum) summing them. A project whose rows use
several different origin layers — e.g. a town-wide pairing table
with “Homes to …”, “Jobs to …”, and “Schools to …” rows — yields one
composite per origin layer, each named after it:
composite_home_state_portland, composite_jobs_state_portland,
and so on. Each group gets its own sum column over just its own rows.
Output formats. The composite honors the same output_geojson /
output_feather / output_csv flags as engine exports. If all
three are FALSE on the final row, a CSV is written as a fallback so a
requested composite is never silently dropped.
The composited results also stay available in memory after the batch:
una.composite_results is a list of (group_name, GeoDataFrame)
pairs, and una.composite_result is the first (or only) composite —
convenient for immediate inspection or plotting.
A complete example
In code:
from urban_network_analysis import UNA
una = UNA()
una.settings.data_folder = r"Boston"
una.settings.network_file = "20260703_PercLenNetwork_InnerCore.geojson"
una.settings.origins_file = "Cambridge_building_centroids.geojson"
una.settings.turns = True
una.settings.elevation = True
for radius, dest_file, dest_col, name in [
( 500, "MA_bus_stops.geojson", "weekly_departures", "bus"),
( 800, "schools_cambridge.geojson", "W", "schools"),
(1500, "MA_metro_stations.geojson", "weekly_departures", "metro"),
(1500, "Cambridge_transit_stations.geojson", "weekly_departures", "transit"),
]:
una.settings.destinations_file = dest_file
una.settings.destination_weight_column = dest_col
una.settings.search_radius = radius
una.settings.name = name
una.SaveSettingsToProject()
# Save + run
una.ExportProjectAsJSON(folder=r"./Settings", file_name="boston_walkscore.json")
una.RunBatch("accessibility")
Four accessibility flows run in sequence, each producing its own
timestamped output. When you’re done you can commit
boston_walkscore.json to git as a self-describing record of the
analysis.
From a file, later:
from urban_network_analysis import UNA
una = UNA()
una.RunBatch("accessibility", pairing_file=r"./Settings/boston_walkscore.json")
Reproducing the four-flow batch from the JSON.
Cleaning up
If you want to reset the in-memory project list without exiting Python:
una.ClearProject()
self.projects is emptied. The next
SaveSettingsToProject() call starts a fresh list.
Behavior notes
Settings leak. RunBatch() sets self.settings = row_snapshot
for each row as it executes. After the batch, self.settings holds
the last row’s values, not what it held before RunBatch() was
called. If you interactively call another method afterward, be aware
that the settings you’ll be running with are the last row’s, not your
originals.
Missing required fields. Rows whose network_file, origins_file,
or destinations_file are blank are logged as “skipped” and the
batch continues with the next row. This is useful when you’re
prototyping a wide CSV where not every row has the required minimum
yet.
Topology caching. For rows that share the same (network, origins,
destinations) triple, RunBatch() reuses the built topology
between rows rather than rebuilding it — a significant speedup for
projects that only vary decay parameters or search radius.
Next steps
RunAccessibility() — the per-row method for accessibility rows.
RunFlow() — the per-row method for flow rows.
Tutorial 2 — Accessibility step-by-step (Boston) — a worked WalkScore-style batch example.
UNA — the
RunBatch()method signature.