DICOM 基于dcm4che的C-FIND查询实现

现在我们能够校验 DICOM 连接性了。我们甚至能够从一个 AE 向另一个发送图像了。但
是我们怎么找出需要发送的数据呢?三个 C-Find SOP 类提供 DICOM 查询的实现方法,如表
28 所示。
查找成像数据不是影像设备特定的,因此 C-Find 不包括许多像 C-Store 那样、基于影像
设备的 SOP 。因此可以认为, C-Find C-Echo 非常相似(图 40 )。然而, C-Find 中还有一样
是需要全新介绍的: DICOM 将所有 C-Find 数据查询分为了三个数据级别:病人、检查、病
- 检查。这些级别称作根,并且 C-Find 在这三个根上使用不同的 SOP 来实现数据查询
DICOM 查询根符合 5.6 中介绍的 DICOM 病人 - 检查 - 序列 - 图像的数据等级。 DICOM 用四
个等级来组织数据,并且查询数据与等级限制配合的非常好。比如,如果支持病人查询 /
取作为根,那么查询和提取只会将限制在病人 - 检查 - 序列 - 图像这个级别;如果使用检查查询
/ 提取作为根,那么查询和提取将会限制在检查 - 序列 - 图像这个级别。在后面的例子中,所有
病人属性(比如病人姓名或者 ID )将会包含在检查属性中用来识别不同检查。
由于目前的放射工作流是以检查为中心的,因此以检查为根在 DICOM 应用程序中会非常广泛地使用并且通常作为默认设置。病人和病人-检查 SOP 作为查询层级则很少使用。事实上,以病人-检查为查询根最近已经在 DICOM 标准中弃用了,这意味着,在未来的 DICOM
版本中将不会支持这种做法,并且会浅浅地在 DICOM 实现过程中消失。 勿须赘言,C-Find SOP 也符合 DIMSE + IOD 结构,如图 41 所示。 DIMSE 对象(编码来作 为 DICOM 命令对象,组 0000 )传送 C-Find 消息参数,并且附加 IOD 对象(编码来作为 DICOM 数据对象)用来承载查询条件去 C-Find SCP 上找匹配的信息。
DICOM 中数据匹配方面的一些词汇
C-Find SCU 发送一个查询请求时,请求会包括希望获得匹配的属性集合。这些属性会
作为查询字段与目标 AE 中的数据进行比较。总的来说, DICOM 会提供一些设置查询值的方
法:
1. 通配符匹配。我们之前已经有所了解。我们曾在 5.3.2 中第一次提到它,当时我们正在
讨论 DICOM 通配符( *? )。不仅仅在 DICOM 中,很多地方都会常常用通配符来匹配字
符串。比如,如果我们知道一个病人名字是以“ Smit ”开头,那么我们可以在 C-Find
求中将病人姓名( Patient Name (0010,0010) 属性里面输入“ Smit ”并且在其后面使用
(*)代表任何字符序列。我们会找到“ Smith ”、“ Smithson ”、甚至“ Smit III the Great ”,
这些都是符合此次通配符查询的。其他 DICOM 通配符,比如问号(?),表示单一位置
字符,但是很少会用到它,因为我们在不了解字符是什么的情况下,也很有可能不知道
字符的数量,因此干脆用星号就好了。
2. 罗列匹配。此技术使用反斜线(\)通配符,这一位置“或”。比如,病人姓名中的
Smith\Graham ”将用来查找所有叫 Smith Graham 的病人。当然可以将罗列和通配
符结合使用比如“ Smit*\Grah* ”,特别是当你处理由录入错误风险的数据时。(手工录
入的病人姓名很容易造成错误录入)
3. 整体匹配。这是一种最常见的匹配规则。如果被匹配的属性是零长度的,那么就意味着
匹配所有。比如,如果我们在病人姓名栏中留空,并以此条件执行 C-Find 查询,那么
在目标归档中的所有病人姓名都将符合该查询条件。事实上,这种情况下整体匹配意味
着任何可能的值相当于使用星号(*)。然而,在 C-Find 中提供一个零长度匹配属性与
什么都不提供是完全不同的两个概念。包含零长度属性意味着我们希望(或必须)使用
这个零长度属性进行匹配并且我们希望在 C-Find 响应中获得匹配结果。不使用属性进
行查询意味着我们不希望查询内容获得匹配(可能根本不支持这种做法)并且我们也不
想提取结果属性。比如,如果我们不想提取病人姓名,无论病人姓名中是否有值,我们
需要在 C-Find 请求中去掉病人姓名属性。
4. 范围匹配。这种匹配类型用作有范围的属性,比如日期或时间。在范围匹配中,你能够
规定开始和结束的属性值,通过连字号(-)分隔两个值。任何在该范围内的内容都将
匹配此次查询。比如,日期范围匹配 20000201-20100202 意味着在 2000 2 1 日和
2000 2 2 日之间的所有内容。如果开始或结束时间不能确定,可以留空;比如
20000201- 表示“ 2000 2 1 日及之后”。
5. 序列查询。这也许是最复杂的 DICOM 属性匹配形式。这种形式只有在属性的整个序列
(由 SQ VR 组成,见 5.3.10 )用作匹配数据时才会采用。比如,比对影像设备已预约病
人检查时, DICOM 会使用病人 ID 、检查日期和检查号组成属性序列,序列中的每个属
性既可以是确定值,也可以使用前面所提到的某一个匹配类型。在一个 SQ 序列中的属
性是按照逻辑“与”来组合的(意味着所有属性必须匹配)。与表示“或”的反斜线(\)
通配符正好相反。
6. 单一值匹配。这就是简单地使用准巨额属性值作为匹配参数:使用“ Smith ”用做病人
姓名查询;“ 20000201 ”用作日期查询等等。很自然地,单一值匹配的属性必须不包含
通配符和范围查询。单一值匹配通产雇佣在各种 ID UID 的查询上,并且特别用在分
级的关键属性(即唯一 ID ,如病人 ID 、 检查实例 UID 等)上(见 5.6.3 )。
DICOM 数据匹配中的所有属性既可以是必须的也可以是可选的。必须的属性,人如
其名必须在匹配请求中出现。如果我们不知道应该将这类查询值设置成什么,那么我们可以
简单地将它们设置为空值(整体匹配)。这就表明我们保证会收到匹配值。如果我们有兴趣
使用,那么可以使用可选的属性。 DICOM 标准通常会对每个查询类型(比如在病人、检查、
序列、图像层面上的 C-Find )规定其必须的和可选的属性,但是你总是需要对你所查询的设
备进行 DICOM 一致性声明的核实,因为他们通常不会顾及那些看起来更一般的 DICOM 规定。
这在某种程度上是可以理解的,因为用在超声扫描仪上的属性肯定与用在 CT 教学归档上的
属性不同。然而,这却总是带来一个实施上的问题,你不得不针对不同设备来设置不同的查
询属性。
最后要说的是,在 DICOM 中几乎所有的匹配都是大小写敏感的。只允许在某些特定的
属性中使用大小写不敏感,比如姓名( PN VR ),在这些属性中也允许空格和强调符不敏感。
以我个人的看法,我认为大小写敏感根本没能给 DICOM 带来任何好处:首先大小写很有可
能在录入时进行转换,其次这几乎没有人关心。更糟糕的是,一些主流的 PACS 界面会要求
用户只能使用大小写中的一种来如入某些数据:比如,只能用大写来录入病人姓名。很明显
这么做有个重大弊端,除非你录入 SMITH 否则你根本别想找到病人 Smith 。实际上,这种要
求实际上逼着用户在使用 PACS 时按下“大写锁定”,但是这样不可避免地会产生一系列其他
的录入问题。因此,只要可以实现, DICOM DICOM 应用程序就应该避免大小写敏感问题。
C-Find IOD
DICOM 属性匹配大陆上航行过后,我们就可以在更高的层次上对 C-Find 查询进行深入了
解了。 C-Find IOD 包含用来在 C-Find 服务提供者(如数字归档)那里进行匹配的查询参数。表
29 提供了一个真实的一致性声明的实例。 1
5.6.3 所述,在 DICOM 中的所有数据符合病人 - 检查 - 序列 - 图像等级制度,而 C-Find
询也不例外;他们必须属于四个级别中的一个。 C-Find 查询层级会反映在( 0008,0052 )属
性中(必须的),内容会是病人( PATIENT )、检查( STUDY )、序列( SERIES )或图像( IMAGE )。
这同样说明在 SOP 根之外,这种规则也一直在 C-Find 的各个查询层级中遵从着:
1. 所有较高层次的关键属性值 2 必须是已知的。比如,在开始进行检查层次的查询时,我
们必须知道病人 ID
2. 所有当前层次的关键属性将通过 C-Find SCP 返回。比如,在一个检查层次的查询中,“检
查实例 UID (0020,000E) 将总会出现在 C-Find 请求的响应中。这符合规则 1 ,即允许我
们处理更低的层级(序列、图像)。
3. 在任何的 C-Find 请求中,我们只能从当前 C-Find 层次来查询和匹配属性。比如,一个
检查层次的查询只能查询检查属性而不能单独查询序列或图像。
请看我们表 29 中的样例 IOD ;它是什么层次的呢?我们会立即发现其中有一个
(0008,0052) 值:这是检查层次。但是即使你不知道这个值是什么,你仍可以去推断: IOD
看起来有病人 ID (病人层次),但是还没有检查实例 UID (检查层次)。根据规则 1 和规则 2。
这显然是个检查层次的查询。这个逻辑在定位 DICOM 问题时也很有用。比如,如果在关键
属性中我们决定采用的层次与 (0008,0052) 声明的不同,那么 C-Find 查询一定会失败。

 

 

当然,你没有必要一定建立你自己的层次属性表格。每个 DICOM 应用程序的 DICOM
致性声明都会针对每个支持的层次(并且用必须的或可选的来标识它们)列出所有支持的属
性。事实上,一个特定的设备真不一定能够支持所有四个等级层次,它们的一致性声明将仅
包含所支持的层次。
了解C-FIND之后接下来看看如何用代码实现
/**
     * 查询
     *
     * @param host                IP地址
     * @param port                端口号
     * @param aeTitle             remoteAETitle
     * @param queryLevel          查询层级
     * @param queryModel          查询模式
     * @param relational          联合查询
     * @param fuzzy               模糊查询
     * @param dataTimeCombine     时间日期合并
     * @param sourceAeTitle       sourceAeTitle
     * @param modality            检查类型
     * @param studyPeriod         查询时间范围
     * @param scheduledStationAET 检查设备的名称
     * @return 查询结果
     */
    public DICOMResultBean query(String host, int port, String aeTitle, QueryLevel queryLevel,
                                 FindSCU.InformationModel queryModel, boolean relational, boolean fuzzy,
                                 boolean dataTimeCombine, String sourceAeTitle, String modality,
                                 StudyPeriod studyPeriod, String scheduledStationAET, Search search) {

        createConn("findScu", "zoncare");

        MyQueryTool queryTool = new MyQueryTool(host, port, aeTitle, queryLevel.getValue(), queryModel, relational, device, sourceAeTitle, conn);
        try {
            Attributes attributes = getAttributes(modality, studyPeriod, scheduledStationAET, search);

            queryTool.addAll(attributes);
            queryTool.query("worklist查询测试", fuzzy, dataTimeCombine);
            QueryResult result = (QueryResult) queryTool.getResult();
            return getDICOMResultBean(result);
        } catch (Exception e) {
            Log.e("yuhao", "queryMWL: Exception" + e.getMessage());
            e.printStackTrace();
        }
        return null;
    }



 @NotNull
    public static Attributes getAttributes(String modality, StudyPeriod studyPeriod, String scheduledStationAET, Search search) {
        VR vr;
        Attributes attributes = new Attributes();

        if (search == Search.IHE) {
            vr = ElementDictionary.vrOf(Tag.AccessionNumber, (String) null);
            attributes.setNull(Tag.AccessionNumber, vr);

            vr = ElementDictionary.vrOf(Tag.ReferringPhysicianName, (String) null);
            attributes.setNull(Tag.ReferringPhysicianName, vr);

            vr = ElementDictionary.vrOf(Tag.InstitutionalDepartmentName, (String) null);
            attributes.setNull(Tag.InstitutionalDepartmentName, vr);

            vr = ElementDictionary.vrOf(Tag.PregnancyStatus, (String) null);
            attributes.setNull(Tag.PregnancyStatus, vr);

            vr = ElementDictionary.vrOf(Tag.RequestingPhysician, (String) null);
            attributes.setNull(Tag.RequestingPhysician, vr);

            VR vrReferencedStudySequence = ElementDictionary.vrOf(Tag.ReferencedStudySequence, (String) null);
            attributes.setNull(Tag.ReferencedStudySequence, vrReferencedStudySequence);

            Sequence sequence = attributes.newSequence(Tag.ReferencedStudySequence, 1);
            Attributes attributes1 = new Attributes();

            vr = ElementDictionary.vrOf(Tag.ReferencedSOPClassUID, (String) null);
            attributes1.setNull(Tag.ReferencedSOPClassUID, vr);

            vr = ElementDictionary.vrOf(Tag.ReferencedSOPInstanceUID, (String) null);
            attributes1.setNull(Tag.ReferencedSOPInstanceUID, vr);

            sequence.add(attributes1);

            vr = ElementDictionary.vrOf(Tag.PatientName, (String) null);
            attributes.setNull(Tag.PatientName, vr);

            vr = ElementDictionary.vrOf(Tag.PatientID, (String) null);
            attributes.setNull(Tag.PatientID, vr);

            vr = ElementDictionary.vrOf(Tag.PatientBirthDate, (String) null);
            attributes.setNull(Tag.PatientBirthDate, vr);

            vr = ElementDictionary.vrOf(Tag.PatientSex, (String) null);
            attributes.setNull(Tag.PatientSex, vr);

            vr = ElementDictionary.vrOf(Tag.PatientSize, (String) null);
            attributes.setNull(Tag.PatientSize, vr);

            vr = ElementDictionary.vrOf(Tag.PatientWeight, (String) null);
            attributes.setNull(Tag.PatientWeight, vr);

            vr = ElementDictionary.vrOf(Tag.StudyInstanceUID, (String) null);
            attributes.setNull(Tag.StudyInstanceUID, vr);

            vr = ElementDictionary.vrOf(Tag.RequestingPhysician, (String) null);
            attributes.setNull(Tag.RequestingPhysician, vr);

            VR vrRequestedProcedureCodeSequence = ElementDictionary.vrOf(Tag.RequestedProcedureCodeSequence, (String) null);
            attributes.setNull(Tag.RequestedProcedureCodeSequence, vrRequestedProcedureCodeSequence);

            Sequence sequence2 = attributes.newSequence(Tag.RequestedProcedureCodeSequence, 1);
            Attributes attributes2 = new Attributes();

            vr = ElementDictionary.vrOf(Tag.CodeValue, (String) null);
            attributes2.setNull(Tag.CodeValue, vr);

            vr = ElementDictionary.vrOf(Tag.CodingSchemeDesignator, (String) null);
            attributes2.setNull(Tag.CodingSchemeDesignator, vr);

            vr = ElementDictionary.vrOf(Tag.CodeMeaning, (String) null);
            attributes2.setNull(Tag.CodeMeaning, vr);

            sequence2.add(attributes2);

            vr = ElementDictionary.vrOf(Tag.CurrentPatientLocation, (String) null);
            attributes.setNull(Tag.CurrentPatientLocation, vr);

            VR vrScheduledProcedureStepSequence = ElementDictionary.vrOf(Tag.ScheduledProcedureStepSequence, (String) null);
            attributes.setNull(Tag.ScheduledProcedureStepSequence, vrScheduledProcedureStepSequence);

            Sequence sequence3 = attributes.newSequence(Tag.ScheduledProcedureStepSequence, 1);
            Attributes attributes3 = new Attributes();

            vr = ElementDictionary.vrOf(Tag.Modality, (String) null);
            if (modality == null) {
                attributes3.setNull(Tag.Modality, vr);
            } else {
                attributes3.setString(Tag.Modality, vr, modality);
            }

            vr = ElementDictionary.vrOf(Tag.InstitutionName, (String) null);
            attributes3.setNull(Tag.InstitutionName, vr);

            vr = ElementDictionary.vrOf(Tag.InstitutionalDepartmentName, (String) null);
            attributes3.setNull(Tag.InstitutionalDepartmentName, vr);

            vr = ElementDictionary.vrOf(Tag.CurrentPatientLocation, (String) null);
            attributes3.setNull(Tag.CurrentPatientLocation, vr);

            vr = ElementDictionary.vrOf(Tag.ScheduledStationAETitle, (String) null);
            if (scheduledStationAET == null) {
                attributes3.setNull(Tag.ScheduledStationAETitle, vr);
            } else {
                attributes3.setString(Tag.ScheduledStationAETitle, vr, scheduledStationAET);
            }

            StudyPeriodBean studyPeriodBean = getStudyPeriod(studyPeriod);
            vr = ElementDictionary.vrOf(Tag.ScheduledProcedureStepStartDate, (String) null);
            if (studyPeriodBean == null || studyPeriod == StudyPeriod.All) {
                attributes3.setNull(Tag.ScheduledProcedureStepStartDate, vr);
            } else {
                attributes3.setString(Tag.ScheduledProcedureStepStartDate, vr, studyPeriodBean.scheduledProcedureStepStartDate);
            }

            vr = ElementDictionary.vrOf(Tag.ScheduledProcedureStepStartTime, (String) null);
            if (studyPeriodBean == null || studyPeriod == StudyPeriod.All) {
                attributes3.setNull(Tag.ScheduledProcedureStepStartTime, vr);
            } else {
                attributes3.setString(Tag.ScheduledProcedureStepStartTime, vr, studyPeriodBean.scheduledProcedureStepStartTime);
            }

            vr = ElementDictionary.vrOf(Tag.ScheduledProcedureStepEndDate, (String) null);
            if (studyPeriodBean == null || studyPeriod == StudyPeriod.All) {
                attributes3.setNull(Tag.ScheduledProcedureStepEndDate, vr);
            } else {
                attributes3.setString(Tag.ScheduledProcedureStepEndDate, vr, studyPeriodBean.scheduledProcedureStepEndDate);
            }

            vr = ElementDictionary.vrOf(Tag.ScheduledProcedureStepEndTime, (String) null);
            if (studyPeriodBean == null || studyPeriod == StudyPeriod.All) {
                attributes3.setNull(Tag.ScheduledProcedureStepEndTime, vr);
            } else {
                attributes3.setString(Tag.ScheduledProcedureStepEndTime, vr, studyPeriodBean.scheduledProcedureStepEndTime);
            }

            vr = ElementDictionary.vrOf(Tag.ScheduledPerformingPhysicianName, (String) null);
            attributes3.setNull(Tag.ScheduledPerformingPhysicianName, vr);

            vr = ElementDictionary.vrOf(Tag.ScheduledProcedureStepDescription, (String) null);
            attributes3.setNull(Tag.ScheduledProcedureStepDescription, vr);

            sequence3.add(attributes3);

            VR vrScheduledProtocolCodeSequence = ElementDictionary.vrOf(Tag.ScheduledProtocolCodeSequence, (String) null);
            attributes3.setNull(Tag.ScheduledProtocolCodeSequence, vrScheduledProtocolCodeSequence);

            Sequence sequence4 = attributes3.newSequence(Tag.ScheduledProtocolCodeSequence, 1);

            Attributes attributes4 = new Attributes();
            vr = ElementDictionary.vrOf(Tag.CodeValue, (String) null);
            attributes4.setNull(Tag.CodeValue, vr);

            vr = ElementDictionary.vrOf(Tag.CodingSchemeDesignator, (String) null);
            attributes4.setNull(Tag.CodingSchemeDesignator, vr);

            vr = ElementDictionary.vrOf(Tag.CodeMeaning, (String) null);
            attributes4.setNull(Tag.CodeMeaning, vr);

            sequence4.add(attributes4);

            vr = ElementDictionary.vrOf(Tag.ScheduledProcedureStepID, (String) null);
            attributes3.setNull(Tag.ScheduledProcedureStepID, vr);

            vr = ElementDictionary.vrOf(Tag.ScheduledStationName, (String) null);
            attributes3.setNull(Tag.ScheduledStationName, vr);

            vr = ElementDictionary.vrOf(Tag.ScheduledProcedureStepLocation, (String) null);
            attributes3.setNull(Tag.ScheduledProcedureStepLocation, vr);

            vr = ElementDictionary.vrOf(Tag.RequestedProcedureID, (String) null);
            attributes.setNull(Tag.RequestedProcedureID, vr);

            vr = ElementDictionary.vrOf(Tag.RequestedProcedureComments, (String) null);
            attributes.setNull(Tag.RequestedProcedureComments, vr);
        } else {
            vr = ElementDictionary.vrOf(Tag.AccessionNumber, (String) null);
            attributes.setNull(Tag.AccessionNumber, vr);

            vr = ElementDictionary.vrOf(Tag.PatientName, (String) null);
            attributes.setNull(Tag.PatientName, vr);

            vr = ElementDictionary.vrOf(Tag.PatientID, (String) null);
            attributes.setNull(Tag.PatientID, vr);

            vr = ElementDictionary.vrOf(Tag.PatientBirthDate, (String) null);
            attributes.setNull(Tag.PatientBirthDate, vr);

            vr = ElementDictionary.vrOf(Tag.PatientSex, (String) null);
            attributes.setNull(Tag.PatientSex, vr);

            vr = ElementDictionary.vrOf(Tag.CurrentPatientLocation, (String) null);
            attributes.setNull(Tag.CurrentPatientLocation, vr);


            VR vrScheduledProcedureStepSequence = ElementDictionary.vrOf(Tag.ScheduledProcedureStepSequence, (String) null);
            attributes.setNull(Tag.ScheduledProcedureStepSequence, vrScheduledProcedureStepSequence);

            Sequence sequence3 = attributes.newSequence(Tag.ScheduledProcedureStepSequence, 1);
            Attributes attributes3 = new Attributes();

            vr = ElementDictionary.vrOf(Tag.Modality, (String) null);
            if (modality == null) {
                attributes3.setNull(Tag.Modality, vr);
            } else {
                attributes3.setString(Tag.Modality, vr, modality);
            }

            vr = ElementDictionary.vrOf(Tag.InstitutionName, (String) null);
            attributes3.setNull(Tag.InstitutionName, vr);

            vr = ElementDictionary.vrOf(Tag.InstitutionalDepartmentName, (String) null);
            attributes3.setNull(Tag.InstitutionalDepartmentName, vr);

            vr = ElementDictionary.vrOf(Tag.CurrentPatientLocation, (String) null);
            attributes3.setNull(Tag.CurrentPatientLocation, vr);

            vr = ElementDictionary.vrOf(Tag.ScheduledStationAETitle, (String) null);
            if (scheduledStationAET == null) {
                attributes3.setNull(Tag.ScheduledStationAETitle, vr);
            } else {
                attributes3.setString(Tag.ScheduledStationAETitle, vr, scheduledStationAET);
            }

            StudyPeriodBean studyPeriodBean = getStudyPeriod(studyPeriod);
            vr = ElementDictionary.vrOf(Tag.ScheduledProcedureStepStartDate, (String) null);
            if (studyPeriodBean == null || studyPeriod == StudyPeriod.All) {
                attributes3.setNull(Tag.ScheduledProcedureStepStartDate, vr);
            } else {
                attributes3.setString(Tag.ScheduledProcedureStepStartDate, vr, studyPeriodBean.scheduledProcedureStepStartDate);
            }

            vr = ElementDictionary.vrOf(Tag.ScheduledProcedureStepStartTime, (String) null);
            if (studyPeriodBean == null || studyPeriod == StudyPeriod.All) {
                attributes3.setNull(Tag.ScheduledProcedureStepStartTime, vr);
            } else {
                attributes3.setString(Tag.ScheduledProcedureStepStartTime, vr, studyPeriodBean.scheduledProcedureStepStartTime);
            }

            vr = ElementDictionary.vrOf(Tag.ScheduledProcedureStepEndDate, (String) null);
            if (studyPeriodBean == null || studyPeriod == StudyPeriod.All) {
                attributes3.setNull(Tag.ScheduledProcedureStepEndDate, vr);
            } else {
                attributes3.setString(Tag.ScheduledProcedureStepEndDate, vr, studyPeriodBean.scheduledProcedureStepEndDate);
            }

            vr = ElementDictionary.vrOf(Tag.ScheduledProcedureStepEndTime, (String) null);
            if (studyPeriodBean == null || studyPeriod == StudyPeriod.All) {
                attributes3.setNull(Tag.ScheduledProcedureStepEndTime, vr);
            } else {
                attributes3.setString(Tag.ScheduledProcedureStepEndTime, vr, studyPeriodBean.scheduledProcedureStepEndTime);
            }

            vr = ElementDictionary.vrOf(Tag.ScheduledPerformingPhysicianName, (String) null);
            attributes3.setNull(Tag.ScheduledPerformingPhysicianName, vr);

            vr = ElementDictionary.vrOf(Tag.ScheduledProcedureStepDescription, (String) null);
            attributes3.setNull(Tag.ScheduledProcedureStepDescription, vr);

            sequence3.add(attributes3);

            VR vrScheduledProtocolCodeSequence = ElementDictionary.vrOf(Tag.ScheduledProtocolCodeSequence, (String) null);
            attributes3.setNull(Tag.ScheduledProtocolCodeSequence, vrScheduledProtocolCodeSequence);
        }

        return attributes;
    }





public class MyQueryTool {
    private String host;
    private int port;
    private String aeTitle;
    private Device device;
    private Connection conn;
    private String sourceAETitle;
    private List<Attributes> response = new ArrayList();
    private TestResult result;
    private String queryLevel;
    private FindSCU.InformationModel queryModel;
    private boolean relational;
    private int numMatches;
    private static String[] IVR_LE_FIRST = new String[]{"1.2.840.10008.1.2", "1.2.840.10008.1.2.1", "1.2.840.10008.1.2.2"};
    private Attributes queryatts = new Attributes();
    private int expectedMatches = -2147483648;
    private long timeFirst = 0L;

    public MyQueryTool(String host, int port, String aeTitle, String queryLevel, FindSCU.InformationModel queryModel, boolean relational, Device device, String sourceAETitle, Connection conn) {
        this.host = host;
        this.port = port;
        this.aeTitle = aeTitle;
        this.device = device;
        this.sourceAETitle = sourceAETitle;
        this.conn = conn;
        this.queryLevel = queryLevel;
        this.queryModel = queryModel;
        this.relational = relational;
    }

    public void query(String testDescription, boolean fuzzy, boolean dataTimeCombined) throws IOException, InterruptedException, IncompatibleConnectionException, GeneralSecurityException {
        this.doQuery(testDescription, fuzzy, dataTimeCombined);
    }


    private void doQuery(String testDescription, boolean fuzzy, boolean combined) throws IOException, InterruptedException, IncompatibleConnectionException, GeneralSecurityException {
        this.device.setInstalled(true);
        ApplicationEntity ae = new ApplicationEntity(this.sourceAETitle);
        this.device.addApplicationEntity(ae);
        ae.addConnection(this.conn);
        FindSCU main = new FindSCU(ae);
        main.getAAssociateRQ().setCalledAET(this.aeTitle);

        main.getRemoteConnection().setHostname(this.host);
        main.getRemoteConnection().setPort(this.port);
        main.getRemoteConnection().setTlsCipherSuites(this.conn.getTlsCipherSuites());
        main.getRemoteConnection().setTlsProtocols(this.conn.getTlsProtocols());
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
        main.getDevice().setExecutor(executorService);
        main.getDevice().setScheduledExecutor(scheduledExecutorService);
        EnumSet<QueryOption> queryOptions = EnumSet.noneOf(QueryOption.class);
        if (fuzzy) {
            queryOptions.add(QueryOption.FUZZY);
        }

        if (combined) {
            queryOptions.add(QueryOption.DATETIME);
        }

        if (this.relational) {
            queryOptions.add(QueryOption.RELATIONAL);
        }

        main.setInformationModel(this.queryModel, IVR_LE_FIRST, queryOptions);
        if (queryModel != FindSCU.InformationModel.MWL) {
            main.addLevel(this.queryLevel);
        }
        main.getKeys().addAll(this.queryatts);
        long timeStart = System.currentTimeMillis();

        try {
            main.open();

            main.query(this.getDimseRSPHandler(main.getAssociation().nextMessageID()));
        } finally {
            main.close();
            executorService.shutdown();
            scheduledExecutorService.shutdown();
        }

        long timeEnd = System.currentTimeMillis();
        this.validateMatches(testDescription);
        this.init(new QueryResult(testDescription, this.expectedMatches, this.numMatches, timeEnd - timeStart, this.timeFirst - timeStart, this.response));
    }

    private void validateMatches(String testDescription) {
        if (this.expectedMatches >= 0) {
            Log.e("MyQueryTool", "test[" + testDescription + "] not returned expected result:" + this.expectedMatches + " but:" + this.numMatches + "," + (this.numMatches == this.expectedMatches));
        }

    }

    public Attributes addQueryTag(int tag, String value) throws Exception {
        VR vr = ElementDictionary.vrOf(tag, (String) null);
        this.queryatts.setString(tag, vr, value);
        return queryatts;
    }

    public Attributes clearQueryKeys() {
        this.queryatts = new Attributes();
        return queryatts;
    }

    public Attributes addAll(Attributes attrs) {
        this.queryatts.addAll(attrs);
        return queryatts;
    }

    public Attributes addReturnTag(int tag) throws Exception {
        VR vr = ElementDictionary.vrOf(tag, (String) null);
        this.queryatts.setNull(tag, vr);
        return queryatts;
    }

    public void setExpectedMatches(int matches) {
        this.expectedMatches = matches;
    }

    private DimseRSPHandler getDimseRSPHandler(int messageID) {
        DimseRSPHandler rspHandler = new DimseRSPHandler(messageID) {
            public void onDimseRSP(Association as, Attributes cmd, Attributes data) {
                super.onDimseRSP(as, cmd, data);
                onCFindResponse(cmd, data);
            }
        };
        return rspHandler;
    }

    protected void onCFindResponse(Attributes cmd, Attributes data) {
        if (this.numMatches == 0) {
            this.timeFirst = System.currentTimeMillis();
        }

        int status = cmd.getInt(2304, -1);
        if (Status.isPending(status)) {
            this.response.add(data);
            ++this.numMatches;
        }

    }

    public void init(TestResult result) {
        this.result = result;
    }

    public TestResult getResult() {
        return this.result;
    }

    public void setAeTitle(String aeTitle) {
        this.aeTitle = aeTitle;
    }

    public String getQueryLevel() {
        return this.queryLevel;
    }
}

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
dcm4che-tool-common.jar是一个Java库文件,属于dcm4cheDICOM for Java)项目的一部分。DICOM是医疗图像和通信的国际标准,dcm4che项目旨在为Java开发者提供处理DICOM图像和通信的工具。 dcm4che-tool-common.jar文件包含了一些公共的工具和功能,用于支持DICOM图像的处理和操作。它提供了一系列的方法和类,可以用于解析和读取DICOM文件、创建和修改DICOM图像、执行DICOM操作,以及处理DICOM标签、图像像素等等。 使用dcm4che-tool-common.jar,开发者可以轻松地在Java应用程序中集成DICOM功能。通过导入该库文件,开发者可以创建一个DICOM图像解析器,将DICOM图像文件读取到Java程序中,并进行进一步的处理和分析。同时,开发者也可以使用该库文件进行DICOM图像的创建和修改,包括添加、删除和更新DICOM标签、像素数据以及其他相关信息。 除此之外,dcm4che-tool-common.jar还提供了一些实用工具,用于执行DICOM操作,比如发送和接收DICOM图像,查询和检索DICOM存储服务器中的图像,以及与其他DICOM设备的通信等等。 总之,dcm4che-tool-common.jar是dcm4che项目中的一个库文件,提供了一系列的工具和功能,用于支持Java开发者处理和操作DICOM图像和通信。它使得开发者可以更加便捷地在Java应用程序中集成DICOM功能,并实现DICOM图像的解析、创建、修改以及与其他DICOM设备的通信等等操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值