Thursday 11 March 2010

ClearCanvas Integration

I have managed to integrate ClearCanvas into one of my applications. (Please note this is not a product that I intend on releasing, but I thought it may interest some of you out there who are looking at making a similar solution) I was tasked with sharing the workload for our TeleRadiology workstation (GE Centricity RA600 Workstation). The solution I came up with does the following:

Ge Centricty Workstation forwards all cases to a Conquest server.
I wrote a C# application that then queries the Conquest database and displays a list of patients.
I added 2 new fields to the conquest studies database table ‘study_reported’ & ‘study_locked’, both are type TINYINT(1) with a default value of 0;
The conquest server is set to forward all cases to the relevant ClearCanvas workstations.
When the user double clicks on a case the application opens the study in ClearCanvas and set the study_locked field in the database to 1 to prevent other users from accessing the same study.
The doctor is then presented with a small dialog window that is set to be the topmost window which allows him/her to set the study status to reported or unreported. When they click on these buttons the study_reported status is updated in the database, the study_locked flag is also set to 0 and the application closes the ClearCanvas study.

This application should allow our doctors to share some of the workload between two or more workstations and prevent them from double reporting cases.

Some early screenshots of my hack and slash solution:

image
The basic worklist page showing normal, locked and reported cases.

image
Update Study Status dialog showing on top of clearcanvas.

 

Below is some code taken from the ClearCanvas developers site to perform some of the integration:

Open a new instance of ClearCanvas Workstation:

public static void StartViewer()
       {
           const string processName = "ClearCanvas.Desktop.Executable";
           const string viewerProcessPath = @"C:\Program Files\ClearCanvas\ClearCanvas Workstation";

           Process[] viewerProcesses = Process.GetProcessesByName(processName);
           if (viewerProcesses == null || viewerProcesses.Length == 0)
           {
               string executable = Path.Combine(viewerProcessPath, processName) + ".exe";

               ProcessStartInfo startInfo = new ProcessStartInfo(executable, "");
               startInfo.WorkingDirectory = viewerProcessPath;
               Process viewerProcess = Process.Start(startInfo);
               if (viewerProcess == null)
                   MessageBox.Show("Failed to start the viewer process.");
           }
       }

Open the a study in ClearCanvas:

private void openStudy(string uid)
        {
            // check if the study is opened by someone else
            if (!isStudyLocked(uid))  // function to check if the study is locked or not
            {
                // lock the study so no one else opens it
                if (lockStudy(uid)) // function to set the study as locked
                {
                    // open the study in ClearCanvas
                    BasicHttpBinding binding = new BasicHttpBinding();
                    EndpointAddress endpoint = new EndpointAddress("http://127.0.0.1:51124/ClearCanvas/ImageViewer/Automation?wsdl");
                    client = new ViewerAutomationServiceClient(binding, endpoint);

                    try
                    {
                        client.Open();
                        OpenStudiesRequest request = new OpenStudiesRequest();
                        request.ActivateIfAlreadyOpen = true;
                        List<OpenStudyInfo> studiesToOpen = new List<OpenStudyInfo>();

                        OpenStudyInfo info = new OpenStudyInfo(uid);
                        studiesToOpen.Add(info);
                        request.StudiesToOpen = studiesToOpen;
                        client.OpenStudies(request);
                        client.Close();

                        this.Visible = false;  // hide the main window
                        Study_Dialog sd = new Study_Dialog(uid); // show the study dialog window
                        sd.ShowDialog();
                        closeOpenViewerWindows(uid); // once the study dialog window is open close the study window in ClearCanvas
                        this.Visible = true;  // show the main form again
                        unlockStudy(uid);   // unlock the study in the database
                        updateStudyReportedStatus(uid, studyDialogResult); // update the reported status of the study with the variable set by the study dialog window.
                    }
                    catch (Exception ex)
                    {
                        client.Abort();
                        MessageBox.Show(ex.Message);
                        unlockStudy(uid);
                    }

                   // StudyDialog sd = new StudyDialog();
                   // sd.ShowDialog();
                }
            }
            else
            {
                // error the study is opened by someone else
                MessageBox.Show("Study is locked by another user!");
            }
        }

Close the open study windows in ClearCanvas:

public void closeOpenViewerWindows(string uid)
       {
           BasicHttpBinding binding = new BasicHttpBinding();
           EndpointAddress endpoint = new EndpointAddress("http://127.0.0.1:51124/ClearCanvas/ImageViewer/Automation?wsdl");
           client = new ViewerAutomationServiceClient(binding, endpoint);

           try
           {
               client.Open();
               GetActiveViewersResult result = client.GetActiveViewers();
               foreach (Viewer viewer in result.ActiveViewers)
               {
                   CloseViewerRequest cclose = new CloseViewerRequest();
                   cclose.Viewer = viewer;
                   cclose.Viewer.PrimaryStudyInstanceUid = uid;
                   client.CloseViewer(cclose);
               }
               client.Close();
           }
           catch (Exception)
           {
               client.Abort();
               throw;
           }
       }