Reference · Structural QC
996102e0
Structural QC Issue Clinic
Use this page after audit_study_qc() returns status == "review" or when you need to interpret a row/group emitted by study_qc_diagnostics().
Structural preflight evaluates a bounded set of implemented representation conditions; it is not a complete measurement-quality or scientific-validity assessment.
The governed catalog below is the documentation authority for the five currently implemented issue families. CI regression tests bind it to the live diagnostic output so a runtime change cannot silently leave the clinic stale.
Showing all 5 issue families.
coordinate_nonfinite
row scope
report: coordinate_issue_rows
Non-finite coordinate
One or both mapped gaze-coordinate values are missing or infinite on an observation.
Diagnostic details
| Detail code | Meaning |
|---|---|
x_missing |
The mapped horizontal coordinate is missing. |
x_infinite |
The mapped horizontal coordinate is positive or negative infinity. |
y_missing |
The mapped vertical coordinate is missing. |
y_infinite |
The mapped vertical coordinate is positive or negative infinity. |
What to inspect
- Confirm whether missingness or infinity is present in the source export or was introduced by preprocessing.
- Check whether the row still carries a valid participant, trial, timestamp, and any upstream validity flag.
- Determine whether downstream operations can represent the missing coordinate explicitly or require a declared handling rule.
Common representation causes
- tracker loss or off-screen gaze represented as missing
- channel-combination or coordinate-conversion output
- invalid numeric conversion or preprocessing arithmetic
- source export conventions for unavailable gaze samples
A non-finite coordinate does not by itself identify the cause, justify imputation, or require row/trial/participant exclusion.
Preserve the missingness explicitly unless a study-owned preprocessing or exclusion rule justifies a different treatment.
timestamp_nonfinite
row scope
report: timestamp_issue_rows
Non-finite timestamp
The mapped timestamp is missing or infinite on an observation.
Diagnostic details
| Detail code | Meaning |
|---|---|
timestamp_missing |
The mapped timestamp is missing. |
timestamp_infinite |
The mapped timestamp is positive or negative infinity. |
What to inspect
- Trace the observation back to the source event/time representation.
- Confirm the declared timestamp unit and origin before attempting any repair.
- Identify every downstream operation that depends on time magnitude, order, duration, interval, or rate.
Common representation causes
- incomplete export rows or malformed event joins
- failed time conversion
- missing event anchors
- invalid arithmetic during timestamp transformation
A non-finite timestamp is not equivalent to time zero and must not be silently coerced to zero.
Repair only from defensible source information; otherwise keep the condition explicit and decide how time-dependent analyses should handle it.
identifier_missing
row scope
report: missing_identifier_rows
Missing canonical identifier
The participant or trial identifier is missing, so the observation cannot be unambiguously assigned to both canonical grouping dimensions.
Diagnostic details
| Detail code | Meaning |
|---|---|
participant_missing |
The mapped participant identifier is missing. |
trial_missing |
The mapped trial identifier is missing. |
What to inspect
- Check source keys, joins, event segmentation, and any ID normalization performed before mapping.
- Confirm whether the identifier can be reconstructed from authoritative source information rather than guessed.
- Review downstream grouping assumptions before retaining an unresolved identifier gap.
Common representation causes
- incomplete merge keys
- event segmentation that did not assign all samples
- export rows outside a recognised trial
- identifier parsing or normalization error
A missing identifier does not authorize inventing a participant or trial ID from row order, neighbouring rows, or convenience.
Recover the identifier from authoritative provenance when possible; otherwise record the unresolved grouping limitation and the study-specific decision.
timestamp_duplicate
row scope
report: duplicate_timestamp_rows
Duplicate participant × trial timestamp
Two or more rows share the same finite participant, trial, and timestamp value; every participating row is reported.
Diagnostic details
| Detail code | Meaning |
|---|---|
timestamp_duplicate |
The row shares its finite participant × trial timestamp with another row. |
What to inspect
- Inspect whether the rows are genuinely duplicated observations or a valid simultaneous representation such as separate channels.
- Compare the non-time columns for the repeated key.
- Check acquisition precision and export resolution before treating equality as duplication error.
Common representation causes
- binocular or multi-channel rows at one acquisition time
- limited timestamp resolution
- concatenated or repeated export rows
- accidental duplication during preprocessing
Duplicate timestamps do not automatically mean duplicated scientific observations and are not an automatic deduplication or exclusion rule.
Preserve, combine, repair, or exclude only after the representation semantics are established and the decision is recorded.
timestamp_decreasing
group scope
report: decreasing_time_groups
Decreasing within-unit time
Finite timestamps decrease in observed row order within at least one participant × trial group.
Diagnostic details
| Detail code | Meaning |
|---|---|
timestamp_decreasing |
A participant × trial group contains a negative finite timestamp difference in observed row order. |
What to inspect
- Inspect the original row order and source segmentation for the affected participant × trial unit.
- Determine whether rows were concatenated, appended, or transformed out of acquisition order.
- Confirm that any sort operation would restore a known source order rather than merely make the warning disappear.
Common representation causes
- concatenated export blocks
- row-order corruption during joins or appends
- mixed event segments assigned to one trial
- unsorted but otherwise valid source representation
A decreasing timestamp does not automatically justify sorting; sorting without establishing the intended temporal order can conceal a representation error.
Repair row order only when the intended order is reconstructable, then rebuild the study and rerun structural preflight.
No issue family matches these filters
Clear the filters, use the site-wide search with Ctrl/Cmd + K, or inspect the complete structural-QC guide.
Read the layers in the right order
A structural preflight has several different outputs. They answer different questions:
| Layer | Example | What it tells you | What it does not tell you |
|---|---|---|---|
| status | review |
at least one implemented structural condition was detected | that the dataset is invalid |
| issue family | timestamp_duplicate |
which class of structural condition occurred | why it occurred |
| report field | duplicate_timestamp_rows |
how many rows participate in that condition | how many scientific events are invalid |
| diagnostic detail | x_missing |
the specific row/group condition | the appropriate repair or exclusion |
| researcher decision | free-text action + rationale | what the study team decided after inspection | a package-wide recommendation |
| readiness policy | researcher-declared thresholds | whether a table/cohort satisfies that declared policy | universal scientific quality |
Do not skip directly from status == "review" to filtering.
Minimal inspection sequence
from gazeaudit import audit_study_qc, study_qc_diagnostics
report = audit_study_qc(study)
diagnostics = study_qc_diagnostics(study)
print(report.status)
print(report.issue_codes)
print(
diagnostics[
[
"diagnostic_id",
"scope",
"issue_code",
"detail_code",
"row_position",
"participant",
"trial",
"timestamp",
]
]
)
Then connect each diagnostic back to the source/mapping provenance before deciding whether the condition is a valid representation, a repairable construction problem, a study-specific exclusion issue, or an unresolved limitation.
Record the decision instead of deleting the evidence
When an issue has been inspected, StudyQCDecision and build_study_qc_audit() let you bind the action and rationale to the diagnostic record.
from gazeaudit import StudyQCDecision, build_study_qc_audit
decision = StudyQCDecision(
issue_code="timestamp_duplicate",
action="retain after representation review",
rationale="Rows are simultaneous channel records in the declared source representation.",
diagnostic_ids=("D000001", "D000002"),
)
audit = build_study_qc_audit(study, decisions=(decision,))
The action above is an illustration, not a default. The correct action depends on the source representation, acquisition protocol, preprocessing history, endpoint, and study-owned decision rules.
If you change the table
A repair that changes mapped coordinates, time, participant/trial identifiers, or row order changes the canonical study representation.
After a repair:
- preserve the pre-repair evidence if it supported an earlier analysis;
- update the data-mapping provenance;
- rebuild
GazeStudy; - rerun
audit_study_qc()andstudy_qc_diagnostics(); - create a new decision/audit record;
- rerun downstream analyses affected by the change.
Do not reuse old diagnostic IDs after changing the audited representation.
Interpretation and reporting
A defensible Methods statement describes what was checked and how decisions were governed, not merely that “data quality was checked.”
Structural preflight evaluated non-finite gaze coordinates and timestamps, missing canonical identifiers, duplicate participant × trial timestamps, and decreasing within-unit time. Flagged conditions were inspected against source and preprocessing provenance; any repair, retention, or exclusion decision was recorded explicitly rather than applied automatically.
A Results statement should report the observed scope and preserve the denominator. For example:
Structural preflight returned
reviewbecause duplicate timestamps and non-finite coordinates were present. The affected rows/units were inspected using row/group diagnostics, and the resulting decisions were retained in the structural-QC audit record.
Replace the issue families and counts with the study’s actual record. Do not copy numerical values from synthetic examples.
If a condition remains unresolved, say so. An unresolved limitation is preferable to a fabricated repair or an unexplained exclusion.
API routes
Use the source-level API pathways for exact current signatures and source links:
GazeStudyaudit_study_qc()study_qc_diagnostics()build_study_qc_audit()- Structural-QC method pathway
- Machine-readable QC issue catalog
Continue from here
- Structural-QC triage guide — step-by-step inspection, decision, repair, rerun, and reporting workflow.
- All structural-QC issues worked example — one synthetic fixture exercising all five issue families and all ten detail codes.
- Data onboarding and structural preflight — full provenance and artifact workflow.
- Analysis-readiness governance — apply researcher-declared thresholds only after structural evidence is understood.