Skip to content
View as Markdown llms.txt

Layers (weather)

Weather data and grid image generation.

WeatherServiceClient

Bases: ScrubbedSessionState

Client for weather data and grid-image generation.

static_base_url selects the public catalog host. api_key, base_url and gateway_base_url are accepted for construction compatibility with the other service clients and are unused: the catalog is public, and no credential ever goes to that host.

logger instance-attribute

logger: Logger = logger

Logger used for fetch, retry and debug messages.

base_url instance-attribute

base_url: str = base_url

The service base URL passed at construction (unused by this client).

close

close() -> None

Close the static reader's session.

get_weather_file_from_location

get_weather_file_from_location(
    *, lat: Latitude, lon: Longitude, radius: Optional[int] = None
)

Return the nearest public weather stations, nearest first.

Parameters:

Name Type Description Default
lat Latitude

Latitude of the point, in degrees.

required
lon Longitude

Longitude of the point, in degrees.

required
radius int

Search radius in kilometres. Default 100.

None

Returns:

Type Description
list of dict

Up to 10 catalog rows (station metadata), nearest first.

Raises:

Type Description
WeatherServiceError

If the catalog cannot be fetched or decoded.

get_weather_file_from_identifier

get_weather_file_from_identifier(*, identifier: str)

Return one public weather station's data by uuid or fileName.

Parameters:

Name Type Description Default
identifier str

The station's uuid or fileName in the public catalog.

required

Returns:

Type Description
dict

The station's data object.

Raises:

Type Description
WeatherServiceError

If the identifier is not in the public catalog, or the catalog or station cannot be fetched or decoded. Private and custom-EPW files are not in the catalog; use parse_epw for those.

parse_epw

parse_epw(source, **options)

Read one local .epw file and validate it.

The bring-your-own weather entry point, and the only one for a file that is not in the public catalog. Nothing is uploaded, nothing is registered and no request leaves this process. Pass the returned WeatherDocument straight to from_weatherfile_payload and keep it for the retry, because its identity is what proves a resume uses the same weather.

Parameters:

Name Type Description Default
source (str, bytes, bytearray or PathLike)

A path to the .epw file, or the file's text (a str with a line end, or bytes).

required
**options

max_bytes and max_rows: tighten the size and row bounds. See parse_epw.

{}

Returns:

Type Description
WeatherDocument

The validated weather document.

Raises:

Type Description
EpwParseError

If the file is unreadable or not a usable EPW file.

filter_weather_data

filter_weather_data(
    *,
    identifier: Optional[str] = None,
    weather: Any = None,
    time_period: TimePeriod,
)

Return weather filtered to time_period, one record per hour.

Give EITHER identifier (a public catalog station, by uuid or fileName) OR weather (a WeatherDocument from parse_epw). The BYO document is accepted everywhere a station id is, runs entirely on your machine and makes no request at all; the window means the same thing for both.

Parameters:

Name Type Description Default
identifier str

A public catalog station, by uuid or fileName.

None
weather WeatherDocument

A document from parse_epw.

None
time_period TimePeriod

The window: a date span with a daily hour range.

required

Returns:

Type Description
list of WeatherDataPoint

One record per hour inside the window.

Raises:

Type Description
ValueError

If neither or both of identifier and weather are given.

WeatherServiceError

For an identifier: if it is not in the public catalog, or the catalog or station cannot be fetched or decoded.

WeatherModelInputsError

For weather: if the document cannot be filtered to the window.

gen_grid_image

gen_grid_image(
    *,
    grid: Sequence[Sequence[Any]],
    analysis_type: Optional[str] = None,
    criteria: Optional[str] = None,
    subtype: Optional[str] = None,
    max_long_axis_px: Optional[int] = DEFAULT_MAX_LONG_AXIS_PX,
    renderer: Any = REMOVED,
)

Render a result grid to a PNG and return the raw PNG bytes.

The grid is coloured with the public colour registry (registry.infrared.city; no API key, cached per process) for the analysis type you name. The image is 1:1, one pixel per grid cell, up to a 960 px long axis. A failure raises WeatherServiceError; you never get a fallback-coloured image when the registry colours cannot be loaded.

Parameters:

Name Type Description Default
grid sequence of sequence

Rows of cells: numbers, None (no data), or wind-comfort class labels ("A".."E", "S", "S15", "S20").

required
analysis_type str

Registry analysis type used to pick the colours. Omit it to colour the grid with the default magma_r ramp.

None
criteria str

Criteria key for an analysis type with several variants.

None
subtype str

Subtype key for an analysis type with several subtypes.

None
max_long_axis_px int

Cap on the long axis of the image, in pixels. Default 960. A larger grid is sampled nearest-neighbour on the VALUES, so it keeps its aspect ratio and its no-data cells; None or 0 renders every cell. Read the image size and the scale factor with infrared_sdk.layers.image_local.grid_image_size.

DEFAULT_MAX_LONG_AXIS_PX
renderer Any

Removed. Passing it raises TypeError.

REMOVED

Returns:

Type Description
bytes

The PNG file contents.

Raises:

Type Description
WeatherServiceError

If the grid is malformed, the colour registry cannot be loaded, or rendering fails.

EpwParseError

Bases: ValueError

An EPW file that was refused, with the reason.

A ValueError subclass, so a caller that already catches ValueError around parse_epw keeps working. The named type is what lets a caller separate a bad FILE from a bad request.

WeatherDocument

One validated EPW file.

Hold it, pass it to a payload builder, and keep it for the retry: its identity is what proves a resumed run uses the same weather as the run it resumes.

Warnings

The identity is computed on every read, never cached. The document is a plain dict you can reach and change, and if you edit it after submitting, the retry is refused rather than served a stale digest that says the weather is unchanged. Computing it hashes the weather columns; it does not re-parse the file.

Attributes:

Name Type Description
document dict

The parsed file as plain data (schema, location, period, time, fields, values, missing and identity), so it round-trips through json.

source_path str or None

Where the bytes came from, used in messages. It is never hashed: two copies of one file under two names are the same weather.

identity property

identity: str

The versioned weather identity, "sha256:<hex>".

It covers the validated values, their order, the location, the calendar columns and the hour basis, and never the file name, a station id or the raw text, so two differently formatted files with the same readings share one identity.

Raises:

Type Description
EpwParseError

If the document is too malformed to have an identity.

location property

location: Mapping[str, Any]

The EPW LOCATION header, as the document records it.

period property

period: Mapping[str, Any]

Row count, records per hour, leap-year and full-year verdicts.

rows property

rows: int

Data rows in the file, before any window is applied.

to_dict

to_dict() -> Dict[str, Any]

Return the document itself, as plain data.

Serialise it with json.dumps.

filter_hours

filter_hours(time_period: TimePeriod) -> List[WeatherDataPoint]

Return the file's hours inside time_period, one record per hour.

The same shape WeatherServiceClient.filter_weather_data returns for a public station, from a local file and with no network call. The window is a date span with a daily hour range, exactly the hours the model counts. A window that crosses the year end (for example 1 December to 28 February) keeps its hours in calendar order of the year: January, February, then December.

Parameters:

Name Type Description Default
time_period TimePeriod

The analysis window.

required

Returns:

Type Description
list of WeatherDataPoint

One record per hour inside the window.

Raises:

Type Description
WeatherModelInputsError

If the file cannot be filtered to that window.

model_inputs

model_inputs(
    *,
    analysis_type: str,
    time_period: TimePeriod,
    subtype: Optional[str] = None,
    solar_model: Optional[str] = None,
) -> Dict[str, Any]

Return the snake_case weather arrays one model reads, for one window.

The window is applied first, then the required fields are checked on the FILTERED rows, then the period rule, so a gap outside the window is harmless, a gap inside it raises, and a model that needs a full year raises on a shorter one.

solar_model belongs to analysis_type="energy-balance", the one analysis that reads it; on any other analysis it raises, because nothing would read it there. solar_model="irradiance" selects the interior-irradiance input set and its full-year rule; omitted, or "legacy-flat", selects the two climate arrays that model reads.

To RUN energy-balance with a file, use from_weather, which calls this method with the full-year window and the request's own solar_model.

Parameters:

Name Type Description Default
analysis_type str

The analysis type, e.g. "thermal-comfort-index".

required
time_period TimePeriod

The analysis window.

required
subtype str

The analysis subtype, for analyses that have several.

None
solar_model str

"legacy-flat" or "irradiance"; only valid for analysis_type="energy-balance".

None

Returns:

Type Description
dict

The weather arrays the model reads, keyed by snake_case field name.

Raises:

Type Description
WeatherModelInputsError

If the document cannot supply what the model needs for this window.

WeatherModelInputsError

Bases: ValueError

The document cannot supply what the requested model needs.

Raised for a gap in a required column inside the selected window, for a window shorter than a full year where the model needs one, and for an analysis that has no weather input set. Always raised before submission.

parse_epw

parse_epw(
    source: Union[str, bytes, bytearray, PathLike],
    *,
    max_bytes: Optional[int] = None,
    max_rows: Optional[int] = None,
) -> WeatherDocument

Read and validate one .epw file, and return its document.

Parameters:

Name Type Description Default
source (str, bytes, bytearray or PathLike)

A path (str without a line end, or Path), or the file's text (str with a line end, or bytes).

required
max_bytes int

Lower the built-in size bound (16 MiB). It may only be TIGHTENED; asking for a wider bound raises rather than being ignored.

None
max_rows int

Lower the built-in row bound (8784 rows). It may only be TIGHTENED; asking for a wider bound raises rather than being ignored.

None

Returns:

Type Description
WeatherDocument

The validated document, ready for from_weatherfile_payload.

Raises:

Type Description
EpwParseError

For every file that is refused: no LOCATION header, a location number out of range, sub-hourly data, a row shorter than 22 columns, an hour outside 1-24, a calendar cell that is not a number, or a file over the size or row bound. The message names the row or the field.