195 lines
8.6 KiB
C#
195 lines
8.6 KiB
C#
using FellowOakDicom;
|
||
using FellowOakDicom.Media;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Data;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
|
||
namespace IRaCIS.Core.Application.Helper
|
||
{
|
||
|
||
public class StudyDIRInfo
|
||
{
|
||
public Guid SubjectVisitId { get; set; }
|
||
// Study
|
||
public Guid DicomStudyId { get; set; }
|
||
|
||
public string PatientId { get; set; }
|
||
public string PatientName { get; set; }
|
||
public string PatientBirthDate { get; set; }
|
||
public string PatientSex { get; set; }
|
||
|
||
public string StudyInstanceUid { get; set; }
|
||
public string StudyId { get; set; }
|
||
public string DicomStudyDate { get; set; }
|
||
public string DicomStudyTime { get; set; }
|
||
public string AccessionNumber { get; set; }
|
||
public string StudyDescription { get; set; }
|
||
|
||
// Series
|
||
public string SeriesInstanceUid { get; set; }
|
||
public string Modality { get; set; }
|
||
public string DicomSeriesDate { get; set; }
|
||
public string DicomSeriesTime { get; set; }
|
||
public int SeriesNumber { get; set; }
|
||
public string SeriesDescription { get; set; }
|
||
|
||
// Instance
|
||
public Guid InstanceId { get; set; }
|
||
public string SopInstanceUid { get; set; }
|
||
public string SOPClassUID { get; set; }
|
||
public int InstanceNumber { get; set; }
|
||
public string MediaStorageSOPClassUID { get; set; }
|
||
public string MediaStorageSOPInstanceUID { get; set; }
|
||
public string TransferSytaxUID { get; set; }
|
||
}
|
||
public static class DicomDIRHelper
|
||
{
|
||
|
||
public static async Task<Dictionary<string, string>> GenerateStudyDIRAndUploadAsync(List<StudyDIRInfo> list, string ossFolder, IOSSService _oSSService)
|
||
{
|
||
var dic = new Dictionary<string, string>();
|
||
var mappings = new List<string>();
|
||
int index = 1;
|
||
|
||
|
||
var dicomDir = new DicomDirectory();
|
||
|
||
foreach (var item in list.OrderBy(t => t.SeriesNumber).ThenBy(t => t.InstanceNumber))
|
||
{
|
||
var dicomUid = DicomUID.Enumerate().FirstOrDefault(uid => uid.UID == item.TransferSytaxUID);
|
||
|
||
if (dicomUid != null)
|
||
{
|
||
var ts = DicomTransferSyntax.Query(dicomUid);
|
||
|
||
var dataset = new DicomDataset(ts)
|
||
{
|
||
{ DicomTag.PatientID, item.PatientId ?? string.Empty },
|
||
{ DicomTag.PatientName, item.PatientName ?? string.Empty },
|
||
{ DicomTag.PatientBirthDate, item.PatientBirthDate ?? string.Empty },
|
||
{ DicomTag.PatientSex, item.PatientSex ?? string.Empty },
|
||
|
||
{ DicomTag.StudyInstanceUID, item.StudyInstanceUid ?? string.Empty },
|
||
{ DicomTag.StudyID, item.StudyId ?? string.Empty },
|
||
{ DicomTag.StudyDate, item.DicomStudyDate ?? string.Empty },
|
||
{ DicomTag.StudyTime, item.DicomStudyTime ?? string.Empty },
|
||
{ DicomTag.AccessionNumber, item.AccessionNumber ?? string.Empty },
|
||
{ DicomTag.StudyDescription, item.StudyDescription ?? string.Empty },
|
||
|
||
{ DicomTag.SeriesInstanceUID, item.SeriesInstanceUid ?? string.Empty },
|
||
{ DicomTag.Modality, item.Modality ?? string.Empty },
|
||
{ DicomTag.SeriesDate, item.DicomSeriesDate ?? string.Empty },
|
||
{ DicomTag.SeriesTime, item.DicomSeriesTime ?? string.Empty },
|
||
{ DicomTag.SeriesNumber, item.SeriesNumber.ToString() ?? string.Empty },
|
||
{ DicomTag.SeriesDescription, item.SeriesDescription ?? string.Empty },
|
||
|
||
{ DicomTag.SOPInstanceUID, item.SopInstanceUid ?? string.Empty },
|
||
{ DicomTag.SOPClassUID, item.SOPClassUID ?? string.Empty },
|
||
{ DicomTag.InstanceNumber, item.InstanceNumber.ToString() ?? string.Empty },
|
||
{ DicomTag.MediaStorageSOPClassUID, item.MediaStorageSOPClassUID ?? string.Empty },
|
||
{ DicomTag.MediaStorageSOPInstanceUID, item.MediaStorageSOPInstanceUID ?? string.Empty },
|
||
{ DicomTag.TransferSyntaxUID, item.TransferSytaxUID ?? string.Empty },
|
||
};
|
||
|
||
var dicomFile = new DicomFile(dataset);
|
||
|
||
// 文件名递增格式:IM_00001, IM_00002, ...
|
||
string filename = $@"IMAGE/IM_{index:D5}"; // :D5 表示补足5位
|
||
|
||
mappings.Add($"{filename} => {item.InstanceId}");
|
||
|
||
dic.Add(item.InstanceId.ToString(), Path.GetFileName(filename));
|
||
|
||
dicomDir.AddFile(dicomFile, filename);
|
||
|
||
index++;
|
||
}
|
||
|
||
|
||
}
|
||
|
||
//有实际的文件
|
||
if (mappings.Count > 0)
|
||
{
|
||
#region 写入临时路径
|
||
var tempFilePath = Path.GetTempFileName();
|
||
|
||
// 保存 DICOMDIR 到临时文件 不能直接写入到流种
|
||
await dicomDir.SaveAsync(tempFilePath);
|
||
|
||
using (var memoryStream = new MemoryStream(File.ReadAllBytes(tempFilePath)))
|
||
{
|
||
// 重置流位置
|
||
memoryStream.Position = 0;
|
||
|
||
await _oSSService.UploadToOSSAsync(memoryStream, ossFolder, "DICOMDIR", false);
|
||
}
|
||
|
||
//清理临时文件
|
||
File.Delete(tempFilePath);
|
||
|
||
#endregion
|
||
|
||
#region 映射上传
|
||
|
||
// 将映射写入内存流
|
||
var mappingText = string.Join(Environment.NewLine, mappings);
|
||
await using var mappingStream = new MemoryStream(Encoding.UTF8.GetBytes(mappingText));
|
||
|
||
await _oSSService.UploadToOSSAsync(mappingStream, ossFolder, $"Download_{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}", false);
|
||
|
||
#endregion
|
||
}
|
||
|
||
|
||
|
||
return dic;
|
||
}
|
||
|
||
|
||
|
||
public static StudyDIRInfo ReadDicomDIRInfo(DicomFile dicomFile)
|
||
{
|
||
var dataset = dicomFile.Dataset;
|
||
|
||
|
||
var info = new StudyDIRInfo
|
||
{
|
||
PatientId = dataset.GetSingleValueOrDefault(DicomTag.PatientID, string.Empty),
|
||
PatientName = dataset.GetSingleValueOrDefault(DicomTag.PatientName, string.Empty),
|
||
PatientBirthDate = dataset.GetSingleValueOrDefault(DicomTag.PatientBirthDate, string.Empty),
|
||
PatientSex = dataset.GetSingleValueOrDefault(DicomTag.PatientSex, string.Empty),
|
||
|
||
StudyInstanceUid = dataset.GetSingleValueOrDefault(DicomTag.StudyInstanceUID, string.Empty),
|
||
StudyId = dataset.GetSingleValueOrDefault(DicomTag.StudyID, string.Empty),
|
||
DicomStudyDate = dataset.GetSingleValueOrDefault(DicomTag.StudyDate, string.Empty),
|
||
DicomStudyTime = dataset.GetSingleValueOrDefault(DicomTag.StudyTime, string.Empty),
|
||
AccessionNumber = dataset.GetSingleValueOrDefault(DicomTag.AccessionNumber, string.Empty),
|
||
StudyDescription = dataset.GetSingleValueOrDefault(DicomTag.StudyDescription, string.Empty),
|
||
|
||
SeriesInstanceUid = dataset.GetSingleValueOrDefault(DicomTag.SeriesInstanceUID, string.Empty),
|
||
Modality = dataset.GetSingleValueOrDefault(DicomTag.Modality, string.Empty),
|
||
DicomSeriesDate = dataset.GetSingleValueOrDefault(DicomTag.SeriesDate, string.Empty),
|
||
DicomSeriesTime = dataset.GetSingleValueOrDefault(DicomTag.SeriesTime, string.Empty),
|
||
SeriesNumber = dataset.GetSingleValueOrDefault(DicomTag.SeriesNumber, 1),
|
||
SeriesDescription = dataset.GetSingleValueOrDefault(DicomTag.SeriesDescription, string.Empty),
|
||
|
||
SopInstanceUid = dataset.GetSingleValueOrDefault(DicomTag.SOPInstanceUID, string.Empty),
|
||
SOPClassUID = dataset.GetSingleValueOrDefault(DicomTag.SOPClassUID, string.Empty),
|
||
InstanceNumber = dataset.GetSingleValueOrDefault(DicomTag.InstanceNumber, 1),
|
||
|
||
MediaStorageSOPClassUID = dicomFile.FileMetaInfo.GetSingleValueOrDefault(DicomTag.MediaStorageSOPClassUID, string.Empty),
|
||
MediaStorageSOPInstanceUID = dicomFile.FileMetaInfo.GetSingleValueOrDefault(DicomTag.MediaStorageSOPInstanceUID, string.Empty),
|
||
|
||
TransferSytaxUID = dicomFile.FileMetaInfo.GetSingleValueOrDefault(DicomTag.TransferSyntaxUID, string.Empty)
|
||
};
|
||
|
||
return info;
|
||
}
|
||
}
|
||
}
|