Using Data Filters on Event Subscriptions
When creating Event Subscriptions for a production environment, consider setting restrictive filter constraints in order to guard against unintended Action execution. The Event Subscription creation dialog includes a field called "Event Payload Filter" that allows you to define which specific data attributes to look for before triggering an action. This Event Payload is written in JSONPath notation, using the attributes of each class of event trigger.
Filtered vs Unfiltered Subscriptions
Unfiltered Subscription
The following subscription (created by a site admin) will be triggered on any type of scan creation across all projects on a site. Note the lack of content in the Event Payload Filter field, and the "Apply to All Projects" selector.
Filtered Subscription
Restricting subscriptions to individual projects is as simple as selecting projects in the multi-select menu. But an additional step of including a payload filter will restrict this subscription behavior even further.
The full JSONPath payload filter in this subscription is
(@.xsiType == "xnat:mrScanData" && @.resources.length() > 0 && "DICOM" in @.resources[*].label)
This means that this event subscription will only apply to newly created scans if all of the following conditions are true:
- the scan is of the
xnat:mrScanData
datatype - the scan contains resource files
- at least one of those resources is labeled
DICOM
.
Not only does this more restrictive subscription ensure the selected Action will have the resources it needs, it reduces undesirable Event Service and Container Service processing.
How JSONPath Filters Work
Payload Capture
The "payload" of the event refers to the XNAT data object that triggered the subscription evaluation process. Payload filtering works by applying a JSONPath filter to the serialized payload object associated with this event. There are several examples of payloads provided in the Event Trigger documentation, but the serialized version of a particular payload can be found by following the Default Logging Action example, adjusting for the event of interest.
For example, to build a filter for a particular type of scan: create a subscription for Scan Created events, with the Logging Action selected:
Then, trigger this event by uploading or creating a scan on the selected project.
After scan creation is complete, browse to the Event Service History page.
Select the appropriate history item to view details.
Note the serialized Scan object, represented in JSON format, listed below "status-message". Here is an abridged and cleaned view of that serialized object:
Serialized Scan Payload (abridged)
{
"id": "4",
"label": "4 - t1_mpr_1mm_p2_pos50",
"xsiType": "xnat:mrScanData",
"uri": "/archive/experiments/XNAT6_E00030/scans/4",
"resources": [
{
"type": "Resource",
"id": "DICOM",
"label": "DICOM",
"xsiType": "xnat:resourceCatalog",
"uri": "/archive/experiments/XNAT6_E00030/scans/4/resources/DICOM",
"directory": "/data/xnat/archive/Fruit_Struct/arc001/Grape_MR1/SCANS/4/DICOM",
"integer-id": 90
}
],
"directory": "/data/xnat/archive/Fruit_Struct/arc001/Grape_MR1/SCANS/4",
"frames": 176,
"modality": "MR",
"quality": "usable",
"scanner": "MEDPC",
"uid": "1.3.12.2.1107.5.2.32.35177.3.2006121409284535196417894.0.0.0",
"integer-id": 75,
"scan-type": "t1_mpr_1mm_p2_pos50",
"project-id": "Fruit_Struct",
"session-id": "XNAT6_E00030",
"scanner-manufacturer": "SIEMENS",
"scanner-model": "TrioTim",
"series-description": "t1_mpr_1mm_p2_pos50",
"start-time": "09:37:11"
}
JSONPath Filter Testing
XNAT Event Service filters use the Java-based Jayway JSONPath library to filter serialized payload objects. Online JsonPath evaluators, such as this one, allow for interactive JSONPath filter development. Using the full or abridged Scan payload JSON above, experiment with JSONPath filter strings. Filters that return any non-empty result will indicate a Subscription 'match'.
NOTE: Be aware that serialized payload objects are likely to include PHI for data that has not been properly anonymized. This data should not be submitted to an online evaluator. Use only properly de-identified data for this step of filter development.
When evaluating the above payload, consider the behavior of the following filter strings:
Positive Match: scan is of type "xnat:mrScanData"
$[?(@.xsiType == "xnat:mrScanData")]
Positive Match: scan is of "MR" modality and has a "usable" quality setting
$[?(@.modality == "MR" && @.quality == "usable")]
No Match. Scan is not of "CT" modality
$[?(@.modality == "CT")]
When an empty result is returned, this indicates a Subscription 'mismatch'. Only Subscriptions with filters that 'match' an Event payload will result in an Action.
Writing a Subscription Filter Definition
Event Service filters should be entered into the XNAT Event Subscription dialog without the $[? ... ]
bracketing. The $[? notation indicates a JSONPath filter string, which is the default and only mode of JSONPath parsing for this parameter.
Raw JsonPath Filter | Event Payload Filter |
---|---|
$[?(@.xsiType == "xnat:mrScanData")] | (@.xsiType == "xnat:mrScanData") |
$[?(@.modality == "MR" && @.quality == "usable")] | (@.modality == "MR" && @.quality == "usable") |
After validating your JSONPath filter using an online tool, edit your subscription to include the adjusted Event Payload Filter.
Example JSONPath Filters
Event Payload | Filter Description | XNAT JSONPath Filter |
---|---|---|
Scan | Scan xsiType is xnat:mrScanData |
|
Scan modality is MR and quality is usable |
| |
Scan xsiType is xnat:mrScanData and greater than zero resources and at least one of those resources is labeled DICOM |
| |
Scan with "modality==RTSTRUCT" |
| |
Scan with
|
| |
Session | Session with and at least one scan | (@.scans.length() > 0 ) |
Session with "subject-id == XNAT_S00001" and "modality == MR" for at least one of the contained scans | (@.subject-id == "XNAT_S00001" && "MR" in @.modalities-in-study) | |
Session with at least one scan element with "modality == RTSTRUCT" |
| |
Subject | Subject with Project ID matched by a regular expression. | (@.project-id =~ /[optionalString]?.*theproject.*[anotherOptionalString]?/i) |
Project | Projects titled with: "TheProjectTitle" |
|
Projects with a title that matches a regular expression |
|