def visualize_in_scan(self, verbose=True): """ Interactive visualization of the slices of the scan along with scan and annotation information. The visualization begins (but is not limited to) the first slice where the nodule occurs (according to the annotation). Contours are plotted atop the images for visualization and can be toggled on and off. """ images = self.scan.load_all_dicom_images(verbose) # Preload contours and sort them by z pos. contours = sorted(self.contours, key=lambda c: c.image_z_position) fnames = self.scan.sorted_dicom_file_names.split(',') index_of_contour = [fnames.index(c.dicom_file_name) for c in contours] fig = plt.figure(figsize=(16,8)) min_slice = min(index_of_contour) max_slice = max(index_of_contour) current_slice = min_slice ax_image = fig.add_axes([0.5,0.0,0.5,1.0]) img = ax_image.imshow(images[current_slice].pixel_array, cmap=plt.cm.gray) contour_lines = [] # We draw all the contours initally and set the visibility # to False. This works better than trying create and destroy # plots every time we update the image. for i,c in enumerate(contours): arr = c.to_matrix() cc, = ax_image.plot(arr[:,0], arr[:,1], '-r') cc.set_visible(i==0) # Set the first contour visible. contour_lines.append( cc ) ax_image.set_xlim(-0.5,511.5); ax_image.set_ylim(511.5,-0.5) ax_image.axis('off') # Add the scan info table ax_scan_info = fig.add_axes([0.1, 0.8, 0.3, 0.1]) ax_scan_info.set_facecolor('w') scan_info_table = ax_scan_info.table( cellText=[ ['Patient ID:', self.scan.patient_id], ['Slice thickness:', '%.3f mm' % self.scan.slice_thickness], ['Pixel spacing:', '%.3f mm'%self.scan.pixel_spacing] ], loc='center', cellLoc='left' ) # Remove the cell borders. # It Seems like there should be an easier way to do this... for cell in scan_info_table.properties()['child_artists']: cell.set_color('w') ax_scan_info.set_title('Scan Info') ax_scan_info.set_xticks([]) ax_scan_info.set_yticks([]) # Add annotations / features table. ax_annotation_info = fig.add_axes([0.1, 0.45, 0.3, 0.25]) ax_annotation_info.set_facecolor('w') # Create the rows to be displayed in the annotations table. cell_text = [] for f in feature_names: row = [] fname = f.capitalize() if fname.startswith('Int'): fname = 'InternalStructure' row.append(fname) row.append(getattr(self,fname)()) row.append(getattr(self,f)) cell_text.append(row) annotation_info_table = ax_annotation_info.table( cellText=cell_text, loc='center', cellLoc='left', colWidths=[0.45,0.45,0.1] ) # Again, remove cell borders. for cell in annotation_info_table.properties()['child_artists']: cell.set_color('w') ax_annotation_info.set_title('Annotation Info') ax_annotation_info.set_xticks([]) ax_annotation_info.set_yticks([]) # Add the checkbox for turning contours on / off. ax_contour_checkbox = fig.add_axes([0.1, 0.25, 0.1, 0.15]) ax_contour_checkbox.set_facecolor('w') contour_checkbox = CheckButtons(ax_contour_checkbox, ('Show Contours',), (True,)) contour_checkbox.is_checked = True # Add the widgets. ax_slice = fig.add_axes([0.1, 0.1, 0.3, 0.05]) ax_slice.set_facecolor('w') txt = 'Z: %.3f'%float(images[current_slice].ImagePositionPatient[-1]) sslice = Slider(ax_slice, txt, 0, len(images)-1, valinit=current_slice, valfmt=u'Slice: %d') def update(_): # Update image itself. current_slice = int(sslice.val) img.set_data(images[current_slice].pixel_array) txt='Z: %.3f'%float(images[current_slice].ImagePositionPatient[-1]) sslice.label.set_text(txt) if contour_checkbox.is_checked: for i,c in enumerate(contour_lines): flag = (index_of_contour[i] == current_slice) flag = flag and (current_slice >= min_slice) flag = flag and (current_slice <= max_slice) # Set contour visible if flag is True. c.set_visible(flag) else: for c in contour_lines: c.set_visible(False) fig.canvas.draw_idle() def update_contours(_): contour_checkbox.is_checked = not contour_checkbox.is_checked update(None) # update requires an argument. sslice.on_changed(update) contour_checkbox.on_clicked(update_contours) plt.show()
def visualize_in_scan(self, verbose=True): """ Interactive visualization of the slices of the scan along with scan and annotation information. The visualization begins (but is not limited to) the first slice where the nodule occurs (according to the annotation). Contours are plotted atop the images for visualization and can be toggled on and off. """ images = self.scan.load_all_dicom_images(verbose) # Preload contours and sort them by z pos. contours = sorted(self.contours, key=lambda c: c.image_z_position) fnames = self.scan.sorted_dicom_file_names.split(',') index_of_contour = [fnames.index(c.dicom_file_name) for c in contours] fig = plt.figure(figsize=(16,8)) min_slice = min(index_of_contour) max_slice = max(index_of_contour) current_slice = min_slice ax_image = fig.add_axes([0.5,0.0,0.5,1.0]) img = ax_image.imshow(images[current_slice].pixel_array, cmap=plt.cm.gray) contour_lines = [] # We draw all the contours initally and set the visibility # to False. This works better than trying create and destroy # plots every time we update the image. for i,c in enumerate(contours): arr = c.to_matrix() cc, = ax_image.plot(arr[:,0], arr[:,1], '-r') cc.set_visible(i==0) # Set the first contour visible. contour_lines.append( cc ) ax_image.set_xlim(-0.5,511.5); ax_image.set_ylim(511.5,-0.5) ax_image.axis('off') # Add the scan info table ax_scan_info = fig.add_axes([0.1, 0.8, 0.3, 0.1]) ax_scan_info.set_axis_bgcolor('w') scan_info_table = ax_scan_info.table( cellText=[ ['Patient ID:', self.scan.patient_id], ['Slice thickness:', '%.3f mm' % self.scan.slice_thickness], ['Pixel spacing:', '%.3f mm'%self.scan.pixel_spacing] ], loc='center', cellLoc='left' ) # Remove the cell borders. # It Seems like there should be an easier way to do this... for cell in scan_info_table.properties()['child_artists']: cell.set_color('w') ax_scan_info.set_title('Scan Info') ax_scan_info.set_xticks([]) ax_scan_info.set_yticks([]) # Add annotations / characteristics table. ax_annotation_info = fig.add_axes([0.1, 0.45, 0.3, 0.25]) ax_annotation_info.set_axis_bgcolor('w') # Create the rows to be displayed in the annotations table. cell_text = [] for c in _all_characteristics_: row = [] cname = c.capitalize() if cname.startswith('Int'): cname = 'InternalStructure' row.append(cname) row.append(getattr(self,cname)()) row.append(getattr(self,c)) cell_text.append(row) annotation_info_table = ax_annotation_info.table( cellText=cell_text, loc='center', cellLoc='left', colWidths=[0.45,0.45,0.1] ) # Again, remove cell borders. for cell in annotation_info_table.properties()['child_artists']: cell.set_color('w') ax_annotation_info.set_title('Annotation Info') ax_annotation_info.set_xticks([]) ax_annotation_info.set_yticks([]) # Add the checkbox for turning contours on / off. ax_contour_checkbox = fig.add_axes([0.1, 0.25, 0.1, 0.15]) ax_contour_checkbox.set_axis_bgcolor('w') contour_checkbox = CheckButtons(ax_contour_checkbox, ('Show Contours',), (True,)) contour_checkbox.is_checked = True # Add the widgets. ax_slice = fig.add_axes([0.1, 0.1, 0.3, 0.05]) ax_slice.set_axis_bgcolor('w') txt = 'Z: %.3f'%float(images[current_slice].ImagePositionPatient[-1]) sslice = Slider(ax_slice, txt, 0, len(images)-1, valinit=current_slice, valfmt=u'Slice: %d') def update(_): # Update image itself. current_slice = int(sslice.val) img.set_data(images[current_slice].pixel_array) txt='Z: %.3f'%float(images[current_slice].ImagePositionPatient[-1]) sslice.label.set_text(txt) if contour_checkbox.is_checked: for i,c in enumerate(contour_lines): flag = (index_of_contour[i] == current_slice) flag = flag and (current_slice >= min_slice) flag = flag and (current_slice <= max_slice) # Set contour visible if flag is True. c.set_visible(flag) else: for c in contour_lines: c.set_visible(False) fig.canvas.draw_idle() def update_contours(_): contour_checkbox.is_checked = not contour_checkbox.is_checked update(None) # update requires an argument. sslice.on_changed(update) contour_checkbox.on_clicked(update_contours) plt.show()