def setUp(self): # Create simple dataset for all tests ds = Dataset() ds.PatientName = "Name^Patient" # Set up a simple nested sequence # first, the innermost sequence subitem1 = Dataset() subitem1.ContourNumber = 1 subitem1.ContourData = ['2', '4', '8', '16'] subitem2 = Dataset() subitem2.ContourNumber = 2 subitem2.ContourData = ['32', '64', '128', '196'] sub_ds = Dataset() sub_ds.ContourSequence = Sequence( (subitem1, subitem2)) # XXX in 0.9.5 will need sub_ds.ContourSequence # Now the top-level sequence ds.ROIContourSequence = Sequence( (sub_ds, )) # Comma necessary to make it a one-tuple # Store so each test can use it self.ds = ds
def setUp(self): # Create simple dataset for all tests ds = Dataset() ds.PatientName = "Name^Patient" # Set up a simple nested sequence # first, the innermost sequence subitem1 = Dataset() subitem1.ContourNumber = 1 subitem1.ContourData = ['2', '4', '8', '16'] subitem2 = Dataset() subitem2.ContourNumber = 2 subitem2.ContourData = ['32', '64', '128', '196'] sub_ds = Dataset() sub_ds.ContourSequence = Sequence((subitem1, subitem2)) # Now the top-level sequence ds.ROIContourSequence = Sequence((sub_ds,)) # Comma to make one-tuple # Store so each test can use it self.ds = ds
def create_rtstruct(RS_File, im_mask_ax, im_mask_sag, im_mask_cor): rmin, rmax, cmin, cmax, zmin, zmax = bbox2_3D(im_mask_sag, 0) if rmin < 0: rmin = 0 if cmin < 0: cmin = 0 if zmin < 0: zmin = 0 im_mask_ax_adj = np.zeros(np.shape(im_mask_ax)) im_mask_ax_adj[rmin:rmax, cmin:cmax, zmin:zmax] = im_mask_ax[rmin:rmax, cmin:cmax, zmin:zmax] ss = dicom.read_file(RS_File) contour_name = FLAGS.structure data_path = FLAGS.data_dir ## Add Contour UID = ss.SOPInstanceUID.split('.') UID_NEW = UID[:-1] UID_NEW.append(datetime.datetime.now().strftime("%Y%m%d%H%M%S%f")[0:19]) ss.SOPInstanceUID = '.'.join(UID_NEW) ss.StructureSetName = FLAGS.structure_match + '_DLV3_' + datetime.datetime.now( ).strftime("%Y%m%d%H%M%S%f")[0:19] ss.StructureSetLabel = datetime.datetime.now().strftime( "%Y%m%d%H%M%S%f")[0:19] ss.InstanceCreationDate = datetime.datetime.now().strftime("%Y%m%d") ss.InstanceCreationTime = datetime.datetime.now().strftime("%H%M%S.%f") ROINumList = [] for s in ss.ROIContourSequence: ROINumList.append(s.ReferencedROINumber) ## Add StructureSetROISequence ss_new = Dataset() ss_new.ROINumber = np.int(max(ROINumList)) + 1 ss_new.ReferencedFrameOfReferenceUID = ss.StructureSetROISequence[ len(ROINumList) - 1].ReferencedFrameOfReferenceUID ss_new.ROIName = FLAGS.structure_match + '_DLV3' ss_new.ROIDescription = '' ss_new.ROIGenerationAlgorithm = 'MANUAL' ss.StructureSetROISequence.append(ss_new) ## Add RTROIObservationsSequence ss_new = Dataset() ss_new.ObservationNumber = np.int(max(ROINumList)) + 1 ss_new.ReferencedROINumber = np.int(max(ROINumList)) + 1 ss_new.ROIObservationDescription = 'Type:Soft, Range:*/*, Fill:0, Opacity:0.0, Thickness:1, LineThickness:2' ss_new.RTROIInterpretedType = '' ss_new.ROIInterpreter = '' ss.RTROIObservationsSequence.append(ss_new) ## Add ROIContourSequence ss_new = Dataset() ss_new.ReferencedROINumber = np.int(max(ROINumList)) + 1 ss_new.ROIDisplayColor = ['255', '0', '0'] ss_new.ContourSequence = Sequence() k = 0 ss_referenceclass = ss.ROIContours[0].Contours[0].ContourImageSequence[ 0].ReferencedSOPClassUID for item in ss.StructureSetROISequence[:]: ## Check if structure is equal to specified structure name if item.ROIName == FLAGS.structure_match: ## ss_maxslice: determines maximum number of image slices contour lives on ss_maxslice = len(ss.ROIContours[k].Contours) ## pattern collects referenced SOP for DICOM collection, searched dir for CT_files list pattern = ss.ROIContours[k].Contours[0].ContourImageSequence[ 0].ReferencedSOPInstanceUID pattern = '*' + '.'.join(pattern.split('.')[:-2]) pattern = pattern[:-3] + '*' CT_files = find(pattern, data_path) try: CT_files.remove(RS_File) except: print('RS not found in CT list') if CT_files: ## Open first CT image, get size, total number of files and ## initialize Numpy Arrays for data collection ct_maxslice = len(CT_files) img = dicom.read_file(CT_files[0]) img_size = np.shape(img.pixel_array) im_mask = np.zeros((img_size[0], img_size[1], ct_maxslice)) im_data = np.zeros((img_size[0], img_size[1], ct_maxslice)) z0 = img.ImagePositionPatient[2] ## Since DICOM files are not in spatial order, determine ## "z0" or starting z position for slice in range(0, ct_maxslice): img = dicom.read_file(CT_files[slice]) if 'RS' in CT_files[slice]: print('not structure') else: if z0 > img.ImagePositionPatient[2]: z0 = img.ImagePositionPatient[2] for slice in range(0, ct_maxslice): if 'RS' in CT_files[slice]: print('not structure') else: contour_dicom = Dataset() img = dicom.read_file(CT_files[slice]) x_y = np.array(img.ImagePositionPatient) xsp_ysp = np.array(img.PixelSpacing) z_prime = float(img.ImagePositionPatient[2]) zsp = float(img.SliceThickness) z = int((z_prime - z0) / zsp) if np.max(im_mask_ax_adj[:, :, z]) > 0 and (np.max( im_mask_sag[:, :, z] > 0)): r = im_mask_ax_adj[:, :, z] contours = measure.find_contours(r, 0.5) for n, contour in enumerate(contours): pointList = [] contour_dicom = Dataset() contour_dicom.ContourGeometricType = 'CLOSED_PLANAR' for i in range(0, len(contour)): y = contour[i][0] x = contour[i][1] x_prime = x * xsp_ysp[0] + x_y[0] y_prime = y * xsp_ysp[1] + x_y[1] pointList.append(x_prime) pointList.append(y_prime) pointList.append(z_prime) if len(pointList) > 0: contour_dicom.NumberOfContourPoints = len( contour) contour_dicom.ContourData = pointList contour_dicom.ContourImageSequence = Sequence() img_seq = Dataset() img_seq.ReferencedSOPClassUID = ss_referenceclass img_seq.ReferencedSOPInstanceUID = CT_files[ slice].split(os.sep)[-1].replace( '.dcm', '').replace('MR.', '') contour_dicom.ContourImageSequence.append( img_seq) ss_new.ContourSequence.append(contour_dicom) k = k + 1 ss.ROIContourSequence.append(ss_new) filename = RS_File.split(os.sep) filename[-1] = contour_name + str( datetime.datetime.now().strftime("%Y%m%d")) + '.dcm' print(filename) ss.save_as(os.sep.join(filename)) return