Source code for svcco.branch_addition.add_branches_v2

import numpy as np
import os #remove before final
import time #not neccessary?
from .check import *
from .close import *
from .local_func_v6 import *
from ..collision.sphere_proximity import *
from ..collision.collision import *
from .add_bifurcation import *
from .sample_triad import *
from .triangle import * #might not need
from .basis import *
from scipy import interpolate
from scipy.spatial import KDTree
import matplotlib.pyplot as plt #remove before final
from .get_point import *
from mpl_toolkits.mplot3d import proj3d #remove before final
from .geodesic import extract_surface,geodesic
from ..implicit.visualize.visualize import show_mesh
from .finite_difference import finite_difference


[docs]def add_branch(data,boundary,edge_number=None,gamma=None, nu=None,Qterm=None,Pperm=None,Pterm=None,lam=None,k=None, mu=None,threshold_adjuster=0.9, threshold_exponent=0.5,max_skip=None,target_low=None, target_high=None,sub_division_map=None,sub_division_index=None, fraction=None,isforest=False,ishomogeneous=None,isconvex=None, isdirected=None,isclamped=None,radius_buffer=None): threshold_distance = (boundary.volume)**(1/3)/(k**threshold_exponent) threshold_distance += threshold_distance*0.5*np.random.random(1) success = False if ishomogeneous: centers = (data[:,0:3] + data[:,3:6])/2 while not success: total_attempts = 0 attempt = 0 while total_attempts < 40: point,_ = boundary.pick(homogeneous=True) vessel, line_distances = close_exact(data,point) if sum(line_distances < threshold_distance) == 0 and min(line_distances) > 4*data[vessel[0],21]: escape = False for i in range(max_skip): if data[vessel[i],22] <= 8*Qterm: vessel = vessel[i] escape = True break if escape: break else: if attempt < 10: attempt += 1 total_attempts += attempt else: print('adjusting threshold') threshold_distance *= threshold_adjuster attempt = 0 proximal = data[vessel,0:3] distal = data[vessel,3:6] terminal = point num = 20 triangle = get_local_points(data,vessel,terminal,num,isclamped) triangle = relative_length_constraint(triangle,proximal,distal,terminal,0.25) if not isconvex: triangle = boundary_constraint(triangle,boundary,2) triangle = angle_constraint(triangle,terminal,distal,-0.4,True) if len(triangle) == 0: continue triangle = angle_constraint(triangle,terminal,distal,0.75,False) if len(triangle) == 0: continue triangle = angle_constraint(triangle,terminal,proximal,0,False) if len(triangle) == 0: continue triangle = angle_constraint(triangle,distal,proximal,0,False) if len(triangle) == 0: continue if data[vessel,17] >= 0: p_vessel = int(data[vessel,17]) daughter1_vector = -data[p_vessel,12:15] daughter2_vector = (triangle - proximal)/np.linalg.norm(triangle - proximal,axis=1).reshape(-1,1) angle = np.array([np.dot(daughter1_vector,daughter2_vector[i]) for i in range(len(daughter2_vector))]) triangle = triangle[angle<0] if len(triangle) == 0: continue #start = time.time() results = fast_local_function(data,triangle,terminal,vessel,gamma,nu,Qterm,Pperm,Pterm) #b_time = time.time() - start volume = np.pi*(results[0]**lam)*(results[1]**mu) idx = np.argmin(volume) bif = results[5][idx] #start = time.time() #fd_bif,fd_idx,fd_volume,fd_trial = finite_difference(data,triangle,terminal,vessel,gamma,nu,Qterm,Pperm,Pterm) #fd_time = time.time() - start no_collision = collision_free(data,results,idx,terminal,vessel,radius_buffer) #no_collision_fd = collision_free_fd(fd_trial,vessel) #print(no_collision) if no_collision: #print('LOCAL ACCEL: {} FINITE DIFF: {}'.format(bif,fd_bif)) #print(np.allclose(bif,fd_bif)) #print('adding') data = np.vstack((data,np.zeros((2,data.shape[1])))) data,sub_division_index = add_bifurcation(data,None,bif,terminal,vessel,Qterm, results[0],results[1],results[2],results[3], np.array(results[6]),np.array(results[7]), np.array(results[8]),np.array(results[9]), np.array(results[10]),np.array(results[11]), np.array(results[12]),np.array(results[13]), results[14],results[15],idx,sub_division_map, sub_division_index,True) #print('FINITE: {} BINDING: {}'.format(fd_time,b_time)) #data = fd_trial k += 2 results = [data,k,sub_division_map,sub_division_index] if not isforest: return data,k,sub_division_map,sub_division_index else: new_terminal = data[-2,:] new_sister = data[-1,:] new_parent = data[vessel,:] return new_terminal,new_sister,new_parent,results else: continue #return data,k,sub_division_map,sub_division_index pure_data = data[data[:,-1]>-1] segment_data = data[data[:,-1]==-1] vessel = np.random.choice(list(range(pure_data.shape[0]))) vessel_path = segment_data[segment_data[:,29].astype(int)==vessel] other_vessels= segment_data[segment_data[:,29].astype(int)!=vessel] if pure_data.shape[0] > 1: other_KDTree = KDTree((other_vessels[:,0:3]+other_vessels[:,3:6])/2) else: other_KDTree = None mesh,pa,cp,cd= boundary.mesh(vessel_path[1:,0:3],threshold_distance,threshold_distance//fraction,dive=0,others=other_KDTree) #show_mesh(mesh,np.array(pa),np.array(cp)) mesh_poly = extract_surface(mesh) proximal = vessel_path[0,0:3] distal = vessel_path[-1,3:6] terminal = cp[-1] #results = fast_local_function(pure_data,mesh,terminal,vessel,gamma,nu,Qterm,Pperm,Pterm) d_max = max(data[vessel,20]*0.1,np.sum(cd)*0.1) mesh_truc = mesh[np.linalg.norm(mesh-proximal,axis=1)>d_max] mesh_truc = mesh_truc[np.linalg.norm(mesh_truc-distal,axis=1)>d_max] #show_mesh(mesh_truc,np.array(pa),np.array(cp)) mesh_truc = mesh_truc[np.linalg.norm(mesh_truc-terminal,axis=1)>d_max] #show_mesh(mesh_truc,np.array(pa),np.array(cp)) results = fast_local_function(pure_data,mesh_truc,terminal,vessel,gamma,nu,Qterm,Pperm,Pterm) volume = np.pi*(results[0]**lam)*(results[1]**mu) idx = np.argmin(volume) bif = results[5][idx] proximal,distal,terminal = geodesic(mesh_poly,proximal,distal,terminal,bif) new_parent_size = proximal['path'].shape[0]-1 new_sister_size = distal['path'].shape[0]-1 new_terminal_size = terminal['path'].shape[0]-1 ########## # Ensure continuity of vessels reapply start and end nodes ########## #terminal['path'][0,:] = cp[-1] #distal['path'][0,:] = vessel_path[-1,3:6] proximal['path'][-1,:] = vessel_path[0,0:3] new_parent = np.zeros((new_parent_size,data.shape[1])) new_sister = np.zeros((new_sister_size,data.shape[1])) new_terminal = np.zeros((new_terminal_size,data.shape[1])) new_segment_data = other_vessels new_terminal[:,0:3] = terminal['path'][:-1,:] new_terminal[:,3:6] = terminal['path'][1:,:] new_terminal[:,20] = np.linalg.norm(new_terminal[:,0:3]-new_terminal[:,3:6]) new_terminal[:,21] = results[0][idx]*results[2][idx] new_terminal[:,29] = np.float(pure_data.shape[0]) new_terminal[:,-1] = -1 new_sister[:,0:3] = distal['path'][:-1,:] new_sister[:,3:6] = distal['path'][1:,:] new_sister[:,20] = np.linalg.norm(new_sister[:,0:3] - new_sister[:,3:6]) new_sister[:,21] = results[0][idx]*results[3][idx] new_sister[:,29] = np.float(pure_data.shape[0])+1 new_sister[:,-1] = -1 new_parent[:,0:3] = proximal['path'][:-1,:] new_parent[:,3:6] = proximal['path'][1:,:] new_parent[:,20] = np.linalg.norm(new_parent[:,0:3] - new_parent[:,3:6]) new_parent[:,29] = np.float(vessel) new_parent[:,-1] = -1 if vessel != 0: new_parent[:,21] = results[0][idx]*results[4][idx] else: new_parent[:,21] = results[0][idx] for i in range(max([new_terminal.shape[0],new_sister.shape[0],new_parent.shape[0]])): if i < new_terminal.shape[0]: basis(new_terminal,i) if i < new_sister.shape[0]: basis(new_sister,i) if i < new_parent.shape[0]: basis(new_parent,i) new_segments = np.vstack((new_segment_data,new_terminal,new_sister,new_parent)) pure_data = np.vstack((pure_data,np.zeros((2,data.shape[1])))) data,sub_division_index = add_bifurcation(pure_data,new_segments,bif,cp[-1],vessel,Qterm, results[0],results[1],results[2],results[3], np.array(results[6]),np.array(results[7]), np.array(results[8]),np.array(results[9]), np.array(results[10]),np.array(results[11]), np.array(results[12]),np.array(results[13]), results[14],results[15],idx,sub_division_map, sub_division_index) k += 2 if not isforest: return data,k,sub_division_map,sub_division_index else: results = [data,k,sub_division_map,sub_division_index] return new_terminal,new_sister,new_parent,results