using IRaCIS.Core.Domain.Share; using System.Text; using Microsoft.AspNetCore.Hosting; using IRaCIS.Core.Infrastructure; using Medallion.Threading; using FellowOakDicom; using FellowOakDicom.Imaging.Codec; using System.Data; using IRaCIS.Core.Domain.Models; using FellowOakDicom.Network; using IRaCIS.Core.SCP.Service; using IRaCIS.Core.Infra.EFCore; using MassTransit; using System.Runtime.Intrinsics.X86; using Serilog.Sinks.File; namespace IRaCIS.Core.SCP.Service { public class DicomArchiveService : BaseService, IDicomArchiveService { private readonly IRepository _patientRepository; private readonly IRepository _studyRepository; private readonly IRepository _seriesRepository; private readonly IRepository _instanceRepository; private readonly IRepository _dictionaryRepository; private readonly IDistributedLockProvider _distributedLockProvider; private List _instanceIdList = new List(); public DicomArchiveService(IRepository patientRepository, IRepository studyRepository, IRepository seriesRepository, IRepository instanceRepository, IRepository dictionaryRepository, IDistributedLockProvider distributedLockProvider) { _distributedLockProvider = distributedLockProvider; _studyRepository = studyRepository; _patientRepository = patientRepository; _seriesRepository = seriesRepository; _instanceRepository = instanceRepository; _dictionaryRepository = dictionaryRepository; } /// /// 单个文件接收 归档 /// /// /// /// public async Task ArchiveDicomFileAsync(DicomDataset dataset, Guid trialId, Guid trialSiteId, string fileRelativePath, string callingAE, string calledAE,long fileSize) { string studyInstanceUid = dataset.GetString(DicomTag.StudyInstanceUID); string seriesInstanceUid = dataset.GetString(DicomTag.SeriesInstanceUID); string sopInstanceUid = dataset.GetString(DicomTag.SOPInstanceUID); string patientIdStr = dataset.GetSingleValueOrDefault(DicomTag.PatientID,string.Empty); //Guid patientId= IdentifierHelper.CreateGuid(patientIdStr); Guid studyId = IdentifierHelper.CreateGuid(studyInstanceUid,trialId.ToString()); Guid seriesId = IdentifierHelper.CreateGuid(studyInstanceUid, seriesInstanceUid, trialId.ToString()); Guid instanceId = IdentifierHelper.CreateGuid(studyInstanceUid, seriesInstanceUid, sopInstanceUid, trialId.ToString()); var isStudyNeedAdd = false; var isSeriesNeedAdd = false; var isInstanceNeedAdd = false; var isPatientNeedAdd = false; //var @lock = _distributedLockProvider.CreateLock($"{studyInstanceUid}"); //using (@lock.Acquire()) { var findPatient = await _patientRepository.FirstOrDefaultAsync(t => t.PatientIdStr == patientIdStr && t.TrialSiteId==trialSiteId ); 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); DateTime? 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); //先传输了修改了患者编号的,又传输了没有修改患者编号的,导致后传输的没有修改患者编号的下面的检查为0 if (findPatient == null && findStudy==null) { isPatientNeedAdd = true; findPatient = new SCPPatient() { Id = NewId.NextSequentialGuid(), TrialId=trialId, TrialSiteId=trialSiteId, PatientIdStr = 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), PatientBirthDate = dataset.GetSingleValueOrDefault(DicomTag.PatientBirthDate, string.Empty), EarliestStudyTime = studyTime, LatestStudyTime = studyTime, LatestPushTime = DateTime.Now, }; if (findPatient.PatientBirthDate.Length == 8) { var birthDateStr = $"{findPatient.PatientBirthDate[0]}{findPatient.PatientBirthDate[1]}{findPatient.PatientBirthDate[2]}{findPatient.PatientBirthDate[3]}-{findPatient.PatientBirthDate[4]}{findPatient.PatientBirthDate[5]}-{findPatient.PatientBirthDate[6]}{findPatient.PatientBirthDate[7]}"; var yearStr = $"{findPatient.PatientBirthDate[0]}{findPatient.PatientBirthDate[1]}{findPatient.PatientBirthDate[2]}{findPatient.PatientBirthDate[3]}"; int year = 0; var canParse = int.TryParse(yearStr, out year); if (canParse && year > 1900) { findPatient.PatientBirthDate = birthDateStr; DateTime birthDate; if (findPatient.PatientAge == string.Empty && studyTime.HasValue && DateTime.TryParse(findPatient.PatientBirthDate,out birthDate)) { var patientAge = studyTime.Value.Year - birthDate.Year; // 如果生日还未到,年龄减去一岁 if (studyTime.Value < birthDate.AddYears(patientAge)) { patientAge--; } findPatient.PatientAge = patientAge.ToString(); } } else { findPatient.PatientBirthDate = string.Empty; } } } else { if (studyTime < findPatient.EarliestStudyTime) { findPatient.EarliestStudyTime = studyTime; } if (studyTime > findPatient.LatestStudyTime) { findPatient.LatestStudyTime = studyTime; } findPatient.LatestPushTime = DateTime.Now; } if (findStudy == null) { isStudyNeedAdd = true; findStudy = new SCPStudy { CalledAE = calledAE, CallingAE = callingAE, PatientId = findPatient.Id, Id = studyId, TrialId = trialId, TrialSiteId = trialSiteId, StudyInstanceUid = studyInstanceUid, StudyTime = studyTime, Modalities = dataset.GetSingleValueOrDefault(DicomTag.Modality, string.Empty), //ModalityForEdit = modalityForEdit, Description = dataset.GetSingleValueOrDefault(DicomTag.StudyDescription, string.Empty), InstitutionName = dataset.GetSingleValueOrDefault(DicomTag.InstitutionName, string.Empty), PatientIdStr = 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), //IsDoubleReview = addtionalInfo.IsDoubleReview, SeriesCount = 0, InstanceCount = 0 }; 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 SCPSeries { 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), InstanceCount = 0 }; ++findStudy.SeriesCount; } if (findInstance == null) { isInstanceNeedAdd = true; findInstance = new SCPInstance { Id = instanceId, StudyId = findStudy.Id, SeriesId = findSerice.Id, StudyInstanceUid = findStudy.StudyInstanceUid, SeriesInstanceUid = findSerice.SeriesInstanceUid, 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), Path = fileRelativePath, FileSize= fileSize, }; ++findStudy.InstanceCount; ++findSerice.InstanceCount; } if (isPatientNeedAdd) { var ss = await _patientRepository.AddAsync(findPatient); } if (isStudyNeedAdd) { var dd = await _studyRepository.AddAsync(findStudy); } else { await _studyRepository.BatchUpdateNoTrackingAsync(t => t.Id == findStudy.Id, t => new SCPStudy() { IsUploadFinished = false }); } if (isSeriesNeedAdd) { await _seriesRepository.AddAsync(findSerice); } if (isInstanceNeedAdd) { await _instanceRepository.AddAsync(findInstance); } else { await _instanceRepository.BatchUpdateNoTrackingAsync(t => t.Id == instanceId, u => new SCPInstance() { Path = fileRelativePath,FileSize=fileSize }); } await _studyRepository.SaveChangesAsync(); return findStudy.Id; } } // 从DICOM文件中获取使用的字符集 private string GetEncodingVaulueFromDicomFile(DicomDataset dataset, DicomTag dicomTag) { // 获取DICOM文件的特定元素,通常用于指示使用的字符集 var charset = dataset.GetSingleValueOrDefault(DicomTag.SpecificCharacterSet, string.Empty); var dicomEncoding = DicomEncoding.GetEncoding(charset); var dicomStringElement = dataset.GetDicomItem(dicomTag); var bytes = dicomStringElement.Buffer.Data; return dicomEncoding.GetString(bytes); //// 从DICOM文件中获取使用的字符集 //string filePath = "C:\\Users\\hang\\Documents\\WeChat Files\\wxid_r2imdzb7j3q922\\FileStorage\\File\\2024-05\\1.2.840.113619.2.80.169103990.5390.1271401378.4.dcm"; //DicomFile dicomFile = DicomFile.Open(filePath); //// 获取DICOM文件的特定元素,通常用于指示使用的字符集 //var charset = dicomFile.Dataset.GetSingleValueOrDefault(DicomTag.SpecificCharacterSet, string.Empty); //var dicomEncoding = DicomEncoding.GetEncoding(charset); //var value = dicomFile.Dataset.GetSingleValueOrDefault(DicomTag.PatientName, string.Empty); //var dicomStringElement = dicomFile.Dataset.GetDicomItem(DicomTag.PatientName); //var bytes = dicomStringElement.Buffer.Data; //var aa= dicomEncoding.GetString(bytes); } } }