Pipeline¶
The end-to-end chain: clean vectors, generate units, fill heights, read land cover, compute
parameters, classify, write outputs. run_pipeline is the only place the stages are wired
together, and the command line calls it rather than restating any of it.
lczkit.pipeline
¶
The whole chain, from a bbox to a run directory and optionally a map site.
run_pipeline is the only place the stages are wired together; the command line calls it. It does
not validate: agreement needs reference data that is not always on disk, so call
lczkit.validation yourself where you have it. StageObserver lets a caller watch the stages
without this module choosing a rendering.
StageObserver
¶
Bases: Protocol
Something that watches each stage begin and end.
PipelineResult
dataclass
¶
PipelineResult(outputs: RunOutputs, site: SiteReport | None, site_skipped: str | None = None, stages: dict[str, float] = dict(), height_products: dict[str, str | None] = dict())
What a run produced, and how long each stage took.
site
instance-attribute
¶
site: SiteReport | None
None when the run was asked not to build one, or when tippecanoe is absent.
site_skipped
class-attribute
instance-attribute
¶
Why no site was built, where one was asked for. The site is the last stage, so a missing
tippecanoe costs only the site; lczkit site build <run_dir> completes it later.
stages
class-attribute
instance-attribute
¶
Wall seconds per stage, in the order they ran.
height_products
class-attribute
instance-attribute
¶
The raster each enabled areal tier resolved to, by tier name; None where the product has
no coverage for this extent (a disabled tier is absent instead).
build_strategy
¶
build_strategy(config: UnitsConfig, *, buildings: GeoDataFrame | None = None) -> SpatialUnitStrategy
The configured SpatialUnitStrategy.
buildings is read only by patch with patch_merge_on_morphology on; it goes to the
constructor because the protocol's generate(bbox, barriers) has no use for it elsewhere.
Source code in src/lczkit/pipeline.py
land_cover_source
¶
land_cover_source(settings: Settings, bbox: BBox) -> RasterSource
The configured land-cover backend (LandCoverConfig.source).
The local backend mosaics the ESA WorldCover tiles the extent spans into the run directory; a
clip keyed to one run is not source data, so it never goes under input/. The Earth Engine
backend caches its own reductions under input/GEE/.
Source code in src/lczkit/pipeline.py
run_pipeline
¶
run_pipeline(settings: Settings, bbox: BBox, *, build_site_after: bool = True, observer: StageObserver | None = None, extent: ExtentRecord | None = None) -> PipelineResult
Clean, fill heights, classify, write a run directory and optionally build its map site.
settings must carry a runnable configuration; lczkit.presets.apply_preset fills the
thresholds that default to None. Nothing existing under input/ is modified. extent
records how bbox was chosen (a named place, a So2Sat window, or the bbox alone) for the
manifest.
Source code in src/lczkit/pipeline.py
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 | |
Raster windows¶
Clipping a raster to a study window, and checking that what came back actually covers it. The check
matters because neither half fails loudly on its own: read(window=…) returns a smaller array
rather than raising when the window runs off the edge of a raster, and units the raster never
reached come back as all-NaN fractions by design. Together that is a partly missing map with
nothing raised.
lczkit.raster_window
¶
Raster windowing shared by the places in the package that read or clip a raster.
The height cascade reads a mean per building footprint; the land-cover sources read class
fractions per spatial unit. Those are different reductions over different libraries, but
both begin by finding the one window of a raster that covers a set of geometries, and getting the
edge padding wrong is a quiet off-by-one rather than a crash. It lives here, next to crs.py,
because it belongs to neither phase.
clip_raster and coverage_shortfall join them because a run has to materialise a window before
it can reduce over one — the global land-cover and reference products are read remotely and written
into the run directory. See lczkit.sources.worldcover.
covering_window
¶
covering_window(src: DatasetReader, bounds: ndarray | tuple[float, float, float, float]) -> Window | None
The raster window covering bounds, padded one cell and clipped to the raster.
bounds is (minx, miny, maxx, maxy) in the raster's own CRS. Returns None when it falls
entirely outside the raster, which callers report as "this product cannot answer" rather than
as an error.
The one-cell pad matters at the edges: a geometry whose boundary sits exactly on a cell boundary still touches the cell beyond it, and that cell has to be inside the window to be counted at all.
Source code in src/lczkit/raster_window.py
clip_raster
¶
clip_raster(source: str, destination: Path, bbox: BBox) -> Path
Window source to bbox and write it into the run directory, preserving nodata and CRS.
Source code in src/lczkit/raster_window.py
coverage_shortfall
¶
coverage_shortfall(bounds: tuple[float, float, float, float], bbox: BBox, res: float) -> dict[str, float]
How far a raster's bounds fall short of bbox on each side, in pixels.
Empty when the raster covers the window. A shortfall under one pixel is not reported: a clip lands on cell boundaries, so a fraction of a cell is rounding rather than missing ground.
Separated out because the failure this guards against is silent. clip_raster windows with
from_bounds and then read(window=...), which returns a smaller array rather than
raising when the window overruns the source, and LocalRasterSource.fractions turns units
with no coverage into all-NaN rather than an error. Both behaviours are correct on their
own; together they let a raster that covers a quarter of the requested window produce a map
with a quarter of its land cover missing and nothing anywhere saying so.