PyDicom - поколение оверлеев GSPS

Я пытаюсь сгенерировать файл DICOM, содержащий данные оверлея GSPS, с помощью PyDicom. Наложение - это, по сути, двоичная маска, возвращаемая алгоритмом. Предполагается, что любое приложение для просмотра сможет отображать оверлей (если поддерживается). Файл DICOM создан, но есть некоторые проблемы.

  1. Когда я запускаю проверку файла с помощью dciodvfy.exe, я получаю ошибки для тегов данных Overlay, содержащихся в тегах (60xx, xxxx).
  2. Когда я пытаюсь вставить сгенерированный файл DICOM в мою систему PACS, я получаю ошибку a900: набор данных не соответствует классу SOP (ошибка). Это происходит, если Rows = Cols >= 200 для данных наложения. Когда Rows = Cols = 100, он импортируется правильно.

Хотя в прошлом я использовал различные библиотеки для чтения файлов DICOM, это моя первая попытка создания файла DICOM. Мне нужна помощь, чтобы выявить любые проблемы в самом коде и некоторые советы о том, как решить проблему с импортом.

Ниже мой код PyDicom:

def AddOverLayTagToDataset(dsIn, tagP1In, tagP2In, valIn) :
    theTag = Tag(tagP1In, tagP2In);
    valList = list(get_entry(theTag));
    dsIn.add_new(theTag, valList[0], valIn);

# write meta data to GSPS file
gspsMeta = Dataset();
gspsMeta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.11.1'; # SOP UID for GSPS is 1.2.840.10008.5.1.4.1.1.11.1
gspsMeta.MediaStorageSOPInstanceUID = inputDcmImg.SOPInstanceUID + '.' + str(randomGen.randint(1, 65535));
gspsMeta.ImplementationClassUID = '1.2.840.113619.6.94'; # value copied from header of GSPS file generated by UV

ds = FileDataset(gspsOutFileName, {}, file_meta=gspsMeta, preamble=b"\0" * 128);

ds.PatientName = inputDcmImg.PatientName;
ds.PatientID = inputDcmImg.PatientID;

# Set creation date/time
dt = datetime.datetime.now();
ds.ContentDate = dt.strftime('%Y%m%d');
timeStr = dt.strftime('%H%M%S.%f');  # long format with micro seconds
ds.ContentTime = timeStr;
ds.SOPClassUID = '1.2.840.10008.5.1.4.1.1.11.1';
ds.SOPInstanceUID = inputDcmImg.SOPInstanceUID + '.' + str(randomGen.randint(1, 65535));
ds.StudyInstanceUID = inputDcmImg.StudyInstanceUID;
ds.SeriesInstanceUID = inputDcmImg.SeriesInstanceUID + '.' + str(randomGen.randint(1, 65535));
ds.PatientName = inputDcmImg.PatientName;
ds.PatientID = inputDcmImg.PatientID;
ds.PatientBirthDate = inputDcmImg.PatientBirthDate;
ds.PatientSex = inputDcmImg.PatientSex;
ds.StudyID = inputDcmImg.StudyID;
#ds.SeriesNumber = inputDcmImg.SeriesNumber;
ds.StudyDate = inputDcmImg.StudyDate;
ds.StudyTime = inputDcmImg.StudyTime;
ds.InstanceNumber = 1;
ds.ContentLabel = "My Content Label";

# GSPS stuff
ds.ShutterShape = "BITMAP";
ds.ShutterOverlayGroup = 0x601e;

# set modality to presentation state as it is GSPS
ds.Modality = "PR"; #inputDcmImg.Modality;

ds.PresentationCreationDate = ds.ContentDate;
ds.PresentationCreationTime = ds.ContentTime;
ds.ShutterPresentationValue = 0xFFFF;

# Overlay stuff for GSPS
numOverLayRows = numOverlayCols = 200;

# add Graphic Layer Sequence
theGraphicLayer = Dataset();
theId = "The ROI ID";
theGraphicLayer.GraphicLayer = theId;
theGraphicLayer.GraphicLayerOrder = 1;
theGraphicLayer.GraphicLayerRecommendedDisplayGrayscaleValue = 0x0000;
theGraphicLayer.GraphicLayerRecommendedDisplayRGBValue = [0x0000, 0x0000, 0xFFFF];

ds.GraphicLayerSequence = Sequence([theGraphicLayer]);

AddOverLayTagToDataset(ds, 0x601e, 0x0010, numOverLayRows); #OverlayRows
AddOverLayTagToDataset(ds, 0x601e, 0x0011, numOverlayCols); #OverlayColumns
#AddOverLayTagToDataset(ds, 0x601e, 0x0015, 1); #NumberOfFramesInOverlay need to be set only for multi-frame overlays
AddOverLayTagToDataset(ds, 0x601e, 0x0040, "ROI"); #OverlayType
AddOverLayTagToDataset(ds, 0x601e, 0x0050, [1, 1]); #OverlayOrigin
AddOverLayTagToDataset(ds, 0x601e, 0x0100, 1); #OverlayBitsAllocated
AddOverLayTagToDataset(ds, 0x601e, 0x0102, 0); #OverlayBitPosition
AddOverLayTagToDataset(ds, 0x601e, 0x0022, "my gen overlay"); #OverlayDescription
AddOverLayTagToDataset(ds, 0x601e, 0x1001, theId); #OverlayActivationLayer
# set overlay data
overlayDataArr = np.full(numOverLayRows*numOverlayCols, True, dtype=bool); #np.ones(ds.OverlayRows*ds.OverlayColumns);
#ds.OverlayData               = overlayDataArr.tostring();
AddOverLayTagToDataset(ds, 0x601e, 0x3000, overlayDataArr.tostring()); #OverlayData

# add sequences
# ReferencedSeriesSequence
refSeriesSeq = Dataset();
#refSeriesSeq.BlockType = "ReferencedSeriesSequence"; # Do not set this. Leads to DICOM compliance errors
refSeriesSeq.SeriesInstanceUID = inputDcmImg.SeriesInstanceUID;

# ReferencedImageSequence
refImgeSeq = Dataset();
#refImgeSeq.BlockType = "ReferencedImageSequence"; # Do not set this. Leads to DICOM compliance errors
refImgeSeq.ReferencedSOPClassUID = inputDcmImg.SOPClassUID;
refImgeSeq.ReferencedSOPInstanceUID = inputDcmImg.SOPInstanceUID;

# add Ref Image Sequence to Ref Series Sequence
refSeriesSeq.ReferencedImageSequence = Sequence([refImgeSeq]);

# add ref series seq to the dataset
ds.ReferencedSeriesSequence = Sequence([refSeriesSeq]);

ds.save_as(gspsOutFileName);

0 ответов

Другие вопросы по тегам