@cosyte/dicom 0.0.19 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -11,7 +11,7 @@ var __export = (target, all) => {
11
11
  };
12
12
 
13
13
  // src/version.ts
14
- var VERSION = "0.0.19";
14
+ var VERSION = "0.1.1";
15
15
 
16
16
  // src/dictionary/index.ts
17
17
  var dictionary_exports = {};
@@ -1261,6 +1261,7 @@ var KEYWORDS = {
1261
1261
  "DopplerSampleVolumeYPosition": "0018603B",
1262
1262
  "DopplerSampleVolumeYPositionRetired": "0018603A",
1263
1263
  "DoseCalculationAlgorithmSequence": "30040081",
1264
+ "DoseCalculationModelName": "3004007F",
1264
1265
  "DoseCalculationModelParameterSequence": "30040083",
1265
1266
  "DoseCalculationModelSequence": "30040080",
1266
1267
  "DoseCalibrationConditionsSequence": "300C0120",
@@ -9348,6 +9349,7 @@ var TAGS = {
9348
9349
  "30040070": { tag: "30040070", keyword: "DVHMinimumDose", name: "DVH Minimum Dose", vr: ["DS"], vm: "1", retired: false },
9349
9350
  "30040072": { tag: "30040072", keyword: "DVHMaximumDose", name: "DVH Maximum Dose", vr: ["DS"], vm: "1", retired: false },
9350
9351
  "30040074": { tag: "30040074", keyword: "DVHMeanDose", name: "DVH Mean Dose", vr: ["DS"], vm: "1", retired: false },
9352
+ "3004007F": { tag: "3004007F", keyword: "DoseCalculationModelName", name: "Dose Calculation Model Name", vr: ["LO"], vm: "1", retired: false },
9351
9353
  "30040080": { tag: "30040080", keyword: "DoseCalculationModelSequence", name: "Dose Calculation Model Sequence", vr: ["SQ"], vm: "1", retired: false },
9352
9354
  "30040081": { tag: "30040081", keyword: "DoseCalculationAlgorithmSequence", name: "Dose Calculation Algorithm Sequence", vr: ["SQ"], vm: "1", retired: false },
9353
9355
  "30040082": { tag: "30040082", keyword: "CommissioningStatus", name: "Commissioning Status", vr: ["CS"], vm: "1", retired: false },
@@ -11092,6 +11094,129 @@ function uid(uidValue) {
11092
11094
  return FROZEN_UIDS[uidValue];
11093
11095
  }
11094
11096
 
11097
+ // src/dataset/directory.ts
11098
+ var MEDIA_STORAGE_DIRECTORY_STORAGE_UID = "1.2.840.10008.1.3.10";
11099
+ var TS_DEFLATED_LE = "1.2.840.10008.1.2.1.99";
11100
+ var DIRECTORY_TAGS = {
11101
+ /** Offset of the First Directory Record of the Root Directory Entity. */
11102
+ FIRST_ROOT_RECORD: "00041200",
11103
+ /** Offset of the Last Directory Record of the Root Directory Entity. */
11104
+ LAST_ROOT_RECORD: "00041202",
11105
+ /** Directory Record Sequence. */
11106
+ RECORD_SEQUENCE: "00041220",
11107
+ /** Offset of the Next Directory Record. */
11108
+ NEXT_RECORD: "00041400",
11109
+ /** Offset of Referenced Lower-Level Directory Entity. */
11110
+ LOWER_LEVEL: "00041420",
11111
+ /** Directory Record Type. */
11112
+ RECORD_TYPE: "00041430",
11113
+ /** Referenced File ID. */
11114
+ REFERENCED_FILE_ID: "00041500"
11115
+ };
11116
+ var ZERO = Object.freeze({ kind: "zero" });
11117
+ var MALFORMED = Object.freeze({ kind: "malformed" });
11118
+ function readOffsetValue(el) {
11119
+ if (el.vr === "SQ" || el.length !== 4 || el.rawBytes.length !== 4) return MALFORMED;
11120
+ const value = el.littleEndian ? el.rawBytes.readUInt32LE(0) : el.rawBytes.readUInt32BE(0);
11121
+ return value === 0 ? ZERO : { kind: "offset", value };
11122
+ }
11123
+ function isDicomdir(fileMeta) {
11124
+ return fileMeta?.mediaStorageSOPClassUID === MEDIA_STORAGE_DIRECTORY_STORAGE_UID;
11125
+ }
11126
+ function isDeflated(fileMeta) {
11127
+ return fileMeta?.transferSyntaxUID === TS_DEFLATED_LE;
11128
+ }
11129
+ function directoryRecords(source) {
11130
+ const items = source.get(DIRECTORY_TAGS.RECORD_SEQUENCE)?.items ?? [];
11131
+ const byFileOffset = /* @__PURE__ */ new Map();
11132
+ const shared = /* @__PURE__ */ new Set();
11133
+ items.forEach((item, index) => {
11134
+ const at3 = item.fileOffset;
11135
+ if (at3 === void 0) return;
11136
+ if (byFileOffset.has(at3)) shared.add(at3);
11137
+ else byFileOffset.set(at3, index);
11138
+ });
11139
+ for (const at3 of shared) byFileOffset.delete(at3);
11140
+ return { items, byFileOffset };
11141
+ }
11142
+ function csValues(el) {
11143
+ if (el === void 0) return void 0;
11144
+ const text = el.rawBytes.toString("latin1").replace(/[\0 ]+$/u, "");
11145
+ return Object.freeze(text === "" ? [] : text.split("\\").map((v) => v.replace(/^ +| +$/gu, "")));
11146
+ }
11147
+ function analyzeDirectory(source) {
11148
+ if (!isDicomdir(source.fileMeta)) return void 0;
11149
+ const deflated = isDeflated(source.fileMeta);
11150
+ const { items, byFileOffset } = directoryRecords(source);
11151
+ const findings = [];
11152
+ let deflatedOffset;
11153
+ const resolve = (element, item) => {
11154
+ if (element === void 0) return void 0;
11155
+ const offset = readOffsetValue(element);
11156
+ if (offset.kind === "zero") return void 0;
11157
+ if (offset.kind === "malformed") {
11158
+ findings.push({ kind: "malformed", element, item });
11159
+ return void 0;
11160
+ }
11161
+ if (deflated) {
11162
+ deflatedOffset ??= { kind: "deflated", element, item };
11163
+ return void 0;
11164
+ }
11165
+ const target = byFileOffset.get(offset.value);
11166
+ if (target === void 0) findings.push({ kind: "unresolved", element, item });
11167
+ return { element, item, target };
11168
+ };
11169
+ const first = resolve(source.get(DIRECTORY_TAGS.FIRST_ROOT_RECORD), void 0);
11170
+ resolve(source.get(DIRECTORY_TAGS.LAST_ROOT_RECORD), void 0);
11171
+ const next = [];
11172
+ const lower = [];
11173
+ for (const item of items) {
11174
+ next.push(resolve(item.get(DIRECTORY_TAGS.NEXT_RECORD), item));
11175
+ lower.push(resolve(item.get(DIRECTORY_TAGS.LOWER_LEVEL), item));
11176
+ }
11177
+ if (deflatedOffset !== void 0) findings.push(deflatedOffset);
11178
+ const children = [];
11179
+ const records = items.map((item, index) => {
11180
+ const lowerLevel = [];
11181
+ children.push(lowerLevel);
11182
+ return Object.freeze({
11183
+ index,
11184
+ type: csValues(item.get(DIRECTORY_TAGS.RECORD_TYPE))?.[0],
11185
+ referencedFileId: csValues(item.get(DIRECTORY_TAGS.REFERENCED_FILE_ID)),
11186
+ lowerLevel,
11187
+ item
11188
+ });
11189
+ });
11190
+ const reached = /* @__PURE__ */ new Set();
11191
+ const expand = [];
11192
+ const chain = (start, into) => {
11193
+ const entity = [];
11194
+ let link = start;
11195
+ while (link?.target !== void 0) {
11196
+ const at3 = link.target;
11197
+ if (reached.has(at3)) {
11198
+ findings.push({ kind: "revisited", element: link.element, item: link.item });
11199
+ break;
11200
+ }
11201
+ reached.add(at3);
11202
+ into.push(records[at3]);
11203
+ entity.push(at3);
11204
+ link = next[at3];
11205
+ }
11206
+ for (const at3 of entity.reverse()) expand.push(at3);
11207
+ };
11208
+ const root = [];
11209
+ chain(first, root);
11210
+ for (let at3 = expand.pop(); at3 !== void 0; at3 = expand.pop()) {
11211
+ chain(lower[at3], children[at3]);
11212
+ }
11213
+ for (const list of children) Object.freeze(list);
11214
+ return {
11215
+ directory: Object.freeze({ records: Object.freeze(records), root: Object.freeze(root) }),
11216
+ findings
11217
+ };
11218
+ }
11219
+
11095
11220
  // src/dataset/helpers/read.ts
11096
11221
  function readString(ds, tag) {
11097
11222
  const v = ds.get(tag)?.value;
@@ -11517,21 +11642,23 @@ var Dataset = class {
11517
11642
  fileMeta;
11518
11643
  warnings;
11519
11644
  /**
11520
- * Element map, keyed by uppercase 8-hex tag. Phase 3 promotes to
11521
- * public navigation surface; Phase 2 keeps it `protected` so only
11522
- * subclasses (`Item`, future Phase-3 extensions) can introspect.
11645
+ * Element map, keyed by uppercase 8-hex tag. Reached publicly through the
11646
+ * navigation surface; kept `protected` here so only subclasses (`Item`, and
11647
+ * any later extension) can introspect it directly.
11523
11648
  *
11524
11649
  * @internal
11525
11650
  */
11526
11651
  _elements;
11527
- /** Memoised Phase 4 domain views (built once, on first access). */
11652
+ /** Memoised domain views (built once, on first access). */
11528
11653
  _patient;
11529
11654
  _study;
11530
11655
  _series;
11531
11656
  _image;
11657
+ /** Boxed so a memoised "not a DICOMDIR" is told apart from "not read yet". */
11658
+ _directory;
11532
11659
  /**
11533
- * Construct a new structural `Dataset`. Phase 2 freezes the warnings
11534
- * array at the model boundary (sibling `message.ts` lines 117–118).
11660
+ * Construct a new structural `Dataset`. The warnings array is frozen at
11661
+ * the model boundary.
11535
11662
  *
11536
11663
  * @internal
11537
11664
  */
@@ -11600,7 +11727,7 @@ var Dataset = class {
11600
11727
  return el !== void 0 ? [el] : [];
11601
11728
  }
11602
11729
  /**
11603
- * Patient-identity view (§4.1). Fail-safe typed-absent fields; `id` is
11730
+ * Patient-identity view. Fail-safe typed-absent fields; `id` is
11604
11731
  * **not** globally unique - match on the `{id, issuerOfId, ...}` tuple
11605
11732
  * plus `otherIds`, never on a bare `(0010,0020)`. Memoised on first read.
11606
11733
  *
@@ -11615,7 +11742,7 @@ var Dataset = class {
11615
11742
  return this._patient ??= buildPatient(this);
11616
11743
  }
11617
11744
  /**
11618
- * Study-identity view (§4.1). `instanceUid` is the cross-system study
11745
+ * Study-identity view. `instanceUid` is the cross-system study
11619
11746
  * key; `accessionNumber` ties it to the order. Memoised on first read.
11620
11747
  *
11621
11748
  * @example
@@ -11629,7 +11756,7 @@ var Dataset = class {
11629
11756
  return this._study ??= buildStudy(this);
11630
11757
  }
11631
11758
  /**
11632
- * Series-identity & co-registration view (§4.1, §4.3). A shared
11759
+ * Series-identity & co-registration view. A shared
11633
11760
  * `frameOfReferenceUid` means images are spatially co-registered.
11634
11761
  * Memoised on first read.
11635
11762
  *
@@ -11644,7 +11771,7 @@ var Dataset = class {
11644
11771
  return this._series ??= buildSeries(this);
11645
11772
  }
11646
11773
  /**
11647
- * Pixel-interpretation + geometry view (§4.2–§4.5). Surfaces exactly
11774
+ * Pixel-interpretation + geometry view. Surfaces exactly
11648
11775
  * what a renderer needs without guessing: `rescaleSlope`/`signed`/
11649
11776
  * `photometricInterpretation` stay absent rather than defaulted, and the
11650
11777
  * three pixel-spacing tags are distinct. Memoised on first read.
@@ -11659,110 +11786,42 @@ var Dataset = class {
11659
11786
  get image() {
11660
11787
  return this._image ??= buildImage(this);
11661
11788
  }
11662
- };
11663
-
11664
- // src/parser/errors.ts
11665
- var FATAL_CODES = {
11666
- NOT_DICOM_PART_10: "NOT_DICOM_PART_10",
11667
- INVALID_FILE_META: "INVALID_FILE_META",
11668
- UNSUPPORTED_TRANSFER_SYNTAX: "UNSUPPORTED_TRANSFER_SYNTAX",
11669
- EMPTY_INPUT: "EMPTY_INPUT"
11670
- };
11671
- var OFFSET_FRAMES = {
11672
- /**
11673
- * Byte 0 is byte 0 of the buffer handed to `parseDicom`. The only frame in
11674
- * which indexing the caller's own input by `byteOffset` is meaningful.
11675
- */
11676
- INPUT: "input",
11677
- /**
11678
- * Byte 0 is byte 0 of the inflated Data Set of a Deflated Explicit VR LE
11679
- * object (`1.2.840.10008.1.2.1.99`). The compressed input holds no such
11680
- * byte, so the offset does not index it at any scale.
11681
- */
11682
- INFLATED_DATASET: "inflated-dataset",
11683
- /**
11684
- * Byte 0 is byte 0 of a slice this parser cut from inside a Value Field: a
11685
- * defined-length Sequence Item's value, or an `SQ`/`UN` value handed to a
11686
- * descent. **Where that slice begins is deliberately not published** - see
11687
- * this table's own note.
11688
- */
11689
- VALUE_SLICE: "value-slice"
11690
- };
11691
- var DicomParseError = class extends Error {
11692
- code;
11693
- byteOffset;
11694
- /**
11695
- * The coordinate system {@link DicomParseError.byteOffset} is counted in.
11696
- * See {@link OFFSET_FRAMES}.
11697
- */
11698
- offsetFrame;
11699
- snippet;
11700
- contextPath;
11701
11789
  /**
11702
- * Construct a new `DicomParseError`. All fields except `contextPath` are
11703
- * required so every thrower populates positional context per `TOL-02` - and
11704
- * `offsetFrame` is required for the same reason `byteOffset` is, because an
11705
- * offset whose frame is optional is an offset whose frame is usually
11706
- * missing.
11790
+ * The DICOMDIR Directory Record tree, or `undefined` when this Dataset is not
11791
+ * a DICOMDIR (its File Meta Media Storage SOP Class UID is not
11792
+ * `1.2.840.10008.1.3.10`). Read from the four offset attributes (PS3.3 2026d
11793
+ * Table F.3-3): `root` is the record `(0004,1200)` names and each
11794
+ * `(0004,1400)` successor, and each record's `lowerLevel` is the record its
11795
+ * `(0004,1420)` names and each successor. An offset resolves only when it is
11796
+ * exactly the file offset of an Item of the Directory Record Sequence
11797
+ * `(0004,1220)`; one that is not names no record, and `parseDicom` warns
11798
+ * (`DICOM_DIRECTORY_OFFSET_UNRESOLVED`, `DICOM_DIRECTORY_OFFSET_MALFORMED`,
11799
+ * `DICOM_DIRECTORY_RECORD_REVISITED`, `DICOM_DIRECTORY_OFFSET_DEFLATED`).
11800
+ * Memoised on first read.
11707
11801
  *
11708
- * @internal
11802
+ * Limits: record keys are not checked against PS3.3 F.5, the File-set
11803
+ * Consistency Flag and `(0004,1202)`'s agreement with the end of the root
11804
+ * chain are not checked, and under Deflated Explicit VR LE no offset resolves,
11805
+ * so every record is listed in `records` and none is linked.
11806
+ *
11807
+ * @example
11808
+ * ```ts
11809
+ * import { parseDicom } from "@cosyte/dicom";
11810
+ * const dir = parseDicom(buf).directory;
11811
+ * for (const patient of dir?.root ?? []) {
11812
+ * for (const study of patient.lowerLevel) {
11813
+ * for (const series of study.lowerLevel) {
11814
+ * for (const image of series.lowerLevel) console.log(image.referencedFileId);
11815
+ * }
11816
+ * }
11817
+ * }
11818
+ * ```
11709
11819
  */
11710
- constructor(code, message, byteOffset, offsetFrame, snippet, contextPath) {
11711
- const formatted = `[${code}] ${message} (offset=${String(byteOffset)} frame=${offsetFrame})` + (contextPath !== void 0 && contextPath.length > 0 ? ` \u2026 in ${contextPath.join("/")}` : "");
11712
- super(formatted);
11713
- this.name = "DicomParseError";
11714
- this.code = code;
11715
- this.byteOffset = byteOffset;
11716
- this.offsetFrame = offsetFrame;
11717
- this.snippet = snippet;
11718
- this.contextPath = contextPath;
11820
+ get directory() {
11821
+ this._directory ??= { value: analyzeDirectory(this)?.directory };
11822
+ return this._directory.value;
11719
11823
  }
11720
11824
  };
11721
- function buildSnippet(buffer, offset) {
11722
- if (offset < 0 || offset >= buffer.length) return "";
11723
- const end = Math.min(offset + 16, buffer.length);
11724
- const slice = buffer.subarray(offset, end);
11725
- const parts = [];
11726
- for (const b of slice) {
11727
- parts.push(b.toString(16).padStart(2, "0"));
11728
- }
11729
- return parts.join(" ");
11730
- }
11731
-
11732
- // src/parser/emit.ts
11733
- function makeEmitter(ctx) {
11734
- const escalate = (w) => {
11735
- throw new DicomParseError(
11736
- // D-35 cast: the WarningCode union does not overlap FatalCode at the
11737
- // type level, but at runtime the strict-thrown error carries the
11738
- // warning code so consumers can narrow on err.code uniformly.
11739
- w.code,
11740
- w.message,
11741
- w.position.byteOffset,
11742
- // Both come off the SAME frame object, so an escalation cannot name one
11743
- // frame and cut its bytes from another. `DicomParseWarning.position`
11744
- // itself carries no frame - that is `PRE-EXISTING` and stated on
11745
- // `DicomPosition`, not closed here.
11746
- ctx.frame.name,
11747
- buildSnippet(ctx.frame.buffer, w.position.byteOffset),
11748
- w.position.contextPath
11749
- );
11750
- };
11751
- return (w) => {
11752
- if (ctx.strict) escalate(w);
11753
- if (ctx.profile !== void 0) {
11754
- if (ctx.profile.suppressions.has(w.code)) return;
11755
- if (ctx.profile.escalations.has(w.code)) escalate(w);
11756
- }
11757
- ctx.warnings.push(w);
11758
- if (ctx.onWarning !== void 0) {
11759
- try {
11760
- ctx.onWarning(w);
11761
- } catch {
11762
- }
11763
- }
11764
- };
11765
- }
11766
11825
 
11767
11826
  // src/parser/endian.ts
11768
11827
  var BE_VR_STRIDE = Object.freeze({
@@ -11783,7 +11842,7 @@ var BE_VR_STRIDE = Object.freeze({
11783
11842
  OV: 8,
11784
11843
  SV: 8,
11785
11844
  UV: 8,
11786
- // No swap - byte streams (D-24) and ASCII / spec-defined VRs.
11845
+ // No swap - byte streams and ASCII / spec-defined VRs.
11787
11846
  OB: 0,
11788
11847
  UN: 0,
11789
11848
  AE: 0,
@@ -11827,377 +11886,13 @@ function renderTag(tag) {
11827
11886
  return lookup(tag) === void 0 ? WITHHELD : tag;
11828
11887
  }
11829
11888
 
11830
- // src/parser/fatals.ts
11831
- var SUPPORTED_TRANSFER_SYNTAXES = "1.2.840.10008.1.2, 1.2.840.10008.1.2.1, 1.2.840.10008.1.2.2, 1.2.840.10008.1.2.1.99";
11832
- var ZLIB_CODES = Object.freeze(
11833
- /* @__PURE__ */ new Set([
11834
- "Z_OK",
11835
- "Z_STREAM_END",
11836
- "Z_NEED_DICT",
11837
- "Z_ERRNO",
11838
- "Z_STREAM_ERROR",
11839
- "Z_DATA_ERROR",
11840
- "Z_MEM_ERROR",
11841
- "Z_BUF_ERROR",
11842
- "Z_VERSION_ERROR"
11843
- ])
11844
- );
11845
- var FATAL_MESSAGES = Object.freeze({
11846
- EMPTY_INPUT: {
11847
- code: FATAL_CODES.EMPTY_INPUT,
11848
- message: "Input is empty."
11849
- },
11850
- EMPTY_INPUT_AFTER_NORMALIZATION: {
11851
- code: FATAL_CODES.EMPTY_INPUT,
11852
- message: "Input is empty after normalization."
11853
- },
11854
- NOT_DICOM_PART_10_REQUIRED: {
11855
- code: FATAL_CODES.NOT_DICOM_PART_10,
11856
- message: "Missing DICM magic at offset 128 (stripPreamble='require')."
11857
- },
11858
- NOT_DICOM_PART_10: {
11859
- code: FATAL_CODES.NOT_DICOM_PART_10,
11860
- message: "Input is not a DICOM Part 10 file (no DICM magic at offset 128 and no recognizable File Meta group at offset 0)."
11861
- },
11862
- // `{ts}` is NOT the UID. It is the PS3.6 registry's own name for the UID, or a
11863
- // fixed phrase when PS3.6 does not publish one - see `renderTransferSyntax`.
11864
- UNSUPPORTED_TRANSFER_SYNTAX: {
11865
- code: FATAL_CODES.UNSUPPORTED_TRANSFER_SYNTAX,
11866
- message: `{ts} in (0002,0010) is not supported by @cosyte/dicom v1 (supported: ${SUPPORTED_TRANSFER_SYNTAXES}).`
11867
- },
11868
- FILE_META_TRUNCATED: {
11869
- code: FATAL_CODES.INVALID_FILE_META,
11870
- message: "File Meta is truncated."
11871
- },
11872
- // The declared group length is deliberately absent. It is four bytes of the
11873
- // document read as a 32-bit integer. **NOT because this code fires only when
11874
- // those four bytes are fabricated** - an honestly truncated file raises it
11875
- // with a perfectly correct group length, measured - but because they are four
11876
- // bytes a sender wrote in either reading, and in the other one they are part
11877
- // of somebody's value.
11878
- FILE_META_GROUP_LENGTH_OVERRUNS: {
11879
- code: FATAL_CODES.INVALID_FILE_META,
11880
- message: "(0002,0000) FileMetaInformationGroupLength declares more bytes than remain in the input. The declared length and the count of bytes that remain are withheld; the byte offset locates the group."
11881
- },
11882
- FILE_META_TRANSFER_SYNTAX_MISSING: {
11883
- code: FATAL_CODES.INVALID_FILE_META,
11884
- message: "Required File Meta element (0002,0010) Transfer Syntax UID is missing or not UI."
11885
- },
11886
- TRUNCATED_DATASET_HEADER: {
11887
- code: FATAL_CODES.INVALID_FILE_META,
11888
- message: "Truncated dataset (header read past buffer end)."
11889
- },
11890
- TRUNCATED_FFFE_HEADER: {
11891
- code: FATAL_CODES.INVALID_FILE_META,
11892
- message: "Truncated dataset (FFFE header read past buffer end)."
11893
- },
11894
- TRUNCATED_EXPLICIT_VR_HEADER: {
11895
- code: FATAL_CODES.INVALID_FILE_META,
11896
- message: "Truncated dataset (Explicit VR header read past buffer end)."
11897
- },
11898
- SQ_ITEM_HEADER_TRUNCATED: {
11899
- code: FATAL_CODES.INVALID_FILE_META,
11900
- message: "Truncated dataset (SQ item header read past buffer end)."
11901
- },
11902
- // Neither the marker's element number nor its length field is here. Both are
11903
- // read at a position the reader may have desynchronized to, so both are
11904
- // document content: the length field measured as 1109414477, `"MR B"`.
11905
- UNEXPECTED_FFFE_AT_DATASET_LEVEL: {
11906
- code: FATAL_CODES.INVALID_FILE_META,
11907
- message: "An (FFFE,xxxx) delimitation item appears at Data Set level under Explicit VR, where no sequence is open. Its element number and its length field are withheld; the byte offset locates it."
11908
- },
11909
- UNEXPECTED_FFFE_AT_DATASET_ROOT: {
11910
- code: FATAL_CODES.INVALID_FILE_META,
11911
- message: "An (FFFE,xxxx) delimitation item appears at Data Set level under Implicit VR LE, where no sequence is open. Its element number is withheld; the byte offset locates it."
11912
- },
11913
- UNDEFINED_LENGTH_ON_NON_SQ_EXPLICIT: {
11914
- code: FATAL_CODES.INVALID_FILE_META,
11915
- message: "An element with VR={vr} declares undefined length (0xFFFFFFFF) under Explicit VR. PS3.5 2026c permits that for a Sequence (7.5.2 Delimitation of The Sequence of Items), for encapsulated (7FE0,0010) Pixel Data (A.4), and for the UN form CP-246 addresses (6.2.2 Unknown (UN) Value Representation), and this element is none of them. Its tag is withheld; the byte offset locates it."
11916
- },
11917
- UNDEFINED_LENGTH_ON_NON_SQ_IMPLICIT: {
11918
- code: FATAL_CODES.INVALID_FILE_META,
11919
- message: "An element whose VR resolved to {vr} declares undefined length (0xFFFFFFFF) under Implicit VR LE, and the descent as an Implicit VR LE item stream (PS3.5 2026c 6.2.2, the UN form CP-246 addresses) did not succeed. Its tag is withheld; the byte offset locates it."
11920
- },
11921
- ELEMENT_LENGTH_EXCEEDS_BUFFER: {
11922
- code: FATAL_CODES.INVALID_FILE_META,
11923
- message: "An element declares a Value Length reaching past the end of the bytes being read. Its tag, its declared length and the count of bytes that remain are withheld; the byte offset locates it."
11924
- },
11925
- UNEXPECTED_TAG_INSIDE_SEQUENCE: {
11926
- code: FATAL_CODES.INVALID_FILE_META,
11927
- message: "A sequence's item stream holds a tag that is neither (FFFE,E000) Item nor (FFFE,E0DD) Sequence Delimitation Item (PS3.5 7.5). That tag is withheld: a value being read as an item stream makes its four bytes document content. The byte offset locates it."
11928
- },
11929
- ENCAPSULATED_FRAGMENT_EXCEEDS_BUFFER: {
11930
- code: FATAL_CODES.INVALID_FILE_META,
11931
- message: "An encapsulated Pixel Data fragment declares a length reaching past the end of the bytes being read. The declared length is withheld; the byte offset locates the fragment."
11932
- },
11933
- ITEM_LENGTH_EXCEEDS_BUFFER: {
11934
- code: FATAL_CODES.INVALID_FILE_META,
11935
- message: "An (FFFE,E000) Item declares a length reaching past the end of the bytes being read. The declared length is withheld; the byte offset locates the item."
11936
- },
11937
- SQ_NESTING_DEPTH_EXCEEDED: {
11938
- code: FATAL_CODES.INVALID_FILE_META,
11939
- message: "SQ nesting depth exceeds {n}."
11940
- },
11941
- INFLATED_PAYLOAD_EXCEEDS_CAP: {
11942
- code: FATAL_CODES.INVALID_FILE_META,
11943
- message: "Inflated Deflated TS payload exceeds {n}-byte cap."
11944
- },
11945
- // `{zlib}` is a member of the nine-name `zlib.codes` table or nothing. zlib's
11946
- // own `err.message` is never forwarded: it is a string from a library handed
11947
- // the sender's bytes, which is the one shape of third-party text this parser
11948
- // cannot vouch for.
11949
- INFLATE_FAILED: {
11950
- code: FATAL_CODES.INVALID_FILE_META,
11951
- message: "Failed to inflate Deflated TS payload (zlib error code: {zlib})."
11952
- }
11953
- });
11954
- function renderTransferSyntax(ts) {
11955
- if (ts === void 0) return "The Transfer Syntax UID";
11956
- const name = uid(ts)?.name ?? "";
11957
- return name.length > 0 ? `Transfer Syntax ${name}` : "The Transfer Syntax UID";
11958
- }
11959
- function renderZlibCode(code) {
11960
- return code !== void 0 && ZLIB_CODES.has(code) ? code : WITHHELD;
11961
- }
11962
- function build(key, byteOffset, offsetFrame, snippet, tokens = {}) {
11963
- const entry = FATAL_MESSAGES[key];
11964
- const message = entry.message.replace("{vr}", renderVr(tokens.vr)).replace("{ts}", renderTransferSyntax(tokens.ts)).replace("{zlib}", renderZlibCode(tokens.zlib)).replace("{n}", String(tokens.n ?? 0));
11965
- return new DicomParseError(entry.code, message, byteOffset, offsetFrame, snippet);
11966
- }
11967
- function at(key, frame, offset, tokens = {}) {
11968
- return build(key, offset, frame.name, buildSnippet(frame.buffer, offset), tokens);
11969
- }
11970
- function emptyInput() {
11971
- return build("EMPTY_INPUT", 0, OFFSET_FRAMES.INPUT, "");
11972
- }
11973
- function emptyInputAfterNormalization() {
11974
- return build("EMPTY_INPUT_AFTER_NORMALIZATION", 0, OFFSET_FRAMES.INPUT, "");
11975
- }
11976
- function notDicomPart10Required(frame, offset) {
11977
- return at("NOT_DICOM_PART_10_REQUIRED", frame, offset);
11978
- }
11979
- function notDicomPart10(frame, offset) {
11980
- return at("NOT_DICOM_PART_10", frame, offset);
11981
- }
11982
- function unsupportedTransferSyntax(frame, offset, ts) {
11983
- const name = uid(ts)?.name ?? "";
11984
- return build(
11985
- "UNSUPPORTED_TRANSFER_SYNTAX",
11986
- offset,
11987
- frame.name,
11988
- name.length > 0 ? name : buildSnippet(frame.buffer, offset),
11989
- { ts }
11990
- );
11991
- }
11992
- function fileMetaTruncated(frame, offset) {
11993
- return at("FILE_META_TRUNCATED", frame, offset);
11994
- }
11995
- function fileMetaGroupLengthOverruns(frame, offset) {
11996
- return at("FILE_META_GROUP_LENGTH_OVERRUNS", frame, offset);
11997
- }
11998
- function fileMetaTransferSyntaxMissing(frame, offset) {
11999
- return at("FILE_META_TRANSFER_SYNTAX_MISSING", frame, offset);
12000
- }
12001
- function truncatedDatasetHeader(frame, offset) {
12002
- return at("TRUNCATED_DATASET_HEADER", frame, offset);
12003
- }
12004
- function truncatedFffeHeader(frame, offset) {
12005
- return at("TRUNCATED_FFFE_HEADER", frame, offset);
12006
- }
12007
- function truncatedExplicitVrHeader(frame, offset) {
12008
- return at("TRUNCATED_EXPLICIT_VR_HEADER", frame, offset);
12009
- }
12010
- function sqItemHeaderTruncated(frame, offset) {
12011
- return at("SQ_ITEM_HEADER_TRUNCATED", frame, offset);
12012
- }
12013
- function unexpectedFffeAtDatasetLevel(frame, offset) {
12014
- return at("UNEXPECTED_FFFE_AT_DATASET_LEVEL", frame, offset);
12015
- }
12016
- function unexpectedFffeAtDatasetRoot(frame, offset) {
12017
- return at("UNEXPECTED_FFFE_AT_DATASET_ROOT", frame, offset);
12018
- }
12019
- function undefinedLengthOnNonSqExplicit(frame, offset, vr) {
12020
- return at("UNDEFINED_LENGTH_ON_NON_SQ_EXPLICIT", frame, offset, { vr });
12021
- }
12022
- function undefinedLengthOnNonSqImplicit(frame, offset, vr) {
12023
- return at("UNDEFINED_LENGTH_ON_NON_SQ_IMPLICIT", frame, offset, { vr });
12024
- }
12025
- function elementLengthExceedsBuffer(frame, offset) {
12026
- return at("ELEMENT_LENGTH_EXCEEDS_BUFFER", frame, offset);
12027
- }
12028
- function unexpectedTagInsideSequence(frame, offset) {
12029
- return at("UNEXPECTED_TAG_INSIDE_SEQUENCE", frame, offset);
12030
- }
12031
- function encapsulatedFragmentExceedsBuffer(frame, offset) {
12032
- return at("ENCAPSULATED_FRAGMENT_EXCEEDS_BUFFER", frame, offset);
12033
- }
12034
- function itemLengthExceedsBuffer(frame, offset) {
12035
- return at("ITEM_LENGTH_EXCEEDS_BUFFER", frame, offset);
12036
- }
12037
- function sqNestingDepthExceeded(frame, offset, limit) {
12038
- return at("SQ_NESTING_DEPTH_EXCEEDED", frame, offset, { n: limit });
12039
- }
12040
- function inflatedPayloadExceedsCap(frame, offset, cap) {
12041
- return at("INFLATED_PAYLOAD_EXCEEDS_CAP", frame, offset, { n: cap });
12042
- }
12043
- function inflateFailed(frame, offset, code) {
12044
- return at("INFLATE_FAILED", frame, offset, ...code !== void 0 ? [{ zlib: code }] : []);
12045
- }
12046
- function copyValueBytes(src) {
12047
- const out = buffer.Buffer.allocUnsafeSlow(src.length);
12048
- src.copy(out);
12049
- return out;
12050
- }
12051
- var ByteCursor = class {
12052
- buffer;
12053
- littleEndian;
12054
- position;
12055
- /**
12056
- * Construct a new cursor at `position` (default 0) over `buffer` with
12057
- * the given endian orientation.
12058
- *
12059
- * @internal
12060
- */
12061
- constructor(buffer, littleEndian, position = 0) {
12062
- this.buffer = buffer;
12063
- this.littleEndian = littleEndian;
12064
- this.position = position;
12065
- }
12066
- /** Read a 16-bit unsigned integer at the current position; advance by 2. */
12067
- readUInt16() {
12068
- if (this.position + 2 > this.buffer.length) {
12069
- throw new RangeError("ByteCursor: read past end of buffer");
12070
- }
12071
- const v = this.littleEndian ? this.buffer.readUInt16LE(this.position) : this.buffer.readUInt16BE(this.position);
12072
- this.position += 2;
12073
- return v;
12074
- }
12075
- /** Read a 32-bit unsigned integer at the current position; advance by 4. */
12076
- readUInt32() {
12077
- if (this.position + 4 > this.buffer.length) {
12078
- throw new RangeError("ByteCursor: read past end of buffer");
12079
- }
12080
- const v = this.littleEndian ? this.buffer.readUInt32LE(this.position) : this.buffer.readUInt32BE(this.position);
12081
- this.position += 4;
12082
- return v;
12083
- }
12084
- /** Read a 16-bit unsigned integer at an explicit offset; cursor unchanged. */
12085
- readUInt16At(offset) {
12086
- if (offset < 0 || offset + 2 > this.buffer.length) {
12087
- throw new RangeError("ByteCursor: read past end of buffer");
12088
- }
12089
- return this.littleEndian ? this.buffer.readUInt16LE(offset) : this.buffer.readUInt16BE(offset);
12090
- }
12091
- /** Read a 32-bit unsigned integer at an explicit offset; cursor unchanged. */
12092
- readUInt32At(offset) {
12093
- if (offset < 0 || offset + 4 > this.buffer.length) {
12094
- throw new RangeError("ByteCursor: read past end of buffer");
12095
- }
12096
- return this.littleEndian ? this.buffer.readUInt32LE(offset) : this.buffer.readUInt32BE(offset);
12097
- }
12098
- /**
12099
- * Take a `length`-byte view starting at the current position; advance
12100
- * the cursor by `length`. Returns a `Buffer.subarray` (zero-copy view);
12101
- * callers wanting a copy must `Buffer.from(slice)` themselves.
12102
- */
12103
- slice(length) {
12104
- if (length < 0 || this.position + length > this.buffer.length) {
12105
- throw new RangeError("ByteCursor: read past end of buffer");
12106
- }
12107
- const out = this.buffer.subarray(this.position, this.position + length);
12108
- this.position += length;
12109
- return out;
12110
- }
12111
- /** Bytes remaining between the current position and the end of the buffer. */
12112
- remaining() {
12113
- return this.buffer.length - this.position;
12114
- }
12115
- };
12116
-
12117
- // src/dataset/vr/charset.ts
12118
- var TERM_TO_LABEL = /* @__PURE__ */ new Map([
12119
- // Default repertoire (ISO 646 IRV / ASCII). Latin-1 is a lenient,
12120
- // never-throws 1:1 superset for the ASCII range.
12121
- ["", "latin1"],
12122
- ["ISO_IR 6", "latin1"],
12123
- ["ISO 2022 IR 6", "latin1"],
12124
- // Single-byte Latin / Cyrillic / Arabic / Greek / Hebrew / Thai.
12125
- ["ISO_IR 100", "latin1"],
12126
- ["ISO 2022 IR 100", "latin1"],
12127
- ["ISO_IR 101", "iso-8859-2"],
12128
- ["ISO 2022 IR 101", "iso-8859-2"],
12129
- ["ISO_IR 109", "iso-8859-3"],
12130
- ["ISO 2022 IR 109", "iso-8859-3"],
12131
- ["ISO_IR 110", "iso-8859-4"],
12132
- ["ISO 2022 IR 110", "iso-8859-4"],
12133
- ["ISO_IR 144", "iso-8859-5"],
12134
- ["ISO 2022 IR 144", "iso-8859-5"],
12135
- ["ISO_IR 127", "iso-8859-6"],
12136
- ["ISO 2022 IR 127", "iso-8859-6"],
12137
- ["ISO_IR 126", "iso-8859-7"],
12138
- ["ISO 2022 IR 126", "iso-8859-7"],
12139
- ["ISO_IR 138", "iso-8859-8"],
12140
- ["ISO 2022 IR 138", "iso-8859-8"],
12141
- ["ISO_IR 148", "iso-8859-9"],
12142
- ["ISO 2022 IR 148", "iso-8859-9"],
12143
- ["ISO_IR 203", "iso-8859-15"],
12144
- ["ISO 2022 IR 203", "iso-8859-15"],
12145
- ["ISO_IR 13", "shift_jis"],
12146
- ["ISO 2022 IR 13", "shift_jis"],
12147
- ["ISO_IR 166", "windows-874"],
12148
- ["ISO 2022 IR 166", "windows-874"],
12149
- // Unicode / Chinese single-shot.
12150
- ["ISO_IR 192", "utf-8"],
12151
- ["GB18030", "gb18030"],
12152
- ["GBK", "gbk"],
12153
- // Multibyte code-extension terms (no bare ISO_IR form).
12154
- ["ISO 2022 IR 87", "iso-2022-jp"],
12155
- ["ISO 2022 IR 159", "iso-2022-jp"],
12156
- ["ISO 2022 IR 149", "euc-kr"],
12157
- ["ISO 2022 IR 58", "gb18030"]
12158
- ]);
12159
- var MULTIBYTE_LABELS = /* @__PURE__ */ new Set([
12160
- "utf-8",
12161
- "iso-2022-jp",
12162
- "euc-kr",
12163
- "gb18030",
12164
- "gbk",
12165
- "shift_jis"
12166
- ]);
12167
- function parseSpecificCharacterSet(bytes) {
12168
- const raw = bytes.toString("latin1");
12169
- return raw.split("\\").map((t) => t.replace(/[ ]+$/u, "").replace(/^[ ]+/u, "")).map((t) => t === "" || TERM_TO_LABEL.has(t) ? t : WITHHELD);
12170
- }
12171
- function isKnownCharsetTerm(term) {
12172
- return TERM_TO_LABEL.has(term);
12173
- }
12174
- function resolveDecoderLabel(terms) {
12175
- if (terms === void 0 || terms.length === 0) return "latin1";
12176
- let firstKnown;
12177
- for (const term of terms) {
12178
- const label = TERM_TO_LABEL.get(term);
12179
- if (label === void 0) continue;
12180
- if (MULTIBYTE_LABELS.has(label)) return label;
12181
- firstKnown ??= label;
12182
- }
12183
- return firstKnown ?? "latin1";
12184
- }
12185
- function decodeText(bytes, terms) {
12186
- const label = resolveDecoderLabel(terms);
12187
- try {
12188
- return new TextDecoder(label, { fatal: false }).decode(bytes);
12189
- } catch {
12190
- try {
12191
- return new TextDecoder("utf-8", { fatal: false }).decode(bytes);
12192
- } catch {
12193
- return bytes.toString("latin1");
12194
- }
12195
- }
12196
- }
12197
-
12198
11889
  // src/parser/warnings.ts
12199
11890
  var WARNING_CODES = {
12200
- // === Phase 2 actively emits (D-08 active list - alphabetical-within-prefix per CONTEXT specifics §) ===
11891
+ // === The parser actively emits these (alphabetical within prefix) ===
11892
+ DICOM_DIRECTORY_OFFSET_DEFLATED: "DICOM_DIRECTORY_OFFSET_DEFLATED",
11893
+ DICOM_DIRECTORY_OFFSET_MALFORMED: "DICOM_DIRECTORY_OFFSET_MALFORMED",
11894
+ DICOM_DIRECTORY_OFFSET_UNRESOLVED: "DICOM_DIRECTORY_OFFSET_UNRESOLVED",
11895
+ DICOM_DIRECTORY_RECORD_REVISITED: "DICOM_DIRECTORY_RECORD_REVISITED",
12201
11896
  DICOM_DUPLICATE_FILE_META_ELEMENT: "DICOM_DUPLICATE_FILE_META_ELEMENT",
12202
11897
  DICOM_DUPLICATE_TAG_IN_DATA_SET: "DICOM_DUPLICATE_TAG_IN_DATA_SET",
12203
11898
  DICOM_EMPTY_ITEM_IN_SEQUENCE: "DICOM_EMPTY_ITEM_IN_SEQUENCE",
@@ -12209,13 +11904,14 @@ var WARNING_CODES = {
12209
11904
  DICOM_MISSING_PREAMBLE: "DICOM_MISSING_PREAMBLE",
12210
11905
  DICOM_NONZERO_RESERVED_BYTES: "DICOM_NONZERO_RESERVED_BYTES",
12211
11906
  DICOM_ODD_LENGTH_VALUE_PADDED: "DICOM_ODD_LENGTH_VALUE_PADDED",
11907
+ DICOM_PIXEL_DATA_FRAGMENTS_NOT_DELIMITED: "DICOM_PIXEL_DATA_FRAGMENTS_NOT_DELIMITED",
12212
11908
  DICOM_PIXEL_DATA_LENGTH_MISMATCH: "DICOM_PIXEL_DATA_LENGTH_MISMATCH",
12213
11909
  DICOM_PRIVATE_TAG_NO_CREATOR: "DICOM_PRIVATE_TAG_NO_CREATOR",
12214
11910
  DICOM_SQ_NOT_DESCENDED: "DICOM_SQ_NOT_DESCENDED",
12215
11911
  DICOM_UN_PARSED_AS_SQ: "DICOM_UN_PARSED_AS_SQ",
12216
11912
  DICOM_UNDEFINED_LENGTH_IN_EXPLICIT_VR: "DICOM_UNDEFINED_LENGTH_IN_EXPLICIT_VR",
12217
11913
  DICOM_VR_MISMATCH: "DICOM_VR_MISMATCH",
12218
- // === VR-decode-time codes (declared but not emitted in Phase 2; Phase 3 lazy decoders fire these - D-08, D-42) ===
11914
+ // === VR-decode-time codes (declared here; the lazy value decoders fire them) ===
12219
11915
  DICOM_BOM_IN_TEXT_VR: "DICOM_BOM_IN_TEXT_VR",
12220
11916
  DICOM_DA_LEGACY_FORMAT: "DICOM_DA_LEGACY_FORMAT",
12221
11917
  DICOM_DT_NONSTANDARD_OFFSET: "DICOM_DT_NONSTANDARD_OFFSET",
@@ -12223,14 +11919,29 @@ var WARNING_CODES = {
12223
11919
  DICOM_NON_ASCII_IN_ASCII_VR: "DICOM_NON_ASCII_IN_ASCII_VR",
12224
11920
  DICOM_TRAILING_NULL_IN_TEXT_VR: "DICOM_TRAILING_NULL_IN_TEXT_VR",
12225
11921
  DICOM_UI_TRAILING_SPACE: "DICOM_UI_TRAILING_SPACE",
12226
- // === Phase 4 charset-decode codes (declared, not emitted in Phase 2 - D-08, D-43) ===
11922
+ // === Charset-decode codes (declared here; the text decoders fire them) ===
12227
11923
  DICOM_CHARSET_AMBIGUOUS_SEPARATOR: "DICOM_CHARSET_AMBIGUOUS_SEPARATOR",
11924
+ DICOM_CHARSET_BYTES_UNDECODABLE: "DICOM_CHARSET_BYTES_UNDECODABLE",
11925
+ DICOM_CHARSET_ESCAPE_UNDECLARED: "DICOM_CHARSET_ESCAPE_UNDECLARED",
11926
+ DICOM_CHARSET_EXTENSION_NOT_RESET: "DICOM_CHARSET_EXTENSION_NOT_RESET",
12228
11927
  DICOM_UNSUPPORTED_CHARSET: "DICOM_UNSUPPORTED_CHARSET",
12229
- // === Reserved by later phases (declared, not emitted in Phase 2) ===
11928
+ // === Declared here, emitted elsewhere or not yet emitted at all ===
12230
11929
  DICOM_BURNED_IN_ANNOTATION_NOT_REMOVED: "DICOM_BURNED_IN_ANNOTATION_NOT_REMOVED",
12231
- // reserved by Phase 7 - not emitted in Phase 2
11930
+ // emitted by deidentify(), never by the parser
11931
+ DICOM_DEIDENT_DATES_NOT_TRANSFORMED: "DICOM_DEIDENT_DATES_NOT_TRANSFORMED",
11932
+ // emitted by deidentify(), never by the parser
11933
+ DICOM_DEIDENT_DICOMDIR_FILE_SET_NOT_DISCHARGED: "DICOM_DEIDENT_DICOMDIR_FILE_SET_NOT_DISCHARGED",
11934
+ // emitted by deidentify(), never by the parser
12232
11935
  DICOM_DEIDENT_EMBEDDED_ATTRIBUTE_REMOVED: "DICOM_DEIDENT_EMBEDDED_ATTRIBUTE_REMOVED",
12233
11936
  // emitted by deidentify(), never by the parser
11937
+ DICOM_DEIDENT_FILE_META_REPLACED: "DICOM_DEIDENT_FILE_META_REPLACED",
11938
+ // emitted by deidentify(), never by the parser
11939
+ DICOM_DEIDENT_GROUP_0004_REMOVED: "DICOM_DEIDENT_GROUP_0004_REMOVED",
11940
+ // emitted by deidentify(), never by the parser
11941
+ DICOM_DEIDENT_METHOD_CODES_PRIOR_REPLACED: "DICOM_DEIDENT_METHOD_CODES_PRIOR_REPLACED",
11942
+ // emitted by deidentify(), never by the parser
11943
+ DICOM_DEIDENT_METHOD_CODES_PRIOR_RETAINED: "DICOM_DEIDENT_METHOD_CODES_PRIOR_RETAINED",
11944
+ // emitted by deidentify(), never by the parser
12234
11945
  DICOM_DEIDENT_METHOD_NOT_ADDED: "DICOM_DEIDENT_METHOD_NOT_ADDED",
12235
11946
  // emitted by deidentify(), never by the parser
12236
11947
  DICOM_DEIDENT_METHOD_NOT_LO: "DICOM_DEIDENT_METHOD_NOT_LO",
@@ -12239,12 +11950,18 @@ var WARNING_CODES = {
12239
11950
  // emitted by deidentify(), never by the parser
12240
11951
  DICOM_DEIDENT_METHOD_VALUE_OVER_LENGTH: "DICOM_DEIDENT_METHOD_VALUE_OVER_LENGTH",
12241
11952
  // emitted by deidentify(), never by the parser
11953
+ DICOM_DEIDENT_PRIVATE_CARRIER_NOT_AUDITABLE: "DICOM_DEIDENT_PRIVATE_CARRIER_NOT_AUDITABLE",
11954
+ // emitted by deidentify(), never by the parser
11955
+ DICOM_DEIDENT_PRIVATE_DECLARATION_NOT_RESOLVED: "DICOM_DEIDENT_PRIVATE_DECLARATION_NOT_RESOLVED",
11956
+ // emitted by deidentify(), never by the parser
12242
11957
  DICOM_DEIDENT_SEQUENCE_NOT_AUDITABLE: "DICOM_DEIDENT_SEQUENCE_NOT_AUDITABLE",
12243
11958
  // emitted by deidentify(), never by the parser
12244
11959
  DICOM_DEIDENT_UNDEFINED_VR_NOT_AUDITABLE: "DICOM_DEIDENT_UNDEFINED_VR_NOT_AUDITABLE",
12245
11960
  // emitted by deidentify(), never by the parser
11961
+ DICOM_DEIDENT_UNREGISTERED_ELEMENT_REMOVED: "DICOM_DEIDENT_UNREGISTERED_ELEMENT_REMOVED",
11962
+ // emitted by deidentify(), never by the parser
12246
11963
  DICOM_PRIVATE_CREATOR_UNKNOWN: "DICOM_PRIVATE_CREATOR_UNKNOWN"
12247
- // reserved by Phase 6 - not emitted in Phase 2
11964
+ // emitted only when a profile is active
12248
11965
  };
12249
11966
  var WARNING_MESSAGES = Object.freeze({
12250
11967
  DICOM_MISSING_PREAMBLE: "No DICM magic at offset 128; falling back to offset-0 dataset.",
@@ -12331,6 +12048,17 @@ var WARNING_MESSAGES = Object.freeze({
12331
12048
  // count, so a conformant 64-character Value can exceed 64 bytes under a
12332
12049
  // single-byte repertoire too. The message states what was measured.
12333
12050
  DICOM_DEIDENT_METHOD_VALUE_OVER_LENGTH: "The De-identification Method (0012,0063) this run wrote carries a Value longer than 64 bytes. PS3.5 Table 6.2-1 bounds an LO Value at 64 characters, per Value and not per Value Field, and PS3.5 6.2 specifies that length in characters rather than bytes and excludes Code Extension escape sequences from the count: a Value of 64 bytes or fewer can never carry more than 64 characters, but a longer one is not necessarily over the maximum. This run never shortens, splits or truncates a Value it did not compose: a caller-supplied method, and a value the source file already carried, are both written through as given. A receiver that enforces the VR may reject the attribute that records the de-identification. The value, its length, how many Values are over and which of them came from where are all withheld from this message.",
12051
+ // Once per run, and no value, no count and no VR: the kept Items are the
12052
+ // file's own bytes, and how many there were is a count over input. The tags in
12053
+ // the text are constants of this code. It is the (0012,0064) sibling of
12054
+ // DICOM_DEIDENT_METHOD_PRIOR_RETAINED and deliberately not that code widened:
12055
+ // that one's published meaning names (0012,0063).
12056
+ DICOM_DEIDENT_METHOD_CODES_PRIOR_RETAINED: "One or more Items of a De-identification Method Code Sequence (0012,0064) the source file already carried were kept, in their original order, ahead of the codes this run added, as PS3.15 E.1.1 requires. Neither that attribute nor the Code Value, Coding Scheme Designator and Code Meaning inside its Items has a Table E.1-1 row, so those bytes are in the output as the sender wrote them, under (0012,0062) = YES, and no code in them was checked against CID 7050. If your source may put identifying text there, read (0012,0064) off the de-identified dataset and decide for yourself. The Items' content and their count are withheld from this message.",
12057
+ // Once per run. No value, no length AND NO VR, for the reason
12058
+ // DICOM_DEIDENT_METHOD_NOT_LO states: the VR is two bytes read from the file,
12059
+ // and a fabricated header makes them document content. The text names both
12060
+ // unreadable shapes so that which one fired is not disclosed by the wording.
12061
+ DICOM_DEIDENT_METHOD_CODES_PRIOR_REPLACED: "The De-identification Method Code Sequence (0012,0064) the source file carried was not a Sequence of Items this run could read (it was not encoded as SQ, or its Items were not parsed), so there were no Items to add this run's codes to (PS3.15 E.1.1) and the attribute was replaced with this run's codes alone. The replaced bytes are not in the output; if you need them, read (0012,0064) off the source dataset before de-identifying. Their content and their VR are both withheld from this message.",
12334
12062
  // BOTH of the disagreeing length fields are deliberately absent, and the
12335
12063
  // second one is the eighth instance of `DICOM-DIAGNOSTIC-PHI-RESIDUALS`: the
12336
12064
  // remaining-bytes count this string used to carry was the enclosing sequence's
@@ -12343,10 +12071,82 @@ var WARNING_MESSAGES = Object.freeze({
12343
12071
  // over. `{n2}` stays - it is the product this parser computed from the image
12344
12072
  // description attributes, not a number it read. The tag is a constant.
12345
12073
  DICOM_PIXEL_DATA_LENGTH_MISMATCH: "(7FE0,0010) PixelData declared length does not match the computed {n2} bytes. The declared length is withheld; the byte offset identifies the element.",
12074
+ // No slot at all. The fragments are the sender's encoded pixels, their lengths
12075
+ // are 32-bit wire reads, and how many were read is a count over input, so none
12076
+ // of the three has a place here. The tags are constants of this code, and the
12077
+ // byte offset is the Pixel Data element's own header, which this parser
12078
+ // counted. See `pixelDataFragmentsNotDelimited`.
12079
+ DICOM_PIXEL_DATA_FRAGMENTS_NOT_DELIMITED: "Encapsulated Pixel Data (7FE0,0010) reaches the end of the bytes being read without the Sequence Delimitation Item (FFFE,E0DD) PS3.5 2026c A.4 requires after its last fragment, so the fragments read from it may not be all the sender wrote. No fragment byte, length or count is reproduced here; the byte offset locates the Pixel Data element.",
12346
12080
  DICOM_IMPLICIT_VR_FOR_PRIVATE_TAG_WITHOUT_VR: "A private element under Implicit VR LE has no VR override; falling back to UN. Its tag is withheld; the byte offset identifies the element.",
12347
12081
  DICOM_PRIVATE_CREATOR_UNKNOWN: "A private element has a Private Creator the active profile's private dictionary does not name; falling back to UN. The creator string is not reproduced here - read the (gggg,00EE) element if you need it. Its tag is withheld; the byte offset identifies the element.",
12348
12082
  DICOM_BURNED_IN_ANNOTATION_NOT_REMOVED: "Pixel Data is present and Burned In Annotation is not 'NO'; this metadata-only de-identifier cannot inspect or clean pixels. Recognizable text may remain burned into the image.",
12083
+ // No tag, no count and no value, and none of the three is caution. This code is
12084
+ // raised ONCE PER RUN rather than once per element, so there is no element to
12085
+ // name and no attacker-chosen multiplier on the string: the tags are on
12086
+ // report.fileMetaElementsDropped, where a caller can read them beside the
12087
+ // total. It fires on a perfectly CONFORMANT file - a Sending AE Title is a
12088
+ // legal (0002,xxxx) element - which is why the tags are not here: the
12089
+ // withholding must not depend on the input being malformed.
12090
+ DICOM_DEIDENT_FILE_META_REPLACED: "The File Meta Information group of the de-identified output describes this de-identifying application, not the source file (PS3.15 E.1.1). The Source Application Entity Title and the source's implementation identity are gone, and every (0002,xxxx) element this library does not model was dropped rather than re-emitted, so the byte-for-byte File Meta round trip does NOT hold for this output. See report.fileMetaElementsDropped for what went and how many.",
12091
+ // Once per run, for the same reason and with the same consequence: no tag, no
12092
+ // count, no context path. report.group0004Removals names the elements it could
12093
+ // fit and report.group0004RemovalCount is the complete total.
12094
+ DICOM_DEIDENT_GROUP_0004_REMOVED: "Data Elements with a Group Number of 0004 were removed from this object, as PS3.15 E.1.1 requires of any SOP Instance or DICOM File other than a DICOMDIR File. Their tags and count are withheld from this message; see report.group0004Removals and report.group0004RemovalCount.",
12095
+ // 🩺 Once per run, on the option set alone, and NOT on Dataset.warnings. The
12096
+ // trigger is a choice the caller made rather than anything in the file, so
12097
+ // there is no element to name, no count and no context path; every token below
12098
+ // is a clause reference or a published option name. It states the half of
12099
+ // PS3.15 E.3.6 this library does not perform, which is the half a recipient
12100
+ // reading MODIFIED would otherwise assume was performed.
12101
+ DICOM_DEIDENT_DATES_NOT_TRANSFORMED: "The Retain Longitudinal Temporal Information With Modified Dates Option was active, so this run resolved Table E.1-1's modified-dates column and wrote (0028,0303) = MODIFIED. It did NOT modify any date or time value: PS3.15 E.3.6 also requires the dates themselves to be modified and the manner of modification to be described in a Conformance Statement, and this library performs no date transformation and states no Conformance Statement. The MODIFIED declaration is true only if you transformed the dates yourself; if you did not, the output makes a claim nobody performed.",
12102
+ // Once per run. The SOP Class UID that selected this branch is a constant of
12103
+ // the code (it is the one value that reaches it), so it is written out; nothing
12104
+ // else about the file is.
12105
+ DICOM_DEIDENT_DICOMDIR_FILE_SET_NOT_DISCHARGED: "This object declares Media Storage SOP Class UID 1.2.840.10008.1.3.10 (Media Storage Directory Storage), so PS3.15 E.1.1's carve-out applies and its (0004,xxxx) Data Elements were NOT removed. Two File-set clauses of that bullet were NOT discharged by this run: no DICOMDIR was created from the de-identified DICOM Files it references, and no non-de-identified DICOMDIR File was removed from the File-set. This library has no view of a File-set, so both are yours to do. Do not treat this output as a File-set-conformant DICOMDIR.",
12106
+ // No slot. The four codes below fire on a DICOMDIR's offset attributes, whose
12107
+ // values are raw 32-bit wire reads, and on records whose keys are the
12108
+ // sender's own, so neither an offset, a record index nor a key has a place
12109
+ // here. `position.byteOffset` locates the attribute (a root one at its
12110
+ // element header, a record's at that record's Item tag) and
12111
+ // `position.contextPath` names which attribute of which record; both are
12112
+ // structure this parser counted.
12113
+ DICOM_DIRECTORY_OFFSET_UNRESOLVED: "A DICOMDIR offset attribute names no Item of the Directory Record Sequence (0004,1220): it is not the file offset of any Directory Record's (FFFE,E000) Item tag (PS3.3 F.3.2.2), so no record was resolved from it and the tree does not follow it. serializeDicom refuses to write it. The offset's value is withheld; the byte offset and context path locate the attribute.",
12114
+ DICOM_DIRECTORY_OFFSET_MALFORMED: "A DICOMDIR offset attribute's Value Length is not 4, so its value is not one 32-bit unsigned integer (UL, VM 1) and no record was resolved from it. serializeDicom refuses to write it. The value and its length are withheld; the byte offset and context path locate the attribute.",
12115
+ DICOM_DIRECTORY_RECORD_REVISITED: "Following a DICOMDIR offset attribute would reach a Directory Record already reached in this walk, so that record is in the tree once and the walk did not follow the offset again. The offset's value is withheld; the byte offset and context path locate the attribute.",
12116
+ DICOM_DIRECTORY_OFFSET_DEFLATED: "This DICOMDIR is encoded in Deflated Explicit VR Little Endian and carries a non-zero Directory Record offset. A byte position inside a deflated stream names no Item a reader can seek to, so no record was resolved from any offset; PS3.10 8.6 requires a DICOMDIR File to use Explicit VR Little Endian. serializeDicom refuses to write it. The byte offset is where the deflated stream begins.",
12349
12117
  DICOM_DEIDENT_EMBEDDED_ATTRIBUTE_REMOVED: "Element ({tag}) {vr} was kept by the action table, but its value ends with {n} whole Data Element(s) - an over-declared Value Length swallowed what followed it. Emptied rather than kept, because the action table cannot see an attribute encoded inside a value. report.embeddedAttributes names the ones this run acts on that also have a literal Table E.1-1 row, which may be none of them.",
12118
+ // Deliberately short, for the reason the two codes below it are short: one is
12119
+ // raised per removed private element and the element count is chosen by the
12120
+ // input.
12121
+ //
12122
+ // 🩺 NO BYTE COUNT, AND THAT IS NOT CAUTION - IT IS THE SAME BOUND TAKEN
12123
+ // OUT OF THE TWO CODES BELOW. `Element.rawBytes.length` EQUALS the Value
12124
+ // Length read off the element header, so on a header an under-declared length
12125
+ // upstream composed out of somebody's value the decimal is four document
12126
+ // bytes. The tag survives because `renderTag` is a membership test against
12127
+ // PS3.6's registry, and a private tag - which every element raising this code
12128
+ // carries - renders `<withheld>` there. See `privateCarrierNotAuditable`.
12129
+ //
12130
+ // 🛑 IT SAID "KEPT" UNTIL THE RUN STOPPED KEEPING THE VALUE, AND THE CODE
12131
+ // NAME IS UNCHANGED WHILE THE MEANING IS NOT. Through `0.0.19` this reported a
12132
+ // value the run SHIPPED unexamined; it now reports one the run REMOVED
12133
+ // unexamined. A consumer narrowing on the code keeps compiling and has to
12134
+ // re-read what it means - which is why the wording states the outcome
12135
+ // outright and why the published code SET did not move.
12136
+ DICOM_DEIDENT_PRIVATE_CARRIER_NOT_AUDITABLE: "Element ({tag}) is a Private Attribute a profile vouched for under RetainSafePrivate whose value this run did not enumerate, so any Data Set encoded inside it could not be audited (PS3.15 E.3.10 vouches for the Attribute, not for a Data Set nested in its value; E.1.1). REMOVED rather than retained. The byte count is withheld; see report.unenumerablePrivateRemovals.",
12137
+ // Deliberately short, and one per Item: the Item count is chosen by the
12138
+ // input.
12139
+ //
12140
+ // 🩺 NOT ONE TOKEN OF THE ITEM IS ECHOED, AND EVERY FIELD THAT WOULD BE IS A
12141
+ // DOCUMENT VALUE. The Item's own values are what failed to resolve: a Private
12142
+ // Creator Reference (0008,0302) is an LO the sender wrote, a Private Group
12143
+ // Reference (0008,0301) is a group number read off the wire, and a Block
12144
+ // Identifying Information Status (0008,0303) that reaches this code is by
12145
+ // construction outside the closed set PS3.3 C.12.1 enumerates, so no
12146
+ // membership test can stand behind it. The two tags in the text are constants
12147
+ // of this code rather than substitutions. `position.byteOffset` locates the
12148
+ // (0008,0300) element and is a position this parser counted.
12149
+ DICOM_DEIDENT_PRIVATE_DECLARATION_NOT_RESOLVED: "An Item of Private Data Element Characteristics Sequence (0008,0300) does not resolve to a block of Private Data Elements reserved in this Data Set, so nothing was retained on account of it (PS3.15 E.3.10; PS3.3 C.12.1). Its declared values are withheld: they are the sender's own and are what failed to resolve.",
12350
12150
  // Deliberately short. One of these is raised per un-auditable element, so a
12351
12151
  // long message is multiplied by an element count the input controls; the
12352
12152
  // reasoning belongs in the docs, not in a string repeated thousands of times.
@@ -12379,6 +12179,16 @@ var WARNING_MESSAGES = Object.freeze({
12379
12179
  // The byte offset locates the element instead, and is a position this parser
12380
12180
  // counted rather than anything the document said.
12381
12181
  DICOM_DEIDENT_UNDEFINED_VR_NOT_AUDITABLE: "An element at byte offset {n2} carries an on-wire VR that is not one of the 34 PS3.5 6.2 defines, so its value bytes are not a Value Field this library decoded; emptied (PS3.15 E.1.1). Its tag, VR and byte count are withheld: an earlier under-declared length can make them fragments of some element's value. See report.undefinedVrElements.",
12182
+ // 🩺 Once per run, and NO TAG, NO VR, NO COUNT AND NO CONTEXT PATH, for the
12183
+ // reason DICOM_DEIDENT_UNDEFINED_VR_NOT_AUDITABLE withholds them: the trigger is
12184
+ // "no PS3.6 row carries this tag", which is exactly what four bytes read out of
12185
+ // some element's value look like, so the tag may BE document content. There is
12186
+ // no membership table for a renderer to fall back on here either, because the
12187
+ // condition is the absence of one. The records are on
12188
+ // report.unregisteredElementRemovals (capped, byte offsets only) and the true
12189
+ // total is on report.unregisteredElementRemovalCount. It fires on a CONFORMANT
12190
+ // newer-edition file too, which is the over-redaction the message states.
12191
+ DICOM_DEIDENT_UNREGISTERED_ELEMENT_REMOVED: "Non-private Data Elements whose tags this build's PS3.6 2026d registry does not carry, and which Table E.1-1 does not list, were removed at every depth: a Standard Attribute newer than this build, or one its sender invented, can carry identifying information no Table E.1-1 row names (PS3.15 E.1.1). A conformant attribute from a later edition is removed too. Their tags, VRs and count are withheld from this message; see report.unregisteredElementRemovals and report.unregisteredElementRemovalCount.",
12382
12192
  DICOM_BOM_IN_TEXT_VR: "Element ({tag}) {vr} value begins with a UTF-8 BOM; stripped on decode.",
12383
12193
  DICOM_TRAILING_NULL_IN_TEXT_VR: "Element ({tag}) {vr} value has a trailing NULL pad where SPACE is expected; trimmed.",
12384
12194
  DICOM_UI_TRAILING_SPACE: "Element ({tag}) UI value is SPACE-padded; UI requires NULL padding (PS3.5 \xA76.2). Trimmed.",
@@ -12387,119 +12197,1060 @@ var WARNING_MESSAGES = Object.freeze({
12387
12197
  DICOM_DA_LEGACY_FORMAT: "Element ({tag}) DA value is not in canonical YYYYMMDD form; decoded best-effort, raw preserved.",
12388
12198
  DICOM_DT_NONSTANDARD_OFFSET: "Element ({tag}) DT value has a non-standard UTC offset; decoded best-effort, raw preserved.",
12389
12199
  DICOM_UNSUPPORTED_CHARSET: "(0008,0005) Specific Character Set value {n} names a defined term this build does not support; decoding text as UTF-8 best-effort. The term is not reproduced here - read the element if you need it.",
12390
- DICOM_CHARSET_AMBIGUOUS_SEPARATOR: "(0008,0005) Specific Character Set value {n} is ambiguous under the active code extensions; decoding text as UTF-8 best-effort."
12200
+ DICOM_CHARSET_AMBIGUOUS_SEPARATOR: "(0008,0005) Specific Character Set value {n} is ambiguous under the active code extensions; decoding text as UTF-8 best-effort.",
12201
+ // The three ISO 2022 code-extension codes take a tag and a VR and nothing
12202
+ // else. The escape sequence, the set it names and the characters around it
12203
+ // are all value bytes, so none of them has a slot here.
12204
+ DICOM_CHARSET_ESCAPE_UNDECLARED: "Element ({tag}) {vr} value switches character set with an ISO 2022 escape sequence for a set that (0008,0005) Specific Character Set does not declare; decoded in the set the escape sequence names.",
12205
+ DICOM_CHARSET_BYTES_UNDECODABLE: "Element ({tag}) {vr} value holds bytes no designated character set decodes (an unrecognized escape sequence, a byte with no set designated for it, or a code its set does not define); they read as U+FFFD in the decoded value. Raw bytes preserved.",
12206
+ DICOM_CHARSET_EXTENSION_NOT_RESET: "Element ({tag}) {vr} value ends a line, a value or a name component without switching back to the (0008,0005) Value 1 character set (PS3.5 6.1.2.5.3); decoded as written, and what follows decodes from Value 1."
12391
12207
  });
12392
- function build2(code, position, tokens = {}) {
12208
+ function build(code, position, tokens = {}) {
12393
12209
  const message = WARNING_MESSAGES[code].replace("{tag}", renderTag(tokens.tag)).replace("{vr2}", renderVr(tokens.vr2)).replace("{vr}", renderVr(tokens.vr)).replace("{n2}", String(tokens.n2 ?? 0)).replace("{n}", String(tokens.n ?? 0));
12394
12210
  return { code, message, position };
12395
12211
  }
12396
12212
  function missingPreamble(position) {
12397
- return build2(WARNING_CODES.DICOM_MISSING_PREAMBLE, position);
12213
+ return build(WARNING_CODES.DICOM_MISSING_PREAMBLE, position);
12398
12214
  }
12399
12215
  function fileMetaGroupLengthMissing(position) {
12400
- return build2(WARNING_CODES.DICOM_FILE_META_GROUP_LENGTH_MISSING, position);
12216
+ return build(WARNING_CODES.DICOM_FILE_META_GROUP_LENGTH_MISSING, position);
12401
12217
  }
12402
12218
  function fileMetaGroupLengthMismatch(position, declared, actual) {
12403
- return build2(WARNING_CODES.DICOM_FILE_META_GROUP_LENGTH_MISMATCH, position, {
12219
+ return build(WARNING_CODES.DICOM_FILE_META_GROUP_LENGTH_MISMATCH, position, {
12404
12220
  n: declared,
12405
12221
  n2: actual
12406
12222
  });
12407
12223
  }
12408
12224
  function undefinedLengthInExplicitVR(position, tag) {
12409
- return build2(WARNING_CODES.DICOM_UNDEFINED_LENGTH_IN_EXPLICIT_VR, position, { tag });
12225
+ return build(WARNING_CODES.DICOM_UNDEFINED_LENGTH_IN_EXPLICIT_VR, position, { tag });
12410
12226
  }
12411
12227
  function oddLengthValuePadded(position, tag) {
12412
- return build2(WARNING_CODES.DICOM_ODD_LENGTH_VALUE_PADDED, position, { tag });
12228
+ return build(WARNING_CODES.DICOM_ODD_LENGTH_VALUE_PADDED, position, { tag });
12413
12229
  }
12414
12230
  function vrMismatch(position, tag, dictVR, fileVR) {
12415
- return build2(WARNING_CODES.DICOM_VR_MISMATCH, position, { tag, vr: dictVR, vr2: fileVR });
12231
+ return build(WARNING_CODES.DICOM_VR_MISMATCH, position, { tag, vr: dictVR, vr2: fileVR });
12416
12232
  }
12417
12233
  function privateTagNoCreator(position) {
12418
- return build2(WARNING_CODES.DICOM_PRIVATE_TAG_NO_CREATOR, position);
12234
+ return build(WARNING_CODES.DICOM_PRIVATE_TAG_NO_CREATOR, position);
12419
12235
  }
12420
12236
  function groupLengthInDataset(position) {
12421
- return build2(WARNING_CODES.DICOM_GROUP_LENGTH_IN_DATASET, position);
12237
+ return build(WARNING_CODES.DICOM_GROUP_LENGTH_IN_DATASET, position);
12422
12238
  }
12423
12239
  function nonzeroReservedBytes(position) {
12424
- return build2(WARNING_CODES.DICOM_NONZERO_RESERVED_BYTES, position);
12240
+ return build(WARNING_CODES.DICOM_NONZERO_RESERVED_BYTES, position);
12425
12241
  }
12426
12242
  function unParsedAsSQ(position, tag) {
12427
- return build2(WARNING_CODES.DICOM_UN_PARSED_AS_SQ, position, { tag });
12243
+ return build(WARNING_CODES.DICOM_UN_PARSED_AS_SQ, position, { tag });
12428
12244
  }
12429
12245
  function sqNotDescended(position, tag) {
12430
- return build2(WARNING_CODES.DICOM_SQ_NOT_DESCENDED, position, { tag });
12246
+ return build(WARNING_CODES.DICOM_SQ_NOT_DESCENDED, position, { tag });
12431
12247
  }
12432
12248
  function itemCrossesSequenceEnd(position, tag) {
12433
- return build2(WARNING_CODES.DICOM_ITEM_CROSSES_SEQUENCE_END, position, { tag });
12249
+ return build(WARNING_CODES.DICOM_ITEM_CROSSES_SEQUENCE_END, position, { tag });
12434
12250
  }
12435
12251
  function emptyItemInSequence(position, tag) {
12436
- return build2(WARNING_CODES.DICOM_EMPTY_ITEM_IN_SEQUENCE, position, { tag });
12252
+ return build(WARNING_CODES.DICOM_EMPTY_ITEM_IN_SEQUENCE, position, { tag });
12253
+ }
12254
+ function pixelDataFragmentsNotDelimited(position) {
12255
+ return build(WARNING_CODES.DICOM_PIXEL_DATA_FRAGMENTS_NOT_DELIMITED, position);
12437
12256
  }
12438
12257
  function duplicateTagInDataSet(position) {
12439
- return build2(WARNING_CODES.DICOM_DUPLICATE_TAG_IN_DATA_SET, position);
12258
+ return build(WARNING_CODES.DICOM_DUPLICATE_TAG_IN_DATA_SET, position);
12440
12259
  }
12441
12260
  function duplicateFileMetaElement(position) {
12442
- return build2(WARNING_CODES.DICOM_DUPLICATE_FILE_META_ELEMENT, position);
12261
+ return build(WARNING_CODES.DICOM_DUPLICATE_FILE_META_ELEMENT, position);
12443
12262
  }
12444
12263
  function implicitVRForPrivateTagWithoutVR(position) {
12445
- return build2(WARNING_CODES.DICOM_IMPLICIT_VR_FOR_PRIVATE_TAG_WITHOUT_VR, position);
12264
+ return build(WARNING_CODES.DICOM_IMPLICIT_VR_FOR_PRIVATE_TAG_WITHOUT_VR, position);
12446
12265
  }
12447
12266
  function privateCreatorUnknown(position) {
12448
- return build2(WARNING_CODES.DICOM_PRIVATE_CREATOR_UNKNOWN, position);
12267
+ return build(WARNING_CODES.DICOM_PRIVATE_CREATOR_UNKNOWN, position);
12449
12268
  }
12450
12269
  function burnedInAnnotationNotRemoved(position) {
12451
- return build2(WARNING_CODES.DICOM_BURNED_IN_ANNOTATION_NOT_REMOVED, position);
12270
+ return build(WARNING_CODES.DICOM_BURNED_IN_ANNOTATION_NOT_REMOVED, position);
12271
+ }
12272
+ function fileMetaReplaced(position) {
12273
+ return build(WARNING_CODES.DICOM_DEIDENT_FILE_META_REPLACED, position);
12274
+ }
12275
+ function group0004Removed(position) {
12276
+ return build(WARNING_CODES.DICOM_DEIDENT_GROUP_0004_REMOVED, position);
12277
+ }
12278
+ function dicomdirFileSetNotDischarged(position) {
12279
+ return build(WARNING_CODES.DICOM_DEIDENT_DICOMDIR_FILE_SET_NOT_DISCHARGED, position);
12280
+ }
12281
+ function directoryOffsetUnresolved(position) {
12282
+ return build(WARNING_CODES.DICOM_DIRECTORY_OFFSET_UNRESOLVED, position);
12283
+ }
12284
+ function directoryOffsetMalformed(position) {
12285
+ return build(WARNING_CODES.DICOM_DIRECTORY_OFFSET_MALFORMED, position);
12286
+ }
12287
+ function directoryRecordRevisited(position) {
12288
+ return build(WARNING_CODES.DICOM_DIRECTORY_RECORD_REVISITED, position);
12289
+ }
12290
+ function directoryOffsetDeflated(position) {
12291
+ return build(WARNING_CODES.DICOM_DIRECTORY_OFFSET_DEFLATED, position);
12292
+ }
12293
+ function datesNotTransformed(position) {
12294
+ return build(WARNING_CODES.DICOM_DEIDENT_DATES_NOT_TRANSFORMED, position);
12452
12295
  }
12453
12296
  function deidentMethodNotAdded(position) {
12454
- return build2(WARNING_CODES.DICOM_DEIDENT_METHOD_NOT_ADDED, position);
12297
+ return build(WARNING_CODES.DICOM_DEIDENT_METHOD_NOT_ADDED, position);
12455
12298
  }
12456
12299
  function deidentMethodNotLo(position) {
12457
- return build2(WARNING_CODES.DICOM_DEIDENT_METHOD_NOT_LO, position);
12300
+ return build(WARNING_CODES.DICOM_DEIDENT_METHOD_NOT_LO, position);
12458
12301
  }
12459
12302
  function deidentMethodPriorRetained(position) {
12460
- return build2(WARNING_CODES.DICOM_DEIDENT_METHOD_PRIOR_RETAINED, position);
12303
+ return build(WARNING_CODES.DICOM_DEIDENT_METHOD_PRIOR_RETAINED, position);
12461
12304
  }
12462
12305
  function deidentMethodValueOverLength(position) {
12463
- return build2(WARNING_CODES.DICOM_DEIDENT_METHOD_VALUE_OVER_LENGTH, position);
12306
+ return build(WARNING_CODES.DICOM_DEIDENT_METHOD_VALUE_OVER_LENGTH, position);
12307
+ }
12308
+ function deidentMethodCodesPriorRetained(position) {
12309
+ return build(WARNING_CODES.DICOM_DEIDENT_METHOD_CODES_PRIOR_RETAINED, position);
12310
+ }
12311
+ function deidentMethodCodesPriorReplaced(position) {
12312
+ return build(WARNING_CODES.DICOM_DEIDENT_METHOD_CODES_PRIOR_REPLACED, position);
12464
12313
  }
12465
12314
  function embeddedAttributeRemoved(position, tag, vr, count) {
12466
- return build2(WARNING_CODES.DICOM_DEIDENT_EMBEDDED_ATTRIBUTE_REMOVED, position, {
12315
+ return build(WARNING_CODES.DICOM_DEIDENT_EMBEDDED_ATTRIBUTE_REMOVED, position, {
12467
12316
  tag,
12468
12317
  vr,
12469
12318
  n: count
12470
12319
  });
12471
12320
  }
12321
+ function privateCarrierNotAuditable(position, tag) {
12322
+ return build(WARNING_CODES.DICOM_DEIDENT_PRIVATE_CARRIER_NOT_AUDITABLE, position, { tag });
12323
+ }
12324
+ function privateDeclarationNotResolved(position) {
12325
+ return build(WARNING_CODES.DICOM_DEIDENT_PRIVATE_DECLARATION_NOT_RESOLVED, position);
12326
+ }
12472
12327
  function sequenceNotAuditable(position, tag) {
12473
- return build2(WARNING_CODES.DICOM_DEIDENT_SEQUENCE_NOT_AUDITABLE, position, { tag });
12328
+ return build(WARNING_CODES.DICOM_DEIDENT_SEQUENCE_NOT_AUDITABLE, position, { tag });
12474
12329
  }
12475
12330
  function undefinedVrNotAuditable(position) {
12476
- return build2(WARNING_CODES.DICOM_DEIDENT_UNDEFINED_VR_NOT_AUDITABLE, position, {
12331
+ return build(WARNING_CODES.DICOM_DEIDENT_UNDEFINED_VR_NOT_AUDITABLE, position, {
12477
12332
  n2: position.byteOffset
12478
12333
  });
12479
12334
  }
12335
+ function unregisteredElementRemoved(position) {
12336
+ return build(WARNING_CODES.DICOM_DEIDENT_UNREGISTERED_ELEMENT_REMOVED, position);
12337
+ }
12480
12338
  function bomInTextVR(position, tag, vr) {
12481
- return build2(WARNING_CODES.DICOM_BOM_IN_TEXT_VR, position, { tag, vr });
12339
+ return build(WARNING_CODES.DICOM_BOM_IN_TEXT_VR, position, { tag, vr });
12482
12340
  }
12483
12341
  function trailingNullInTextVR(position, tag, vr) {
12484
- return build2(WARNING_CODES.DICOM_TRAILING_NULL_IN_TEXT_VR, position, { tag, vr });
12342
+ return build(WARNING_CODES.DICOM_TRAILING_NULL_IN_TEXT_VR, position, { tag, vr });
12485
12343
  }
12486
12344
  function uiTrailingSpace(position, tag) {
12487
- return build2(WARNING_CODES.DICOM_UI_TRAILING_SPACE, position, { tag });
12345
+ return build(WARNING_CODES.DICOM_UI_TRAILING_SPACE, position, { tag });
12488
12346
  }
12489
12347
  function nonAsciiInAsciiVR(position, tag, vr) {
12490
- return build2(WARNING_CODES.DICOM_NON_ASCII_IN_ASCII_VR, position, { tag, vr });
12348
+ return build(WARNING_CODES.DICOM_NON_ASCII_IN_ASCII_VR, position, { tag, vr });
12349
+ }
12350
+ function isNonintegerValue(position, tag) {
12351
+ return build(WARNING_CODES.DICOM_IS_NONINTEGER_VALUE, position, { tag });
12352
+ }
12353
+ function daLegacyFormat(position, tag) {
12354
+ return build(WARNING_CODES.DICOM_DA_LEGACY_FORMAT, position, { tag });
12355
+ }
12356
+ function dtNonstandardOffset(position, tag) {
12357
+ return build(WARNING_CODES.DICOM_DT_NONSTANDARD_OFFSET, position, { tag });
12358
+ }
12359
+ function unsupportedCharset(position, valueIndex) {
12360
+ return build(WARNING_CODES.DICOM_UNSUPPORTED_CHARSET, position, { n: valueIndex });
12361
+ }
12362
+ function charsetEscapeUndeclared(position, tag, vr) {
12363
+ return build(WARNING_CODES.DICOM_CHARSET_ESCAPE_UNDECLARED, position, { tag, vr });
12364
+ }
12365
+ function charsetBytesUndecodable(position, tag, vr) {
12366
+ return build(WARNING_CODES.DICOM_CHARSET_BYTES_UNDECODABLE, position, { tag, vr });
12367
+ }
12368
+ function charsetExtensionNotReset(position, tag, vr) {
12369
+ return build(WARNING_CODES.DICOM_CHARSET_EXTENSION_NOT_RESET, position, { tag, vr });
12370
+ }
12371
+
12372
+ // src/parser/directory.ts
12373
+ function emitDirectoryFindings(source, frame, emit) {
12374
+ const analysis = analyzeDirectory(source);
12375
+ if (analysis === void 0) return;
12376
+ const deflated = isDeflated(source.fileMeta);
12377
+ const positionOf = (finding) => {
12378
+ if (deflated) return { byteOffset: frame.fileMetaEnd };
12379
+ if (finding.item === void 0) return { byteOffset: finding.element.byteOffset };
12380
+ const byteOffset = (finding.item.fileOffset ?? frame.origin) - frame.origin;
12381
+ const contextPath = [
12382
+ DIRECTORY_TAGS.RECORD_SEQUENCE,
12383
+ String(finding.item.index),
12384
+ finding.element.tag
12385
+ ];
12386
+ return { byteOffset, contextPath };
12387
+ };
12388
+ for (const finding of analysis.findings) {
12389
+ const position = positionOf(finding);
12390
+ switch (finding.kind) {
12391
+ case "unresolved":
12392
+ emit(directoryOffsetUnresolved(position));
12393
+ break;
12394
+ case "malformed":
12395
+ emit(directoryOffsetMalformed(position));
12396
+ break;
12397
+ case "revisited":
12398
+ emit(directoryRecordRevisited(position));
12399
+ break;
12400
+ case "deflated":
12401
+ emit(directoryOffsetDeflated(position));
12402
+ break;
12403
+ }
12404
+ }
12405
+ }
12406
+
12407
+ // src/parser/errors.ts
12408
+ var FATAL_CODES = {
12409
+ NOT_DICOM_PART_10: "NOT_DICOM_PART_10",
12410
+ INVALID_FILE_META: "INVALID_FILE_META",
12411
+ UNSUPPORTED_TRANSFER_SYNTAX: "UNSUPPORTED_TRANSFER_SYNTAX",
12412
+ EMPTY_INPUT: "EMPTY_INPUT"
12413
+ };
12414
+ var OFFSET_FRAMES = {
12415
+ /**
12416
+ * Byte 0 is byte 0 of the buffer handed to `parseDicom`. The only frame in
12417
+ * which indexing the caller's own input by `byteOffset` is meaningful.
12418
+ */
12419
+ INPUT: "input",
12420
+ /**
12421
+ * Byte 0 is byte 0 of the inflated Data Set of a Deflated Explicit VR LE
12422
+ * object (`1.2.840.10008.1.2.1.99`). The compressed input holds no such
12423
+ * byte, so the offset does not index it at any scale.
12424
+ */
12425
+ INFLATED_DATASET: "inflated-dataset",
12426
+ /**
12427
+ * Byte 0 is byte 0 of a slice this parser cut from inside a Value Field: a
12428
+ * defined-length Sequence Item's value, or an `SQ`/`UN` value handed to a
12429
+ * descent. **Where that slice begins is deliberately not published** - see
12430
+ * this table's own note.
12431
+ */
12432
+ VALUE_SLICE: "value-slice"
12433
+ };
12434
+ function valueSliceFrame(enclosing, slice, start) {
12435
+ return enclosing.origin === void 0 ? { buffer: slice, name: OFFSET_FRAMES.VALUE_SLICE } : { buffer: slice, name: OFFSET_FRAMES.VALUE_SLICE, origin: enclosing.origin + start };
12436
+ }
12437
+ function fileOffsetIn(frame, offset) {
12438
+ return frame.origin === void 0 ? void 0 : frame.origin + offset;
12439
+ }
12440
+ var DicomParseError = class extends Error {
12441
+ code;
12442
+ byteOffset;
12443
+ /**
12444
+ * The coordinate system {@link DicomParseError.byteOffset} is counted in.
12445
+ * See {@link OFFSET_FRAMES}.
12446
+ */
12447
+ offsetFrame;
12448
+ snippet;
12449
+ contextPath;
12450
+ /**
12451
+ * Construct a new `DicomParseError`. All fields except `contextPath` are
12452
+ * required so every thrower populates positional context - and
12453
+ * `offsetFrame` is required for the same reason `byteOffset` is, because an
12454
+ * offset whose frame is optional is an offset whose frame is usually
12455
+ * missing.
12456
+ *
12457
+ * @internal
12458
+ */
12459
+ constructor(code, message, byteOffset, offsetFrame, snippet, contextPath) {
12460
+ const formatted = `[${code}] ${message} (offset=${String(byteOffset)} frame=${offsetFrame})` + (contextPath !== void 0 && contextPath.length > 0 ? ` \u2026 in ${contextPath.join("/")}` : "");
12461
+ super(formatted);
12462
+ this.name = "DicomParseError";
12463
+ this.code = code;
12464
+ this.byteOffset = byteOffset;
12465
+ this.offsetFrame = offsetFrame;
12466
+ this.snippet = snippet;
12467
+ this.contextPath = contextPath;
12468
+ }
12469
+ };
12470
+ function buildSnippet(buffer, offset) {
12471
+ if (offset < 0 || offset >= buffer.length) return "";
12472
+ const end = Math.min(offset + 16, buffer.length);
12473
+ const slice = buffer.subarray(offset, end);
12474
+ const parts = [];
12475
+ for (const b of slice) {
12476
+ parts.push(b.toString(16).padStart(2, "0"));
12477
+ }
12478
+ return parts.join(" ");
12479
+ }
12480
+
12481
+ // src/parser/emit.ts
12482
+ function makeEmitter(ctx) {
12483
+ const escalate = (w) => {
12484
+ throw new DicomParseError(
12485
+ // The cast is deliberate: the WarningCode union does not overlap FatalCode at the
12486
+ // type level, but at runtime the strict-thrown error carries the
12487
+ // warning code so consumers can narrow on err.code uniformly.
12488
+ w.code,
12489
+ w.message,
12490
+ w.position.byteOffset,
12491
+ // Both come off the SAME frame object, so an escalation cannot name one
12492
+ // frame and cut its bytes from another. `DicomParseWarning.position`
12493
+ // itself carries no frame - that is `PRE-EXISTING` and stated on
12494
+ // `DicomPosition`, not closed here.
12495
+ ctx.frame.name,
12496
+ buildSnippet(ctx.frame.buffer, w.position.byteOffset),
12497
+ w.position.contextPath
12498
+ );
12499
+ };
12500
+ return (w) => {
12501
+ if (ctx.strict) escalate(w);
12502
+ if (ctx.profile !== void 0) {
12503
+ if (ctx.profile.suppressions.has(w.code)) return;
12504
+ if (ctx.profile.escalations.has(w.code)) escalate(w);
12505
+ }
12506
+ ctx.warnings.push(w);
12507
+ if (ctx.onWarning !== void 0) {
12508
+ try {
12509
+ ctx.onWarning(w);
12510
+ } catch {
12511
+ }
12512
+ }
12513
+ };
12514
+ }
12515
+
12516
+ // src/dictionary/generated/encapsulated-transfer-syntaxes.ts
12517
+ var ENCAPSULATED_TRANSFER_SYNTAX_EDITION = "2026c";
12518
+ var ENCAPSULATED_TRANSFER_SYNTAX_UIDS = Object.freeze([
12519
+ "1.2.840.10008.1.2.1.98",
12520
+ // Encapsulated Uncompressed Explicit VR Little Endian
12521
+ "1.2.840.10008.1.2.4.100",
12522
+ // MPEG2 Main Profile / Main Level
12523
+ "1.2.840.10008.1.2.4.100.1",
12524
+ // Fragmentable MPEG2 Main Profile / Main Level
12525
+ "1.2.840.10008.1.2.4.101",
12526
+ // MPEG2 Main Profile / High Level
12527
+ "1.2.840.10008.1.2.4.101.1",
12528
+ // Fragmentable MPEG2 Main Profile / High Level
12529
+ "1.2.840.10008.1.2.4.102",
12530
+ // MPEG-4 AVC/H.264 High Profile / Level 4.1
12531
+ "1.2.840.10008.1.2.4.102.1",
12532
+ // Fragmentable MPEG-4 AVC/H.264 High Profile / Level 4.1
12533
+ "1.2.840.10008.1.2.4.103",
12534
+ // MPEG-4 AVC/H.264 BD-compatible High Profile / Level 4.1
12535
+ "1.2.840.10008.1.2.4.103.1",
12536
+ // Fragmentable MPEG-4 AVC/H.264 BD-compatible High Profile / Level 4.1
12537
+ "1.2.840.10008.1.2.4.104",
12538
+ // MPEG-4 AVC/H.264 High Profile / Level 4.2 For 2D Video
12539
+ "1.2.840.10008.1.2.4.104.1",
12540
+ // Fragmentable MPEG-4 AVC/H.264 High Profile / Level 4.2 For 2D Video
12541
+ "1.2.840.10008.1.2.4.105",
12542
+ // MPEG-4 AVC/H.264 High Profile / Level 4.2 For 3D Video
12543
+ "1.2.840.10008.1.2.4.105.1",
12544
+ // Fragmentable MPEG-4 AVC/H.264 High Profile / Level 4.2 For 3D Video
12545
+ "1.2.840.10008.1.2.4.106",
12546
+ // MPEG-4 AVC/H.264 Stereo High Profile / Level 4.2
12547
+ "1.2.840.10008.1.2.4.106.1",
12548
+ // Fragmentable MPEG-4 AVC/H.264 Stereo High Profile / Level 4.2
12549
+ "1.2.840.10008.1.2.4.107",
12550
+ // HEVC/H.265 Main Profile / Level 5.1
12551
+ "1.2.840.10008.1.2.4.108",
12552
+ // HEVC/H.265 Main 10 Profile / Level 5.1
12553
+ "1.2.840.10008.1.2.4.110",
12554
+ // JPEG XL Lossless
12555
+ "1.2.840.10008.1.2.4.111",
12556
+ // JPEG XL JPEG Recompression
12557
+ "1.2.840.10008.1.2.4.112",
12558
+ // JPEG XL
12559
+ "1.2.840.10008.1.2.4.201",
12560
+ // High-Throughput JPEG 2000 Image Compression (Lossless Only)
12561
+ "1.2.840.10008.1.2.4.202",
12562
+ // High-Throughput JPEG 2000 with RPCL Options Image Compression (Lossless Only)
12563
+ "1.2.840.10008.1.2.4.203",
12564
+ // High-Throughput JPEG 2000 Image Compression
12565
+ "1.2.840.10008.1.2.4.50",
12566
+ // JPEG Baseline (Process 1)
12567
+ "1.2.840.10008.1.2.4.51",
12568
+ // JPEG Extended (Process 2 & 4)
12569
+ "1.2.840.10008.1.2.4.57",
12570
+ // JPEG Lossless, Non-Hierarchical (Process 14)
12571
+ "1.2.840.10008.1.2.4.70",
12572
+ // JPEG Lossless, Non-Hierarchical, First-Order Prediction (Process 14 [Selection Value 1])
12573
+ "1.2.840.10008.1.2.4.80",
12574
+ // JPEG-LS Lossless Image Compression
12575
+ "1.2.840.10008.1.2.4.81",
12576
+ // JPEG-LS Lossy (Near-Lossless) Image Compression
12577
+ "1.2.840.10008.1.2.4.90",
12578
+ // JPEG 2000 Image Compression (Lossless Only)
12579
+ "1.2.840.10008.1.2.4.91",
12580
+ // JPEG 2000 Image Compression
12581
+ "1.2.840.10008.1.2.4.92",
12582
+ // JPEG 2000 Part 2 Multi-component Image Compression (Lossless Only)
12583
+ "1.2.840.10008.1.2.4.93",
12584
+ // JPEG 2000 Part 2 Multi-component Image Compression
12585
+ "1.2.840.10008.1.2.5",
12586
+ // RLE Lossless
12587
+ "1.2.840.10008.1.2.8.1"
12588
+ // Deflated Image Frame Compression
12589
+ ]);
12590
+
12591
+ // src/parser/fatals.ts
12592
+ var NATIVE_TRANSFER_SYNTAXES = Object.freeze([
12593
+ "1.2.840.10008.1.2",
12594
+ "1.2.840.10008.1.2.1",
12595
+ "1.2.840.10008.1.2.2",
12596
+ "1.2.840.10008.1.2.1.99"
12597
+ ]);
12598
+ var SUPPORTED_TRANSFER_SYNTAXES = `${NATIVE_TRANSFER_SYNTAXES.join(", ")}, every encapsulated Pixel Data Transfer Syntax PS3.5 ${ENCAPSULATED_TRANSFER_SYNTAX_EDITION} section A.4 names, and the four JPIP Referenced Transfer Syntaxes of its sections A.6, A.7, A.11 and A.12`;
12599
+ var ZLIB_CODES = Object.freeze(
12600
+ /* @__PURE__ */ new Set([
12601
+ "Z_OK",
12602
+ "Z_STREAM_END",
12603
+ "Z_NEED_DICT",
12604
+ "Z_ERRNO",
12605
+ "Z_STREAM_ERROR",
12606
+ "Z_DATA_ERROR",
12607
+ "Z_MEM_ERROR",
12608
+ "Z_BUF_ERROR",
12609
+ "Z_VERSION_ERROR"
12610
+ ])
12611
+ );
12612
+ var FATAL_MESSAGES = Object.freeze({
12613
+ EMPTY_INPUT: {
12614
+ code: FATAL_CODES.EMPTY_INPUT,
12615
+ message: "Input is empty."
12616
+ },
12617
+ EMPTY_INPUT_AFTER_NORMALIZATION: {
12618
+ code: FATAL_CODES.EMPTY_INPUT,
12619
+ message: "Input is empty after normalization."
12620
+ },
12621
+ NOT_DICOM_PART_10_REQUIRED: {
12622
+ code: FATAL_CODES.NOT_DICOM_PART_10,
12623
+ message: "Missing DICM magic at offset 128 (stripPreamble='require')."
12624
+ },
12625
+ NOT_DICOM_PART_10: {
12626
+ code: FATAL_CODES.NOT_DICOM_PART_10,
12627
+ message: "Input is not a DICOM Part 10 file (no DICM magic at offset 128 and no recognizable File Meta group at offset 0)."
12628
+ },
12629
+ // `{ts}` is NOT the UID. It is the PS3.6 registry's own name for the UID, or a
12630
+ // fixed phrase when PS3.6 does not publish one - see `renderTransferSyntax`.
12631
+ UNSUPPORTED_TRANSFER_SYNTAX: {
12632
+ code: FATAL_CODES.UNSUPPORTED_TRANSFER_SYNTAX,
12633
+ message: `{ts} in (0002,0010) is not supported by @cosyte/dicom v1 (supported: ${SUPPORTED_TRANSFER_SYNTAXES}).`
12634
+ },
12635
+ FILE_META_TRUNCATED: {
12636
+ code: FATAL_CODES.INVALID_FILE_META,
12637
+ message: "File Meta is truncated."
12638
+ },
12639
+ // The declared group length is deliberately absent. It is four bytes of the
12640
+ // document read as a 32-bit integer. **NOT because this code fires only when
12641
+ // those four bytes are fabricated** - an honestly truncated file raises it
12642
+ // with a perfectly correct group length, measured - but because they are four
12643
+ // bytes a sender wrote in either reading, and in the other one they are part
12644
+ // of somebody's value.
12645
+ FILE_META_GROUP_LENGTH_OVERRUNS: {
12646
+ code: FATAL_CODES.INVALID_FILE_META,
12647
+ message: "(0002,0000) FileMetaInformationGroupLength declares more bytes than remain in the input. The declared length and the count of bytes that remain are withheld; the byte offset locates the group."
12648
+ },
12649
+ FILE_META_TRANSFER_SYNTAX_MISSING: {
12650
+ code: FATAL_CODES.INVALID_FILE_META,
12651
+ message: "Required File Meta element (0002,0010) Transfer Syntax UID is missing or not UI."
12652
+ },
12653
+ TRUNCATED_DATASET_HEADER: {
12654
+ code: FATAL_CODES.INVALID_FILE_META,
12655
+ message: "Truncated dataset (header read past buffer end)."
12656
+ },
12657
+ TRUNCATED_FFFE_HEADER: {
12658
+ code: FATAL_CODES.INVALID_FILE_META,
12659
+ message: "Truncated dataset (FFFE header read past buffer end)."
12660
+ },
12661
+ TRUNCATED_EXPLICIT_VR_HEADER: {
12662
+ code: FATAL_CODES.INVALID_FILE_META,
12663
+ message: "Truncated dataset (Explicit VR header read past buffer end)."
12664
+ },
12665
+ SQ_ITEM_HEADER_TRUNCATED: {
12666
+ code: FATAL_CODES.INVALID_FILE_META,
12667
+ message: "Truncated dataset (SQ item header read past buffer end)."
12668
+ },
12669
+ // Neither the marker's element number nor its length field is here. Both are
12670
+ // read at a position the reader may have desynchronized to, so both are
12671
+ // document content: the length field measured as 1109414477, `"MR B"`.
12672
+ UNEXPECTED_FFFE_AT_DATASET_LEVEL: {
12673
+ code: FATAL_CODES.INVALID_FILE_META,
12674
+ message: "An (FFFE,xxxx) delimitation item appears at Data Set level under Explicit VR, where no sequence is open. Its element number and its length field are withheld; the byte offset locates it."
12675
+ },
12676
+ UNEXPECTED_FFFE_AT_DATASET_ROOT: {
12677
+ code: FATAL_CODES.INVALID_FILE_META,
12678
+ message: "An (FFFE,xxxx) delimitation item appears at Data Set level under Implicit VR LE, where no sequence is open. Its element number is withheld; the byte offset locates it."
12679
+ },
12680
+ UNDEFINED_LENGTH_ON_NON_SQ_EXPLICIT: {
12681
+ code: FATAL_CODES.INVALID_FILE_META,
12682
+ message: "An element with VR={vr} declares undefined length (0xFFFFFFFF) under Explicit VR. PS3.5 2026c permits that for a Sequence (7.5.2 Delimitation of The Sequence of Items), for encapsulated (7FE0,0010) Pixel Data (A.4), and for the UN form CP-246 addresses (6.2.2 Unknown (UN) Value Representation), and this element is none of them. Its tag is withheld; the byte offset locates it."
12683
+ },
12684
+ UNDEFINED_LENGTH_ON_NON_SQ_IMPLICIT: {
12685
+ code: FATAL_CODES.INVALID_FILE_META,
12686
+ message: "An element whose VR resolved to {vr} declares undefined length (0xFFFFFFFF) under Implicit VR LE, and the descent as an Implicit VR LE item stream (PS3.5 2026c 6.2.2, the UN form CP-246 addresses) did not succeed. Its tag is withheld; the byte offset locates it."
12687
+ },
12688
+ ELEMENT_LENGTH_EXCEEDS_BUFFER: {
12689
+ code: FATAL_CODES.INVALID_FILE_META,
12690
+ message: "An element declares a Value Length reaching past the end of the bytes being read. Its tag, its declared length and the count of bytes that remain are withheld; the byte offset locates it."
12691
+ },
12692
+ UNEXPECTED_TAG_INSIDE_SEQUENCE: {
12693
+ code: FATAL_CODES.INVALID_FILE_META,
12694
+ message: "A sequence's item stream holds a tag that is neither (FFFE,E000) Item nor (FFFE,E0DD) Sequence Delimitation Item (PS3.5 7.5). That tag is withheld: a value being read as an item stream makes its four bytes document content. The byte offset locates it."
12695
+ },
12696
+ ENCAPSULATED_FRAGMENT_EXCEEDS_BUFFER: {
12697
+ code: FATAL_CODES.INVALID_FILE_META,
12698
+ message: "An encapsulated Pixel Data fragment declares a length reaching past the end of the bytes being read. The declared length is withheld; the byte offset locates the fragment."
12699
+ },
12700
+ ITEM_LENGTH_EXCEEDS_BUFFER: {
12701
+ code: FATAL_CODES.INVALID_FILE_META,
12702
+ message: "An (FFFE,E000) Item declares a length reaching past the end of the bytes being read. The declared length is withheld; the byte offset locates the item."
12703
+ },
12704
+ SQ_NESTING_DEPTH_EXCEEDED: {
12705
+ code: FATAL_CODES.INVALID_FILE_META,
12706
+ message: "SQ nesting depth exceeds {n}."
12707
+ },
12708
+ INFLATED_PAYLOAD_EXCEEDS_CAP: {
12709
+ code: FATAL_CODES.INVALID_FILE_META,
12710
+ message: "Inflated Deflated TS payload exceeds {n}-byte cap."
12711
+ },
12712
+ // `{zlib}` is a member of the nine-name `zlib.codes` table or nothing. zlib's
12713
+ // own `err.message` is never forwarded: it is a string from a library handed
12714
+ // the sender's bytes, which is the one shape of third-party text this parser
12715
+ // cannot vouch for.
12716
+ INFLATE_FAILED: {
12717
+ code: FATAL_CODES.INVALID_FILE_META,
12718
+ message: "Failed to inflate Deflated TS payload (zlib error code: {zlib})."
12719
+ }
12720
+ });
12721
+ function renderTransferSyntax(ts) {
12722
+ if (ts === void 0) return "The Transfer Syntax UID";
12723
+ const name = uid(ts)?.name ?? "";
12724
+ return name.length > 0 ? `Transfer Syntax ${name}` : "The Transfer Syntax UID";
12725
+ }
12726
+ function renderZlibCode(code) {
12727
+ return code !== void 0 && ZLIB_CODES.has(code) ? code : WITHHELD;
12728
+ }
12729
+ function build2(key, byteOffset, offsetFrame, snippet, tokens = {}) {
12730
+ const entry = FATAL_MESSAGES[key];
12731
+ const message = entry.message.replace("{vr}", renderVr(tokens.vr)).replace("{ts}", renderTransferSyntax(tokens.ts)).replace("{zlib}", renderZlibCode(tokens.zlib)).replace("{n}", String(tokens.n ?? 0));
12732
+ return new DicomParseError(entry.code, message, byteOffset, offsetFrame, snippet);
12733
+ }
12734
+ function at(key, frame, offset, tokens = {}) {
12735
+ return build2(key, offset, frame.name, buildSnippet(frame.buffer, offset), tokens);
12736
+ }
12737
+ function emptyInput() {
12738
+ return build2("EMPTY_INPUT", 0, OFFSET_FRAMES.INPUT, "");
12739
+ }
12740
+ function emptyInputAfterNormalization() {
12741
+ return build2("EMPTY_INPUT_AFTER_NORMALIZATION", 0, OFFSET_FRAMES.INPUT, "");
12742
+ }
12743
+ function notDicomPart10Required(frame, offset) {
12744
+ return at("NOT_DICOM_PART_10_REQUIRED", frame, offset);
12745
+ }
12746
+ function notDicomPart10(frame, offset) {
12747
+ return at("NOT_DICOM_PART_10", frame, offset);
12748
+ }
12749
+ function unsupportedTransferSyntax(frame, offset, ts) {
12750
+ const name = uid(ts)?.name ?? "";
12751
+ return build2(
12752
+ "UNSUPPORTED_TRANSFER_SYNTAX",
12753
+ offset,
12754
+ frame.name,
12755
+ name.length > 0 ? name : buildSnippet(frame.buffer, offset),
12756
+ { ts }
12757
+ );
12758
+ }
12759
+ function fileMetaTruncated(frame, offset) {
12760
+ return at("FILE_META_TRUNCATED", frame, offset);
12761
+ }
12762
+ function fileMetaGroupLengthOverruns(frame, offset) {
12763
+ return at("FILE_META_GROUP_LENGTH_OVERRUNS", frame, offset);
12764
+ }
12765
+ function fileMetaTransferSyntaxMissing(frame, offset) {
12766
+ return at("FILE_META_TRANSFER_SYNTAX_MISSING", frame, offset);
12767
+ }
12768
+ function truncatedDatasetHeader(frame, offset) {
12769
+ return at("TRUNCATED_DATASET_HEADER", frame, offset);
12770
+ }
12771
+ function truncatedFffeHeader(frame, offset) {
12772
+ return at("TRUNCATED_FFFE_HEADER", frame, offset);
12773
+ }
12774
+ function truncatedExplicitVrHeader(frame, offset) {
12775
+ return at("TRUNCATED_EXPLICIT_VR_HEADER", frame, offset);
12776
+ }
12777
+ function sqItemHeaderTruncated(frame, offset) {
12778
+ return at("SQ_ITEM_HEADER_TRUNCATED", frame, offset);
12779
+ }
12780
+ function unexpectedFffeAtDatasetLevel(frame, offset) {
12781
+ return at("UNEXPECTED_FFFE_AT_DATASET_LEVEL", frame, offset);
12782
+ }
12783
+ function unexpectedFffeAtDatasetRoot(frame, offset) {
12784
+ return at("UNEXPECTED_FFFE_AT_DATASET_ROOT", frame, offset);
12785
+ }
12786
+ function undefinedLengthOnNonSqExplicit(frame, offset, vr) {
12787
+ return at("UNDEFINED_LENGTH_ON_NON_SQ_EXPLICIT", frame, offset, { vr });
12788
+ }
12789
+ function undefinedLengthOnNonSqImplicit(frame, offset, vr) {
12790
+ return at("UNDEFINED_LENGTH_ON_NON_SQ_IMPLICIT", frame, offset, { vr });
12791
+ }
12792
+ function elementLengthExceedsBuffer(frame, offset) {
12793
+ return at("ELEMENT_LENGTH_EXCEEDS_BUFFER", frame, offset);
12794
+ }
12795
+ function unexpectedTagInsideSequence(frame, offset) {
12796
+ return at("UNEXPECTED_TAG_INSIDE_SEQUENCE", frame, offset);
12797
+ }
12798
+ function encapsulatedFragmentExceedsBuffer(frame, offset) {
12799
+ return at("ENCAPSULATED_FRAGMENT_EXCEEDS_BUFFER", frame, offset);
12800
+ }
12801
+ function itemLengthExceedsBuffer(frame, offset) {
12802
+ return at("ITEM_LENGTH_EXCEEDS_BUFFER", frame, offset);
12803
+ }
12804
+ function sqNestingDepthExceeded(frame, offset, limit) {
12805
+ return at("SQ_NESTING_DEPTH_EXCEEDED", frame, offset, { n: limit });
12806
+ }
12807
+ function inflatedPayloadExceedsCap(frame, offset, cap) {
12808
+ return at("INFLATED_PAYLOAD_EXCEEDS_CAP", frame, offset, { n: cap });
12809
+ }
12810
+ function inflateFailed(frame, offset, code) {
12811
+ return at("INFLATE_FAILED", frame, offset, ...code !== void 0 ? [{ zlib: code }] : []);
12812
+ }
12813
+ function copyValueBytes(src) {
12814
+ const out = buffer.Buffer.allocUnsafeSlow(src.length);
12815
+ src.copy(out);
12816
+ return out;
12817
+ }
12818
+ var ByteCursor = class {
12819
+ buffer;
12820
+ littleEndian;
12821
+ position;
12822
+ /**
12823
+ * Construct a new cursor at `position` (default 0) over `buffer` with
12824
+ * the given endian orientation.
12825
+ *
12826
+ * @internal
12827
+ */
12828
+ constructor(buffer, littleEndian, position = 0) {
12829
+ this.buffer = buffer;
12830
+ this.littleEndian = littleEndian;
12831
+ this.position = position;
12832
+ }
12833
+ /** Read a 16-bit unsigned integer at the current position; advance by 2. */
12834
+ readUInt16() {
12835
+ if (this.position + 2 > this.buffer.length) {
12836
+ throw new RangeError("ByteCursor: read past end of buffer");
12837
+ }
12838
+ const v = this.littleEndian ? this.buffer.readUInt16LE(this.position) : this.buffer.readUInt16BE(this.position);
12839
+ this.position += 2;
12840
+ return v;
12841
+ }
12842
+ /** Read a 32-bit unsigned integer at the current position; advance by 4. */
12843
+ readUInt32() {
12844
+ if (this.position + 4 > this.buffer.length) {
12845
+ throw new RangeError("ByteCursor: read past end of buffer");
12846
+ }
12847
+ const v = this.littleEndian ? this.buffer.readUInt32LE(this.position) : this.buffer.readUInt32BE(this.position);
12848
+ this.position += 4;
12849
+ return v;
12850
+ }
12851
+ /** Read a 16-bit unsigned integer at an explicit offset; cursor unchanged. */
12852
+ readUInt16At(offset) {
12853
+ if (offset < 0 || offset + 2 > this.buffer.length) {
12854
+ throw new RangeError("ByteCursor: read past end of buffer");
12855
+ }
12856
+ return this.littleEndian ? this.buffer.readUInt16LE(offset) : this.buffer.readUInt16BE(offset);
12857
+ }
12858
+ /** Read a 32-bit unsigned integer at an explicit offset; cursor unchanged. */
12859
+ readUInt32At(offset) {
12860
+ if (offset < 0 || offset + 4 > this.buffer.length) {
12861
+ throw new RangeError("ByteCursor: read past end of buffer");
12862
+ }
12863
+ return this.littleEndian ? this.buffer.readUInt32LE(offset) : this.buffer.readUInt32BE(offset);
12864
+ }
12865
+ /**
12866
+ * Take a `length`-byte view starting at the current position; advance
12867
+ * the cursor by `length`. Returns a `Buffer.subarray` (zero-copy view);
12868
+ * callers wanting a copy must `Buffer.from(slice)` themselves.
12869
+ */
12870
+ slice(length) {
12871
+ if (length < 0 || this.position + length > this.buffer.length) {
12872
+ throw new RangeError("ByteCursor: read past end of buffer");
12873
+ }
12874
+ const out = this.buffer.subarray(this.position, this.position + length);
12875
+ this.position += length;
12876
+ return out;
12877
+ }
12878
+ /** Bytes remaining between the current position and the end of the buffer. */
12879
+ remaining() {
12880
+ return this.buffer.length - this.position;
12881
+ }
12882
+ };
12883
+
12884
+ // src/dataset/vr/iso2022.ts
12885
+ var ESC = 27;
12886
+ var LF = 10;
12887
+ var FF = 12;
12888
+ var CR = 13;
12889
+ var SPACE = 32;
12890
+ var DEL = 127;
12891
+ var BACKSLASH = 92;
12892
+ var CARET = 94;
12893
+ var EQUALS = 61;
12894
+ var REPLACEMENT = String.fromCharCode(65533);
12895
+ var NO_CODE_EXTENSION_VALUE_1 = /* @__PURE__ */ new Set(["ISO_IR 192", "GB18030", "GBK"]);
12896
+ var ESCAPE_SEQUENCES = [
12897
+ { tail: [40, 66], ir: 6, element: "G0" },
12898
+ { tail: [45, 65], ir: 100, element: "G1" },
12899
+ { tail: [45, 66], ir: 101, element: "G1" },
12900
+ { tail: [45, 67], ir: 109, element: "G1" },
12901
+ { tail: [45, 68], ir: 110, element: "G1" },
12902
+ { tail: [45, 76], ir: 144, element: "G1" },
12903
+ { tail: [45, 71], ir: 127, element: "G1" },
12904
+ { tail: [45, 70], ir: 126, element: "G1" },
12905
+ { tail: [45, 72], ir: 138, element: "G1" },
12906
+ { tail: [45, 77], ir: 148, element: "G1" },
12907
+ { tail: [45, 98], ir: 203, element: "G1" },
12908
+ { tail: [45, 84], ir: 166, element: "G1" },
12909
+ { tail: [41, 73], ir: 13, element: "G1" },
12910
+ { tail: [40, 74], ir: 14, element: "G0" },
12911
+ { tail: [36, 66], ir: 87, element: "G0" },
12912
+ { tail: [36, 40, 68], ir: 159, element: "G0" },
12913
+ { tail: [36, 41, 67], ir: 149, element: "G1" },
12914
+ { tail: [36, 41, 65], ir: 58, element: "G1" }
12915
+ ];
12916
+ var SINGLE_BYTE_G1_ROWS = [
12917
+ 100,
12918
+ 101,
12919
+ 109,
12920
+ 110,
12921
+ 144,
12922
+ 127,
12923
+ 126,
12924
+ 138,
12925
+ 148,
12926
+ 203,
12927
+ 166
12928
+ ];
12929
+ var TERM_ROWS = (() => {
12930
+ const rows = /* @__PURE__ */ new Map();
12931
+ const addBoth = (ir, row2) => {
12932
+ rows.set(`ISO 2022 IR ${String(ir)}`, row2);
12933
+ rows.set(`ISO_IR ${String(ir)}`, row2);
12934
+ };
12935
+ addBoth(6, { declares: [6], initial: { g0: 6, g1: void 0 } });
12936
+ for (const ir of SINGLE_BYTE_G1_ROWS) {
12937
+ addBoth(ir, { declares: [6, ir], initial: { g0: 6, g1: ir } });
12938
+ }
12939
+ addBoth(13, { declares: [14, 13], initial: { g0: 14, g1: 13 } });
12940
+ for (const ir of [87, 159, 149, 58]) rows.set(`ISO 2022 IR ${String(ir)}`, { declares: [ir] });
12941
+ return rows;
12942
+ })();
12943
+ var SINGLE_BYTE_LABELS = /* @__PURE__ */ new Map([
12944
+ [100, "latin1"],
12945
+ [101, "iso-8859-2"],
12946
+ [109, "iso-8859-3"],
12947
+ [110, "iso-8859-4"],
12948
+ [144, "iso-8859-5"],
12949
+ [127, "iso-8859-6"],
12950
+ [126, "iso-8859-7"],
12951
+ [138, "iso-8859-8"],
12952
+ [148, "iso-8859-9"],
12953
+ [203, "iso-8859-15"],
12954
+ [166, "windows-874"],
12955
+ [13, "shift_jis"]
12956
+ ]);
12957
+ var NINETY_FOUR_CHARACTER_G1 = /* @__PURE__ */ new Set([13]);
12958
+ function gb2312Assigned(row2, cell) {
12959
+ if (row2 === 2) {
12960
+ return cell >= 17 && cell <= 66 || cell >= 69 && cell <= 78 || cell >= 81 && cell <= 92;
12961
+ }
12962
+ if (row2 === 6) return cell >= 1 && cell <= 24 || cell >= 33 && cell <= 56;
12963
+ if (row2 === 8) return cell >= 1 && cell <= 26 || cell >= 37 && cell <= 73;
12964
+ return true;
12965
+ }
12966
+ var DOUBLE_BYTE_SETS = /* @__PURE__ */ new Map([
12967
+ [
12968
+ 87,
12969
+ {
12970
+ label: "euc-jp",
12971
+ prefix: [],
12972
+ assigned: (row2) => row2 >= 1 && row2 <= 8 || row2 >= 16 && row2 <= 84
12973
+ }
12974
+ ],
12975
+ [159, { label: "euc-jp", prefix: [143], assigned: (row2) => row2 <= 77 }],
12976
+ [149, { label: "euc-kr", prefix: [], assigned: () => true }],
12977
+ [58, { label: "gb18030", prefix: [], assigned: gb2312Assigned }]
12978
+ ]);
12979
+ var decoders = /* @__PURE__ */ new Map();
12980
+ function decoderFor(label) {
12981
+ if (!decoders.has(label)) {
12982
+ let decoder;
12983
+ try {
12984
+ decoder = new TextDecoder(label, { fatal: false });
12985
+ } catch {
12986
+ decoder = void 0;
12987
+ }
12988
+ decoders.set(label, decoder);
12989
+ }
12990
+ return decoders.get(label);
12991
+ }
12992
+ function isCharacter(text) {
12993
+ const cp = text.codePointAt(0);
12994
+ if (cp === void 0 || String.fromCodePoint(cp).length !== text.length) return false;
12995
+ return cp >= 128 && cp !== 65533 && !(cp >= 57344 && cp <= 63743);
12996
+ }
12997
+ var singleByteTables = /* @__PURE__ */ new Map();
12998
+ function singleByteCharacter(ir, byte) {
12999
+ let table = singleByteTables.get(ir);
13000
+ if (table === void 0) {
13001
+ const label = SINGLE_BYTE_LABELS.get(ir);
13002
+ const decoder = label === void 0 ? void 0 : decoderFor(label);
13003
+ const built = [];
13004
+ for (let b = 160; b <= 255; b += 1) {
13005
+ const outside = NINETY_FOUR_CHARACTER_G1.has(ir) && (b === 160 || b === 255);
13006
+ const text = decoder === void 0 || outside ? "" : decoder.decode(Uint8Array.of(b));
13007
+ built.push(isCharacter(text) ? text : void 0);
13008
+ }
13009
+ table = built;
13010
+ singleByteTables.set(ir, table);
13011
+ }
13012
+ return table[byte - 160];
13013
+ }
13014
+ var pairCaches = /* @__PURE__ */ new Map();
13015
+ function pairCharacter(set, ir, first, second) {
13016
+ const row2 = (first & 127) - 32;
13017
+ const cell = (second & 127) - 32;
13018
+ if (!set.assigned(row2, cell)) return void 0;
13019
+ let cache = pairCaches.get(ir);
13020
+ if (cache === void 0) {
13021
+ cache = /* @__PURE__ */ new Map();
13022
+ pairCaches.set(ir, cache);
13023
+ }
13024
+ const key = row2 * 256 + cell;
13025
+ if (!cache.has(key)) {
13026
+ const decoder = decoderFor(set.label);
13027
+ const text = decoder === void 0 ? "" : decoder.decode(Uint8Array.of(...set.prefix, first | 128, second | 128));
13028
+ cache.set(key, isCharacter(text) ? text : void 0);
13029
+ }
13030
+ return cache.get(key);
13031
+ }
13032
+ function at2(bytes, index) {
13033
+ return bytes[index] ?? -1;
13034
+ }
13035
+ function matchEscape(bytes, index) {
13036
+ return ESCAPE_SEQUENCES.find(
13037
+ (sequence) => sequence.tail.every((byte, k) => at2(bytes, index + 1 + k) === byte)
13038
+ );
13039
+ }
13040
+ function isLineBreak(byte) {
13041
+ return byte === CR || byte === LF || byte === FF;
13042
+ }
13043
+ function endOfUnrecognizedRun(bytes, from) {
13044
+ let index = from;
13045
+ while (index < bytes.length) {
13046
+ const byte = at2(bytes, index);
13047
+ if (isLineBreak(byte) || byte === ESC && matchEscape(bytes, index) !== void 0) break;
13048
+ index += 1;
13049
+ }
13050
+ return index;
13051
+ }
13052
+ function isDelimiter(byte, delimiters) {
13053
+ if (delimiters === "personName") return byte === BACKSLASH || byte === CARET || byte === EQUALS;
13054
+ if (delimiters === "multiValued") return byte === BACKSLASH;
13055
+ return false;
13056
+ }
13057
+ function isGl(byte) {
13058
+ return byte >= 33 && byte <= 126;
13059
+ }
13060
+ function isGr94(byte) {
13061
+ return byte >= 161 && byte <= 254;
13062
+ }
13063
+ function usesCodeExtensions(terms) {
13064
+ return terms !== void 0 && terms.length > 1 && !NO_CODE_EXTENSION_VALUE_1.has(terms[0] ?? "");
13065
+ }
13066
+ function decodeWithCodeExtensions(bytes, terms, delimiters) {
13067
+ const declared = /* @__PURE__ */ new Set();
13068
+ for (const term of terms) for (const ir of TERM_ROWS.get(term)?.declares ?? []) declared.add(ir);
13069
+ if (terms[0] === "") declared.add(6);
13070
+ const initial = TERM_ROWS.get(terms[0] ?? "")?.initial ?? { g0: 6, g1: void 0 };
13071
+ let g0 = initial.g0;
13072
+ let g1 = initial.g1;
13073
+ let escapeUndeclared = false;
13074
+ let bytesUndecodable = false;
13075
+ let extensionNotReset = false;
13076
+ const out = [];
13077
+ const reset = () => {
13078
+ if (g0 !== initial.g0) extensionNotReset = true;
13079
+ g0 = initial.g0;
13080
+ g1 = initial.g1;
13081
+ };
13082
+ const replace = () => {
13083
+ out.push(REPLACEMENT);
13084
+ bytesUndecodable = true;
13085
+ };
13086
+ let i = 0;
13087
+ while (i < bytes.length) {
13088
+ const byte = at2(bytes, i);
13089
+ if (byte === ESC) {
13090
+ const sequence = matchEscape(bytes, i);
13091
+ if (sequence === void 0) {
13092
+ replace();
13093
+ i = endOfUnrecognizedRun(bytes, i + 1);
13094
+ continue;
13095
+ }
13096
+ if (!declared.has(sequence.ir)) escapeUndeclared = true;
13097
+ if (sequence.element === "G0") g0 = sequence.ir;
13098
+ else g1 = sequence.ir;
13099
+ i += 1 + sequence.tail.length;
13100
+ continue;
13101
+ }
13102
+ if (isLineBreak(byte)) {
13103
+ out.push(String.fromCharCode(byte));
13104
+ reset();
13105
+ i += 1;
13106
+ continue;
13107
+ }
13108
+ if (byte >= 128) {
13109
+ const doubleG1 = g1 === void 0 ? void 0 : DOUBLE_BYTE_SETS.get(g1);
13110
+ if (g1 === void 0 || byte < 160) {
13111
+ replace();
13112
+ i += 1;
13113
+ } else if (doubleG1 !== void 0) {
13114
+ const next = at2(bytes, i + 1);
13115
+ if (isGr94(byte) && isGr94(next)) {
13116
+ const text = pairCharacter(doubleG1, g1, byte, next);
13117
+ if (text === void 0) replace();
13118
+ else out.push(text);
13119
+ i += 2;
13120
+ } else {
13121
+ replace();
13122
+ i += 1;
13123
+ }
13124
+ } else {
13125
+ const text = singleByteCharacter(g1, byte);
13126
+ if (text === void 0) replace();
13127
+ else out.push(text);
13128
+ i += 1;
13129
+ }
13130
+ continue;
13131
+ }
13132
+ if (!isGl(byte)) {
13133
+ out.push(String.fromCharCode(byte));
13134
+ i += 1;
13135
+ continue;
13136
+ }
13137
+ const doubleG0 = DOUBLE_BYTE_SETS.get(g0);
13138
+ if (doubleG0 !== void 0) {
13139
+ const next = at2(bytes, i + 1);
13140
+ if (isGl(next)) {
13141
+ const text = pairCharacter(doubleG0, g0, byte, next);
13142
+ if (text === void 0) replace();
13143
+ else out.push(text);
13144
+ i += 2;
13145
+ } else if (isDelimiter(byte, delimiters)) {
13146
+ out.push(String.fromCharCode(byte));
13147
+ reset();
13148
+ i += 1;
13149
+ } else {
13150
+ replace();
13151
+ i += 1;
13152
+ }
13153
+ continue;
13154
+ }
13155
+ if (isDelimiter(byte, delimiters)) {
13156
+ out.push(String.fromCharCode(byte));
13157
+ reset();
13158
+ i += 1;
13159
+ continue;
13160
+ }
13161
+ let end = i + 1;
13162
+ while (end < bytes.length) {
13163
+ const b = at2(bytes, end);
13164
+ if (b < SPACE || b >= DEL || isDelimiter(b, delimiters)) break;
13165
+ end += 1;
13166
+ }
13167
+ out.push(bytes.toString("latin1", i, end));
13168
+ i = end;
13169
+ }
13170
+ if (g0 !== initial.g0) extensionNotReset = true;
13171
+ return { text: out.join(""), escapeUndeclared, bytesUndecodable, extensionNotReset };
12491
13172
  }
12492
- function isNonintegerValue(position, tag) {
12493
- return build2(WARNING_CODES.DICOM_IS_NONINTEGER_VALUE, position, { tag });
13173
+
13174
+ // src/dataset/vr/charset.ts
13175
+ var TERM_TO_LABEL = /* @__PURE__ */ new Map([
13176
+ // Default repertoire (ISO 646 IRV / ASCII). Latin-1 is a lenient,
13177
+ // never-throws 1:1 superset for the ASCII range.
13178
+ ["", "latin1"],
13179
+ ["ISO_IR 6", "latin1"],
13180
+ ["ISO 2022 IR 6", "latin1"],
13181
+ // Single-byte Latin / Cyrillic / Arabic / Greek / Hebrew / Thai.
13182
+ ["ISO_IR 100", "latin1"],
13183
+ ["ISO 2022 IR 100", "latin1"],
13184
+ ["ISO_IR 101", "iso-8859-2"],
13185
+ ["ISO 2022 IR 101", "iso-8859-2"],
13186
+ ["ISO_IR 109", "iso-8859-3"],
13187
+ ["ISO 2022 IR 109", "iso-8859-3"],
13188
+ ["ISO_IR 110", "iso-8859-4"],
13189
+ ["ISO 2022 IR 110", "iso-8859-4"],
13190
+ ["ISO_IR 144", "iso-8859-5"],
13191
+ ["ISO 2022 IR 144", "iso-8859-5"],
13192
+ ["ISO_IR 127", "iso-8859-6"],
13193
+ ["ISO 2022 IR 127", "iso-8859-6"],
13194
+ ["ISO_IR 126", "iso-8859-7"],
13195
+ ["ISO 2022 IR 126", "iso-8859-7"],
13196
+ ["ISO_IR 138", "iso-8859-8"],
13197
+ ["ISO 2022 IR 138", "iso-8859-8"],
13198
+ ["ISO_IR 148", "iso-8859-9"],
13199
+ ["ISO 2022 IR 148", "iso-8859-9"],
13200
+ ["ISO_IR 203", "iso-8859-15"],
13201
+ ["ISO 2022 IR 203", "iso-8859-15"],
13202
+ ["ISO_IR 13", "shift_jis"],
13203
+ ["ISO 2022 IR 13", "shift_jis"],
13204
+ ["ISO_IR 166", "windows-874"],
13205
+ ["ISO 2022 IR 166", "windows-874"],
13206
+ // Unicode / Chinese single-shot.
13207
+ ["ISO_IR 192", "utf-8"],
13208
+ ["GB18030", "gb18030"],
13209
+ ["GBK", "gbk"],
13210
+ // Multibyte code-extension terms (no bare ISO_IR form).
13211
+ ["ISO 2022 IR 87", "iso-2022-jp"],
13212
+ ["ISO 2022 IR 159", "iso-2022-jp"],
13213
+ ["ISO 2022 IR 149", "euc-kr"],
13214
+ ["ISO 2022 IR 58", "gb18030"]
13215
+ ]);
13216
+ var MULTIBYTE_LABELS = /* @__PURE__ */ new Set([
13217
+ "utf-8",
13218
+ "iso-2022-jp",
13219
+ "euc-kr",
13220
+ "gb18030",
13221
+ "gbk",
13222
+ "shift_jis"
13223
+ ]);
13224
+ function parseSpecificCharacterSet(bytes) {
13225
+ const raw = bytes.toString("latin1");
13226
+ return raw.split("\\").map((t) => t.replace(/[ ]+$/u, "").replace(/^[ ]+/u, "")).map((t) => t === "" || TERM_TO_LABEL.has(t) ? t : WITHHELD);
12494
13227
  }
12495
- function daLegacyFormat(position, tag) {
12496
- return build2(WARNING_CODES.DICOM_DA_LEGACY_FORMAT, position, { tag });
13228
+ function isKnownCharsetTerm(term) {
13229
+ return TERM_TO_LABEL.has(term);
12497
13230
  }
12498
- function dtNonstandardOffset(position, tag) {
12499
- return build2(WARNING_CODES.DICOM_DT_NONSTANDARD_OFFSET, position, { tag });
13231
+ function resolveDecoderLabel(terms) {
13232
+ if (terms === void 0 || terms.length === 0) return "latin1";
13233
+ let firstKnown;
13234
+ for (const term of terms) {
13235
+ const label = TERM_TO_LABEL.get(term);
13236
+ if (label === void 0) continue;
13237
+ if (MULTIBYTE_LABELS.has(label)) return label;
13238
+ firstKnown ??= label;
13239
+ }
13240
+ return firstKnown ?? "latin1";
12500
13241
  }
12501
- function unsupportedCharset(position, valueIndex) {
12502
- return build2(WARNING_CODES.DICOM_UNSUPPORTED_CHARSET, position, { n: valueIndex });
13242
+ function decodeText(bytes, terms) {
13243
+ if (usesCodeExtensions(terms)) return decodeWithCodeExtensions(bytes, terms, "text").text;
13244
+ const label = resolveDecoderLabel(terms);
13245
+ try {
13246
+ return new TextDecoder(label, { fatal: false }).decode(bytes);
13247
+ } catch {
13248
+ try {
13249
+ return new TextDecoder("utf-8", { fatal: false }).decode(bytes);
13250
+ } catch {
13251
+ return bytes.toString("latin1");
13252
+ }
13253
+ }
12503
13254
  }
12504
13255
 
12505
13256
  // src/profiles/lookup.ts
@@ -13026,16 +13777,16 @@ function parsePersonName(value) {
13026
13777
  // src/dataset/vr/decode.ts
13027
13778
  var BINARY_VRS = /* @__PURE__ */ new Set(["OB", "OD", "OF", "OL", "OV", "OW", "UN"]);
13028
13779
  var NUMBER_VRS = /* @__PURE__ */ new Set(["US", "UL", "SS", "SL", "FL", "FD"]);
13029
- var SPACE = 32;
13780
+ var SPACE2 = 32;
13030
13781
  var NULL = 0;
13031
13782
  function stripPad(bytes, tag, vr, position, warnings) {
13032
13783
  let end = bytes.length;
13033
13784
  if (vr === "UI") {
13034
- if (end > 0 && bytes[end - 1] === SPACE) warnings.push(uiTrailingSpace(position, tag));
13035
- while (end > 0 && (bytes[end - 1] === NULL || bytes[end - 1] === SPACE)) end--;
13785
+ if (end > 0 && bytes[end - 1] === SPACE2) warnings.push(uiTrailingSpace(position, tag));
13786
+ while (end > 0 && (bytes[end - 1] === NULL || bytes[end - 1] === SPACE2)) end--;
13036
13787
  } else {
13037
13788
  if (end > 0 && bytes[end - 1] === NULL) warnings.push(trailingNullInTextVR(position, tag, vr));
13038
- while (end > 0 && (bytes[end - 1] === SPACE || bytes[end - 1] === NULL)) end--;
13789
+ while (end > 0 && (bytes[end - 1] === SPACE2 || bytes[end - 1] === NULL)) end--;
13039
13790
  }
13040
13791
  return bytes.subarray(0, end);
13041
13792
  }
@@ -13051,13 +13802,23 @@ function decodeAsciiString(bytes, tag, vr, position, warnings) {
13051
13802
  }
13052
13803
  return bytes.toString("latin1");
13053
13804
  }
13805
+ function delimiterClass(vr) {
13806
+ if (vr === "PN") return "personName";
13807
+ if (vr === "LO" || vr === "SH" || vr === "UC") return "multiValued";
13808
+ return "text";
13809
+ }
13054
13810
  function decodeCharsetString(bytes, tag, vr, charset, position, warnings) {
13055
13811
  let b = bytes;
13056
13812
  if (b.length >= 3 && b[0] === 239 && b[1] === 187 && b[2] === 191) {
13057
13813
  warnings.push(bomInTextVR(position, tag, vr));
13058
13814
  b = b.subarray(3);
13059
13815
  }
13060
- return decodeText(b, charset);
13816
+ if (!usesCodeExtensions(charset)) return decodeText(b, charset);
13817
+ const decoded = decodeWithCodeExtensions(b, charset, delimiterClass(vr));
13818
+ if (decoded.escapeUndeclared) warnings.push(charsetEscapeUndeclared(position, tag, vr));
13819
+ if (decoded.bytesUndecodable) warnings.push(charsetBytesUndecodable(position, tag, vr));
13820
+ if (decoded.extensionNotReset) warnings.push(charsetExtensionNotReset(position, tag, vr));
13821
+ return decoded.text;
13061
13822
  }
13062
13823
  function decodeElementValue(element) {
13063
13824
  const { vr, rawBytes, tag } = element;
@@ -13157,10 +13918,10 @@ var Element = class {
13157
13918
  byteOffset;
13158
13919
  privateCreator;
13159
13920
  /**
13160
- * Phase 2 hint for Phase 3's lazy SQ decoder per D-30. `true` when this
13161
- * Element was promoted from `VR=UN` with undefined length to `VR=SQ` via
13162
- * the CP-246 fallback. Phase 3 uses this to choose the Implicit VR LE
13163
- * inner decoder. Always `undefined` on standard SQ elements.
13921
+ * Hint for the lazy SQ decoder. `true` when this Element was promoted
13922
+ * from `VR=UN` with undefined length to `VR=SQ` via the CP-246 fallback,
13923
+ * which is what selects the Implicit VR LE inner decoder. Always
13924
+ * `undefined` on standard SQ elements.
13164
13925
  *
13165
13926
  * @internal
13166
13927
  */
@@ -13174,9 +13935,9 @@ var Element = class {
13174
13935
  /** Lazily-decoded, memoized {@link DicomValue}. */
13175
13936
  _valueCache;
13176
13937
  /**
13177
- * Construct a new structural `Element`. Producers (parser plans 02-03
13178
- * onward) build these directly from on-wire bytes; consumers receive
13179
- * them via `Dataset` after `parseDicom`.
13938
+ * Construct a new structural `Element`. The parser builds these directly
13939
+ * from on-wire bytes; consumers receive them via `Dataset` after
13940
+ * `parseDicom`.
13180
13941
  *
13181
13942
  * @internal
13182
13943
  */
@@ -13224,15 +13985,38 @@ function defineElement(elements, element, emit) {
13224
13985
  // src/dataset/item.ts
13225
13986
  var Item = class extends Dataset {
13226
13987
  index;
13988
+ /**
13989
+ * Byte offset of this Item's `(FFFE,E000)` Item tag in the Part 10 file it
13990
+ * was read from, counted from the first byte of the File Preamble, which is
13991
+ * how PS3.3 2026d Table F.3-3 counts a DICOMDIR's offsets. For a file read
13992
+ * without a preamble, the 132 bytes of File Preamble and `DICM` prefix it
13993
+ * lacks are still counted, so the File Meta group's first byte is offset 132.
13994
+ *
13995
+ * `undefined` for an Item with no position in a file: one inside a Deflated
13996
+ * Data Set (a byte of a deflated stream is not a byte of the file), and one
13997
+ * built by hand. `deidentify()` carries it from each source Item to the Item
13998
+ * it rebuilds, as that Item's identity: it is how `serializeDicom` ties a
13999
+ * DICOMDIR offset to the Directory Record it named.
14000
+ *
14001
+ * @example
14002
+ * ```ts
14003
+ * import { parseDicom } from "@cosyte/dicom";
14004
+ * const ds = parseDicom(buf);
14005
+ * const first = ds.get("00041220")?.items?.[0];
14006
+ * first?.fileOffset; // where that Directory Record Item starts in the file
14007
+ * ```
14008
+ */
14009
+ fileOffset;
13227
14010
  /**
13228
14011
  * Construct a new structural `Item`. Producers are the SQ / FFFE
13229
- * marker parsers in plan 02-04.
14012
+ * marker parsers.
13230
14013
  *
13231
14014
  * @internal
13232
14015
  */
13233
14016
  constructor(init) {
13234
14017
  super(init);
13235
14018
  this.index = init.index;
14019
+ this.fileOffset = init.fileOffset;
13236
14020
  }
13237
14021
  };
13238
14022
 
@@ -13286,19 +14070,25 @@ function parseSequence(buffer, valueStart, ctx, emit, opts) {
13286
14070
  throw err;
13287
14071
  }
13288
14072
  const itemTag = joinTag(group, element);
14073
+ const fileOffset = fileOffsetIn(ctx.frame, itemHeaderStart);
14074
+ const itemPosition = fileOffset !== void 0 ? { fileOffset } : {};
13289
14075
  if (itemTag === SEQ_DELIM_TAG) {
13290
- return { items, endOffset: cursor.position };
14076
+ return { items, endOffset: cursor.position, delimited: true };
13291
14077
  }
13292
14078
  if (itemTag !== ITEM_TAG) {
13293
14079
  throw unexpectedTagInsideSequence(ctx.frame, itemHeaderStart);
13294
14080
  }
13295
14081
  if (itemLength === 0) {
13296
- emit(emptyItemInSequence({ byteOffset: itemHeaderStart }, itemTag));
14082
+ const emptyBasicOffsetTable = opts.encapsulatedPixelData === true && itemIndex === 0;
14083
+ if (!emptyBasicOffsetTable) {
14084
+ emit(emptyItemInSequence({ byteOffset: itemHeaderStart }, itemTag));
14085
+ }
13297
14086
  items.push(
13298
14087
  new Item({
13299
14088
  warnings: [],
13300
14089
  elements: /* @__PURE__ */ new Map(),
13301
- index: itemIndex
14090
+ index: itemIndex,
14091
+ ...itemPosition
13302
14092
  })
13303
14093
  );
13304
14094
  itemIndex += 1;
@@ -13309,7 +14099,9 @@ function parseSequence(buffer, valueStart, ctx, emit, opts) {
13309
14099
  throw encapsulatedFragmentExceedsBuffer(ctx.frame, itemHeaderStart);
13310
14100
  }
13311
14101
  cursor.position += itemLength;
13312
- items.push(new Item({ warnings: [], elements: /* @__PURE__ */ new Map(), index: itemIndex }));
14102
+ items.push(
14103
+ new Item({ warnings: [], elements: /* @__PURE__ */ new Map(), index: itemIndex, ...itemPosition })
14104
+ );
13313
14105
  itemIndex += 1;
13314
14106
  continue;
13315
14107
  }
@@ -13319,7 +14111,14 @@ function parseSequence(buffer, valueStart, ctx, emit, opts) {
13319
14111
  const inner = opts.innerStrategy(buffer, cursor.position, ctx, emit, {
13320
14112
  stopOnItemDelim: true
13321
14113
  });
13322
- items.push(new Item({ warnings: [], elements: inner.elements, index: itemIndex }));
14114
+ items.push(
14115
+ new Item({
14116
+ warnings: [],
14117
+ elements: inner.elements,
14118
+ index: itemIndex,
14119
+ ...itemPosition
14120
+ })
14121
+ );
13323
14122
  cursor.position = inner.endOffset;
13324
14123
  } else {
13325
14124
  if (opts.explicitLength !== void 0 && endLimit < buffer.length && cursor.position + itemLength > endLimit) {
@@ -13332,17 +14131,24 @@ function parseSequence(buffer, valueStart, ctx, emit, opts) {
13332
14131
  const enclosingFrame = ctx.frame;
13333
14132
  let inner;
13334
14133
  try {
13335
- ctx.frame = { buffer: itemSlice, name: OFFSET_FRAMES.VALUE_SLICE };
14134
+ ctx.frame = valueSliceFrame(enclosingFrame, itemSlice, cursor.position);
13336
14135
  inner = opts.innerStrategy(itemSlice, 0, ctx, emit);
13337
14136
  } finally {
13338
14137
  ctx.frame = enclosingFrame;
13339
14138
  }
13340
- items.push(new Item({ warnings: [], elements: inner.elements, index: itemIndex }));
14139
+ items.push(
14140
+ new Item({
14141
+ warnings: [],
14142
+ elements: inner.elements,
14143
+ index: itemIndex,
14144
+ ...itemPosition
14145
+ })
14146
+ );
13341
14147
  cursor.position += itemLength;
13342
14148
  }
13343
14149
  itemIndex += 1;
13344
14150
  }
13345
- return { items, endOffset: cursor.position };
14151
+ return { items, endOffset: cursor.position, delimited: false };
13346
14152
  } finally {
13347
14153
  ctx.nestingDepth -= 1;
13348
14154
  ctx.encodingContextStack.pop();
@@ -13363,7 +14169,7 @@ function tryParseDefinedLengthSQ(buffer, valueStart, valueLength, ctx, emit, imp
13363
14169
  const enclosingFrame = ctx.frame;
13364
14170
  let result;
13365
14171
  try {
13366
- ctx.frame = { buffer: slice, name: OFFSET_FRAMES.VALUE_SLICE };
14172
+ ctx.frame = valueSliceFrame(enclosingFrame, slice, valueStart);
13367
14173
  result = parseSequence(slice, 0, ctx, emit, {
13368
14174
  explicitLength: valueLength,
13369
14175
  littleEndian: true,
@@ -13395,13 +14201,13 @@ function tryParseUnAsSQ(buffer, valueStart, valueLength, ctx, emit, implicitLeIn
13395
14201
  const opts = {
13396
14202
  explicitLength: valueLength === UNDEFINED_LENGTH ? void 0 : valueLength,
13397
14203
  littleEndian: true,
13398
- // CP-246: Implicit VR LE inner per D-30.
14204
+ // CP-246: the inner encoding is Implicit VR LE.
13399
14205
  innerStrategy: implicitLeInner
13400
14206
  };
13401
14207
  const enclosingFrame = ctx.frame;
13402
14208
  let result;
13403
14209
  try {
13404
- ctx.frame = { buffer: slice, name: OFFSET_FRAMES.VALUE_SLICE };
14210
+ ctx.frame = valueSliceFrame(enclosingFrame, slice, valueStart);
13405
14211
  result = parseSequence(slice, 0, ctx, emit, opts);
13406
14212
  } finally {
13407
14213
  ctx.frame = enclosingFrame;
@@ -13570,7 +14376,7 @@ function parseImplicitLE(buffer, datasetStart, ctx, emit, opts = {}) {
13570
14376
  new Element({
13571
14377
  tag,
13572
14378
  vr,
13573
- // Phase 2 placeholder - Phase 3 derives VM from VR + value layout.
14379
+ // Placeholder - the value decoders derive VM from VR + value layout.
13574
14380
  vm: 1,
13575
14381
  length,
13576
14382
  rawBytes: valueSlice,
@@ -13691,14 +14497,19 @@ function _parseExplicit(buffer, datasetStart, ctx, emit, mode, opts = {}) {
13691
14497
  encapsulatedPixelData: true
13692
14498
  };
13693
14499
  const result = parseSequence(buffer, valueStart2, ctx, emit, seqOpts);
14500
+ if (!result.delimited) {
14501
+ emit(pixelDataFragmentsNotDelimited(position));
14502
+ }
13694
14503
  cursor.position = result.endOffset;
13695
14504
  const rawBytes = ctx.copyValues ? copyValueBytes(buffer.subarray(headerStart, cursor.position)) : buffer.subarray(headerStart, cursor.position);
13696
14505
  defineElement(
13697
14506
  elements,
13698
14507
  new Element({
13699
14508
  tag,
14509
+ // NOT promoted: the value stays `binary` over the whole on-wire span.
14510
+ // `readPixelDataFragments` walks that span for the Basic Offset Table
14511
+ // and the fragments.
13700
14512
  vr: "OB",
13701
- // NOT promoted; Phase 4 surfaces fragments.
13702
14513
  vm: result.items.length,
13703
14514
  length: UNDEFINED_LENGTH2,
13704
14515
  rawBytes,
@@ -13789,7 +14600,7 @@ function _parseExplicit(buffer, datasetStart, ctx, emit, mode, opts = {}) {
13789
14600
  new Element({
13790
14601
  tag,
13791
14602
  vr: finalVr,
13792
- // Phase 2 placeholder - Phase 3 derives VM from VR + value layout.
14603
+ // Placeholder - the value decoders derive VM from VR + value layout.
13793
14604
  vm: 1,
13794
14605
  length,
13795
14606
  rawBytes: valueSlice,
@@ -13861,8 +14672,28 @@ function parseExplicitBE(buffer, datasetStart, ctx, emit, opts = {}) {
13861
14672
  );
13862
14673
  }
13863
14674
 
14675
+ // src/parser/jpip-referenced.ts
14676
+ var JPIP_REFERENCED_EXPLICIT_LE_UIDS = Object.freeze([
14677
+ "1.2.840.10008.1.2.4.94",
14678
+ "1.2.840.10008.1.2.4.204"
14679
+ ]);
14680
+ var JPIP_REFERENCED_DEFLATE_UIDS = Object.freeze([
14681
+ "1.2.840.10008.1.2.4.95",
14682
+ "1.2.840.10008.1.2.4.205"
14683
+ ]);
14684
+ var JPIP_REFERENCED_UIDS = Object.freeze([
14685
+ ...JPIP_REFERENCED_EXPLICIT_LE_UIDS,
14686
+ ...JPIP_REFERENCED_DEFLATE_UIDS
14687
+ ]);
14688
+
13864
14689
  // src/parser/transfer-syntax.ts
14690
+ function entriesFor(uids, strategy) {
14691
+ return uids.map((uid2) => [uid2, strategy]);
14692
+ }
13865
14693
  var TRANSFER_SYNTAX_PARSERS = Object.freeze({
14694
+ ...Object.fromEntries(entriesFor(ENCAPSULATED_TRANSFER_SYNTAX_UIDS, parseExplicitLE)),
14695
+ ...Object.fromEntries(entriesFor(JPIP_REFERENCED_EXPLICIT_LE_UIDS, parseExplicitLE)),
14696
+ ...Object.fromEntries(entriesFor(JPIP_REFERENCED_DEFLATE_UIDS, parseDeflatedLE)),
13866
14697
  "1.2.840.10008.1.2": parseImplicitLE,
13867
14698
  "1.2.840.10008.1.2.1": parseExplicitLE,
13868
14699
  "1.2.840.10008.1.2.2": parseExplicitBE,
@@ -13870,6 +14701,7 @@ var TRANSFER_SYNTAX_PARSERS = Object.freeze({
13870
14701
  });
13871
14702
 
13872
14703
  // src/parser/index.ts
14704
+ var PREAMBLE_AND_PREFIX_LENGTH = 132;
13873
14705
  function parseDicom(input, options = {}) {
13874
14706
  if (rawInputIsEmpty(input)) {
13875
14707
  throw emptyInput();
@@ -13881,7 +14713,8 @@ function parseDicom(input, options = {}) {
13881
14713
  const warnings = [];
13882
14714
  const ctx = buildContext(buffer, options, warnings);
13883
14715
  const emit = makeEmitter(ctx);
13884
- const { datasetStart } = parsePart10Header(buffer, ctx, emit);
14716
+ const { datasetStart, hadPreamble } = parsePart10Header(buffer, ctx, emit);
14717
+ ctx.frame = { ...ctx.frame, origin: hadPreamble ? 0 : PREAMBLE_AND_PREFIX_LENGTH };
13885
14718
  const { fileMeta, fileMetaEnd } = parseFileMeta(buffer, datasetStart, ctx, emit);
13886
14719
  const tsUid = fileMeta.transferSyntaxUID;
13887
14720
  const strategy = TRANSFER_SYNTAX_PARSERS[tsUid];
@@ -13889,6 +14722,11 @@ function parseDicom(input, options = {}) {
13889
14722
  throw unsupportedTransferSyntax(ctx.frame, fileMetaEnd, tsUid);
13890
14723
  }
13891
14724
  const { elements } = strategy(buffer, fileMetaEnd, ctx, emit);
14725
+ emitDirectoryFindings(
14726
+ { fileMeta, get: (tag) => elements.get(tag) },
14727
+ { origin: hadPreamble ? 0 : PREAMBLE_AND_PREFIX_LENGTH, fileMetaEnd },
14728
+ emit
14729
+ );
13892
14730
  return new Dataset({ fileMeta, warnings: ctx.warnings, elements });
13893
14731
  }
13894
14732
  function rawInputIsEmpty(input) {
@@ -13938,12 +14776,159 @@ var Sequence = class {
13938
14776
  this.length = length;
13939
14777
  }
13940
14778
  };
14779
+
14780
+ // src/dataset/pixel-data.ts
14781
+ var PIXEL_DATA = "7FE00010";
13941
14782
  var UNDEFINED_LENGTH3 = 4294967295;
14783
+ var ELEMENT_HEADER_LENGTH = 12;
14784
+ var ITEM_HEADER_LENGTH = 8;
14785
+ var ITEM_GROUP = 65534;
14786
+ var ITEM = 57344;
14787
+ var SEQUENCE_DELIMITATION = 57565;
14788
+ function readPixelDataFragments(ds) {
14789
+ const el = ds.get(PIXEL_DATA);
14790
+ if (el === void 0 || !isEncapsulated(el)) return void 0;
14791
+ return walkItems(el);
14792
+ }
14793
+ function isEncapsulated(el) {
14794
+ return el.vr === "OB" && el.length === UNDEFINED_LENGTH3;
14795
+ }
14796
+ function walkItems(el) {
14797
+ const raw = el.rawBytes;
14798
+ const frame = { buffer: raw, name: OFFSET_FRAMES.VALUE_SLICE };
14799
+ const read16 = (at4) => el.littleEndian ? raw.readUInt16LE(at4) : raw.readUInt16BE(at4);
14800
+ const read32 = (at4) => el.littleEndian ? raw.readUInt32LE(at4) : raw.readUInt32BE(at4);
14801
+ let basicOffsetTable;
14802
+ const fragments = [];
14803
+ let at3 = ELEMENT_HEADER_LENGTH;
14804
+ while (at3 < raw.length) {
14805
+ if (at3 + ITEM_HEADER_LENGTH > raw.length) throw sqItemHeaderTruncated(frame, at3);
14806
+ const group = read16(at3);
14807
+ const element = read16(at3 + 2);
14808
+ if (group === ITEM_GROUP && element === SEQUENCE_DELIMITATION) break;
14809
+ if (group !== ITEM_GROUP || element !== ITEM) throw unexpectedTagInsideSequence(frame, at3);
14810
+ const valueStart = at3 + ITEM_HEADER_LENGTH;
14811
+ const valueEnd = valueStart + read32(at3 + 4);
14812
+ if (valueEnd > raw.length) throw encapsulatedFragmentExceedsBuffer(frame, at3);
14813
+ const value = raw.subarray(valueStart, valueEnd);
14814
+ if (basicOffsetTable === void 0) basicOffsetTable = value;
14815
+ else fragments.push(value);
14816
+ at3 = valueEnd;
14817
+ }
14818
+ return { basicOffsetTable, fragments };
14819
+ }
14820
+
14821
+ // src/dataset/vr/date-conversion.ts
14822
+ var FRACTION_DIGITS = /\.(\d+)/u;
14823
+ function pad(value, width) {
14824
+ return String(value).padStart(width, "0");
14825
+ }
14826
+ function fractionDigits(value) {
14827
+ if (!("fractionalSeconds" in value) || value.fractionalSeconds === void 0) return void 0;
14828
+ const digits = FRACTION_DIGITS.exec(value.raw)?.[1];
14829
+ return digits === void 0 || digits === "" ? void 0 : digits;
14830
+ }
14831
+ function millisecondOf(digits) {
14832
+ return Number(`${digits}000`.slice(0, 3));
14833
+ }
14834
+ function isLeapYear(year) {
14835
+ return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
14836
+ }
14837
+ var MONTH_LENGTHS = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
14838
+ var MAX_OFFSET_MINUTES = 14 * 60 + 59;
14839
+ function longestDayOfMonth(year, month) {
14840
+ if (month === 2) return year === void 0 || isLeapYear(year) ? 29 : 28;
14841
+ return MONTH_LENGTHS[month - 1] ?? 31;
14842
+ }
14843
+ function withinBounds(value, low, high) {
14844
+ return value === void 0 || Number.isInteger(value) && value >= low && value <= high;
14845
+ }
14846
+ function statesARealCalendarDate(parts) {
14847
+ if (!withinBounds(parts.year, 0, 9999)) return false;
14848
+ if (!withinBounds(parts.month, 1, 12)) return false;
14849
+ if (!withinBounds(parts.hour, 0, 23)) return false;
14850
+ if (!withinBounds(parts.minute, 0, 59)) return false;
14851
+ if (!withinBounds(parts.second, 0, 59)) return false;
14852
+ if (!withinBounds(parts.offsetMinutes, -MAX_OFFSET_MINUTES, MAX_OFFSET_MINUTES)) return false;
14853
+ if (parts.month === void 0) return withinBounds(parts.day, 1, 31);
14854
+ return withinBounds(parts.day, 1, longestDayOfMonth(parts.year, parts.month));
14855
+ }
14856
+ function renderTime(parts, digits) {
14857
+ if (parts.hour === void 0) return void 0;
14858
+ let out = pad(parts.hour, 2);
14859
+ if (parts.minute === void 0) return out;
14860
+ out += `:${pad(parts.minute, 2)}`;
14861
+ if (parts.second === void 0) return out;
14862
+ out += `:${pad(parts.second, 2)}`;
14863
+ return digits === void 0 ? out : `${out}.${digits}`;
14864
+ }
14865
+ function renderBody(parts, digits) {
14866
+ const time = renderTime(parts, digits);
14867
+ if (parts.year === void 0) return time;
14868
+ let out = pad(parts.year, 4);
14869
+ if (parts.month !== void 0) {
14870
+ out += `-${pad(parts.month, 2)}`;
14871
+ if (parts.day !== void 0) out += `-${pad(parts.day, 2)}`;
14872
+ }
14873
+ return time === void 0 ? out : `${out}T${time}`;
14874
+ }
14875
+ function renderOffset(offsetMinutes) {
14876
+ if (offsetMinutes === void 0) return "";
14877
+ if (offsetMinutes === 0) return "Z";
14878
+ const total = Math.abs(offsetMinutes);
14879
+ const sign = offsetMinutes < 0 ? "-" : "+";
14880
+ return `${sign}${pad(Math.trunc(total / 60), 2)}:${pad(total % 60, 2)}`;
14881
+ }
14882
+ function toObject(value) {
14883
+ if (value === void 0 || value === null || !value.valid) return void 0;
14884
+ const year = "year" in value ? value.year : void 0;
14885
+ const month = "month" in value ? value.month : void 0;
14886
+ const day = "day" in value ? value.day : void 0;
14887
+ const hour = "hours" in value ? value.hours : void 0;
14888
+ const minute = "minutes" in value ? value.minutes : void 0;
14889
+ const second = "seconds" in value ? value.seconds : void 0;
14890
+ const digits = fractionDigits(value);
14891
+ const rawOffset = "offsetMinutes" in value ? value.offsetMinutes : void 0;
14892
+ const offsetMinutes = rawOffset === 0 ? 0 : rawOffset;
14893
+ const parts = {
14894
+ ...year !== void 0 ? { year } : {},
14895
+ ...month !== void 0 ? { month } : {},
14896
+ ...day !== void 0 ? { day } : {},
14897
+ ...hour !== void 0 ? { hour } : {},
14898
+ ...minute !== void 0 ? { minute } : {},
14899
+ ...second !== void 0 ? { second } : {},
14900
+ ...digits !== void 0 ? { millisecond: millisecondOf(digits) } : {},
14901
+ ...offsetMinutes !== void 0 ? { offsetMinutes } : {}
14902
+ };
14903
+ if (Object.keys(parts).length === 0) return void 0;
14904
+ if (!statesARealCalendarDate(parts)) return void 0;
14905
+ return Object.freeze(parts);
14906
+ }
14907
+ function toISO(value) {
14908
+ if (value === void 0 || value === null) return void 0;
14909
+ const parts = toObject(value);
14910
+ if (parts === void 0) return void 0;
14911
+ const body = renderBody(parts, fractionDigits(value));
14912
+ return body === void 0 ? void 0 : `${body}${renderOffset(parts.offsetMinutes)}`;
14913
+ }
14914
+ function toDate(value, options) {
14915
+ if (value === void 0 || value === null) return void 0;
14916
+ const parts = toObject(value);
14917
+ if (parts?.year === void 0) return void 0;
14918
+ const offsetMinutes = parts.offsetMinutes ?? options?.assumeOffsetMinutes;
14919
+ if (offsetMinutes === void 0 || !Number.isFinite(offsetMinutes)) return void 0;
14920
+ const utc = /* @__PURE__ */ new Date(0);
14921
+ utc.setUTCFullYear(parts.year, (parts.month ?? 1) - 1, parts.day ?? 1);
14922
+ utc.setUTCHours(parts.hour ?? 0, parts.minute ?? 0, parts.second ?? 0, parts.millisecond ?? 0);
14923
+ const instant = new Date(utc.getTime() - offsetMinutes * 6e4);
14924
+ return Number.isNaN(instant.getTime()) ? void 0 : instant;
14925
+ }
14926
+ var UNDEFINED_LENGTH4 = 4294967295;
13942
14927
  var NULL_PAD_VRS = /* @__PURE__ */ new Set(["UI", "OB", "OW", "OF", "OD", "OL", "OV", "UN"]);
13943
14928
  function padValue(value, vr) {
13944
14929
  if (value.length % 2 === 0) return buffer.Buffer.from(value);
13945
- const pad = NULL_PAD_VRS.has(vr) ? 0 : 32;
13946
- return buffer.Buffer.concat([value, buffer.Buffer.from([pad])]);
14930
+ const pad2 = NULL_PAD_VRS.has(vr) ? 0 : 32;
14931
+ return buffer.Buffer.concat([value, buffer.Buffer.from([pad2])]);
13947
14932
  }
13948
14933
  function uint16(n, littleEndian) {
13949
14934
  const buf = buffer.Buffer.alloc(2);
@@ -13958,15 +14943,15 @@ function uint32(n, littleEndian) {
13958
14943
  return buf;
13959
14944
  }
13960
14945
  function isFullSpanElement(el, encoding) {
13961
- if (el.length === UNDEFINED_LENGTH3) return true;
14946
+ if (el.length === UNDEFINED_LENGTH4) return true;
13962
14947
  return el.vr === "SQ" && encoding !== "implicit";
13963
14948
  }
13964
- function encodeDatasetElement(el, encoding) {
14949
+ function encodeDatasetElement(el, encoding, rawBytes = el.rawBytes) {
13965
14950
  if (isFullSpanElement(el, encoding)) {
13966
- return buffer.Buffer.from(el.rawBytes);
14951
+ return buffer.Buffer.from(rawBytes);
13967
14952
  }
13968
14953
  const { group, element } = splitTag(el.tag);
13969
- const value = padValue(el.rawBytes, el.vr);
14954
+ const value = padValue(rawBytes, el.vr);
13970
14955
  if (encoding === "implicit") {
13971
14956
  return buffer.Buffer.concat([
13972
14957
  uint16(group, true),
@@ -13975,49 +14960,473 @@ function encodeDatasetElement(el, encoding) {
13975
14960
  value
13976
14961
  ]);
13977
14962
  }
13978
- const littleEndian = encoding === "explicitLE";
13979
- const vrBuf = buffer.Buffer.from(el.vr, "ascii");
13980
- if (LONG_FORM_VRS.has(el.vr) || !isRecognizedVr(el.vr)) {
13981
- return buffer.Buffer.concat([
13982
- uint16(group, littleEndian),
13983
- uint16(element, littleEndian),
13984
- vrBuf,
13985
- buffer.Buffer.from([0, 0]),
13986
- // reserved (PS3.5 §7.1.2)
13987
- uint32(value.length, littleEndian),
13988
- value
13989
- ]);
14963
+ const littleEndian = encoding === "explicitLE";
14964
+ const vrBuf = buffer.Buffer.from(el.vr, "ascii");
14965
+ if (LONG_FORM_VRS.has(el.vr) || !isRecognizedVr(el.vr)) {
14966
+ return buffer.Buffer.concat([
14967
+ uint16(group, littleEndian),
14968
+ uint16(element, littleEndian),
14969
+ vrBuf,
14970
+ buffer.Buffer.from([0, 0]),
14971
+ // reserved (PS3.5 §7.1.2)
14972
+ uint32(value.length, littleEndian),
14973
+ value
14974
+ ]);
14975
+ }
14976
+ return buffer.Buffer.concat([
14977
+ uint16(group, littleEndian),
14978
+ uint16(element, littleEndian),
14979
+ vrBuf,
14980
+ uint16(value.length, littleEndian),
14981
+ value
14982
+ ]);
14983
+ }
14984
+
14985
+ // src/serialize/errors.ts
14986
+ var SERIALIZE_ERROR_CODES = {
14987
+ MISSING_TRANSFER_SYNTAX: "MISSING_TRANSFER_SYNTAX",
14988
+ UNSUPPORTED_TRANSFER_SYNTAX: "UNSUPPORTED_TRANSFER_SYNTAX",
14989
+ INVALID_ENCAPSULATED_PIXEL_DATA: "INVALID_ENCAPSULATED_PIXEL_DATA",
14990
+ DIRECTORY_OFFSET_UNRESOLVED: "DIRECTORY_OFFSET_UNRESOLVED",
14991
+ DIRECTORY_OFFSET_DEFLATED: "DIRECTORY_OFFSET_DEFLATED"
14992
+ };
14993
+ var DicomSerializeError = class extends Error {
14994
+ code;
14995
+ /**
14996
+ * Construct a new `DicomSerializeError`. The `message` MUST be built only
14997
+ * from structural facts (never a decoded attribute value) so the error is
14998
+ * always safe to log.
14999
+ *
15000
+ * @internal
15001
+ */
15002
+ constructor(code, message) {
15003
+ super(`[${code}] ${message}`);
15004
+ this.name = "DicomSerializeError";
15005
+ this.code = code;
15006
+ }
15007
+ };
15008
+ var UNDEFINED_LENGTH5 = 4294967295;
15009
+ var ITEM2 = 4294893568;
15010
+ var ITEM_DELIMITATION = 4294893581;
15011
+ var SEQUENCE_DELIMITATION2 = 4294893789;
15012
+ var PIXEL_DATA2 = "7FE00010";
15013
+ var MARKER_LENGTH = 8;
15014
+ var IMPLICIT_LE = { encoding: "implicit", littleEndian: true, explicitVr: false };
15015
+ var SYNTAX = {
15016
+ implicit: IMPLICIT_LE,
15017
+ explicitLE: { encoding: "explicitLE", littleEndian: true, explicitVr: true },
15018
+ explicitBE: { encoding: "explicitBE", littleEndian: false, explicitVr: true }
15019
+ };
15020
+ function readUint16(buf, offset, littleEndian) {
15021
+ return littleEndian ? buf.readUInt16LE(offset) : buf.readUInt16BE(offset);
15022
+ }
15023
+ function readUint32(buf, offset, littleEndian) {
15024
+ return littleEndian ? buf.readUInt32LE(offset) : buf.readUInt32BE(offset);
15025
+ }
15026
+ function readTagNumber(buf, offset, littleEndian) {
15027
+ return readUint16(buf, offset, littleEndian) * 65536 + readUint16(buf, offset + 2, littleEndian);
15028
+ }
15029
+ function isMarker(tagNumber2) {
15030
+ return tagNumber2 >= 4294836224 && tagNumber2 < 4294901760;
15031
+ }
15032
+ function appendAll(target, source) {
15033
+ for (const part of source) target.push(part);
15034
+ }
15035
+ function tagNumber(tag) {
15036
+ const { group, element } = splitTag(tag);
15037
+ return group * 65536 + element;
15038
+ }
15039
+ function tagOf(tagNumberValue) {
15040
+ return tagNumberValue.toString(16).padStart(8, "0").toUpperCase();
15041
+ }
15042
+ function isImplicitSequence(tagNumberValue) {
15043
+ const group = Math.floor(tagNumberValue / 65536);
15044
+ if (group % 2 === 1) return false;
15045
+ const tag = tagOf(tagNumberValue);
15046
+ const entry = TAGS[tag] ?? matchRepeatingGroup(tag);
15047
+ return entry?.vr[0] === "SQ";
15048
+ }
15049
+ function readElementHeader(buf, p, stop, syntax) {
15050
+ if (p + MARKER_LENGTH > stop) return void 0;
15051
+ const le = syntax.littleEndian;
15052
+ const tag = readTagNumber(buf, p, le);
15053
+ if (!syntax.explicitVr || isMarker(tag)) {
15054
+ return { tag, headerLength: MARKER_LENGTH, length: readUint32(buf, p + 4, le), vr: void 0 };
15055
+ }
15056
+ const vr = buf.toString("ascii", p + 4, p + 6);
15057
+ if (LONG_FORM_VRS.has(vr) || !isRecognizedVr(vr)) {
15058
+ if (p + 12 > stop) return void 0;
15059
+ return { tag, headerLength: 12, length: readUint32(buf, p + 8, le), vr };
15060
+ }
15061
+ return { tag, headerLength: MARKER_LENGTH, length: readUint16(buf, p + 6, le), vr };
15062
+ }
15063
+ function isSequence(header, syntax) {
15064
+ return syntax.explicitVr ? header.vr === "SQ" : isImplicitSequence(header.tag);
15065
+ }
15066
+ function verbatim(buf, start, end) {
15067
+ return { parts: [buf.subarray(start, end)], changed: false, end };
15068
+ }
15069
+ function fragmentsClose(buf, start, littleEndian) {
15070
+ let p = start;
15071
+ while (p + MARKER_LENGTH <= buf.length) {
15072
+ const tag = readTagNumber(buf, p, littleEndian);
15073
+ p += MARKER_LENGTH;
15074
+ if (tag === SEQUENCE_DELIMITATION2) return p === buf.length;
15075
+ if (tag !== ITEM2) return false;
15076
+ p += readUint32(buf, p - 4, littleEndian);
15077
+ }
15078
+ return false;
15079
+ }
15080
+ function closesItself(el, syntax, depth) {
15081
+ const raw = el.rawBytes;
15082
+ const valueStart = syntax.explicitVr ? 12 : MARKER_LENGTH;
15083
+ if (el.cp246Promoted === true || el.vr === "SQ") {
15084
+ if (depth > NESTING_DEPTH_LIMIT) return false;
15085
+ const itemSyntax = el.cp246Promoted === true ? IMPLICIT_LE : syntax;
15086
+ const walked = walkItems2(raw, valueStart, void 0, raw.length, itemSyntax, depth, el.items);
15087
+ return walked?.end === raw.length;
15088
+ }
15089
+ return el.tag === PIXEL_DATA2 && fragmentsClose(raw, valueStart, syntax.littleEndian);
15090
+ }
15091
+ function walkElement(buf, p, stop, syntax, depth, item) {
15092
+ const header = readElementHeader(buf, p, stop, syntax);
15093
+ if (header === void 0) return void 0;
15094
+ const model = item.get(tagOf(header.tag));
15095
+ if (model === void 0) return void 0;
15096
+ const valueStart = p + header.headerLength;
15097
+ const undefinedLength = header.length === UNDEFINED_LENGTH5;
15098
+ const items = depth < NESTING_DEPTH_LIMIT && isSequence(header, syntax) && model.vr === "SQ" ? model.items : void 0;
15099
+ let walked;
15100
+ if (items !== void 0) {
15101
+ const definedEnd = undefinedLength ? void 0 : valueStart + header.length;
15102
+ walked = definedEnd !== void 0 && definedEnd > stop ? void 0 : walkItems2(buf, valueStart, definedEnd, stop, syntax, depth + 1, items);
15103
+ } else {
15104
+ const end = undefinedLength ? p + model.rawBytes.length : valueStart + header.length;
15105
+ walked = end < valueStart || end > stop ? void 0 : verbatim(buf, valueStart, end);
15106
+ }
15107
+ if (walked === void 0) return void 0;
15108
+ const span = {
15109
+ tag: header.tag,
15110
+ start: p,
15111
+ valueStart,
15112
+ undefinedLength,
15113
+ descended: items !== void 0,
15114
+ model
15115
+ };
15116
+ if (!walked.changed) return { ...span, ...verbatim(buf, p, walked.end) };
15117
+ const parts = [buf.subarray(p, valueStart)];
15118
+ appendAll(parts, walked.parts);
15119
+ return { ...span, parts, changed: true, end: walked.end };
15120
+ }
15121
+ function agrees(buf, span, encoding) {
15122
+ const model = span.model;
15123
+ const valueOnly = !isFullSpanElement(model, encoding);
15124
+ const bytes = buf.subarray(valueOnly ? span.valueStart : span.start, span.end);
15125
+ if (span.descended) return model.rawBytes.length === bytes.length;
15126
+ if (model.rawBytes.equals(bytes)) return true;
15127
+ return valueOnly && bytes.length === model.rawBytes.length + 1 && padValue(model.rawBytes, model.vr).equals(bytes);
15128
+ }
15129
+ function walkDataSet(buf, start, definedEnd, limit, syntax, depth, model, placed) {
15130
+ const stop = definedEnd ?? limit;
15131
+ const spans = [];
15132
+ let delimiter;
15133
+ let p = start;
15134
+ while (definedEnd === void 0 || p < definedEnd) {
15135
+ if (p + MARKER_LENGTH > stop) return void 0;
15136
+ const tag = readTagNumber(buf, p, syntax.littleEndian);
15137
+ if (isMarker(tag)) {
15138
+ if (definedEnd !== void 0 || tag !== ITEM_DELIMITATION) return void 0;
15139
+ delimiter = buf.subarray(p, p + MARKER_LENGTH);
15140
+ p += MARKER_LENGTH;
15141
+ break;
15142
+ }
15143
+ const span = walkElement(buf, p, stop, syntax, depth, model);
15144
+ if (span === void 0) return void 0;
15145
+ spans.push(span);
15146
+ p = span.end;
15147
+ }
15148
+ const last = /* @__PURE__ */ new Map();
15149
+ for (const span of spans) last.set(span.tag, span);
15150
+ for (const el of model.elements()) {
15151
+ if (!last.has(tagNumber(el.tag)) && splitTag(el.tag).element !== 0) return void 0;
15152
+ }
15153
+ const closed = [];
15154
+ const open = [];
15155
+ for (const span of spans) {
15156
+ if (last.get(span.tag) !== span) {
15157
+ if (span.undefinedLength) return void 0;
15158
+ closed.push({
15159
+ tag: span.tag,
15160
+ start: span.start,
15161
+ valueStart: span.valueStart,
15162
+ ...verbatim(buf, span.start, span.end)
15163
+ });
15164
+ } else if (!agrees(buf, span, syntax.encoding)) {
15165
+ return void 0;
15166
+ } else if (span.descended || !isFullSpanElement(span.model, syntax.encoding) || closesItself(span.model, syntax, depth + 1)) {
15167
+ closed.push(span);
15168
+ } else {
15169
+ open.push(span);
15170
+ }
15171
+ }
15172
+ const ordered = [...closed.sort((a, b) => a.tag - b.tag), ...open];
15173
+ if (placed !== void 0) {
15174
+ let at3 = start;
15175
+ for (const span of ordered) {
15176
+ const length = span.end - span.start;
15177
+ placed.push({
15178
+ tag: span.tag,
15179
+ start: at3,
15180
+ valueStart: at3 + (span.valueStart - span.start),
15181
+ end: at3 + length
15182
+ });
15183
+ at3 += length;
15184
+ }
15185
+ }
15186
+ const moved = ordered.some((span, i) => span.start !== spans[i]?.start);
15187
+ if (!moved && !ordered.some((span) => span.changed)) return verbatim(buf, start, p);
15188
+ const parts = [];
15189
+ for (const span of ordered) appendAll(parts, span.parts);
15190
+ if (delimiter !== void 0) parts.push(delimiter);
15191
+ return { parts, changed: true, end: p };
15192
+ }
15193
+ function walkItems2(buf, start, definedEnd, limit, syntax, depth, items, placements) {
15194
+ if (items === void 0) return void 0;
15195
+ const stop = definedEnd ?? limit;
15196
+ const le = syntax.littleEndian;
15197
+ const parts = [];
15198
+ let changed = false;
15199
+ let index = 0;
15200
+ let p = start;
15201
+ while (definedEnd === void 0 || p < definedEnd) {
15202
+ if (p + MARKER_LENGTH > stop) return void 0;
15203
+ const tag = readTagNumber(buf, p, le);
15204
+ if (tag === SEQUENCE_DELIMITATION2 && definedEnd === void 0) {
15205
+ parts.push(buf.subarray(p, p + MARKER_LENGTH));
15206
+ p += MARKER_LENGTH;
15207
+ break;
15208
+ }
15209
+ const model = items[index];
15210
+ if (tag !== ITEM2 || model === void 0) return void 0;
15211
+ const length = readUint32(buf, p + 4, le);
15212
+ const bodyStart = p + MARKER_LENGTH;
15213
+ const placed = [];
15214
+ const collect = placements !== void 0 ? placed : void 0;
15215
+ let item;
15216
+ if (length === UNDEFINED_LENGTH5) {
15217
+ item = walkDataSet(buf, bodyStart, void 0, stop, syntax, depth, model, collect);
15218
+ } else if (bodyStart + length <= stop) {
15219
+ item = walkDataSet(buf, bodyStart, bodyStart + length, stop, syntax, depth, model, collect);
15220
+ }
15221
+ if (item === void 0) return void 0;
15222
+ placements?.push({ itemStart: p, elements: placed });
15223
+ parts.push(buf.subarray(p, bodyStart));
15224
+ appendAll(parts, item.parts);
15225
+ changed ||= item.changed;
15226
+ p = item.end;
15227
+ index += 1;
15228
+ }
15229
+ if (index !== items.length) return void 0;
15230
+ if (!changed) return verbatim(buf, start, p);
15231
+ return { parts, changed, end: p };
15232
+ }
15233
+ function walkSequence(el, syntax, placements) {
15234
+ const raw = el.rawBytes;
15235
+ let valueStart = 0;
15236
+ let definedEnd = raw.length;
15237
+ if (isFullSpanElement(el, syntax.encoding)) {
15238
+ const header = readElementHeader(raw, 0, raw.length, syntax);
15239
+ if (header === void 0 || syntax.explicitVr && header.vr !== "SQ") return void 0;
15240
+ valueStart = header.headerLength;
15241
+ definedEnd = header.length === UNDEFINED_LENGTH5 ? void 0 : valueStart + header.length;
15242
+ }
15243
+ const walked = walkItems2(
15244
+ raw,
15245
+ valueStart,
15246
+ definedEnd,
15247
+ raw.length,
15248
+ syntax,
15249
+ 1,
15250
+ el.items,
15251
+ placements
15252
+ );
15253
+ if (walked?.end !== raw.length) return void 0;
15254
+ if (!walked.changed) return walked;
15255
+ return { parts: [raw.subarray(0, valueStart), ...walked.parts], changed: true, end: raw.length };
15256
+ }
15257
+ function emissionOf(el, encoding, place = false) {
15258
+ const syntax = SYNTAX[encoding];
15259
+ const valueOnly = !isFullSpanElement(el, encoding);
15260
+ if (el.vr !== "SQ" || el.cp246Promoted === true) {
15261
+ return { rawBytes: void 0, closed: valueOnly || closesItself(el, syntax, 1) };
15262
+ }
15263
+ const placements = place ? [] : void 0;
15264
+ const walked = walkSequence(el, syntax, placements);
15265
+ if (walked === void 0) return { rawBytes: void 0, closed: valueOnly };
15266
+ return {
15267
+ rawBytes: walked.changed ? buffer.Buffer.concat(walked.parts) : void 0,
15268
+ closed: true,
15269
+ ...placements !== void 0 ? { placements } : {}
15270
+ };
15271
+ }
15272
+
15273
+ // src/serialize/directory.ts
15274
+ var PLACED_TAGS = /* @__PURE__ */ new Set([
15275
+ DIRECTORY_TAGS.FIRST_ROOT_RECORD,
15276
+ DIRECTORY_TAGS.LAST_ROOT_RECORD,
15277
+ DIRECTORY_TAGS.RECORD_SEQUENCE
15278
+ ]);
15279
+ var RECORD_OFFSET_TAGS = /* @__PURE__ */ new Set([
15280
+ tagNumber(DIRECTORY_TAGS.NEXT_RECORD),
15281
+ tagNumber(DIRECTORY_TAGS.LOWER_LEVEL)
15282
+ ]);
15283
+ var IMPLICIT_HEADER_LENGTH = 8;
15284
+ var UNRESOLVED_MESSAGE = "The Dataset is a DICOMDIR and carries a Directory Record offset attribute that the writer cannot tie to a Directory Record the Dataset holds: a non-zero offset that names no Item of the Directory Record Sequence, or a value that is not one unsigned integer of four bytes. Written stale it would name the wrong bytes, and written as zero it would silently prune the tree, so nothing is written.";
15285
+ var DEFLATED_MESSAGE = "The Dataset is a DICOMDIR to be written in Deflated Explicit VR Little Endian and carries a non-zero Directory Record offset. A position inside a deflated stream names no Item a reader can seek to, so nothing is written. A DICOMDIR File is to be written in Explicit VR Little Endian.";
15286
+ function refuse(deflated) {
15287
+ throw deflated ? new DicomSerializeError(SERIALIZE_ERROR_CODES.DIRECTORY_OFFSET_DEFLATED, DEFLATED_MESSAGE) : new DicomSerializeError(
15288
+ SERIALIZE_ERROR_CODES.DIRECTORY_OFFSET_UNRESOLVED,
15289
+ UNRESOLVED_MESSAGE
15290
+ );
15291
+ }
15292
+ function readValue(body, at3, littleEndian) {
15293
+ const value = littleEndian ? body.readUInt32LE(at3) : body.readUInt32BE(at3);
15294
+ return value === 0 ? { kind: "zero" } : { kind: "offset", value };
15295
+ }
15296
+ function rewriteDirectoryOffsets(ds, body, placed, encoding, bodyFileOffset, deflated) {
15297
+ const littleEndian = encoding !== "explicitBE";
15298
+ const { items, byFileOffset } = directoryRecords(ds);
15299
+ const sequence = placed.get(DIRECTORY_TAGS.RECORD_SEQUENCE);
15300
+ const placements = sequence?.placements;
15301
+ const slots = [];
15302
+ for (const tag of [DIRECTORY_TAGS.FIRST_ROOT_RECORD, DIRECTORY_TAGS.LAST_ROOT_RECORD]) {
15303
+ const root = placed.get(tag);
15304
+ if (root === void 0) continue;
15305
+ slots.push({ value: readOffsetValue(root.el), at: root.start + root.bytes.length - 4 });
15306
+ }
15307
+ const rawStart = sequence === void 0 ? 0 : sequence.start + (isFullSpanElement(sequence.el, encoding) ? 0 : IMPLICIT_HEADER_LENGTH);
15308
+ if (placements !== void 0) {
15309
+ for (const placement of placements) {
15310
+ for (const span of placement.elements) {
15311
+ if (!RECORD_OFFSET_TAGS.has(span.tag)) continue;
15312
+ const at3 = rawStart + span.valueStart;
15313
+ const value = span.end - span.valueStart === 4 ? readValue(body, at3, littleEndian) : { kind: "malformed" };
15314
+ slots.push({ value, at: at3 });
15315
+ }
15316
+ }
15317
+ } else {
15318
+ for (const item of items) {
15319
+ for (const tag of [DIRECTORY_TAGS.NEXT_RECORD, DIRECTORY_TAGS.LOWER_LEVEL]) {
15320
+ const el = item.get(tag);
15321
+ if (el !== void 0) slots.push({ value: readOffsetValue(el), at: void 0 });
15322
+ }
15323
+ }
15324
+ }
15325
+ const patches = [];
15326
+ for (const slot of slots) {
15327
+ if (slot.value.kind === "zero") continue;
15328
+ if (slot.value.kind === "malformed" || deflated) refuse(deflated);
15329
+ const target = byFileOffset.get(slot.value.value);
15330
+ const record = target === void 0 ? void 0 : placements?.[target];
15331
+ if (record === void 0 || slot.at === void 0) refuse(false);
15332
+ patches.push({ at: slot.at, value: bodyFileOffset + rawStart + record.itemStart });
15333
+ }
15334
+ for (const patch of patches) {
15335
+ if (littleEndian) body.writeUInt32LE(patch.value, patch.at);
15336
+ else body.writeUInt32BE(patch.value, patch.at);
15337
+ }
15338
+ }
15339
+ var PIXEL_DATA3 = "7FE00010";
15340
+ var FLOAT_PIXEL_DATA = "7FE00008";
15341
+ var DOUBLE_FLOAT_PIXEL_DATA = "7FE00009";
15342
+ var UNDEFINED_LENGTH6 = 4294967295;
15343
+ var ELEMENT_HEADER_LENGTH2 = 12;
15344
+ var ITEM_HEADER_LENGTH2 = 8;
15345
+ var ITEM_GROUP2 = 65534;
15346
+ var ITEM3 = 57344;
15347
+ var SEQUENCE_DELIMITATION3 = 57565;
15348
+ var PIXEL_DATA_HEADER = buffer.Buffer.from([
15349
+ 224,
15350
+ 127,
15351
+ 16,
15352
+ 0,
15353
+ 79,
15354
+ 66,
15355
+ 0,
15356
+ 0,
15357
+ 255,
15358
+ 255,
15359
+ 255,
15360
+ 255
15361
+ ]);
15362
+ var SEQUENCE_DELIMITATION_ITEM = buffer.Buffer.from([
15363
+ 254,
15364
+ 255,
15365
+ 221,
15366
+ 224,
15367
+ 0,
15368
+ 0,
15369
+ 0,
15370
+ 0
15371
+ ]);
15372
+ var MESSAGES = {
15373
+ absent: "A PS3.5 section A.4 Transfer Syntax needs Pixel Data (7FE0,0010) in the top-level Data Set, and it has none.",
15374
+ float: "A PS3.5 section A.4 Transfer Syntax cannot carry Float Pixel Data (7FE0,0008) or Double Float Pixel Data (7FE0,0009) in the top-level Data Set.",
15375
+ native: "Top-level Pixel Data (7FE0,0010) under a PS3.5 section A.4 Transfer Syntax has a defined Value Length (Native Format); it must be Encapsulated Format.",
15376
+ notFragmentSpan: "Top-level Pixel Data (7FE0,0010) is not held as an undefined-length (7FE0,0010) span, so it is not a fragment stream the writer can emit.",
15377
+ notItem: "The top-level Pixel Data fragment stream holds something other than an Item (FFFE,E000) of defined Item Length before its Sequence Delimitation Item.",
15378
+ notDelimited: "The top-level Pixel Data fragment stream does not end on a Sequence Delimitation Item (FFFE,E0DD); the writer does not append one to a stream that may be short.",
15379
+ afterDelimiter: "The top-level Pixel Data span holds bytes after its Sequence Delimitation Item (FFFE,E0DD).",
15380
+ oddLength: "An Item in the top-level Pixel Data fragment stream has an odd Item Length; PS3.5 section A.4 requires an even number of bytes.",
15381
+ emptyFragment: "A fragment Item after the Basic Offset Table in the top-level Pixel Data fragment stream has Item Length zero; PS3.5 section A.4 requires two bytes or more.",
15382
+ noBasicOffsetTable: "The top-level Pixel Data fragment stream holds no Item, so it has no Basic Offset Table Item.",
15383
+ noFragment: "The top-level Pixel Data fragment stream holds a Basic Offset Table Item and no fragment Item."
15384
+ };
15385
+ function refuse2(reason) {
15386
+ throw new DicomSerializeError(
15387
+ SERIALIZE_ERROR_CODES.INVALID_ENCAPSULATED_PIXEL_DATA,
15388
+ MESSAGES[reason]
15389
+ );
15390
+ }
15391
+ function itemStreamEnd(raw) {
15392
+ let at3 = ELEMENT_HEADER_LENGTH2;
15393
+ let items = 0;
15394
+ for (; ; ) {
15395
+ if (at3 + ITEM_HEADER_LENGTH2 > raw.length) refuse2("notDelimited");
15396
+ const group = raw.readUInt16LE(at3);
15397
+ const element = raw.readUInt16LE(at3 + 2);
15398
+ const length = raw.readUInt32LE(at3 + 4);
15399
+ if (group === ITEM_GROUP2 && element === SEQUENCE_DELIMITATION3) break;
15400
+ if (group !== ITEM_GROUP2 || element !== ITEM3 || length === UNDEFINED_LENGTH6) refuse2("notItem");
15401
+ if (length % 2 === 1) refuse2("oddLength");
15402
+ if (length === 0 && items > 0) refuse2("emptyFragment");
15403
+ if (at3 + ITEM_HEADER_LENGTH2 + length > raw.length) refuse2("notDelimited");
15404
+ at3 += ITEM_HEADER_LENGTH2 + length;
15405
+ items += 1;
15406
+ }
15407
+ if (at3 + ITEM_HEADER_LENGTH2 !== raw.length) refuse2("afterDelimiter");
15408
+ if (items === 0) refuse2("noBasicOffsetTable");
15409
+ if (items === 1) refuse2("noFragment");
15410
+ return at3;
15411
+ }
15412
+ function encapsulatedPixelData(ds) {
15413
+ if (ds.has(FLOAT_PIXEL_DATA) || ds.has(DOUBLE_FLOAT_PIXEL_DATA)) refuse2("float");
15414
+ const el = ds.get(PIXEL_DATA3);
15415
+ if (el === void 0) refuse2("absent");
15416
+ if (el.length !== UNDEFINED_LENGTH6) refuse2("native");
15417
+ const raw = el.rawBytes;
15418
+ if (raw.length < ELEMENT_HEADER_LENGTH2 || raw.readUInt16LE(0) !== 32736 || raw.readUInt16LE(2) !== 16 || raw.readUInt32LE(8) !== UNDEFINED_LENGTH6) {
15419
+ refuse2("notFragmentSpan");
13990
15420
  }
15421
+ const end = itemStreamEnd(raw);
13991
15422
  return buffer.Buffer.concat([
13992
- uint16(group, littleEndian),
13993
- uint16(element, littleEndian),
13994
- vrBuf,
13995
- uint16(value.length, littleEndian),
13996
- value
15423
+ PIXEL_DATA_HEADER,
15424
+ raw.subarray(ELEMENT_HEADER_LENGTH2, end),
15425
+ SEQUENCE_DELIMITATION_ITEM
13997
15426
  ]);
13998
15427
  }
13999
-
14000
- // src/serialize/errors.ts
14001
- var SERIALIZE_ERROR_CODES = {
14002
- MISSING_TRANSFER_SYNTAX: "MISSING_TRANSFER_SYNTAX",
14003
- UNSUPPORTED_TRANSFER_SYNTAX: "UNSUPPORTED_TRANSFER_SYNTAX"
14004
- };
14005
- var DicomSerializeError = class extends Error {
14006
- code;
14007
- /**
14008
- * Construct a new `DicomSerializeError`. The `message` MUST be built only
14009
- * from structural facts (never a decoded attribute value) so the error is
14010
- * always safe to log.
14011
- *
14012
- * @internal
14013
- */
14014
- constructor(code, message) {
14015
- super(`[${code}] ${message}`);
14016
- this.name = "DicomSerializeError";
14017
- this.code = code;
14018
- }
14019
- };
14020
15428
  var COSYTE_IMPLEMENTATION_CLASS_UID = "2.25.200853462534740285303254730069375064698";
15429
+ var COSYTE_IMPLEMENTATION_VERSION_NAME = "COSYTE_DICOM";
14021
15430
  var DEFAULT_FILE_META_VERSION = buffer.Buffer.from([0, 1]);
14022
15431
  var TAG_GROUP_LENGTH = "00020000";
14023
15432
  function encodeMetaElement(tag, vr, rawValue) {
@@ -14089,27 +15498,54 @@ function encodeFileMeta(fileMeta) {
14089
15498
  }
14090
15499
 
14091
15500
  // src/serialize/serialize.ts
15501
+ var RECORD_SEQUENCE = DIRECTORY_TAGS.RECORD_SEQUENCE;
14092
15502
  var TS_IMPLICIT_LE = "1.2.840.10008.1.2";
14093
15503
  var TS_EXPLICIT_LE = "1.2.840.10008.1.2.1";
14094
15504
  var TS_EXPLICIT_BE = "1.2.840.10008.1.2.2";
14095
- var TS_DEFLATED_LE = "1.2.840.10008.1.2.1.99";
15505
+ var TS_DEFLATED_LE2 = "1.2.840.10008.1.2.1.99";
14096
15506
  var BODY_ENCODING = {
14097
15507
  [TS_IMPLICIT_LE]: "implicit",
14098
15508
  [TS_EXPLICIT_LE]: "explicitLE",
14099
15509
  [TS_EXPLICIT_BE]: "explicitBE",
14100
15510
  // Deflated TS body is Explicit VR LE before compression (PS3.5 Annex A.5).
14101
- [TS_DEFLATED_LE]: "explicitLE"
15511
+ [TS_DEFLATED_LE2]: "explicitLE"
14102
15512
  };
15513
+ var ENCAPSULATED_SYNTAXES = new Set(ENCAPSULATED_TRANSFER_SYNTAX_UIDS);
14103
15514
  function part10Preamble() {
14104
15515
  return buffer.Buffer.concat([buffer.Buffer.alloc(128, 0), buffer.Buffer.from("DICM", "ascii")]);
14105
15516
  }
14106
- function encodeBody(ds, encoding) {
14107
- const parts = [];
14108
- for (const el of ds.elements()) {
14109
- if (splitTag(el.tag).element === 0) continue;
14110
- parts.push(encodeDatasetElement(el, encoding));
15517
+ function encodeBody(ds, encoding, pixelData, placed) {
15518
+ const kept = ds.elements().filter((el) => splitTag(el.tag).element !== 0);
15519
+ const closed = [];
15520
+ const open = [];
15521
+ for (const el of kept) {
15522
+ if (pixelData !== void 0 && el.tag === PIXEL_DATA3) {
15523
+ closed.push({ tag: tagNumber(el.tag), bytes: pixelData, el });
15524
+ continue;
15525
+ }
15526
+ const emission = emissionOf(el, encoding, placed !== void 0 && el.tag === RECORD_SEQUENCE);
15527
+ const bytes = encodeDatasetElement(el, encoding, emission.rawBytes);
15528
+ const entry = { tag: tagNumber(el.tag), bytes, el, placements: emission.placements };
15529
+ if (emission.closed) closed.push(entry);
15530
+ else open.push(entry);
14111
15531
  }
14112
- return buffer.Buffer.concat(parts);
15532
+ closed.sort((a, b) => a.tag - b.tag);
15533
+ const ordered = [...closed, ...open];
15534
+ if (placed !== void 0) {
15535
+ let start = 0;
15536
+ for (const entry of ordered) {
15537
+ if (PLACED_TAGS.has(entry.el.tag)) {
15538
+ placed.set(entry.el.tag, {
15539
+ el: entry.el,
15540
+ start,
15541
+ bytes: entry.bytes,
15542
+ placements: entry.placements
15543
+ });
15544
+ }
15545
+ start += entry.bytes.length;
15546
+ }
15547
+ }
15548
+ return buffer.Buffer.concat(ordered.map((entry) => entry.bytes));
14113
15549
  }
14114
15550
  function serializeDicom(ds) {
14115
15551
  const tsUid = ds.fileMeta?.transferSyntaxUID;
@@ -14119,18 +15555,26 @@ function serializeDicom(ds) {
14119
15555
  "Dataset has no File Meta Transfer Syntax UID to serialize under."
14120
15556
  );
14121
15557
  }
14122
- const encoding = BODY_ENCODING[tsUid];
15558
+ const encapsulated = ENCAPSULATED_SYNTAXES.has(tsUid);
15559
+ const encoding = encapsulated ? "explicitLE" : BODY_ENCODING[tsUid];
14123
15560
  if (encoding === void 0) {
14124
15561
  throw new DicomSerializeError(
14125
15562
  SERIALIZE_ERROR_CODES.UNSUPPORTED_TRANSFER_SYNTAX,
14126
- `The Dataset's File Meta Transfer Syntax UID is not supported by the @cosyte/dicom v1 writer (supported: ${Object.keys(BODY_ENCODING).join(", ")}).`
15563
+ `The Dataset's File Meta Transfer Syntax UID is not supported by the @cosyte/dicom writer (supported: ${Object.keys(BODY_ENCODING).join(", ")}, and every PS3.5 2026c section A.4 encapsulation syntax).`
14127
15564
  );
14128
15565
  }
15566
+ const pixelData = encapsulated ? encapsulatedPixelData(ds) : void 0;
14129
15567
  const preamble = part10Preamble();
14130
15568
  const fileMeta = encodeFileMeta(ds.fileMeta);
14131
- const body = encodeBody(ds, encoding);
14132
- const datasetBytes = tsUid === TS_DEFLATED_LE ? zlib.deflateRawSync(body) : body;
14133
- return buffer.Buffer.concat([preamble, fileMeta, datasetBytes]);
15569
+ const deflated = tsUid === TS_DEFLATED_LE2;
15570
+ if (!isDicomdir(ds.fileMeta)) {
15571
+ const body2 = encodeBody(ds, encoding, pixelData);
15572
+ return buffer.Buffer.concat([preamble, fileMeta, deflated ? zlib.deflateRawSync(body2) : body2]);
15573
+ }
15574
+ const placed = /* @__PURE__ */ new Map();
15575
+ const body = encodeBody(ds, encoding, pixelData, placed);
15576
+ rewriteDirectoryOffsets(ds, body, placed, encoding, preamble.length + fileMeta.length, deflated);
15577
+ return buffer.Buffer.concat([preamble, fileMeta, deflated ? zlib.deflateRawSync(body) : body]);
14134
15578
  }
14135
15579
 
14136
15580
  // src/profiles/errors.ts
@@ -14476,26 +15920,26 @@ var ANNEX_E = Object.freeze({
14476
15920
  "00001001": Object.freeze({ tag: "00001001", keyword: "Requested SOP Instance UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
14477
15921
  "00020003": Object.freeze({ tag: "00020003", keyword: "Media Storage SOP Instance UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
14478
15922
  "00041511": Object.freeze({ tag: "00041511", keyword: "Referenced SOP Instance UID in File", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
14479
- "00080012": Object.freeze({ tag: "00080012", keyword: "Instance Creation Date", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14480
- "00080013": Object.freeze({ tag: "00080013", keyword: "Instance Creation Time", basicProfile: "X/Z/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
15923
+ "00080012": Object.freeze({ tag: "00080012", keyword: "Instance Creation Date", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
15924
+ "00080013": Object.freeze({ tag: "00080013", keyword: "Instance Creation Time", basicProfile: "X/Z/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14481
15925
  "00080014": Object.freeze({ tag: "00080014", keyword: "Instance Creator UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
14482
- "00080015": Object.freeze({ tag: "00080015", keyword: "Instance Coercion DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
15926
+ "00080015": Object.freeze({ tag: "00080015", keyword: "Instance Coercion DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14483
15927
  "00080017": Object.freeze({ tag: "00080017", keyword: "Acquisition UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
14484
15928
  "00080018": Object.freeze({ tag: "00080018", keyword: "SOP Instance UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
14485
15929
  "00080019": Object.freeze({ tag: "00080019", keyword: "Pyramid UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
14486
- "00080020": Object.freeze({ tag: "00080020", keyword: "Study Date", basicProfile: "Z", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14487
- "00080021": Object.freeze({ tag: "00080021", keyword: "Series Date", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14488
- "00080022": Object.freeze({ tag: "00080022", keyword: "Acquisition Date", basicProfile: "X/Z", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14489
- "00080023": Object.freeze({ tag: "00080023", keyword: "Content Date", basicProfile: "Z/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14490
- "00080024": Object.freeze({ tag: "00080024", keyword: "Overlay Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14491
- "00080025": Object.freeze({ tag: "00080025", keyword: "Curve Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14492
- "0008002A": Object.freeze({ tag: "0008002A", keyword: "Acquisition DateTime", basicProfile: "X/Z/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14493
- "00080030": Object.freeze({ tag: "00080030", keyword: "Study Time", basicProfile: "Z", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14494
- "00080031": Object.freeze({ tag: "00080031", keyword: "Series Time", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14495
- "00080032": Object.freeze({ tag: "00080032", keyword: "Acquisition Time", basicProfile: "X/Z", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14496
- "00080033": Object.freeze({ tag: "00080033", keyword: "Content Time", basicProfile: "Z/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14497
- "00080034": Object.freeze({ tag: "00080034", keyword: "Overlay Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14498
- "00080035": Object.freeze({ tag: "00080035", keyword: "Curve Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
15930
+ "00080020": Object.freeze({ tag: "00080020", keyword: "Study Date", basicProfile: "Z", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
15931
+ "00080021": Object.freeze({ tag: "00080021", keyword: "Series Date", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
15932
+ "00080022": Object.freeze({ tag: "00080022", keyword: "Acquisition Date", basicProfile: "X/Z", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
15933
+ "00080023": Object.freeze({ tag: "00080023", keyword: "Content Date", basicProfile: "Z/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
15934
+ "00080024": Object.freeze({ tag: "00080024", keyword: "Overlay Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
15935
+ "00080025": Object.freeze({ tag: "00080025", keyword: "Curve Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
15936
+ "0008002A": Object.freeze({ tag: "0008002A", keyword: "Acquisition DateTime", basicProfile: "X/Z/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
15937
+ "00080030": Object.freeze({ tag: "00080030", keyword: "Study Time", basicProfile: "Z", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
15938
+ "00080031": Object.freeze({ tag: "00080031", keyword: "Series Time", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
15939
+ "00080032": Object.freeze({ tag: "00080032", keyword: "Acquisition Time", basicProfile: "X/Z", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
15940
+ "00080033": Object.freeze({ tag: "00080033", keyword: "Content Time", basicProfile: "Z/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
15941
+ "00080034": Object.freeze({ tag: "00080034", keyword: "Overlay Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
15942
+ "00080035": Object.freeze({ tag: "00080035", keyword: "Curve Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14499
15943
  "00080050": Object.freeze({ tag: "00080050", keyword: "Accession Number", basicProfile: "Z", optionSet: Object.freeze({}) }),
14500
15944
  "00080054": Object.freeze({ tag: "00080054", keyword: "Retrieve AE Title", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "C" }) }),
14501
15945
  "00080055": Object.freeze({ tag: "00080055", keyword: "Station AE Title", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "C" }) }),
@@ -14509,9 +15953,9 @@ var ANNEX_E = Object.freeze({
14509
15953
  "00080096": Object.freeze({ tag: "00080096", keyword: "Referring Physician Identification Sequence", basicProfile: "X", optionSet: Object.freeze({}) }),
14510
15954
  "0008009C": Object.freeze({ tag: "0008009C", keyword: "Consulting Physician's Name", basicProfile: "Z", optionSet: Object.freeze({}) }),
14511
15955
  "0008009D": Object.freeze({ tag: "0008009D", keyword: "Consulting Physician Identification Sequence", basicProfile: "X", optionSet: Object.freeze({}) }),
14512
- "00080106": Object.freeze({ tag: "00080106", keyword: "Context Group Version", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14513
- "00080107": Object.freeze({ tag: "00080107", keyword: "Context Group Local Version", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14514
- "00080201": Object.freeze({ tag: "00080201", keyword: "Timezone Offset From UTC", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
15956
+ "00080106": Object.freeze({ tag: "00080106", keyword: "Context Group Version", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
15957
+ "00080107": Object.freeze({ tag: "00080107", keyword: "Context Group Local Version", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
15958
+ "00080201": Object.freeze({ tag: "00080201", keyword: "Timezone Offset From UTC", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14515
15959
  "00081000": Object.freeze({ tag: "00081000", keyword: "Network ID", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "C" }) }),
14516
15960
  "00081010": Object.freeze({ tag: "00081010", keyword: "Station Name", basicProfile: "X/Z/D", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
14517
15961
  "00081030": Object.freeze({ tag: "00081030", keyword: "Study Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
@@ -14592,7 +16036,7 @@ var ANNEX_E = Object.freeze({
14592
16036
  "001021A0": Object.freeze({ tag: "001021A0", keyword: "Smoking Status", basicProfile: "X", optionSet: Object.freeze({ "RetainPatientCharacteristics": "K" }) }),
14593
16037
  "001021B0": Object.freeze({ tag: "001021B0", keyword: "Additional Patient History", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14594
16038
  "001021C0": Object.freeze({ tag: "001021C0", keyword: "Pregnancy Status", basicProfile: "X", optionSet: Object.freeze({ "RetainPatientCharacteristics": "K" }) }),
14595
- "001021D0": Object.freeze({ tag: "001021D0", keyword: "Last Menstrual Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16039
+ "001021D0": Object.freeze({ tag: "001021D0", keyword: "Last Menstrual Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14596
16040
  "001021F0": Object.freeze({ tag: "001021F0", keyword: "Patient's Religious Preference", basicProfile: "X", optionSet: Object.freeze({}) }),
14597
16041
  "00102203": Object.freeze({ tag: "00102203", keyword: "Patient's Sex Neutered", basicProfile: "X/Z", optionSet: Object.freeze({ "RetainPatientCharacteristics": "K" }) }),
14598
16042
  "00102297": Object.freeze({ tag: "00102297", keyword: "Responsible Person", basicProfile: "X", optionSet: Object.freeze({}) }),
@@ -14619,10 +16063,10 @@ var ANNEX_E = Object.freeze({
14619
16063
  "00120073": Object.freeze({ tag: "00120073", keyword: "Issuer of Clinical Trial Series ID", basicProfile: "X", optionSet: Object.freeze({}) }),
14620
16064
  "00120081": Object.freeze({ tag: "00120081", keyword: "Clinical Trial Protocol Ethics Committee Name", basicProfile: "D", optionSet: Object.freeze({ "RetainInstitutionIdentity": "K" }) }),
14621
16065
  "00120082": Object.freeze({ tag: "00120082", keyword: "Clinical Trial Protocol Ethics Committee Approval Number", basicProfile: "X", optionSet: Object.freeze({}) }),
14622
- "00120086": Object.freeze({ tag: "00120086", keyword: "Ethics Committee Approval Effectiveness Start Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14623
- "00120087": Object.freeze({ tag: "00120087", keyword: "Ethics Committee Approval Effectiveness End Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14624
- "0014407C": Object.freeze({ tag: "0014407C", keyword: "Calibration Time", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K" }) }),
14625
- "0014407E": Object.freeze({ tag: "0014407E", keyword: "Calibration Date", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K" }) }),
16066
+ "00120086": Object.freeze({ tag: "00120086", keyword: "Ethics Committee Approval Effectiveness Start Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16067
+ "00120087": Object.freeze({ tag: "00120087", keyword: "Ethics Committee Approval Effectiveness End Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16068
+ "0014407C": Object.freeze({ tag: "0014407C", keyword: "Calibration Time", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16069
+ "0014407E": Object.freeze({ tag: "0014407E", keyword: "Calibration Date", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14626
16070
  "0016002B": Object.freeze({ tag: "0016002B", keyword: "Maker Note", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14627
16071
  "0016004B": Object.freeze({ tag: "0016004B", keyword: "Device Setting Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14628
16072
  "0016004D": Object.freeze({ tag: "0016004D", keyword: "Camera Owner Name", basicProfile: "X", optionSet: Object.freeze({}) }),
@@ -14659,11 +16103,11 @@ var ANNEX_E = Object.freeze({
14659
16103
  "0016008A": Object.freeze({ tag: "0016008A", keyword: "GPS Dest Distance", basicProfile: "X", optionSet: Object.freeze({}) }),
14660
16104
  "0016008B": Object.freeze({ tag: "0016008B", keyword: "GPS Processing Method", basicProfile: "X", optionSet: Object.freeze({}) }),
14661
16105
  "0016008C": Object.freeze({ tag: "0016008C", keyword: "GPS Area Information", basicProfile: "X", optionSet: Object.freeze({}) }),
14662
- "0016008D": Object.freeze({ tag: "0016008D", keyword: "GPS Date Stamp", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16106
+ "0016008D": Object.freeze({ tag: "0016008D", keyword: "GPS Date Stamp", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14663
16107
  "0016008E": Object.freeze({ tag: "0016008E", keyword: "GPS Differential", basicProfile: "X", optionSet: Object.freeze({}) }),
14664
16108
  "00180010": Object.freeze({ tag: "00180010", keyword: "Contrast/Bolus Agent", basicProfile: "Z/D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14665
- "00180027": Object.freeze({ tag: "00180027", keyword: "Intervention Drug Stop Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14666
- "00180035": Object.freeze({ tag: "00180035", keyword: "Intervention Drug Start Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16109
+ "00180027": Object.freeze({ tag: "00180027", keyword: "Intervention Drug Stop Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16110
+ "00180035": Object.freeze({ tag: "00180035", keyword: "Intervention Drug Start Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14667
16111
  "00181000": Object.freeze({ tag: "00181000", keyword: "Device Serial Number", basicProfile: "X/Z/D", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
14668
16112
  "00181002": Object.freeze({ tag: "00181002", keyword: "Device UID", basicProfile: "U", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainUIDs": "K" }) }),
14669
16113
  "00181004": Object.freeze({ tag: "00181004", keyword: "Plate ID", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
@@ -14675,48 +16119,48 @@ var ANNEX_E = Object.freeze({
14675
16119
  "0018100B": Object.freeze({ tag: "0018100B", keyword: "Manufacturer's Device Class UID", basicProfile: "U", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainUIDs": "K" }) }),
14676
16120
  "00181010": Object.freeze({ tag: "00181010", keyword: "Secondary Capture Device ID", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
14677
16121
  "00181011": Object.freeze({ tag: "00181011", keyword: "Hardcopy Creation Device ID", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
14678
- "00181012": Object.freeze({ tag: "00181012", keyword: "Date of Secondary Capture", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14679
- "00181014": Object.freeze({ tag: "00181014", keyword: "Time of Secondary Capture", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16122
+ "00181012": Object.freeze({ tag: "00181012", keyword: "Date of Secondary Capture", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16123
+ "00181014": Object.freeze({ tag: "00181014", keyword: "Time of Secondary Capture", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14680
16124
  "00181030": Object.freeze({ tag: "00181030", keyword: "Protocol Name", basicProfile: "X/D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14681
- "00181042": Object.freeze({ tag: "00181042", keyword: "Contrast/Bolus Start Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14682
- "00181043": Object.freeze({ tag: "00181043", keyword: "Contrast/Bolus Stop Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14683
- "00181072": Object.freeze({ tag: "00181072", keyword: "Radiopharmaceutical Start Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14684
- "00181073": Object.freeze({ tag: "00181073", keyword: "Radiopharmaceutical Stop Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14685
- "00181078": Object.freeze({ tag: "00181078", keyword: "Radiopharmaceutical Start DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14686
- "00181079": Object.freeze({ tag: "00181079", keyword: "Radiopharmaceutical Stop DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14687
- "001811BB": Object.freeze({ tag: "001811BB", keyword: "Acquisition Field Of View Label", basicProfile: "D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14688
- "00181200": Object.freeze({ tag: "00181200", keyword: "Date of Last Calibration", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K" }) }),
14689
- "00181201": Object.freeze({ tag: "00181201", keyword: "Time of Last Calibration", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K" }) }),
14690
- "00181202": Object.freeze({ tag: "00181202", keyword: "DateTime of Last Calibration", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K" }) }),
14691
- "00181203": Object.freeze({ tag: "00181203", keyword: "Calibration DateTime", basicProfile: "Z", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K" }) }),
14692
- "00181204": Object.freeze({ tag: "00181204", keyword: "Date of Manufacture", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K" }) }),
14693
- "00181205": Object.freeze({ tag: "00181205", keyword: "Date of Installation", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K" }) }),
16125
+ "00181042": Object.freeze({ tag: "00181042", keyword: "Contrast/Bolus Start Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16126
+ "00181043": Object.freeze({ tag: "00181043", keyword: "Contrast/Bolus Stop Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16127
+ "00181072": Object.freeze({ tag: "00181072", keyword: "Radiopharmaceutical Start Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16128
+ "00181073": Object.freeze({ tag: "00181073", keyword: "Radiopharmaceutical Stop Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16129
+ "00181078": Object.freeze({ tag: "00181078", keyword: "Radiopharmaceutical Start DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16130
+ "00181079": Object.freeze({ tag: "00181079", keyword: "Radiopharmaceutical Stop DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16131
+ "001811BB": Object.freeze({ tag: "001811BB", keyword: "Acquisition Field of View Label", basicProfile: "D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
16132
+ "00181200": Object.freeze({ tag: "00181200", keyword: "Date of Last Calibration", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16133
+ "00181201": Object.freeze({ tag: "00181201", keyword: "Time of Last Calibration", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16134
+ "00181202": Object.freeze({ tag: "00181202", keyword: "DateTime of Last Calibration", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16135
+ "00181203": Object.freeze({ tag: "00181203", keyword: "Calibration DateTime", basicProfile: "Z", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16136
+ "00181204": Object.freeze({ tag: "00181204", keyword: "Date of Manufacture", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16137
+ "00181205": Object.freeze({ tag: "00181205", keyword: "Date of Installation", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14694
16138
  "00181400": Object.freeze({ tag: "00181400", keyword: "Acquisition Device Processing Description", basicProfile: "X/D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14695
16139
  "00182042": Object.freeze({ tag: "00182042", keyword: "Target UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
14696
16140
  "00184000": Object.freeze({ tag: "00184000", keyword: "Acquisition Comments", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14697
16141
  "00185011": Object.freeze({ tag: "00185011", keyword: "Transducer Identification Sequence", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
14698
16142
  "0018700A": Object.freeze({ tag: "0018700A", keyword: "Detector ID", basicProfile: "X/D", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
14699
- "0018700C": Object.freeze({ tag: "0018700C", keyword: "Date of Last Detector Calibration", basicProfile: "X/D", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K" }) }),
14700
- "0018700E": Object.freeze({ tag: "0018700E", keyword: "Time of Last Detector Calibration", basicProfile: "X/D", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K" }) }),
14701
- "00189074": Object.freeze({ tag: "00189074", keyword: "Frame Acquisition DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14702
- "00189151": Object.freeze({ tag: "00189151", keyword: "Frame Reference DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16143
+ "0018700C": Object.freeze({ tag: "0018700C", keyword: "Date of Last Detector Calibration", basicProfile: "X/D", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16144
+ "0018700E": Object.freeze({ tag: "0018700E", keyword: "Time of Last Detector Calibration", basicProfile: "X/D", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16145
+ "00189074": Object.freeze({ tag: "00189074", keyword: "Frame Acquisition DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16146
+ "00189151": Object.freeze({ tag: "00189151", keyword: "Frame Reference DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14703
16147
  "00189185": Object.freeze({ tag: "00189185", keyword: "Respiratory Motion Compensation Technique Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14704
16148
  "00189367": Object.freeze({ tag: "00189367", keyword: "X-Ray Source ID", basicProfile: "D", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
14705
- "00189369": Object.freeze({ tag: "00189369", keyword: "Source Start DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14706
- "0018936A": Object.freeze({ tag: "0018936A", keyword: "Source End DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16149
+ "00189369": Object.freeze({ tag: "00189369", keyword: "Source Start DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16150
+ "0018936A": Object.freeze({ tag: "0018936A", keyword: "Source End DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14707
16151
  "00189371": Object.freeze({ tag: "00189371", keyword: "X-Ray Detector ID", basicProfile: "D", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
14708
16152
  "00189373": Object.freeze({ tag: "00189373", keyword: "X-Ray Detector Label", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
14709
16153
  "0018937B": Object.freeze({ tag: "0018937B", keyword: "Multi-energy Acquisition Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14710
16154
  "0018937F": Object.freeze({ tag: "0018937F", keyword: "Decomposition Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14711
16155
  "00189424": Object.freeze({ tag: "00189424", keyword: "Acquisition Protocol Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14712
- "00189516": Object.freeze({ tag: "00189516", keyword: "Start Acquisition DateTime", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14713
- "00189517": Object.freeze({ tag: "00189517", keyword: "End Acquisition DateTime", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14714
- "00189623": Object.freeze({ tag: "00189623", keyword: "Functional Sync Pulse", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14715
- "00189701": Object.freeze({ tag: "00189701", keyword: "Decay Correction DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14716
- "00189804": Object.freeze({ tag: "00189804", keyword: "Exclusion Start DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14717
- "00189919": Object.freeze({ tag: "00189919", keyword: "Instruction Performed DateTime", basicProfile: "Z/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16156
+ "00189516": Object.freeze({ tag: "00189516", keyword: "Start Acquisition DateTime", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16157
+ "00189517": Object.freeze({ tag: "00189517", keyword: "End Acquisition DateTime", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16158
+ "00189623": Object.freeze({ tag: "00189623", keyword: "Functional Sync Pulse", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16159
+ "00189701": Object.freeze({ tag: "00189701", keyword: "Decay Correction DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16160
+ "00189804": Object.freeze({ tag: "00189804", keyword: "Exclusion Start DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16161
+ "00189919": Object.freeze({ tag: "00189919", keyword: "Instruction Performed DateTime", basicProfile: "Z/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14718
16162
  "00189937": Object.freeze({ tag: "00189937", keyword: "Requested Series Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14719
- "0018A002": Object.freeze({ tag: "0018A002", keyword: "Contribution DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16163
+ "0018A002": Object.freeze({ tag: "0018A002", keyword: "Contribution DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14720
16164
  "0018A003": Object.freeze({ tag: "0018A003", keyword: "Contribution Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14721
16165
  "0020000D": Object.freeze({ tag: "0020000D", keyword: "Study Instance UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
14722
16166
  "0020000E": Object.freeze({ tag: "0020000E", keyword: "Series Instance UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
@@ -14725,8 +16169,8 @@ var ANNEX_E = Object.freeze({
14725
16169
  "00200052": Object.freeze({ tag: "00200052", keyword: "Frame of Reference UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
14726
16170
  "00200200": Object.freeze({ tag: "00200200", keyword: "Synchronization Frame of Reference UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
14727
16171
  "00203401": Object.freeze({ tag: "00203401", keyword: "Modifying Device ID", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
14728
- "00203403": Object.freeze({ tag: "00203403", keyword: "Modified Image Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14729
- "00203405": Object.freeze({ tag: "00203405", keyword: "Modified Image Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16172
+ "00203403": Object.freeze({ tag: "00203403", keyword: "Modified Image Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16173
+ "00203405": Object.freeze({ tag: "00203405", keyword: "Modified Image Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14730
16174
  "00203406": Object.freeze({ tag: "00203406", keyword: "Modified Image Description", basicProfile: "X", optionSet: Object.freeze({}) }),
14731
16175
  "00204000": Object.freeze({ tag: "00204000", keyword: "Image Comments", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14732
16176
  "00209158": Object.freeze({ tag: "00209158", keyword: "Frame Comments", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
@@ -14736,23 +16180,23 @@ var ANNEX_E = Object.freeze({
14736
16180
  "00281214": Object.freeze({ tag: "00281214", keyword: "Large Palette Color Lookup Table UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
14737
16181
  "00284000": Object.freeze({ tag: "00284000", keyword: "Image Presentation Comments", basicProfile: "X", optionSet: Object.freeze({}) }),
14738
16182
  "00320012": Object.freeze({ tag: "00320012", keyword: "Study ID Issuer", basicProfile: "X", optionSet: Object.freeze({}) }),
14739
- "00320032": Object.freeze({ tag: "00320032", keyword: "Study Verified Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14740
- "00320033": Object.freeze({ tag: "00320033", keyword: "Study Verified Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14741
- "00320034": Object.freeze({ tag: "00320034", keyword: "Study Read Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14742
- "00320035": Object.freeze({ tag: "00320035", keyword: "Study Read Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14743
- "00321000": Object.freeze({ tag: "00321000", keyword: "Scheduled Study Start Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14744
- "00321001": Object.freeze({ tag: "00321001", keyword: "Scheduled Study Start Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14745
- "00321010": Object.freeze({ tag: "00321010", keyword: "Scheduled Study Stop Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14746
- "00321011": Object.freeze({ tag: "00321011", keyword: "Scheduled Study Stop Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16183
+ "00320032": Object.freeze({ tag: "00320032", keyword: "Study Verified Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16184
+ "00320033": Object.freeze({ tag: "00320033", keyword: "Study Verified Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16185
+ "00320034": Object.freeze({ tag: "00320034", keyword: "Study Read Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16186
+ "00320035": Object.freeze({ tag: "00320035", keyword: "Study Read Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16187
+ "00321000": Object.freeze({ tag: "00321000", keyword: "Scheduled Study Start Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16188
+ "00321001": Object.freeze({ tag: "00321001", keyword: "Scheduled Study Start Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16189
+ "00321010": Object.freeze({ tag: "00321010", keyword: "Scheduled Study Stop Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16190
+ "00321011": Object.freeze({ tag: "00321011", keyword: "Scheduled Study Stop Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14747
16191
  "00321020": Object.freeze({ tag: "00321020", keyword: "Scheduled Study Location", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
14748
16192
  "00321021": Object.freeze({ tag: "00321021", keyword: "Scheduled Study Location AE Title", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "C" }) }),
14749
16193
  "00321030": Object.freeze({ tag: "00321030", keyword: "Reason for Study", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14750
16194
  "00321032": Object.freeze({ tag: "00321032", keyword: "Requesting Physician", basicProfile: "X", optionSet: Object.freeze({}) }),
14751
16195
  "00321033": Object.freeze({ tag: "00321033", keyword: "Requesting Service", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14752
- "00321040": Object.freeze({ tag: "00321040", keyword: "Study Arrival Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14753
- "00321041": Object.freeze({ tag: "00321041", keyword: "Study Arrival Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14754
- "00321050": Object.freeze({ tag: "00321050", keyword: "Study Completion Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14755
- "00321051": Object.freeze({ tag: "00321051", keyword: "Study Completion Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16196
+ "00321040": Object.freeze({ tag: "00321040", keyword: "Study Arrival Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16197
+ "00321041": Object.freeze({ tag: "00321041", keyword: "Study Arrival Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16198
+ "00321050": Object.freeze({ tag: "00321050", keyword: "Study Completion Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16199
+ "00321051": Object.freeze({ tag: "00321051", keyword: "Study Completion Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14756
16200
  "00321060": Object.freeze({ tag: "00321060", keyword: "Requested Procedure Description", basicProfile: "X/Z", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14757
16201
  "00321066": Object.freeze({ tag: "00321066", keyword: "Reason for Visit", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14758
16202
  "00321067": Object.freeze({ tag: "00321067", keyword: "Reason for Visit Code Sequence", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
@@ -14761,20 +16205,20 @@ var ANNEX_E = Object.freeze({
14761
16205
  "00340001": Object.freeze({ tag: "00340001", keyword: "Flow Identifier Sequence", basicProfile: "D", optionSet: Object.freeze({}) }),
14762
16206
  "00340002": Object.freeze({ tag: "00340002", keyword: "Flow Identifier", basicProfile: "D", optionSet: Object.freeze({}) }),
14763
16207
  "00340005": Object.freeze({ tag: "00340005", keyword: "Source Identifier", basicProfile: "D", optionSet: Object.freeze({}) }),
14764
- "00340007": Object.freeze({ tag: "00340007", keyword: "Frame Origin Timestamp", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16208
+ "00340007": Object.freeze({ tag: "00340007", keyword: "Frame Origin Timestamp", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14765
16209
  "00380004": Object.freeze({ tag: "00380004", keyword: "Referenced Patient Alias Sequence", basicProfile: "X", optionSet: Object.freeze({}) }),
14766
16210
  "00380010": Object.freeze({ tag: "00380010", keyword: "Admission ID", basicProfile: "X", optionSet: Object.freeze({}) }),
14767
16211
  "00380011": Object.freeze({ tag: "00380011", keyword: "Issuer of Admission ID", basicProfile: "X", optionSet: Object.freeze({}) }),
14768
16212
  "00380014": Object.freeze({ tag: "00380014", keyword: "Issuer of Admission ID Sequence", basicProfile: "X", optionSet: Object.freeze({}) }),
14769
- "0038001A": Object.freeze({ tag: "0038001A", keyword: "Scheduled Admission Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14770
- "0038001B": Object.freeze({ tag: "0038001B", keyword: "Scheduled Admission Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14771
- "0038001C": Object.freeze({ tag: "0038001C", keyword: "Scheduled Discharge Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14772
- "0038001D": Object.freeze({ tag: "0038001D", keyword: "Scheduled Discharge Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16213
+ "0038001A": Object.freeze({ tag: "0038001A", keyword: "Scheduled Admission Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16214
+ "0038001B": Object.freeze({ tag: "0038001B", keyword: "Scheduled Admission Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16215
+ "0038001C": Object.freeze({ tag: "0038001C", keyword: "Scheduled Discharge Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16216
+ "0038001D": Object.freeze({ tag: "0038001D", keyword: "Scheduled Discharge Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14773
16217
  "0038001E": Object.freeze({ tag: "0038001E", keyword: "Scheduled Patient Institution Residence", basicProfile: "X", optionSet: Object.freeze({}) }),
14774
- "00380020": Object.freeze({ tag: "00380020", keyword: "Admitting Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14775
- "00380021": Object.freeze({ tag: "00380021", keyword: "Admitting Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14776
- "00380030": Object.freeze({ tag: "00380030", keyword: "Discharge Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14777
- "00380032": Object.freeze({ tag: "00380032", keyword: "Discharge Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16218
+ "00380020": Object.freeze({ tag: "00380020", keyword: "Admitting Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16219
+ "00380021": Object.freeze({ tag: "00380021", keyword: "Admitting Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16220
+ "00380030": Object.freeze({ tag: "00380030", keyword: "Discharge Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16221
+ "00380032": Object.freeze({ tag: "00380032", keyword: "Discharge Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14778
16222
  "00380040": Object.freeze({ tag: "00380040", keyword: "Discharge Diagnosis Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14779
16223
  "00380050": Object.freeze({ tag: "00380050", keyword: "Special Needs", basicProfile: "X", optionSet: Object.freeze({ "RetainPatientCharacteristics": "C" }) }),
14780
16224
  "00380060": Object.freeze({ tag: "00380060", keyword: "Service Episode ID", basicProfile: "X", optionSet: Object.freeze({}) }),
@@ -14789,14 +16233,14 @@ var ANNEX_E = Object.freeze({
14789
16233
  "003A0203": Object.freeze({ tag: "003A0203", keyword: "Channel Label", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14790
16234
  "003A020C": Object.freeze({ tag: "003A020C", keyword: "Channel Derivation Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14791
16235
  "003A0310": Object.freeze({ tag: "003A0310", keyword: "Multiplex Group UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
14792
- "003A0314": Object.freeze({ tag: "003A0314", keyword: "Impedance Measurement DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16236
+ "003A0314": Object.freeze({ tag: "003A0314", keyword: "Impedance Measurement DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14793
16237
  "003A0329": Object.freeze({ tag: "003A0329", keyword: "Waveform Filter Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14794
16238
  "003A032B": Object.freeze({ tag: "003A032B", keyword: "Filter Lookup Table Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14795
16239
  "00400001": Object.freeze({ tag: "00400001", keyword: "Scheduled Station AE Title", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "C" }) }),
14796
- "00400002": Object.freeze({ tag: "00400002", keyword: "Scheduled Procedure Step Start Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14797
- "00400003": Object.freeze({ tag: "00400003", keyword: "Scheduled Procedure Step Start Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14798
- "00400004": Object.freeze({ tag: "00400004", keyword: "Scheduled Procedure Step End Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14799
- "00400005": Object.freeze({ tag: "00400005", keyword: "Scheduled Procedure Step End Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16240
+ "00400002": Object.freeze({ tag: "00400002", keyword: "Scheduled Procedure Step Start Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16241
+ "00400003": Object.freeze({ tag: "00400003", keyword: "Scheduled Procedure Step Start Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16242
+ "00400004": Object.freeze({ tag: "00400004", keyword: "Scheduled Procedure Step End Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16243
+ "00400005": Object.freeze({ tag: "00400005", keyword: "Scheduled Procedure Step End Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14800
16244
  "00400006": Object.freeze({ tag: "00400006", keyword: "Scheduled Performing Physician's Name", basicProfile: "X", optionSet: Object.freeze({}) }),
14801
16245
  "00400007": Object.freeze({ tag: "00400007", keyword: "Scheduled Procedure Step Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14802
16246
  "00400009": Object.freeze({ tag: "00400009", keyword: "Scheduled Procedure Step ID", basicProfile: "X", optionSet: Object.freeze({}) }),
@@ -14807,10 +16251,10 @@ var ANNEX_E = Object.freeze({
14807
16251
  "00400241": Object.freeze({ tag: "00400241", keyword: "Performed Station AE Title", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "C" }) }),
14808
16252
  "00400242": Object.freeze({ tag: "00400242", keyword: "Performed Station Name", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
14809
16253
  "00400243": Object.freeze({ tag: "00400243", keyword: "Performed Location", basicProfile: "X", optionSet: Object.freeze({}) }),
14810
- "00400244": Object.freeze({ tag: "00400244", keyword: "Performed Procedure Step Start Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14811
- "00400245": Object.freeze({ tag: "00400245", keyword: "Performed Procedure Step Start Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14812
- "00400250": Object.freeze({ tag: "00400250", keyword: "Performed Procedure Step End Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14813
- "00400251": Object.freeze({ tag: "00400251", keyword: "Performed Procedure Step End Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16254
+ "00400244": Object.freeze({ tag: "00400244", keyword: "Performed Procedure Step Start Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16255
+ "00400245": Object.freeze({ tag: "00400245", keyword: "Performed Procedure Step Start Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16256
+ "00400250": Object.freeze({ tag: "00400250", keyword: "Performed Procedure Step End Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16257
+ "00400251": Object.freeze({ tag: "00400251", keyword: "Performed Procedure Step End Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14814
16258
  "00400253": Object.freeze({ tag: "00400253", keyword: "Performed Procedure Step ID", basicProfile: "X", optionSet: Object.freeze({}) }),
14815
16259
  "00400254": Object.freeze({ tag: "00400254", keyword: "Performed Procedure Step Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14816
16260
  "00400275": Object.freeze({ tag: "00400275", keyword: "Request Attributes Sequence", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
@@ -14842,8 +16286,8 @@ var ANNEX_E = Object.freeze({
14842
16286
  "00401104": Object.freeze({ tag: "00401104", keyword: "Person's Telecom Information", basicProfile: "X", optionSet: Object.freeze({}) }),
14843
16287
  "00401400": Object.freeze({ tag: "00401400", keyword: "Requested Procedure Comments", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14844
16288
  "00402001": Object.freeze({ tag: "00402001", keyword: "Reason for the Imaging Service Request", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14845
- "00402004": Object.freeze({ tag: "00402004", keyword: "Issue Date of Imaging Service Request", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14846
- "00402005": Object.freeze({ tag: "00402005", keyword: "Issue Time of Imaging Service Request", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16289
+ "00402004": Object.freeze({ tag: "00402004", keyword: "Issue Date of Imaging Service Request", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16290
+ "00402005": Object.freeze({ tag: "00402005", keyword: "Issue Time of Imaging Service Request", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14847
16291
  "00402008": Object.freeze({ tag: "00402008", keyword: "Order Entered By", basicProfile: "X", optionSet: Object.freeze({}) }),
14848
16292
  "00402009": Object.freeze({ tag: "00402009", keyword: "Order Enterer's Location", basicProfile: "X", optionSet: Object.freeze({}) }),
14849
16293
  "00402010": Object.freeze({ tag: "00402010", keyword: "Order Callback Phone Number", basicProfile: "X", optionSet: Object.freeze({}) }),
@@ -14852,10 +16296,10 @@ var ANNEX_E = Object.freeze({
14852
16296
  "00402017": Object.freeze({ tag: "00402017", keyword: "Filler Order Number / Imaging Service Request", basicProfile: "Z", optionSet: Object.freeze({}) }),
14853
16297
  "00402400": Object.freeze({ tag: "00402400", keyword: "Imaging Service Request Comments", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14854
16298
  "00403001": Object.freeze({ tag: "00403001", keyword: "Confidentiality Constraint on Patient Data Description", basicProfile: "X", optionSet: Object.freeze({}) }),
14855
- "00404005": Object.freeze({ tag: "00404005", keyword: "Scheduled Procedure Step Start DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14856
- "00404008": Object.freeze({ tag: "00404008", keyword: "Scheduled Procedure Step Expiration DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14857
- "00404010": Object.freeze({ tag: "00404010", keyword: "Scheduled Procedure Step Modification DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14858
- "00404011": Object.freeze({ tag: "00404011", keyword: "Expected Completion DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16299
+ "00404005": Object.freeze({ tag: "00404005", keyword: "Scheduled Procedure Step Start DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16300
+ "00404008": Object.freeze({ tag: "00404008", keyword: "Scheduled Procedure Step Expiration DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16301
+ "00404010": Object.freeze({ tag: "00404010", keyword: "Scheduled Procedure Step Modification DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16302
+ "00404011": Object.freeze({ tag: "00404011", keyword: "Expected Completion DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14859
16303
  "00404023": Object.freeze({ tag: "00404023", keyword: "Referenced General Purpose Scheduled Procedure Step Transaction UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
14860
16304
  "00404025": Object.freeze({ tag: "00404025", keyword: "Scheduled Station Name Code Sequence", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
14861
16305
  "00404027": Object.freeze({ tag: "00404027", keyword: "Scheduled Station Geographic Location Code Sequence", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
@@ -14865,36 +16309,36 @@ var ANNEX_E = Object.freeze({
14865
16309
  "00404035": Object.freeze({ tag: "00404035", keyword: "Actual Human Performers Sequence", basicProfile: "X", optionSet: Object.freeze({}) }),
14866
16310
  "00404036": Object.freeze({ tag: "00404036", keyword: "Human Performer's Organization", basicProfile: "X", optionSet: Object.freeze({}) }),
14867
16311
  "00404037": Object.freeze({ tag: "00404037", keyword: "Human Performer's Name", basicProfile: "X", optionSet: Object.freeze({}) }),
14868
- "00404050": Object.freeze({ tag: "00404050", keyword: "Performed Procedure Step Start DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14869
- "00404051": Object.freeze({ tag: "00404051", keyword: "Performed Procedure Step End DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14870
- "00404052": Object.freeze({ tag: "00404052", keyword: "Procedure Step Cancellation DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14871
- "0040A023": Object.freeze({ tag: "0040A023", keyword: "Findings Group Recording Date (Trial)", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14872
- "0040A024": Object.freeze({ tag: "0040A024", keyword: "Findings Group Recording Time (Trial)", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16312
+ "00404050": Object.freeze({ tag: "00404050", keyword: "Performed Procedure Step Start DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16313
+ "00404051": Object.freeze({ tag: "00404051", keyword: "Performed Procedure Step End DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16314
+ "00404052": Object.freeze({ tag: "00404052", keyword: "Procedure Step Cancellation DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16315
+ "0040A023": Object.freeze({ tag: "0040A023", keyword: "Findings Group Recording Date (Trial)", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16316
+ "0040A024": Object.freeze({ tag: "0040A024", keyword: "Findings Group Recording Time (Trial)", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14873
16317
  "0040A027": Object.freeze({ tag: "0040A027", keyword: "Verifying Organization", basicProfile: "D", optionSet: Object.freeze({}) }),
14874
- "0040A030": Object.freeze({ tag: "0040A030", keyword: "Verification DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14875
- "0040A032": Object.freeze({ tag: "0040A032", keyword: "Observation DateTime", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14876
- "0040A033": Object.freeze({ tag: "0040A033", keyword: "Observation Start DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14877
- "0040A034": Object.freeze({ tag: "0040A034", keyword: "Effective Start DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14878
- "0040A035": Object.freeze({ tag: "0040A035", keyword: "Effective Stop DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16318
+ "0040A030": Object.freeze({ tag: "0040A030", keyword: "Verification DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16319
+ "0040A032": Object.freeze({ tag: "0040A032", keyword: "Observation DateTime", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16320
+ "0040A033": Object.freeze({ tag: "0040A033", keyword: "Observation Start DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16321
+ "0040A034": Object.freeze({ tag: "0040A034", keyword: "Effective Start DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16322
+ "0040A035": Object.freeze({ tag: "0040A035", keyword: "Effective Stop DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14879
16323
  "0040A073": Object.freeze({ tag: "0040A073", keyword: "Verifying Observer Sequence", basicProfile: "D", optionSet: Object.freeze({}) }),
14880
16324
  "0040A075": Object.freeze({ tag: "0040A075", keyword: "Verifying Observer Name", basicProfile: "D", optionSet: Object.freeze({}) }),
14881
16325
  "0040A078": Object.freeze({ tag: "0040A078", keyword: "Author Observer Sequence", basicProfile: "X", optionSet: Object.freeze({}) }),
14882
16326
  "0040A07A": Object.freeze({ tag: "0040A07A", keyword: "Participant Sequence", basicProfile: "X", optionSet: Object.freeze({}) }),
14883
16327
  "0040A07C": Object.freeze({ tag: "0040A07C", keyword: "Custodial Organization Sequence", basicProfile: "X", optionSet: Object.freeze({}) }),
14884
- "0040A082": Object.freeze({ tag: "0040A082", keyword: "Participation DateTime", basicProfile: "Z", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16328
+ "0040A082": Object.freeze({ tag: "0040A082", keyword: "Participation DateTime", basicProfile: "Z", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14885
16329
  "0040A088": Object.freeze({ tag: "0040A088", keyword: "Verifying Observer Identification Code Sequence", basicProfile: "Z", optionSet: Object.freeze({}) }),
14886
- "0040A110": Object.freeze({ tag: "0040A110", keyword: "Date of Document or Verbal Transaction (Trial)", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14887
- "0040A112": Object.freeze({ tag: "0040A112", keyword: "Time of Document Creation or Verbal Transaction (Trial)", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14888
- "0040A120": Object.freeze({ tag: "0040A120", keyword: "DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14889
- "0040A121": Object.freeze({ tag: "0040A121", keyword: "Date", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14890
- "0040A122": Object.freeze({ tag: "0040A122", keyword: "Time", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16330
+ "0040A110": Object.freeze({ tag: "0040A110", keyword: "Date of Document or Verbal Transaction (Trial)", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16331
+ "0040A112": Object.freeze({ tag: "0040A112", keyword: "Time of Document Creation or Verbal Transaction (Trial)", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16332
+ "0040A120": Object.freeze({ tag: "0040A120", keyword: "DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16333
+ "0040A121": Object.freeze({ tag: "0040A121", keyword: "Date", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16334
+ "0040A122": Object.freeze({ tag: "0040A122", keyword: "Time", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14891
16335
  "0040A123": Object.freeze({ tag: "0040A123", keyword: "Person Name", basicProfile: "D", optionSet: Object.freeze({}) }),
14892
16336
  "0040A124": Object.freeze({ tag: "0040A124", keyword: "UID", basicProfile: "U", optionSet: Object.freeze({}) }),
14893
- "0040A13A": Object.freeze({ tag: "0040A13A", keyword: "Referenced DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16337
+ "0040A13A": Object.freeze({ tag: "0040A13A", keyword: "Referenced DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14894
16338
  "0040A171": Object.freeze({ tag: "0040A171", keyword: "Observation UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
14895
16339
  "0040A172": Object.freeze({ tag: "0040A172", keyword: "Referenced Observation UID (Trial)", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
14896
- "0040A192": Object.freeze({ tag: "0040A192", keyword: "Observation Date (Trial)", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14897
- "0040A193": Object.freeze({ tag: "0040A193", keyword: "Observation Time (Trial)", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16340
+ "0040A192": Object.freeze({ tag: "0040A192", keyword: "Observation Date (Trial)", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16341
+ "0040A193": Object.freeze({ tag: "0040A193", keyword: "Observation Time (Trial)", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14898
16342
  "0040A307": Object.freeze({ tag: "0040A307", keyword: "Current Observer (Trial)", basicProfile: "X", optionSet: Object.freeze({}) }),
14899
16343
  "0040A352": Object.freeze({ tag: "0040A352", keyword: "Verbal Source (Trial)", basicProfile: "X", optionSet: Object.freeze({}) }),
14900
16344
  "0040A353": Object.freeze({ tag: "0040A353", keyword: "Address (Trial)", basicProfile: "X", optionSet: Object.freeze({}) }),
@@ -14903,51 +16347,51 @@ var ANNEX_E = Object.freeze({
14903
16347
  "0040A402": Object.freeze({ tag: "0040A402", keyword: "Observation Subject UID (Trial)", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
14904
16348
  "0040A730": Object.freeze({ tag: "0040A730", keyword: "Content Sequence", basicProfile: "D", optionSet: Object.freeze({ "CleanStructuredContent": "C" }) }),
14905
16349
  "0040B020": Object.freeze({ tag: "0040B020", keyword: "Waveform Annotation Sequence", basicProfile: "X/D", optionSet: Object.freeze({ "CleanStructuredContent": "C" }) }),
14906
- "0040B034": Object.freeze({ tag: "0040B034", keyword: "Annotation DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14907
- "0040B036": Object.freeze({ tag: "0040B036", keyword: "Segment Definition DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16350
+ "0040B034": Object.freeze({ tag: "0040B034", keyword: "Annotation DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16351
+ "0040B036": Object.freeze({ tag: "0040B036", keyword: "Segment Definition DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14908
16352
  "0040B03B": Object.freeze({ tag: "0040B03B", keyword: "Montage Name", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14909
16353
  "0040B03F": Object.freeze({ tag: "0040B03F", keyword: "Montage Channel Label", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14910
- "0040DB06": Object.freeze({ tag: "0040DB06", keyword: "Template Version", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14911
- "0040DB07": Object.freeze({ tag: "0040DB07", keyword: "Template Local Version", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16354
+ "0040DB06": Object.freeze({ tag: "0040DB06", keyword: "Template Version", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16355
+ "0040DB07": Object.freeze({ tag: "0040DB07", keyword: "Template Local Version", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14912
16356
  "0040DB0C": Object.freeze({ tag: "0040DB0C", keyword: "Template Extension Organization UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
14913
16357
  "0040DB0D": Object.freeze({ tag: "0040DB0D", keyword: "Template Extension Creator UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
14914
- "0040E004": Object.freeze({ tag: "0040E004", keyword: "HL7 Document Effective Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16358
+ "0040E004": Object.freeze({ tag: "0040E004", keyword: "HL7 Document Effective Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14915
16359
  "0040E012": Object.freeze({ tag: "0040E012", keyword: "Display URI", basicProfile: "X", optionSet: Object.freeze({}) }),
14916
16360
  "00420011": Object.freeze({ tag: "00420011", keyword: "Encapsulated Document", basicProfile: "D", optionSet: Object.freeze({}) }),
14917
- "00440004": Object.freeze({ tag: "00440004", keyword: "Approval Status DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14918
- "0044000B": Object.freeze({ tag: "0044000B", keyword: "Product Expiration DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14919
- "00440010": Object.freeze({ tag: "00440010", keyword: "Substance Administration DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14920
- "00440104": Object.freeze({ tag: "00440104", keyword: "Assertion DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14921
- "00440105": Object.freeze({ tag: "00440105", keyword: "Assertion Expiration DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16361
+ "00440004": Object.freeze({ tag: "00440004", keyword: "Approval Status DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16362
+ "0044000B": Object.freeze({ tag: "0044000B", keyword: "Product Expiration DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16363
+ "00440010": Object.freeze({ tag: "00440010", keyword: "Substance Administration DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16364
+ "00440104": Object.freeze({ tag: "00440104", keyword: "Assertion DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16365
+ "00440105": Object.freeze({ tag: "00440105", keyword: "Assertion Expiration DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14922
16366
  "0050001B": Object.freeze({ tag: "0050001B", keyword: "Container Component ID", basicProfile: "X", optionSet: Object.freeze({}) }),
14923
16367
  "00500020": Object.freeze({ tag: "00500020", keyword: "Device Description", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
14924
16368
  "00500021": Object.freeze({ tag: "00500021", keyword: "Long Device Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14925
16369
  "00620021": Object.freeze({ tag: "00620021", keyword: "Tracking UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
14926
16370
  "00640003": Object.freeze({ tag: "00640003", keyword: "Source Frame of Reference UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
14927
- "00686226": Object.freeze({ tag: "00686226", keyword: "Effective DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14928
- "00686270": Object.freeze({ tag: "00686270", keyword: "Information Issue DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16371
+ "00686226": Object.freeze({ tag: "00686226", keyword: "Effective DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16372
+ "00686270": Object.freeze({ tag: "00686270", keyword: "Information Issue DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14929
16373
  "006A0003": Object.freeze({ tag: "006A0003", keyword: "Annotation Group UID", basicProfile: "D", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
14930
16374
  "006A0005": Object.freeze({ tag: "006A0005", keyword: "Annotation Group Label", basicProfile: "D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14931
16375
  "006A0006": Object.freeze({ tag: "006A0006", keyword: "Annotation Group Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14932
16376
  "00700001": Object.freeze({ tag: "00700001", keyword: "Graphic Annotation Sequence", basicProfile: "D", optionSet: Object.freeze({ "CleanGraphics": "C" }) }),
14933
16377
  "00700006": Object.freeze({ tag: "00700006", keyword: "Unformatted Text Value", basicProfile: "D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14934
- "00700082": Object.freeze({ tag: "00700082", keyword: "Presentation Creation Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14935
- "00700083": Object.freeze({ tag: "00700083", keyword: "Presentation Creation Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16378
+ "00700082": Object.freeze({ tag: "00700082", keyword: "Presentation Creation Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16379
+ "00700083": Object.freeze({ tag: "00700083", keyword: "Presentation Creation Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14936
16380
  "00700084": Object.freeze({ tag: "00700084", keyword: "Content Creator's Name", basicProfile: "Z/D", optionSet: Object.freeze({}) }),
14937
16381
  "00700086": Object.freeze({ tag: "00700086", keyword: "Content Creator's Identification Code Sequence", basicProfile: "X", optionSet: Object.freeze({}) }),
14938
16382
  "0070031A": Object.freeze({ tag: "0070031A", keyword: "Fiducial UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
14939
16383
  "00701101": Object.freeze({ tag: "00701101", keyword: "Presentation Display Collection UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
14940
16384
  "00701102": Object.freeze({ tag: "00701102", keyword: "Presentation Sequence Collection UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
14941
- "0072000A": Object.freeze({ tag: "0072000A", keyword: "Hanging Protocol Creation DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16385
+ "0072000A": Object.freeze({ tag: "0072000A", keyword: "Hanging Protocol Creation DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14942
16386
  "0072005E": Object.freeze({ tag: "0072005E", keyword: "Selector AE Value", basicProfile: "D", optionSet: Object.freeze({ "RetainDeviceIdentity": "C" }) }),
14943
16387
  "0072005F": Object.freeze({ tag: "0072005F", keyword: "Selector AS Value", basicProfile: "D", optionSet: Object.freeze({ "RetainPatientCharacteristics": "K" }) }),
14944
- "00720061": Object.freeze({ tag: "00720061", keyword: "Selector DA Value", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14945
- "00720063": Object.freeze({ tag: "00720063", keyword: "Selector DT Value", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16388
+ "00720061": Object.freeze({ tag: "00720061", keyword: "Selector DA Value", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16389
+ "00720063": Object.freeze({ tag: "00720063", keyword: "Selector DT Value", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14946
16390
  "00720065": Object.freeze({ tag: "00720065", keyword: "Selector OB Value", basicProfile: "D", optionSet: Object.freeze({}) }),
14947
16391
  "00720066": Object.freeze({ tag: "00720066", keyword: "Selector LO Value", basicProfile: "D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14948
16392
  "00720068": Object.freeze({ tag: "00720068", keyword: "Selector LT Value", basicProfile: "D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14949
16393
  "0072006A": Object.freeze({ tag: "0072006A", keyword: "Selector PN Value", basicProfile: "D", optionSet: Object.freeze({}) }),
14950
- "0072006B": Object.freeze({ tag: "0072006B", keyword: "Selector TM Value", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16394
+ "0072006B": Object.freeze({ tag: "0072006B", keyword: "Selector TM Value", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14951
16395
  "0072006C": Object.freeze({ tag: "0072006C", keyword: "Selector SH Value", basicProfile: "D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14952
16396
  "0072006D": Object.freeze({ tag: "0072006D", keyword: "Selector UN Value", basicProfile: "D", optionSet: Object.freeze({}) }),
14953
16397
  "0072006E": Object.freeze({ tag: "0072006E", keyword: "Selector ST Value", basicProfile: "D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
@@ -14961,11 +16405,11 @@ var ANNEX_E = Object.freeze({
14961
16405
  "00880906": Object.freeze({ tag: "00880906", keyword: "Topic Subject", basicProfile: "X", optionSet: Object.freeze({}) }),
14962
16406
  "00880910": Object.freeze({ tag: "00880910", keyword: "Topic Author", basicProfile: "X", optionSet: Object.freeze({}) }),
14963
16407
  "00880912": Object.freeze({ tag: "00880912", keyword: "Topic Keywords", basicProfile: "X", optionSet: Object.freeze({}) }),
14964
- "01000420": Object.freeze({ tag: "01000420", keyword: "SOP Authorization DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16408
+ "01000420": Object.freeze({ tag: "01000420", keyword: "SOP Authorization DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14965
16409
  "04000100": Object.freeze({ tag: "04000100", keyword: "Digital Signature UID", basicProfile: "U", optionSet: Object.freeze({}) }),
14966
- "04000105": Object.freeze({ tag: "04000105", keyword: "Digital Signature DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16410
+ "04000105": Object.freeze({ tag: "04000105", keyword: "Digital Signature DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14967
16411
  "04000115": Object.freeze({ tag: "04000115", keyword: "Certificate of Signer", basicProfile: "D", optionSet: Object.freeze({}) }),
14968
- "04000310": Object.freeze({ tag: "04000310", keyword: "Certified Timestamp", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16412
+ "04000310": Object.freeze({ tag: "04000310", keyword: "Certified Timestamp", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14969
16413
  "04000402": Object.freeze({ tag: "04000402", keyword: "Referenced Digital Signature Sequence", basicProfile: "X", optionSet: Object.freeze({}) }),
14970
16414
  "04000403": Object.freeze({ tag: "04000403", keyword: "Referenced SOP Instance MAC Sequence", basicProfile: "X", optionSet: Object.freeze({}) }),
14971
16415
  "04000404": Object.freeze({ tag: "04000404", keyword: "MAC", basicProfile: "X", optionSet: Object.freeze({}) }),
@@ -14973,30 +16417,31 @@ var ANNEX_E = Object.freeze({
14973
16417
  "04000551": Object.freeze({ tag: "04000551", keyword: "Nonconforming Modified Attributes Sequence", basicProfile: "X", optionSet: Object.freeze({}) }),
14974
16418
  "04000552": Object.freeze({ tag: "04000552", keyword: "Nonconforming Data Element Value", basicProfile: "X", optionSet: Object.freeze({}) }),
14975
16419
  "04000561": Object.freeze({ tag: "04000561", keyword: "Original Attributes Sequence", basicProfile: "X", optionSet: Object.freeze({}) }),
14976
- "04000562": Object.freeze({ tag: "04000562", keyword: "Attribute Modification DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16420
+ "04000562": Object.freeze({ tag: "04000562", keyword: "Attribute Modification DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14977
16421
  "04000563": Object.freeze({ tag: "04000563", keyword: "Modifying System", basicProfile: "D", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
14978
16422
  "04000564": Object.freeze({ tag: "04000564", keyword: "Source of Previous Values", basicProfile: "Z", optionSet: Object.freeze({ "RetainInstitutionIdentity": "K" }) }),
14979
16423
  "04000565": Object.freeze({ tag: "04000565", keyword: "Reason for the Attribute Modification", basicProfile: "D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14980
16424
  "04000600": Object.freeze({ tag: "04000600", keyword: "Instance Origin Status", basicProfile: "X", optionSet: Object.freeze({}) }),
14981
16425
  "20300020": Object.freeze({ tag: "20300020", keyword: "Text String", basicProfile: "X", optionSet: Object.freeze({}) }),
14982
- "21000040": Object.freeze({ tag: "21000040", keyword: "Creation Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14983
- "21000050": Object.freeze({ tag: "21000050", keyword: "Creation Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16426
+ "21000040": Object.freeze({ tag: "21000040", keyword: "Creation Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16427
+ "21000050": Object.freeze({ tag: "21000050", keyword: "Creation Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14984
16428
  "21000070": Object.freeze({ tag: "21000070", keyword: "Originator", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "C" }) }),
14985
16429
  "21000140": Object.freeze({ tag: "21000140", keyword: "Destination AE", basicProfile: "D", optionSet: Object.freeze({ "RetainDeviceIdentity": "C" }) }),
14986
16430
  "22000002": Object.freeze({ tag: "22000002", keyword: "Label Text", basicProfile: "X/Z", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14987
16431
  "22000005": Object.freeze({ tag: "22000005", keyword: "Barcode Value", basicProfile: "X/Z", optionSet: Object.freeze({}) }),
14988
16432
  "30020121": Object.freeze({ tag: "30020121", keyword: "Position Acquisition Template Name", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14989
16433
  "30020123": Object.freeze({ tag: "30020123", keyword: "Position Acquisition Template Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
16434
+ "3004007F": Object.freeze({ tag: "3004007F", keyword: "Dose Calculation Model Name", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14990
16435
  "30060002": Object.freeze({ tag: "30060002", keyword: "Structure Set Label", basicProfile: "D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14991
16436
  "30060004": Object.freeze({ tag: "30060004", keyword: "Structure Set Name", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14992
16437
  "30060006": Object.freeze({ tag: "30060006", keyword: "Structure Set Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14993
- "30060008": Object.freeze({ tag: "30060008", keyword: "Structure Set Date", basicProfile: "Z", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14994
- "30060009": Object.freeze({ tag: "30060009", keyword: "Structure Set Time", basicProfile: "Z", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16438
+ "30060008": Object.freeze({ tag: "30060008", keyword: "Structure Set Date", basicProfile: "Z", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16439
+ "30060009": Object.freeze({ tag: "30060009", keyword: "Structure Set Time", basicProfile: "Z", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
14995
16440
  "30060024": Object.freeze({ tag: "30060024", keyword: "Referenced Frame of Reference UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
14996
16441
  "30060026": Object.freeze({ tag: "30060026", keyword: "ROI Name", basicProfile: "Z", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14997
16442
  "30060028": Object.freeze({ tag: "30060028", keyword: "ROI Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
14998
- "3006002D": Object.freeze({ tag: "3006002D", keyword: "ROI DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
14999
- "3006002E": Object.freeze({ tag: "3006002E", keyword: "ROI Observation DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16443
+ "3006002D": Object.freeze({ tag: "3006002D", keyword: "ROI DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16444
+ "3006002E": Object.freeze({ tag: "3006002E", keyword: "ROI Observation DateTime", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
15000
16445
  "30060038": Object.freeze({ tag: "30060038", keyword: "ROI Generation Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
15001
16446
  "3006004D": Object.freeze({ tag: "3006004D", keyword: "ROI Creator Sequence", basicProfile: "X", optionSet: Object.freeze({}) }),
15002
16447
  "3006004E": Object.freeze({ tag: "3006004E", keyword: "ROI Interpreter Sequence", basicProfile: "X", optionSet: Object.freeze({}) }),
@@ -15004,22 +16449,22 @@ var ANNEX_E = Object.freeze({
15004
16449
  "30060088": Object.freeze({ tag: "30060088", keyword: "ROI Observation Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
15005
16450
  "300600A6": Object.freeze({ tag: "300600A6", keyword: "ROI Interpreter", basicProfile: "Z", optionSet: Object.freeze({}) }),
15006
16451
  "300600C2": Object.freeze({ tag: "300600C2", keyword: "Related Frame of Reference UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
15007
- "30080024": Object.freeze({ tag: "30080024", keyword: "Treatment Control Point Date", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
15008
- "30080025": Object.freeze({ tag: "30080025", keyword: "Treatment Control Point Time", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
15009
- "30080054": Object.freeze({ tag: "30080054", keyword: "First Treatment Date", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
15010
- "30080056": Object.freeze({ tag: "30080056", keyword: "Most Recent Treatment Date", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16452
+ "30080024": Object.freeze({ tag: "30080024", keyword: "Treatment Control Point Date", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16453
+ "30080025": Object.freeze({ tag: "30080025", keyword: "Treatment Control Point Time", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16454
+ "30080054": Object.freeze({ tag: "30080054", keyword: "First Treatment Date", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16455
+ "30080056": Object.freeze({ tag: "30080056", keyword: "Most Recent Treatment Date", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
15011
16456
  "30080105": Object.freeze({ tag: "30080105", keyword: "Source Serial Number", basicProfile: "X/Z", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
15012
- "30080162": Object.freeze({ tag: "30080162", keyword: "Safe Position Exit Date", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
15013
- "30080164": Object.freeze({ tag: "30080164", keyword: "Safe Position Exit Time", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
15014
- "30080166": Object.freeze({ tag: "30080166", keyword: "Safe Position Return Date", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
15015
- "30080168": Object.freeze({ tag: "30080168", keyword: "Safe Position Return Time", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
15016
- "30080250": Object.freeze({ tag: "30080250", keyword: "Treatment Date", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
15017
- "30080251": Object.freeze({ tag: "30080251", keyword: "Treatment Time", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16457
+ "30080162": Object.freeze({ tag: "30080162", keyword: "Safe Position Exit Date", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16458
+ "30080164": Object.freeze({ tag: "30080164", keyword: "Safe Position Exit Time", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16459
+ "30080166": Object.freeze({ tag: "30080166", keyword: "Safe Position Return Date", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16460
+ "30080168": Object.freeze({ tag: "30080168", keyword: "Safe Position Return Time", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16461
+ "30080250": Object.freeze({ tag: "30080250", keyword: "Treatment Date", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16462
+ "30080251": Object.freeze({ tag: "30080251", keyword: "Treatment Time", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
15018
16463
  "300A0002": Object.freeze({ tag: "300A0002", keyword: "RT Plan Label", basicProfile: "D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
15019
16464
  "300A0003": Object.freeze({ tag: "300A0003", keyword: "RT Plan Name", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
15020
16465
  "300A0004": Object.freeze({ tag: "300A0004", keyword: "RT Plan Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
15021
- "300A0006": Object.freeze({ tag: "300A0006", keyword: "RT Plan Date", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
15022
- "300A0007": Object.freeze({ tag: "300A0007", keyword: "RT Plan Time", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16466
+ "300A0006": Object.freeze({ tag: "300A0006", keyword: "RT Plan Date", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16467
+ "300A0007": Object.freeze({ tag: "300A0007", keyword: "RT Plan Time", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
15023
16468
  "300A000B": Object.freeze({ tag: "300A000B", keyword: "Treatment Sites", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
15024
16469
  "300A000E": Object.freeze({ tag: "300A000E", keyword: "Prescription Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
15025
16470
  "300A0013": Object.freeze({ tag: "300A0013", keyword: "Dose Reference UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
@@ -15034,8 +16479,8 @@ var ANNEX_E = Object.freeze({
15034
16479
  "300A01A6": Object.freeze({ tag: "300A01A6", keyword: "Shielding Device Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
15035
16480
  "300A01B2": Object.freeze({ tag: "300A01B2", keyword: "Setup Technique Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
15036
16481
  "300A0216": Object.freeze({ tag: "300A0216", keyword: "Source Manufacturer", basicProfile: "X", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
15037
- "300A022C": Object.freeze({ tag: "300A022C", keyword: "Source Strength Reference Date", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
15038
- "300A022E": Object.freeze({ tag: "300A022E", keyword: "Source Strength Reference Time", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16482
+ "300A022C": Object.freeze({ tag: "300A022C", keyword: "Source Strength Reference Date", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16483
+ "300A022E": Object.freeze({ tag: "300A022E", keyword: "Source Strength Reference Time", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
15039
16484
  "300A02EB": Object.freeze({ tag: "300A02EB", keyword: "Compensator Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
15040
16485
  "300A0608": Object.freeze({ tag: "300A0608", keyword: "Treatment Position Group Label", basicProfile: "D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
15041
16486
  "300A0609": Object.freeze({ tag: "300A0609", keyword: "Treatment Position Group UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
@@ -15050,11 +16495,11 @@ var ANNEX_E = Object.freeze({
15050
16495
  "300A067D": Object.freeze({ tag: "300A067D", keyword: "Radiation Generation Mode Description", basicProfile: "Z", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
15051
16496
  "300A0700": Object.freeze({ tag: "300A0700", keyword: "Treatment Session UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
15052
16497
  "300A0734": Object.freeze({ tag: "300A0734", keyword: "Treatment Tolerance Violation Description", basicProfile: "D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
15053
- "300A0736": Object.freeze({ tag: "300A0736", keyword: "Treatment Tolerance Violation DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
15054
- "300A073A": Object.freeze({ tag: "300A073A", keyword: "Recorded RT Control Point DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
15055
- "300A0741": Object.freeze({ tag: "300A0741", keyword: "Interlock DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16498
+ "300A0736": Object.freeze({ tag: "300A0736", keyword: "Treatment Tolerance Violation DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16499
+ "300A073A": Object.freeze({ tag: "300A073A", keyword: "Recorded RT Control Point DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16500
+ "300A0741": Object.freeze({ tag: "300A0741", keyword: "Interlock DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
15056
16501
  "300A0742": Object.freeze({ tag: "300A0742", keyword: "Interlock Description", basicProfile: "D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
15057
- "300A0760": Object.freeze({ tag: "300A0760", keyword: "Override DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16502
+ "300A0760": Object.freeze({ tag: "300A0760", keyword: "Override DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
15058
16503
  "300A0783": Object.freeze({ tag: "300A0783", keyword: "Interlock Origin Description", basicProfile: "D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
15059
16504
  "300A0785": Object.freeze({ tag: "300A0785", keyword: "Referenced Treatment Position Group UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
15060
16505
  "300A078E": Object.freeze({ tag: "300A078E", keyword: "Patient Treatment Preparation Procedure Parameter Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
@@ -15062,9 +16507,9 @@ var ANNEX_E = Object.freeze({
15062
16507
  "300A0794": Object.freeze({ tag: "300A0794", keyword: "Patient Setup Photo Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
15063
16508
  "300A079A": Object.freeze({ tag: "300A079A", keyword: "Displacement Reference Label", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
15064
16509
  "300C0113": Object.freeze({ tag: "300C0113", keyword: "Reason for Omission Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
15065
- "300C0127": Object.freeze({ tag: "300C0127", keyword: "Beam Hold Transition DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K" }) }),
15066
- "300E0004": Object.freeze({ tag: "300E0004", keyword: "Review Date", basicProfile: "Z", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
15067
- "300E0005": Object.freeze({ tag: "300E0005", keyword: "Review Time", basicProfile: "Z", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16510
+ "300C0127": Object.freeze({ tag: "300C0127", keyword: "Beam Hold Transition DateTime", basicProfile: "D", optionSet: Object.freeze({ "RetainDeviceIdentity": "K", "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16511
+ "300E0004": Object.freeze({ tag: "300E0004", keyword: "Review Date", basicProfile: "Z", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16512
+ "300E0005": Object.freeze({ tag: "300E0005", keyword: "Review Time", basicProfile: "Z", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
15068
16513
  "300E0008": Object.freeze({ tag: "300E0008", keyword: "Reviewer Name", basicProfile: "X/Z", optionSet: Object.freeze({}) }),
15069
16514
  "30100006": Object.freeze({ tag: "30100006", keyword: "Conceptual Volume UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
15070
16515
  "3010000B": Object.freeze({ tag: "3010000B", keyword: "Referenced Conceptual Volume UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
@@ -15083,8 +16528,8 @@ var ANNEX_E = Object.freeze({
15083
16528
  "30100038": Object.freeze({ tag: "30100038", keyword: "Entity Long Label", basicProfile: "D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
15084
16529
  "3010003B": Object.freeze({ tag: "3010003B", keyword: "RT Treatment Phase UID", basicProfile: "U", optionSet: Object.freeze({ "RetainUIDs": "K" }) }),
15085
16530
  "30100043": Object.freeze({ tag: "30100043", keyword: "Manufacturer's Device Identifier", basicProfile: "Z", optionSet: Object.freeze({ "RetainDeviceIdentity": "K" }) }),
15086
- "3010004C": Object.freeze({ tag: "3010004C", keyword: "Intended Phase Start Date", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
15087
- "3010004D": Object.freeze({ tag: "3010004D", keyword: "Intended Phase End Date", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16531
+ "3010004C": Object.freeze({ tag: "3010004C", keyword: "Intended Phase Start Date", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16532
+ "3010004D": Object.freeze({ tag: "3010004D", keyword: "Intended Phase End Date", basicProfile: "X/D", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
15088
16533
  "30100054": Object.freeze({ tag: "30100054", keyword: "RT Prescription Label", basicProfile: "D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
15089
16534
  "30100056": Object.freeze({ tag: "30100056", keyword: "RT Treatment Approach Label", basicProfile: "X/D", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
15090
16535
  "3010005A": Object.freeze({ tag: "3010005A", keyword: "RT Physician Intent Narrative", basicProfile: "Z", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
@@ -15097,22 +16542,22 @@ var ANNEX_E = Object.freeze({
15097
16542
  "3010007B": Object.freeze({ tag: "3010007B", keyword: "Prescription Notes", basicProfile: "Z", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
15098
16543
  "3010007F": Object.freeze({ tag: "3010007F", keyword: "Fractionation Notes", basicProfile: "Z", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
15099
16544
  "30100081": Object.freeze({ tag: "30100081", keyword: "Prescription Notes Sequence", basicProfile: "Z", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
15100
- "30100085": Object.freeze({ tag: "30100085", keyword: "Intended Fraction Start Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16545
+ "30100085": Object.freeze({ tag: "30100085", keyword: "Intended Fraction Start Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
15101
16546
  "40000010": Object.freeze({ tag: "40000010", keyword: "Arbitrary", basicProfile: "X", optionSet: Object.freeze({}) }),
15102
16547
  "40004000": Object.freeze({ tag: "40004000", keyword: "Text Comments", basicProfile: "X", optionSet: Object.freeze({}) }),
15103
16548
  "40080040": Object.freeze({ tag: "40080040", keyword: "Results ID", basicProfile: "X", optionSet: Object.freeze({}) }),
15104
16549
  "40080042": Object.freeze({ tag: "40080042", keyword: "Results ID Issuer", basicProfile: "X", optionSet: Object.freeze({}) }),
15105
- "40080100": Object.freeze({ tag: "40080100", keyword: "Interpretation Recorded Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
15106
- "40080101": Object.freeze({ tag: "40080101", keyword: "Interpretation Recorded Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16550
+ "40080100": Object.freeze({ tag: "40080100", keyword: "Interpretation Recorded Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16551
+ "40080101": Object.freeze({ tag: "40080101", keyword: "Interpretation Recorded Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
15107
16552
  "40080102": Object.freeze({ tag: "40080102", keyword: "Interpretation Recorder", basicProfile: "X", optionSet: Object.freeze({}) }),
15108
- "40080108": Object.freeze({ tag: "40080108", keyword: "Interpretation Transcription Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
15109
- "40080109": Object.freeze({ tag: "40080109", keyword: "Interpretation Transcription Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16553
+ "40080108": Object.freeze({ tag: "40080108", keyword: "Interpretation Transcription Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16554
+ "40080109": Object.freeze({ tag: "40080109", keyword: "Interpretation Transcription Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
15110
16555
  "4008010A": Object.freeze({ tag: "4008010A", keyword: "Interpretation Transcriber", basicProfile: "X", optionSet: Object.freeze({}) }),
15111
16556
  "4008010B": Object.freeze({ tag: "4008010B", keyword: "Interpretation Text", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
15112
16557
  "4008010C": Object.freeze({ tag: "4008010C", keyword: "Interpretation Author", basicProfile: "X", optionSet: Object.freeze({}) }),
15113
16558
  "40080111": Object.freeze({ tag: "40080111", keyword: "Interpretation Approver Sequence", basicProfile: "X", optionSet: Object.freeze({}) }),
15114
- "40080112": Object.freeze({ tag: "40080112", keyword: "Interpretation Approval Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
15115
- "40080113": Object.freeze({ tag: "40080113", keyword: "Interpretation Approval Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K" }) }),
16559
+ "40080112": Object.freeze({ tag: "40080112", keyword: "Interpretation Approval Date", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
16560
+ "40080113": Object.freeze({ tag: "40080113", keyword: "Interpretation Approval Time", basicProfile: "X", optionSet: Object.freeze({ "RetainLongitudinalTemporal": "K", "RetainLongitudinalTemporalModifiedDates": "C" }) }),
15116
16561
  "40080114": Object.freeze({ tag: "40080114", keyword: "Physician Approving Interpretation", basicProfile: "X", optionSet: Object.freeze({}) }),
15117
16562
  "40080115": Object.freeze({ tag: "40080115", keyword: "Interpretation Diagnosis Description", basicProfile: "X", optionSet: Object.freeze({ "CleanDescriptors": "C" }) }),
15118
16563
  "40080118": Object.freeze({ tag: "40080118", keyword: "Results Distribution List Sequence", basicProfile: "X", optionSet: Object.freeze({}) }),
@@ -15182,6 +16627,73 @@ function matchRepeatingRule(upper) {
15182
16627
  }
15183
16628
  return void 0;
15184
16629
  }
16630
+
16631
+ // src/dictionary/registered.ts
16632
+ var CONCRETE_TAG_RE = /^[0-9A-F]{8}$/;
16633
+ var MASK_CHAR = "x";
16634
+ var MASKED_ROWS = Object.freeze(
16635
+ Object.keys(TAGS).filter((key) => key.includes(MASK_CHAR))
16636
+ );
16637
+ function isSection76Family(pattern) {
16638
+ return REPEATING_GROUP_RANGES[pattern.slice(0, 2).toUpperCase()] !== void 0 && pattern.slice(2, 4) === MASK_CHAR + MASK_CHAR;
16639
+ }
16640
+ function matchesMaskedRow(pattern, tag) {
16641
+ if (isSection76Family(pattern)) return matchesRepeatingPattern(pattern, tag);
16642
+ for (let i = 0; i < pattern.length; i++) {
16643
+ const printed = pattern.charAt(i);
16644
+ if (printed === MASK_CHAR) continue;
16645
+ if (printed.toUpperCase() !== tag.charAt(i)) return false;
16646
+ }
16647
+ return true;
16648
+ }
16649
+ function isRegisteredTag(tag) {
16650
+ if (typeof tag !== "string") return false;
16651
+ const upper = tag.toUpperCase();
16652
+ if (!CONCRETE_TAG_RE.test(upper)) return false;
16653
+ if (Object.prototype.hasOwnProperty.call(TAGS, upper)) return true;
16654
+ return MASKED_ROWS.some((pattern) => matchesMaskedRow(pattern, upper));
16655
+ }
16656
+
16657
+ // src/deident/types.ts
16658
+ var DEIDENTIFY_OPTIONS = Object.freeze([
16659
+ "CleanGraphics",
16660
+ "CleanStructuredContent",
16661
+ "CleanDescriptors",
16662
+ "RetainLongitudinalTemporal",
16663
+ "RetainLongitudinalTemporalModifiedDates",
16664
+ "RetainPatientCharacteristics",
16665
+ "RetainDeviceIdentity",
16666
+ "RetainUIDs",
16667
+ "RetainSafePrivate",
16668
+ "RetainInstitutionIdentity"
16669
+ ]);
16670
+ var DEIDENTIFY_ERROR_CODES = Object.freeze({
16671
+ INVALID_OPTIONS: "INVALID_OPTIONS",
16672
+ UNSUPPORTED_TRANSFER_SYNTAX: "UNSUPPORTED_TRANSFER_SYNTAX"
16673
+ });
16674
+ var DeidentifyError = class extends Error {
16675
+ code;
16676
+ /**
16677
+ * @param message Human-readable, PHI-free description.
16678
+ * @param code One of {@link DEIDENTIFY_ERROR_CODES}.
16679
+ */
16680
+ constructor(message, code) {
16681
+ super(message);
16682
+ this.name = "DeidentifyError";
16683
+ this.code = code;
16684
+ }
16685
+ };
16686
+
16687
+ // src/deident/actions.ts
16688
+ function effectiveCode(action, active) {
16689
+ for (const opt of DEIDENTIFY_OPTIONS) {
16690
+ if (active.has(opt)) {
16691
+ const override = action.optionSet[opt];
16692
+ if (override !== void 0) return override;
16693
+ }
16694
+ }
16695
+ return action.basicProfile;
16696
+ }
15185
16697
  function resolveAction(code) {
15186
16698
  const first = code.split("/", 1)[0]?.replace("*", "") ?? "K";
15187
16699
  return first;
@@ -15223,7 +16735,7 @@ function uidValueMultiplicity(rawBytes) {
15223
16735
  }
15224
16736
 
15225
16737
  // src/deident/embedded.ts
15226
- var UNDEFINED_LENGTH4 = 4294967295;
16738
+ var UNDEFINED_LENGTH7 = 4294967295;
15227
16739
  var FFFE_GROUP = 65534;
15228
16740
  var SCANNABLE_CARRIER_VRS = /* @__PURE__ */ new Set([
15229
16741
  "AE",
@@ -15278,7 +16790,7 @@ function decodeAt(value, off, encoding) {
15278
16790
  const tag = joinTag(group, element);
15279
16791
  if (encoding === "implicit") {
15280
16792
  const length2 = readU32(value, off + 4, littleEndian);
15281
- if (length2 === UNDEFINED_LENGTH4 || length2 % 2 !== 0) return void 0;
16793
+ if (length2 === UNDEFINED_LENGTH7 || length2 % 2 !== 0) return void 0;
15282
16794
  const next2 = off + 8 + length2;
15283
16795
  return next2 > value.length ? void 0 : { next: next2, tag };
15284
16796
  }
@@ -15288,7 +16800,7 @@ function decodeAt(value, off, encoding) {
15288
16800
  if (off + 12 > value.length) return void 0;
15289
16801
  if (value[off + 6] !== 0 || value[off + 7] !== 0) return void 0;
15290
16802
  const length2 = readU32(value, off + 8, littleEndian);
15291
- if (length2 === UNDEFINED_LENGTH4 || length2 % 2 !== 0) return void 0;
16803
+ if (length2 === UNDEFINED_LENGTH7 || length2 % 2 !== 0) return void 0;
15292
16804
  const next2 = off + 12 + length2;
15293
16805
  return next2 > value.length ? void 0 : { next: next2, tag };
15294
16806
  }
@@ -15355,33 +16867,64 @@ function findEmbeddedAttributes(value, carrierVr, encoding, isActionable) {
15355
16867
  return void 0;
15356
16868
  }
15357
16869
 
15358
- // src/deident/types.ts
15359
- var DEIDENTIFY_OPTIONS = Object.freeze([
15360
- "CleanGraphics",
15361
- "CleanStructuredContent",
15362
- "CleanDescriptors",
15363
- "RetainLongitudinalTemporal",
15364
- "RetainPatientCharacteristics",
15365
- "RetainDeviceIdentity",
15366
- "RetainUIDs",
15367
- "RetainSafePrivate",
15368
- "RetainInstitutionIdentity"
15369
- ]);
15370
- var DEIDENTIFY_ERROR_CODES = Object.freeze({
15371
- INVALID_OPTIONS: "INVALID_OPTIONS"
16870
+ // src/deident/method-codes.ts
16871
+ function row(codeValue, codeMeaning) {
16872
+ return Object.freeze({ codeValue, codingSchemeDesignator: "DCM", codeMeaning });
16873
+ }
16874
+ var BASIC_PROFILE = row("113100", "Basic Application Confidentiality Profile");
16875
+ var CLEAN_PIXEL_DATA = row("113101", "Clean Pixel Data Option");
16876
+ var CLEAN_RECOGNIZABLE_VISUAL_FEATURES = row(
16877
+ "113102",
16878
+ "Clean Recognizable Visual Features Option"
16879
+ );
16880
+ var CLEAN_GRAPHICS = row("113103", "Clean Graphics Option");
16881
+ var CLEAN_STRUCTURED_CONTENT = row("113104", "Clean Structured Content Option");
16882
+ var CLEAN_DESCRIPTORS = row("113105", "Clean Descriptors Option");
16883
+ var RETAIN_TEMPORAL_FULL_DATES = row(
16884
+ "113106",
16885
+ "Retain Longitudinal Temporal Information Full Dates Option"
16886
+ );
16887
+ var RETAIN_TEMPORAL_MODIFIED_DATES = row(
16888
+ "113107",
16889
+ "Retain Longitudinal Temporal Information Modified Dates Option"
16890
+ );
16891
+ var RETAIN_PATIENT_CHARACTERISTICS = row("113108", "Retain Patient Characteristics Option");
16892
+ var RETAIN_DEVICE_IDENTITY = row("113109", "Retain Device Identity Option");
16893
+ var RETAIN_UIDS = row("113110", "Retain UIDs Option");
16894
+ var RETAIN_SAFE_PRIVATE = row("113111", "Retain Safe Private Option");
16895
+ var RETAIN_INSTITUTION_IDENTITY = row("113112", "Retain Institution Identity Option");
16896
+ var DEIDENTIFICATION_METHOD_CODES = Object.freeze({
16897
+ contextGroupUid: "1.2.840.10008.6.1.925",
16898
+ contextGroupVersion: "20170914",
16899
+ rows: Object.freeze([
16900
+ BASIC_PROFILE,
16901
+ CLEAN_PIXEL_DATA,
16902
+ CLEAN_RECOGNIZABLE_VISUAL_FEATURES,
16903
+ CLEAN_GRAPHICS,
16904
+ CLEAN_STRUCTURED_CONTENT,
16905
+ CLEAN_DESCRIPTORS,
16906
+ RETAIN_TEMPORAL_FULL_DATES,
16907
+ RETAIN_TEMPORAL_MODIFIED_DATES,
16908
+ RETAIN_PATIENT_CHARACTERISTICS,
16909
+ RETAIN_DEVICE_IDENTITY,
16910
+ RETAIN_UIDS,
16911
+ RETAIN_SAFE_PRIVATE,
16912
+ RETAIN_INSTITUTION_IDENTITY
16913
+ ]),
16914
+ profile: BASIC_PROFILE,
16915
+ options: Object.freeze({
16916
+ CleanGraphics: CLEAN_GRAPHICS,
16917
+ CleanStructuredContent: CLEAN_STRUCTURED_CONTENT,
16918
+ CleanDescriptors: CLEAN_DESCRIPTORS,
16919
+ RetainLongitudinalTemporal: RETAIN_TEMPORAL_FULL_DATES,
16920
+ RetainLongitudinalTemporalModifiedDates: RETAIN_TEMPORAL_MODIFIED_DATES,
16921
+ RetainPatientCharacteristics: RETAIN_PATIENT_CHARACTERISTICS,
16922
+ RetainDeviceIdentity: RETAIN_DEVICE_IDENTITY,
16923
+ RetainUIDs: RETAIN_UIDS,
16924
+ RetainSafePrivate: RETAIN_SAFE_PRIVATE,
16925
+ RetainInstitutionIdentity: RETAIN_INSTITUTION_IDENTITY
16926
+ })
15372
16927
  });
15373
- var DeidentifyError = class extends Error {
15374
- code;
15375
- /**
15376
- * @param message Human-readable, PHI-free description.
15377
- * @param code One of {@link DEIDENTIFY_ERROR_CODES}.
15378
- */
15379
- constructor(message, code) {
15380
- super(message);
15381
- this.name = "DeidentifyError";
15382
- this.code = code;
15383
- }
15384
- };
15385
16928
  var DEFAULT_UID_ROOT = "2.25";
15386
16929
  var ROOT_RE = /^[0-9]+(\.[0-9]+)*$/;
15387
16930
  var MAX_UID_LENGTH = 64;
@@ -15418,8 +16961,51 @@ function deriveUid(root, sourceUid) {
15418
16961
  // src/deident/deidentify.ts
15419
16962
  var TAG_PATIENT_IDENTITY_REMOVED = "00120062";
15420
16963
  var TAG_DEIDENTIFICATION_METHOD = "00120063";
16964
+ var TAG_DEIDENTIFICATION_METHOD_CODE_SEQUENCE = "00120064";
16965
+ var TAG_CODE_VALUE = "00080100";
16966
+ var TAG_CODING_SCHEME_DESIGNATOR = "00080102";
16967
+ var TAG_CODE_MEANING = "00080104";
15421
16968
  var TAG_PIXEL_DATA = "7FE00010";
15422
16969
  var TAG_BURNED_IN_ANNOTATION = "00280301";
16970
+ var TAG_LONGITUDINAL_TEMPORAL_INFORMATION_MODIFIED = "00280303";
16971
+ var TAG_PRIVATE_DATA_ELEMENT_CHARACTERISTICS_SEQUENCE = "00080300";
16972
+ var TAG_PRIVATE_GROUP_REFERENCE = "00080301";
16973
+ var TAG_PRIVATE_CREATOR_REFERENCE = "00080302";
16974
+ var TAG_BLOCK_IDENTIFYING_INFORMATION_STATUS = "00080303";
16975
+ var TAG_NONIDENTIFYING_PRIVATE_ELEMENTS = "00080304";
16976
+ var TEMPORAL_OPTIONS = Object.freeze([
16977
+ "RetainLongitudinalTemporal",
16978
+ "RetainLongitudinalTemporalModifiedDates"
16979
+ ]);
16980
+ var TEMPORAL_STATE = {
16981
+ removed: "REMOVED",
16982
+ unmodified: "UNMODIFIED",
16983
+ modified: "MODIFIED"
16984
+ };
16985
+ function temporalState(active) {
16986
+ if (active.has("RetainLongitudinalTemporalModifiedDates")) return TEMPORAL_STATE.modified;
16987
+ if (active.has("RetainLongitudinalTemporal")) return TEMPORAL_STATE.unmodified;
16988
+ return TEMPORAL_STATE.removed;
16989
+ }
16990
+ var GROUP_0004_PREFIX = "0004";
16991
+ var GROUP_LENGTH_ELEMENT = 0;
16992
+ var FILE_META_GROUP = 2;
16993
+ var MEDIA_STORAGE_DIRECTORY_STORAGE_UID2 = "1.2.840.10008.1.3.10";
16994
+ var MAX_FILE_META_DROP_FINDINGS = 64;
16995
+ var MAX_GROUP_0004_FINDINGS = 64;
16996
+ var MAX_UNREGISTERED_ELEMENT_FINDINGS = 64;
16997
+ var REFUSED_TRANSFER_SYNTAXES = new Set(JPIP_REFERENCED_UIDS);
16998
+ var REFUSED_TRANSFER_SYNTAX_MESSAGE = "deidentify does not de-identify an object under a JPIP Referenced Transfer Syntax (PS3.5 2026c sections A.6, A.7, A.11 and A.12): its Pixel Data Provider URL (0028,7FE0) has no PS3.15 Table E.1-1 action and would be kept by omission. Nothing was de-identified.";
16999
+ function isRefusedTransferSyntax(transferSyntaxUID) {
17000
+ if (transferSyntaxUID === void 0) return false;
17001
+ let end = transferSyntaxUID.length;
17002
+ while (end > 0) {
17003
+ const last = transferSyntaxUID.charCodeAt(end - 1);
17004
+ if (last !== 0 && last !== 32) break;
17005
+ end -= 1;
17006
+ }
17007
+ return REFUSED_TRANSFER_SYNTAXES.has(transferSyntaxUID.slice(0, end));
17008
+ }
15423
17009
  var BODY_ENCODING2 = {
15424
17010
  "1.2.840.10008.1.2": "implicit",
15425
17011
  "1.2.840.10008.1.2.1": "explicitLE",
@@ -15428,6 +17014,7 @@ var BODY_ENCODING2 = {
15428
17014
  };
15429
17015
  var MAX_UNAUDITABLE_SEQUENCE_FINDINGS = 64;
15430
17016
  var MAX_UNDEFINED_VR_FINDINGS = 64;
17017
+ var MAX_PRIVATE_DECLARATION_WARNINGS = 64;
15431
17018
  function validateRetain(retain) {
15432
17019
  const valid = new Set(DEIDENTIFY_OPTIONS);
15433
17020
  const active = /* @__PURE__ */ new Set();
@@ -15440,16 +17027,13 @@ function validateRetain(retain) {
15440
17027
  }
15441
17028
  active.add(opt);
15442
17029
  }
15443
- return active;
15444
- }
15445
- function effectiveCode(action, active) {
15446
- for (const opt of DEIDENTIFY_OPTIONS) {
15447
- if (active.has(opt)) {
15448
- const override = action.optionSet[opt];
15449
- if (override !== void 0) return override;
15450
- }
17030
+ if (TEMPORAL_OPTIONS.every((opt) => active.has(opt))) {
17031
+ throw new DeidentifyError(
17032
+ `The PS3.15 E.3.6 Retain Longitudinal Temporal Information Options are mutually exclusive; ${TEMPORAL_OPTIONS.join(" and ")} cannot both be active in one call. Pass at most one.`,
17033
+ "INVALID_OPTIONS"
17034
+ );
15451
17035
  }
15452
- return action.basicProfile;
17036
+ return active;
15453
17037
  }
15454
17038
  function freshScalar(orig, value, vm) {
15455
17039
  const init = {
@@ -15507,19 +17091,7 @@ function encodeSequenceValue(items, encoding) {
15507
17091
  }
15508
17092
  function rebuildSequence(orig, items, encoding) {
15509
17093
  const value = encodeSequenceValue(items, encoding);
15510
- let rawBytes;
15511
- if (encoding === "implicit") {
15512
- rawBytes = value;
15513
- } else {
15514
- const littleEndian = encoding === "explicitLE";
15515
- const { group, element } = splitTag(orig.tag);
15516
- const header = buffer.Buffer.alloc(12);
15517
- le16(header, group, 0, littleEndian);
15518
- le16(header, element, 2, littleEndian);
15519
- header.write("SQ", 4, "ascii");
15520
- le32(header, value.length, 8, littleEndian);
15521
- rawBytes = buffer.Buffer.concat([header, value]);
15522
- }
17094
+ const rawBytes = sequenceRawBytes(orig.tag, value, encoding);
15523
17095
  const init = {
15524
17096
  tag: orig.tag,
15525
17097
  vr: "SQ",
@@ -15534,6 +17106,30 @@ function rebuildSequence(orig, items, encoding) {
15534
17106
  };
15535
17107
  return new Element(init);
15536
17108
  }
17109
+ function sequenceRawBytes(tag, value, encoding) {
17110
+ if (encoding === "implicit") return value;
17111
+ const littleEndian = encoding === "explicitLE";
17112
+ const { group, element } = splitTag(tag);
17113
+ const header = buffer.Buffer.alloc(12);
17114
+ le16(header, group, 0, littleEndian);
17115
+ le16(header, element, 2, littleEndian);
17116
+ header.write("SQ", 4, "ascii");
17117
+ le32(header, value.length, 8, littleEndian);
17118
+ return buffer.Buffer.concat([header, value]);
17119
+ }
17120
+ function insertedSequence(tag, items, encoding) {
17121
+ const value = encodeSequenceValue(items, encoding);
17122
+ return new Element({
17123
+ tag,
17124
+ vr: "SQ",
17125
+ vm: items.length,
17126
+ length: value.length,
17127
+ rawBytes: sequenceRawBytes(tag, value, encoding),
17128
+ byteOffset: 0,
17129
+ littleEndian: encoding !== "explicitBE",
17130
+ items
17131
+ });
17132
+ }
15537
17133
  function decodeCreator(el) {
15538
17134
  return el.rawBytes.toString("latin1").replace(/[\0 ]+$/, "").trim();
15539
17135
  }
@@ -15589,17 +17185,57 @@ function isUnauditableSequence(el) {
15589
17185
  function emptyUnauditableSequence(el, ctx, contextPath, out) {
15590
17186
  emptyUnauditableCarrier(el, ctx, contextPath, out, rebuildSequence(el, [], ctx.encoding));
15591
17187
  }
17188
+ function isGroup0004(tag) {
17189
+ return tag.slice(0, 4) === GROUP_0004_PREFIX;
17190
+ }
17191
+ function recordGroup0004Removal(tag, ctx, contextPath) {
17192
+ ctx.group0004.total++;
17193
+ if (ctx.group0004.findings.length >= MAX_GROUP_0004_FINDINGS) return;
17194
+ ctx.group0004.findings.push({
17195
+ tag,
17196
+ applied: "removed",
17197
+ ...contextPath.length > 0 ? { contextPath: [...contextPath] } : {}
17198
+ });
17199
+ }
17200
+ function isUnregisteredStandardTag(tag) {
17201
+ const { group, element } = splitTag(tag);
17202
+ if (element === GROUP_LENGTH_ELEMENT) return false;
17203
+ if (group === FILE_META_GROUP || isGroup0004(tag)) return false;
17204
+ return !isRegisteredTag(tag);
17205
+ }
17206
+ function removeUnregisteredElement(el, ctx, contextPath) {
17207
+ ctx.unregistered.total++;
17208
+ if (ctx.unregistered.findings.length >= MAX_UNREGISTERED_ELEMENT_FINDINGS) return;
17209
+ ctx.unregistered.findings.push({
17210
+ byteOffset: el.byteOffset,
17211
+ ...contextPath.length > 0 ? { contextPath: [...contextPath] } : {}
17212
+ });
17213
+ }
15592
17214
  function emptyUnauditableCarrier(el, ctx, contextPath, out, replacement) {
15593
17215
  out.elements.set(el.tag, replacement);
15594
17216
  if (ctx.budget.unauditableSequences >= MAX_UNAUDITABLE_SEQUENCE_FINDINGS) return;
15595
17217
  ctx.budget.unauditableSequences += 1;
15596
17218
  out.unauditableSequences.push({
15597
17219
  tag: el.tag,
17220
+ applied: "emptied",
15598
17221
  byteLength: el.rawBytes.length,
15599
17222
  ...contextPath.length > 0 ? { contextPath: [...contextPath] } : {}
15600
17223
  });
15601
17224
  out.warnings.push(sequenceNotAuditable({ byteOffset: el.byteOffset }, el.tag));
15602
17225
  }
17226
+ function removeUnenumerablePrivate(el, ctx, contextPath, out) {
17227
+ out.elements.delete(el.tag);
17228
+ out.removedPrivateTags.push(el.tag);
17229
+ out.unenumerablePrivateRemovals.push({
17230
+ tag: el.tag,
17231
+ applied: "removed",
17232
+ reason: "unenumerable",
17233
+ ...contextPath.length > 0 ? { contextPath: [...contextPath] } : {}
17234
+ });
17235
+ if (ctx.budget.unenumerableRemovals >= MAX_UNAUDITABLE_SEQUENCE_FINDINGS) return;
17236
+ ctx.budget.unenumerableRemovals += 1;
17237
+ out.warnings.push(privateCarrierNotAuditable({ byteOffset: el.byteOffset }, el.tag));
17238
+ }
15603
17239
  function creatorsInScope(source) {
15604
17240
  const byBlock = /* @__PURE__ */ new Map();
15605
17241
  for (const el of source) {
@@ -15613,28 +17249,139 @@ function creatorFor(tag, creators) {
15613
17249
  const { group, element } = splitTag(tag);
15614
17250
  return creators.get(`${String(group)}:${String(element >> 8 & 255)}`);
15615
17251
  }
15616
- var UNDEFINED_LENGTH5 = 4294967295;
17252
+ var BLOCK_STATUS = {
17253
+ safe: "SAFE",
17254
+ unsafe: "UNSAFE",
17255
+ mixed: "MIXED"
17256
+ };
17257
+ var NO_PRIVATE_DECLARATION = /* @__PURE__ */ new Map();
17258
+ function declarationKey(group, creator) {
17259
+ return `${String(group)}:${creator}`;
17260
+ }
17261
+ function decodeEnumerated(el) {
17262
+ return el.rawBytes.toString("latin1").replace(/[\0 ]+$/, "").trim();
17263
+ }
17264
+ function readUnsignedShorts(el) {
17265
+ const values = [];
17266
+ for (let offset = 0; offset + 2 <= el.rawBytes.length; offset += 2) {
17267
+ values.push(
17268
+ el.littleEndian ? el.rawBytes.readUInt16LE(offset) : el.rawBytes.readUInt16BE(offset)
17269
+ );
17270
+ }
17271
+ return values;
17272
+ }
17273
+ function reservedBlocks(source) {
17274
+ const reserved = /* @__PURE__ */ new Set();
17275
+ for (const el of source) {
17276
+ if (!isPrivateTag(el.tag) || !isPrivateCreatorElement(el.tag)) continue;
17277
+ reserved.add(declarationKey(splitTag(el.tag).group, decodeCreator(el)));
17278
+ }
17279
+ return reserved;
17280
+ }
17281
+ function intersectBlocks(first, second) {
17282
+ if (first.allSafe) return second;
17283
+ if (second.allSafe) return first;
17284
+ const both = /* @__PURE__ */ new Set();
17285
+ for (const element of first.safeElements) {
17286
+ if (second.safeElements.has(element)) both.add(element);
17287
+ }
17288
+ return { allSafe: false, safeElements: both };
17289
+ }
17290
+ var UNRESOLVED_ITEM = { resolved: false };
17291
+ function readDeclaredItem(item, reserved) {
17292
+ const groupEl = item.get(TAG_PRIVATE_GROUP_REFERENCE);
17293
+ const creatorEl = item.get(TAG_PRIVATE_CREATOR_REFERENCE);
17294
+ const statusEl = item.get(TAG_BLOCK_IDENTIFYING_INFORMATION_STATUS);
17295
+ if (groupEl === void 0 || creatorEl === void 0 || statusEl === void 0) {
17296
+ return UNRESOLVED_ITEM;
17297
+ }
17298
+ const group = readUnsignedShorts(groupEl)[0];
17299
+ if (group === void 0 || (group & 1) === 0) return UNRESOLVED_ITEM;
17300
+ const creator = decodeCreator(creatorEl);
17301
+ if (creator.length === 0) return UNRESOLVED_ITEM;
17302
+ const key = declarationKey(group, creator);
17303
+ if (!reserved.has(key)) return UNRESOLVED_ITEM;
17304
+ const status = decodeEnumerated(statusEl);
17305
+ if (status === BLOCK_STATUS.safe) {
17306
+ return { resolved: true, key, block: { allSafe: true, safeElements: /* @__PURE__ */ new Set() } };
17307
+ }
17308
+ if (status === BLOCK_STATUS.unsafe) {
17309
+ return { resolved: true, key, block: { allSafe: false, safeElements: /* @__PURE__ */ new Set() } };
17310
+ }
17311
+ if (status !== BLOCK_STATUS.mixed) return UNRESOLVED_ITEM;
17312
+ const listEl = item.get(TAG_NONIDENTIFYING_PRIVATE_ELEMENTS);
17313
+ if (listEl === void 0) return UNRESOLVED_ITEM;
17314
+ const listed = /* @__PURE__ */ new Set();
17315
+ for (const value of readUnsignedShorts(listEl)) {
17316
+ if (value <= 255) listed.add(value);
17317
+ }
17318
+ if (listed.size === 0) return UNRESOLVED_ITEM;
17319
+ return { resolved: true, key, block: { allSafe: false, safeElements: listed } };
17320
+ }
17321
+ function resolvePrivateDeclaration(source, encoding, budget, warnings) {
17322
+ const at3 = source.findIndex((el) => el.tag === TAG_PRIVATE_DATA_ELEMENT_CHARACTERISTICS_SEQUENCE);
17323
+ const declarationEl = at3 < 0 ? void 0 : source[at3];
17324
+ if (declarationEl?.items === void 0) return NO_PRIVATE_DECLARATION;
17325
+ const bound = settledBound(source, encoding);
17326
+ if (!isSettled(declarationEl, at3, bound)) return NO_PRIVATE_DECLARATION;
17327
+ const reserved = reservedBlocks(source.filter((el, index) => isSettled(el, index, bound)));
17328
+ const declaration = /* @__PURE__ */ new Map();
17329
+ for (const item of declarationEl.items) {
17330
+ const read = readDeclaredItem(item, reserved);
17331
+ if (!read.resolved) {
17332
+ if (budget.privateDeclarationItems >= MAX_PRIVATE_DECLARATION_WARNINGS) continue;
17333
+ budget.privateDeclarationItems += 1;
17334
+ warnings.push(
17335
+ privateDeclarationNotResolved({ byteOffset: declarationEl.byteOffset, fileMeta: false })
17336
+ );
17337
+ continue;
17338
+ }
17339
+ const existing = declaration.get(read.key);
17340
+ declaration.set(
17341
+ read.key,
17342
+ existing === void 0 ? read.block : intersectBlocks(existing, read.block)
17343
+ );
17344
+ }
17345
+ return declaration;
17346
+ }
17347
+ function declaredSafe(el, ctx, creators) {
17348
+ if (ctx.declaration.size === 0) return false;
17349
+ const { group, element } = splitTag(el.tag);
17350
+ if (isPrivateCreatorElement(el.tag)) {
17351
+ const block2 = ctx.declaration.get(declarationKey(group, decodeCreator(el)));
17352
+ if (block2 === void 0) return false;
17353
+ return block2.allSafe || block2.safeElements.size > 0;
17354
+ }
17355
+ const creator = creatorFor(el.tag, creators);
17356
+ if (creator === void 0) return false;
17357
+ const block = ctx.declaration.get(declarationKey(group, creator));
17358
+ if (block === void 0) return false;
17359
+ return block.allSafe || block.safeElements.has(element & 255);
17360
+ }
17361
+ var UNDEFINED_LENGTH8 = 4294967295;
15617
17362
  var EXPLICIT_SQ_HEADER_BYTES = 12;
15618
17363
  function itemStreamOverrunsSequence(el, encoding) {
15619
- if (el.vr !== "SQ" || el.length === UNDEFINED_LENGTH5) return false;
17364
+ if (el.vr !== "SQ" || el.length === UNDEFINED_LENGTH8) return false;
15620
17365
  const headerBytes = encoding === "implicit" ? 0 : EXPLICIT_SQ_HEADER_BYTES;
15621
17366
  return el.rawBytes.length - headerBytes > el.length;
15622
17367
  }
15623
17368
  function settledBound(source, encoding) {
15624
17369
  let index = source.length;
15625
17370
  let byteOffset;
15626
- for (const [at2, el] of source.entries()) {
17371
+ for (const [at3, el] of source.entries()) {
15627
17372
  if (!itemStreamOverrunsSequence(el, encoding) && !isUnauditableSequence(el)) continue;
15628
- if (index === source.length) index = at2 + 1;
17373
+ if (index === source.length) index = at3 + 1;
15629
17374
  if (byteOffset === void 0 || el.byteOffset < byteOffset) byteOffset = el.byteOffset;
15630
17375
  }
15631
17376
  return { index, byteOffset };
15632
17377
  }
15633
- function isSettled(el, at2, bound) {
15634
- return at2 < bound.index && (bound.byteOffset === void 0 || el.byteOffset <= bound.byteOffset);
17378
+ function isSettled(el, at3, bound) {
17379
+ return at3 < bound.index && (bound.byteOffset === void 0 || el.byteOffset <= bound.byteOffset);
15635
17380
  }
15636
17381
  function keepsPrivate(el, ctx, creators) {
15637
- if (!ctx.active.has("RetainSafePrivate") || ctx.profile === void 0) return false;
17382
+ if (!ctx.active.has("RetainSafePrivate")) return false;
17383
+ if (declaredSafe(el, ctx, creators)) return true;
17384
+ if (ctx.profile === void 0) return false;
15638
17385
  if (isPrivateCreatorElement(el.tag)) {
15639
17386
  return ctx.profile.privateDictionary.has(decodeCreator(el));
15640
17387
  }
@@ -15661,7 +17408,10 @@ function keepRetainedPrivate(el, ctx, contextPath, out, reservationsUsable, crea
15661
17408
  emptyUnauditableCarrier(el, ctx, contextPath, out, freshScalar(el, buffer.Buffer.alloc(0), 0));
15662
17409
  return;
15663
17410
  }
15664
- keepOrEmpty(el, ctx, contextPath, out);
17411
+ if (!keepOrEmpty(el, ctx, contextPath, out)) return;
17412
+ if (isPrivateCreatorElement(el.tag) || el.rawBytes.length === 0) return;
17413
+ if (declaredSafe(el, ctx, creators)) return;
17414
+ removeUnenumerablePrivate(el, ctx, contextPath, out);
15665
17415
  }
15666
17416
  function processElements(source, ctx, contextPath, reservationsUsable) {
15667
17417
  const out = {
@@ -15670,20 +17420,29 @@ function processElements(source, ctx, contextPath, reservationsUsable) {
15670
17420
  removedPrivateTags: [],
15671
17421
  embeddedAttributes: [],
15672
17422
  unauditableSequences: [],
17423
+ unenumerablePrivateRemovals: [],
15673
17424
  undefinedVrElements: [],
15674
17425
  warnings: []
15675
17426
  };
15676
17427
  const bound = settledBound(source, ctx.encoding);
15677
- const creators = creatorsInScope(source.filter((el, at2) => isSettled(el, at2, bound)));
15678
- for (const [at2, el] of source.entries()) {
17428
+ const creators = creatorsInScope(source.filter((el, at3) => isSettled(el, at3, bound)));
17429
+ for (const [at3, el] of source.entries()) {
17430
+ if (ctx.removeGroup0004 && isGroup0004(el.tag)) {
17431
+ recordGroup0004Removal(el.tag, ctx, contextPath);
17432
+ continue;
17433
+ }
15679
17434
  if (isPrivateTag(el.tag)) {
15680
- if (reservationsUsable && isSettled(el, at2, bound) && keepsPrivate(el, ctx, creators))
17435
+ if (reservationsUsable && isSettled(el, at3, bound) && keepsPrivate(el, ctx, creators))
15681
17436
  keepRetainedPrivate(el, ctx, contextPath, out, reservationsUsable, creators);
15682
17437
  else out.removedPrivateTags.push(el.tag);
15683
17438
  continue;
15684
17439
  }
15685
17440
  const action = annexE(el.tag);
15686
17441
  if (action === void 0) {
17442
+ if (isUnregisteredStandardTag(el.tag)) {
17443
+ removeUnregisteredElement(el, ctx, contextPath);
17444
+ continue;
17445
+ }
15687
17446
  if (el.vr === "SQ") {
15688
17447
  if (isUnauditableSequence(el)) emptyUnauditableSequence(el, ctx, contextPath, out);
15689
17448
  else
@@ -15746,9 +17505,17 @@ function descendSequence(el, ctx, contextPath, out, reservationsUsable) {
15746
17505
  out.removedPrivateTags.push(...inner.removedPrivateTags);
15747
17506
  out.embeddedAttributes.push(...inner.embeddedAttributes);
15748
17507
  out.unauditableSequences.push(...inner.unauditableSequences);
17508
+ out.unenumerablePrivateRemovals.push(...inner.unenumerablePrivateRemovals);
15749
17509
  out.undefinedVrElements.push(...inner.undefinedVrElements);
15750
17510
  out.warnings.push(...inner.warnings);
15751
- newItems.push(new Item({ index, warnings: [], elements: inner.elements }));
17511
+ newItems.push(
17512
+ new Item({
17513
+ index,
17514
+ warnings: [],
17515
+ elements: inner.elements,
17516
+ ...item.fileOffset !== void 0 ? { fileOffset: item.fileOffset } : {}
17517
+ })
17518
+ );
15752
17519
  });
15753
17520
  return rebuildSequence(el, newItems, ctx.encoding);
15754
17521
  }
@@ -15798,12 +17565,26 @@ function auditAttribute(tag, source, action, applied, contextPath) {
15798
17565
  };
15799
17566
  }
15800
17567
  function rebuildFileMeta(fileMeta, ctx) {
15801
- if (fileMeta === void 0) return void 0;
15802
- if (ctx.active.has("RetainUIDs") || fileMeta.mediaStorageSOPInstanceUID === void 0)
15803
- return fileMeta;
17568
+ if (fileMeta === void 0) return { fileMeta: void 0, dropped: [], droppedCount: 0 };
17569
+ const extras = fileMeta.extraElements ?? [];
17570
+ const dropped = [];
17571
+ for (const extra of extras) {
17572
+ if (dropped.length >= MAX_FILE_META_DROP_FINDINGS) break;
17573
+ dropped.push({ tag: extra.tag, vr: extra.vr, byteLength: extra.value.length });
17574
+ }
17575
+ const sourceSopInstance = fileMeta.mediaStorageSOPInstanceUID;
17576
+ const sopInstance = sourceSopInstance === void 0 || ctx.active.has("RetainUIDs") ? sourceSopInstance : ctx.remap.map(sourceSopInstance);
15804
17577
  return {
15805
- ...fileMeta,
15806
- mediaStorageSOPInstanceUID: ctx.remap.map(fileMeta.mediaStorageSOPInstanceUID)
17578
+ fileMeta: {
17579
+ transferSyntaxUID: fileMeta.transferSyntaxUID,
17580
+ ...fileMeta.mediaStorageSOPClassUID !== void 0 ? { mediaStorageSOPClassUID: fileMeta.mediaStorageSOPClassUID } : {},
17581
+ ...sopInstance !== void 0 ? { mediaStorageSOPInstanceUID: sopInstance } : {},
17582
+ ...fileMeta.fileMetaInformationVersion !== void 0 ? { fileMetaInformationVersion: fileMeta.fileMetaInformationVersion } : {},
17583
+ implementationClassUID: COSYTE_IMPLEMENTATION_CLASS_UID,
17584
+ implementationVersionName: COSYTE_IMPLEMENTATION_VERSION_NAME
17585
+ },
17586
+ dropped,
17587
+ droppedCount: extras.length
15807
17588
  };
15808
17589
  }
15809
17590
  var DEFAULT_METHOD_PROFILE = "@cosyte/dicom Basic Application Level Confidentiality Profile";
@@ -15859,6 +17640,58 @@ function splitValues(value) {
15859
17640
  }
15860
17641
  return out;
15861
17642
  }
17643
+ function methodCodesForRun(active) {
17644
+ const options = DEIDENTIFY_OPTIONS.filter((option) => active.has(option));
17645
+ return [
17646
+ DEIDENTIFICATION_METHOD_CODES.profile,
17647
+ ...options.map((option) => DEIDENTIFICATION_METHOD_CODES.options[option])
17648
+ ];
17649
+ }
17650
+ function methodCodeItem(code, index, littleEndian) {
17651
+ const text = (tag, vr, value) => [
17652
+ tag,
17653
+ insertedScalar(tag, vr, padValue(buffer.Buffer.from(value, "latin1"), vr), littleEndian)
17654
+ ];
17655
+ return new Item({
17656
+ index,
17657
+ warnings: [],
17658
+ elements: new Map([
17659
+ text(TAG_CODE_VALUE, "SH", code.codeValue),
17660
+ text(TAG_CODING_SCHEME_DESIGNATOR, "SH", code.codingSchemeDesignator),
17661
+ text(TAG_CODE_MEANING, "LO", code.codeMeaning)
17662
+ ])
17663
+ });
17664
+ }
17665
+ function carriesCode(item, code) {
17666
+ const designator = item.get(TAG_CODING_SCHEME_DESIGNATOR);
17667
+ const value = item.get(TAG_CODE_VALUE);
17668
+ if (designator === void 0 || value === void 0) return false;
17669
+ return trimTrailingPad(designator.rawBytes).equals(
17670
+ buffer.Buffer.from(code.codingSchemeDesignator, "latin1")
17671
+ ) && trimTrailingPad(value.rawBytes).equals(buffer.Buffer.from(code.codeValue, "latin1"));
17672
+ }
17673
+ function holdsNonPadding(el, encoding) {
17674
+ const headed = isFullSpanElement(el, encoding) && el.length !== UNDEFINED_LENGTH8 && el.length <= el.rawBytes.length;
17675
+ const value = headed ? el.rawBytes.subarray(el.rawBytes.length - el.length) : el.rawBytes;
17676
+ return trimTrailingPad(value).length > 0;
17677
+ }
17678
+ function addDeidentificationMethodCodes(source, processed, active, encoding) {
17679
+ const prior = source?.vr === "SQ" && source.items !== void 0 ? processed?.items : void 0;
17680
+ const kept = prior ?? [];
17681
+ const added = methodCodesForRun(active).filter(
17682
+ (code) => !kept.some((item) => carriesCode(item, code))
17683
+ );
17684
+ const littleEndian = encoding !== "explicitBE";
17685
+ const items = [
17686
+ ...kept,
17687
+ ...added.map((code, i) => methodCodeItem(code, kept.length + i, littleEndian))
17688
+ ];
17689
+ return {
17690
+ element: insertedSequence(TAG_DEIDENTIFICATION_METHOD_CODE_SEQUENCE, items, encoding),
17691
+ retainedPrior: kept.length > 0,
17692
+ replacedPrior: source !== void 0 && prior === void 0 && holdsNonPadding(source, encoding)
17693
+ };
17694
+ }
15862
17695
  function hasUncleanedBurnedIn(ds) {
15863
17696
  if (!ds.has(TAG_PIXEL_DATA)) return false;
15864
17697
  const flag = ds.get(TAG_BURNED_IN_ANNOTATION);
@@ -15866,17 +17699,36 @@ function hasUncleanedBurnedIn(ds) {
15866
17699
  return flag.rawBytes.toString("latin1").replace(/[\0 ]+$/, "").trim().toUpperCase() !== "NO";
15867
17700
  }
15868
17701
  function deidentify(ds, options = {}) {
17702
+ if (isRefusedTransferSyntax(ds.fileMeta?.transferSyntaxUID)) {
17703
+ throw new DeidentifyError(
17704
+ REFUSED_TRANSFER_SYNTAX_MESSAGE,
17705
+ DEIDENTIFY_ERROR_CODES.UNSUPPORTED_TRANSFER_SYNTAX
17706
+ );
17707
+ }
15869
17708
  const active = validateRetain(options.retain);
15870
17709
  const remap = makeUidRemapper(options.uidRoot, options.uidMap);
15871
17710
  const tsUid = ds.fileMeta?.transferSyntaxUID ?? "";
15872
17711
  const encoding = BODY_ENCODING2[tsUid] ?? "explicitLE";
15873
17712
  const littleEndian = encoding !== "explicitBE";
17713
+ const isDicomdir2 = ds.fileMeta?.mediaStorageSOPClassUID === MEDIA_STORAGE_DIRECTORY_STORAGE_UID2;
17714
+ const budget = {
17715
+ unauditableSequences: 0,
17716
+ unenumerableRemovals: 0,
17717
+ undefinedVrElements: 0,
17718
+ privateDeclarationItems: 0
17719
+ };
17720
+ const declarationWarnings = [];
17721
+ const declaration = active.has("RetainSafePrivate") ? resolvePrivateDeclaration(ds.elements(), encoding, budget, declarationWarnings) : NO_PRIVATE_DECLARATION;
15874
17722
  const ctx = {
15875
17723
  active,
15876
17724
  remap,
15877
17725
  profile: options.profile,
15878
17726
  encoding,
15879
- budget: { unauditableSequences: 0, undefinedVrElements: 0 }
17727
+ removeGroup0004: !isDicomdir2,
17728
+ group0004: { findings: [], total: 0 },
17729
+ unregistered: { findings: [], total: 0 },
17730
+ declaration,
17731
+ budget
15880
17732
  };
15881
17733
  const processed = processElements(ds.elements(), ctx, [], true);
15882
17734
  const {
@@ -15885,6 +17737,7 @@ function deidentify(ds, options = {}) {
15885
17737
  removedPrivateTags,
15886
17738
  embeddedAttributes,
15887
17739
  unauditableSequences,
17740
+ unenumerablePrivateRemovals,
15888
17741
  undefinedVrElements
15889
17742
  } = processed;
15890
17743
  elements.set(
@@ -15898,7 +17751,24 @@ function deidentify(ds, options = {}) {
15898
17751
  TAG_DEIDENTIFICATION_METHOD,
15899
17752
  insertedScalar(TAG_DEIDENTIFICATION_METHOD, "LO", deidentMethod.value, littleEndian)
15900
17753
  );
15901
- const warnings = [...processed.warnings];
17754
+ const priorCodes = ds.get(TAG_DEIDENTIFICATION_METHOD_CODE_SEQUENCE);
17755
+ const methodCodes = addDeidentificationMethodCodes(
17756
+ priorCodes,
17757
+ elements.get(TAG_DEIDENTIFICATION_METHOD_CODE_SEQUENCE),
17758
+ active,
17759
+ encoding
17760
+ );
17761
+ elements.set(TAG_DEIDENTIFICATION_METHOD_CODE_SEQUENCE, methodCodes.element);
17762
+ elements.set(
17763
+ TAG_LONGITUDINAL_TEMPORAL_INFORMATION_MODIFIED,
17764
+ insertedScalar(
17765
+ TAG_LONGITUDINAL_TEMPORAL_INFORMATION_MODIFIED,
17766
+ "CS",
17767
+ buffer.Buffer.from(temporalState(active), "latin1"),
17768
+ littleEndian
17769
+ )
17770
+ );
17771
+ const warnings = [...declarationWarnings, ...processed.warnings];
15902
17772
  if (deidentMethod.replacedPrior) {
15903
17773
  warnings.push(
15904
17774
  deidentMethodNotAdded({ byteOffset: priorMethod?.byteOffset ?? 0, fileMeta: false })
@@ -15919,11 +17789,37 @@ function deidentify(ds, options = {}) {
15919
17789
  deidentMethodValueOverLength({ byteOffset: priorMethod?.byteOffset ?? 0, fileMeta: false })
15920
17790
  );
15921
17791
  }
17792
+ if (methodCodes.retainedPrior) {
17793
+ warnings.push(
17794
+ deidentMethodCodesPriorRetained({ byteOffset: priorCodes?.byteOffset ?? 0, fileMeta: false })
17795
+ );
17796
+ }
17797
+ if (methodCodes.replacedPrior) {
17798
+ warnings.push(
17799
+ deidentMethodCodesPriorReplaced({ byteOffset: priorCodes?.byteOffset ?? 0, fileMeta: false })
17800
+ );
17801
+ }
15922
17802
  if (hasUncleanedBurnedIn(ds)) {
15923
17803
  const offset = ds.get(TAG_PIXEL_DATA)?.byteOffset ?? 0;
15924
17804
  warnings.push(burnedInAnnotationNotRemoved({ byteOffset: offset, fileMeta: false }));
15925
17805
  }
15926
- const newFileMeta = rebuildFileMeta(ds.fileMeta, ctx);
17806
+ if (active.has("RetainLongitudinalTemporalModifiedDates")) {
17807
+ warnings.push(datesNotTransformed({ byteOffset: 0, fileMeta: false }));
17808
+ }
17809
+ const rebuiltFileMeta = rebuildFileMeta(ds.fileMeta, ctx);
17810
+ if (rebuiltFileMeta.droppedCount > 0) {
17811
+ warnings.push(fileMetaReplaced({ byteOffset: 0, fileMeta: true }));
17812
+ }
17813
+ if (ctx.group0004.total > 0) {
17814
+ warnings.push(group0004Removed({ byteOffset: 0, fileMeta: false }));
17815
+ }
17816
+ if (ctx.unregistered.total > 0) {
17817
+ warnings.push(unregisteredElementRemoved({ byteOffset: 0, fileMeta: false }));
17818
+ }
17819
+ if (isDicomdir2) {
17820
+ warnings.push(dicomdirFileSetNotDischarged({ byteOffset: 0, fileMeta: true }));
17821
+ }
17822
+ const newFileMeta = rebuiltFileMeta.fileMeta;
15927
17823
  const datasetInit = {
15928
17824
  warnings: ds.warnings,
15929
17825
  elements,
@@ -15935,7 +17831,14 @@ function deidentify(ds, options = {}) {
15935
17831
  removedPrivateTags,
15936
17832
  embeddedAttributes,
15937
17833
  unauditableSequences,
17834
+ unenumerablePrivateRemovals,
15938
17835
  undefinedVrElements,
17836
+ fileMetaElementsDropped: rebuiltFileMeta.dropped,
17837
+ fileMetaElementsDroppedCount: rebuiltFileMeta.droppedCount,
17838
+ group0004Removals: ctx.group0004.findings,
17839
+ group0004RemovalCount: ctx.group0004.total,
17840
+ unregisteredElementRemovals: ctx.unregistered.findings,
17841
+ unregisteredElementRemovalCount: ctx.unregistered.total,
15939
17842
  uidMap: remap.cache,
15940
17843
  warnings,
15941
17844
  retained: [...active]
@@ -15945,6 +17848,7 @@ function deidentify(ds, options = {}) {
15945
17848
 
15946
17849
  exports.CODING_SCHEME_OIDS = CODING_SCHEME_OIDS;
15947
17850
  exports.DEFAULT_UID_ROOT = DEFAULT_UID_ROOT;
17851
+ exports.DEIDENTIFICATION_METHOD_CODES = DEIDENTIFICATION_METHOD_CODES;
15948
17852
  exports.DEIDENTIFY_ERROR_CODES = DEIDENTIFY_ERROR_CODES;
15949
17853
  exports.DEIDENTIFY_OPTIONS = DEIDENTIFY_OPTIONS;
15950
17854
  exports.Dataset = Dataset;
@@ -15978,7 +17882,11 @@ exports.parseSpecificCharacterSet = parseSpecificCharacterSet;
15978
17882
  exports.parseTime = parseTime;
15979
17883
  exports.profiles = profiles;
15980
17884
  exports.readCode = readCode;
17885
+ exports.readPixelDataFragments = readPixelDataFragments;
15981
17886
  exports.resolveDecoderLabel = resolveDecoderLabel;
15982
17887
  exports.serializeDicom = serializeDicom;
17888
+ exports.toDate = toDate;
17889
+ exports.toISO = toISO;
17890
+ exports.toObject = toObject;
15983
17891
  //# sourceMappingURL=index.cjs.map
15984
17892
  //# sourceMappingURL=index.cjs.map