Skip to content

Workflow of cirs-gapp

Getting active hospitalids from database

AS our application supports multiple hospitals, we get the ids of the hospitals whose active status="1" in the database from a table called "MST_Hospital"

Getting documents that are to be processed

After getting ids of active hospitals from database , then we will get all the pending documents that are to be processed for each active hospital by using the stored procedure "CIRS_GetPendingDocumentToProcess"

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
select Top 50 hdd.DocumentID,1 hospitalId,hdd.Document,hd.DocumentTypeID,mdt.DocumentAliasName,hd.TranscriptionDateTime,hd.AccountNumber,
        hv.PatientClass,DATEDIFF(MONTH,hp.DOB,hv.AdmitDate)/12 as Age,DATEDIFF(DAY,hp.DOB,hv.AdmitDate) as AgeInDays,hp.Gender,hd.HospitalDay,
        ISNULL(CONVERT(VARCHAR(10),hv.AdmitDate,101),CONVERT(VARCHAR(10),getDate(),101)) AdmitDate,ISNULL(CONVERT(VARCHAR(10),hv.DischargeDate,101),CONVERT(VARCHAR(10),getDate(),101)) DischargeDate,
        CONVERT(VARCHAR(10),hp.DOB,101) DateOfBirth,idt.InternalDocumentTypeID,idt.InternalDocumentName
        from HIM_DocumentData hdd
        inner join HIM_Document hd on hdd.DocumentID=hd.DocumentID
        inner join MST_DocumentType mdt on mdt.DocumentTypeID=hd.DocumentTypeID
        inner join MST_InternalDocumentType idt on mdt.InternalDocumentTypeID=idt.InternalDocumentTypeID
        inner join HIM_Visit hv on hv.AccountNumber=hd.AccountNumber        
        inner join HIM_Patient hp on hp.PatientId=hv.PatientID
        where hd.DocumentRunningStatusID=0 and hd.Formatted=1 and hd.HospitalDay is not null 

here we will connect to each hospital database by using the jdbcTemplate which is generated dynamically based on the id of the hospital.

After getting the documents that are to be processed from the database , we create gate documents from these documents by appending different features along with dictionary running features and jape running features,which will be required while processing the document through the gapp file

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
for(ClinicalDocument clinicalDocument: clinicalDocuments) {
           Document gateDocument=Factory.newDocument(clinicalDocument.getDocument());
           FeatureMap featureMap=Factory.newFeatureMap();
           featureMap.put("documentId", clinicalDocument.getDocumentId());
           featureMap.put("accountNumber", clinicalDocument.getAccountNumber());
           featureMap.put("documentName", clinicalDocument.getDocumentName());
           featureMap.put("documentTypeId", clinicalDocument.getDocumentTypeId());
           featureMap.put("documentAliasName",clinicalDocument.getDocumentAliasName());
           featureMap.put("internalDocumentAliasName", clinicalDocument.getInternalDocumentAliasName());
           featureMap.put("hospitalDay", clinicalDocument.getHospitalDay());
           featureMap.put("worktype", clinicalDocument.getDocumentAliasName());
           featureMap.put("ageInDays", clinicalDocument.getAgeInDays());
           featureMap.put("age", clinicalDocument.getAge());
           featureMap.put("admitDate", clinicalDocument.getAdmitDate());
           featureMap.put("dischargeDate", clinicalDocument.getDischargeDate());
           featureMap.put("dateOfBirth", clinicalDocument.getDateOfBirth());
           featureMap.put("gender", clinicalDocument.getGender());
           featureMap.put("internalDocumentName",clinicalDocument.getInternalDocumentName());
           clinicalDocumentRunningFeatures.setDictionaryRunningFeatures(featureMap);
           clinicalDocumentRunningFeatures.setJapeRunningFeatures(featureMap, clinicalDocument.getInternalDocumentTypeId());
           gateDocument.setFeatures(featureMap);
           gateDocuments.add(gateDocument);
            }

Processing the documents

Now these gate documents are ready to be processed ,we will pass these documents one by one to the processDocument method of the document Processor instance which we got from the gate-beans.xml

Before passing the documents to the processDocument method we update the documentRunningStatus of the document to 2 in the database.

If the document is processed successfully we will update the documentRunningStatus to 1 in the database.

Reading Annotations from document

Later these processed documents are passed to the handleDocumentAnnotations method of AnnotationService class , in which we will call different types of annotation readers to extract all the annotations from the processed document and save them to the database.we will discuss later in detail about the annotationService class and the different type of annotationReaders

Saving these analysed documents to xml

After analysis these documents are saved into the datastores in xml format based on the worktype and processing date of the document .These files when again loaded into gate developer will be helpful in displaying the annotations and their covered texts and also can be useful in debugging the missed annotations.

If any exception occurs in the above whole process then the documentrunningstatus will be updated to 3 in the database

Scheduling the application

All the above processes are called in a single method called processClinicalDocumentFromQueue, which is scheduled for every thirty seconds by using @Scheduled(fixedRate=time stamp) above the method signature which is achieved by enabling scheduling option in the main class by using @EnableScheduling annotation

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
 @Scheduled(fixedRate= 30000)
        public void processClinicalDocumentFromQueue() throws GateException, IOException {

            List<Hospital> hospitalList=clinicalDocumentRepository.getActiveHospitals();
            for ( Hospital hospital: hospitalList) {

                int hospitalId= hospital.getHospitalId();               
                log.info(hospitalId+"------------------------hospitalId");
            List<Document> documents=clinicalDocumentService.getGateDocument(hospitalId);

                for(Document document: documents) {
                    int documentId=0;
                    documentId=(int) document.getFeatures().get("documentId");
                clinicalDocumentFactory.updateDocumentRunningStatus( documentId,2,hospitalId) ;
                log.info("Processing document :"+document.getFeatures().get("documentId"));

                try {
                    long analyisStartTime = System.currentTimeMillis();
                    documentProcessor.processDocument(document);
                    long analysisEndTime = System.currentTimeMillis();
                    long analysisDuration=(analysisEndTime-analyisStartTime);
                    log.info("analysis time{}",analysisDuration);
                    if(analysisDuration>60000)
                    log.warn("processing of this document is taking too long {}",documentId);

                    clinicalDocumentFactory.updateDocumentRunningStatus( documentId,1,hospitalId) ;
                    clinicalDocumentFactory.updateDocumentInitialRunningDate(documentId,hospitalId);
                    clinicalDocumentFactory.updateDocumentLastRunDate(documentId,hospitalId);

                    long insertionStartTime = System.currentTimeMillis();
                    annotationService.handleDocumentAnnotations(document ,hospitalId);
                    long insertionEndTime = System.currentTimeMillis();
                    long insertionDuration=(insertionEndTime-insertionStartTime);
                    log.info("insertion time{} ",insertionDuration);
                    if(insertionDuration>60000)
                    log.warn("Insertion of this document  is taking too long {}",documentId);

                    saveDocToXml( document);


                }

Cirs-gapp work flow

cirs-gapp_work-flow1.png