Tutorials › Physiologically-Based Pharmacokinetics (PBPK) › Blinded Prediction Files And Audit Trails

Calibration Versus Independent Validation · Tutorial 707 of 799

Blinded Prediction Files And Audit Trails

Learn to assemble and verify a blinded prediction package that records exactly what was predicted, with which model and inputs, before validation data are unblinded.

Advanced 12 min read

What You'll Learn

  • Identify the files and metadata needed to make a pre-unblinding prediction package auditable.
  • Distinguish a file hash, a trusted timestamp, and an assertion that a file was created before unblinding.
  • Link each prediction to its model version, input record, endpoint, and unit.
  • Check chronology, file integrity, record counts, and prediction-to-subject mapping.
  • Recognize common failures, including mutable files and outcome leakage.
  • Explain what a locked prediction package can establish—and what it cannot.

Why a Prediction File Needs an Audit Trail

A PBPK prediction is useful for independent verification only if the record shows what was predicted before the corresponding validation observations were available to the modeling team. A table of predictions alone cannot establish that chronology. It might have been edited after the observations were seen, generated with a different model version, or joined to the validation records using information that was unavailable at prediction time.

The purpose of a blinded prediction file and its audit trail is therefore narrow and practical: preserve a reproducible, identifiable record of the model version, input data, execution, and predictions, together with evidence that the record was committed before unblinding. This complements prespecifying predictions; it does not replace a sound independent validation design.

Definition: A blinded prediction package is a locked collection of prediction outputs and their provenance, created before the team responsible for generating or evaluating those predictions has access to the validation outcomes. An audit trail is the time-ordered, reviewable record of the package’s creation, integrity checks, custody, and any later access or changes.

“Blinded” must describe the actual information available to the people generating predictions, not merely a label on a file. The outcome data, outcome-derived summaries, and identifiers that reveal the answer must be withheld from those people until the package is locked. A designated custodian may hold the key linking blinded records to participants or studies, but the custodian’s role and access should be documented.

What the Locked Package Should Contain

The package should allow an independent reviewer to answer four questions: which model was used, what information went into the run, what predictions came out, and when was the package fixed relative to unblinding? A concise machine-readable manifest can record the answer while keeping the prediction table separate from the model files.

  • Model identity: a unique version or release identifier; model structure and parameter-set identifiers; and references to any required configuration files. State explicitly whether parameters were frozen and whether any fitting or adjustment occurred for this validation exercise.
  • Inputs: the exact input files or records used, their formats, units, record identifiers, and cryptographic hashes. Include protocol information required to run the model, such as dose, route, formulation, sampling schedule, and relevant population characteristics.
  • Execution: analysis code and its version, the command or procedure used to run it, software and dependency versions, operating environment, random seeds if relevant, and execution start and completion times with time zone.
  • Predictions: one row per prespecified prediction unit, with a stable blinded identifier, endpoint, time or summary measure, predicted value, unit, and any status needed to distinguish a valid result from a failed or missing output. Define the row structure and permitted values in advance.
  • Lock and custody: a manifest, file hashes, a timestamped record of package creation, the identity or role of the person or service that committed it, and the planned date or procedure for unblinding. Record later access and any attempted or authorized changes.

Machine-readable means that the fields, types, units, identifiers, and allowed missing-value codes are defined, not that a file merely has a computer-readable extension. For example, a manifest might record the fields “package_id,” “model_version,” “input_sha256,” “code_commit,” “runtime_version,” “prediction_file_sha256,” “created_utc,” “timestamp_service,” and “unblinding_utc.” Document the schema and version it. Use stable identifiers rather than names or other direct identifiers in prediction files; keep any re-identification key separately under controlled access.

Hash values identify the bytes of particular files. If even one byte changes, a cryptographic hash will almost certainly change as well, provided the hash function is appropriate and the file representation is fixed. To make this check meaningful, specify the exact files hashed and their encoding or canonicalization rules. A hash does not prove that the contents are accurate, that the model is scientifically valid, or that the file existed at the claimed time. A trusted timestamp or controlled repository record can provide evidence of when a particular hash was committed; it still does not establish that the underlying prediction process was free from bias.

Chronology and Integrity Checks

A defensible lock requires more than putting a date in a spreadsheet. Keep timestamps in a stated time standard, preferably Coordinated Universal Time (UTC), and record the source of the timestamp. Retain the original committed package and its manifest in storage with access controls and version history; do not overwrite it with a “corrected” file. If an error requires a new package, give it a new identifier and preserve the old one and the reason for replacement.

Let \(t_L\) denote the time the package was committed and \(t_U\) the time outcomes were unblinded. The basic chronology check is:

$$ t_L < t_U $$

That inequality is necessary, but it is not sufficient. The times must come from credible, auditable records; the committed hash must match the package reviewed; and the people generating predictions must not have had earlier access to outcomes through another route. If unblinding occurred before the lock, a later timestamp cannot restore the intended blinding.

A practical audit also checks that the prediction table conforms to its prespecified structure. If there are \(N\) blinded participants and \(K\) predictions per participant, the expected number of rows is \(N K\), provided every participant has all \(K\) required predictions. Check for missing and duplicate keys, unexpected endpoints, inconsistent units, and records not in the prespecified analysis set. These are data-integrity checks, not assessments of predictive performance.

1
Prepare the blinded inputs.
Confirm that the modeling team receives only the information allowed by the prediction protocol. Record the input version and its hash.
2
Run and export predictions.
Record the model, code, environment, command, and execution details. Export predictions using the prespecified identifiers, endpoints, and units.
3
Validate and commit the package.
Check schema, record counts, identifiers, and file hashes. Create a manifest and commit the package to controlled, time-stamped storage.
4
Unblind under documented control.
Record when and by whom the key or outcomes became available. Match the reviewed package to the committed hashes before analysis.

Worked Example: Checking Whether the Lock Predates Unblinding

Suppose a hypothetical validation exercise produces a package committed to a controlled repository at 14:32 UTC on 12 March. The repository records a trusted timestamp for the manifest hash. The custodian logs outcome unblinding at 09:05 UTC on 15 March. Check the chronology.

Put both times on the same scale. The dates are in UTC, so no time-zone conversion is needed. From 12 March at 14:32 to 15 March at 09:05 is \(72\) hours minus \(5\) hours \(27\) minutes, or \(66\) hours \(33\) minutes.

Apply the chronology condition. Since \(t_L=\) 12 March, 14:32 UTC and \(t_U=\) 15 March, 09:05 UTC, \(t_L<t_U\). The committed package predates logged unblinding by 66 hours 33 minutes.

This supports the claim that this particular package hash was committed before the recorded unblinding event. It does not, by itself, prove that nobody saw outcomes earlier, that the timestamp source was correctly controlled, or that the package contains the predictions from the stated model. Those claims require access logs, custody records, and integrity checks.

Linking Predictions to Inputs and Verifying the Package

A prediction is auditable only if a reviewer can trace it to the intended blinded record and model run. Use a stable key that remains the same across the input file, prediction file, and manifest, while not exposing identity to the modeling team. Define the prediction unit precisely: for example, one participant-endpoint-time combination, not simply “one patient.” Record units explicitly, because a value without a unit can be misread even when its numeric value is unchanged.

Before lock, reconcile expected and observed output rows. Suppose a study has \(N=8\) blinded participants and \(K=3\) prespecified sampling-time predictions per participant. If all are required, the expected count is:

$$ N K = 8 \times 3 = 24 \text{ prediction rows} $$

A count of 24 alone does not guarantee correct linkage: one missing row and one duplicate row would still give 24. Therefore, check uniqueness of the composite key, such as participant ID, endpoint, and time, as well as the full expected key set. Compare units and endpoint labels to the schema. Verify that every file hash in the manifest matches the file actually reviewed.

Worked Example: Reconciling a Prediction Table

In a hypothetical study, four blinded participants each require predictions at 1, 4, and 8 hours for one concentration endpoint. The expected number of rows is \(4 \times 3=12\). A table contains 12 rows, but a key check finds two rows for participant B at 4 hours and no row for participant C at 4 hours.

Check the count. Observed rows \(=12\); expected rows \(=4 \times 3=12\). Thus the count difference is \(12-12=0\), which would pass a count-only check.

Check key uniqueness and coverage. There are 12 expected participant-time keys. The duplicate B-at-4-hours key occupies two rows, while the C-at-4-hours key is absent. Therefore the number of unique keys is \(12-1=11\), and one expected key is missing. The table fails reconciliation despite having the right row count.

The correction must be made while outcomes remain blinded, with the original export preserved and the correction documented. A replacement file should receive a new hash and package version. The audit trail should state what changed, why it changed, who authorized it, and whether the change occurred before unblinding. Do not silently edit the locked file.

Reproducibility, Alternatives, and Limits

Re-running the recorded code can help establish that the inputs and specified execution produce the stored predictions. Exact equality may depend on software versions, numerical libraries, hardware, parallel execution, or random-number handling. Where exact reproducibility is not guaranteed, define the expected reproducibility check in advance—for example, exact equality for deterministic output or a documented numerical tolerance—and retain the original output as the authoritative locked prediction file. A tolerance should not be invented after observing a discrepancy.

A useful audit trail links files in a provenance chain: input files and model configuration lead to a recorded execution, which leads to a prediction file and manifest. Hashes can detect later byte changes in those files; a trusted repository timestamp can strengthen evidence of when a hash was committed. Neither alternative alone is enough. A spreadsheet date is easy to alter; a file hash without a trusted record does not establish when the file existed; and a timestamped hash does not reveal whether a person had already seen the outcomes.

The approach also has limits. It cannot establish that the PBPK model is biologically appropriate, that all relevant inputs were recorded, or that validation data are independent. It cannot prevent collusion or access outside the logged system. It cannot turn a post hoc prediction into a prospectively blinded one. Its value is that it makes key claims inspectable and helps detect inconsistencies, unauthorized changes, and ambiguous provenance.

Key takeaway: An auditable blinded prediction requires a specified data schema, traceable model and input versions, preserved outputs, integrity checks, credible pre-unblinding time evidence, and documented custody. A hash is evidence about file integrity, not a certificate of scientific validity or blinding.

Common Pitfalls

  • Wrong reasoning: “The file is named final_predictions.csv, so it was finalized before unblinding.” Correction: Names are not chronology evidence. Check a credible timestamped commit and its hash against the exact file reviewed.
  • Wrong reasoning: “The file hash matches, so the prediction process was unbiased.” Correction: A matching hash supports byte-level integrity. Review blinding, access, and custody records separately.
  • Wrong reasoning: “The table has the expected number of rows, so all predictions are present.” Correction: Also check key uniqueness and coverage of every expected participant-endpoint-time combination.
  • Wrong reasoning: “We can overwrite the output to fix a formatting error because the values are unchanged.” Correction: Preserve the committed artifact; create a versioned replacement, recompute hashes, and document the change and its timing.
  • Wrong reasoning: “A reproducible run proves the model is valid.” Correction: Reproducibility concerns the ability to recover specified outputs from recorded inputs and code. It is distinct from independent predictive performance.

Worked Example: Interpreting a Hash Mismatch

A hypothetical manifest records that the prediction file has hash value H1. At review, the file in the analysis folder has hash value H2, and H1 differs from H2. The team reports that it only changed a column heading after the lock.

Interpret the check. The reviewed file is not byte-for-byte identical to the file identified by the manifest. The mismatch is a signal to stop and investigate; it does not tell the reviewer whether numeric predictions changed.

Resolve the provenance question. Retrieve the originally committed file and verify that its hash is H1. Compare the two versions, document the heading change and its time, and determine whether the changed file was created before or after unblinding. If a revised file is needed, issue a new package version and manifest rather than replacing the original.

If the change occurred after unblinding, the original H1 file remains the evidence of what was locked before unblinding. The revised H2 file must not be represented as the pre-unblinding artifact. Even a harmless label edit needs documentation because a reviewer should not have to infer what changed or when.

Check Your Understanding

Answer each question, then compare your reasoning with the solutions.

  1. A prediction package was committed at 16:00 UTC on 7 June. Outcomes were unblinded at 08:00 UTC on 9 June. How much earlier was the commit, and what does that chronology establish?
  2. A study requires 6 participants and 4 predictions per participant. The output has 24 rows, but one composite key appears twice. Is row-count reconciliation sufficient? What additional check is required?
  3. What can a cryptographic hash establish about a prediction file, and what can it not establish?
  4. A team discovers a unit-label error after locking but before unblinding. Describe an auditable way to handle the correction.
  5. Why does reproducing the stored predictions from the recorded code not, by itself, validate the PBPK model?

Solutions. (1) The elapsed time is \(24\) hours from 7 June at 16:00 to 8 June at 16:00, plus \(16\) hours to 9 June at 08:00, totaling \(40\) hours. This establishes that the recorded commit preceded the recorded unblinding, assuming the timestamps and custody records are credible; it does not rule out earlier outcome access. (2) The expected row count is \(6 \times 4=24\), but a duplicate can conceal a missing key. Check uniqueness and complete coverage of all 24 expected composite keys. (3) A hash can help detect whether the reviewed bytes differ from the bytes associated with a recorded hash. It cannot show that the contents are correct, when they were created without a trusted timestamp, or whether the model is valid. (4) Preserve the locked file, document the error and its discovery time, create a versioned corrected file and new manifest, recompute hashes, and retain the original. Since correction occurs before unblinding, document that chronology and ensure the correction does not use outcome information. (5) Reproduction supports consistency between recorded inputs, code, environment, and outputs. Predictive validity requires evidence about performance against independent observations; reproducibility alone does not supply that evidence.