Im trying to upload a test segmentation instance to orthanc and am getting the error:
{
“HttpError” : “Not Found”,
“HttpStatus” : 404,
“Message” : “Inexistent tag”,
“Method” : “POST”,
“OrthancError” : “Inexistent tag”,
“OrthancStatus” : 21,
“Uri” : “/instances/”
}
This is my code:
ref_instance_id = study.get_image_path()
img_arr = study.load_image(ref_instance_id)
# Create a 3D uint8 image filled with zeros with the same shape as img_arr
zeros_img = np.zeros(img_arr.shape, dtype=np.uint8)
# Set a cube with len 10 at the center of the image as 1
x_middle = img_arr.shape[1] // 2
y_middle = img_arr.shape[2] // 2
z_middle = img_arr.shape[0] // 2
len_cube = 10
zeros_img[x_middle-len_cube:x_middle+len_cube, y_middle-len_cube:y_middle+len_cube, z_middle-len_cube:z_middle+len_cube] = 1
len_cube = 3
zeros_img[x_middle-len_cube:x_middle, y_middle-len_cube:y_middle, z_middle-len_cube:z_middle] = 2
zeros_img[x_middle+1:x_middle+len_cube, y_middle+1:y_middle+len_cube, z_middle+1:z_middle+len_cube] = 3
# study.save_segmentation("input", zeros_img)
segmentation_array = zeros_img
print("Creating a new segmentation instance")
original_dcm = study._load_dcm_object(ref_instance_id)
assert (
original_dcm.pixel_array.shape == segmentation_array.shape
), f"Segmentation array shape {segmentation_array.shape} does not match the original DICOM image shape {original_dcm.pixel_array.shape}."
# Create a new DICOM dataset
# Set the transfer syntax to Explicit VR Little Endian
file_meta = Dataset()
file_meta.MediaStorageSOPClassUID = SegmentationStorage
file_meta.MediaStorageSOPInstanceUID = generate_uid()
file_meta.TransferSyntaxUID = ExplicitVRLittleEndian
# Create the FileDataset
ds = FileDataset(
"segmentation.dcm", {}, file_meta=file_meta, preamble=b"\0" * 128
)
# Add patient and study information
ds.PatientName = original_dcm.PatientName
ds.PatientID = original_dcm.PatientID
ds.StudyInstanceUID = original_dcm.StudyInstanceUID
# Check if series with SEG modality exists in same study as ref_img_type
ref_instance = study.orthanc.instances.get(ref_instance_id)
ref_study = ref_instance.series.study
seg_series_uid = None
series_list = ref_study.series
for serie in series_list:
if serie.main_dicom_tags.get("Modality") == "SEG":
seg_series_uid = serie.tags["SeriesInstanceUID"]
break
if seg_series_uid is None:
print("Creating a new series for the segmentations")
seg_series_uid = generate_uid()
else:
print(
f"Found existing series with SeriesInstanceUID {seg_series_uid}"
)
ds.SeriesInstanceUID = seg_series_uid
ds.SOPInstanceUID = file_meta.MediaStorageSOPInstanceUID
ds.Modality = "SEG"
ds.StudyID = original_dcm.StudyID
ds.InstanceNumber = original_dcm.InstanceNumber
# Add other required attributes
ds.SpecificCharacterSet = "ISO_IR 100"
ds.ImageType = ["DERIVED", "PRIMARY"]
ds.ContentDate = datetime.now().strftime("%Y%m%d")
ds.ContentTime = datetime.now().strftime("%H%M%S")
# Define the segments
labels = {
item[1]["segment_number"]: item[0]
for item in config["labels"].items()
}
ds.SegmentSequence = []
for label, name in labels.items():
segment = Dataset()
segment.SegmentNumber = label
segment.SegmentLabel = name
segment.SegmentAlgorithmType = (
"MANUAL" if True else "AUTOMATIC"
)
segment.SegmentAlgorithmName = "FollicleFinder"
ds.SegmentSequence.append(segment)
# Create Referenced Series Sequence
ref_series_seq = Dataset()
ref_series_seq.SeriesInstanceUID = original_dcm.SeriesInstanceUID
ref_series_seq.ReferencedInstanceSequence = []
# Reference the original 3D instance
ref_instance = Dataset()
ref_instance.ReferencedSOPClassUID = original_dcm.SOPClassUID
ref_instance.ReferencedSOPInstanceUID = original_dcm.SOPInstanceUID
ref_series_seq.ReferencedInstanceSequence.append(ref_instance)
# Add the Referenced Series Sequence to the dataset
ds.ReferencedSeriesSequence = [ref_series_seq]
# Convert the numpy array to a SimpleITK image
seg_image = sitk.GetImageFromArray(segmentation_array.astype(np.uint16))
# Set the origin and spacing to match the original DICOM
seg_image.SetSpacing(
list(original_dcm.PixelSpacing) + [original_dcm.SpacingBetweenSlices]
)
# Add the necessary DICOM tags for segmentation
ds.BitsAllocated = 8
ds.BitsStored = 8
ds.HighBit = 7
ds.SamplesPerPixel = 1
ds.PhotometricInterpretation = "MONOCHROME2"
ds.NumberOfFrames = segmentation_array.shape[0]
ds.Rows = segmentation_array.shape[1]
ds.Columns = segmentation_array.shape[2]
ds.PixelRepresentation = 0
# save numpy array to pixel array
ds.PixelData = segmentation_array.astype(np.uint8).tobytes()
# Update the PixelData VR to 'OB' for 8-bit data
ds[0x7FE0, 0x0010].VR = 'OB'
import io
import requests
# Upload the segmentation to the Orthanc server
print("Uploading segmentation to Orthanc server")
dcm_bytes = io.BytesIO()
ds.save_as(dcm_bytes)
response = requests.post(
f'http://localhost:8042/instances/',
data=dcm_bytes.getvalue(),
auth=(
"",
"",
),
)
print(response.text)
response.raise_for_status() # Error occurs here
new_segmentation_id = response.json().get("ID")
# Download the segmentation from the Orthanc server
print("Downloading segmentation from Orthanc server")
downloaded_dcm = study._load_dcm_object(new_segmentation_id)
seg_arr = downloaded_dcm.pixel_array