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-typeParameter.jsonschemas — one Template Signature per template; the two schemas differ only in theirphase1shape.Constraints.json+Constraint.jsonand 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 — aphase1block. 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.jsonforacquisitiontemplates (carriesphase1.referenceTargets);TemplateSignature.jsonforscience/calib/testtemplates.- Purpose:
One per template. Declares the
templateName,type(acquisition/science/calib/test),instrument,label,description,parametersand (for P1 templates)phase1. Each parameter is validated byParameter.jsonand 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
templateNameto the Python module that implements its Sequencer Script. The Sequencer loads this file to resolvetemplateName→ 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 theifw-templatesinstrument examples). The compiler emits it automatically using the same convention as the generated Sequencer stubs:<instr>.stubs.<templateName>. If the instrument team authors a customapp/library.cfgalongside the.ipt.yamlinputs, 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.zipandresource/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 only —
format.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 Sequencerapp/map and thedoc/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 separateresource/doc/<instr>/artefact) — they are simply not part of the IP package. Two archive formats are emitted side-by-side:.zipfor OTTO tooling and Windows consumers,.tar.gzfor Linux-native workflows. Pass--no-zipto 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.texfile. Both files are regenerated on every compile by default; once the instrument team starts authoring prose, pass--keep-manual-proseto preserve the main file across subsequent compiles. Builds to PDF viapdflatex(preferred) orlatexmk.
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
initialValueis used as itsvalue). 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
ifwIpToolCompilerto generate the IP, validates it withifwIpToolValidator, 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
#includein 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.includes 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 typesIpToolParameter,IpToolTemplate, andIpToolIpMetadata. 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.yamlcarries 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.
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).