def full_imageProcess(ArrayDicom_o, dx, dy, title): # process a full image ArrayDicom = u.norm01(ArrayDicom_o) height = np.shape(ArrayDicom)[0] width = np.shape(ArrayDicom)[1] blobs_log = blob_log( ArrayDicom, min_sigma=1, max_sigma=5, num_sigma=20, threshold=0.15 ) # run on windows, for some stupid reason exclude_border is not recognized in my distro at home center = [] point_det = [] for blob in blobs_log: y, x, r = blob point_det.append((x, y, r)) point_det = sorted( point_det, key=itemgetter(2), reverse=True ) # here we sort by the radius of the dot bigger dots are around the center and edges # we need to find the centre dot as well as the larger dots on the sides of the image # for j in range(0, len(point_det)): # x, y, r = point_det[j] # center.append((int(round(x)), int(round(y)))) # now that we have detected the centre we are going to increase the precision of the detected point im_centre = Image.fromarray( 255 * ArrayDicom[ height // 2 - 20 : height // 2 + 20, width // 2 - 20 : width // 2 + 20 ] ) im_centre = im_centre.resize( (im_centre.width * 10, im_centre.height * 10), Image.LANCZOS ) xdet_int, ydet_int = point_detect_singleImage(im_centre) xdet = int(width // 2 - 20) + xdet_int / 10 ydet = int(height // 2 - 20) + ydet_int / 10 center.append((xdet, ydet)) textstr = "" print("center=", center) fig, ax = viewer(u.range_invert(ArrayDicom_o), dx, dy, center, title, textstr) return fig, ax, center
def read_dicom(directory): for subdir, dirs, files in os.walk( directory): # pylint: disable = unused-variable list_title = [] list_gantry_angle = [] list_collimator_angle = [] list_figs = [] # center_g0c90 = [(0, 0)] center_g0 = [(0, 0)] dx = 0 dy = 0 distance = 0 # pylint: disable = unused-variable k = 0 # we callect all the images in ArrayDicom for file in tqdm(sorted(files)): print(file) if os.path.splitext(directory + file)[1] == ".dcm": dataset = pydicom.dcmread(directory + file) gantry_angle = dataset[0x300A, 0x011E].value collimator_angle = dataset[0x300A, 0x0120].value list_gantry_angle.append(gantry_angle) list_collimator_angle.append(collimator_angle) # title = ('Gantry= ' + str(gantry_angle), 'Collimator= ' + str(collimator_angle)) title = ( "g" + str(round(gantry_angle)), "c" + str(round(collimator_angle)), ) print(title) if k == 0: # title = ('Gantry= ' + str(gantry_angle), 'Collimator= ' + str(collimator_angle)) title = ( "g" + str(round(gantry_angle)), "c" + str(round(collimator_angle)), ) list_title.append(title) ArrayDicom = dataset.pixel_array # height = np.shape(ArrayDicom)[0] # width = np.shape(ArrayDicom)[1] SID = dataset.RTImageSID dx = 1 / (SID * (1 / dataset.ImagePlanePixelSpacing[0]) / 1000) dy = 1 / (SID * (1 / dataset.ImagePlanePixelSpacing[1]) / 1000) print("pixel spacing row [mm]=", dx) print("pixel spacing col [mm]=", dy) distance, fig_scaling = scalingAnalysis(ArrayDicom, dx, dy) else: list_title.append(title) tmp_array = dataset.pixel_array tmp_array = u.norm01(tmp_array) # tmp_array = norm01(tmp_array) ArrayDicom = np.dstack((ArrayDicom, tmp_array)) k = k + 1 # After we colect all the images we only select g0c90 and g0c270 to calculate the center at g0 print(list_title) for i, _ in enumerate(list_title): if list_title[i][0] == "g0" and list_title[i][1] == "c90": # height = np.shape(ArrayDicom[:, :, i])[0] # width = np.shape(ArrayDicom[:, :, i])[1] fig_g0c90, ax_g0c90, center_g0c90 = full_imageProcess( ArrayDicom[:, :, i], dx, dy, list_title[i]) center_g0[0] = ( center_g0[0][0] + center_g0c90[0][0] * 0.5, center_g0[0][1] + center_g0c90[0][1] * 0.5, ) list_figs.append(fig_g0c90) # we plot always the image at g0c90 if list_title[i][0] == "g0" and list_title[i][1] == "c270": center_g0c270 = full_imageProcess_noGraph(ArrayDicom[:, :, i]) center_g0[0] = ( center_g0[0][0] + center_g0c270[0][0] * 0.5, center_g0[0][1] + center_g0c270[0][1] * 0.5, ) # for i in range(0, len(list_title)): for i, _ in enumerate(list_title): if list_title[i][1] != "c90": center = full_imageProcess_noGraph(ArrayDicom[:, :, i]) x_g0, y_g0 = center_g0[0] x, y = center[0] dist = sqrt((x_g0 - x) * (x_g0 - x) * dx * dx + (y_g0 - y) * (y_g0 - y) * dy * dy) # dist = sqrt((width//2 - x) * (width//2 - x) * dx * dx + (height//2 - y) * (height//2 - y) * dy * dy) textstr = "offset" + str(list_title[i]) + "=" + str(round( dist, 4)) + " mm" ax_g0c90.scatter(x * dx, (ArrayDicom[:, :, i].shape[0] - y) * dy, label=textstr) # perfect! print(list_title[i], "center_g0c90=", center_g0c90, "center=", center, dist) ax_g0c90.legend(bbox_to_anchor=(1.25, 1), loc=2, borderaxespad=0.0) with PdfPages(directory + "/" + "Graticule_report.pdf") as pdf: # Page = plt.figure(figsize=(4, 5)) # Page.text(0, 0.9, 'Report', size=18) # Page.text(0, 0.9, "Distance=" + str(distance)+ " cm", size=14) pdf.savefig(fig_g0c90) pdf.savefig(fig_scaling) # exit(0) sys.exit(0)
def scalingAnalysis(ArrayDicom_o, dx, dy): # determine scaling ArrayDicom = u.norm01(ArrayDicom_o) # ArrayDicom = norm01(ArrayDicom_o) blobs_log = blob_log( ArrayDicom, min_sigma=1, max_sigma=5, num_sigma=20, threshold=0.15 ) # run on windows, for some stupid reason exclude_border is not recognized in my distro at home point_det = [] for blob in blobs_log: y, x, r = blob point_det.append((x, y, r)) point_det = sorted( point_det, key=itemgetter(2), reverse=True ) # here we sort by the radius of the dot bigger dots are around the center and edges point_det = np.asarray(point_det) # now we need to select the most extreme left and right point print(np.shape(ArrayDicom)[0] // 2) print(abs(point_det[:6, 1] - np.shape(ArrayDicom)[0] // 2) < 10) point_sel = [] for i in range(0, 6): if abs(point_det[i, 1] - np.shape(ArrayDicom)[0] // 2) < 10: point_sel.append(abs(point_det[i, :])) point_sel = np.asarray(point_sel) imax = np.argmax(point_sel[:, 0]) imin = np.argmin(point_sel[:, 0]) print(point_sel[imax, :], point_sel[imin, :]) distance = (np.sqrt((point_sel[imax, 0] - point_sel[imin, 0]) * (point_sel[imax, 0] - point_sel[imin, 0]) * dx * dx + (point_sel[imax, 1] - point_sel[imin, 1]) * (point_sel[imax, 1] - point_sel[imin, 1]) * dy * dy) / 10.0) print("distance=", distance, "cm") # distance is reported in cm # plotting the figure of scaling results fig = plt.figure(figsize=(12, 7)) ax = fig.subplots() ax.volume = ArrayDicom_o width = ArrayDicom_o.shape[1] height = ArrayDicom_o.shape[0] extent = (0, 0 + (width * dx), 0, 0 + (height * dy)) img = ax.imshow( # pylint: disable = unused-variable ArrayDicom_o, extent=extent, origin="lower") # fig.colorbar(img, ax=ax, orientation="vertical") # img = ax.imshow(ArrayDicom_o) ax.set_xlabel("x distance [mm]") ax.set_ylabel("y distance [mm]") ax.scatter(point_sel[imax, 0] * dx, point_sel[imax, 1] * dy) ax.scatter(point_sel[imin, 0] * dx, point_sel[imin, 1] * dy) # adding a horizontal arrow ax.annotate( s="", xy=(point_sel[imax, 0] * dx, point_sel[imax, 1] * dy), xytext=(point_sel[imin, 0] * dx, point_sel[imin, 1] * dy), arrowprops=dict(arrowstyle="<->", color="r"), ) # example on how to plot a double headed arrow ax.text( (width // 2.8) * dx, (height // 2 + 10) * dy, "Distance=" + str(round(distance, 4)) + " cm", rotation=0, fontsize=14, color="r", ) return distance, fig
def read_dicom3D(direc, i_option): # item = 0 for subdir, dirs, files in os.walk( direc): # pylint: disable = unused-variable k = 0 for file in tqdm(sorted(files)): # print('filename=', file) if os.path.splitext(file)[1] == ".dcm": dataset = pydicom.dcmread(direc + file) if k == 0: ArrayDicom = np.zeros( (dataset.Rows, dataset.Columns, 0), dtype=dataset.pixel_array.dtype, ) tmp_array = dataset.pixel_array if i_option.startswith(("y", "yeah", "yes")): max_val = np.amax(tmp_array) tmp_array = tmp_array / max_val min_val = np.amin(tmp_array) tmp_array = tmp_array - min_val tmp_array = 1 - tmp_array # inverting the range # min_val = np.amin(tmp_array) # normalizing # tmp_array = tmp_array - min_val # tmp_array = tmp_array / (np.amax(tmp_array)) tmp_array = u.norm01(tmp_array) else: # min_val = np.amin(tmp_array) # tmp_array = tmp_array - min_val # tmp_array = tmp_array / (np.amax(tmp_array)) tmp_array = u.norm01(tmp_array) # just normalize ArrayDicom = np.dstack((ArrayDicom, tmp_array)) # print("item thickness [mm]=", dataset.SliceThickness) SID = dataset.RTImageSID dx = 1 / (SID * (1 / dataset.ImagePlanePixelSpacing[0]) / 1000) dy = 1 / (SID * (1 / dataset.ImagePlanePixelSpacing[1]) / 1000) print("pixel spacing row [mm]=", dx) print("pixel spacing col [mm]=", dy) else: tmp_array = dataset.pixel_array if i_option.startswith(("y", "yeah", "yes")): max_val = np.amax(tmp_array) tmp_array = tmp_array / max_val min_val = np.amin(tmp_array) tmp_array = tmp_array - min_val tmp_array = 1 - tmp_array # inverting the range # min_val = np.amin(tmp_array) # normalizing # tmp_array = tmp_array - min_val # tmp_array = tmp_array / (np.amax(tmp_array)) tmp_array = u.norm01(tmp_array) else: # min_val = np.amin(tmp_array) # tmp_array = tmp_array - min_val # tmp_array = tmp_array / (np.amax(tmp_array)) # just normalize tmp_array = u.norm01(tmp_array) ArrayDicom = np.dstack((ArrayDicom, tmp_array)) k = k + 1 xfield, yfield, rotfield = image_analyze(ArrayDicom, i_option) multi_slice_viewer(ArrayDicom, dx, dy) if np.shape(xfield)[2] == 2: fig, peak_figs, junctions_figs = merge_view_vert(xfield, dx, dy) with PdfPages(direc + "jaws_X_report.pdf") as pdf: pdf.savefig(fig) # for i in range(0, len(peak_figs)): for _, f in enumerate(peak_figs): pdf.savefig(f) # for i in range(0, len(junctions_figs)): for _, f in enumerate(junctions_figs): pdf.savefig(f) plt.close() else: print( "X jaws data analysis not completed please verify that you have two X jaws images. For more information see manual." ) if np.shape(yfield)[2] == 4: fig, peak_figs, junctions_figs = merge_view_horz(yfield, dx, dy) # print('peak_figs********************************************************=', len(peak_figs),peak_figs) with PdfPages(direc + "jaws_Y_report.pdf") as pdf: pdf.savefig(fig) # for i in range(0, len(peak_figs)): for _, f in enumerate(peak_figs): pdf.savefig(f) for _, f in enumerate(junctions_figs): pdf.savefig(f) plt.close() else: print( "Y jaws data analysis not completed please verify that you have four Y jaws images. For more information see manual." ) if np.shape(rotfield)[2] == 4: fig, peak_figs, junctions_figs = merge_view_filtrot(rotfield, dx, dy) with PdfPages(direc + "jaws_FR_report.pdf") as pdf: pdf.savefig(fig) for _, f in enumerate(peak_figs): pdf.savefig(f) for _, f in enumerate(junctions_figs): pdf.savefig(f) plt.close() else: print( "Field rotation data analysis not completed please verify that you have four field rotation images. For more information see manual." )
def read_dicom(filenm, ioptn): dataset = pydicom.dcmread(filenm) now = datetime.now() ArrayDicom = np.zeros((dataset.Rows, dataset.Columns), dtype=dataset.pixel_array.dtype) ArrayDicom = dataset.pixel_array SID = dataset.RTImageSID print("array_shape=", np.shape(ArrayDicom)) height = np.shape(ArrayDicom)[0] width = np.shape(ArrayDicom)[1] dx = 1 / (SID * (1 / dataset.ImagePlanePixelSpacing[0]) / 1000) dy = 1 / (SID * (1 / dataset.ImagePlanePixelSpacing[1]) / 1000) print("pixel spacing row [mm]=", dx) print("pixel spacing col [mm]=", dy) # creating the figure extent based on the image dimensions, we divide by 10 to get the units in cm extent = ( 0, 0 + (ArrayDicom.shape[1] * dx / 10), 0 + (ArrayDicom.shape[0] * dy / 10), 0, ) # creating the figure extent list for the bib images list_extent = [] # plt.figure() # plt.imshow(ArrayDicom, extent=extent, origin='upper') # plt.imshow(ArrayDicom) # plt.xlabel('x distance [cm]') # plt.ylabel('y distance [cm]') # plt.show() if ioptn.startswith(("y", "yeah", "yes")): height, width = ArrayDicom.shape ArrayDicom_mod = ArrayDicom[:, width // 2 - height // 2:width // 2 + height // 2] else: ArrayDicom_mod = ArrayDicom # we take a diagonal profile to avoid phantom artifacts # im_profile = ArrayDicom_mod.diagonal() # test to make sure image is displayed correctly bibs are high amplitude against dark background ctr_pixel = ArrayDicom_mod[height // 2, width // 2] corner_pixel = ArrayDicom_mod[0, 0] if ctr_pixel > corner_pixel: ArrayDicom = u.range_invert(ArrayDicom) ArrayDicom = u.norm01(ArrayDicom) # working on transforming the full image and invert it first and go from there. if ioptn.startswith(("y", "yeah", "yes")): ROI1 = { "edge_top": 70, "edge_bottom": 130, "edge_left": 270, "edge_right": 350 } ROI2 = { "edge_top": 70, "edge_bottom": 130, "edge_left": 680, "edge_right": 760 } ROI3 = { "edge_top": 150, "edge_bottom": 210, "edge_left": 760, "edge_right": 830, } ROI4 = { "edge_top": 560, "edge_bottom": 620, "edge_left": 760, "edge_right": 830, } ROI5 = { "edge_top": 640, "edge_bottom": 700, "edge_left": 680, "edge_right": 760, } ROI6 = { "edge_top": 640, "edge_bottom": 700, "edge_left": 270, "edge_right": 350, } ROI7 = { "edge_top": 560, "edge_bottom": 620, "edge_left": 200, "edge_right": 270, } ROI8 = { "edge_top": 150, "edge_bottom": 210, "edge_left": 200, "edge_right": 270, } else: ROI1 = { "edge_top": 280, "edge_bottom": 360, "edge_left": 360, "edge_right": 440, } ROI2 = { "edge_top": 280, "edge_bottom": 360, "edge_left": 830, "edge_right": 910, } ROI3 = { "edge_top": 360, "edge_bottom": 440, "edge_left": 940, "edge_right": 1020, } ROI4 = { "edge_top": 840, "edge_bottom": 920, "edge_left": 940, "edge_right": 1020, } ROI5 = { "edge_top": 930, "edge_bottom": 1000, "edge_left": 830, "edge_right": 910, } ROI6 = { "edge_top": 930, "edge_bottom": 1000, "edge_left": 360, "edge_right": 440, } ROI7 = { "edge_top": 840, "edge_bottom": 920, "edge_left": 280, "edge_right": 360, } ROI8 = { "edge_top": 360, "edge_bottom": 440, "edge_left": 280, "edge_right": 360, } # images for object detection imcirclist = [] imcirc1 = Image.fromarray( 255 * ArrayDicom[ROI1["edge_top"]:ROI1["edge_bottom"], ROI1["edge_left"]:ROI1["edge_right"], ]) imcirc1 = imcirc1.resize((imcirc1.width * 10, imcirc1.height * 10), Image.LANCZOS) list_extent.append(( (ROI1["edge_left"] * dx / 10), (ROI1["edge_right"] * dx / 10), (ROI1["edge_bottom"] * dy / 10), (ROI1["edge_top"] * dy / 10), )) imcirc2 = Image.fromarray( 255 * ArrayDicom[ROI2["edge_top"]:ROI2["edge_bottom"], ROI2["edge_left"]:ROI2["edge_right"], ]) imcirc2 = imcirc2.resize((imcirc2.width * 10, imcirc2.height * 10), Image.LANCZOS) list_extent.append(( (ROI2["edge_left"] * dx / 10), (ROI2["edge_right"] * dx / 10), (ROI2["edge_bottom"] * dy / 10), (ROI2["edge_top"] * dy / 10), )) imcirc3 = Image.fromarray( 255 * ArrayDicom[ROI3["edge_top"]:ROI3["edge_bottom"], ROI3["edge_left"]:ROI3["edge_right"], ]) imcirc3 = imcirc3.resize((imcirc3.width * 10, imcirc3.height * 10), Image.LANCZOS) list_extent.append(( (ROI3["edge_left"] * dx / 10), (ROI3["edge_right"] * dx / 10), (ROI3["edge_bottom"] * dy / 10), (ROI3["edge_top"] * dy / 10), )) imcirc4 = Image.fromarray( 255 * ArrayDicom[ROI4["edge_top"]:ROI4["edge_bottom"], ROI4["edge_left"]:ROI4["edge_right"], ]) imcirc4 = imcirc4.resize((imcirc4.width * 10, imcirc4.height * 10), Image.LANCZOS) list_extent.append(( (ROI4["edge_left"] * dx / 10), (ROI4["edge_right"] * dx / 10), (ROI4["edge_bottom"] * dy / 10), (ROI4["edge_top"] * dy / 10), )) imcirc5 = Image.fromarray( 255 * ArrayDicom[ROI5["edge_top"]:ROI5["edge_bottom"], ROI5["edge_left"]:ROI5["edge_right"], ]) imcirc5 = imcirc5.resize((imcirc5.width * 10, imcirc5.height * 10), Image.LANCZOS) list_extent.append(( (ROI5["edge_left"] * dx / 10), (ROI5["edge_right"] * dx / 10), (ROI5["edge_bottom"] * dy / 10), (ROI5["edge_top"] * dy / 10), )) imcirc6 = Image.fromarray( 255 * ArrayDicom[ROI6["edge_top"]:ROI6["edge_bottom"], ROI6["edge_left"]:ROI6["edge_right"], ]) imcirc6 = imcirc6.resize((imcirc6.width * 10, imcirc6.height * 10), Image.LANCZOS) list_extent.append(( (ROI6["edge_left"] * dx / 10), (ROI6["edge_right"] * dx / 10), (ROI6["edge_bottom"] * dy / 10), (ROI6["edge_top"] * dy / 10), )) imcirc7 = Image.fromarray( 255 * ArrayDicom[ROI7["edge_top"]:ROI7["edge_bottom"], ROI7["edge_left"]:ROI7["edge_right"], ]) imcirc7 = imcirc7.resize((imcirc7.width * 10, imcirc7.height * 10), Image.LANCZOS) list_extent.append(( (ROI7["edge_left"] * dx / 10), (ROI7["edge_right"] * dx / 10), (ROI7["edge_bottom"] * dy / 10), (ROI7["edge_top"] * dy / 10), )) imcirc8 = Image.fromarray( 255 * ArrayDicom[ROI8["edge_top"]:ROI8["edge_bottom"], ROI8["edge_left"]:ROI8["edge_right"], ]) imcirc8 = imcirc8.resize((imcirc8.width * 10, imcirc8.height * 10), Image.LANCZOS) list_extent.append(( (ROI8["edge_left"] * dx / 10), (ROI8["edge_right"] * dx / 10), (ROI8["edge_bottom"] * dy / 10), (ROI8["edge_top"] * dy / 10), )) imcirclist.append(imcirc1) imcirclist.append(imcirc2) imcirclist.append(imcirc3) imcirclist.append(imcirc4) imcirclist.append(imcirc5) imcirclist.append(imcirc6) imcirclist.append(imcirc7) imcirclist.append(imcirc8) xdet, ydet = point_detect(imcirclist) profiles = [] profile1 = np.array(imcirc1, dtype=np.uint8)[:, xdet[0]] / 255 profile2 = np.array(imcirc2, dtype=np.uint8)[:, xdet[1]] / 255 profile3 = np.array(imcirc3, dtype=np.uint8)[ydet[2], :] / 255 profile4 = np.array(imcirc4, dtype=np.uint8)[ydet[3], :] / 255 profile5 = np.array(imcirc5, dtype=np.uint8)[:, xdet[4]] / 255 profile6 = np.array(imcirc6, dtype=np.uint8)[:, xdet[5]] / 255 profile7 = np.array(imcirc7, dtype=np.uint8)[ydet[6], :] / 255 profile8 = np.array(imcirc8, dtype=np.uint8)[ydet[7], :] / 255 profiles.append(profile1) profiles.append(profile2) profiles.append(profile3) profiles.append(profile4) profiles.append(profile5) profiles.append(profile6) profiles.append(profile7) profiles.append(profile8) k = 0 fig = plt.figure(figsize=(8, 12)) # this figure will hold the bibs plt.subplots_adjust(hspace=0.35) # creating the page to write the results dirname = os.path.dirname(filenm) # tolerance levels to change at will tol = 1.0 # tolearance level act = 2.0 # action level phantom_distance = 3.0 # distance from the bib to the edge of the phantom with PdfPages(dirname + "/" + now.strftime("%d-%m-%Y_%H:%M_") + dataset[0x0008, 0x1010].value + "_Lightrad_report.pdf") as pdf: Page = plt.figure(figsize=(4, 5)) Page.text(0.45, 0.9, "Report", size=18) kk = 0 # counter for data points for profile in profiles: _, index = u.find_nearest(profile, 0.5) # find the 50% amplitude point # value_near, index = find_nearest(profile, 0.5) # find the 50% amplitude point if ( # pylint: disable = consider-using-in k == 0 or k == 1 or k == 4 or k == 5): # there are the bibs in the horizontal offset_value_y = round( abs((ydet[k] - index) * (dy / 10)) - phantom_distance, 2) txt = str(offset_value_y) # print('offset_value_y=', offset_value_y) if abs(offset_value_y) <= tol: Page.text( 0.1, 0.8 - kk / 10, "Point" + str(kk + 1) + " offset=" + txt + " mm", color="g", ) elif abs(offset_value_y) > tol and abs(offset_value_y) <= act: Page.text( 0.1, 0.8 - kk / 10, "Point" + str(kk + 1) + " offset=" + txt + " mm", color="y", ) else: Page.text( 0.1, 0.8 - kk / 10, "Point" + str(kk + 1) + " offset=" + txt + " mm", color="r", ) kk = kk + 1 ax = fig.add_subplot( 4, 2, k + 1) # plotting all the figures in a single plot ax.imshow( np.array(imcirclist[k], dtype=np.uint8) / 255, extent=list_extent[k], origin="upper", ) ax.scatter( list_extent[k][0] + xdet[k] * dx / 100, list_extent[k][3] + ydet[k] * dy / 100, s=30, marker="P", color="y", ) ax.set_title("Bib=" + str(k + 1)) ax.axhline(list_extent[k][3] + index * dy / 100, color="r", linestyle="--") ax.set_xlabel("x distance [cm]") ax.set_ylabel("y distance [cm]") else: offset_value_x = round( abs((xdet[k] - index) * (dx / 10)) - phantom_distance, 2) txt = str(offset_value_x) if abs(offset_value_x) <= tol: # print('1') Page.text( 0.1, 0.8 - kk / 10, "Point" + str(kk + 1) + " offset=" + txt + " mm", color="g", ) elif abs(offset_value_x) > tol and abs(offset_value_x) <= act: # print('2') Page.text( 0.1, 0.8 - kk / 10, "Point" + str(kk + 1) + " offset=" + txt + " mm", color="y", ) else: # print('3') Page.text( 0.1, 0.8 - kk / 10, "Point" + str(kk + 1) + " offset=" + txt + " mm", color="r", ) kk = kk + 1 ax = fig.add_subplot( 4, 2, k + 1) # plotting all the figures in a single plot ax.imshow( np.array(imcirclist[k], dtype=np.uint8) / 255, extent=list_extent[k], origin="upper", ) ax.scatter( list_extent[k][0] + xdet[k] * dx / 100, list_extent[k][3] + ydet[k] * dy / 100, s=30, marker="P", color="y", ) ax.set_title("Bib=" + str(k + 1)) ax.axvline(list_extent[k][0] + index * dx / 100, color="r", linestyle="--") ax.set_xlabel("x distance [cm]") ax.set_ylabel("y distance [cm]") k = k + 1 pdf.savefig() pdf.savefig(fig) # we now need to select a horizontal and a vertical profile to find the edge of the field from an image # for the field size calculation im = Image.fromarray(255 * ArrayDicom) if ioptn.startswith(("y", "yeah", "yes")): PROFILE = { "horizontal": 270, "vertical": 430, } # location to extract the horizontal and vertical profiles if this is a linac else: PROFILE = { "horizontal": 470, "vertical": 510, } # location to extract the horizontal and vertical profiles if this is a true beam profilehorz = ( np.array(im, dtype=np.uint8)[PROFILE["horizontal"], :] / 255 ) # we need to change these limits on a less specific criteria profilevert = np.array(im, dtype=np.uint8)[:, PROFILE["vertical"]] / 255 # top_edge, index_top = find_nearest(profilevert[0:height//2], 0.5) # finding the edge of the field on the top # bot_edge, index_bot = find_nearest(profilevert[height//2:height], 0.5) # finding the edge of the field on the bottom _, index_top = u.find_nearest( profilevert[0:height // 2], 0.5) # finding the edge of the field on the top _, index_bot = u.find_nearest( profilevert[height // 2:height], 0.5) # finding the edge of the field on the bottom # l_edge, index_l = find_nearest(profilehorz[0:width//2], 0.5) #finding the edge of the field on the bottom # r_edge, index_r = find_nearest(profilehorz[width//2:width], 0.5) #finding the edge of the field on the right _, index_l = u.find_nearest( profilehorz[0:width // 2], 0.5) # finding the edge of the field on the bottom _, index_r = u.find_nearest( profilehorz[width // 2:width], 0.5) # finding the edge of the field on the right fig2 = plt.figure( figsize=(7, 5) ) # this figure will show the vertical and horizontal calculated field size ax = fig2.subplots() ax.imshow(ArrayDicom, extent=extent, origin="upper") ax.set_xlabel("x distance [cm]") ax.set_ylabel("y distance [cm]") # adding a vertical arrow ax.annotate( s="", xy=(PROFILE["vertical"] * dx / 10, index_top * dy / 10), xytext=(PROFILE["vertical"] * dx / 10, (height // 2 + index_bot) * dy / 10), arrowprops=dict(arrowstyle="<->", color="r"), ) # example on how to plot a double headed arrow ax.text( (PROFILE["vertical"] + 10) * dx / 10, (height // 1.25) * dy / 10, "Vfs=" + str(round( (height // 2 + index_bot - index_top) * dy / 10, 2)) + "cm", rotation=90, fontsize=14, color="r", ) # adding a horizontal arrow # print(index_l*dx, index_l, PROFILE['horizontal']*dy, PROFILE['horizontal']) ax.annotate( s="", xy=(index_l * dx / 10, PROFILE["horizontal"] * dy / 10), xytext=((width // 2 + index_r) * dx / 10, PROFILE["horizontal"] * dy / 10), arrowprops=dict(arrowstyle="<->", color="r"), ) # example on how to plot a double headed arrow ax.text( (width // 2) * dx / 10, (PROFILE["horizontal"] - 10) * dy / 10, "Hfs=" + str(round( (width // 2 + index_r - index_l) * dx / 10, 2)) + "cm", rotation=0, fontsize=14, color="r", ) pdf.savefig(fig2)
def read_dicom(directory): now = datetime.now() for subdir, dirs, files in os.walk(directory): # pylint: disable = unused-variable dirs.clear() list_title = [] list_gantry_angle = [] list_collimator_angle = [] list_figs = [] center = [] center_g0 = [(0, 0)] center_g90 = [(0, 0)] center_g180 = [(0, 0)] center_g270 = [(0, 0)] dx = 0 dy = 0 k = 0 # we callect all the images in ArrayDicom for file in tqdm(sorted(files)): print("Reading file=>", file) if os.path.splitext(directory + file)[1] == ".dcm": dataset = pydicom.dcmread(directory + file) gantry_angle = dataset[0x300A, 0x011E].value collimator_angle = dataset[0x300A, 0x0120].value list_gantry_angle.append(gantry_angle) list_collimator_angle.append(collimator_angle) if round(gantry_angle) == 360: gantry_angle = 0 if round(collimator_angle) == 360: collimator_angle = 0 title = ( "g" + str(round(gantry_angle)), "c" + str(round(collimator_angle)), ) print(title) if k == 0: # title = ('Gantry= ' + str(gantry_angle), 'Collimator= ' + str(collimator_angle)) title = ( "g" + str(round(gantry_angle)), "c" + str(round(collimator_angle)), ) list_title.append(title) ArrayDicom = dataset.pixel_array height = np.shape(ArrayDicom)[0] width = np.shape(ArrayDicom)[1] SID = dataset.RTImageSID dx = 1 / (SID * (1 / dataset.ImagePlanePixelSpacing[0]) / 1000) dy = 1 / (SID * (1 / dataset.ImagePlanePixelSpacing[1]) / 1000) print("pixel spacing row [mm]=", dx) print("pixel spacing col [mm]=", dy) distance, fig_scaling = scalingAnalysis(ArrayDicom, dx, dy) print("distance", distance) else: list_title.append(title) tmp_array = dataset.pixel_array tmp_array = u.norm01(tmp_array) ArrayDicom = np.dstack((ArrayDicom, tmp_array)) k = k + 1 # After we colect all the images we only select g0c90 and g0c270 to calculate the center at g0 k = 0 l = 0 m = 0 n = 0 for i, _ in enumerate(list_title): if list_title[i][0] == "g0" and k == 0: k = k + 1 # height = np.shape(ArrayDicom[:, :, i])[0] # width = np.shape(ArrayDicom[:, :, i])[1] fig_g0c90, ax_g0c90, center_g0c90 = full_imageProcess( ArrayDicom[:, :, i], dx, dy, list_title[i] ) center_g0[0] = ( center_g0[0][0] + center_g0c90[0][0], center_g0[0][1] + center_g0c90[0][1], ) list_figs.append(fig_g0c90) # we plot always the image at g0c90 if list_title[i][0] == "g0" and k != 0: k = k + 1 center_g0c270 = full_imageProcess_noGraph(ArrayDicom[:, :, i]) center_g0[0] = ( center_g0[0][0] + center_g0c270[0][0], center_g0[0][1] + center_g0c270[0][1], ) for i, _ in enumerate(list_title): if list_title[i][0] == "g90": l = l + 1 center_g90c = full_imageProcess_noGraph(ArrayDicom[:, :, i]) center_g90[0] = ( center_g90[0][0] + center_g90c[0][0], center_g90[0][1] + center_g90c[0][1], ) if list_title[i][0] == "g180": m = m + 1 center_g180c = full_imageProcess_noGraph(ArrayDicom[:, :, i]) center_g180[0] = ( center_g180[0][0] + center_g180c[0][0], center_g180[0][1] + center_g180c[0][1], ) if list_title[i][0] == "g270": n = n + 1 center_g270c = full_imageProcess_noGraph(ArrayDicom[:, :, i]) center_g270[0] = ( center_g270[0][0] + center_g270c[0][0], center_g270[0][1] + center_g270c[0][1], ) print(k, "images used for g0") print(l, "images used for g90") print(m, "images used for g180") print(n, "images used for g270") center_g0[0] = (center_g0[0][0] / k, center_g0[0][1] / k) center_g90[0] = (center_g90[0][0] / l, center_g90[0][1] / l) center_g180[0] = (center_g180[0][0] / m, center_g180[0][1] / m) center_g270[0] = (center_g270[0][0] / n, center_g270[0][1] / n) center.append(center_g0[0]) center.append(center_g90[0]) center.append(center_g180[0]) center.append(center_g270[0]) x_g0, y_g0 = center_g0[0] x_g90, y_g90 = center_g90[0] x_g180, y_g180 = center_g180[0] x_g270, y_g270 = center_g270[0] max_deltax = 0 max_deltay = 0 for i in range(0, len(center)): # pylint: disable = consider-using-enumerate for j in range(i + 1, len(center)): deltax = abs(center[i][0] - center[j][0]) deltay = abs(center[i][1] - center[j][1]) if deltax > max_deltax: max_deltax = deltax if deltay > max_deltay: max_deltay = deltay print("Maximum delta x =", max_deltax * dx, "mm") print("Maximum delta y =", max_deltay * dy, "mm") ax_g0c90.scatter( x_g0 * dx, (ArrayDicom[:, :, i].shape[0] - y_g0) * dy, label="g=0" ) # perfect! ax_g0c90.scatter( x_g90 * dx, (ArrayDicom[:, :, i].shape[0] - y_g90) * dy, label="g=90" ) # perfect! ax_g0c90.scatter( x_g180 * dx, (ArrayDicom[:, :, i].shape[0] - y_g180) * dy, label="g=180" ) # perfect! ax_g0c90.scatter( x_g270 * dx, (ArrayDicom[:, :, i].shape[0] - y_g270) * dy, label="g=270" ) # perfect! # print(list_title[i], "center_g0c90=", center_g0c90, "center=", center, dist) ax_g0c90.legend(bbox_to_anchor=(1.25, 1), loc=2, borderaxespad=0.0) # adding a horizontal arrow # ax.annotate( # s="", # xy=(point_sel[imax, 0] * dx, point_sel[imax, 1] * dy), # xytext=(point_sel[imin, 0] * dx, point_sel[imin, 1] * dy), # arrowprops=dict(arrowstyle="<->", color="r"), # ) # example on how to plot a double headed arrow ax_g0c90.text( (width // 2.15) * dx, (height // 2.15) * dy, "Maximum delta x =" + str(round(max_deltax * dx, 4)) + " mm", rotation=0, fontsize=14, color="r", ) ax_g0c90.text( (width // 2.15) * dx, (height // 2.18) * dy, "Maximum delta y =" + str(round(max_deltay * dy, 4)) + " mm", rotation=0, fontsize=14, color="r", ) if platform == "linux": output_flnm = ( dirname + "/" + now.strftime("%d-%m-%Y_%H:%M_") + dataset[0x0008, 0x1010].value + "_Graticule_report.pdf" ) elif platform == "win32": output_flnm = dataset[0x0008, 0x1010].value + "_Graticule_report.pdf" # with PdfPages(directory + "/" + output_flnm) as pdf: with PdfPages(output_flnm) as pdf: # Page = plt.figure(figsize=(4, 5)) # Page.text(0, 0.9, 'Report', size=18) # Page.text(0, 0.9, "Distance=" + str(distance)+ " cm", size=14) pdf.savefig(fig_g0c90) pdf.savefig(fig_scaling) # exit(0) sys.exit(0)