def id_lagrangian_like(input_vf): """ :param input_vf: input vector field. :return: corresponding identity grid position in Eulerian coordinates """ qr.check_is_vf(input_vf) return np.zeros_like(input_vf)
def id_eulerian_like(input_vf): """ :param input_vf: input vector field. :return: corresponding grid position, i.e. the identity vector field sampled in the input_vf grid matrix in Lagrangian coordinates. """ qr.check_is_vf(input_vf) return id_eulerian(qr.get_omega(input_vf), t=input_vf.shape[3])
def compute_jacobian(input_vf, affine=np.eye(4), is_lagrangian=False): """ :param input_vf: input vecgor field :param affine: The affine transformation optionally associated to the field. :param is_lagrangian: if the identity matrix should be added to each jacobian matrix See itk documentation: http://www.itk.org/Doxygen/html/classitk_1_1DisplacementFieldJacobianDeterminantFilter.html On the diagonal it possess the sample distances for each dimension. Jacobian matrix at each point of the grid is stored in a vector of size 9 in row major order. """ # TODO It works only for svf (1 time point) - provisional - do with multiple time point d = qr.check_is_vf(input_vf) jacobian = initialise_jacobian(input_vf) dims = [] for i in range(d): dims.append(affine[i, i]) output_data = jacobian.squeeze() for i in range(d): grad = np.gradient(np.squeeze(input_vf[..., i]), *dims) for j in range(d): output_data[..., i * d + j] = grad[j].squeeze() if is_lagrangian: jacobian += matrices.id_matrix_field(input_vf.shape[:d]) return jacobian
def initialise_input(self, input_vf): """ Initialise class variable given an input vf """ self.dimension = qr.check_is_vf(input_vf) self.omega = qr.get_omega(input_vf) self.vf = copy.deepcopy(input_vf) self.phi = np.zeros_like(self.vf)
def initialise_jacobian(input_vf): d = qr.check_is_vf(input_vf) sh = list(input_vf.shape) while len(sh) < 5: sh.extend([1]) sh[-1] = d ** 2 return np.zeros(sh, dtype=np.float64)
def compute_jacobian_determinant(input_vf, is_lagrangian=False): """ :param input_vf: The Field or children whose jacobian we need to compute. :param is_lagrangian: add the identity to the jacobian matrix before the computation of the jacobian determinant. If it is none, it is allocated. Jacobian matrix at each point of the grid is stored in a vector of size 9 in row major order. !! It works only for 1 time point - provisional !! """ d = qr.check_is_vf(input_vf) vf_jacobian = compute_jacobian(input_vf, is_lagrangian=is_lagrangian) sh = list(input_vf.shape) while len(sh) < 5: sh.extend([1]) sh = sh[:-1] sh.extend([d, d]) v = vf_jacobian.reshape(sh) return np.linalg.det(v)
def quiver_3d(svf, flow=None, sample=(1, 1, 1), scale=1): omega_svf = qr.check_is_vf(svf) omega_flow = qr.check_is_vf(flow) np.testing.assert_array_equal(omega_flow, omega_svf) id_field = gen_id.id_eulerian_like(svf) fig = plt.figure() ax = fig.gca(projection='3d') x = id_field[::sample[0], ::sample[1], ::sample[2], 0, 0] y = id_field[::sample[0], ::sample[1], ::sample[2], 0, 1] z = id_field[::sample[0], ::sample[1], ::sample[2], 0, 2] x = x.reshape(np.product(x.shape)) y = y.reshape(np.product(y.shape)) z = z.reshape(np.product(z.shape)) svf_x = svf[::sample[0], ::sample[1], ::sample[2], 0, 0] svf_y = svf[::sample[0], ::sample[1], ::sample[2], 0, 1] svf_z = svf[::sample[0], ::sample[1], ::sample[2], 0, 2] svf_x = svf_x.reshape(np.product(svf_x.shape)) svf_y = svf_y.reshape(np.product(svf_y.shape)) svf_z = svf_z.reshape(np.product(svf_z.shape)) lengths = scale * np.sqrt(svf_x**2 + svf_y**2 + svf_z**2) for x1, y1, z1, u1, v1, w1, l in zip(x, y, z, svf_x, svf_y, svf_z, lengths): ax.quiver(x1, y1, z1, u1, v1, w1, pivot='tail', length=l, color='r', linewidths=0.1) if flow is not None: flow_x = flow[::sample[0], ::sample[1], ::sample[2], 0, 0] flow_y = flow[::sample[0], ::sample[1], ::sample[2], 0, 1] flow_z = flow[::sample[0], ::sample[1], ::sample[2], 0, 2] flow_x = flow_x.reshape(np.product(flow_x.shape)) flow_y = flow_y.reshape(np.product(flow_y.shape)) flow_z = flow_z.reshape(np.product(flow_z.shape)) lengthsflow = scale * np.sqrt(svf_x**2 + svf_y**2 + svf_z**2) for x1, y1, z1, u1, v1, w1, l in zip(x, y, z, flow_x, flow_y, flow_z, lengthsflow): ax.quiver(x1, y1, z1, u1, v1, w1, pivot='tail', length=l, color='b', linewidths=0.1)
def see_2_fields(input_obj_0, input_obj_1, anatomical_plane_0='axial', anatomical_plane_1='axial', h_slice_0=0, h_slice_1=0, sample_0=(1, 1), sample_1=(1, 1), window_title_input='quiver 2 screens', title_input_0='Vector field', title_input_1='Vector field', long_title_0=False, long_title_1=False, fig_tag=1, scale_0=1, scale_1=1, subtract_id_0=False, subtract_id_1=False, input_color='b'): """ :param input_obj_0: :param input_obj_1: :param anatomical_plane_0: :param anatomical_plane_1: :param h_slice_0: :param h_slice_1: :param sample_0: :param sample_1: :param window_title_input: :param title_input_0: :param title_input_1: :param long_title_0: :param long_title_1: :param fig_tag: :param scale_0: :param scale_1: :param subtract_id_0: :param subtract_id_1: :param input_color: :return: """ qr.check_is_vf(input_obj_0) qr.check_is_vf(input_obj_1) id_field_0 = gen_id.id_eulerian_like( input_obj_0) # other option is casting with Field() id_field_1 = gen_id.id_eulerian_like(input_obj_1) input_field_0 = copy.deepcopy(input_obj_0) input_field_1 = copy.deepcopy(input_obj_1) if subtract_id_0: input_field_0 -= id_field_0 if subtract_id_1: input_field_1 -= id_field_1 fig = plt.figure(fig_tag) ax0 = fig.add_subplot(121) ax1 = fig.add_subplot(122) fig.canvas.set_window_title(window_title_input) # figure 0 if anatomical_plane_0 == 'axial': ax0.quiver(id_field_0[::sample_0[0], ::sample_0[1], h_slice_0, 0, 0], id_field_0[::sample_0[0], ::sample_0[1], h_slice_0, 0, 1], input_field_0[::sample_0[0], ::sample_0[1], h_slice_0, 0, 0], input_field_0[::sample_0[0], ::sample_0[1], h_slice_0, 0, 1], color=input_color, linewidths=0.01, width=0.03, units='xy', angles='xy', scale=scale_0, scale_units='xy') elif anatomical_plane_0 == 'sagittal': ax0.quiver(id_field_0[::sample_0[0], h_slice_0, ::sample_0[1], 0, 0], id_field_0[::sample_0[0], h_slice_0, ::sample_0[1], 0, 1], input_field_0[::sample_0[0], h_slice_0, ::sample_0[1], 0, 0], input_field_0[::sample_0[0], h_slice_0, ::sample_0[1], 0, 1], color=input_color, linewidths=0.01, width=0.03, units='xy', angles='xy', scale=scale_0, scale_units='xy') elif anatomical_plane_0 == 'coronal': ax0.quiver(id_field_0[h_slice_0, ::sample_0[0], ::sample_0[1], 0, 0], id_field_0[h_slice_0, ::sample_0[0], ::sample_0[1], 0, 1], input_field_0[h_slice_0, ::sample_0[0], ::sample_0[1], 0, 0], input_field_0[h_slice_0, ::sample_0[0], ::sample_0[1], 0, 1], color=input_color, linewidths=0.01, width=0.03, units='xy', angles='xy', scale=scale_0, scale_units='xy') else: raise TypeError( 'anatomical_plane_0 must be axial, sagittal or coronal') if long_title_0: ax0.set_title(title_input_0 + ', ' + str(anatomical_plane_0) + ' plane, slice ' + str(h_slice_0)) else: ax0.set_title(title_input_0) ax0.xaxis.grid(True, linestyle='-', which='major', color='lightgrey', alpha=0.5) ax0.yaxis.grid(True, linestyle='-', which='major', color='lightgrey', alpha=0.5) ax0.set_axisbelow(True) # figure 1 if anatomical_plane_1 == 'axial': ax1.quiver(id_field_1[::sample_1[0], ::sample_1[1], h_slice_1, 0, 0], id_field_1[::sample_1[0], ::sample_1[1], h_slice_1, 0, 1], input_field_1[::sample_1[0], ::sample_1[1], h_slice_1, 0, 0], input_field_1[::sample_1[0], ::sample_1[1], h_slice_1, 0, 1], color=input_color, linewidths=0.01, width=0.03, units='xy', angles='xy', scale=scale_1, scale_units='xy') elif anatomical_plane_1 == 'sagittal': ax1.quiver(id_field_0[::sample_1[0], h_slice_0, ::sample_1[1], 0, 0], id_field_0[::sample_1[0], h_slice_0, ::sample_1[1], 0, 1], input_field_0[::sample_1[0], h_slice_0, ::sample_1[1], 0, 0], input_field_0[::sample_1[0], h_slice_0, ::sample_1[1], 0, 1], color=input_color, linewidths=0.01, width=0.03, units='xy', angles='xy', scale=scale_1, scale_units='xy') elif anatomical_plane_1 == 'coronal': ax1.quiver(id_field_1[h_slice_1, ::sample_1[0], ::sample_1[1], 0, 0], id_field_1[h_slice_1, ::sample_1[0], ::sample_1[1], 0, 1], input_field_1[h_slice_1, ::sample_1[0], ::sample_1[1], 0, 0], input_field_1[h_slice_1, ::sample_1[0], ::sample_1[1], 0, 1], color=input_color, linewidths=0.01, width=0.03, units='xy', angles='xy', scale=scale_1, scale_units='xy') else: raise TypeError( 'anatomical_plane_1 must be axial, sagittal or coronal') if long_title_1: ax1.set_title(title_input_1 + ', ' + str(anatomical_plane_1) + ' plane, slice ' + str(h_slice_1)) else: ax1.set_title(title_input_1) ax1.xaxis.grid(True, linestyle='-', which='major', color='lightgrey', alpha=0.5) ax1.yaxis.grid(True, linestyle='-', which='major', color='lightgrey', alpha=0.5) ax1.set_axisbelow(True) fig.set_tight_layout(True)
def see_field(input_vf, anatomical_plane='axial', h_slice=0, sample=(1, 1), window_title_input='quiver', title_input='2d vector field', long_title=False, fig_tag=1, scale=1, subtract_id=False, input_color='b', annotate=None, annotate_position=(1, 1), width=0.03): qr.check_is_vf(input_vf) id_field = gen_id.id_eulerian_like(input_vf) fig = plt.figure(fig_tag) ax0 = fig.add_subplot(111) fig.canvas.set_window_title(window_title_input) input_field_copy = copy.deepcopy(input_vf) if subtract_id: input_field_copy -= id_field if anatomical_plane == 'axial': ax0.quiver(id_field[::sample[0], ::sample[1], h_slice, 0, 0], id_field[::sample[0], ::sample[1], h_slice, 0, 1], input_field_copy[::sample[0], ::sample[1], h_slice, 0, 0], input_field_copy[::sample[0], ::sample[1], h_slice, 0, 1], color=input_color, linewidths=0.01, width=width, scale=scale, scale_units='xy', units='xy', angles='xy') ax0.set_xlabel('x') ax0.set_ylabel('y') elif anatomical_plane == 'sagittal': ax0.quiver(id_field[::sample[0], h_slice, ::sample[1], 0, 0], id_field[::sample[0], h_slice, ::sample[1], 0, 1], input_field_copy[::sample[0], h_slice, ::sample[1], 0, 0], input_field_copy[::sample[0], h_slice, ::sample[1], 0, 1], color=input_color, linewidths=0.01, width=width, units='xy', angles='xy', scale=scale, scale_units='xy') elif anatomical_plane == 'coronal': ax0.quiver(id_field[h_slice, ::sample[0], ::sample[1], 0, 0], id_field[h_slice, ::sample[0], ::sample[1], 0, 1], input_field_copy[h_slice, ::sample[0], ::sample[1], 0, 0], input_field_copy[h_slice, ::sample[0], ::sample[1], 0, 1], color=input_color, linewidths=0.01, width=width, units='xy', angles='xy', scale=scale, scale_units='xy') else: raise TypeError('Anatomical_plane must be axial, sagittal or coronal') ax0.xaxis.grid(True, linestyle='-', which='major', color='lightgrey', alpha=0.5) ax0.yaxis.grid(True, linestyle='-', which='major', color='lightgrey', alpha=0.5) ax0.set_axisbelow(True) if long_title: ax0.set_title(title_input + ', ' + str(anatomical_plane) + ' plane, slice ' + str(h_slice)) else: ax0.set_title(title_input) if annotate is not None: ax0.text(annotate_position[0], annotate_position[1], annotate) plt.axes().set_aspect('equal', 'datalim') return fig
def test_check_is_vf_ok(): assert qr.check_is_vf(np.zeros([10, 10, 10, 1, 3])) == 3 assert qr.check_is_vf(np.zeros([10, 10, 10, 1, 9])) == 3 assert qr.check_is_vf(np.zeros([10, 10, 1, 1, 2])) == 2 assert qr.check_is_vf(np.zeros([10, 10, 1, 1, 4])) == 2
def test_check_is_vf_mismatch_omega_last_dimension(): with assert_raises(IOError): qr.check_is_vf(np.zeros([10, 10, 10, 1, 7]))
def test_check_is_vf_wrong_input_len(): with assert_raises(IOError): qr.check_is_vf(np.array([1, 2, 3]))
def test_check_is_vf_wrong_input(): with assert_raises(IOError): qr.check_is_vf([1, 2, 3])
def see_overlay_of_n_fields_and_flow(list_of_obj, list_of_integral_curves, list_of_alpha_for_obj=None, alpha_for_integral_curves=None, anatomical_plane='axial', h_slice=0, sample=(1, 1), window_title_input='quiver', title_input='2d vector field', long_title=False, fig_tag=1, scale=1, subtract_id=None, input_color=('r', 'b'), input_label=None, see_tips=False): fig = plt.figure(fig_tag) ax0 = fig.add_subplot(111) fig.canvas.set_window_title(window_title_input) if subtract_id is None: subtract_id = [ False, ] * len(list_of_obj) if list_of_alpha_for_obj is None: list_of_alpha_for_obj = [ 0.8, ] * len(list_of_obj) if alpha_for_integral_curves is None: alpha_for_integral_curves = 0.8 for num_obj, input_obj in enumerate(list_of_obj): if input_obj is not None: assert qr.check_is_vf(input_obj) == 2 id_field = gen_id.id_eulerian_like(input_obj) input_field_copy = copy.deepcopy(input_obj) if subtract_id[num_obj]: input_field_copy -= id_field if anatomical_plane == 'axial': q = ax0.quiver(id_field[::sample[0], ::sample[1], h_slice, 0, 0], id_field[::sample[0], ::sample[1], h_slice, 0, 1], input_field_copy[::sample[0], ::sample[1], h_slice, 0, 0], input_field_copy[::sample[0], ::sample[1], h_slice, 0, 1], color=input_color[num_obj], linewidths=0.01, width=0.03, scale=scale, scale_units='xy', units='xy', angles='xy', alpha=list_of_alpha_for_obj[num_obj]) elif anatomical_plane == 'sagittal': q = ax0.quiver(id_field[::sample[0], h_slice, ::sample[1], 0, 0], id_field[::sample[0], h_slice, ::sample[1], 0, 1], input_field_copy[::sample[0], h_slice, ::sample[1], 0, 0], input_field_copy[::sample[0], h_slice, ::sample[1], 0, 1], color=input_color[num_obj], linewidths=1, units='xy', angles='xy', scale=scale, scale_units='xy', alpha=list_of_alpha_for_obj[num_obj]) elif anatomical_plane == 'coronal': q = ax0.quiver(id_field[h_slice, ::sample[0], ::sample[1], 0, 0], id_field[h_slice, ::sample[0], ::sample[1], 0, 1], input_field_copy[h_slice, ::sample[0], ::sample[1], 0, 0], input_field_copy[h_slice, ::sample[0], ::sample[1], 0, 1], color=input_color[num_obj], linewidths=1, units='xy', angles='xy', scale=scale, scale_units='xy', alpha=list_of_alpha_for_obj[num_obj]) else: raise TypeError( 'Anatomical_plane must be axial, sagittal or coronal') # add the integral curves: for fl in list_of_integral_curves: ax0.plot(fl[:, 0], fl[:, 1], color='m', lw=1, alpha=alpha_for_integral_curves) if see_tips: ax0.plot(fl[0, 0], fl[0, 1], 'go', alpha=0.3) ax0.plot(fl[fl.shape[0] - 1, 0], fl[fl.shape[0] - 1, 1], 'mo', alpha=0.5) if input_label is not None: ax0.quiverkey(q, 1.2, 0.515, 2, input_label[num_obj], coordinates='data') ax0.xaxis.grid(True, linestyle='-', which='major', color='lightgrey', alpha=0.5) ax0.yaxis.grid(True, linestyle='-', which='major', color='lightgrey', alpha=0.5) ax0.set_axisbelow(True) if long_title: ax0.set_title(title_input + ', ' + str(anatomical_plane) + ' plane, slice ' + str(h_slice)) else: ax0.set_title(title_input) fig.set_tight_layout(True)
def image_quiver_image(image_1, input_vf, image_2, fig_tag=5, input_fig_size=(15, 5), window_title_input='triptych', h_slice=1, sampling_svf=(1, 1), anatomical_plane='axial', subtract_id=False, scale=1, input_color='r', line_arrowwidths=0.01, arrowwidths=0.5, integral_curves=(), curve_width=0.5, show_overlay=False): pyplot.cla() fig = pyplot.figure(fig_tag, figsize=input_fig_size, dpi=100, facecolor='w', edgecolor='k') fig.subplots_adjust(left=0.04, right=0.96, top=0.92, bottom=0.08) font = { 'family': 'serif', 'color': 'darkblue', 'weight': 'normal', 'size': 12 } fig.canvas.set_window_title(window_title_input) # First axis on the left ax_1 = pyplot.subplot(131) ax_1.imshow(image_1, cmap='Greys', interpolation='nearest', origin='lower') # ax_1.axes.xaxis.set_ticklabels([]) # ax_1.axes.yaxis.set_ticklabels([]) ax_1.set_xlabel('Input image', fontdict=font) ax_1.set_aspect('equal') # Central vector field ax_2 = pyplot.subplot(132) # add background warped if show_overlay: ax_2.imshow(image_2, cmap='Greys', interpolation='none', origin='lower') # add integral curves if any for int_curve in integral_curves: ax_2.plot(int_curve[:, 0], int_curve[:, 1], color='b', lw=curve_width) ax_2.plot(int_curve[int_curve.shape[0] - 1, 0], int_curve[int_curve.shape[0] - 1, 1], 'bo', alpha=0.5) qr.check_is_vf(input_vf) id_field = gen_id.id_eulerian_like(input_vf) input_field_copy = copy.deepcopy(input_vf) if subtract_id: input_field_copy -= id_field if anatomical_plane == 'axial': ax_2.quiver(id_field[::sampling_svf[0], ::sampling_svf[1], h_slice, 0, 0], id_field[::sampling_svf[0], ::sampling_svf[1], h_slice, 0, 1], input_field_copy[::sampling_svf[0], ::sampling_svf[1], h_slice, 0, 0], input_field_copy[::sampling_svf[0], ::sampling_svf[1], h_slice, 0, 1], color=input_color, linewidths=line_arrowwidths, width=arrowwidths, scale=scale, scale_units='xy', units='xy', angles='xy') elif anatomical_plane == 'sagittal': ax_2.quiver(id_field[::sampling_svf[0], h_slice, ::sampling_svf[1], 0, 0], id_field[::sampling_svf[0], h_slice, ::sampling_svf[1], 0, 1], input_field_copy[::sampling_svf[0], h_slice, ::sampling_svf[1], 0, 0], input_field_copy[::sampling_svf[0], h_slice, ::sampling_svf[1], 0, 1], color=input_color, linewidths=line_arrowwidths, width=arrowwidths, units='xy', angles='xy', scale=scale, scale_units='xy') elif anatomical_plane == 'coronal': ax_2.quiver( id_field[h_slice, ::sampling_svf[0], ::sampling_svf[1], 0, 0], id_field[h_slice, ::sampling_svf[0], ::sampling_svf[1], 0, 1], input_field_copy[h_slice, ::sampling_svf[0], ::sampling_svf[1], 0, 0], input_field_copy[h_slice, ::sampling_svf[0], ::sampling_svf[1], 0, 1], color=input_color, linewidths=line_arrowwidths, width=arrowwidths, units='xy', angles='xy', scale=scale, scale_units='xy') else: raise TypeError('Anatomical_plane must be axial, sagittal or coronal') ax_2.set_xlim(0, image_1.shape[0]) ax_2.set_ylim(0, image_1.shape[1]) # ax_2.set_xlabel('x') # ax_2.set_ylabel('y') # ax_2.axes.xaxis.set_ticklabels([]) # ax_2.axes.yaxis.set_ticklabels([]) ax_2.set_xlabel('Transformation', fontdict=font) ax_2.set_aspect('equal') # Third axis: ax_3 = pyplot.subplot(133) ax_3.imshow(image_2, cmap='Greys', interpolation='none', origin='lower') # ax_3.axes.xaxis.set_ticklabels([]) # ax_3.axes.yaxis.set_ticklabels([]) ax_3.set_xlabel('Transformed image', fontdict=font) ax_3.set_aspect('equal') fig.set_tight_layout(True) return fig