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