CLI Output Formats¶
The three scoring commands support human-readable summaries, interoperable text formats, and lossless NumPy archives:
| Format | Destination | Best for |
|---|---|---|
text |
file, .gz, or standard output |
Interactive review |
json |
file, .gz, or standard output |
Structured metadata and web tooling |
csv |
file, .gz, or standard output |
Row-oriented statistics workflows |
npz |
explicit .npz file |
Fast, typed Python and NumPy workflows |
CSV rows and JSON respondent arrays are written forward-only with bounded output
allocation. JSON converts non-finite numbers to null, and CSV emits empty
cells. NPZ preserves NumPy dtypes and non-finite values exactly without object
arrays or pickling.
Screen and composite commands report soft per-index failures on standard error
without mixing warnings into standard output. Their JSON results retain an
errors object, while NPZ archives use aligned error_names and
error_messages vectors. Text repeats the failures inline. CSV stays
row-oriented and carries no global metadata, so retain standard error when its
diagnostics matter.
NumPy archives¶
Write archives from any scoring command:
ier screen responses.npy --indices irv longstring --format npz --output screening.npz
ier composite responses.csv --format npz --output composite.npz
ier response-time timings.csv --format npz --output timing.npz
NPZ output requires --output with a .npz suffix. It cannot target standard
output or an additional .gz layer; the NPZ container is already a ZIP archive.
Every writer completes the archive in a temporary directory beside the target
before an atomic replacement. Handled write failures leave existing content
intact and clean up partial output; successful replacement retains existing
permission bits.
Load every archive with pickling disabled:
import numpy as np
with np.load("screening.npz", allow_pickle=False) as result:
print(result["schema_version"].item())
print(result["result_type"].item())
print(result["index_names"])
irv_scores = result["score__irv"]
irv_flags = result["flag__irv"]
For validated score reuse, prefer the public save/load pair. The writer creates a compact score-only archive; full CLI archives retain the additional flags and decision metadata documented below.
from ier import load_score_archive, save_score_archive, screen_scores
save_score_archive(
"raw-scores.npz",
{"irv": [0.1, 0.7], "longstring": [3.0, 8.0]},
respondent_ids=["case-1", "case-2"],
)
saved = load_score_archive("screening.npz")
updated = screen_scores(saved["scores"], percentile=99)
print(saved["respondent_ids"])
print(saved["errors"])
save_score_archive() validates the destination, result type, registered index
names, aligned vectors, optional IDs, and soft failures before opening the file.
It streams compatible arrays without constructing a respondent-by-index matrix;
the shared atomic boundary protects the destination from later I/O failures.
load_score_archive() always disables pickling and validates the complete
schema. It accepts compact public archives, screen CLI archives, and composite
CLI archives written with --include-components. Aggregate-only composite and
response-time archives do not contain reusable registered-index vectors and are
rejected with a contextual error.
Common schema¶
All archives use schema version 1 and include:
| Key | Value |
|---|---|
schema_version |
Integer scalar |
result_type |
screen, composite, or response_time |
n_respondents |
Integer scalar |
respondent_ids |
Optional Unicode vector when --id-column is used |
Row positions are respondent identifiers when respondent_ids is absent.
Screen schema¶
screen archives include n_indices, min_flags, index_names, thresholds,
threshold_sources, percentiles, flag_counts, valid_index_counts,
consensus_eligible, and consensus_flags.
When --min-valid-indices is supplied, the scalar min_valid_indices records
the completeness requirement. Numeric thresholds and percentile settings align
with index_names; NaN represents a fixed/presence rule without a percentile,
or a presence-based index without a numeric threshold. threshold_sources
distinguishes those cases. JSON exposes equivalent mappings and uses null for
unset values. CSV includes valid_index_count and consensus_eligible columns
for every respondent but intentionally omits global cutoff metadata.
Each successful index has a score__NAME float vector and flag__NAME boolean
vector. Summary values use summary_columns, summary_statistics,
summary_n_flagged, summary_n_valid, summary_n_unavailable, and
summary_flag_rate. The rate uses valid scores as its denominator and is NaN
when an index has no available scores. JSON exposes the same values inside each
index summary and uses null for an unavailable rate. Soft failures are stored
in aligned error_names and error_messages Unicode vectors.
Composite schema¶
composite archives include the method string scalar, standardized boolean
scalar, and respondent-aligned scores float vector. When --weight is
supplied, aligned weight_names and weights vectors record the explicit
overrides; selected indices not listed there use weight 1. When
--min-valid-indices is supplied, min_valid_indices records the integer
completeness requirement. JSON composite output uses equivalent method,
standardized, and optional weights and min_valid_indices fields. Text also
records the effective standardization setting. Aligned error_names and
error_messages vectors preserve soft failures; JSON uses the errors object.
When --threshold or --percentile is supplied, NPZ and JSON add threshold,
threshold_source, and respondent-aligned boolean flags. Percentile output
also records the requested percentile. CSV adds composite_flag, while text
reports the cutoff, source, flagged count, and row-level flag. These fields are
absent when flagging is not requested.
With --include-probability, NPZ and JSON add respondent-aligned
probabilities plus probability_scale="uncalibrated_logistic". CSV adds
composite_probability, and text adds the value to each ranked row. The vector
is transformed from the already-computed aggregate scores without rescoring
indices. It is absent by default. Flag thresholds remain in the original
composite-score units even when probability output is included.
With --include-components, composite NPZ adds index_names,
valid_index_counts, and one score__NAME float vector per successful index.
JSON adds indices_used, valid_index_counts, and a component_scores object;
CSV adds valid_index_count and NAME_score columns; text shows the same fields
for ranked respondents. These are raw public index scores before direction
correction, standardization, and weighting. The aggregate scores vector is
unchanged.
Response-time schema¶
response-time archives include metric, flag_direction, threshold,
respondent-aligned scores, and boolean flags.
Load and reflag the retained scores through the public validated boundary:
from ier import (
load_response_time_archive,
response_time_score_flags,
save_response_time_archive,
)
saved = load_response_time_archive("timing.npz")
revised = response_time_score_flags(
saved["scores"],
threshold=1.0,
direction=saved["flag_direction"],
)
save_response_time_archive(
"revised-timing.npz",
saved["scores"],
revised,
threshold=1.0,
metric=saved["metric"],
flag_direction=saved["flag_direction"],
respondent_ids=saved["respondent_ids"],
)
load_response_time_archive() disables pickling and verifies schema version,
metric and direction compatibility, finite cutoff metadata, aligned score and
flag vectors, optional respondent identifiers, and agreement between stored
flags and their cutoff rule. It accepts both inclusive fixed-threshold flags and
tie-exclusive percentile flags.
save_response_time_archive() writes the same CLI-compatible schema and checks
all scores, Boolean flags, cutoff metadata, direction rules, and optional
identifiers before opening the destination. It streams the validated vectors
without stacking or adding a runtime dependency.
Consumers should reject unsupported future schema_version values rather than
assuming their layout is unchanged.