---
name: ufoathome-recording
description: Build a UFO@home recording (the sighting JSON file replayed at ufoathome.org) from the documents of a UFO/UAP sighting case, such as reports, questionnaires, statements, sketches, maps and photos of the place. Use when asked to reconstruct, simulate, replay or model what an observer saw for UFO@home, or to write or fix a sighting.json / observer-*.json file.
---

# Recording a sighting for UFO@home

A UFO@home recording is one JSON file stating what one observer saw: when, where, which way they
looked, and the phenomenon as directions and apparent sizes over time. The player computes the rest
(the real sky of that moment, the ground, the weather, the optics of the eye or the camera) from
it. Your job is to state the account precisely and honestly, not to illustrate it.

Written for UFO@home 0.127.3. Format reference: https://ufoathome.org/docs/format/ ,
schema: `references/sighting.schema.json` (also https://ufoathome.org/sighting.schema.json ),
smallest valid example: `references/example-minimal.json`.

## The one rule that matters

Every value is one of three things, and you say which:

- **stated**: the observer said it (a bare value means this);
- **derived**: worked out from what they said plus something checkable (a map, a measured
  drawing, a road's width, a clock correction). Write it as
  `{"value": ..., "basis": "derived", "rationale": "the working, with the numbers"}`;
- **assumed**: chosen so the reconstruction has a value at all, on nothing the observer said.
  Write it as `{"value": ..., "basis": "assumed", "rationale": "what it was chosen for"}`.

A wrong value marked "assumed" is a question for the author. A guess passed off as stated is a
fabricated account, the one thing this format exists to prevent. When in doubt, mark it weaker. Do
not wrap plumbing (`version`, `id`, `sourceId`).

## Method

1. **Read every document, and cite as you go** (document and page). Note each contradiction between
   them (times, distances, directions, durations) instead of silently picking one; pick one for the
   file, and say which and why.
2. **Place and time.** Coordinates of where the observer stood, from the case's own map or survey
   first (a KMZ, a plan), a geocoder last. The local time their clock showed, corrected if the
   investigator measured the clock. The time zone and the legal offset on that date.
3. **The phenomenon, in angles.** The best source is a drawing the observer made or approved on a
   photograph of the place: find the photo's scale (a stated field of view, or two landmarks of
   known bearing) and measure, with code, the shape's centre, width, height and tilt at each stage.
   Otherwise convert the account's comparisons. One keyframe per moment the account distinguishes.
4. **The observer.** Where they stood and which way they looked, at each moment (a head turned
   towards the phenomenon is a pose change), walking or driving if they were.
5. **What surrounds them**, only as far as the account uses it: the objects the phenomenon stood
   before or went behind, the vehicle they were in, the other people present. The weather they
   described, and the record it can be checked against (the ERA5 reanalysis, for instance
   https://archive-api.open-meteo.com/v1/archive with hourly cloud cover, precipitation and wind,
   named in `weatherSource`; the last five days are not in ERA5 yet, and https://historical-forecast-api.open-meteo.com/v1/forecast answers for them). Sound, if they said anything about it.
6. **Say what it was, and who said it.** What the observer themselves concluded (a craft standing on
   its legs, a being of a certain height) goes in `interpretation`, as bodies in metres tested
   against the angles. Someone else's reading, an investigator's or yours, is not part of the account:
   it is another recording of the case, listed in its `case.json` as an event of type
   `sighting` marked `interpretationOf`, which names the account's event by its `id` in the case
   (give that event an `id`, `"trent"`: it is local to the case, not the recording's own). A natural cause the account suggests is stated there too
   (`interpretation.launches` for a rocket's exhaust in the twilight, `reentries` for a satellite
   or stage breaking up), never drawn into the shapes. Do not write what the player works out from
   the date and the place: the sky, the planets, the Moon, eclipses, satellites, the relief
   (https://ufoathome.org/docs/sources/ lists them).
7. **One recording per observer.** When several people saw it, write a recording for each and a case
   file that names them (https://ufoathome.org/docs/format/#several-observers-the-case). People,
   vehicles, trees and buildings come from the catalogue
   https://ufoathome.org/models/index.json , by `model.id`: never invent a model, and never leave a
   person to the built-in shape. A model publishes its own settings (a costume colour, a hull
   colour, retracted landing gear) under `modelParameters`: state one only when the account does.
8. **Say what the file is about.** `summary` (a sentence or two, in the account's language) and
   `image` (the observer's own drawing or a photograph of the place, when the documents hold
   one) are what a shared link shows; the case file takes the same two. Without them the link shows
   the logo and who saw it.
9. **Write the file**, then **validate it**: `python3 scripts/validate.py recording.json` must say
   `valid`, and so must `case.json` (it checks that every `interpretationOf` names an event of the
   case, and that no `id` is borne twice). It catches misspelt keys and words a closed list does not have; it cannot catch a
   wrong direction.
10. **Hand over** the file with a short report: the values you derived and how, the list of assumed
   values, the contradictions between the account and the computed sky (kept, not corrected), and the
   questions to put back to the observer or the investigator: one for each "assumed" value you would
   like replaced (height at the start, timed duration, which way the head turned, standing point,
   what was behind, sense and radius of a turn).
   Tell the user to play it at https://ufoathome.org/play/ ("From your computer", choosing the
   photos it names along with it) and to check that the phenomenon sits where the drawings put it;
   then to correct it with you, or in the editor at https://ufoathome.org/edit/ for fine placement.
   Only the observer can say it looks like what they saw.

## Format rules

1. Sizes are ANGULAR, in degrees (`angular`: {widthDeg, heightDeg}), never metric: the format stores
   no physical size, because an observer perceives an angle and a size only follows from a distance
   nobody measured. Convert the comparisons an account gives (the full Moon and the Sun about 0.5
   degrees across, a thumbnail at arm's length about 1.5, a one-euro coin about 1.5 at arm's length,
   a tennis ball about 6 if held out at arm's length, a fist about 10), or measure them: a
   drawing made on a photograph of the place, with a known field of view or a landmark of known
   bearing, gives degrees per pixel. Where nothing gives a size, work from what the scene implies
   and put the range in the rationale. Never inflate: an angle below one pixel is invisible, and
   that is a fact about the account to report, not something to enlarge so that the shape shows.
   If another document gives a larger figure (an interview years later), you may take it, but say
   which one you took and why.
2. A shape is PLACED by `aim`, the direction of its centre in the observer's sky: `azimuthDeg`
   clockwise from true north and `altitudeDeg` above the horizon. Not the way the observer faced,
   which is the pose's heading and pitch. `bounds` (pixels) is recomputed on load from `aim` and
   `angular`; leave it out. `angle` tilts the shape, in radians, positive clockwise on screen.
   Derive directions from the geography where it allows (a map, the bearing of a road, a landmark
   the observer named); where nothing bears on the altitude, assume something low and plausible and
   mark it "assumed".
3. Times are the local legal time at the place, as the observer's clock read it. Give the IANA
   `timeZone` their clock was on ("Europe/Paris") AND `utcOffsetHours`, the legal offset on that
   date, summer time included (+2 for France in June 2012, +1 in 1965): the player places the sky
   from the number alone, and without it approximates the offset from the longitude, which knows
   nothing of legal time. A time corrected by the investigator (a clock found fast) is "derived".
4. Duration: `durationSeconds` is the one length the reconstruction is played at, a bare number. For a
   vague length ("a few minutes"), state it in `durationText` (an ISO 8601 duration with a doubt, `"PT3M~"`, or a
   range, `"PT5M/PT10M"`) and put the length chosen to play at in `durationSeconds`, with its provenance. Use
   `durationSeconds` alone for a length that was timed or bounded.
5. `timeline.keyframes` is [{t, shapes: [{sourceId, shape}]}], t in milliseconds from the start of
   the recording. Give a keyframe only for a moment the account distinguishes (where it arrived,
   when it changed, where it went); the player interpolates between them. A keyframe need only
   restate what changes: every field a shape leaves out is held from the keyframe before. To make a
   shape vanish, keyframe it at `transparency: 1`. There is no field for blinking: write a flash as
   keyframes a few milliseconds apart, per `sourceId` (interpolation is per source). A rotation of more
   than half a turn between two keyframes needs intermediate keyframes with unrolled angles, or the
   shape turns the short way round. Motion the account calls continuous or slowing down (a landing,
   a take-off) needs a path sampled about every 100 ms and eased, not six keyframes joined by
   straight lines, whose speed jumps at each one. `milestones` ([{t, label, note}]) name the
   moments the account itself names ("A", "B"), shown on the seek bar.
6. A shape is `kind` "oval" or "polygon" (a polygon's `points` are stretched with its box: when you leave
   `bounds` out, as you should, write them as FRACTIONS of the box from 0 to 1, e.g.
   {"x": 0.26, "y": 0.98}; values written as pixels (0-100) are multiplied by the box's width and
   give a giant shape), `title` (what the observer called it),
   `angular` and `aim`. Add `color`, `haloScale` (a glow around it), `brightness` (0 a light
   you can look at, 1 one you cannot) and `blur` (0 hard edges, 1 none) only when the account
   describes them; left out, they assert nothing. `brightness` above 0 adds a dazzle veil, a large
   ringed halo: leave it at 0 on anything that is not a light.
7. `description` is the account itself, in prose: what the observer said, in their words where the
   documents quote them, one string or one per language ({"fr": ..., "en": ...}). Not your
   analysis: measurements, contradictions and reasoning belong in the values, their rationales,
   and your report.
8. `tags` are stored in English whatever the account's language, because two recordings that share
   a tag have to match on it. Reuse the vocabulary already in use where it fits (landing, trace, aerial observation, project sign, paralysis, contact, occupants, close encounter, photograph, radar, electromagnetic effect); pass
   classification codes and case references through unchanged ("RR3", "NL", "GEIPAN D1").
   `paralysis` changes the replay (the view is held still): use it only when the account says the
   observer could not move.
9. `decor` is the scenery the account names, and `eastM`/`northM` are metres from where the
   observer stood at the start. Something the observer is INSIDE (their car) goes at 0,0 and carries
   `observerSide` ("front-left" for a European driver's seat); anything else must be away from
   0,0, or it is drawn on the lens. Give `sizeM` ({widthM, lengthM, heightM}) where known. The
   relief and the roads of the map are drawn for you: add decor for what the account uses (the wood the phenomenon stood before, the car, the other people present, as kind
   "observer"). When the account says the phenomenon went behind something, that object's
   `occludesSourceIds` names the shape. The converse is a trap: a decor object that stands on a
   shape's line of sight WITHOUT declaring it is read as "the phenomenon passed in front of it", and the
   distance is capped by its own (a car 5 m away gave "at most 0.05 m" for a 6 m object). A distance is
   an inequality: in front of X is less than X's distance, behind X is at least that. A track's
   `altitudeM` is metres above the GROUND under the object, not above the observer (the eye is
   at `elevationM` + 1.6 m). Draw only what you can place: never a building or garage whose plan you do
   not have, and no real surroundings when the place is only known to about 0.1 degree; say so
   instead. Roads the map lacks go in `roads`. An obstacle that explains why the account describes what it does (a
   tree line the phenomenon went behind) may be added from a survey or open data, with its
   provenance. A decor of kind "entity" counts as seen; a companion who saw nothing is an
   "observer", placed only where the account puts them: someone in another vehicle whose type and
   position are unknown is left out and listed in your report, not drawn as a pedestrian in the road.
   The eye is 1.6 m above the ground plus the pose's `elevationM`: for a high seat (a tractor cab, a
   lorry), raise `elevationM` by the difference. A seat that is not a car's (a central seat) is
   `observerSide` "front". Standing decor sits on the ground; only a `track` lifts it.
10. `observerTrack` ({keyframes: [{t, pose}]}) is where the observer stood and which way they looked,
   over time: `lat`, `lng`, `elevationM` (metres above the local ground, 0 for someone standing
   on it: the eye's own height is added), `headingDeg` and `pitchDeg` (the direction they LOOKED,
   same conventions as `aim`), `fovDeg` (the vertical field shown, about 60 for the naked eye).
   A walk is a series of poses; a head turned towards the phenomenon is two poses a fraction of a
   second apart. An observer who follows a moving phenomenon looks 0.15 to 0.2 s behind it, so keep
   the gaze on the same path, sampled as densely, or it leaves the field. `instrument` is "eye" unless a camera was used.
11. `account` is about the observer and how the account travelled: `observerAgeYears` (at the
   time), `observerOccupation` (in their words), `source` (how it reached whoever wrote the
   recording: on-site, interview, telephone, questionnaire, letter, social-media, press) and `followedUp`
   (whether they were gone back to). Where the account can be read goes in `sources`, in the
   shape of an RR0 source: [{type ("book" | "article", none for a web page or a post), title,
   authors, url, publication: {publisher, time}, index}]. Always give the documents you worked from. Each other person present is a `decor` object of kind
   "observer".
12. Absent is not zero. An observer who says the thing was silent gets a `soundTrack` whose keyframe
   holds a sound of kind "none"; an account that never mentions sound gets no soundTrack. The same
   holds for the weather: `weatherTrack` states what the observer saw of the sky (cover, rain,
   wind); when it comes from a record (ERA5, a METAR, a station), `weatherSource` names it.
13. `lightPollution` (a number) is how bright the night sky of the place is, towns and all: the
   zenith of a moonless night in magnitudes per square arcsecond, as a Sky Quality Meter reads it or
   as the World Atlas of artificial sky brightness gives it ("SQM", Falchi et al. 2016). 22 is a
   natural sky, and absent means one. "derived" when looked up in the atlas (name it in the
   rationale), "stated" when the observer measured it. It brightens the sky, hides the Milky Way
   and takes stars away; never write a brighter sky than the source gives.
14. The observer's own estimate in metres ("60 m long, 175 m away, 10 m up") is not an observation
   but a conclusion: it goes in `interpretation` (bodies in metres, see the format page), never in
   the shapes. When it contradicts the angles the observer measured, keep it anyway and say so in
   your report: the player's comparison is what shows the contradiction.
15. Place the observer from the account's own description (the road, the property, the bearing of a
   landmark), not from the nearest village; when only a town centre is known, mark the place
   "assumed", not "derived". A shape drawn from a description (a crescent "tips down") rather than measured on the observer's
   sketch is "assumed", whole, in its envelope. Check coordinates before trusting them: a file placed 2.4 km from a field
   that photographs showed to be flat sat on an 11 % slope; a memorial is not the place where
   something happened. The `{value, basis, rationale}` envelope may wrap the whole `{lat, lng}`. When the account gives
   only a distance and a direction from a known point ("2 km west of the village"), move from that
   point by that bearing and distance, mark the result "assumed", and state the offset and the point it
   started from in the rationale: a bare village centre would be wrong, and a shifted one is honest only
   if it says it was shifted.
16. Use the sky the account cites to pin and to check the time (a star at a stated azimuth and
   altitude, the Moon "up" or "down", a sunset), and report the mismatches; if you have no way to
   compute the sky, say the check was approximate or not made, never that it passed; do not correct the
   account to fit the computed sky, and do not delete a value that contradicts it. Check that a
   sentence is testimony before keeping it: "the Sun was still below the horizon" in a summary is not
   something the observer said. With several observers, share one clock and give each their own offset.
   Take the legal offset of THAT year, not today's (a weather service answering with `timezone=auto`
   gives today's rules).
17. Do not invent a difference between observers, and do not flatten the ones stated: use a ratio
   an observer annotated on their own drawing for that observer only, and leave out what nobody
   said. The light-pollution atlas dates from 2015: do not apply it to an event decades earlier; omit
   the field and say so. Once written, cross-check your numbers against independent figures in the
   documents (a table of distances, a runway's axis), and report the residuals.
18. Words: the person is an "observer" (a human and their instruments), what they gave is an
   "account", what is seen is a "phenomenon". Never "witness", "testimony", "object", "craft", "flew" or
   "landed" in a title, a summary, a rationale or your report, except in the observer's own words:
   naming an object already concludes there was one, and excludes a halo, a planet or a reflection.
19. Before handing over, project where each shape and decor object should appear and compare with what
   the player draws, before touching any value: "misplaced" and "hidden by something" look alike, and
   a decor 8 m away that looked wrong was right and merely covered. Look at a close-up of the key
   moment instead of concluding from numbers. A grey or black scene is more often "not loaded" or a
   camera inside a wall than a data fault. Then list, in your report, the questions whose answers would
   replace each "assumed" value (height at the start, timed duration, which way the head turned, standing
   point, what was behind), because that list is what an investigator can act on.

## Things that have gone wrong before

- Setting `aim` to the direction the observer faced rather than to the phenomenon's own direction
  puts every keyframe at the centre of the view.
- Moving `bounds` does nothing: `aim` and `angular` decide where the shape is and how big.
- An elevation above sea level in `elevationM` lifts the observer into the air: it is above the
  ground.
- Metres in the shapes (a "60 m object" as a size) are a conclusion, not an observation: they belong
  in `interpretation`.
- `description` filled with your analysis instead of the account: keep the account there, and your
  working in the rationales and the report.
- Polygon `points` written as pixels (0-100) while `bounds` is left out: they are fractions of the
  box (0 to 1), and pixels give a shape hundreds of times too large.
- A decor object on a shape's line of sight without `occludesSourceIds`: the player reads it as the
  phenomenon passing in front of it, and caps the distance at the object's own.
- A decor `track`'s `altitudeM` taken as above the observer: it is above the ground under the object.
- A `brightness` above 0 on something that is not a light: it adds a large ringed halo.
- A spiral or a long turn written with two keyframes: the shape turns the short way. Add keyframes
  with unrolled angles. Continuous motion needs a path sampled every 100 ms or so, not six keyframes.
- A building or garage placed without its plan, which put the camera against a wall: a grey scene.
- A town centre passed off as the observer's position: mark it "assumed", and take the place from
  what the account describes.
- An angle below one pixel enlarged "so that it shows": report that it is invisible instead.

## Privacy

An account is personal data. Use initials or the case's own anonymisation unless the observer is
already public or agreed to be named, and never put details that identify a private person in
`observer`, `description` or `account` beyond what the published case file itself shows.
