Why transfer logs are not proof
Most migration tools report success when the target acknowledges each object. That tells you what was sent. It does not tell you what the target stored, whether it filed the study under the right patient, or whether it can return the study when someone queries for it a year from now.
Targets reject objects they don't support. They merge studies that share an accession number. They coerce patient IDs on ingest. A study can be acknowledged and still be unreachable. Validation means comparing the two systems directly, using the same questions a clinician's query would ask.
The rule: every study in the source ends up in one of three states. Verified in the target, deliberately excluded with a documented reason, or an open exception with an owner. Nothing is left unexplained.
1. Inventory the source first
You can't prove completeness without a baseline. Before moving anything, build a list of every study in the source: Study Instance UID, patient ID, accession number, study date, modalities, and series and instance counts.
- Query in small windows. Many archives cap how many results a single C-FIND returns. Break study-level queries into date ranges small enough that no window hits the cap, and confirm it by checking that no window returns exactly the limit.
- Catch studies with no date. A study with an empty or invalid Study Date never appears in a date-range query. Query for them separately, or read the archive database directly.
- Check the counts are returned. Number of Study Related Series and Instances are optional return keys. If the source doesn't return them, count at series level instead.
- Freeze a snapshot. The source keeps changing until cutover. Record when the inventory was taken, and plan a delta inventory before go-live.
The inventory doubles as your scoping document: it shows the real volume, the modality mix, the date range and where the data quality problems are, before they become migration problems.
2. Decide how studies match
Comparison only works if you know what "the same study" means in both systems.
- Study Instance UID first. It is the natural key, and it works when the migration preserves UIDs.
- A fallback key. Patient ID, accession number and study date together, for studies where UIDs were regenerated, or where the target split or merged studies.
- Apply the planned changes. If the migration remaps patient IDs to an enterprise MPI, adds issuer prefixes, or cleans accession numbers, compare against the expected value, not the original one. Otherwise every intentional change looks like a mismatch.
Write the matching rules down before the migration starts. They are part of the acceptance criteria.
3. Compare counts, top down
Start broad and drill down only where the numbers disagree. It keeps the work proportional to the problems.
| Level | Compare | Finds |
|---|---|---|
| Study | Study exists in target; series and instance counts match | Missing studies, partial studies |
| Series | Each Series Instance UID exists; instance count per series matches | Which series is short, and usually why (rejected SOP class, timeout on a large multi-frame object) |
| Instance | Each SOP Instance UID exists in the target | The exact objects to resend |
Some archives count differently. A target may include presentation states or key object selections that the source counts separately, or the reverse. Investigate small, consistent differences once, document the rule, and apply it across the archive.
4. Compare the metadata that matters
A study that arrived under the wrong patient is worse than a missing one, because nobody goes looking for it. After counts, compare the fields clinicians and downstream systems rely on:
- Patient ID and issuer, patient name, birth date and sex
- Accession number
- Study date and time, study description, modality
Normalize before comparing: name case and caret placement, date formats, character sets. Then compare against the expected post-migration value. See the DICOM tag reference for what to watch in each field.
5. Look at the images
Counts and headers don't show a picture that decoded wrong. Transcoding problems can invert grayscale, shift colors or drop frames while every count still matches. Open a sample of studies in the target viewer, weighted toward the risky ones:
- Studies that were transcoded between compression schemes
- Multi-frame objects: tomosynthesis, enhanced CT and MR, ultrasound cine
- Color data: ultrasound, secondary captures, whole-slide images
- Converted formats, such as Hologic SCO to BTO
- At least a few studies from every modality and every source site
6. Classify every exception
Every difference goes into a category with a next action. A typical breakdown:
| Category | What it means | Usual action |
|---|---|---|
| Missing | Study not found in the target | Resend; if it fails again, find out why |
| Partial | Study found, some series or instances missing | Resend the missing objects |
| Mismatched | Study found, key metadata differs from expected | Correct in the target or fix the mapping rule |
| Rejected | Target refused the object, often an unsupported SOP class or transfer syntax | Convert, or preserve outside the target |
| Unmatched | Study has no valid patient or order to attach to | Reconcile, quarantine or preserve. See unmatched studies |
| Expected | Excluded by scope, retention policy, or merged by design | Document the reason; no action |
Resolve, then re-validate. An exception is closed when the comparison passes, not when someone resent it.
7. Keep checking after cutover
Go-live is when the most new gaps appear. A modality nobody reconfigured keeps sending to the old PACS. A technologist corrects a study in the source the day after its delta ran. A target purges objects under a retention rule nobody expected.
Run a final reconciliation once the source is read-only, and keep a lighter comparison running for several weeks after. For archives that keep moving between systems, such as a PACS feeding a VNA, continuous monitoring is the only way to know they stay in sync. That's what DICOMatics Validate is built for.
Validation checklist
- Source inventory taken, with date windows that never hit the query capIncluding studies with empty or invalid dates
- Matching keys and fallback rules written down
- Expected changes listed: ID remaps, issuer prefixes, accession cleanup, merges
- Study-level counts compared for every study
- Series and instance comparison on every study that differs, plus a sample that matched
- Key metadata compared against expected values
- Visual sample in the target viewer, weighted to transcoded, multi-frame and color data
- Every exception categorized, owned and re-validated after resolution
- Final reconciliation after the source is read-only
- Validation report signed off: every study verified, excluded with a reason, or open with an owner
Questions
How do you validate a PACS migration?
Inventory every study in the source before the migration starts, decide which keys identify the same study in both systems, then compare study, series and instance counts and key metadata between source and target. Every difference is classified (missing, partial, mismatched, rejected, expected), resolved and re-checked, and the result is a report that accounts for every study.
Is a transfer log enough to prove a migration is complete?
No. A transfer log shows what the migration tool sent and what the target acknowledged. It does not show what the target actually stored, filed under the right patient, or can return when queried. Validation compares the two systems directly.
Should validation be done at study or instance level?
Both, in order. Study-level count comparison is fast and finds most problems. Series and instance comparison is slower, so it is usually run only on the studies whose counts differ, plus a sample of those that matched.
What match rate is acceptable?
The goal is that every study is accounted for, not a percentage. Some differences are expected and documented, such as studies excluded by scope or deliberately merged. What is not acceptable is an unexplained difference.
Does validation stop at cutover?
It should not. Modalities that still send to the old system, late corrections in the source, and target-side rejections can all create new gaps after go-live. A final reconciliation after cutover, or continuous monitoring, closes them.