Lab Order processing
Flow Description
A hospital sends an HL7 2.3 message containing an order via SFTP to their predefined vendor folder on the Data Exchange Server. An interface engine (Integrator) formats the source message into the AP Easy specification and moves it to the predefined client folder on the server. The client is a Lab, such as Quest Diagnostics.
Source HL7 message
MSH|^~\&|MM|MOD6078|AP Easy|MOD6078|20161216231442||ORM^O01|211072-20161216231442|P|2.3|
PID|1|12345678|123456||LastName^FirstName^MiddleName||19050925|M|||1000 PERSHING LN^^FORKED RIVER^NJ^08731||||||||11122333
IN1|1||12379|MEDICARE B-NJ: NOVITAS SOLUTIONS|PO BOX 1234^^MECHANICSBURG^PA^170551802||||||||||PRIMARY|LastName^FirstName^MiddleName|1|19050925|^^^^|||1||||||||||||||1504245123
IN1|2||61667|BCBS-NJ: HORIZON BCBS - OUT OF STATE - BLUE CARD (PPO)|PO BOX 11122^^NEPTUNE^NJ^077541301|||00865600002|||||||SECONDARY|LastName^FirstName^MiddleName|1|19050925|^^^^|||2||||||||||||||YHB3HZN64699555
ORC|NW|211072-A||211072|||||20161216231442|||^HAHN^JUSTENE^
OBR|1|211072-A|A|D48.5^Biopsy by Shave Method;H and E||20161216231442|20161216081131||||||Morphology: erythematous scaly papule;DDX: Squamous Cell Carcinoma vs. Verruca Vulgaris vs. Irritated Seborrheic Keratosis;Location: left central parietal scalp;||^^^left central parietal scalp|^HAHN^JUSTENE^|||||||||F||^^^^^^^^||||
NTE|1|Specimen Label|shave bx
NTE|2|Specimen Source|A) left central parietal scalp
NTE|3|Morphology|erythematous scaly papule
NTE|4|Procedure Name|Biopsy by Shave Method
NTE|5|triangulation|from lt tragus 14.5cm up and 3cm rt
NTE|6|triangulation|0.6cm
DG1|1|I10|D48.5|Squamous Cell Carcinoma vs. Verruca Vulgaris vs. Irritated Seborrheic Keratosis
ORC|NW|211072-B||211072|||||20161216231442|||^HAHN^JUSTENE^
OBR|1|211072-B|B|D48.5^Biopsy by Shave Method;H and E||20161216231442|20161216081049||||||Morphology: Erythematous scaling plaque;DDX: Squamous Cell Carcinoma vs. Verruca Vulgaris vs. Irritated Seborrheic Keratosis;Location: left central frontal scalp;||^^^left central frontal scalp|^HAHN^JUSTENE^|||||||||F||^^^^^^^^||||
NTE|1|Specimen Label|shave bx
NTE|2|Specimen Source|B) left central frontal scalp
NTE|3|Morphology|Erythematous scaling plaque
NTE|4|Procedure Name|Biopsy by Shave Method
NTE|5|triangulation|from lt tragus 14.5 cm up and 2cm rt
NTE|6|triangulation|1cm
DG1|1|I10|D48.5|Squamous Cell Carcinoma vs. Verruca Vulgaris vs. Irritated Seborrheic Keratosis
The reformatted destination HL7 message
MSH|^~\&|Integrator|MOD6078|AP Easy|MOD6078|20161216231442||ORM^O01|211072-20161216231442|P|2.3
PID|1|12345678|123456||LastName^FirstName^MiddleName||19050925|M|||1000 PERSHING LN^^FORKED RIVER^NJ^08731||||||||11122333
PV1|1||^^^&MOD6078||||^HAHN^JUSTENE
IN1|1||12379|MEDICARE B-NJ: NOVITAS SOLUTIONS|PO BOX 1234^^MECHANICSBURG^PA^170551802||||||||||PRIMARY|LastName^FirstName^MiddleName|1|19050925||||1||||||||||||||1504245123
IN1|2||61667|BCBS-NJ: HORIZON BCBS - OUT OF STATE - BLUE CARD (PPO)|PO BOX 11122^^NEPTUNE^NJ^077541301|||00865600002|||||||SECONDARY|LastName^FirstName^MiddleName|1|19050925||||2||||||||||||||YHB3HZN64699555
ORC|NW|211072-A||211072|||||20161216231442|||^HAHN^JUSTENE
OBR|1|211072-A|A|D48.5^Biopsy by Shave Method;H and E||20161216231442|20161216081131||||||Morphology: erythematous scaly papule;DDX: Squamous Cell Carcinoma vs. Verruca Vulgaris vs. Irritated Seborrheic Keratosis;Location: left central parietal scalp;||^^^left central parietal scalp|^HAHN^JUSTENE|||||||||F
OBX|1|FT|03^Clinical||Morphology: erythematous scaly papule;DDX: Squamous Cell Carcinoma vs. Verruca Vulgaris vs. Irritated Seborrheic Keratosis;Location: left central parietal scalp;
OBX|2|FT|01^Site||A) left central parietal scalp
OBX|3|FT|02^Procedure||SHAVE
ORC|NW|211072-B||211072|||||20161216231442|||^HAHN^JUSTENE
OBR|1|211072-B|B|D48.5^Biopsy by Shave Method;H and E||20161216231442|20161216081049||||||Morphology: Erythematous scaling plaque;DDX: Squamous Cell Carcinoma vs. Verruca Vulgaris vs. Irritated Seborrheic Keratosis;Location: left central frontal scalp;||^^^left central frontal scalp|^HAHN^JUSTENE|||||||||F
OBX|1|FT|03^Clinical||Morphology: Erythematous scaling plaque;DDX: Squamous Cell Carcinoma vs. Verruca Vulgaris vs. Irritated Seborrheic Keratosis;Location: left central frontal scalp;
OBX|2|FT|01^Site||B) left central frontal scalp
OBX|3|FT|02^Procedure||SHAVE
Connections
- Source - SFTP
- Destination - SFTP
Prerequisites
Before creating a flow, you must create all the required folders on the server:
source-orders
processing
failed
destination-orders
How an Order is Processed
- The hospital sends an order via SFTP to the source-orders folder.
- Integrator moves the order to the processing folder.
- Integrator reformats the message into the AP Easy specification, which is understood by the Lab software, and moves it to the destination-orders folder.
- If there is an error during Step 3, Integrator moves the original message to the failed folder.
This suggested approach is just one of many possibilities. We want to make our flow processing as reliable as possible, hence all the file movements between folders. Ultimately, Step 3 does all the hard lifting; everything else is just implementation of a fail safe mechanism.
The Order Flow
Step 1. Create all the required SFTP connections, one connection per folder, as above:
When creating connections, set the following properties:
- For a connection which points to the processing folder and has Enable Wildcard File Name set to oldest: If there are multiple files in the processing folder, it will direct the flow to select the oldest file to process.
- For a connection which points to the destination-orders folder and has Add Suffix When Creating Files set to timestamp, it will direct the flow to create files in the destination-orders folder with a timestamp suffix. With this setting, if the file already exists, it will not be overwritten. Instead, a new file will be created each time.
Step 2. Create an HL7 format
When creating a format, set the HL7 Version to 2.3 and leave everything else set to the default:
Step 3. Create a "reformat" flow.
This flow will reformat the source message in the processing folder to the AP Easy specification and will move it to the destination-orders folder.
For this flow, you will need the following connections and formats:
- A connection which points to the processing folder.
- A connection which points to the destination-orders folder.
- The format created in Step 2.
1) Start creating a flow by clicking the Add flow
button on the Flows window.
2) Type HL7
into the Search... box and select HL7 to HL7
3) In the opened window, select the source (FROM) connection which points to the processing folder and the destination (TO) connection which points to the destination-orders folder.
4) Select the format created in Step 2 for the FROM and TO formats.
5) Enter *.hl7
as the FROM and Vendor_Order_Destination.hl7
into the TO field:
6) Click the MAPPING
button and select the Parameters tab.
7) Enter order
in the Transformation Name field. It will be used in reports and on the dashboard.
8) Select Ignore when there is no file
. By doing this you will allow the flow to finish even when there are no files in the processing folder.
9) Enter the following code into the Preprocessing field. This code does all the reformatting. Read more about using JavaScript when the source is an HL7 message or when the destination is an HL7 message.
importPackage(Packages.ca.uhn.hl7v2.model.v23.message);
importPackage(Packages.ca.uhn.hl7v2.model.v23.segment);
importPackage(Packages.ca.uhn.hl7v2.model.v23.datatype);
var message = dataSet.getActualData();
// clone source message
var destMessage = ClassUtils.clone(message);
// change sender
destMessage.getMSH().getSendingApplication().getNamespaceID().setValue("Integrator");
var numOrders = destMessage.getORDERReps();
// add OBX segmentts, remove NTE and DG segments
for (num = 0; num < numOrders; num++) {
var order = destMessage.getORDER(num);
var detail = order.getORDER_DETAIL();
var allNte = detail.getNTEAll();
var maxId = 1;
for (i = 0; i < allNte.length; i++) {
// skip 1,3,5,6
if (i == 0 || i == 2 || i == 4 || i == 5) {
continue;
}
maxId++;
}
// obx 1
var obx = detail.insertOBSERVATION(0).getOBX();
obx.getObx1_SetIDOBX().setValue(1);
// OBX-2 -> FT ?
obx.getObx2_ValueType().setValue("FT");
// OBX-3.1 -> max ID ?
obx.getObx3_ObservationIdentifier().getIdentifier().setValue("0" + maxId);
// OBX-3.2 -> Clinical ?
obx.getObx3_ObservationIdentifier().getText().setValue("Clinical");
// OBX-5 = OBR-13 in source message
var ft = new FT(destMessage);
ft.setValue(detail.getOBR().getObr13_RelevantClinicalInformation().getValue());
obx.insertObservationValue(0).setData(ft);
var index = 1;
for (i = 0; i < allNte.length; i++) {
var nte = allNte.get(i);
// skip 1,3,5,6
if (i == 0 || i == 2 || i == 4 || i == 5) {
continue;
}
var obx = detail.insertOBSERVATION(index++).getOBX();
// OBX-1 -> index ?
obx.getObx1_SetIDOBX().setValue(index);
// OBX-2 -> FT ?
obx.getObx2_ValueType().setValue("FT");
// OBX-3.1 -> index ?
obx.getObx3_ObservationIdentifier().getIdentifier().setValue("0" + (index - 1));
// OBX-3.2 -> mapping, from NTE-2 ?
var qualifier = nte.getNte2_SourceOfComment().getValue().toLowerCase();
obx.getObx3_ObservationIdentifier().getText().setValue(qualifier.contains("specimen") ? "Site" : "Procedure");
// OBX-5 = mapping from NTE-3
var obx5Value = nte.getNte3_Comment(0).getValue();
var nte3 = obx5Value.toLowerCase();
if (nte3.contains("biopsy by punch method")) {
obx5Value = "PUNCH";
} else if (nte3.contains("biopsy by shave method")) {
obx5Value = "SHAVE";
} else if (nte3.contains("shave removal")) {
obx5Value = "SHAVE";
} else if (nte3.contains("curettage and destruction with pathology")) {
obx5Value = "SHAVE";
} else if (nte3.contains("punch excision")) {
obx5Value = "EXCISION";
} else if (nte3.contains("excision")) {
obx5Value = "EXCISION";
}
var ft = new FT(destMessage);
ft.setValue(obx5Value);
obx.insertObservationValue(0).setData(ft);
}
// remove NTE segments
while (detail.getNTEReps() > 0) {
detail.removeNTE(0);
}
// remove DG1 segments
while (detail.getDG1Reps() > 0) {
detail.removeDG1(0);
}
}
// add segment PV1
var pv1 = destMessage.getPATIENT().getPATIENT_VISIT().getPV1();
// PV1-1: Patient Visit ID
pv1.getPv11_SetIDPatientVisit().setValue("1");
// PV1-3 = MSH-4
pv1.getAssignedPatientLocation().getFacility().getUniversalID().setValue(
destMessage.getMSH().getMsh4_SendingFacility().getNamespaceID().getValue());
// XCN - attending doctor
var doctor = pv1.getAttendingDoctor(0);
if (message.getORDER().getORC().getOrc12_OrderingProviderReps() > 0) {
var provider = message.getORDER().getORC().getOrc12_OrderingProvider(0);
// PV1-7.1 = ORC-12.1
doctor.getIDNumber().setValue(provider.getXcn1_IDNumber().getValue());
// PV1-7.2 = ORC-12.2
doctor.getFamilyName().setValue(provider.getFamilyName().getValue());
// PV1-7.3 = ORC-12.3
doctor.getGivenName().setValue(provider.getGivenName().getValue());
// PV1-7.4 = ORC-12.4
doctor.getMiddleInitialOrName().setValue(provider.getXcn4_MiddleInitialOrName().getValue());
}
dataSet.setActualData(destMessage);
10) Save and test the flow.
- A prerequisite for this flow to work: the source file exists in the processing folder.
- To verify that the flow has been executed and has produced the correct results: make sure the correct file was created in the destination-orders folder.
Step 4. Create a move files to processing flow.
This flow moves files from the source-orders folder to the processing folder.
For this flow we will need the following connections:
- A connection which points to the source-orders folder.
- A connection which points to the processing folder.
1) Start creating a flow by clicking the Add flow
button on the Flows window.
2) Type files into the Search... box and select File Management.
3) In the opened window, select the source (FROM) connection which points to the source-orders folder and the destination (TO) connection which points to the processing folder.
4) Click the MAPPING
button and select the Parameters tab.
5) Select Move
for the Action. By selecting this action you are configuring the flow to move files from the source-orders folder to the processing folder.
6) Save and test the flow.
- A prerequisite for this flow to work: the source file exists in the source-orders folder.
- To verify that the flow has been executed and has produced the correct results, check that the file was copied to the processing folder and deleted from the source-orders folder.
Step 5. Create a clean up flow.
This flow deletes files from the processing folder or, if there is an error, moves files to the failed folder.
1) Start creating a flow by clicking the Add flow
button on the Flows window.
2) Type files
into the Search... box and select File Management
3) In the opened window, add two transformations:
-
Delete files from the processing folder.
1) Select the source (FROM) connection which points to the processing folder.
2) Enter
*.*
in the FROM field.3) Click the
MAPPING
button and select the Parameters tab.4) Select
Delete
for the Action. By selecting this action you are configuring the transformation to delete files from the processing folder. -
Move files to a failed folder.
1) Select the source (FROM) connection which points to the processing folder.
2) Select the destination (TO) connection which points to the failed folder.
3) Enter
*.*
in the FROM field.4) Click the
MAPPING
button and select the Parameters tab.5) Select
Move
for the Action. By selecting this action you are configuring the transformation to move files from the processing folder to the failed folder.6) Select Execute if Error. By selecting this action you are configuring the transformation to move files from the processing folder to the failed folder in case of any error.
4) Save and test the flow.
- A prerequisite for this flow to work: the source file exists in the processing folder.
- To verify that the flow has been executed and has produced the correct results, check that the file was deleted from the processing folder.
Step 6. Put it all together.
In the previous 5 steps, we created 3 flows which:
- Move files from the source-orders to the processing folder.
- Reformat a file and copy it to the destination-orders folder.
- Clean up by removing files from the processing folder, or moving files to the failed folder if there was an error.
In order to put it all together, we will need to create a nested flow.
Add the following flows to the nested flow:
1) The flow created in Step 4.
2) The flow created in Step 3.
3) The flow created in Step 5.
Save and test the flow.
- A prerequisites for this flow to work: the source file exists in the source-orders folder.
- To verify that flow has been executed and has produced the correct results: check that the correct file was created in the destination-orders folder, and the original source file was deleted from the source-ordersfolder.
Step 7. Schedule the flow created in Step 6 to be executed periodically.
Lab Results processing
Flow Description
The client sends a HL7 2.3 message containing test results and a PDF from AP Easy via SFTP to their predefined client folder on the server. The interface engine (Integrator) formats the source message to vendor specifications. Base x64 encodes the PDF into the HL7 message as the last OBX segment, and moves the file to the predefined vendor folder on the server. The vendor retrieves messages via SFTP. The client is a Lab, such as Quest Diagnostics.
Source HL7 message
MSH|^~\&|AP Easy|COMPASS||MOD6078|20161216140344||ORU^R01|C16-23271|P|2.2
PID|1|123456|Pt000123456||TEST^JACK^||191220|M|||123 N SMITH ROAD^^GALLOWAY^NJ^08205||||||||||
PV1|1||||||1902855349^Yanusz^Donna^^APN|^^^^|^^^^||||||||^^^^
ORC|RE|210915-A210915-B|C16-23271^AP Easy||CM||||201612150712
OBR|1|210915-A~210915-B~|C16-23271^AP Easy|Surgical Pathology|||201612140000|||||||201612150712||1902855349^Yanusz^Donna^^APN||||||201612160000||SP|F|||||||1093993263^Erickson^Christof^^MD|^^^^|^^^^
OBX|1|TX|Specimen(s) Received||A. PUNCH. right medial heel\\.br\\B. PUNCH. right medial heel\\.br\\||||||F|||||||
OBX|2|TX|Clinical Information||A. Morphology: tense bullae and erosions;DDX: Bullous Pemphigoid vs. Blister\\.br\\B. Morphology: tense bullae and erosions;DDX: Bullous Pemphigoid vs. Blister\\.br\\||||||F|||||||
OBX|3|TX|Gross Description||A. A tan three piece aggregate 3x2x12 mm punch biopsy skin specimen was received in formalin. The larger piece was bisected and entirely submitted with one punch, as well as with the smaller piece in one cassette.\\.br\\B. A tan two piece aggregate 3x2x8 mm punch biopsy skin specimen received in Michel's medium. One punch and the remaining piece were entirely submitted for frozen sectioning.\\.br\\||||||F|||||||
OBX|4|TX|Microscopic Description||A. In thick skin there is subepidermal vesicular dermatitis with an infiltrate of lymphocytes, histiocytes and eosinophils in the papillary dermis beneath. A special stain, PAS, is negative for hyphae. \\.br\\B. Frozen tissue examination was performed and shows vesicle formation with loss of the overlying epidermis.\\.br\\DIRECT IMMUNOFLUORESCENCE RESULTS:\\.br\\ IgG - negative\\.br\\ C3 - negative\\.br\\ IgA - negative\\.br\\ IgM - negative\\.br\\ Fibrinogen - negative\\.br\\Positive and negative controls were examined and showed appropriate staining. Intrinsic staining of patient tissue was appropriate.\\.br\\\\.br\\This test was developed and its performance characteristics determined by Compass Dermatopathology. It has not been cleared or approved by the U.S. Food and Drug Administration (USFDA). The USFDA has determined that such clearance or approval is not necessary. This test is used for clinical purposes and should not be regarded as investigational or for research. This laboratory is certified under the Clinical Laboratory Improvement Amendments (CLIA) as qualified to perform high complexity clinical laboratory testing.\\.br\\\\.br\\The CPT and ICD-10 codes are for information purposes only and are based on AMA guidelines without regard to specific payor requirements. \\.br\\||||||F|||||||
OBX|5|TX|Diagnosis||A. SUBEPIDERMAL VESICULAR DERMATITIS WITH EOSINPHILS\\.br\\B. NON-DIAGNOSTIC Direct ImmunofluorescencE\\.br\\\\.br\\||||||F|||||||
OBX|6|TX|Comments||A. These changes may be seen in bullous pemphigoid. The histologic differential diagnosis includes a bullous hypersensitivity reaction and other immunobullous disorders. \\.br\\B. The biopsy shows blister formation with loss of the epidermis which results in artifactual changes which render interpretation of immunofluorescence patterns problematic. Repeat perilesional biopsy for direct immunofluorescence is recommended.\\.br\\\\.br\\||||||F|||||||
OBR|2|210915-A~210915-B~|C16-23271^AP Easy|Surgical Pathology|||201612140000|||||||201612150712||1902855349^Yanusz^Donna^^APN||||||201612160000||SP|F|||||||1093993263^Erickson^Christof^^MD|^^^^|^^^^
OBX|1|TX|Specimen(s) Received_1||PUNCH. RIGHT MEDIAL HEEL|||N|||F|||||||
OBX|2|TX|Specimen(s) Received_2||PUNCH. RIGHT MEDIAL HEEL|||N|||F|||||||
OBX|3|TX|Clinical Information_1||Morphology: tense bullae and erosions;DDX: Bullous Pemphigoid vs. Blister|||N|||F|||||||
OBX|4|TX|Clinical Information_2||Morphology: tense bullae and erosions;DDX: Bullous Pemphigoid vs. Blister|||N|||F|||||||
OBX|5|TX|Gross Description_1||A tan three piece aggregate 3x2x12 mm punch biopsy skin specimen was received in formalin. The larger piece was bisected and entirely submitted with one punch, as well as with the smaller piece in one cassette.|||N|||F|||||||
OBX|6|TX|Gross Description_2||A tan two piece aggregate 3x2x8 mm punch biopsy skin specimen received in Michel's medium. One punch and the remaining piece were entirely submitted for frozen sectioning.|||N|||F|||||||
OBX|7|TX|Microscopic Description_1||In thick skin there is subepidermal vesicular dermatitis with an infiltrate of lymphocytes, histiocytes and eosinophils in the papillary dermis beneath. A special stain, PAS, is negative for hyphae. |||N|||F|||||||
OBX|8|TX|Microscopic Description_2||Frozen tissue examination was performed and shows vesicle formation with loss of the overlying epidermis.\\.br\\DIRECT IMMUNOFLUORESCENCE RESULTS:\\.br\\ IgG - negative\\.br\\ C3 - negative\\.br\\ IgA - negative\\.br\\ IgM - negative\\.br\\ Fibrinogen - negative\\.br\\Positive and negative controls were examined and showed appropriate staining. Intrinsic staining of patient tissue was appropriate.\\.br\\\\.br\\This test was developed and its performance characteristics determined by Compass Dermatopathology. It has not been cleared or approved by the U.S. Food and Drug Administration (USFDA). The USFDA has determined that such clearance or approval is not necessary. This test is used for clinical purposes and should not be regarded as investigational or for research. This laboratory is certified under the Clinical Laboratory Improvement Amendments (CLIA) as qualified to perform high complexity clinical laboratory testing.\\.br\\\\.br\\The CPT and ICD-10 codes are for information purposes only and are based on AMA guidelines without regard to specific payor requirements. |||N|||F|||||||
OBX|9|TX|Diagnosis_1||SUBEPIDERMAL VESICULAR DERMATITIS WITH EOSINPHILS|||N|||F|||||||
OBX|10|TX|Diagnosis_2||NON-DIAGNOSTIC DIRECT IMMUNOFLUORESCENCE^B|||N|||F|||||||
OBX|11|TX|Comments_1||THESE CHANGES MAY BE SEEN IN BULLOUS PEMPHIGOID. THE HISTOLOGIC DIFFERENTIAL DIAGNOSIS INCLUDES A BULLOUS HYPERSENSITIVITY REACTION AND OTHER IMMUNOBULLOUS DISORDERS. |||N|||F|||||||
OBX|12|TX|Comments_2||THE BIOPSY SHOWS BLISTER FORMATION WITH LOSS OF THE EPIDERMIS WHICH RESULTS IN ARTIFACTUAL CHANGES WHICH RENDER INTERPRETATION OF IMMUNOFLUORESCENCE PATTERNS PROBLEMATIC. REPEAT PERILESIONAL BIOPSY FOR DIRECT IMMUNOFLUORESCENCE IS RECOMMENDED.^B|||N|||F|||||||
The reformatted destination HL7 message
MSH|^~\\&|AP Easy|COMPASS||MOD6078|20161216140344||ORU^R01|C16-23271|P|2.2
PID|1|123456|Pt000123456||TEST^JACK^||191220|M|||123 N SMITH ROAD^^GALLOWAY^NJ^08205||||||||||
PV1|1||||||1902855349^Yanusz^Donna^^APN|^^^^|^^^^||||||||^^^^
ORC|RE|210915-A|C16-23271^AP Easy|210915|CM||||201612150712
OBR|1|210915-A|C16-23271^AP Easy|Surgical Pathology|||201612140000|||||||201612150712||1902855349^Yanusz^Donna^^APN||||||201612160000||SP|F|||||||1093993263^Erickson^Christof^^MD|^^^^|^^^^
OBX|1|TX|Specimen(s) Received||PUNCH. RIGHT MEDIAL HEEL|||N|||F
OBX|2|TX|Clinical Information||Morphology: tense bullae and erosions;DDX: Bullous Pemphigoid vs. Blister|||N|||F
OBX|3|TX|Gross Description||A tan three piece aggregate 3x2x12 mm punch biopsy skin specimen was received in formalin. The larger piece was bisected and entirely submitted with one punch, as well as with the smaller piece in one cassette.|||N|||F
OBX|4|TX|Microscopic Description||In thick skin there is subepidermal vesicular dermatitis with an infiltrate of lymphocytes, histiocytes and eosinophils in the papillary dermis beneath. A special stain, PAS, is negative for hyphae. |||N|||F
OBX|5|TX|Diagnosis||SUBEPIDERMAL VESICULAR DERMATITIS WITH EOSINPHILS|||N|||F
OBX|6|TX|Comments||THESE CHANGES MAY BE SEEN IN BULLOUS PEMPHIGOID. THE HISTOLOGIC DIFFERENTIAL DIAGNOSIS INCLUDES A BULLOUS HYPERSENSITIVITY REACTION AND OTHER IMMUNOBULLOUS DISORDERS. |||N|||F
ORC|RE|210915-B|C16-23271^AP Easy|210915|CM||||201612150712
OBR|2|210915-B|C16-23271^AP Easy|Surgical Pathology|||201612140000|||||||201612150712||1902855349^Yanusz^Donna^^APN||||||201612160000||SP|F|||||||1093993263^Erickson^Christof^^MD|^^^^|^^^^
OBX|7|TX|Specimen(s) Received||PUNCH. RIGHT MEDIAL HEEL|||N|||F
OBX|8|TX|Clinical Information||Morphology: tense bullae and erosions;DDX: Bullous Pemphigoid vs. Blister|||N|||F
OBX|9|TX|Gross Description||A tan two piece aggregate 3x2x8 mm punch biopsy skin specimen received in Michel's medium. One punch and the remaining piece were entirely submitted for frozen sectioning.|||N|||F
OBX|10|TX|Microscopic Description||Frozen tissue examination was performed and shows vesicle formation with loss of the overlying epidermis.\\.br\\DIRECT IMMUNOFLUORESCENCE RESULTS:\\.br\\ IgG - negative\\.br\\ C3 - negative\\.br\\ IgA - negative\\.br\\ IgM - negative\\.br\\ Fibrinogen - negative\\.br\\Positive and negative controls were examined and showed appropriate staining. Intrinsic staining of patient tissue was appropriate.\\.br\\\\.br\\This test was developed and its performance characteristics determined by Compass Dermatopathology. It has not been cleared or approved by the U.S. Food and Drug Administration (USFDA). The USFDA has determined that such clearance or approval is not necessary. This test is used for clinical purposes and should not be regarded as investigational or for research. This laboratory is certified under the Clinical Laboratory Improvement Amendments (CLIA) as qualified to perform high complexity clinical laboratory testing.\\.br\\\\.br\\The CPT and ICD-10 codes are for information purposes only and are based on AMA guidelines without regard to specific payor requirements. |||N|||F
OBX|11|TX|Diagnosis||NON-DIAGNOSTIC DIRECT IMMUNOFLUORESCENCE|||N|||F
OBX|12|TX|Comments||THE BIOPSY SHOWS BLISTER FORMATION WITH LOSS OF THE EPIDERMIS WHICH RESULTS IN ARTIFACTUAL CHANGES WHICH RENDER INTERPRETATION OF IMMUNOFLUORESCENCE PATTERNS PROBLEMATIC. REPEAT PERILESIONAL BIOPSY FOR DIRECT IMMUNOFLUORESCENCE IS RECOMMENDED.|||N|||F
OBX|13|ED|PDF^PDF BASE64|1|^^PDF^Base64^$\{ATTACH:44713897-7733-4c3c-812d-ce4424183c36\}
Connections
- Source - SFTP
- Processing - Integrator Home folder
- Destination - SFTP
Prerequisites
Before creating a flow, all the required folders must be created on the Data Exchange Server:
source-results
processing (remote)
failed
destination-results
To read and encode a PDF file, you will need to store it in the Account's Home folder. An Account's Home folder is automatically created for each client, so the user doesn't need to worry about creating it, but you still need to have a connection which points to this folder. Suppose this folder is called processing (local). It is going to be under the Account's Home folder.
home
processing (local)
How Lab Results are Processed
- The lab sends results via SFTP to the source-results folder.
- Integrator moves the results and PDF to both the processing (remote) and processing (local) folders. Files in the processing (remote) folder are used as a backup copy of the original message and PDF. If a transformation fails, files from processing (remote) will be copied to the failed folder.
- Using files in the processing (local) folder, Integrator reformats the message from the AP Easy specification to the vendor specs, base64 encodes the PDF and attaches it to the last OBX segment, then moves the message to the destination-results folder.
- If there is an error during Step 3, Integrator moves the original message and PDF from the processing (remote) to the failed folder. Otherwise it deletes the files in both the processing (remote) and processing (local) folders.
This suggested approach is just one of many possibilities. We want to make our flow processing as reliable as possible, hence all the file movements between folders. Ultimately, Steps 2 and 3 do all the hard lifting; everything else is just implementation of a fail safe mechanism.
The Flow
Step 1. Create all required SFTP connections, one connection per folder above:
when creating connections, set the following properties:
- A connection which points to the processing folder and Enable Wildcard File Name is set to oldest. If there are multiple files in the processing folder, this will direct the flow to select the oldest file to process.
- A connection which points to the destination-results folder and Add Suffix When Creating Files set to timestamp. This will direct the flow to create files in the destination-results folder with a timestamp suffix. So, if a file already exists, it will not be overwritten. Instead, a new file will be created each time.
Step 2. Create a connection for the processing (local) folder. The Server Storage connection type must be used.
Since you are locked into having the Home folder as your root folder, you will need to use the Files fields to point the connection to the actual folder under Home.
Step 3. If you don't already have it, create an HL7 format
When creating a format, set the HL7 Version to 2.3 and leave everything else set to the default setting:
Step 4. Create a "reformat" flow.
This flow will reformat the source message in the processing (local) folder from an AP Easy specification to the vendor specs, base x64 encode the PDF and attach it to the HL7 message in the last OBX segment. Then it will move the reformatted message to the destination-results folder.
For this flow, we will need the following connections and formats:
- A connection which points to the processing (local) folder.
- A connection which points to the destination-results folder.
- The format created in Step 3.
1) Start creating a flow by clicking the Add flow
button on the Flows window.
2) Type HL7
into the Search... box and select HL7 to HL7
3) In the opened window, select a source (FROM) connection which points to the processing (local) folder and a destination (TO) connection which points to the destination-results folder.
4) Select the format created in Step 2 for the FROM and TO formats.
5) Enter result.hl7
into the FROM and Vendor_Result_Destination.hl7
into the TO field:
6) Click the MAPPING
button and select the Parameters tab.
7) Enter result
into the Transformation Name field. It will be used in reports and on the dashboard.
8) Select Ignore when there is no file
. By doing this, you will allow the flow to finish even when there are no files in the processing (local) folder.
9) Enter the following code into the Preprocessing field. This code does all the reformatting. Read more about using JavaScript when the source or destination is an HL7 message.
importPackage(Packages.ca.uhn.hl7v2.model.v23.message);
importPackage(Packages.ca.uhn.hl7v2.model.v23.segment);
importPackage(Packages.ca.uhn.hl7v2.model.v23.datatype);
importPackage(Packages.ca.uhn.hl7v2.util);
importPackage(java.io);
var message = dataSet.getActualData();
var destMessage = new ORU_R01();
// copy MSH from the source
DeepCopy.copy(message.getMSH(), destMessage.getMSH());
// change sender
destMessage.getMSH().getSendingApplication().getNamespaceID().setValue("Integrator");
var responses = message.getRESPONSEAll();
for (resNum = 0; resNum < responses.length; resNum++) {
var response = responses.get(resNum);
var newResponse = destMessage.insertRESPONSE(resNum);
// copy PID AND PV1 from the source
DeepCopy.copy(response.getPATIENT().getPID(), newResponse.getPATIENT().getPID());
DeepCopy.copy(response.getPATIENT().getVISIT().getPV1(), newResponse.getPATIENT().getVISIT().getPV1());
// Everything below and including OBR|2| in source message is not used.
var orderObservation = response.getORDER_OBSERVATION();
var sourceObr = orderObservation.getOBR();
var orderNums = sourceObr.getPlacerOrderNumber();
if (orderNums != null) {
for (orNum = 0; orNum < orderNums.length; orNum++) {
var or = orderNums[orNum];
var destOrderObservation = newResponse.insertORDER_OBSERVATION(orNum);
// copy ORC from the source and chnage ORC-2
DeepCopy.copy(orderObservation.getORC(), destOrderObservation.getORC());
while (destOrderObservation.getORC().getOrc2_PlacerOrderNumberReps() > 1) destOrderObservation.getORC().removeOrc2_PlacerOrderNumber(1);
destOrderObservation.getORC().getOrc2_PlacerOrderNumber(0).getEntityIdentifier().setValue(or.getEntityIdentifier().getValue());
// copy OBR from the source
DeepCopy.copy(orderObservation.getOBR(), destOrderObservation.getOBR());
while (destOrderObservation.getOBR().getObr2_PlacerOrderNumberReps() > 1) destOrderObservation.getOBR().removeObr2_PlacerOrderNumber(1);
destOrderObservation.getOBR().getObr2_PlacerOrderNumber(0).getEntityIdentifier().setValue(or.getEntityIdentifier().getValue());
var observations = orderObservation.getOBSERVATIONAll();
// copy source OBX to dest OBX
for (index = 0; index < observations.length; index++) {
var observation = observations.get(index);
var newObservation = destOrderObservation.insertOBSERVATION(index);
DeepCopy.copy(observation.getOBX(), newObservation.getOBX());
}
// add PDF attachment as last obx
if (orNum == orderNums.length - 1) {
var folder = FilenameUtils.getFullPath(etlConfig.getAliasesMap().get(task.getConnectionName()).getUrl());
var file = folder + "result.PDF";
if (FileUtils.fileExists(file)) {
var attachment = Base64.encodeBytes(FileUtils.getBytesFromFile(new File(file)), Base64.DONT_BREAK_LINES);
var newObservation = destOrderObservation.insertOBSERVATION(observations.length);
newObservation.getOBX().getObx1_SetIDOBX().setValue(observations.length + 1);
newObservation.getOBX().getObx2_ValueType().setValue("ED");
newObservation.getOBX().getObservationIdentifier().getCe1_Identifier().setValue("PDF");
newObservation.getOBX().getObservationIdentifier().getCe2_Text().setValue("PDF BASE64");
newObservation.getOBX().getObservationSubID().setValue(1);
var msg = "^^PDF^Base64^${ATTACH:" + attachment + "}";
newObservation.getOBX().insertObx5_ObservationValue(0).parse(msg);
}
}
}
}
}
dataSet.setActualData(destMessage);
The part of the code below is responsible for reading the PDF from the processing (local) folder, base64 encoding it, and attaching to the reformatted message. The expected file name is result.PDF:
....
// add PDF attachment as last obx
if (orNum == orderNums.length - 1) {
var folder = FilenameUtils.getFullPath(etlConfig.getAliasesMap().get(task.getConnectionName()).getUrl());
var file = folder + "result.PDF";
if (FileUtils.fileExists(file)) {
var attachment = Base64.encodeBytes(FileUtils.getBytesFromFile(new File(file)), Base64.DONT_BREAK_LINES);
var newObservation = destOrderObservation.insertOBSERVATION(observations.length);
newObservation.getOBX().getObx1_SetIDOBX().setValue(observations.length + 1);
newObservation.getOBX().getObx2_ValueType().setValue("ED");
newObservation.getOBX().getObservationIdentifier().getCe1_Identifier().setValue("PDF");
newObservation.getOBX().getObservationIdentifier().getCe2_Text().setValue("PDF BASE64");
newObservation.getOBX().getObservationSubID().setValue(1);
var msg = "^^PDF^Base64^${ATTACH:" + attachment + "}";
newObservation.getOBX().insertObx5_ObservationValue(0).parse(msg);
}
}
....
Please also keep in mind that, according to the HL7 specs, the size of the attachment in the OBX segment is limited to 65 Kb.
10) Save and test the flow.
- Prerequisites for this flow to work: the files result.hl7 and result.PDF exist in the processing (local) folder.
- To verify that the flow has been executed and has produced the correct results, check that the correct file was created in destination-results folder.
Step 5. Create a move files to processing flow.
This flow moves files from the source-results folder to both the processing (local) and processing (remote) folders. Files in the processing (remote) folder have the same names as the original files. Files in the processing (local) folder will be renamed to result..
For this flow we will need the following connections:
- A connection which points to the source-results folder.
- A connection which points to the processing (local) folder.
- A connection which points to the processing (remote) folder.
1) Start creating a flow by clicking the Add flow
button on the Flows window.
2) Type files
into the Search... box and select File Management.
3) In the opened window add 4 transformations:
-
Move all the files from source-results to the processing (remote) folder.
1) Select a source (FROM) connection which points to the source-results folder.
2) Enter
*.*
into the FROM field.3) Select a destination (TO) connection which points to the processing (remote) folder.
4) Enter
*.*
in the TO field.5) Click the
MAPPING
button and select the Parameters tab.6) Select
Move
for the Action. By selecting this action you are configuring the transformation to move files from the source-results to the processing (remote) folder. -
Create the folder processing (local) if it does not exist.
1) Select source (FROM) and destination (TO) connections which point to the processing (local) folder.
2) Enter
processing
in the FROM and TO fields.3) Click the
MAPPING
button and select the Parameters tab.4) Select
Create Folder(s)
as the Action. By selecting this action you are configuring the transformation to create a processing (local) folder if it does not exist. -
Copy files from the processing (remote) to the processing (local) folder.
1) Select a source (FROM) connection which points to the processing (remote) folder.
2) Enter
*.*
into the FROM field.3) Select a destination (TO) connection which points to the processing (local) folder.
4) Enter
*.*
into the TO field.3) Click the
MAPPING
button and select the Parameters tab.4) Select
Copy
as the Action. By selecting this action you are configuring the transformation to copy files from the processing (remote) to the processing (local) folder. -
Rename files in the processing (local) to result..
1) Select a source (FROM) connection which points to the processing (local) folder.
2) Enter
*.*
into the FROM field.3) Select a destination (TO) connection which points to the processing (local) folder.
4) Enter
result.*
into the TO field.3) Click the
MAPPING
button and select the Parameters tab.4) Select
Rename
as the Action. By selecting this action, you are configuring the transformation to rename files in the processing (local) folder to result..
4) Save and test the flow.
- A prerequisite for this flow to succeed: the source files exist in the source-results folder.
- To verify that the flow has been executed and has produced the correct results, check to see that the source files were moved with the same name to the processing (remote) folder and were copied to the processing (local) folder with a different name: result. .
Step 6. Create a clean up flow.
This flow deletes files from both the processing folders or, if there is an error, moves files to the failed folder.
1) Start creating a flow by clicking the Add flow
button on the Flows window.
2) Type files
into the Search... box and select File Management
3) In the opened window add 3 transformations:
-
Delete files from the processing (local) folder.
1) Select a source (FROM) connection which points to the processing (local) folder.
2) Enter
*.*
into the FROM field.3) Click the
MAPPING
button and select the Parameters tab.4) Select Delete as the Action. By selecting this action you are configuring the transformation to delete files from the processing (local) folder.
-
Delete files from the processing (remote) folder.
1) Select a source (FROM) connection which points to the processing (remote) folder.
2) Enter
*.*
into the FROM field.3) Click the
MAPPING
button and select the Parameters tab.4) Select
Delete
as the Action. By selecting this action you are configuring the transformation to delete files from the processing (remote) folder. -
Move files to the failed folder.
1) Select a source (FROM) connection which points to the processing (remote) folder.
2) Select a destination (TO) connection which points to the failed folder.
3) Enter
*.*
into the FROM field.4) Click the
MAPPING
button and select the Parameters tab.5) Select
Move
for the Action. By selecting this action you are configuring the transformation to move files from the processing (remote) folder to the failed folder.6) Select Execute if Error. By selecting this action you are configuring the transformation to move files from the processing (remote) folder to the failed folder in case of any error.
4) Save and test the flow.
- The prerequisite for this flow to work: the file exists in the processing (local) and processing (remote) folders.
- To verify that the flow has been executed and has produced the correct results, check that the files were deleted from the processing (local) and processing (remote) folders.
Step 7. Put it all together.
In the previous 6 steps, we created 3 flows which:
- Move files from the source-results to the 2 processing folders.
- Reformat a file and copy it to the destination-results folder.
- Clean up by removing files from the processing folders, or moving files to the failed folder, if there was an error.
In order to put it all together, we will need to create a nested flow.
Add the following flows to the nested flow:
1) The flow created in Step 5.
2) The flow created in Step 4.
3) The flow created in Step 6.
Save and test the flow.
- A prerequisite for this flow to work: the source file exists in the source-results folder.
- To verify that the flow has been executed and has produced the correct results, check that the correct file was created in the destination-results folder, and the original source files were deleted from the source-results folder.
Step 8. Schedule the flow created in Step 7 to be executed periodically.
Comments
0 comments
Please sign in to leave a comment.