Overview

This chapter explains what an Instrument Package is and how IpTool fits into the observing pipeline. It also introduces the parts of the CII Config Service that IpTool relies on for authoring.

The Instrument Package (IP)

An Instrument Package is what an instrument’s team delivers to ESO’s observation preparation team so observations with that instrument can be prepared. It is consumed primarily by the preparation tools (Phase 1 / Phase 2), which use it to render the templates the astronomer can choose from, the parameters those templates take, the observing constraints that apply, and the checks that must be completed before an observation is accepted. The preparation tools then write the result as an Observation Block Description (OBD).

The ELT IFW Sequencer executes the OBD at observation time by running the instrument’s Sequencer Scripts; the Sequencer’s input is the OBD, not the IP. (The Sequencer may optionally read the IP’s app/library.cfg template-to-module map and per-template Template Signature files for convenience, but it never reads the constraints, checklist, laser or format files at runtime.)

Without an IP, an instrument is invisible to the preparation tools and no OBD can be produced for it.

Concretely, an IP is a directory of JSON files whose content and structure are defined authoritatively by the OTTO IP schemata.

OTTO (“Otto Tackles Telescope Observations”) is the ESO-internal framework that specifies the JSON contract between instrument teams and the observation preparation pipeline. It is maintained by ESO’s observation-preparation group. OTTO defines two artefact families:

  • The IP — what an instrument team produces (this manual’s topic).

  • The OBD — what the preparation tools produce per observation, which the Sequencer then executes.

The OTTO IP schemata themselves ship as a directory of JSON Schema files (ip_schemata/: Format.json, TemplateIndex.json, TemplateSignature.json, Fmt1TemplateSignature.json, Constraints.json, Checklist.json, Laser.json, plus the per-parameter-type schemas in parameters/). For convenience ifw-iptool vendors a copy of the current schema set at ifw-iptool/lib/resource/schema/otto/ip_schemata/; the ifwIpToolValidator uses that copy by default. The schemas are the authoritative source of truth for IP content: anything outside those schemata is, by definition, not part of the IP.

Schema versions are rolled out by ESO as drops (e.g. 2026-04 → 2026-05). When OTTO introduces a breaking change, ifw-iptool’s vendored copy is bumped and the IpTool typedefs and emitter are updated to match; instrument teams then rebuild their IPs against the new schemata. See the validator’s output for which schema set your IP was checked against.

One IP exists per instrument. Its artefacts are JSON files validated against the following OTTO schemas:

  • Format.json — IP format, instrument, IP version.

  • TemplateIndex.json — the index of templates.

  • Fmt1TemplateSignature.json (acquisition templates) / TemplateSignature.json (science / calib / test templates) + per-type Parameter.json schemas — one Template Signature per template; the two schemas differ only in their phase1 shape.

  • Constraints.json + Constraint.json and per-constraint schemas — the observing constraints.

  • Checklist.json — the checklist items.

  • Laser.json — laser-collision information (for laser-using instruments).

  • Phase1.json / Phase1VLT.json / Phase1ReferenceTargets.json — Phase-1 metadata carried by P1 templates.

Role in the operations pipeline

  Instrument software team
  (YAML authoring)                Instrument control software
        |                         (Sequencer Scripts + configuration)
        v                                       |
+-------------------+                           |
|      IpTool       |   compiles YAML -> IP     |  deployed separately
+---------+---------+                           |  to the telescope host
          |                                     |
          v                                     |
 Instrument Package (IP)                        |
 (OTTO JSON artefacts)                          |
          |                                     |
          |  delivered to ESO's                 |
          |  observation preparation team       |
          v                                     |
  Preparation tools                             |
  (Phase 1 / Phase 2):                          |
  construct + validate                          |
  the OBD using the IP                          |
          |                                     |
          v                                     v
          Observation Block Description (OBD)
                            |
                            v
                    ELT IFW Sequencer
              (executes OBD using the instrument
                control software's Sequencer Scripts)
  • Preparation tools consume the IP during Phase 1 (proposal preparation) and Phase 2 (observation preparation). They read the Template Signatures, parameter domains, constraints and checklist, and use them to render a UI in which the astronomer constructs and validates an OBD.

  • The ELT IFW Sequencer then executes the OBD using the Sequencer Script modules installed on the deployment machine as part of the instrument control software.

The IP is the integration contract between the instrument team and ESO’s observation preparation tools.

IP artefacts (defined by the OTTO IP schemata)

The following artefacts constitute the IP. File paths shown are the locations emitted by ifwIpToolCompiler; the OTTO schema column is the authoritative definition of each artefact’s content.

Artefact:

Format (mandatory)

Emitted file:

format.json

OTTO IP schema:

Format.json

Purpose:

IP format version (1 or 2), instrument name, IP version. Used by preparation tools to confirm compatibility before loading the rest of the IP. Every IP must ship one; the validator refuses to run without it.


Artefact:

Template index

Emitted file:

templates.json

OTTO IP schema:

TemplateIndex.json

Purpose:

One entry per template: templateName, type, label, description, and — for Phase-1 templates — a phase1 block. Preparation tools use it to list the templates an astronomer can pick from.


Artefact:

Template Signature

Emitted file:

templates/<templateName>.json

OTTO IP schema:

Fmt1TemplateSignature.json for acquisition templates (carries phase1.referenceTargets); TemplateSignature.json for science / calib / test templates.

Purpose:

One per template. Declares the templateName, type (acquisition / science / calib / test), instrument, label, description, parameters and (for P1 templates) phase1. Each parameter is validated by Parameter.json and its per-type variant (IntParam.json, KeywordParam.json, …).


Artefact:

Constraints

Emitted file:

constraints.json

OTTO IP schema:

Constraints.json

Purpose:

Observing constraints (seeing, airmass, skyTransparency, moonDistance, fli, strehlRatio, pwv, twilight, turbulence). Used by preparation tools to enforce valid ranges and by scheduling to decide when the OB may run.


Artefact:

Checklist

Emitted file:

checklist.json

OTTO IP schema:

Checklist.json

Purpose:

User-facing checks (text / boolean / 2-state / 3-state / list) surfaced by preparation tools before the OB is accepted.


Artefact:

Laser (optional)

Emitted file:

laser.json

OTTO IP schema:

Laser.json

Purpose:

fov, laserUsingTemplates, alwaysSensitiveTemplates, maybeSensitiveTemplates, checkedParameters, checkedValues — the information the Laser Traffic Control System (LTCS) needs for collision checking. Present only for laser-using instruments. (OTTO open issue: the OTTO team asked for ``laser.json`` in every IP, but the OTTO ``Laser.json`` schema makes an empty “no laser” form unvalidatable — the base requires ``checkedParameters``/``checkedValues`` to have ``minItems:1`` while the “all empty” branch requires ``maxItems:0``. Pending a schema fix, ``laser.json`` is emitted only for laser instruments.)


Artefact:

App library (mandatory)

Emitted file:

app/library.cfg

OTTO IP schema:

(not OTTO-defined; consumed by the Sequencer)

Purpose:

Maps each OTTO templateName to the Python module that implements its Sequencer Script. The Sequencer loads this file to resolve templateName → module on OB execution, which makes it mandatory for ELT IPs.

The file is a JSON array of {"templateName", "moduleName"} objects — the format the ELT Sequencer consumes (matching the ifw-templates instrument examples). The compiler emits it automatically using the same convention as the generated Sequencer stubs: <instr>.stubs.<templateName>. If the instrument team authors a custom app/library.cfg alongside the .ipt.yaml inputs, that authored version is copied through and respected (the auto-emit step is skipped).


Artefact:

IP archives (default; ``–no-zip`` to skip both)

Emitted files:

resource/ip/<instr>/ip.zip and resource/ip/<instr>/ip.tar.gz

OTTO IP schema:

(none; archive of the OTTO IP files)

Purpose:

The IP package handed to the OTTO preparation tools. It contains the OTTO IP files onlyformat.json, templates.json, templates/, constraints.json, checklist.json, laser.json. By requirement of the OTTO team, the package carries the OTTO IP and nothing else, so the Sequencer app/ map and the doc/ Template Reference Manual are excluded from the archives. Those directories are still generated and installed under $PREFIX (app/ beside the IP for the Sequencer; doc/ as a separate resource/doc/<instr>/ artefact) — they are simply not part of the IP package. Two archive formats are emitted side-by-side: .zip for OTTO tooling and Windows consumers, .tar.gz for Linux-native workflows. Pass --no-zip to skip both (the flag name is historical; it covers all archive formats — the directory tree alone is then the deliverable).


Artefact:

Template Reference Manual (LaTeX + optional PDF)

Emitted file:

resource/doc/<instr>/ip/<instr>_template_manual.tex

OTTO IP schema:

(not OTTO-defined; companion document)

Purpose:

Human-readable companion to the machine-readable IP. Contains auto-generated tables for the template overview, per-template parameter signatures, constraints, checklist, laser, and indices, plus prose-stub sections (introduction, instrument overview, operational notes, examples) for the instrument team to fill in. The auto-generated tables live in a sibling <instr>_template_manual_data.tex file. Both files are regenerated on every compile by default; once the instrument team starts authoring prose, pass --keep-manual-prose to preserve the main file across subsequent compiles. Builds to PDF via pdflatex (preferred) or latexmk.

IpTool also generates per-template artefacts that are not part of the IP — see below.

Artefacts that are not part of the IP

The following are IpTool-generated aids, produced alongside the IP to help the instrument team load a sample OBD into the Sequencer and inspect a template’s parameter signature. They are not defined by the OTTO IP schemata, not consumed by preparation tools, and not used in operations.

These aids live under <output>/ipt/<instr_lower>/ — deliberately outside resource/ip/ so they don’t get confused with the IP, and under their own <instr>.stubs Python package so the stubs don’t clash with the Sequencer distribution’s seq.lib namespace.

Aid:

Example OBD per template

Emitted file:

ipt/<instr_lower>/obd/<templateName>.obd.json

Purpose:

A default-filled Observation Block Description built from each Template Signature (each parameter’s initialValue is used as its value). A worked example the instrument team can load into the Sequencer to inspect a template’s parameter signature. Production OBDs are authored in the preparation tools.


Aid:

Example Sequencer Script stub per template

Emitted file:

ipt/<instr_lower>/seq/<instr_lower>/stubs/<templateName>.py

Purpose:

A minimal Python module matching the template’s parameter surface, importable as <instr_lower>.stubs.<templateName>. Lets the example OBD above be loaded into the Sequencer before the real Sequencer Scripts are available. Production Sequencer Scripts live under the instrument control software with a different package path.

How the IP is used

  • Authoring: the instrument software team prepares the IpTool sources, runs ifwIpToolCompiler to generate the IP, validates it with ifwIpToolValidator, and delivers the IP to ESO’s observation preparation team.

  • Observation preparation: the preparation tools (Phase 1 / Phase 2) load the IP, render template choices, parameter inputs and constraints, and write the resulting OBD.

  • Execution: the ELT IFW Sequencer runs the OBD using the instrument’s Sequencer Scripts.

The CII Config Service

IpTool does not parse YAML itself — that is delegated to the CII Config Service, the ESO Common Infrastructure component that provides typed YAML configuration with includes, inheritance, and type-checking. For full reference see the CII Config Service manual; for IpTool authoring you only need to know the four features below.

!cfg.include <path>:

Inserts the contents of another YAML file at the point of the tag, before type-checking. Conceptually similar to #include in C, but YAML-native and fully type-aware. IpTool uses this to share a parameter library across templates: parameters are grouped into per-FITS-prefix files (det.keys.ipt.yaml, seq.keys.ipt.yaml, dpr.keys.ipt.yaml, tel.keys.ipt.yaml, ins.keys.ipt.yaml) and each template explicitly !cfg.include s the prefix files its parameters belong to.

!cfg.typedef <Name>: / !cfg.type:<Name>

Define a typed shape (!cfg.typedef) and tag a YAML mapping with that type (!cfg.type:<Name>). The CII Config Service then type- checks the mapping against the typedef. IpTool ships a single typedef file (iptool.schema.yaml) declaring the types IpToolParameter, IpToolTemplate, and IpToolIpMetadata. Authors include that file once per source file and tag each parameter / template / metadata block with the matching type.

!cfg.merge <instance>:

Modifies fields of an existing typed instance defined elsewhere (typically in an included keys file). This is how IpTool expresses per-template overrides on a shared parameter without duplicating its definition. New fields cannot be introduced via merge — only existing fields can be modified, and the new value must satisfy the field’s type.

These four primitives are everything IpTool authoring needs. If a build fails with a CII Config Service error code (e.g. B0070_UNDEFINED_INSTANCE or C0003_INVALID_VALUE), it is usually an undefined parameter referenced by a !cfg.merge, or a value that does not match the field type — chase the file and line the error refers to.

Goals

  • Human-readable authoring. Comments, references, and clean parameter-library reuse — everything OTTO JSON cannot express.

  • Inheritance via !cfg.merge. One canonical definition per keyword; per-template overrides type-checked by the CII Config Service.

  • Single source of truth per instrument. <instr>.meta.ipt.yaml carries format, constraints, checklist and laser together.

  • Deterministic output. The compiler always produces the same IP tree for the same inputs; diffs in generated JSON are meaningful.

Authoring model

Every IpTool YAML source file has a mandatory role encoded in its filename suffix. The compiler enforces the role on every file it loads — both inputs named on the CLI and files pulled in via !cfg.include.

Role

Suffix

Must contain

Parameter library (“keys”)

.keys.ipt.yaml

Only IpToolParameter instances (one per keyword). May be empty (aggregator files that only !cfg.include others).

Template

.tpl.ipt.yaml

Exactly one IpToolTemplate instance, plus optional !cfg.merge overrides of parameters declared in included keys files.

IP-wide metadata

.meta.ipt.yaml

Exactly one ip_metadata: !cfg.type:IpToolIpMetadata instance carrying Format, Constraints, Checklist, and optional Laser.

Output tree

Running ifwIpToolCompiler -o <output> produces two trees:

The IP itself (consumed by the preparation tools):

<output>/resource/ip/<instr_lower>/ip/
    format.json
    templates.json
    constraints.json         (only if ip_metadata.constraints set)
    checklist.json           (only if ip_metadata.checklist set)
    laser.json               (only if ip_metadata.laser set)
    templates/<tpl>.json     (Template Signatures)
    app/library.cfg          (template->module map; mandatory for ELT;
                              auto-emitted, user-authored override respected.
                              Consumed by the Sequencer, NOT by the OTTO
                              preparation tools - see the IP package note below)
<output>/resource/ip/<instr_lower>/ip.zip
<output>/resource/ip/<instr_lower>/ip.tar.gz
                             (the IP PACKAGE: the OTTO IP files only -
                              format/templates/constraints/checklist/laser.
                              The OTTO team requires the package to carry the
                              OTTO IP and nothing else, so app/ and doc/ are
                              EXCLUDED from the archives. default; pass
                              --no-zip to skip both)
<output>/resource/doc/<instr_lower>/ip/
    <instr>_template_manual.tex          (prose skeleton; regenerated by default,
                                          pass --keep-manual-prose to preserve)
    <instr>_template_manual_data.tex     (auto-generated tables; always regenerated)
    <instr>_template_manual.pdf          (built by default; --omit-pdf skips.
                                          The Template Reference Manual - a
                                          separate doc artefact, NOT part of the
                                          IP package)

The IpTool-generated demo aids (NOT part of the IP):

<output>/ipt/<instr_lower>/
    obd/<tpl>.obd.json                          (sample OBDs)
    seq/<instr_lower>/stubs/<tpl>.py            (Sequencer stubs)
    seq/<instr_lower>/__init__.py               (package roots so the
    seq/<instr_lower>/stubs/__init__.py          stubs are importable
                                                 as <instr>.stubs.<tpl>)

To load a sample OBD into the Sequencer, put <output>/ipt/<instr_lower>/seq on PYTHONPATH; the Sequencer will find <instr_lower>.stubs.<tpl> modules there.

The instrument directory name is the lowercased format.instrument (so TSTINS becomes tstins).