From 6389919cfdde6f10f706c147ca68855dee397c58 Mon Sep 17 00:00:00 2001
From: hang <872297557@qq.com>
Date: Tue, 19 Mar 2024 08:58:45 +0800
Subject: [PATCH 1/2] =?UTF-8?q?=E5=BD=92=E6=A1=A3=E9=A2=84=E5=A4=84?=
=?UTF-8?q?=E7=90=861?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../IRaCIS.Core.Application.xml | 20 +-
.../Service/ImageAndDoc/CStoreSCPService.cs | 35 ++++
.../ImageAndDoc/DicomArchiveService.cs | 197 ++++++++++++++++++
.../Interface/IDicomArchiveService.cs | 6 +-
4 files changed, 255 insertions(+), 3 deletions(-)
diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml
index fd58e4f9d..942adfe18 100644
--- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml
+++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml
@@ -847,6 +847,11 @@
+
+
+ 后台托管服务的方式运行
+
+
指定资源Id,渲染Dicom检查的Jpeg预览图像
Dicom检查的Id
@@ -1836,7 +1841,7 @@
- 计算靶病灶状态
+ 计算分裂靶病灶状态
@@ -5071,6 +5076,11 @@
任务Id
+
+
+ 问题类型
+
+
任务Id
@@ -11500,6 +11510,14 @@
Financial---项目收入价格验证
+
+
+ 单个文件接收 归档
+
+
+
+
+
指定资源Id,获取Dicom序列所属的实例信息列表
Dicom序列的Id
diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/CStoreSCPService.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/CStoreSCPService.cs
index 53ea5547e..29933a52d 100644
--- a/IRaCIS.Core.Application/Service/ImageAndDoc/CStoreSCPService.cs
+++ b/IRaCIS.Core.Application/Service/ImageAndDoc/CStoreSCPService.cs
@@ -8,9 +8,44 @@ using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using IRaCIS.Core.Application.Contracts.Dicom;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
namespace IRaCIS.Core.Application.Service.ImageAndDoc
{
+ ///
+ /// 后台托管服务的方式运行
+ ///
+ public class CStoreSCPHostedService : IHostedService
+ {
+ private readonly ILogger _logger;
+ private readonly IDicomServerFactory _dicomServerFactory;
+ private IDicomServer? _server;
+
+ public CStoreSCPHostedService(ILogger logger, IDicomServerFactory dicomServerFactory)
+ {
+ _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+ _dicomServerFactory = dicomServerFactory ?? throw new ArgumentNullException(nameof(dicomServerFactory));
+ }
+
+ public async Task StartAsync(CancellationToken cancellationToken)
+ {
+ _logger.LogInformation("Starting DICOM server");
+ _server = _dicomServerFactory.Create(104);
+ _logger.LogInformation("DICOM server is running");
+ }
+
+ public Task StopAsync(CancellationToken cancellationToken)
+ {
+ if (_server != null)
+ {
+ _server.Stop();
+ _server.Dispose();
+ _server = null;
+ }
+ return Task.CompletedTask;
+ }
+ }
+
public class CStoreSCPService : DicomService, IDicomServiceProvider, IDicomCStoreProvider, IDicomCEchoProvider
{
diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/DicomArchiveService.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/DicomArchiveService.cs
index 69929b1da..31991c2cd 100644
--- a/IRaCIS.Core.Application/Service/ImageAndDoc/DicomArchiveService.cs
+++ b/IRaCIS.Core.Application/Service/ImageAndDoc/DicomArchiveService.cs
@@ -9,6 +9,9 @@ using IRaCIS.Core.Infrastructure;
using Medallion.Threading;
using FellowOakDicom;
using FellowOakDicom.Imaging.Codec;
+using System.Data;
+using IRaCIS.Core.Domain.Models;
+using FellowOakDicom.Network;
namespace IRaCIS.Core.Application.Services
{
@@ -474,11 +477,205 @@ namespace IRaCIS.Core.Application.Services
}
+ ///
+ /// 单个文件接收 归档
+ ///
+ ///
+ ///
+ ///
+ public async Task ArchiveDicomFileAsync(DicomDataset dataset)
+ {
+ string studyInstanceUid = dataset.GetString(DicomTag.StudyInstanceUID);
+ string seriesInstanceUid = dataset.GetString(DicomTag.SeriesInstanceUID);
+ string sopInstanceUid = dataset.GetString(DicomTag.SOPInstanceUID);
+
+ Guid studyId = IdentifierHelper.CreateGuid(studyInstanceUid);
+ Guid seriesId = IdentifierHelper.CreateGuid(studyInstanceUid, seriesInstanceUid);
+ Guid instanceId = IdentifierHelper.CreateGuid(studyInstanceUid, seriesInstanceUid, sopInstanceUid);
+
+ var isStudyNeedAdd = false;
+ var isSeriesNeedAdd = false;
+ var isInstanceNeedAdd = false;
+
+ var @lock = _distributedLockProvider.CreateLock($"StudyInstanceUid");
+
+ using (@lock.Acquire())
+ {
+ var findStudy = await _studyRepository.FirstOrDefaultAsync(t => t.Id == studyId);
+ var findSerice = await _seriesRepository.FirstOrDefaultAsync(t => t.Id == seriesId);
+ var findInstance = await _instanceRepository.FirstOrDefaultAsync(t => t.Id == instanceId);
+
+
+ if (findStudy == null)
+ {
+ isStudyNeedAdd = true;
+ findStudy = new DicomStudy
+ {
+ Id = studyId,
+ StudyInstanceUid = studyInstanceUid,
+ StudyTime = dataset.GetSingleValueOrDefault(DicomTag.StudyDate, string.Empty) == string.Empty ? null : dataset.GetSingleValue(DicomTag.StudyDate).Add(dataset.GetSingleValueOrDefault(DicomTag.StudyTime, string.Empty) == string.Empty ? TimeSpan.Zero : dataset.GetSingleValue(DicomTag.StudyTime).TimeOfDay),
+ //Modalities = modality,
+ //ModalityForEdit = modalityForEdit,
+ Description = dataset.GetSingleValueOrDefault(DicomTag.StudyDescription, string.Empty),
+ InstitutionName = dataset.GetSingleValueOrDefault(DicomTag.InstitutionName, string.Empty),
+ PatientId = dataset.GetSingleValueOrDefault(DicomTag.PatientID, string.Empty),
+ PatientName = dataset.GetSingleValueOrDefault(DicomTag.PatientName, string.Empty),
+ PatientAge = dataset.GetSingleValueOrDefault(DicomTag.PatientAge, string.Empty),
+ PatientSex = dataset.GetSingleValueOrDefault(DicomTag.PatientSex, string.Empty),
+ BodyPartExamined = dataset.GetSingleValueOrDefault(DicomTag.BodyPartExamined, string.Empty),
+
+ StudyId = dataset.GetSingleValueOrDefault(DicomTag.StudyID, string.Empty),
+ AccessionNumber = dataset.GetSingleValueOrDefault(DicomTag.AccessionNumber, string.Empty),
+
+ //需要特殊处理
+ PatientBirthDate = dataset.GetSingleValueOrDefault(DicomTag.PatientBirthDate, string.Empty),
+
+
+ AcquisitionTime = dataset.GetSingleValueOrDefault(DicomTag.AcquisitionTime, string.Empty),
+ AcquisitionNumber = dataset.GetSingleValueOrDefault(DicomTag.AcquisitionNumber, string.Empty),
+ TriggerTime = dataset.GetSingleValueOrDefault(DicomTag.TriggerTime, string.Empty),
+
+
+ SiteId = Guid.Empty,
+ TrialId = Guid.Empty,
+ SubjectId = Guid.Empty,
+ SubjectVisitId = Guid.Empty,
+ //IsDoubleReview = addtionalInfo.IsDoubleReview,
+ SeriesCount = 0,
+ InstanceCount = 0
+ };
+
+ //特殊逻辑
+
+ var modality = dataset.GetSingleValueOrDefault(DicomTag.Modality, string.Empty);
+
+ var dicModalityList = _dictionaryRepository.Where(t => t.Code == "Modality").SelectMany(t => t.ChildList.Select(c => c.Value)).ToList();
+
+ var modalityForEdit = dicModalityList.Contains(modality) ? modality : String.Empty;
+
+ if (modality == "MR")
+ {
+ modalityForEdit = "MRI";
+ }
+
+ if (modality == "PT")
+ {
+ modalityForEdit = "PET";
+ }
+ if (modality == "PT、CT")
+ {
+ modalityForEdit = "PET-CT";
+ }
+
+ findStudy.Modalities = modality;
+ findStudy.ModalityForEdit= modalityForEdit;
+
+ if (findStudy.PatientBirthDate.Length == 8)
+ {
+ findStudy.PatientBirthDate = $"{findStudy.PatientBirthDate[0]}{findStudy.PatientBirthDate[1]}{findStudy.PatientBirthDate[2]}{findStudy.PatientBirthDate[3]}-{findStudy.PatientBirthDate[4]}{findStudy.PatientBirthDate[5]}-{findStudy.PatientBirthDate[6]}{findStudy.PatientBirthDate[7]}";
+ }
+ }
+
+
+ if (findSerice == null)
+ {
+ isSeriesNeedAdd = true;
+
+ findSerice = new DicomSeries
+ {
+ Id = seriesId,
+ StudyId = findStudy.Id,
+
+ StudyInstanceUid = findStudy.StudyInstanceUid,
+ SeriesInstanceUid = seriesInstanceUid,
+ SeriesNumber = dataset.GetSingleValueOrDefault(DicomTag.SeriesNumber, 1),
+ //SeriesTime = dataset.GetSingleValueOrDefault(DicomTag.SeriesDate, DateTime.Now).Add(dataset.GetSingleValueOrDefault(DicomTag.SeriesTime, DateTime.Now).TimeOfDay),
+ //SeriesTime = DateTime.TryParse(dataset.GetSingleValue(DicomTag.SeriesDate) + dataset.GetSingleValue(DicomTag.SeriesTime), out DateTime dt) ? dt : null,
+ SeriesTime = dataset.GetSingleValueOrDefault(DicomTag.SeriesDate, string.Empty) == string.Empty ? null : dataset.GetSingleValue(DicomTag.SeriesDate).Add(dataset.GetSingleValueOrDefault(DicomTag.SeriesTime, string.Empty) == string.Empty ? TimeSpan.Zero : dataset.GetSingleValue(DicomTag.SeriesTime).TimeOfDay),
+ Modality = dataset.GetSingleValueOrDefault(DicomTag.Modality, string.Empty),
+ Description = dataset.GetSingleValueOrDefault(DicomTag.SeriesDescription, string.Empty),
+ SliceThickness = dataset.GetSingleValueOrDefault(DicomTag.SliceThickness, string.Empty),
+
+ ImagePositionPatient = dataset.GetSingleValueOrDefault(DicomTag.ImagePositionPatient, string.Empty),
+ ImageOrientationPatient = dataset.GetSingleValueOrDefault(DicomTag.ImageOrientationPatient, string.Empty),
+ BodyPartExamined = dataset.GetSingleValueOrDefault(DicomTag.BodyPartExamined, string.Empty),
+ SequenceName = dataset.GetSingleValueOrDefault(DicomTag.SequenceName, string.Empty),
+ ProtocolName = dataset.GetSingleValueOrDefault(DicomTag.ProtocolName, string.Empty),
+ ImagerPixelSpacing = dataset.GetSingleValueOrDefault(DicomTag.ImagerPixelSpacing, string.Empty),
+
+ AcquisitionTime = dataset.GetSingleValueOrDefault(DicomTag.AcquisitionTime, string.Empty),
+ AcquisitionNumber = dataset.GetSingleValueOrDefault(DicomTag.AcquisitionNumber, string.Empty),
+ TriggerTime = dataset.GetSingleValueOrDefault(DicomTag.TriggerTime, string.Empty),
+
+ SiteId = Guid.Empty,
+ TrialId = Guid.Empty,
+ SubjectId = Guid.Empty,
+ SubjectVisitId = Guid.Empty,
+
+ InstanceCount = 0
+ };
+
+ ++findStudy.SeriesCount;
+ }
+
+
+ if (findInstance == null)
+ {
+ isInstanceNeedAdd = true;
+ findInstance = new DicomInstance
+ {
+ Id = instanceId,
+ StudyId = findStudy.Id,
+ SeriesId = findSerice.Id,
+ StudyInstanceUid = findStudy.StudyInstanceUid,
+ SeriesInstanceUid = findSerice.SeriesInstanceUid,
+
+ SiteId = Guid.Empty,
+ TrialId = Guid.Empty,
+ SubjectId = Guid.Empty,
+ SubjectVisitId = Guid.Empty,
+ SopInstanceUid = sopInstanceUid,
+ InstanceNumber = dataset.GetSingleValueOrDefault(DicomTag.InstanceNumber, 1),
+ InstanceTime = dataset.GetSingleValueOrDefault(DicomTag.ContentDate, string.Empty) == string.Empty ? null : dataset.GetSingleValue(DicomTag.ContentDate).Add(dataset.GetSingleValueOrDefault(DicomTag.ContentTime, string.Empty) == string.Empty ? TimeSpan.Zero : dataset.GetSingleValue(DicomTag.ContentTime).TimeOfDay),
+ //InstanceTime = DateTime.TryParse(dataset.GetSingleValue(DicomTag.ContentDate) + dataset.GetSingleValue(DicomTag.ContentTime), out DateTime dt) ? dt : null,
+ //InstanceTime = dataset.GetSingleValueOrDefault(DicomTag.ContentDate,(DateTime?)null)?.Add(dataset.GetSingleValueOrDefault(DicomTag.ContentTime, TimeSpan.Zero)),
+ //dataset.GetSingleValueOrDefault(DicomTag.ContentDate,DateTime.Now);//, DicomTag.ContentTime)
+ CPIStatus = false,
+ ImageRows = dataset.GetSingleValueOrDefault(DicomTag.Rows, 0),
+ ImageColumns = dataset.GetSingleValueOrDefault(DicomTag.Columns, 0),
+ SliceLocation = dataset.GetSingleValueOrDefault(DicomTag.SliceLocation, 0),
+ SliceThickness = dataset.GetSingleValueOrDefault(DicomTag.SliceThickness, string.Empty),
+ NumberOfFrames = dataset.GetSingleValueOrDefault(DicomTag.NumberOfFrames, 0),
+ PixelSpacing = dataset.GetSingleValueOrDefault(DicomTag.PixelSpacing, string.Empty),
+ ImagerPixelSpacing = dataset.GetSingleValueOrDefault(DicomTag.ImagerPixelSpacing, string.Empty),
+ FrameOfReferenceUID = dataset.GetSingleValueOrDefault(DicomTag.FrameOfReferenceUID, string.Empty),
+ WindowCenter = dataset.GetSingleValueOrDefault(DicomTag.WindowCenter, string.Empty),
+ WindowWidth = dataset.GetSingleValueOrDefault(DicomTag.WindowWidth, string.Empty),
+ };
+ ++findStudy.InstanceCount;
+ ++findSerice.InstanceCount;
+ }
+ if (isStudyNeedAdd)
+ {
+ await _studyRepository.AddAsync(findStudy);
+ }
+ if(isSeriesNeedAdd)
+ {
+ await _seriesRepository.AddAsync(findSerice);
+ }
+ if(isInstanceNeedAdd)
+ {
+ await _instanceRepository.AddAsync(findInstance);
+ }
+ await _studyRepository.SaveChangesAsync();
+ }
+
+ }
}
}
diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/Interface/IDicomArchiveService.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/Interface/IDicomArchiveService.cs
index f78222dfc..92332cb06 100644
--- a/IRaCIS.Core.Application/Service/ImageAndDoc/Interface/IDicomArchiveService.cs
+++ b/IRaCIS.Core.Application/Service/ImageAndDoc/Interface/IDicomArchiveService.cs
@@ -1,4 +1,6 @@
-namespace IRaCIS.Core.Application.Contracts.Dicom
+using FellowOakDicom;
+
+namespace IRaCIS.Core.Application.Contracts.Dicom
{
public interface IDicomArchiveService
{
@@ -18,7 +20,7 @@
////[EasyCachingAble(Expiration = 6000)]
//string GetSeriesPreview(Guid seriesId);
-
+ Task ArchiveDicomFileAsync(DicomDataset dicomDataset);
}
}
From e22941d947657c109986bda6b16b7d62c6c221dd Mon Sep 17 00:00:00 2001
From: hang <872297557@qq.com>
Date: Tue, 19 Mar 2024 09:13:15 +0800
Subject: [PATCH 2/2] =?UTF-8?q?=E6=B3=A8=E9=87=8A=E6=9C=8D=E5=8A=A1?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../IRaCIS.Core.Application.xml | 2 +-
.../Service/ImageAndDoc/CStoreSCPService.cs | 54 +++++++++----------
2 files changed, 28 insertions(+), 28 deletions(-)
diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml
index 942adfe18..f23af1399 100644
--- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml
+++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml
@@ -847,7 +847,7 @@
-
+
后台托管服务的方式运行
diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/CStoreSCPService.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/CStoreSCPService.cs
index 29933a52d..79536d0b1 100644
--- a/IRaCIS.Core.Application/Service/ImageAndDoc/CStoreSCPService.cs
+++ b/IRaCIS.Core.Application/Service/ImageAndDoc/CStoreSCPService.cs
@@ -15,36 +15,36 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
///
/// 后台托管服务的方式运行
///
- public class CStoreSCPHostedService : IHostedService
- {
- private readonly ILogger _logger;
- private readonly IDicomServerFactory _dicomServerFactory;
- private IDicomServer? _server;
+ //public class CStoreSCPHostedService : IHostedService
+ //{
+ // private readonly ILogger _logger;
+ // private readonly IDicomServerFactory _dicomServerFactory;
+ // private IDicomServer? _server;
- public CStoreSCPHostedService(ILogger logger, IDicomServerFactory dicomServerFactory)
- {
- _logger = logger ?? throw new ArgumentNullException(nameof(logger));
- _dicomServerFactory = dicomServerFactory ?? throw new ArgumentNullException(nameof(dicomServerFactory));
- }
+ // public CStoreSCPHostedService(ILogger logger, IDicomServerFactory dicomServerFactory)
+ // {
+ // _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+ // _dicomServerFactory = dicomServerFactory ?? throw new ArgumentNullException(nameof(dicomServerFactory));
+ // }
- public async Task StartAsync(CancellationToken cancellationToken)
- {
- _logger.LogInformation("Starting DICOM server");
- _server = _dicomServerFactory.Create(104);
- _logger.LogInformation("DICOM server is running");
- }
+ // public async Task StartAsync(CancellationToken cancellationToken)
+ // {
+ // _logger.LogInformation("Starting DICOM server");
+ // _server = _dicomServerFactory.Create(104);
+ // _logger.LogInformation("DICOM server is running");
+ // }
- public Task StopAsync(CancellationToken cancellationToken)
- {
- if (_server != null)
- {
- _server.Stop();
- _server.Dispose();
- _server = null;
- }
- return Task.CompletedTask;
- }
- }
+ // public Task StopAsync(CancellationToken cancellationToken)
+ // {
+ // if (_server != null)
+ // {
+ // _server.Stop();
+ // _server.Dispose();
+ // _server = null;
+ // }
+ // return Task.CompletedTask;
+ // }
+ //}
public class CStoreSCPService : DicomService, IDicomServiceProvider, IDicomCStoreProvider, IDicomCEchoProvider