Skip to content

Tag edits and scripts

Routes can change headers on the way in (a source’s edits, before the file is written) and on the way out (a destination’s edits, as each instance is sent; the router’s own copy never changes).

Edits apply in order. Each names a tag (a keyword such as InstitutionName, or (0008,0080)) and an action:

Action Does
Set Sets the value, adding the element if it is missing.
SetIfMissing Sets it only when it is missing or empty.
Replace Regular expression replace on an existing value: pattern → value.
Prefix, Suffix Adds text before or after an existing value.
Remove Removes the element.
CopyFrom Copies the value of the tag named as the value, if present.
MapPatientId Translates the Patient ID through a patient ID map.
Map through a table Translates the value through a lookup table, such as station names to departments or one site’s procedure codes to another’s: a value in the table (any case) becomes the table’s, others keep theirs or take the table’s default. The tables are the ones HL7 routing uses (Configuration › HL7 routing › Lookup tables). If the table is missing, the instance is not sent unmapped: it fails, and its error says why.

Values can use placeholders: {CallingAE}, {CalledAE}, {RemoteIP}, {Port}, {NodeName}, {SourceName}, {RouteName}, {Date} and {Time}; in destination edits also {DestinationName}, {DestinationAE} and {SourceAE}. Any tag can be named too: {PatientID}, {(0008,0080)}.

  • Only top-level elements before the pixel data can be edited.
  • Values must fit their element’s maximum length. Text is cut to fit, with a warning in the log; UIDs, dates, times and numbers are never cut: the instance is refused (or, on send, dead-lettered) with an explanation. A fixed value that cannot fit is rejected when you save.
  • Regular expressions (in Replace, in conditions, and in HL7 routing) run in time proportional to the value, so no pattern can hold up the instances it is applied to. Patterns with backreferences or lookarounds (\1, (?=…)) also work, but are given up after 100 ms on a value: the instance is then refused (or dead-lettered) rather than sent unchanged, since the edit may be what keeps a name or ID out.
Goal Edit
Stamp where a study came from InstitutionName Set North Clinic
Prefix accession numbers for a merged PACS AccessionNumber Prefix NC
Strip a site prefix from patient IDs PatientID Replace ^NC- → (empty)
Record the sending modality StationName SetIfMissing {CallingAE}

For rules edits cannot express, a source or destination can run a script: JavaScript, written under Configuration › Scripts and chosen on the source or destination.

  • A source’s script runs on every instance received, after its edits. It can change the header, refuse the instance, or send it to other destinations.
  • A destination’s script runs as each instance is sent, after its edits and before de-identification. Rejecting dead-letters the instance.
  • An HL7 route’s script works on HL7 messages instead.
// Reports only to the archive
if (dataset.get('Modality') === 'SR') route.only('Archive');
// Refuse instances without an accession number
if (!dataset.get('AccessionNumber')) reject('No accession number');
// Name the campus by the sending modality
dataset.set('InstitutionName', context.callingAE === 'CT1' ? 'Main campus' : 'Clinic');
Name What it is
dataset.get(tag), has, set(tag, value[, vr]), remove(tag) The header. An array sets several values.
context hook (“receive” or “send”), callingAE, calledAE, remoteIp, port, node, source, route, destination.
route.destinations, route.only(…), route.add(name), route.remove(name) On receipt only: where the instance goes, by destination name.
reject(reason) Refuse the instance (on receipt), or dead-letter it (on send).
log(…) Write to the node’s log.

Each run is sandboxed: no files, network or .NET, at most 1 second, 16 MB and 1,000,000 statements, and nothing kept from one instance to the next. A script that fails refuses (or dead-letters) the instance with its error.

Test, in the script editor, runs the code on a sample header and shows what changed and what it decided, without saving.