RZDCX - Fast Strike DICOM Toolkit  Release 2.1.0.4
ModalityWorklistSCUForm.cs

A C# DICOM Query/Retrieve SCU Example

/*
*
* Copyright (c) 2015, H.R.Z. SOftware Services LTD
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using rzdcxLib;
using System.Runtime.InteropServices;
using System.Configuration;
{
public partial class ModalityWorklistSCUForm : Form
{
Configuration config;
private int RecordsCount;
private bool _QueryCanceled;
MWQuery _MWQuery;
Task _queryTask;
public ModalityWorklistSCUForm()
{
InitializeComponent();
}
private string TryGetString(DCXOBJ obj, DICOM_TAGS_ENUM tag)
{
try
{
DCXELM e = obj.getElementByTag((int)tag);
if (e != null && e.Value != null)
return obj.getElementByTag((int)tag).Value.ToString();
else
return "N/A";
}
catch (COMException)
{
return "N/A";
}
}
private void CreateGridsDataLayout()
{
// Requested Procedure Table
DataTable rq = new DataTable("RQ");
rq.Columns.Add(new DataColumn("#", typeof(string)));
rq.Columns.Add(new DataColumn("Patient Name", typeof(string)));
rq.Columns.Add(new DataColumn("Patient ID", typeof(string)));
rq.Columns.Add(new DataColumn("Accession Number", typeof(string)));
rq.Columns.Add(new DataColumn("Requested Procedure ID", typeof(string)));
rq.Columns.Add(new DataColumn("Requested Procedure Description", typeof(string)));
rq.Columns.Add(new DataColumn("Referring Physicians Name", typeof(string)));
rq.Columns.Add(new DataColumn("OBJ", typeof(DCXOBJ)));
DataTable sps = new DataTable("SPS");
sps.Columns.Add(new DataColumn("#Proc", typeof(string)));
sps.Columns.Add(new DataColumn("Requested Procedure ID", typeof(string)));
sps.Columns.Add(new DataColumn("Scheduled Procedure Step Description", typeof(string)));
sps.Columns.Add(new DataColumn("Modality", typeof(string)));
sps.Columns.Add(new DataColumn("Scheduled Station AE Title", typeof(string)));
sps.Columns.Add(new DataColumn("ProcedureStartDate", typeof(string)));
sps.Columns.Add(new DataColumn("ProcedureStartTime", typeof(string)));
sps.Columns.Add(new DataColumn("SPS ID", typeof(string)));
sps.Columns.Add(new DataColumn("OBJ", typeof(DCXOBJ)));
DataTable PrC = new DataTable("PrC");
PrC.Columns.Add(new DataColumn("SPS ID", typeof(string)));
PrC.Columns.Add(new DataColumn("CodeValue", typeof(string)));
PrC.Columns.Add(new DataColumn("CodingSchemeDesignator", typeof(string)));
PrC.Columns.Add(new DataColumn("CodingSchemeVersion", typeof(string)));
PrC.Columns.Add(new DataColumn("CodeMeaning", typeof(string)));
DataSet data = new DataSet();
data.Tables.Add(rq);
data.Tables.Add(sps);
data.Tables.Add(PrC);
//DataRelation relation1 = new DataRelation("RP_SPS",
// data.Tables["RQ"].Columns["Requested Procedure ID"],
// data.Tables["SPS"].Columns["Requested Procedure ID"], false);
//data.Relations.Add(relation1);
DataRelation relation1 = new DataRelation("RP_SPS",
data.Tables["RQ"].Columns["#"],
data.Tables["SPS"].Columns["#Proc"], false);
data.Relations.Add(relation1);
DataRelation relation2 = new DataRelation("SPS_PrC",
data.Tables["SPS"].Columns["SPS ID"],
data.Tables["PrC"].Columns["SPS ID"], false);
data.Relations.Add(relation2);
// Bind the master data connector
bsRP.DataSource = data;
bsRP.DataMember = "RQ";
// Bind the details data connector
// using the DataRelation name to filter the information in the
// details table based on the current row in the master table.
bsSPS.DataSource = bsRP;
bsSPS.DataMember = "RP_SPS";
//Bind Protocol Codes
bsPrC.DataSource = bsSPS;
bsPrC.DataMember = "SPS_PrC";
// Resize the master DataGridView columns to fit the newly loaded data.
dgvRP.AutoResizeColumns();
dgvRP.Columns["OBJ"].Visible = false;
// Configure the details DataGridView so that its columns automatically
// adjust their widths when the data changes.
dgvSPS.AutoSizeColumnsMode =
DataGridViewAutoSizeColumnsMode.AllCells;
dgvSPS.Columns["OBJ"].Visible = false;
dgvSPS.Columns["#Proc"].Visible = false;
this.dgvProtocolCodes.AutoSizeColumnsMode =
DataGridViewAutoSizeColumnsMode.AllCells;
//dgvProtocolCodes.Columns["OBJ"].Visible = false;
dgvProtocolCodes.Columns["SPS ID"].Visible = false;
}
private void QueryBtn_Click(object sender, EventArgs e)
{
this.RecordsCount = 0;
this._QueryCanceled = false;
this._MWQuery = this.BuildMWQuery();
this._MWQuery.MWQueryResultUpdatingHookHandler += new MWQuery.MWQueryResultUpdatingHook(query_QueryResultUpdatingHandler);
_queryTask = Task.Factory.StartNew(() => RunQuery(_MWQuery));
}
void query_QueryResultUpdatingHandler(MWQueryEntry newRec, bool Cancel, string ErrMess)
{
DoUiStuff(
() =>
{
if (newRec != null)
{
DataTable rq = ((DataSet)(bsRP.DataSource)).Tables["RQ"];
DataTable sps = ((DataSet)(bsRP.DataSource)).Tables["SPS"];
DataTable PrC = ((DataSet)(bsRP.DataSource)).Tables["PrC"];
DataRow rqRow;
DataRow spsRow;
DataRow PrCRow;
this.RecordsCount++;
this._QueryCanceled = Cancel;
rqRow = rq.NewRow();
rqRow["#"] = this.RecordsCount.ToString();
rqRow["Patient Name"] = newRec.PatientName;
rqRow["Patient ID"] = newRec.PatientID;
rqRow["Accession Number"] = newRec.AccessionNumber;
rqRow["Requested Procedure ID"] = newRec.RequestedProcedureID;
rqRow["Requested Procedure Description"] = newRec.RequestedProcedureDescription;
rqRow["Referring Physicians Name"] = newRec.ReferringPhysiciansName;
rqRow["OBJ"] = newRec.DicomObject;
rq.Rows.Add(rqRow);
// Now iterate over the SPS of this RQ
for (int i = 0; i < newRec.ScheduledProcedureStepID.Count; i++ )
{
spsRow = sps.NewRow();
spsRow["#Proc"] = this.RecordsCount.ToString();
spsRow["Requested Procedure ID"] = newRec.RequestedProcedureID;
spsRow["Scheduled Procedure Step Description"] = newRec.ScheduledProcedureStepDescription[i];
spsRow["Modality"] = newRec.Modality[i];
spsRow["Scheduled Station AE Title"] = newRec.StationName[i];
spsRow["ProcedureStartDate"] = newRec.ProcedureStartDate[i];
spsRow["ProcedureStartTime"] = newRec.ProcedureStartTime[i];
spsRow["SPS ID"] = newRec.ScheduledProcedureStepID[i];
spsRow["OBJ"] = newRec.StepDicomObject[i];
sps.Rows.Add(spsRow);
// Now iterate over the Protocol Codes of this SPS if needed
if (this.cbPrCodes.Checked &&
(newRec.StepDicomObject[i].GetElement((int)DICOM_TAGS_ENUM.ScheduledProtocolCodeSequence) != null) &&
(newRec.StepDicomObject[i].GetElement((int)DICOM_TAGS_ENUM.ScheduledProtocolCodeSequence).Value != null))
{
DCXOBJIterator PrCIt =
newRec.StepDicomObject[i].getElementByTag((int)DICOM_TAGS_ENUM.ScheduledProtocolCodeSequence).Value as DCXOBJIterator; ;
for (; !PrCIt.AtEnd(); PrCIt.Next())
{
DCXOBJ PrCObj = PrCIt.Get();
PrCRow = PrC.NewRow();
//PrCRow["#Proc"] = Counter.ToString();
//PrCRow["Requested Procedure ID"] =
// TryGetString(currObj, DICOM_TAGS_ENUM.RequestedProcedureID);
PrCRow["CodeValue"] =
TryGetString(PrCObj, DICOM_TAGS_ENUM.CodeValue);
PrCRow["CodingSchemeDesignator"] =
TryGetString(PrCObj, DICOM_TAGS_ENUM.CodingSchemeDesignator);
PrCRow["CodingSchemeVersion"] =
TryGetString(PrCObj, DICOM_TAGS_ENUM.CodingSchemeVersion);
PrCRow["CodeMeaning"] =
TryGetString(PrCObj, DICOM_TAGS_ENUM.CodeMeaning);
PrCRow["SPS ID"] = newRec.ScheduledProcedureStepID[i];
//PrCRow["OBJ"] = PrCObj;
PrC.Rows.Add(PrCRow);
}
}
}
}
else
{
if (!Cancel && (ErrMess != ""))
{
MessageBox.Show("Couldn't connect to Worklist Server. Please verify your settings.\r\n" + ErrMess);
}
}
}
);
}
private MWQuery BuildMWQuery()
{
string DateRange = "";
string TimeRange = "";
string Modality = "";
//Patient data can be added to a query
string PatID = "";
string PatName = "";
string AccNo = "";
//Requested procedure ID can be added to a query
string ReqProcID = "";
DateRange = DCXFunctions.BuildDateTimeRange(checkDateExact.Checked, dateExact.Value,
checkDateFrom.Checked, dateStartDate.Value,
checkDateTo.Checked, dateEndDate.Value,
true);
TimeRange = DCXFunctions.BuildDateTimeRange(checkTimeExact.Checked, timeExact.Value,
checkTimeFrom.Checked, timeFrom.Value,
checkTimeTo.Checked, timeTo.Value,
false);
Modality = comboBoxModality.Text;
MWQuery qr = new MWQuery(this.StationNameEdit.Text, DateRange, TimeRange,
TargetAEEdit.Text,
Modality,
PatID, PatName, AccNo, ReqProcID,
this.cbPrCodes.Checked, this.txtProtocolCode.Text);
return qr;
}
private void RunQuery(MWQuery query)
{
OnQueryStarted();
int Timeout = 5; //Seconds
string PathToLog = "LastWorklistQuery1.log"; //Define your own log file
query.Run(Timeout,
this.LocalAEEdit.Text,
this.TargetAEEdit.Text,
this.HostEdit.Text,
Convert.ToUInt16(this.PortEdit.Text),
PathToLog);
this.OnQueryEnded();
}
private void OnQueryStarted()
{
DoUiStuff(
() =>
{
dgvRP.DataSource = null;
dgvSPS.DataSource = null;
dgvProtocolCodes.DataSource = null;
DataTable rq = ((DataSet)(bsRP.DataSource)).Tables["RQ"];
DataTable sps = ((DataSet)(bsRP.DataSource)).Tables["SPS"];
DataTable PrC = ((DataSet)(bsRP.DataSource)).Tables["PrC"];
sps.Rows.Clear();
rq.Rows.Clear();
PrC.Rows.Clear();
dgvRP.DataSource = bsRP;
dgvSPS.DataSource = bsSPS;
dgvProtocolCodes.DataSource = bsPrC;
// Resize the master DataGridView columns to fit the newly loaded data.
dgvRP.AutoResizeColumns();
dgvRP.Columns["OBJ"].Visible = false;
// Configure the details DataGridView so that its columns automatically
// adjust their widths when the data changes.
dgvSPS.AutoSizeColumnsMode =
DataGridViewAutoSizeColumnsMode.AllCells;
dgvSPS.Columns["OBJ"].Visible = false;
dgvSPS.Columns["#Proc"].Visible = false;
}
);
}
private void OnQueryEnded()
{
DoUiStuff(
() =>
{
// Clear it
_queryTask = null;
//Some UI actions can be called on query ended - sort grid etc.
}
);
}
private void DoUiStuff(Action a)
{
try
{
if (this.InvokeRequired)
this.Invoke(new MethodInvoker(a));
else
a();
}
catch (Exception)
{
}
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
if (checkDateTo.Checked)
{
checkDateExact.Checked = false;
dateEndDate.Enabled = true;
}
else
dateEndDate.Enabled = false;
}
private void checkBox2_CheckedChanged(object sender, EventArgs e)
{
if (checkDateFrom.Checked)
{
checkDateExact.Checked = false;
dateStartDate.Enabled = true;
}
else
dateStartDate.Enabled = false;
}
private void checkBox3_CheckedChanged(object sender, EventArgs e)
{
if (checkDateExact.Checked)
{
dateExact.Enabled = true;
checkDateTo.Checked = false;
checkDateFrom.Checked = false;
}
else
{
dateExact.Enabled = false;
}
}
private void checkTimeExact_CheckedChanged(object sender, EventArgs e)
{
if (checkTimeExact.Checked)
{
timeExact.Enabled = true;
checkTimeFrom.Checked = false;
checkTimeTo.Checked = false;
}
else
{
timeExact.Enabled = false;
}
}
private void checkTimeFrom_CheckedChanged(object sender, EventArgs e)
{
if (checkTimeFrom.Checked)
{
checkTimeExact.Checked = false;
timeFrom.Enabled = true;
}
else
timeFrom.Enabled = false;
}
private void checkTimeTo_CheckedChanged(object sender, EventArgs e)
{
if (checkTimeTo.Checked)
{
checkTimeExact.Checked = false;
timeTo.Enabled = true;
}
else
timeTo.Enabled = false;
}
private void ModalityWorklistSCUExampleForm_Load(object sender, EventArgs e)
{
this.config = ConfigurationManager.OpenExeConfiguration(Application.ExecutablePath);
this.LocalAEEdit.Text = this.config.AppSettings.Settings["LocalAETitle"].Value;
this.TargetAEEdit.Text = this.config.AppSettings.Settings["RemoteAETitle"].Value;
this.HostEdit.Text = this.config.AppSettings.Settings["RemoteHost"].Value;
this.PortEdit.Text = this.config.AppSettings.Settings["RemotePort"].Value;
// Bind the DataGridView controls to the BindingSource
// components and load the data from the database.
dgvRP.DataSource = bsRP;
dgvSPS.DataSource = bsSPS;
this.dgvProtocolCodes.DataSource = bsPrC;
CreateGridsDataLayout();
}
private NetConnectionInfo GetConnectionInfo()
{
NetConnectionInfo conn = new NetConnectionInfo();
conn.CalledETitle = TargetAEEdit.Text;
conn.CallingAETitle = LocalAEEdit.Text;
conn.Host = HostEdit.Text;
conn.Port = UInt16.Parse(PortEdit.Text);
return conn;
}
private void dgvQueryResults_SelectionChanged(object sender, EventArgs e)
{
if (dgvSPS.Rows.Count == 1)
dgvSPS.Rows[0].Selected = true;
}
private void ModalityWorklistSCUForm_FormClosed(object sender, FormClosedEventArgs e)
{
this.ResetOneSettingValue("LocalAETitle", this.LocalAEEdit.Text);
this.ResetOneSettingValue("RemoteAETitle", this.TargetAEEdit.Text);
this.ResetOneSettingValue("RemoteHost", this.HostEdit.Text);
this.ResetOneSettingValue("RemotePort", this.PortEdit.Text);
this.config.Save(ConfigurationSaveMode.Modified);
}
private void ResetOneSettingValue(string keyName, string newValue)
{
if (this.config.AppSettings.Settings[keyName].Value != newValue)
{
this.config.AppSettings.Settings.Remove(keyName);
this.config.AppSettings.Settings.Add(keyName, newValue);
}
}
private void cbPrCodes_CheckedChanged(object sender, EventArgs e)
{
this.dgvProtocolCodes.Visible = cbPrCodes.Checked;
this.dgvSPS.Height = cbPrCodes.Checked ? this.splitContainer1.Panel2.Height - this.dgvProtocolCodes.Height - 7 : this.splitContainer1.Panel2.Height;
}
}
}