def test_create_stenosis(surface_paths): # Get default input common_input = read_command_line_area(surface_paths[0], surface_paths[1]) # Get region points base_path = get_path_names(common_input['input_filepath']) centerline = extract_single_line(read_polydata(base_path + "_centerline.vtp"), 0) n = centerline.GetNumberOfPoints() region_point = list(centerline.GetPoint(int(n * 0.4))) # Change default input common_input.update(dict(region_of_interest="commandline", region_points=region_point, method="stenosis", size=2.0, percentage=50)) # Create a stenosis manipulate_area(**common_input) # Import old area and splined centerline for region of interest base_path = get_path_names(common_input['input_filepath']) centerline_spline_path = base_path + "_centerline_spline.vtp" centerline_area_spline_path = base_path + "_centerline_area_spline.vtp" new_surface_path = common_input["output_filepath"] surface = read_polydata(new_surface_path) centerline_area = read_polydata(centerline_area_spline_path) centerline_spline = read_polydata(centerline_spline_path) new_centerline_area, _ = vmtk_compute_centerline_sections(surface, centerline_spline) old_area = get_point_data_array("CenterlineSectionArea", centerline_area) new_area = get_point_data_array("CenterlineSectionArea", new_centerline_area) # Check if there is a 50 % narrowing assert abs((np.sqrt(new_area / old_area)).min() - 0.5) < 0.05
def test_automated_landmarking(surface_paths, algorithm): # Get region points base_path = get_path_names(surface_paths[0]) relevant_outlets = [35.8, 59.8, 39.7, 76.8, 54.7, 53.2] ica_centerline = extract_ica_centerline(base_path, surface_paths[0], 0.1, relevant_outlets=relevant_outlets) landmark_input = dict(centerline=ica_centerline, base_path=base_path, approximation_method="spline", algorithm=algorithm, resampling_step=0.1, smooth_line=False, nknots=8, iterations=100) if algorithm == "bogunovic": landmark_input.update(smoothing_factor=1.0, coronal_axis='z') landmarks = landmarking_bogunovic(**landmark_input) assert len(landmarks) == 4 if algorithm == "piccinelli": landmark_input.update(smoothing_factor_torsion=1.0, smoothing_factor_curv=1.0) landmarks = landmarking_piccinelli(**landmark_input) assert len(landmarks) > 0
def test_inflation_and_deflation_of_area(surface_paths, percentage): # Get default input common_input = read_command_line_area(surface_paths[0], surface_paths[1]) # Change the default input common_input.update(dict(method="area", region_of_interest="first_line", percentage=percentage, smooth=False)) # Perform area manipulation manipulate_area(**common_input) # Import old area and splined centerline for region of interest base_path = get_path_names(common_input['input_filepath']) centerline_spline_path = base_path + "_centerline_spline.vtp" centerline_area_spline_path = base_path + "_centerline_area_spline.vtp" surface = read_polydata(common_input["output_filepath"]) centerline_area = read_polydata(centerline_area_spline_path) centerline_spline = read_polydata(centerline_spline_path) new_centerline_area, _ = vmtk_compute_centerline_sections(surface, centerline_spline) old_area = get_point_data_array("CenterlineSectionArea", centerline_area) new_area = get_point_data_array("CenterlineSectionArea", new_centerline_area) # Exclude first 5 % old_area = old_area[int(0.1 * old_area.shape[0]):] new_area = new_area[int(0.1 * new_area.shape[0]):] # Change in radius ratio = np.sqrt(new_area / old_area) # Check if the altered area is equal has change according to percentage assert np.mean(np.abs(ratio - (1 + percentage * 0.01))) < 0.05
def test_siphon(surface_paths, alpha, beta): # Set problem specific parameters common_input = read_command_line_bend(surface_paths[0], surface_paths[1]) common_input.update( dict(alpha=alpha, beta=beta, region_of_interest="commandline", region_points=[ 44.17085266113281, 38.514854431152344, 41.20818328857422, 43.242130279541016, 42.68572235107422, 38.65191650390625 ])) # Perform manipulation manipulate_bend(**common_input) # Compute angle base_path = get_path_names(common_input['input_filepath']) new_centerlines_path = base_path + "_centerlines_alpha_%s_beta_%s.vtp" % ( alpha, beta) new_centerlines = read_polydata(new_centerlines_path) angle_new, angle_original = compute_angle( common_input["input_filepath"], alpha, beta, "plane", new_centerlines, region_of_interest=common_input["region_of_interest"], region_points=common_input["region_points"]) if alpha < 0 and beta == 0 or beta > 0 and alpha == 0: assert angle_original < angle_new elif alpha > 0 and beta == 0 or beta < 0 and alpha == 0: assert angle_original > angle_new else: assert angle_original > angle_new
def test_manipulate_branch_translation_and_polar_rotation(surface_paths): # Get default input common_input = read_command_line_branch(surface_paths[0], surface_paths[1]) # Arbitrary branch in model C0001 branch_number = 0 # No rotation around new surface normal vector azimuth_angle0 = 0 # New location of branch new_branch_location = (47.0, 27.8, 54.4) # Branch translation method translation_method = 'commandline' # Change default input common_input.update( dict(branch_to_manipulate_number=branch_number, branch_location=new_branch_location, translation_method=translation_method)) # Run without rotation around surface normal common_input.update(dict(azimuth_angle=azimuth_angle0)) # Run area variation manipulate_branch(**common_input) # Set file paths base_path = get_path_names(common_input['input_filepath']) old_centerlines_path = base_path + "_centerline.vtp" new_centerlines_path = base_path + "_centerline_moved.vtp" # Read centerlines old_centerlines = read_polydata(old_centerlines_path) old_centerlines = [extract_single_line(old_centerlines, i) for i in range(old_centerlines.GetNumberOfLines())] new_centerlines0 = read_polydata(new_centerlines_path) new_centerlines0 = [extract_single_line(new_centerlines0, i) for i in range(new_centerlines0.GetNumberOfLines())] # Perform same manipulation WITH rotation around new surface normal. azimuth_angle1 = np.pi common_input.update(dict(azimuth_angle=azimuth_angle1)) # Run manipulate branch manipulate_branch(**common_input) # Read centerlines new_centerlines_path = base_path + "_centerline_moved_and_rotated.vtp" new_centerlines1 = read_polydata(new_centerlines_path) new_centerlines1 = [extract_single_line(new_centerlines1, i) for i in range(new_centerlines1.GetNumberOfLines())] # Compare end point of all centerlines unchanged_centerlines = compare_end_points(new_centerlines0, new_centerlines1) unchanged_centerlines0 = compare_end_points(new_centerlines0, old_centerlines) unchanged_centerlines1 = compare_end_points(new_centerlines1, old_centerlines) assert len(unchanged_centerlines) < len(old_centerlines) assert len(unchanged_centerlines0) < len(old_centerlines) assert len(unchanged_centerlines1) < len(old_centerlines)
def test_area_linear(surface_paths): # Get default input common_input = read_command_line_area(surface_paths[0], surface_paths[1]) # Set region points base_path = get_path_names(common_input['input_filepath']) centerline = extract_single_line(read_polydata(base_path + "_centerline.vtp"), 0) n = centerline.GetNumberOfPoints() region_points = list(centerline.GetPoint(int(n * 0.3))) + list(centerline.GetPoint(int(n * 0.4))) # Change default input common_input.update(dict(region_of_interest="commandline", region_points=region_points, method="linear", smooth=False, size=1, percentage=50)) # Run area variation manipulate_area(**common_input) # Set file paths base_path = get_path_names(common_input['input_filepath']) centerline_spline_path = base_path + "_centerline_spline.vtp" new_surface_path = common_input["output_filepath"] # Read data, and get new area surface = read_polydata(new_surface_path) centerline_spline = read_polydata(centerline_spline_path) new_centerline_area, _ = vmtk_compute_centerline_sections(surface, centerline_spline) length = get_curvilinear_coordinate(centerline_spline) new_area = get_point_data_array("CenterlineSectionArea", new_centerline_area) linear_change = new_area[0] + (new_area[-1] - new_area[0]) * (length / length.max()) # Check if the new area is within 2 % of the expected value assert (np.abs(new_area[:, 0] - linear_change) / linear_change).max() < 0.02
def test_decrease_curvature(surface_paths, smooth_line): # Get default inputs common_input = read_command_line_curvature(surface_paths[0], surface_paths[1]) # Get region points base_path = get_path_names(common_input["input_filepath"]) centerline = extract_single_line(read_polydata(base_path + "_centerline.vtp"), 1) n = centerline.GetNumberOfPoints() region_points = list(centerline.GetPoint(int(n * 0.1))) + list(centerline.GetPoint(int(n * 0.4))) # Set problem specific parameters common_input.update(dict(smooth_factor_line=1.5, iterations=200, region_of_interest="commandline", region_points=region_points, smooth_line=smooth_line)) # Manipulate surface manipulate_curvature(**common_input) # Select and compare altered region p1 = np.asarray(region_points[:3]) p2 = np.asarray(region_points[3:]) old_centerlines_path = base_path + "_centerline.vtp" old_centerlines = read_polydata(old_centerlines_path) old_locator = get_vtk_point_locator(extract_single_line(old_centerlines, 0)) old_id1 = old_locator.FindClosestPoint(p1) old_id2 = old_locator.FindClosestPoint(p2) old_centerline = extract_single_line(old_centerlines, 0, start_id=old_id1, end_id=old_id2) direction = "smoothed" if smooth_line else "extended" new_centerlines_path = base_path + "_centerline_new_%s.vtp" % direction new_centerlines = read_polydata(new_centerlines_path) new_locator = get_vtk_point_locator(extract_single_line(new_centerlines, 0)) new_id1 = new_locator.FindClosestPoint(p1) new_id2 = new_locator.FindClosestPoint(p2) new_centerline = extract_single_line(new_centerlines, 0, start_id=new_id1, end_id=new_id2) # Comute curvature and assert _, old_curvature = compute_discrete_derivatives(old_centerline, neigh=20) _, new_curvature = compute_discrete_derivatives(new_centerline, neigh=20) old_mean_curv = np.mean(old_curvature) new_mean_curv = np.mean(new_curvature) if smooth_line: assert old_mean_curv > new_mean_curv else: assert old_mean_curv < new_mean_curv
def test_area_variation(ratio, surface_paths): # Get default input common_input = read_command_line_area(surface_paths[0], surface_paths[1]) # Set region points base_path = get_path_names(common_input['input_filepath']) centerline = extract_single_line(read_polydata(base_path + "_centerline.vtp"), 0) n = centerline.GetNumberOfPoints() region_points = list(centerline.GetPoint(int(n * 0.05))) + list(centerline.GetPoint(int(n * 0.5))) # Change default input common_input.update(dict(method="variation", smooth=False, region_of_interest="commandline", region_points=region_points, ratio=ratio, beta=None)) # Run area variation manipulate_area(**common_input) # Set file paths base_path = get_path_names(common_input['input_filepath']) centerline_spline_path = base_path + "_centerline_spline.vtp" new_surface_path = common_input["output_filepath"] # Read data, and get new area surface = read_polydata(new_surface_path) centerline_spline = read_polydata(centerline_spline_path) new_centerline_area, _ = vmtk_compute_centerline_sections(surface, centerline_spline) new_area = get_point_data_array("CenterlineSectionArea", new_centerline_area) # Check if the new ratio holds assert abs(ratio - new_area.max() / new_area.min()) < 0.15
def test_manipulate_branch_translation(surface_paths): # Get default input common_input = read_command_line_branch(surface_paths[0], surface_paths[1]) # Opthalmic artery in model C0001 branch_number = 2 # No rotation around new surface normal vector azimuth_angle = 0 # No rotation around new surface 'tangent' vector polar_angle = 0 # New location of branch new_branch_location = (45.7, 37.6, 42.5) # Branch translation method translation_method = 'commandline' # Change default input common_input.update( dict(polar_angle=polar_angle, branch_to_manipulate_number=branch_number, branch_location=new_branch_location, translation_method=translation_method, azimuth_angle=azimuth_angle)) # Run manipulate branch manipulate_branch(**common_input) # Set file paths base_path = get_path_names(common_input['input_filepath']) old_centerlines_path = base_path + "_centerline.vtp" new_centerlines_path = base_path + "_centerline_moved.vtp" # Read data, and get new area old_centerlines = read_polydata(old_centerlines_path) new_centerlines = read_polydata(new_centerlines_path) old_centerlines = [extract_single_line(old_centerlines, i) for i in range(old_centerlines.GetNumberOfLines())] new_centerlines = [extract_single_line(new_centerlines, i) for i in range(new_centerlines.GetNumberOfLines())] untouched_centerlines = compare_end_points(old_centerlines, new_centerlines) assert len(untouched_centerlines) < len(new_centerlines)
def test_manipulate_branch_azimuthal_rotation(surface_paths): # Get default input common_input = read_command_line_branch(surface_paths[0], surface_paths[1]) # Arbitrary branch in model C0001 branch_number = 2 # No rotation around new surface normal vector azimuth_angle = np.pi # Branch translation method translation_method = 'no_translation' # Change default input common_input.update( dict(branch_to_manipulate_number=branch_number, translation_method=translation_method)) # Run with only rotation around original surface normal common_input.update(dict(azimuth_angle=azimuth_angle)) # Run manipulate branch manipulate_branch(**common_input) # Set file paths base_path = get_path_names(common_input['input_filepath']) old_centerlines_path = base_path + "_centerline.vtp" new_centerlines_path = base_path + "_centerline_rotated.vtp" # Read centerlines old_centerlines = read_polydata(old_centerlines_path) old_centerlines = [extract_single_line(old_centerlines, i) for i in range(old_centerlines.GetNumberOfLines())] new_centerlines = read_polydata(new_centerlines_path) new_centerlines = [extract_single_line(new_centerlines, i) for i in range(new_centerlines.GetNumberOfLines())] # Compare end point of all centerlines unchanged_centerlines = compare_end_points(new_centerlines, old_centerlines) assert len(unchanged_centerlines) < len(old_centerlines)
def test_bifurcation_angle(surface_paths, angle): common_input = read_command_line_bifurcation(surface_paths[0], surface_paths[1]) common_input.update( dict(angle=angle, region_of_interest="commandline", region_points=[35.8, 59.8, 39.7, 76.8, 54.7, 53.2])) manipulate_bifurcation(**common_input) # Read in files to compute angle base_path = get_path_names(common_input["input_filepath"]) old_centerlines = read_polydata(base_path + "_centerline_par.vtp") new_centerlines = read_polydata(base_path + "_centerline_interpolated_ang.vtp") end_points = read_polydata(base_path + "_clippingpoints.vtp") # Start points start_point1 = end_points.GetPoint(1) start_point2 = end_points.GetPoint(2) # Get relevant centerlines cl_old_1 = -1 cl_old_2 = -1 cl_new_1 = -1 cl_new_2 = -1 tol = get_centerline_tolerance(old_centerlines) for i in range(old_centerlines.GetNumberOfLines()): line_old = extract_single_line(old_centerlines, i) line_new = extract_single_line(new_centerlines, i) loc_old = get_vtk_point_locator(line_old) loc_new = get_vtk_point_locator(line_new) id1_old = loc_old.FindClosestPoint(start_point1) id2_old = loc_old.FindClosestPoint(start_point2) id1_new = loc_new.FindClosestPoint(start_point1) id2_new = loc_new.FindClosestPoint(start_point2) if get_distance(start_point1, line_old.GetPoint(id1_old)) < tol: cl_old_1 = i cl_old_id1 = id1_old if get_distance(start_point2, line_old.GetPoint(id2_old)) < tol: cl_old_2 = i cl_old_id2 = id2_old if get_distance(start_point1, line_new.GetPoint(id1_new)) < tol: cl_new_1 = i cl_new_id1 = id1_new if get_distance(start_point2, line_new.GetPoint(id2_new)) < tol: cl_new_2 = i cl_new_id2 = id2_new if -1 not in [cl_old_1, cl_old_2, cl_new_1, cl_new_2]: break # Get end points end_point1_old = np.array( extract_single_line(old_centerlines, cl_old_1).GetPoint(cl_old_id1 + 20)) end_point2_old = np.array( extract_single_line(old_centerlines, cl_old_2).GetPoint(cl_old_id2 + 20)) end_point1_new = np.array( extract_single_line(new_centerlines, cl_new_1).GetPoint(cl_new_id1 + 20)) end_point2_new = np.array( extract_single_line(new_centerlines, cl_new_2).GetPoint(cl_new_id2 + 20)) # Vectors v1_old = end_point1_old - np.array(start_point1) v2_old = end_point2_old - np.array(start_point2) v1_new = end_point1_new - np.array(start_point1) v2_new = end_point2_new - np.array(start_point2) # Normalize v1_old = v1_old / np.sqrt(np.sum(v1_old**2)) v2_old = v2_old / np.sqrt(np.sum(v2_old**2)) v1_new = v1_new / np.sqrt(np.sum(v1_new**2)) v2_new = v2_new / np.sqrt(np.sum(v2_new**2)) # Angle first_daughter_branch_angle_change = np.arccos(np.dot(v1_old, v1_new)) second_daughter_branch_angle_change = np.arccos(np.dot(v2_old, v2_new)) assert abs(first_daughter_branch_angle_change + second_daughter_branch_angle_change - 2 * abs(common_input["angle"])) < 0.04