Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions docs/concepts/analysis-readiness.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ scientifically suitable.

```python
assessment = experiment.assess_readiness()
assessment.sedimentation_velocity.status # ReadinessStatus
assessment.sedimentation_velocity.status # ReadinessStatus
assessment.sedimentation_equilibrium.status
assessment.scientific_suitability.status # always NOT_ASSESSED
assessment.scientific_suitability.status # always NOT_ASSESSED
```

## What readiness is not
Expand Down Expand Up @@ -69,11 +69,11 @@ appears in `advisory_issues` for the tiers it pertains to.

```python
entry = experiment.assess_readiness().sedimentation_velocity
entry.status # ReadinessStatus
entry.is_blocked # bool
entry.blocking_issues # findings whose `blocks` names this tier
entry.advisory_issues # findings pertaining to this tier that block nothing
entry.note # why the status is what it is
entry.status # ReadinessStatus
entry.is_blocked # bool
entry.blocking_issues # findings whose `blocks` names this tier
entry.advisory_issues # findings pertaining to this tier that block nothing
entry.note # why the status is what it is
entry.to_dict()
```

Expand All @@ -88,7 +88,7 @@ tier is blocked — that is the normal case for a historical dataset with sparse
metadata, and it is a success, not a failure:

```python
assert experiment.validate_structure().is_valid # nothing wrong with it
assert experiment.validate_structure().is_valid # nothing wrong with it
assert experiment.assess_readiness().sedimentation_velocity.is_blocked
```

Expand Down
26 changes: 16 additions & 10 deletions docs/concepts/data-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,21 @@ to serialise an array layer it does not own.

```python
from openauc.models import (
AUCExperiment, ExperimentMetadata, ScanMetadata, Observations, Quantity,
Unit, OpticalSystem,
AUCExperiment,
ExperimentMetadata,
ScanMetadata,
Observations,
Quantity,
Unit,
OpticalSystem,
)

experiment = AUCExperiment(
metadata=ExperimentMetadata(experiment_id="exp-1"),
scans=(
ScanMetadata(
scan_id="scan-1", index=0,
scan_id="scan-1",
index=0,
elapsed_time=Quantity.of(0.0, Unit.SECOND),
optical_system=OpticalSystem.ABSORBANCE,
),
Expand Down Expand Up @@ -76,12 +82,12 @@ authoritative rather than relying on `NaN`.

```python
obs = Observations.from_per_scan(
radii=[[6.0, 6.1, 6.2], [6.0, 6.05]], # different lengths
radii=[[6.0, 6.1, 6.2], [6.0, 6.05]], # different lengths
signals=[[0.1, 0.2, 0.3], [0.4, 0.5]],
scan_ids=["a", "b"],
signal_unit=Unit.FRINGE,
)
obs.points_per_scan() # (3, 2) — real observations per scan
obs.points_per_scan() # (3, 2) — real observations per scan
obs.valid_radius_values() # excludes padding
```

Expand All @@ -94,11 +100,11 @@ exist.
Validation is **tiered**, and none of it raises:

```python
report = experiment.validate_structure() # archival + structural findings
report = experiment.validate() # all four tiers
assessment = experiment.assess_readiness() # metadata presence per workflow
summary = experiment.summary_data() # structured facts
print(experiment.summary()) # the human-readable rendering
report = experiment.validate_structure() # archival + structural findings
report = experiment.validate() # all four tiers
assessment = experiment.assess_readiness() # metadata presence per workflow
summary = experiment.summary_data() # structured facts
print(experiment.summary()) # the human-readable rendering
```

`validate_structure()` checks representational consistency only — identifier
Expand Down
4 changes: 2 additions & 2 deletions docs/concepts/missing-and-unknown-values.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ A `PRESENT` quantity must carry a finite value; every other status must carry
```python
from openauc.models import Quantity, ValueStatus

Quantity.unknown().status # ValueStatus.UNKNOWN — not the same as MISSING
Quantity.not_applicable().value # None
Quantity.unknown().status # ValueStatus.UNKNOWN — not the same as MISSING
Quantity.not_applicable().value # None
Quantity.of(20.0, Unit.DEGREE_CELSIUS).is_present # True
```

Expand Down
18 changes: 9 additions & 9 deletions docs/concepts/provenance-and-checksums.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ representation, not an audit claim, and nothing in it is inferred.
```python
p = experiment.provenance
p.source_path, p.source_filename
p.parser_name, p.parser_version # e.g. 'generic-long', '0.1.0a1'
p.imported_at # UTC timestamp
p.sha256 # digest of the primary data file
p.source_checksums # one typed entry per source file
p.parser_name, p.parser_version # e.g. 'generic-long', '0.1.0a1'
p.imported_at # UTC timestamp
p.sha256 # digest of the primary data file
p.source_checksums # one typed entry per source file
p.warnings, p.assumptions
```

Expand Down Expand Up @@ -57,11 +57,11 @@ source**:

```python
p = generated.provenance
p.parser_name # 'openauc.synthetic'
p.source_path # None — nothing was read from disk
p.sha256 # None
p.transformations # ('generated scenario=moving-boundary',)
p.assumptions # the synthetic disclaimer, seed, noise level
p.parser_name # 'openauc.synthetic'
p.source_path # None — nothing was read from disk
p.sha256 # None
p.transformations # ('generated scenario=moving-boundary',)
p.assumptions # the synthetic disclaimer, seed, noise level
```

## Archive provenance
Expand Down
4 changes: 2 additions & 2 deletions docs/concepts/synthetic-data.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ impossible domains are rejected at construction with a clear message.
```python
from openauc.synthetic import write_generic_long, write_generic_wide, write_aucx

write_generic_long(experiment, "out/long") # manifest.json + scans.csv
write_generic_wide(experiment, "out/wide") # shared-axis only
write_generic_long(experiment, "out/long") # manifest.json + scans.csv
write_generic_wide(experiment, "out/wide") # shared-axis only
write_aucx(experiment, "out/experiment.aucx")

restored = openauc.load("out/experiment.aucx")
Expand Down
4 changes: 2 additions & 2 deletions docs/concepts/units.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ rejected.
```python
from openauc.models import Quantity, Unit, ValueProvenance

Quantity.of(50000.0, Unit.RPM) # present, supplied
Quantity.of(0.5, Unit.OTHER, unit_label="mg/mL") # open-ended unit retained
Quantity.of(50000.0, Unit.RPM) # present, supplied
Quantity.of(0.5, Unit.OTHER, unit_label="mg/mL") # open-ended unit retained
Quantity.of(4.3, Unit.SECOND, provenance=ValueProvenance.CONVERTED) # tagged
```
30 changes: 15 additions & 15 deletions docs/concepts/validation-tiers.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ Only the first three exist in `openauc`, and they live in different places:
## The two entry points

```python
report = experiment.validate_structure() # tiers A+B, ERROR and WARNING only
report = experiment.validate() # all four tiers, all severities
report = experiment.validate_structure() # tiers A+B, ERROR and WARNING only
report = experiment.validate() # all four tiers, all severities
```

`validate_structure()` is unchanged in meaning: `report.is_valid` is `True` when
Expand Down Expand Up @@ -152,21 +152,21 @@ no scientific interpretation.
## Finding structure

```python
issue.code # stable identifier, e.g. "rotor_speed_absent"
issue.severity # ERROR | WARNING | INFO
issue.tiers # tiers this finding speaks to (never empty)
issue.tier # the primary (first) tier
issue.blocks # tiers this finding prevents
issue.message # what was found
issue.observed # what was actually there
issue.expected # the condition that would satisfy the check
issue.remediation # a concrete suggestion
issue.component # the model field concerned
issue.location # the single affected subject, when there is exactly one
issue.scan_ids # every affected scan, sorted
issue.code # stable identifier, e.g. "rotor_speed_absent"
issue.severity # ERROR | WARNING | INFO
issue.tiers # tiers this finding speaks to (never empty)
issue.tier # the primary (first) tier
issue.blocks # tiers this finding prevents
issue.message # what was found
issue.observed # what was actually there
issue.expected # the condition that would satisfy the check
issue.remediation # a concrete suggestion
issue.component # the model field concerned
issue.location # the single affected subject, when there is exactly one
issue.scan_ids # every affected scan, sorted
issue.blocks_structural_validity
issue.blocks_tier(tier)
issue.describe() # multi-line rendering with the detail above
issue.describe() # multi-line rendering with the detail above
issue.to_dict()
```

Expand Down
10 changes: 5 additions & 5 deletions docs/formats/aucx.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ ordinary tools**, to preserve the canonical model exactly, and to be verifiable.
```python
import openauc

experiment = openauc.load("path/to/experiment") # generic CSV/TSV
experiment.export("experiment.aucx") # write
restored = openauc.load("experiment.aucx") # read back
experiment = openauc.load("path/to/experiment") # generic CSV/TSV
experiment.export("experiment.aucx") # write
restored = openauc.load("experiment.aucx") # read back
assert restored.to_dict() == experiment.to_dict()
```

Expand Down Expand Up @@ -156,14 +156,14 @@ the message.
Archive integrity is **separate** from structural and scientific validation:

```python
info = openauc.inspect_aucx("experiment.aucx") # verifies; raises on problems
info = openauc.inspect_aucx("experiment.aucx") # verifies; raises on problems
info.aucx_format_version, info.radius_axis_mode, info.n_scans, info.export

report = openauc.validate_aucx("experiment.aucx") # never raises
report.is_valid, report.issues

restored = openauc.load("experiment.aucx")
restored.validate_structure() # a different question entirely
restored.validate_structure() # a different question entirely
restored.validate()
restored.assess_readiness()
restored.summary_data()
Expand Down
4 changes: 2 additions & 2 deletions docs/formats/generic-delimited.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ experiment identity and metadata.
```python
import openauc

experiment = openauc.load("path/to/experiment") # a directory
experiment = openauc.load("path/to/experiment/scans.csv") # a data file
experiment = openauc.load("path/to/experiment") # a directory
experiment = openauc.load("path/to/experiment/scans.csv") # a data file
experiment = openauc.load("path/to/experiment", format="generic-long")
experiment = openauc.load("dir", manifest="dir/manifest.json")

Expand Down
4 changes: 2 additions & 2 deletions docs/getting-started/first-experiment.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ uv run openauc inspect my-experiment

```python
report = experiment.validate_structure()
print(report) # 'structural validation: OK (no issues)'
print(report.is_valid) # True
print(report) # 'structural validation: OK (no issues)'
print(report.is_valid) # True
```

`is_valid` being `True` means the scans and observations correspond
Expand Down
3 changes: 2 additions & 1 deletion docs/getting-started/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ uv run openauc formats # lists aucx, generic-long, generic-wide

```python
import openauc
print(openauc.__version__) # '0.1.0a1'

print(openauc.__version__) # '0.1.0a1'
print([f.format_id for f in openauc.available_formats()])
# ['aucx', 'generic-long', 'generic-wide']
```
Expand Down
10 changes: 5 additions & 5 deletions docs/getting-started/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ import openauc
from openauc.synthetic import SyntheticExperimentConfig, generate_experiment
from openauc.plotting import plot_scans

config = SyntheticExperimentConfig( # (1)!
config = SyntheticExperimentConfig( # (1)!
scenario="moving-boundary",
n_scans=20,
n_points=300,
Expand All @@ -105,15 +105,15 @@ config = SyntheticExperimentConfig( # (1)!

experiment = generate_experiment(config) # (2)!

print(experiment.summary()) # (3)!
print(experiment.summary()) # (3)!

report = experiment.validate() # (4)!
report = experiment.validate() # (4)!
readiness = experiment.assess_readiness() # (5)!

ax = plot_scans(experiment) # (6)!
ax = plot_scans(experiment) # (6)!
ax.figure.savefig("synthetic-scans.png") # (7)!

experiment.export("synthetic.aucx") # (8)!
experiment.export("synthetic.aucx") # (8)!
restored = openauc.load("synthetic.aucx") # (9)!
assert restored.to_dict() == experiment.to_dict() # (10)!
```
Expand Down
2 changes: 1 addition & 1 deletion docs/how-to/assess-analysis-readiness.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ for issue in sv.advisory_issues:
## The permanent non-assessment

```python
assessment.scientific_suitability.status # always NOT_ASSESSED
assessment.scientific_suitability.status # always NOT_ASSESSED
```

Present in **every** assessment, as a machine-readable entry rather than a prose
Expand Down
31 changes: 19 additions & 12 deletions docs/how-to/inspect-an-experiment.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ uv run openauc inspect examples/data/demo_experiment --json
import openauc

experiment = openauc.load("examples/data/demo_experiment")
print(experiment.summary()) # human-readable text
summary = experiment.summary_data() # structured, frozen, JSON-friendly
print(experiment.summary()) # human-readable text
summary = experiment.summary_data() # structured, frozen, JSON-friendly
```

## What the summary carries
Expand All @@ -38,25 +38,31 @@ summary = experiment.summary_data() # structured, frozen, JSON-friendly
## Ranges

```python
summary.radius.minimum # float | None
summary.radius.minimum # float | None
summary.radius.maximum
summary.radius.unit # declared unit, never converted
summary.radius.unit # declared unit, never converted
summary.radius.n_present, summary.radius.n_absent
summary.radius.render() # '5.9 to 7.2 cm (observed)' or 'unknown'
summary.radius.is_observed # bool
summary.radius.render() # '5.9 to 7.2 cm (observed)' or 'unknown'
summary.radius.is_observed # bool
```

## Counting absence honestly

```python
for entry in summary.metadata_presence:
print(
entry.component, entry.field,
"present", entry.present,
"missing", entry.missing,
"unknown", entry.unknown,
"not_applicable", entry.not_applicable,
"absent", entry.absent,
entry.component,
entry.field,
"present",
entry.present,
"missing",
entry.missing,
"unknown",
entry.unknown,
"not_applicable",
entry.not_applicable,
"absent",
entry.absent,
)
```

Expand All @@ -67,6 +73,7 @@ value.

```python
import json

print(json.dumps(summary.to_dict(), indent=2))
```

Expand Down
22 changes: 11 additions & 11 deletions docs/how-to/interpret-validation-findings.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@ Full rationale per rule: [Validation tiers](../concepts/validation-tiers.md).
## Anatomy of a finding

```python
issue.code # stable identifier, e.g. 'rotor_speed_absent'
issue.severity # ERROR | WARNING | INFO
issue.tiers # tier(s) it speaks to
issue.blocks # tier(s) it prevents — may be empty
issue.message # what was found
issue.observed # what was actually there
issue.expected # what would have satisfied the check
issue.remediation # a concrete suggestion
issue.component # the model field concerned
issue.location # the single affected subject, when there is exactly one
issue.scan_ids # every affected scan, sorted
issue.code # stable identifier, e.g. 'rotor_speed_absent'
issue.severity # ERROR | WARNING | INFO
issue.tiers # tier(s) it speaks to
issue.blocks # tier(s) it prevents — may be empty
issue.message # what was found
issue.observed # what was actually there
issue.expected # what would have satisfied the check
issue.remediation # a concrete suggestion
issue.component # the model field concerned
issue.location # the single affected subject, when there is exactly one
issue.scan_ids # every affected scan, sorted
issue.describe() # all of the above, rendered
```

Expand Down
Loading