---
title: Facade layout schedule
source: https://infrared.city/docs/sdk/1.0/python/facade_layout_schedule/
---

# Facade layout schedule

Derive `synthesize_facade_layout` inputs from a saved `AreaSchedule`.

A tiled facade run is made of many tiles, so a caller reloading one should not have to recompute each tile's frame by hand. This module derives `site_origin` and `jobs` from the run's saved `AreaSchedule`, using the same computation `run_area` used to anchor each tile when it submitted it, so a schedule-derived `tile_origin` cannot drift from the one the live submission used.

## tile_origin_of

```python
tile_origin_of(schedule: 'AreaSchedule', job_id: str) -> Tuple[float, float]
```

Return the `(lon, lat)` of a job's tile south-west corner.

This is the same computation `run_area` used to anchor that tile when it submitted it.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `schedule` | `[AreaSchedule](../tiling/#infrared_sdk.tiling.AreaSchedule)` | The saved schedule of a tiled run. | *required* |
| `job_id` | `str` | A job id from `schedule.jobs`. | *required* |

Returns:

| Type | Description |
| --- | --- |
| `tuple of float` | `(lon, lat)` of the tile's south-west corner. |

Raises:

| Type | Description |
| --- | --- |
| `ValueError` | If `job_id` is not one of the values of `schedule.jobs`, or if `schedule.polygon` has no usable origin. |

## jobs_from_schedule

```python
jobs_from_schedule(
schedule: "AreaSchedule",
) -> Tuple[Tuple[float, float], List["FacadeLayoutJobSpec"]]
```

Return `(site_origin, jobs)` for every job a saved tiled run submitted.

Each job's building ids come from `schedule.batch_membership`. It is `None` on an untiled or non-facade schedule, and each job's `active_ids` is then `None` too, which `synthesize_facade_layout` reads as "every building". Jobs follow the sorted order of the schedule's keys, so the `jobs` list is deterministic.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `schedule` | `[AreaSchedule](../tiling/#infrared_sdk.tiling.AreaSchedule)` | The saved schedule of a tiled run. | *required* |

Returns:

| Type | Description |
| --- | --- |
| `tuple` | `site_origin` as `(lon, lat)`, and the list of `FacadeLayoutJobSpec`, one per scheduled job. |

Raises:

| Type | Description |
| --- | --- |
| `ValueError` | If `schedule.polygon` has no usable origin. |

## apply_site_frame_shift

```python
apply_site_frame_shift(
layout: "FacadeLayout", schedule: "AreaSchedule"
) -> None
```

Move a schedule-derived rebuild from its tile frames into the site frame.

A rebuild made with `schedule=` comes back with each job's frames in that tile's own local frame. The merged `SurfaceColumns` of the live run is in the site frame, so this adds each job's tile south-west offset to its coordinates. Without this step `attach_values` refuses every tiled surface.

`frame.origin`, `job.points` and `job.cell_tris` are shifted. Axes and normals are directions and are unaffected by a translation.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `layout` | `[FacadeLayout](../facade_layout/#infrared_sdk.facade_layout.FacadeLayout)` | The rebuilt layout. Its `jobs` are modified in place. | *required* |
| `schedule` | `[AreaSchedule](../tiling/#infrared_sdk.tiling.AreaSchedule)` | The saved schedule of the tiled run the layout was rebuilt from. | *required* |

Raises:

| Type | Description |
| --- | --- |
| `ValueError` | If a job of `layout` is not in `schedule`. |
