Skip to content

lunartrace.temporal

The one-call Study: lt.temporal.study(...) over the exact v1 temporal method.

This module is a facade, not a method. It builds the Lunar ODE query for a site, resolves the event interval to an lunartrace.science.temporal.EventBasis, obtains the source pages (live, or retained bytes checked against their receipt) and hands them to lunartrace.science.temporal.compile_study. The record that comes back is the digest-covered Study record of method lunartrace.temporal_prepost/v1. Nothing is added to it: frontiers, why answers and the seven-section anatomy are views over that record.

>>> import lunartrace as lt
>>> study = lt.temporal.study(
... site=(-69.3741, 32.32),
... event="2023-08-23T12:33Z/12:35Z",
... products="LRO/LROC/CDRNAC4",
... archive="vikram-2026-10-14",
... )
>>> study.digest[:15]
'sha256:3d75a662'
>>> len(study.frontier("angles"))
13

Only archive=None touches the network. A live Study is labelled live and is never claimed to reproduce a retained run.

class

Frontier

The pairs that no other pair beats on every objective of one screening.

Behaves as a read-only sequence of PairView. witnesses are the record’s dominance witnesses, one per dominated pair; comparisons is the number of dominance tests the screening ran.

class

IntegrityError

A Study record no longer hashes to the study_digest it carries.

class

PairView

One PRE x POST pair: both observation rows, the angle deltas and the time gaps.

deltas is (Δsun, Δview, Δphase), the absolute incidence, emission and phase differences in degrees. gaps is (pre, post), the seconds from each observation to the adopted event instant.

class

Study

A compiled Study: the v1 record plus views over it. Build one with study.

record is the digest-covered dict, exposed read-only at the top level; its nested values are the record’s own and must not be mutated (verify would then fail). source_mode is "live" for a Study fetched by this call and "retained" for one compiled from retained bytes or loaded from a saved file. sources holds the retained bytes when they are available, which is what save(sources=True) and replay need.

The digest-covered Study record (read-only top level).

The record’s study_digest, sha256:<hex>.

Counts: observations, pre, post, pairs and the frontier sizes.

The four limitations, verbatim from the record.

Every observation row of the Study (read-only mappings).

Every PRE x POST pair row of the Study, ordered by pair_id (read-only mappings).

def pair(self, pair_id: str) -> PairView

The pair with this id.

  • KeyError — If the Study has no such pair.
def frontier(self, name: str) -> Frontier

The Pareto frontier called name.

"angles" (V1_ANGLES), "angles+resolution" (V2_ANGLES_RESOLUTION), "angles+time" (V3_ANGLES_TIME) or "all" (V4_FULL_AVAILABLE); the V-ids are accepted as aliases.

  • KeyError — If name is not one of those; the message lists the valid names.
def why(self, pair_id: str, frontier: str = 'angles') -> Why

Why pair_id is on, or off, a frontier, naming the pair that beat it.

The witness is the one the record retained; it is never recomputed. str of the result is one sentence.

  • KeyError — If the pair or the frontier name is unknown.
def anatomy(self) -> dict[str, Any]

The Study’s seven sections, in reading order, as a view over the record.

what_ran, from_which_bytes, around_when, on_what, why_these (keyed by frontier name), where_it_stops and has_anything_moved (the digest).

def verify(self) -> bool

Recompute the digest from the record; True, or raise IntegrityError.

def save(self, path: str | os.PathLike[str], *, sources: bool = False) -> Path

Write the canonical record bytes to path and return it.

The file’s bytes are exactly canonical_json(record). With sources=True the retained receipt and raw pages are also written to <stem>.sources/ beside it, which is what replay and load look for.

  • FileNotFoundError — If sources=True but this Study holds no retained bytes.
def replay(self) -> Study

Re-compile from the retained bytes with this Study’s event basis; a new Study.

Compare replay().digest with digest to see whether the run reproduces.

  • FileNotFoundError — If no retained sources are attached (save with sources=True or pass sources= to load).
  • ValueError — If a retained page no longer matches its receipt digest.
def to_notebook(
self,
path: str | os.PathLike[str],
*,
study_path: str | os.PathLike[str] | None = None,
) -> Path

Write a marimo notebook (a .py file) that loads, verifies and shows this Study.

The notebook loads a saved Study file. study_path names it; when omitted the Study is saved beside the notebook as <notebook stem>.study.json (with its sources, if held). Returns the notebook path.

class

Why

Why one pair is on or off a frontier.

witness is the pair the record retained as beating it (None on the frontier). deltas and witness_deltas are (Δsun, Δview, Δphase). everywhere says, per frontier name, whether the pair is on that frontier. missing lists objectives the pair could not be evaluated on, in which case it is neither on the frontier nor beaten.

function

def load(
path: str | os.PathLike[str],
*,
sources: str | os.PathLike[str] | None = None,
) -> Study

Read a saved Study file and verify it.

sources names a directory of retained bytes; by default <stem>.sources/ beside the file is used when it exists.

  • IntegrityError — If the record does not hash to its study_digest.
  • ValueError — If the file is not a Study record.

function

def study(
*,
site: tuple[float, float] | str,
event: str,
products: str,
archive: str | os.PathLike[str] | None = None,
box: tuple[float, float] = DEFAULT_HALF_BOX_DEG,
) -> Study

Compile the temporal PRE/POST Study for a site, an event interval and a product type.

NameTypeDescription
site`tuple[float, float]str`
eventstr"START/END": ISO UTC times ending in Z, END exclusive and optionally just a clock time on START’s date ("2023-08-23T12:33Z/12:35Z"); or a registered basis id such as "vikram:minute-envelope". An interval equal to a registered basis uses that basis and its cited rationale; any other is recorded as adhoc:<interval>.
productsstr"IHID/IID/PT", for example "LRO/LROC/CDRNAC4".
archive`stros.PathLike[str]
boxtuple[float, float]Half-width (dlat, dlon) of the query box in degrees. Default DEFAULT_HALF_BOX_DEG.
  • ValueError — For a malformed argument, an archive fetched for a different query, or a retained page whose bytes no longer match its receipt.