Model run views

Model run views are custom, parameterized reports that visualize a model run’s output in the pd4castr UI. Each view is its own page in a model’s Model Run Views section, where a viewer picks a model run, sets the view’s parameters, and sees the result rendered as a chart, a table, or both.

A view runs a SQL query over the selected run’s output and your model’s supporting data. This lets you reshape and aggregate run results into a purpose-built report, beyond the forecast chart that outputs define. Views build on datasets, which supply the static reference data a view query joins against.

When to use a view

Use a view when you want to give users a dedicated report over a model run, with its own parameters, chart, and table. For example:

  • A summary that aggregates fine-grained output into a compact chart and table.
  • A breakdown that joins output against a dataset, such as labeling result rows with friendly names from a reference table.
  • A parameterized report where users pick a value (such as a region or scenario) from a dropdown and the report recomputes for that selection.

If you only need to plot forecast series over time, the forecast chart that outputs define already covers that. To summarize input data rather than run results, use input aggregations.

How a view appears in the UI

Each view is a separate page under a model’s Model Run Views section, and users switch between a model’s views with the view selector. On a view page, the viewer chooses which model run to inspect, sets the view’s parameters, and the view query runs against that run.

The result renders as a chart, a table, or both, depending on the view’s columns:

  • A chart plots the first dimension column on the x-axis and draws one line per measure column. A view renders a chart only when every measure declares the same non-empty unit. Otherwise it falls back to a table.
  • A table shows every returned column in query order, with each measure’s unit appended to its header.

See Columns for how role, unit, and label shape this.

How a view query works

A view is a SQL query, stored in a file in your project, that the platform runs against a model run. The query has these tables in scope:

  • output: the rows your model produced for the run.
  • dataset_<key>: one table per declared dataset, named from its key (for example, dataset_regions).
  • input_<key>: one table per declared input, named from its key (for example, input_demand).

Datasets and inputs are namespaced by kind so an input and a dataset that share a key don’t collide.

The query reads any parameters through getvariable(). For example, a region parameter is read as getvariable('region'). Each column the query returns must be declared in columns, and each columns entry must match a returned column.

Configure views

Add views in the views array in your .pd4castrrc.json file. Each view points to a local SQL file and declares the columns its query returns.

FieldTypeRequiredDescription
keystringYesUnique identifier for the view. Must be lowercase alphanumeric, with hyphens or underscores.
namestringYesDisplay name for the view, shown in the pd4castr UI.
sqlstringYesPath to the view’s SQL file, relative to your project root.
paramsobjectNoMap of parameter name to parameter configuration. See Parameters.
columnsarrayYesMetadata for each column the query returns. See Columns.

A minimal view with no parameters looks like this:

{
  "views": [
    {
      "key": "daily_average",
      "name": "Daily average price",
      "sql": "views/daily_average.sql",
      "columns": [
        { "key": "day", "role": "dimension", "label": "Day" },
        {
          "key": "avg_price",
          "role": "measure",
          "label": "Average price",
          "unit": "$/MWh"
        }
      ]
    }
  ]
}

Parameters

Parameters let users drive a view query from the UI. You declare each parameter under params, keyed by the variable name the query reads with getvariable().

FieldTypeRequiredDefaultDescription
typestringYesValue type: string, number, or boolean.
labelstringYesDisplay label shown above the parameter’s form field.
descriptionstringNoExplanatory text shown in an info tooltip beside the label. Maximum 500 characters.
optionalbooleanNofalseWhether the parameter can be left unset. An unset parameter binds to NULL.
controlstringNoUI control for the parameter. Currently only select (a dropdown) is supported.
optionsstringselect onlyPath to a SQL file whose rows populate the dropdown. Required for select, invalid otherwise.
defaultFromstringNoResolve this parameter’s default from another select parameter’s option metadata. See below.
samplestring | number | booleanRequired non-selectA representative value the CLI uses to test the view when you publish. See Sample values.

Every declared parameter must be referenced at least once with getvariable() in the view SQL or its options SQL, and every getvariable() reference must map to a declared parameter.

Select parameters and the options query

A select parameter shows a dropdown populated by a separate options query. The options query must return these columns:

ColumnTypeRequiredDescription
valuestring | number | booleanYesThe value bound to the parameter when the option is selected. Must be non-null and unique.
labelstringYesThe text shown for the option in the dropdown.
metadataJSON objectNoPer-option data. Powers dependent parameters and dependent field pre-fill in the UI.

The first option row is the default selection. Use json_object() to build the metadata column.

Optional parameters

Mark a parameter optional: true when the user can leave it unset. An unset optional parameter binds to NULL, so the view SQL must handle the null case, typically with coalesce().

Dependent parameters

Use defaultFrom to default one parameter from another parameter’s selection. The reference takes the form <sourceParam>.metadata.<key>, where <sourceParam> is a select parameter and <key> is a field on that parameter’s option metadata.

A defaultFrom parameter must be optional: true and must not itself be a select. The referenced metadata key must be present and non-null on every option row of the source parameter.

Sample values

When you publish, the CLI runs each view query once to confirm it works and to capture the columns it returns. To run the query, it needs a value for every parameter, before any real user has chosen one. It fills these in as follows:

  • A select parameter uses its first option.
  • An optional parameter is left unset.
  • A required parameter that isn’t a select (a free text, number, or boolean value the user types in) has no value the CLI can pick. For these, you provide a representative value with sample.

The sample value is only used for this check at publish. When someone opens the view, they supply their own value. The value must match the parameter’s type.

Columns

The columns array declares metadata for each column the view query returns. Every returned column must have an entry, and every entry must match a returned column.

FieldTypeRequiredDescription
keystringYesColumn name as returned by the query.
rolestringYesdimension for category columns (the chart x-axis), measure for numeric values (chart series and measure columns).
labelstringNoDisplay label for the column. Defaults to the column key.
unitstringNoUnit for the column’s values, such as $/MWh or %. Appended to table headers and used as the chart y-axis title.
formatstringNoDeclared value format: currency, percent, integer, decimal, date, or datetime.

Example

This example defines a price_by_hour view. It lets a viewer pick a region from a dropdown, then shows the average and peak forecast price for each hour of the day in that region.

The view configuration declares the SQL file, the region select parameter backed by an options query, and the columns the query returns:

{
  "views": [
    {
      "key": "price_by_hour",
      "name": "Average price by hour",
      "sql": "views/price-by-hour.sql",
      "params": {
        "region": {
          "type": "string",
          "label": "Region",
          "description": "The NEM region the prices are averaged over",
          "optional": false,
          "control": "select",
          "options": "views/region-options.sql"
        }
      },
      "columns": [
        { "key": "hour_of_day", "role": "dimension", "label": "Hour of day" },
        {
          "key": "avg_price",
          "role": "measure",
          "label": "Average price",
          "unit": "$/MWh"
        },
        {
          "key": "peak_price",
          "role": "measure",
          "label": "Peak price",
          "unit": "$/MWh"
        }
      ]
    }
  ]
}

The view SQL reads the selected region with getvariable('region'), filters the run’s output to that region, and aggregates price by hour of day:

select
  hour(forecast_datetime) as hour_of_day,
  avg(price) as avg_price,
  max(price) as peak_price
from output
where region = getvariable('region')
group by 1
order by 1;

The options query reads the available regions from a dataset, returning a value and label for each, plus a metadata object carrying the region’s time zone:

select
  code as value,
  name as label,
  json_object('timezone', timezone) as metadata
from dataset_regions
order by name;

Validation at publish

When you run pd4castr publish, the CLI validates every view against your local test data before uploading it, so problems surface before the view reaches the platform. It runs each view query and its options queries, then checks that the parameters resolve and that the declared columns match what the query returns.

This validation uses the output from your most recent local test run, so run pd4castr test before publishing.

Next steps