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).
Tag edits
Section titled “Tag edits”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.
Examples
Section titled “Examples”| 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} |
Scripts
Section titled “Scripts”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 archiveif (dataset.get('Modality') === 'SR') route.only('Archive');// Refuse instances without an accession numberif (!dataset.get('AccessionNumber')) reject('No accession number');// Name the campus by the sending modalitydataset.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.
