本教程展示了如何配置一个pac与XML数据库服务器,允许客户端找到DICOM服务器上的数据集在c# WinForms应用程序使用LEADTOOLS SDK。
| 概述 | |
|---|---|
| 总结 | 本教程介绍了如何处理C-FIND要求PACS服务器在WinForms c#应用程序。 |
| 完成时间 | 60分钟 |
| Visual Studio项目 | 下载教程项目(KB) 22日 |
| 平台 | Windows WinForms c#应用程序 |
| IDE | Visual Studio 2019 |
| 开发许可 | 下载LEADTOOLS |
熟悉的基本步骤,创建一个项目与一个XML数据库和pac服务器通过审查添加引用和设置一个许可证,创建一个简单的PACS服务器,处理请求存储在PACS服务器教程,在工作之前处理发现请求在pac服务器——WinForms c#教程。
从项目中创建的副本处理请求存储在PACS服务器教程。如果你没有这个项目,按照这个教程中的步骤创建它。
的引用需要取决于项目的目的。引用可以通过添加一个或另一个下面的两种方法(但不是全部)。
如果使用NuGet引用,本教程需要以下NuGet包:
Leadtools.Dicom.Pacs.Scp如果使用本地DLL的引用,下面的DLL是必要的。
dll位于< INSTALL_DIR > \ LEADTOOLS22 \ Bin \ Dotnet4 \ x64:
Leadtools.dllLeadtools.Dicom.dll对于一个完整的列表的应用程序所需的DLL文件,请参考文件包含在您的应用程序。
许可解锁项目需要的特性。它之前必须设置工具箱功能。详情,包括教程为不同的平台,请参考设置一个运行时许可。
有两种类型的运行时许可证:
请注意
添加LEADTOOLS NuGet和本地引用设置许可中会详细介绍添加引用和设置一个许可证教程。
与项目创建、添加引用,许可,可以开始编码。
打开数据库\ DicomDB.cs文件,将下面的代码添加到搜索的数据库记录过滤器根据指定的字符串。
公共DataView FindRecords (字符串类型,字符串过滤器){DataView dv;锁(adoDatasetLock){dv =新DataView (ds.Tables[型]);如果(dv ! =零){dv。RowFilter =过滤器;}}返回dv;}
去公用事业\ Client.cs文件,添加下面的代码OnReceiveCFindRequest ()处理程序方法叫做当C-FIND请求发送:
受保护的覆盖无效OnReceiveCFindRequest (字节presentationID,int消息id,字符串affectedClass DicomCommandPriorityType优先级、DicomDataSet数据集){action = _server.InitAction (“C-FIND-REQUEST”ProcessType.FindRequest,这数据集);行动。PresentationID = PresentationID;行动。消息id =消息id;行动。类= affectedClass;行动。优先级=的优先级;action.DoAction ();dataSet.Dispose ();}
打开DicomCommon / Utils.cs文件,并添加以下使用语句。
/ /添加到使用块使用System.Collections.Specialized;使用包含;
添加以下方法从DICOM数据解析和插入不同的值。
公共静态boolIsTagPresent (DicomDataSet扩张型心肌病,长标签){DicomElement元素;元素= dcm.FindFirstElement (零、标签、真正的);返回(元素! =零);}公共静态DicomExceptionCode InsertKeyElement (DicomDataSet dcmRsp, DicomDataSet dcmReq,长标签){DicomExceptionCode ret = DicomExceptionCode.Success;DicomElement元素;试一试{元素= dcmReq.FindFirstElement (零、标签、真正的);如果(元素! =零){dcmRsp.InsertElement (零,假、标签、DicomVRType.UN假,0);}}抓(DicomException de){ret = de.Code;}返回受潮湿腐烂;}公共静态DicomExceptionCode SetKeyElement (DicomDataSet dcmRsp,长标签,对象tagValue){DicomExceptionCode ret = DicomExceptionCode.Success;DicomElement元素;如果(tagValue = =零)返回DicomExceptionCode.Parameter;试一试{元素= dcmRsp.FindFirstElement (零、标签、真正的);如果(元素! =零){字符串s = tagValue.ToString ();如果(IsAscii (s))dcmRsp。SetConvertValue(元素,年代,1);其他的dcmRsp。SetStringValue(元素、年代DicomCharacterSetType.UnicodeInUtf8);}}抓(DicomException de){ret = de.Code;}返回受潮湿腐烂;}公共静态StringCollection GetStringValues (DicomDataSet扩张型心肌病,长标签){DicomElement元素;StringCollection sc =新StringCollection ();元素= dcm.FindFirstElement (零、标签、真正的);如果(元素! =零){如果(dcm.GetElementValueCount(元素)> 0){字符串s = dcm.GetConvertValue(元素);字符串[]= s.Split项目(“\ \”);foreach(字符串价值在项目){sc.Add(价值);}}}返回sc;}公共静态字节[]GetBinaryValues (DicomDataSet扩张型心肌病,长标签){DicomElement元素;元素= dcm.FindFirstElement (零、标签、真正的);如果(元素! =零){如果(元素。长度> 0){返回扩张型心肌病。GetBinaryValue(元素,(int)element.Length);}}返回零;}
打开公用事业\ DicomAction.cs文件,并添加以下使用块。
使用系统;使用System.Collections.Specialized;使用System.Data;
添加FindRequest后直接枚举名称空间声明。
公共枚举ProcessType{EchoRequest,StoreRequest,FindRequest}
添加一个QueryLevel枚举指定查询找到行动发生在水平。
公共枚举QueryLevel{耐心,研究中,系列中,图像}
修改DoAction方法解析FindRequest的过程。
公共无效DoAction (){如果(客户端。协会! =零){开关(流程){/ / C-ECHO情况下ProcessType.EchoRequest:DoEchoRequest ();打破;/ / C-STORE情况下ProcessType.StoreRequest:DoStoreRequest ();打破;/ / C-FIND情况下ProcessType.FindRequest:DoFindRequest ();打破;}}}
使用以下代码DoFindRequest ()方法验证发现请求并调用相关方法根据查询请求。
私人无效DoFindRequest (){字符串水平;字符串msgTag =”“;DicomCommandStatusType状态;/ /检查是否支持抽象语法如果(! IsActionSupported ()){字符串name = GetUIDName ();server.MainForm.Log (“C-FIND-REQUEST:抽象语法(“+名称+不支持通过协会”);客户端。SendCFindResponse (_PresentationID _MessageID、_Class DicomCommandStatusType.ClassNotSupported,零);返回;}/ /检查是否找到请求通过一个有效的数据集如果(ds = =零){server.MainForm.Log (“C-FIND-REQUEST:没有提供数据集”);客户端。SendCFindResponse (_PresentationID _MessageID、_Class DicomCommandStatusType.InvalidArgumentValue,零);返回;}/ /检索查询级别和检查相关标签中所提供的数据集水平=跑龙套。GetStringValue (ds, DicomTag.QueryRetrieveLevel);状态= AttributeStatus(水平,裁判msgTag);如果(状态! = DicomCommandStatusType.Success){server.MainForm.Log (”C-FIND-REQUEST:“+ msgTag);客户端。SendCFindResponse (_PresentationID _MessageID _Class,地位,零);返回;}/ /找到方法根据查询试一试{开关(高度){情况下“病人”:DoPatientFind ();打破;情况下“研究”:DoStudyFind ();打破;情况下“系列”:DoSeriesFind ();打破;情况下“图像”:DoFindImage ();打破;默认的:server.MainForm.Log (“C-FIND-REQUEST:无效的查询检索水平:“+级);客户端。SendCFindResponse (_PresentationID _MessageID、_Class DicomCommandStatusType.InvalidAttributeValue,零);打破;}}抓(异常e){server.MainForm.Log (“C-FIND-REQUEST:处理失败:”+ e.Message);如果(零客户& & client.IsConnected ! = ()){客户端。SendCFindResponse (_PresentationID _MessageID、_Class DicomCommandStatusType.ProcessingFailure,零);}}}
使用以下代码AttributeStatus方法,验证所需的DICOM标签指定查询的水平。
私人DicomCommandStatusType AttributeStatus (字符串的水平,裁判字符串msgTag){如果(水平。长度= = 0){msgTag =“查询检索水平”;返回DicomCommandStatusType.InvalidArgumentValue;}如果(_Class = = DicomUidType。PatientRootQueryFind & &水平! =“病人”){如果(!跑龙套。IsTagPresent (ds, DicomTag.PatientID)){msgTag =“病人ID”;返回DicomCommandStatusType.MissingAttribute;}如果(跑龙套。DicomTag.PatientID GetStringValue (ds)。长度= = 0){msgTag =“病人ID缺失值”;返回DicomCommandStatusType.MissingAttribute;}}如果(要求等级= =“研究”= = | |水平“系列”= = | |水平“图像”){如果(!跑龙套。IsTagPresent (ds, DicomTag.StudyInstanceUID)){msgTag =“UID研究实例”;返回DicomCommandStatusType.MissingAttribute;}如果(要求等级= =“系列”= = | |水平“图像”){如果(跑龙套。DicomTag.StudyInstanceUID GetStringValue (ds)。长度= = 0){msgTag =“研究实例UID缺失值”;返回DicomCommandStatusType.MissingAttribute;}}}如果(要求等级= =“系列”= = | |水平“图像”){如果(!跑龙套。IsTagPresent (ds, DicomTag.SeriesInstanceUID)){msgTag =”系列实例ID”;返回DicomCommandStatusType.MissingAttribute;}}如果(要求等级= =“图像”){如果(!跑龙套。IsTagPresent (ds, DicomTag.SOPInstanceUID)){msgTag =“SOP实例ID”;返回DicomCommandStatusType.MissingAttribute;}}返回DicomCommandStatusType.Success;}
使用下面的代码来实现发现病人查询操作水平。该方法将解析每个检索记录和DICOM数据集作为响应发送到客户机。
响应数据集包含以下要素:
私人无效DoPatientFind (){DataView dv;字符串过滤器=“PATIENTID像‘*’”;字符串patientID =跑龙套。GetStringValue (ds, DicomTag.PatientID);字符串patientName =跑龙套。GetStringValue (ds, DicomTag.PatientName);DicomDataSet rspDs;/ /构建病人过滤器如果(patientID。长度> 0)过滤器=“PATIENTID像”+ patientID +“”;如果(patientName。长度> 0){如果(过滤器。长度> 0)过滤器+ =”和“;过滤器+ =“PATIENTNAME像”+ patientName +“”;}/ /数据库搜索匹配的记录server.MainForm.Log (“数据库查询:“+过滤);dv = server.MainForm.DicomData.FindRecords (“病人”、过滤);/ /填充响应数据集与数据从发现记录foreach(DataRowView drv在dv){我们应该行= drv.Row;rspDs = InitResponseDS (QueryLevel.Patient);跑龙套。SetKeyElement (rspDs DicomTag。PatientID,行“PatientID”]);如果(行“PatientName”]! =零)跑龙套。SetKeyElement (rspDs DicomTag。PatientName,行“PatientName”]);如果(行“PatientBirthDate”]! =零)跑龙套。SetKeyElement (rspDs DicomTag。PatientBirthDate,行“PatientBirthDate”]);如果(行“PatientBirthTime”]! =零)跑龙套。SetKeyElement (rspDs DicomTag。PatientBirthTime,行“PatientBirthTime”]);如果(行“PatientSex”]! =零)跑龙套。SetKeyElement (rspDs DicomTag。PatientSex,行“PatientSex”]);如果(行“EthnicGroup”]! =零)跑龙套。SetKeyElement (rspDs DicomTag。EthnicGroup,行“EthnicGroup”]);如果(行“PatientComments”]! =零)跑龙套。SetKeyElement (rspDs DicomTag。PatientComments,行“PatientComments”]);intseriesCount = 0;intimageCount = 0;DataView dvStudies = server.MainForm.DicomData.FindRecords (“研究”,“PatientID = '”+行(“PatientID”].ToString () +“”);跑龙套。SetKeyElement (rspDs DicomTag。NumberOfPatientRelatedStudies dvStudies.Count);foreach(DataRowView drvStudies在dvStudies){我们应该rowStudy = drvStudies.Row;DataView dvSeries;dvSeries = server.MainForm.DicomData.FindRecords (“系列”,“StudyInstanceUID = '”+ rowStudy [“StudyInstanceUID”].ToString () +“”);seriesCount + = dvSeries.Count;foreach(DataRowView drvSeries在dvSeries){我们应该rowSeries = drvSeries.Row;DataView drvImages;drvImages = server.MainForm.DicomData.FindRecords (“图片”,“SeriesInstanceUID = '”+ rowSeries [“SeriesInstanceUID”].ToString () +“”);imageCount + = drvImages.Count;}}跑龙套。SetKeyElement (rspDs DicomTag。NumberOfPatientRelatedSeries seriesCount);跑龙套。SetKeyElement (rspDs DicomTag。NumberOfPatientRelatedInstances imageCount);试一试{客户端。SendCFindResponse (_PresentationID _MessageID、_Class DicomCommandStatusType。等待,rspDs);server.MainForm.Log (“C-FIND-RESPONSE:响应发送到”+ _AETitle +”(待定));}抓{}rspDs.Dispose ();}客户端。SendCFindResponse (_PresentationID _MessageID、_Class DicomCommandStatusType.Success,零);server.MainForm.Log (“C-FIND-RESPONSE:响应发送到”+ _AETitle +“(最终)”);}
添加以下代码来实现查询找到行动研究水平和发送匹配的数据集在响应给客户端。
响应数据集包含以下要素:
请注意
的值学习日期在请求的DICOM数据集名称(例如:19930822将是8月22日,1993)。创建字符串查询筛选搜索数据库,代码解析二进制值,产生以下结果之一,根据请求客户端:
- 一个字符串的形式“< date1 > - < date2 >”匹配出现的所有日期介于< date1 >和< date2 >包容性。
- 一个字符串的形式”——< date1 >”匹配出现的所有日期之前和包括< date1 >。
- 一个字符串的形式相匹配的“< date1 >——”出现的所有< date1 >和随后的日期。
私人无效DoStudyFind (){DataView dv;字符串过滤器=”“;字符串patientID =”“,studyID accessionNum patientName referringPhysicianName;StringCollection studyInstance;DicomDataSet rspDs;字节[]studyDate;如果(跑龙套。IsTagPresent (ds, DicomTag.PatientID))patientID =跑龙套。GetStringValue (ds, DicomTag.PatientID);accessionNum =跑龙套。GetStringValue (ds, DicomTag.AccessionNumber);studyID =跑龙套。GetStringValue (ds, DicomTag.StudyID);patientName =跑龙套。GetStringValue (ds, DicomTag.PatientName);referringPhysicianName =跑龙套。GetStringValue (ds, DicomTag.ReferringPhysicianName);/ /构建研究过滤器如果(patientID。长度> 0)过滤器+ =“PatientID = '”+ patientID +“”;如果(patientName。长度> 0){如果(过滤器。长度> 0)过滤器+ =”和“;过滤器+ =“PatientName = '”+ patientName +“”;}studyInstance =跑龙套。GetStringValues (ds, DicomTag.StudyInstanceUID);foreach(字符串实例在studyInstance){如果(过滤器。长度> 0)过滤器+ =”和“;过滤器+ =“StudyInstanceUID = '”+实例+“”;}studyDate =跑龙套。GetBinaryValues (ds, DicomTag.StudyDate);/ /解析日期如果(studyDate ! =零& & studyDate。长度> 0){字符串日期;字符串德尔=@“\”;字符串[]dateArray;日期= System.Text.Encoding.ASCII.GetString (studyDate);而(date.IndexOf (“\ 0”)! = 1)日期= date.Remove (date.IndexOf (“\ 0”),1);dateArray = date.Split (del.ToCharArray ());为(int我= 0;我< dateArray.Length;我+ +)dateArray[我]= dateArray[我].Replace (”“,”“);如果(过滤器。长度> 0)过滤器+ =”和“;如果(dateArray [0] .IndexOf (“-”)! = 1){字符串reqDate;如果(dateArray [0]。Substring (0,1) = =“-”){/ /如果它始于一个”——“这是一个范围reqDate = dateArray [0] .Substring (1);过滤器+ =“(StudyDate < = #”+ ConvertToQueryDate (reqDate) +“#)”;}其他的如果(dateArray [0] .Substring (dateArray [0]。长度- 1,1)= =“-”){/ /如果结尾”——“那么低reqDate = dateArray [0]。Substring (0, dateArray [0]。长度- 1);过滤器+ =“(StudyDate > = #”+ ConvertToQueryDate (reqDate) +“#)”;}其他的{/ /日期提供字符串[]cmpDates = dateArray [0] .Split (“- - -”);过滤器+ =“(StudyDate > = #”+ + ConvertToQueryDate (cmpDates [0])“#和“;过滤器+ =“StudyDate < = #”+ + ConvertToQueryDate (cmpDates [1])“#)”;}}其他的过滤器+ =“(StudyDate = #”+ + ConvertToQueryDate (dateArray [0])“#)”;}如果(accessionNum。长度> 0){如果(过滤器。长度> 0)过滤器+ =”和“;过滤器+ =“AccessionNumber像”+ accessionNum +“”;}如果(studyID。长度> 0){如果(过滤器。长度> 0)过滤器+ =”和“;过滤器+ =“StudyID像”+ studyID +“”;}如果(referringPhysicianName。长度> 0){如果(过滤器。长度> 0)过滤器+ =”和“;过滤器+ =“ReferringDrName像”+ referringPhysicianName +“”;}如果(过滤器。长度= = 0)过滤器=“STUDYID像‘*’”;/ /数据库搜索匹配的记录server.MainForm.Log (“数据库查询:“+过滤);dv = server.MainForm.DicomData.FindRecords (“研究”、过滤);/ /填充响应数据集与数据从发现记录foreach(DataRowView drv在dv){我们应该行= drv.Row;rspDs = InitResponseDS (QueryLevel.Study);如果(_Class = = DicomUidType.PatientRootQueryFind)跑龙套。SetKeyElement (rspDs DicomTag。PatientID PatientID);跑龙套。SetKeyElement (rspDs DicomTag。StudyInstanceUID,行“StudyInstanceUID”]);如果(行“StudyDate”]! =零)跑龙套。SetKeyElement (rspDs DicomTag。StudyDate,行“StudyDate”]);如果(行“StudyTime”]! =零)跑龙套。SetKeyElement (rspDs DicomTag。StudyTime,行“StudyTime”]);如果(行“AccessionNumber”]! =零)跑龙套。SetKeyElement (rspDs DicomTag。AccessionNumber,行“AccessionNumber”]);如果(行“StudyID”]! =零)跑龙套。SetKeyElement (rspDs DicomTag。StudyID,行“StudyID”]);如果(行“PatientID”]! =零)跑龙套。SetKeyElement (rspDs DicomTag。PatientID,行“PatientID”]);如果(行“PatientName”]! =零)跑龙套。SetKeyElement (rspDs DicomTag。PatientName,行“PatientName”]);如果(行“ReferringDrName”]! =零)跑龙套。SetKeyElement (rspDs DicomTag。ReferringPhysicianName,行“ReferringDrName”]);DataView dvSeries;intseriesCount = 0;intimageCount = 0;dvSeries = server.MainForm.DicomData.FindRecords (“系列”,“StudyInstanceUID = '”+行(“StudyInstanceUID”].ToString () +“”);seriesCount + = dvSeries.Count;foreach(DataRowView drvSeries在dvSeries){我们应该rowSeries = drvSeries.Row;DataView drvImages;drvImages = server.MainForm.DicomData.FindRecords (“图片”,“SeriesInstanceUID = '”+ rowSeries [“SeriesInstanceUID”].ToString () +“”);imageCount + = drvImages.Count;}跑龙套。SetKeyElement (rspDs DicomTag。NumberOfStudyRelatedSeries seriesCount);跑龙套。SetKeyElement (rspDs DicomTag。NumberOfStudyRelatedInstances imageCount);试一试{客户端。SendCFindResponse (_PresentationID _MessageID、_Class DicomCommandStatusType。等待,rspDs);server.MainForm.Log (“C-FIND-RESPONSE:响应发送到”+ _AETitle +”(待定));}抓{}rspDs.Dispose ();}客户端。SendCFindResponse (_PresentationID _MessageID、_Class DicomCommandStatusType.Success,零);server.MainForm.Log (“C-FIND-RESPONSE:响应发送到”+ _AETitle +“(最终)”);}
添加一个新的ConvertToQueryDate方法和添加下面的代码来解析日期的代码存储在数据库一个合适的滤波器用于检索指定的研究。
私人字符串ConvertToQueryDate (字符串reqDate){返回reqDate。子串(4,2)+“/”+ reqDate。子串(2)+“/”+ reqDate。Substring (0, 4);}
添加以下代码来实现寻找行动系列查询级别和发送匹配的数据集在响应给客户端。
响应数据集包含以下要素:
私人无效DoSeriesFind (){DataView dv;字符串过滤器;字符串形态、seriesNumber patientID studyInstance;StringCollection seriesInstance;DicomDataSet rspDs;patientID =跑龙套。GetStringValue (ds, DicomTag.PatientID);形态=跑龙套。GetStringValue (ds, DicomTag.Modality);seriesNumber =跑龙套。GetStringValue (ds, DicomTag.SeriesNumber);studyInstance =跑龙套。GetStringValue (ds, DicomTag.StudyInstanceUID);/ /构建系列过滤器过滤器=“StudyInstanceUID = '”+ studyInstance +“”;如果(_Class = = DicomUidType。PatientRootQueryFind & & patientID。长度> 0)过滤器+ =”和PatientID = '”+ patientID +“”;seriesInstance =跑龙套。GetStringValues (ds, DicomTag.SeriesInstanceUID);foreach(字符串实例在seriesInstance)过滤器+ =”和SeriesInstanceUID = '”+实例+“”;如果(形态。长度> 0)过滤器+ =“等形态”+方法+“”;如果(seriesNumber。长度> 0)过滤器+ =”和SeriesNumber = "+ seriesNumber;/ /数据库搜索匹配的记录server.MainForm.Log (“数据库查询:“+过滤);dv = server.MainForm.DicomData.FindRecords (“系列”、过滤);/ /填充响应数据集与数据从发现记录foreach(DataRowView drv在dv){我们应该行= drv.Row;rspDs = InitResponseDS (QueryLevel.Series);如果(_Class = = DicomUidType.PatientRootQueryFind)跑龙套。SetKeyElement (rspDs DicomTag。PatientID PatientID);跑龙套。SetKeyElement (rspDs DicomTag。StudyInstanceUID studyInstance);跑龙套。SetKeyElement (rspDs DicomTag。SeriesInstanceUID,行“SeriesInstanceUID”]);如果(行“形态”]! =零)跑龙套。SetKeyElement (rspDs DicomTag。形态,行“形态”]);如果(行“SeriesNumber”]! =零)跑龙套。SetKeyElement (rspDs DicomTag。SeriesNumber,行“SeriesNumber”]);如果(行“SeriesDate”]! =零)跑龙套。SetKeyElement (rspDs DicomTag。SeriesDate,行“SeriesDate”]);DataView dvImages;dvImages = server.MainForm.DicomData.FindRecords (“图片”,“SeriesInstanceUID = '”+行(“SeriesInstanceUID”].ToString () +“”);如果(dvImages ! =零)跑龙套。SetKeyElement (rspDs DicomTag。NumberOfSeriesRelatedInstances dvImages.Count);试一试{客户端。SendCFindResponse (_PresentationID _MessageID、_Class DicomCommandStatusType。等待,rspDs);server.MainForm.Log (“C-FIND-RESPONSE:响应发送到”+ _AETitle +”(待定));}抓{}rspDs.Dispose ();}客户端。SendCFindResponse (_PresentationID _MessageID、_Class DicomCommandStatusType.Success,零);server.MainForm.Log (“C-FIND-RESPONSE:响应发送到”+ _AETitle +“(最终)”);}
使用下面的代码来实现找到动作的图像查询级别和发送匹配的数据集在响应给客户端。
响应数据集包含以下要素:
私人无效DoFindImage (){DataView dv;字符串过滤器;DicomDataSet rspDS;字符串studyInstance、patientID instanceNumber;字符串seriesInstance;StringCollection sopInstanceUID;studyInstance =跑龙套。GetStringValue (ds, DicomTag.StudyInstanceUID);seriesInstance =跑龙套。GetStringValue (ds, DicomTag.SeriesInstanceUID);patientID =跑龙套。GetStringValue (ds, DicomTag.PatientID);instanceNumber =跑龙套。GetStringValue (ds, DicomTag.InstanceNumber);过滤器=“StudyInstanceUID = '”+ studyInstance +“”;过滤器+ =”和SeriesInstanceUID = '”+ seriesInstance +“”;如果(_Class = = DicomUidType。PatientRootQueryFind & & patientID。长度> 0)过滤器+ =”和PatientID = '”+ patientID +“”;sopInstanceUID =跑龙套。GetStringValues (ds, DicomTag.SOPInstanceUID);foreach(字符串实例在sopInstanceUID)过滤器+ =”和SOPInstanceUID = '”+实例+“”;如果(instanceNumber。长度> 0)过滤器+ =”和InstanceNumber = "+ instanceNumber.ToString ();server.MainForm.Log (“数据库查询:“+过滤);dv = server.MainForm.DicomData.FindRecords (“图片”、过滤);foreach(DataRowView drv在dv){我们应该行= drv.Row;rspDS = InitResponseDS (QueryLevel.Image);如果(_Class = = DicomUidType.PatientRootQueryFind)跑龙套。SetKeyElement (rspDS DicomTag。PatientID PatientID);跑龙套。SetKeyElement (rspDS DicomTag。SOPInstanceUID,行“SOPInstanceUID”]);如果(行“InstanceNumber”]! =零)跑龙套。SetKeyElement (rspDS DicomTag。InstanceNumber,行“InstanceNumber”]);rspDS.Dispose ();}客户端。SendCFindResponse (_PresentationID _MessageID、_Class DicomCommandStatusType.Success,零);server.MainForm.Log (“C-FIND-RESPONSE:响应发送到”+ _AETitle +“(最终)”);}
使用下面的代码来添加InitResponseDS ()方法创建了DICOM数据集对象,将作为响应对每个匹配的记录找到行动。
一旦创建,该方法将关键元素插入到数据集根据查询的水平。
私人DicomDataSet InitResponseDS (QueryLevel级别){DicomDataSet rspDs =新DicomDataSet ();rspDs.Initialize (DicomClassType。未定义,DicomDataSetInitializeType.ExplicitVRLittleEndian);开关(高度){情况下QueryLevel.Patient:跑龙套。SetTag (rspDs DicomTag.QueryRetrieveLevel,“病人”);/ /需要钥匙跑龙套。InsertKeyElement (rspDs ds, DicomTag.PatientName);/ /可选的钥匙跑龙套。InsertKeyElement (rspDs ds, DicomTag.PatientBirthDate);跑龙套。InsertKeyElement (rspDs ds, DicomTag.PatientBirthTime);跑龙套。InsertKeyElement (rspDs ds, DicomTag.PatientSex);跑龙套。InsertKeyElement (rspDs ds, DicomTag.EthnicGroup);跑龙套。InsertKeyElement (rspDs ds, DicomTag.PatientComments);跑龙套。InsertKeyElement (rspDs ds, DicomTag.NumberOfPatientRelatedStudies);跑龙套。InsertKeyElement (rspDs ds, DicomTag.NumberOfPatientRelatedSeries);跑龙套。InsertKeyElement (rspDs ds, DicomTag.NumberOfPatientRelatedInstances);打破;情况下QueryLevel.Study:跑龙套。SetTag (rspDs DicomTag.QueryRetrieveLevel,“研究”);/ /需要钥匙跑龙套。InsertKeyElement (rspDs ds, DicomTag.StudyDate);跑龙套。InsertKeyElement (rspDs ds, DicomTag.StudyTime);跑龙套。InsertKeyElement (rspDs ds, DicomTag.AccessionNumber);跑龙套。InsertKeyElement (rspDs ds, DicomTag.StudyID);跑龙套。InsertKeyElement (rspDs ds, DicomTag.PatientName);跑龙套。InsertKeyElement (rspDs ds, DicomTag.PatientID);/ /可选的钥匙跑龙套。InsertKeyElement (rspDs ds, DicomTag.StudyDescription);跑龙套。InsertKeyElement (rspDs ds, DicomTag.ReferringPhysicianName);跑龙套。InsertKeyElement (rspDs ds, DicomTag.NumberOfStudyRelatedSeries);跑龙套。InsertKeyElement (rspDs ds, DicomTag.NumberOfStudyRelatedInstances);打破;情况下QueryLevel.Series:跑龙套。SetTag (rspDs DicomTag.QueryRetrieveLevel,“系列”);/ /需要钥匙跑龙套。InsertKeyElement (rspDs ds, DicomTag.Modality);跑龙套。InsertKeyElement (rspDs ds, DicomTag.SeriesNumber);跑龙套。InsertKeyElement (rspDs ds, DicomTag.SeriesDate);/ /可选的钥匙跑龙套。InsertKeyElement (rspDs ds, DicomTag.NumberOfSeriesRelatedInstances);打破;情况下QueryLevel.Image:跑龙套。SetTag (rspDs DicomTag.QueryRetrieveLevel,“图像”);/ /需要钥匙跑龙套。InsertKeyElement (rspDs ds, DicomTag.InstanceNumber);打破;}如果(_Class = = DicomUidType。PatientRootQueryFind & &水平! = QueryLevel.Study)rspDs.InsertElement (零,假,DicomTag。PatientID DicomVRType.UN,假,0);如果(= = QueryLevel水平。研究| | = = QueryLevel水平。系列| | = = QueryLevel.Image)水平rspDs.InsertElement (零,假,DicomTag。StudyInstanceUID DicomVRType.UN,假,0);如果(= = QueryLevel水平。系列| | = = QueryLevel.Image)水平rspDs.InsertElement (零,假,DicomTag。SeriesInstanceUID DicomVRType.UN,假,0);如果(要求等级= = QueryLevel.Image)rspDs.InsertElement (零,假,DicomTag。SOPInstanceUID DicomVRType.UN,假,0);返回rspDs;}
在运行项目,之前打开工具/ Server.cs文件并添加语法支持查找操作。
私人无效BuildInclusionList (){_UidInclusionList.Add (DicomUidType.VerificationClass);/ /存储传输语法_UidInclusionList.Add (DicomUidType.JPEG2000LosslessOnly);/ / Image1.dcm_UidInclusionList.Add (DicomUidType.JPEGLosslessNonhier14B);/ / Image2.dcm_UidInclusionList.Add (DicomUidType.ImplicitVRLittleEndian);/ / Image3.dcm/ /存储抽象语法_UidInclusionList.Add (DicomUidType.EnhancedMRImageStorage);/ / Image1.dcm_UidInclusionList.Add (DicomUidType.DXImageStoragePresentation);/ / Image2.dcm_UidInclusionList.Add (DicomUidType.MRImageStorage);/ / Image3.dcm/ /找到抽象语法_UidInclusionList.Add (DicomUidType.PatientRootQueryFind);_UidInclusionList.Add (DicomUidType.StudyRootQueryFind);}
按运行项目F5,或通过选择调试- >开始调试。
如果是正确的步骤,应用程序运行时,允许pac客户机发送C-FIND请求到服务器。在成功验证,处理请求允许检索特定的数据集和发送响应给客户端。
运行LEADTOOLS Dicom客户演示c#演示测试服务器,这个演示是在这里找到:< INSTALL_DIR > \ LEADTOOLS22 \ Bin \ DotNet4 \ x64 \ DicomClientDemo_Original.exe
使用选项按钮配置连接,然后单击搜索按钮来找到所有DICOM数据存储在PACS服务器。
请注意
看到处理请求存储在PACS服务器教程与pac如何添加DICOM数据集文件服务器数据库为了寻找他们。
本教程展示了如何添加一个数据库pac服务器实施C-FIND请求通过搜索数据库的处理和发送一个数据集对应查询的响应级别的请求。