DICOM 测试工具

一个DICOM测试工具。

引用了 fo-dicom 。fo-dicom 算是比较好用的,我的另外一个项目也是用了它。

using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Dicom;
using Dicom.Log;
using Dicom.Network;
using Dicom.Serialization;
using Newtonsoft.Json;

namespace DicomUtils
{

    public delegate void CStoreRequestHandler(TDicomServer Server, TDicomService service, string studyuid, string instuid, string tag, ref string fileid, ref string filename);
    public delegate void CStoreFileSavedHandler(TDicomServer Server, TDicomService service, string studyuid, string instuid, string tag, string fileid, string filename);
    public delegate void CFindHandler(TDicomServer Server, TDicomService service, string json,ref DataTable dt);

    public class TDicomServer
    {
        public IDicomServer Server = null;
        public ServerConfig Config = null;
        public List<TLogItem> Log = new List<TLogItem>();
        public void Start()
        {
            wirtelog("Server "+ "Start");
            Server = DicomServer.Create<TDicomService>(Config.Port, userState: this);

        }
        public void Stop()
        {
            if (Server != null)
            {
                wirtelog("Server " + "Stop");
                Server.Stop();
                Server.Dispose();
                Server = null;
            }

        }
        public event CStoreRequestHandler EventCStoreRequest;

        public virtual void OnCStoreRequest(TDicomService service,string studyuid, string instuid, string tag, ref string fileid, ref string filename)
        {
            if (filename == "")
            {
                string dir =get_storge_dir();
                string fn = System.IO.Path.Combine(dir, studyuid, instuid + ".dcm");
                filename = fn;

            }
            wirtelog("OnCStoreRequest " + filename);
            if (EventCStoreRequest != null)
            {
                EventCStoreRequest(this, service, studyuid, instuid, tag, ref fileid, ref filename);
            }
        }
        public event CStoreFileSavedHandler EventCStoreFileSaved;
        public virtual void OnCStoreFileSaved(TDicomService service, string studyuid, string instuid, string tag, string fileid, string filename)
        {
            wirtelog("OnCStoreFileSaved " + filename);
            string fn_json = System.IO.Path.ChangeExtension(filename,".json");
            System.IO.File.WriteAllText(fn_json, tag);
            if (EventCStoreFileSaved != null)
            {
                EventCStoreFileSaved(this, service, studyuid, instuid, tag, fileid, filename);
            }
        }
        public event CFindHandler EventCFind;
        public virtual void OnCFindRequest(TDicomService service, DicomDataset request, string json, List<DicomDataset> list)
        {
            wirtelog("OnCFindRequest " + json);
            if (EventCFind != null)
            {
                DataTable dt = null;
                EventCFind(this, service, json,ref dt);
                if (dt != null)
                {
                    List<WorklistItem> worklists = WorklistHandler.dt2worklists(dt);
                    List<DicomDataset> data= WorklistHandler.Worklist2DataSet(request,worklists);
                    list.AddRange(data);
                }
            } 
        }
        public void wirtelog(string msg)
        {
            lock (Log)
                try
                {

                    if (Log.Count > 1000)
                    {
                        Log.RemoveRange(0,500);
                    }
                    Log.Add(TLogItem.new_item(msg));
                }
                catch
                {

                } 
        }
        public string get_storge_dir()
        {
            return Config.get_storge_dir();
        }
    }



    public class TDicomService : DicomService, IDicomServiceProvider, IDicomCStoreProvider, IDicomCFindProvider, IDicomCMoveProvider, IDicomCGetProvider, IDicomCEchoProvider
    {
        private static readonly DicomTransferSyntax[] AcceptedTransferSyntaxes = new DicomTransferSyntax[]
        {
               DicomTransferSyntax.ExplicitVRLittleEndian,
               DicomTransferSyntax.ExplicitVRBigEndian,
               DicomTransferSyntax.ImplicitVRLittleEndian
        };

        private static readonly DicomTransferSyntax[] AcceptedImageTransferSyntaxes = new DicomTransferSyntax[]
        {
               // Lossless
               DicomTransferSyntax.JPEGLSLossless,
               DicomTransferSyntax.JPEG2000Lossless,
               DicomTransferSyntax.JPEGProcess14SV1,
               DicomTransferSyntax.JPEGProcess14,
               DicomTransferSyntax.RLELossless,
               // Lossy
               DicomTransferSyntax.JPEGLSNearLossless,
               DicomTransferSyntax.JPEG2000Lossy,
               DicomTransferSyntax.JPEGProcess1,
               DicomTransferSyntax.JPEGProcess2_4,
               // Uncompressed
               DicomTransferSyntax.ExplicitVRLittleEndian,
               DicomTransferSyntax.ExplicitVRBigEndian,
               DicomTransferSyntax.ImplicitVRLittleEndian
        };

        public TDicomService(INetworkStream stream, Encoding fallbackEncoding, Logger log)
            : base(stream, fallbackEncoding, log)
        {


        }
        public TDicomServer GetSCPServer()
        {
            return (TDicomServer)UserState;
        }
        public void wirtelog(string msg)
        {
            TDicomServer Server = GetSCPServer();
            Server.wirtelog(msg);

        }
        public Task OnReceiveAssociationRequestAsync(DicomAssociation association)
        {
            wirtelog("OnReceiveAssociationRequestAsync  IP:" + association.RemoteHost + " PORT:" + association.RemotePort.ToString() + " AE:" + association.CalledAE);

            TDicomServer Server = GetSCPServer();
            if (!Server.Config.isAllowAE(association.CalledAE))
            {
                wirtelog("SendAssociationRejectAsync  IP:" + association.RemoteHost + " PORT:" + association.RemotePort.ToString() + " AE:" + association.CalledAE);

                return SendAssociationRejectAsync(
                    DicomRejectResult.Permanent,
                    DicomRejectSource.ServiceUser,
                    DicomRejectReason.CalledAENotRecognized);
            }

            foreach (var pc in association.PresentationContexts)
            {
                if (pc.AbstractSyntax == DicomUID.Verification
                  || pc.AbstractSyntax == DicomUID.PatientRootQueryRetrieveInformationModelFind
                  || pc.AbstractSyntax == DicomUID.PatientRootQueryRetrieveInformationModelMove
                  || pc.AbstractSyntax == DicomUID.StudyRootQueryRetrieveInformationModelFind
                  || pc.AbstractSyntax == DicomUID.StudyRootQueryRetrieveInformationModelMove

                  || pc.AbstractSyntax == DicomUID.ModalityWorklistInformationModelFind
                  || pc.AbstractSyntax == DicomUID.ModalityPerformedProcedureStep
                  || pc.AbstractSyntax == DicomUID.ModalityPerformedProcedureStepNotification
                  || pc.AbstractSyntax == DicomUID.ModalityPerformedProcedureStepRetrieve

                  )
                {
                    pc.AcceptTransferSyntaxes(AcceptedTransferSyntaxes);
                }

                if (pc.AbstractSyntax == DicomUID.Verification) pc.AcceptTransferSyntaxes(AcceptedTransferSyntaxes);
                else if (pc.AbstractSyntax.StorageCategory != DicomStorageCategory.None) pc.AcceptTransferSyntaxes(AcceptedImageTransferSyntaxes);
            }

            return SendAssociationAcceptAsync(association);
        }

        public Task OnReceiveAssociationReleaseRequestAsync()
        {
            wirtelog("OnReceiveAssociationReleaseRequestAsync");
            return SendAssociationReleaseResponseAsync();
        }

        public void OnReceiveAbort(DicomAbortSource source, DicomAbortReason reason)
        {
            wirtelog("OnReceiveAbort  IP:" + source.ToString() + " reason:" + reason.ToString());

        }

        public void OnConnectionClosed(Exception exception)
        {
            if (exception != null)
            {
                wirtelog("OnConnectionClosed  exception:" + exception.ToString());
            }
            else
            {
                wirtelog("OnConnectionClosed");
            }
        }
    
        public DicomCStoreResponse OnCStoreRequest(DicomCStoreRequest request)
        {
            TDicomServer Server = GetSCPServer();

            string studyUid = request.Dataset.GetSingleValue<string>(DicomTag.StudyInstanceUID);
            string instUid = request.SOPInstanceUID.UID;
            wirtelog("OnCStoreRequest  studyUid:" + studyUid + " instUid:" + instUid);
            string tag = "";
            if (request.HasDataset)
                tag=Pub.DicomDataset2json(request.Dataset); 
            string filename = "";
            string fileid = "";
            Server.OnCStoreRequest(this, studyUid, instUid, tag, ref fileid, ref filename);
            string dir = System.IO.Path.GetDirectoryName(filename);
            if (!Directory.Exists(dir))
                Directory.CreateDirectory(dir);

            request.File.Save(filename);
            Server.OnCStoreFileSaved(this, studyUid, instUid, tag, fileid, filename);

            return new DicomCStoreResponse(request, DicomStatus.Success);

        }

        public void OnCStoreRequestException(string tempFileName, Exception e)
        {
            wirtelog("OnCStoreRequest  tempFileName:" + tempFileName + " exception:" + e.Message);
        }

        public DicomCEchoResponse OnCEchoRequest(DicomCEchoRequest request)
        {
            wirtelog("OnCEchoRequest  MessageID:" + request.MessageID);
            return new DicomCEchoResponse(request, DicomStatus.Success);
        }

        public IEnumerable<DicomCFindResponse> OnCFindRequest(DicomCFindRequest request)
        {
            wirtelog("OnCFindRequest  request:" + request.Type.ToString());
            string json = "";
            if (request.HasDataset)
                json =Pub.DicomDataset2json(request.Dataset);
            TDicomServer Server = GetSCPServer();
            List<DicomCFindResponse> responses = new List<DicomCFindResponse>();
            List<DicomDataset> list = new List<DicomDataset>();
            Server.OnCFindRequest(this, request.Dataset,json, list);
            foreach (DicomDataset result in list)
            {
                responses.Add(new DicomCFindResponse(request, DicomStatus.Pending) { Dataset = result });
            }
            responses.Add(new DicomCFindResponse(request, DicomStatus.Success));
            return responses;
        }

        public IEnumerable<DicomCMoveResponse> OnCMoveRequest(DicomCMoveRequest request)
        {
            wirtelog("OnCMoveRequest  request:" + request.Type.ToString());
            throw new NotImplementedException();
        }

        public IEnumerable<DicomCGetResponse> OnCGetRequest(DicomCGetRequest request)
        {
            wirtelog("OnCGetRequest  request:" + request.Type.ToString());
            throw new NotImplementedException();
        }
    }

    public class TLogItem
    {
        public Int64 id = get_new_id();
        public DateTime time = DateTime.Now;
        public string msg = "";
        public static Int64 last_id = 0;
        public static Int64 get_new_id()
        {
            last_id = last_id + 1;
            return last_id;
        }
        public static TLogItem new_item(string msg)
        {
            TLogItem i = new TLogItem();
            i.msg = msg;
            return i;
        }
    } 
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/586009.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Go语言map

map 概念 在Go语言中&#xff0c;map 是一种内建的数据结构&#xff0c;它提供了一种关联式的存储机制&#xff0c;允许你以键值对的形式存储数据。每个键都是唯一的&#xff0c;并且与一个值相关联。你可以通过键来查找、添加、更新和删除值&#xff0c;这类似于其他编程语言…

Spring Boot的热部署工具“AND”Swagger测试工具

Spring Boot的热部署&Swagger测试页面的使用 热部署指的是在项目无需重启的情况下&#xff0c;只需要刷新页面&#xff0c;即可获得已经修改的样式或功能。要注意该工具一般用于开发环境&#xff0c;在生产环境中最好不要添加这个工具。 对于无需重启便可刷新这么方便的工…

小剧场短剧影视小程序源码_后端PHP

项目运行截图 源码贡献 https://githubs.xyz/boot?app42 部署说明 linux/win任选 PHP版本&#xff1a;7.3/7.2&#xff08;测试时我用的7.2要安装sg扩展 &#xff09; 批量替换域名http://video.owoii.com更换为你的 批量替换域名http://120.79.77.163:1更换为你的 这两个…

交通运输智慧监管平台---强化物流安全与效率的新举措

一、建设背景 随着社会对于交通安全和环境保护的要求不断提高&#xff0c;对卡车运输的监管和合规性要求也逐渐加强。为了满足快速发展的物流需求&#xff0c;提高供应链协同和可追溯性、解决安全问题、提高运输效率和降低成本&#xff0c;我们利用现代技术和信息化手段着力建设…

Spark SQL编程初级实践

参考链接 Spark编程: Spark SQL基本操作 2020.11.01_df.agg("age"->"avg")-CSDN博客 RDD编程初级实践-CSDN博客 Spark和Hadoop的安装-CSDN博客 1. Spark SQL基本操作 { "id":1 , "name":" Ella" , "age":…

数字电路-5路呼叫显示和8路抢答器

本内容涉及两个电路&#xff0c;分别为5路呼叫显示电路和8路抢答器电路&#xff0c;包含Multisim仿真原文件&#xff0c;为掌握FPGA做个铺垫。紫色文字是超链接&#xff0c;点击自动跳转至相关博文。持续更新&#xff0c;原创不易&#xff01; 目录&#xff1a; 一、5路呼叫显…

每日OJ题_DFS爆搜深搜回溯剪枝②_力扣526. 优美的排列

目录 力扣526. 优美的排列 解析代码 力扣526. 优美的排列 526. 优美的排列 难度 中等 假设有从 1 到 n 的 n 个整数。用这些整数构造一个数组 perm&#xff08;下标从 1 开始&#xff09;&#xff0c;只要满足下述条件 之一 &#xff0c;该数组就是一个 优美的排列 &#…

nginx缓存清理

背景 昨天打开我的gpt镜像网站&#xff0c;意外发现静态图片资源全都无法获取了 CoCo-AI 一番排查下来&#xff0c;发现是引用的cdn链接失效了 且cdn源是属于七牛云的&#xff0c;且不再维护&#xff0c;于是果断切换到cloudflare export function getEmojiUrl(unified: str…

JavaScript中的Object方法、Array方法、String方法

个人主页&#xff1a;学习前端的小z 个人专栏&#xff1a;JavaScript 精粹 本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结&#xff0c;欢迎大家在评论区交流讨论&#xff01; 文章目录 &#x1f525;Object方法&#x1f31e;1 Object.is()&#x1f31e;2 Object.…

区块链 | 由外部实体导致的 NFT 安全问题

&#x1f98a;原文&#xff1a; Understanding Security Issues in the NFT Ecosystem &#x1f98a;警告&#xff1a; 本文只记录了原文的第 6 节。 1 问题描述 NFT 所指向的数字资产&#xff08;图片、视频等&#xff09;必须是可以访问的&#xff0c;这样 NFT 才具有意义…

iA Writer for Mac:简洁强大的写作软件

在追求高效写作的今天&#xff0c;iA Writer for Mac凭借其简洁而强大的功能&#xff0c;成为了许多作家、记者和学生的首选工具。这款专为Mac用户打造的写作软件&#xff0c;以其独特的设计理念和实用功能&#xff0c;助你轻松打造高质量的文章。 iA Writer for Mac v7.1.2中文…

数据挖掘之基于Lightgbm等多模型消融实验的信用欺诈检测实现

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景 在当前的金融环境中&#xff0c;信用欺诈行为日益增多&#xff0c;给金融机构和消费者带来了巨大的损…

ThingsBoard PE专业版解决方案技术文档——温度湿度

1、项目总览 2、设备接入 3、设备告警 3.1 高温告警 创建一个Flag作为标杆&#xff0c;作为开启告警的开关。 3.2 低湿度告警 创建一个Flag作为标杆&#xff0c;作为开启告警的开关。 4、部件仪表 4.1 Entities table 部件预览&#xff1a; 标题样式&#xff1a; {"…

nuxt3项目服务端bulid后在本地浏览的3种方式(nuxi preview、Node.js Server、PM2)

你也许会问有了开发调试本地浏览&#xff0c;为什么还要服务端构建之后在本地浏览&#xff1f; 举个简单例子 在 Nuxt 3 服务端打包中&#xff0c;由于运行环境不同&#xff0c;无法直接访问 process 对象。服务端打包通常是在 Node.js 环境中进行的&#xff0c;而 process 对象…

Linux 手动部署JDK21 环境

1、下载包&#xff08;我下载的是tar) https://www.oracle.com/cn/java/technologies/downloads/#java21 完成后进行上传 2、检查已有JDK&#xff0c;并删除&#xff08;我原有是jdk8&#xff09; rpm -qa | grep -i java | xargs -n1 rpm -e --nodeps3、清理掉 profile中的j…

vue3 安装-使用之第一篇

首先需要node版本高于V16.14.1 安装 执行 npm create vitelatest 具体选择按照自己实际需要的来 Project name:项目名称 Select a framework:选择用哪种框架 &#xff08;我选择vue&#xff09; Select a variant: 选择用JS还是TS&#xff08;我选择JS&#xff09;找到项目&…

【云原生】Docker 实践(三):使用 Dockerfile 文件构建镜像

Docker 实践&#xff08;三&#xff09;&#xff1a;使用 Dockerfile 文件构建镜像 1.使用 Dockerfile 文件构建镜像2.Dockerfile 文件详解 1.使用 Dockerfile 文件构建镜像 Dockerfile 是一个文本文件&#xff0c;其中包含了一条条的指令&#xff0c;每一条指令都用于构建镜像…

笔记-PPT绘图导出高清无失真图片

问题描述&#xff1a;PPT绘图已经用了高清图&#xff08;jpg、tif格式&#xff09;&#xff0c;但论文图片还是不清晰&#xff0c;打印出来还是有点糊 以下是PPT导出高清不失真图片&#xff08;emf格式&#xff09;的具体描述。 目录 一、绘图工具二、操作步骤 一、绘图工具 …

Java | Leetcode Java题解之第60题排列序列

题目&#xff1a; 题解&#xff1a; class Solution {public String getPermutation(int n, int k) {int[] factorial new int[n];factorial[0] 1;for (int i 1; i < n; i) {factorial[i] factorial[i - 1] * i;}--k;StringBuffer ans new StringBuffer();int[] valid…

为什么公共事业机构会偏爱 TiDB :TiDB 数据库在某省妇幼健康管理系统的应用

本文介绍了某省妇幼健康管理系统的建设和数据库架构优化的过程。原有的数据库架构使用了 StarRocks 作为分析层&#xff0c;但随着业务的发展&#xff0c;这套架构暴露出诸多痛点&#xff0c;不再适应妇幼业务的需求。为解决这些问题&#xff0c;该系统选择了将原有架构中的 St…