import numpy as np
import numba as nb
from functools import partial
from copy import deepcopy
from scipy.optimize import minimize,approx_fprime
[docs]@nb.jit(nopython=True)
def fast_local_function(data,mesh,terminal,edge,gamma,nu,Qterm,Pperm,Pterm):
####################
reduced_resistances = []
reduced_lengths = []
bifurcations = []
flows = [] # should only be changing path (not alt paths)
main_idx = [] # index 0: data[:,15]; index 1: data[:,16]
alt_idx = []
new_scale = [] # compound bifurcations
alt_scale = []
####################
total_flow = data[edge,22].item()+Qterm*2
upstream = data[edge,0:3]
downstream = data[edge,3:6]
upstream_length = np.sqrt(np.sum(np.square(mesh-upstream),axis=1))
downstream_length = np.sqrt(np.sum(np.square(mesh-downstream),axis=1))
terminal_length = np.sqrt(np.sum(np.square(mesh-terminal),axis=1))
# Begin calculating reduced resistance and bifurcation ratios
R_terminal = (8*nu/np.pi)*terminal_length
R_terminal_sister = (8*nu/np.pi)*downstream_length + (data[edge,25]-(8*nu/np.pi)*data[edge,20])
f_terminal = (1+((data[edge,22]*R_terminal_sister)/(Qterm*R_terminal))**(gamma/4)) ** (-1/gamma)
f_terminal_sister = (1+((data[edge,22]*R_terminal_sister)/(Qterm*R_terminal))**(-gamma/4)) ** (-1/gamma)
R_0 = (8*nu/np.pi)*upstream_length + ((f_terminal**4)/R_terminal +
(f_terminal_sister**4)/R_terminal_sister)**-1
L_0 = f_terminal ** 2 * terminal_length + f_terminal_sister ** 2 * (downstream_length + data[edge,27])
reduced_resistances.append(R_0)
reduced_lengths.append(L_0)
flows.append(data[edge,22].item()+Qterm)
main_idx.append(edge.item())
bifurcations.append(f_terminal_sister) # 0 -> 15; 1-> 16
bifurcations.append(f_terminal)
if edge == 0:
# on the terminating round the new terminal is always 16 and the existing is 15
#bifurcations.append([f_terminal_sister,f_terminal])
L_0 = upstream_length + L_0
R_0 = (((data[edge,22]+Qterm)*R_0)/(Pperm-Pterm))**(1/4)
alt_idx.append(-1)
new_scale.append(np.ones(f_terminal.shape))
alt_scale.append(np.ones(f_terminal.shape))
return (R_0,L_0,f_terminal,f_terminal_sister,None,mesh,reduced_resistances,
reduced_lengths,bifurcations,flows,main_idx,alt_idx,new_scale,alt_scale,R_terminal,
R_terminal_sister)
previous = edge
edge = int(data[edge,17].item())
if int(data[edge,15].item()) == previous:
alt = int(data[edge,16].item())
if alt == -1:
alt = -2
alt_idx.append(alt)
position = 0
#bifurcations.append([f_terminal,f_terminal_sister])
else:
alt = int(data[edge,15].item())
if alt == -1:
alt = -2
alt_idx.append(alt)
position = 1
#bifurcations.append([f_terminal_sister,f_terminal])
if alt == -2:
f_changed = np.array([1.0])
f_stagnant = np.array([0.0])
f_terminal = f_terminal*f_changed
f_terminal_sister = f_terminal_sister*f_changed
f_parent = f_changed
R_0 = (8*nu/np.pi)*data[edge,20].item() + R_0
L_0 = f_changed ** 2 *(upstream_length+L_0)
else:
f_changed = (1+((data[alt,22]*data[alt,25])/((data[previous,22]+Qterm)*R_0)) ** (gamma/4)) ** (-1/gamma)
f_stagnant = (1+((data[alt,22]*data[alt,25])/((data[previous,22]+Qterm)*R_0)) ** (-gamma/4)) ** (-1/gamma)
f_terminal = f_terminal*f_changed
f_terminal_sister = f_terminal_sister*f_changed
f_parent = f_changed
R_0 = (8*nu/np.pi)*data[edge,20] + ((f_changed ** 4) /R_0 + (f_stagnant ** 4) /data[alt,25]) ** -1
L_0 = f_changed ** 2 *(upstream_length+L_0) + f_stagnant ** 2 * (data[alt,20] + data[alt,27])
reduced_resistances.append(R_0)
reduced_lengths.append(L_0)
flows.append(data[edge,22].item()+Qterm)
main_idx.append(edge)
new_scale.append(f_changed)
alt_scale.append(f_stagnant)
if position == 0:
bifurcations.append(f_changed)
bifurcations.append(f_stagnant)
else:
bifurcations.append(f_stagnant)
bifurcations.append(f_changed)
if edge == 0:
L_0 = data[edge,20]+L_0
R_0 = (((data[edge,22]+Qterm)*R_0)/(Pperm-Pterm))**(1/4)
return (R_0,L_0,f_terminal,f_terminal_sister,f_parent,mesh,reduced_resistances,
reduced_lengths,bifurcations,flows,main_idx,alt_idx,new_scale,alt_scale,R_terminal,
R_terminal_sister)
previous = edge
edge = int(data[edge,17].item())
while edge >= 0:
if int(data[edge, 15].item()) == previous:
alt = int(data[edge,16].item())
if alt == -1:
alt = -2
alt_idx.append(alt)
position = 0
else:
alt = int(data[edge,15].item())
if alt == -1:
alt = -2
alt_idx.append(alt)
position = 1
if alt == -2:
f_changed = np.array([1.0])
f_stagnant = np.array([0.0])
R_0 = (8*nu/np.pi)*data[edge,20] + R_0
L_0 = f_changed ** 2 * (data[previous, 20] + L_0)
f_terminal = f_terminal*f_changed
f_terminal_sister = f_terminal_sister*f_changed
f_parent = f_parent*f_changed
else:
f_changed = (1+((data[alt, 22]*data[alt,25])/((Qterm+data[previous,22])*R_0)) ** (gamma/4)) ** (-1/gamma)
f_stagnant = (1+((data[alt, 22]*data[alt,25])/((Qterm+data[previous,22])*R_0)) ** (-gamma/4)) ** (-1/gamma)
f_terminal = f_terminal*f_changed
f_terminal_sister = f_terminal_sister*f_changed
f_parent = f_parent*f_changed
R_0 = (8*nu/np.pi)*data[edge,20] + ((f_changed ** 4 / R_0) + (f_stagnant ** 4 / data[alt, 25])) ** -1
L_0 = f_changed ** 2 * (data[previous, 20] + L_0) + f_stagnant ** 2 *(data[alt, 20] + data[alt, 27])
reduced_resistances.append(R_0)
reduced_lengths.append(L_0)
flows.append(data[edge,22].item()+Qterm)
main_idx.append(edge)
if edge >= 0:
for j in range(len(new_scale)):
new_scale[j] = new_scale[j]*f_changed
alt_scale[j] = alt_scale[j]*f_changed
new_scale.append(f_changed)
#alt_scale = [bif*f_changed for bif in alt_scale]
alt_scale.append(f_stagnant)
#else:
# new_scale.append(np.ones(f_changed.shape))
# alt_scale.append(np.ones(f_changed.shape))
if position == 0:
bifurcations.append(f_changed)
bifurcations.append(f_stagnant)
else:
bifurcations.append(f_stagnant)
bifurcations.append(f_changed)
previous = edge
edge = int(data[edge,17].item())
L_0 = data[0,20] + L_0
R_0 = (((data[0, 22]+Qterm)*R_0)/(Pperm-Pterm))**(1/4)
return (R_0,L_0,f_terminal,f_terminal_sister,f_parent,mesh,reduced_resistances,
reduced_lengths,bifurcations,flows,main_idx,alt_idx,new_scale,alt_scale,R_terminal,
R_terminal_sister)
[docs]def fast_local_function_test(data,mesh,terminal,edge,gamma,nu,Qterm,Pperm,Pterm):
####################
reduced_resistances = []
reduced_lengths = []
bifurcations = []
flows = [] # should only be changing path (not alt paths)
main_idx = [] # index 0: data[:,15]; index 1: data[:,16]
alt_idx = []
new_scale = [] # compound bifurcations
alt_scale = []
####################
#total_flow = data[edge,22].item()+Qterm*2
upstream = data[edge,0:3]
downstream = data[edge,3:6]
upstream_length = np.sqrt(np.sum(np.square(mesh-upstream),axis=1))
downstream_length = np.sqrt(np.sum(np.square(mesh-downstream),axis=1))
terminal_length = np.sqrt(np.sum(np.square(mesh-terminal),axis=1))
# Begin calculating reduced resistance and bifurcation ratios
R_terminal = (8*nu/np.pi)*terminal_length
R_terminal_sister = (8*nu/np.pi)*downstream_length + (data[edge,25]-(8*nu/np.pi)*data[edge,20])
f_terminal = (1+((data[edge,22]*R_terminal_sister)/(Qterm*R_terminal))**(gamma/4)) ** (-1/gamma)
f_terminal_sister = (1+((data[edge,22]*R_terminal_sister)/(Qterm*R_terminal))**(-gamma/4)) ** (-1/gamma)
R_0 = (8*nu/np.pi)*upstream_length + ((f_terminal**4)/R_terminal +
(f_terminal_sister**4)/R_terminal_sister)**-1
L_0 = f_terminal ** 2 * terminal_length + f_terminal_sister ** 2 * (downstream_length + data[edge,27])
reduced_resistances.append(R_0)
reduced_lengths.append(L_0)
flows.append(data[edge,22].item()+Qterm)
main_idx.append(edge.item())
bifurcations.append(f_terminal_sister) # 0 -> 15; 1-> 16
bifurcations.append(f_terminal)
if edge == 0:
# on the terminating round the new terminal is always 16 and the existing is 15
#bifurcations.append([f_terminal_sister,f_terminal])
L_0 = upstream_length + L_0
R_0 = (((data[edge,22]+Qterm)*R_0)/(Pperm-Pterm))**(1/4)
alt_idx.append(-1)
new_scale.append(np.ones(f_terminal.shape))
alt_scale.append(np.ones(f_terminal.shape))
return (R_0,L_0,f_terminal,f_terminal_sister,None,mesh,reduced_resistances,
reduced_lengths,bifurcations,flows,main_idx,alt_idx,new_scale,alt_scale,R_terminal,
R_terminal_sister)
previous = edge
edge = int(data[edge,17].item())
if int(data[edge,15].item()) == previous:
alt = int(data[edge,16].item())
if alt == -1:
alt = -2
alt_idx.append(alt)
position = 0
#bifurcations.append([f_terminal,f_terminal_sister])
else:
alt = int(data[edge,15].item())
if alt == -1:
alt = -2
alt_idx.append(alt)
position = 1
#bifurcations.append([f_terminal_sister,f_terminal])
if alt == -2:
f_changed = np.array([1.0])
f_stagnant = np.array([0.0])
f_terminal = f_terminal*f_changed
f_terminal_sister = f_terminal_sister*f_changed
f_parent = f_changed
R_0 = (8*nu/np.pi)*data[edge,20].item() + R_0
L_0 = f_changed ** 2 *(upstream_length+L_0)
else:
f_changed = (1+((data[alt,22]*data[alt,25])/((data[previous,22]+Qterm)*R_0)) ** (gamma/4)) ** (-1/gamma)
f_stagnant = (1+((data[alt,22]*data[alt,25])/((data[previous,22]+Qterm)*R_0)) ** (-gamma/4)) ** (-1/gamma)
f_terminal = f_terminal*f_changed
f_terminal_sister = f_terminal_sister*f_changed
f_parent = f_changed
R_0 = (8*nu/np.pi)*data[edge,20] + ((f_changed ** 4) /R_0 + (f_stagnant ** 4) /data[alt,25]) ** -1
L_0 = f_changed ** 2 *(upstream_length+L_0) + f_stagnant ** 2 * (data[alt,20] + data[alt,27])
reduced_resistances.append(R_0)
reduced_lengths.append(L_0)
flows.append(data[edge,22].item()+Qterm)
main_idx.append(edge)
new_scale.append(f_changed)
alt_scale.append(f_stagnant)
if position == 0:
bifurcations.append(f_changed)
bifurcations.append(f_stagnant)
else:
bifurcations.append(f_stagnant)
bifurcations.append(f_changed)
if edge == 0:
L_0 = data[edge,20]+L_0
R_0 = (((data[edge,22]+Qterm)*R_0)/(Pperm-Pterm))**(1/4)
return (R_0,L_0,f_terminal,f_terminal_sister,f_parent,mesh,reduced_resistances,
reduced_lengths,bifurcations,flows,main_idx,alt_idx,new_scale,alt_scale,R_terminal,
R_terminal_sister)
previous = edge
edge = int(data[edge,17].item())
while edge >= 0:
if int(data[edge, 15].item()) == previous:
alt = int(data[edge,16].item())
if alt == -1:
alt = -2
alt_idx.append(alt)
position = 0
else:
alt = int(data[edge,15].item())
if alt == -1:
alt = -2
alt_idx.append(alt)
position = 1
if alt == -2:
f_changed = np.array([1.0])
f_stagnant = np.array([0.0])
R_0 = (8*nu/np.pi)*data[edge,20] + R_0
L_0 = f_changed ** 2 * (data[previous, 20] + L_0)
f_terminal = f_terminal*f_changed
f_terminal_sister = f_terminal_sister*f_changed
f_parent = f_parent*f_changed
else:
f_changed = (1+((data[alt, 22]*data[alt,25])/((Qterm+data[previous,22])*R_0)) ** (gamma/4)) ** (-1/gamma)
f_stagnant = (1+((data[alt, 22]*data[alt,25])/((Qterm+data[previous,22])*R_0)) ** (-gamma/4)) ** (-1/gamma)
f_terminal = f_terminal*f_changed
f_terminal_sister = f_terminal_sister*f_changed
f_parent = f_parent*f_changed
R_0 = (8*nu/np.pi)*data[edge,20] + ((f_changed ** 4 / R_0) + (f_stagnant ** 4 / data[alt, 25])) ** -1
L_0 = f_changed ** 2 * (data[previous, 20] + L_0) + f_stagnant ** 2 *(data[alt, 20] + data[alt, 27])
reduced_resistances.append(R_0)
reduced_lengths.append(L_0)
flows.append(data[edge,22].item()+Qterm)
main_idx.append(edge)
if edge >= 0:
for j in range(len(new_scale)):
new_scale[j] = new_scale[j]*f_changed
alt_scale[j] = alt_scale[j]*f_changed
new_scale.append(f_changed)
#alt_scale = [bif*f_changed for bif in alt_scale]
alt_scale.append(f_stagnant)
#else:
# new_scale.append(np.ones(f_changed.shape))
# alt_scale.append(np.ones(f_changed.shape))
if position == 0:
bifurcations.append(f_changed)
bifurcations.append(f_stagnant)
else:
bifurcations.append(f_stagnant)
bifurcations.append(f_changed)
previous = edge
edge = int(data[edge,17].item())
L_0 = data[0,20] + L_0
R_0 = (((data[0, 22]+Qterm)*R_0)/(Pperm-Pterm))**(1/4)
return (R_0,L_0,f_terminal,f_terminal_sister,f_parent,mesh,reduced_resistances,
reduced_lengths,bifurcations,flows,main_idx,alt_idx,new_scale,alt_scale,R_terminal,
R_terminal_sister)
"""
def fast_local_function_bind(bif_point,data,terminal,edge,gamma,nu,Qterm,Pperm,Pterm):
upstream = data[edge,0:3]
downstream = data[edge,3:6]
upstream_length = np.sqrt(np.sum(np.square(bif_point-upstream),axis=1))
downstream_length = np.sqrt(np.sum(np.square(bif_point-downstream),axis=1))
terminal_length = np.sqrt(np.sum(np.square(bif_point-terminal),axis=1))
"""
[docs]def path(data,edge):
path_to_root = [edge]
alt_paths = []
while path[-1] > 0:
previous = edge
edge = int(data[edge,17].item())
path_to_root.append(edge)
left = int(data[edge,15].item())
right = int(data[edge,16].item())
if left == previous:
alt_paths.append(right)
else:
alt_paths.append(left)
return path_to_root,alt_paths
[docs]@nb.jit(nopython=True)
def volume(x,data,terminal,edge,gamma,nu,Qterm,Pperm,Pterm):
####################
reduced_resistances = []
reduced_lengths = []
bifurcations = []
flows = [] # should only be changing path (not alt paths)
main_idx = [] # index 0: data[:,15]; index 1: data[:,16]
alt_idx = []
new_scale = [] # compound bifurcations
alt_scale = []
rescale = np.zeros(data.shape[0])
####################
#total_flow = data[edge,22].item()+Qterm*2
upstream = data[edge,0:3]
downstream = data[edge,3:6]
upstream_length = np.sqrt(np.sum(np.square(x-upstream),axis=1))
downstream_length = np.sqrt(np.sum(np.square(x-downstream),axis=1))
terminal_length = np.sqrt(np.sum(np.square(x-terminal),axis=1))
# Begin calculating reduced resistance and bifurcation ratios
R_terminal = (8*nu/np.pi)*terminal_length
R_terminal_sister = (8*nu/np.pi)*downstream_length + (data[edge,25]-(8*nu/np.pi)*data[edge,20])
f_terminal = (1+((data[edge,22]*R_terminal_sister)/(Qterm*R_terminal))**(gamma/4)) ** (-1/gamma)
f_terminal_sister = (1+((data[edge,22]*R_terminal_sister)/(Qterm*R_terminal))**(-gamma/4)) ** (-1/gamma)
R_0 = (8*nu/np.pi)*upstream_length + ((f_terminal**4)/R_terminal +
(f_terminal_sister**4)/R_terminal_sister)**-1
L_0 = f_terminal ** 2 * terminal_length + f_terminal_sister ** 2 * (downstream_length + data[edge,27])
reduced_resistances.append(R_0)
reduced_lengths.append(L_0)
flows.append(data[edge,22].item()+Qterm)
main_idx.append(edge.item())
bifurcations.append(f_terminal_sister) # 0 -> 15; 1-> 16
bifurcations.append(f_terminal)
if edge == 0:
# on the terminating round the new terminal is always 16 and the existing is 15
#bifurcations.append([f_terminal_sister,f_terminal])
L_0 = upstream_length + L_0
R_0 = (((data[edge,22]+Qterm)*R_0)/(Pperm-Pterm))**(1/4)
alt_idx.append(-1)
new_scale.append(np.ones(f_terminal.shape))
alt_scale.append(np.ones(f_terminal.shape))
return (R_0,L_0,f_terminal,f_terminal_sister,None,x,reduced_resistances,
reduced_lengths,bifurcations,flows,main_idx,alt_idx,new_scale,alt_scale,R_terminal,
R_terminal_sister)
previous = edge
edge = int(data[edge,17].item())
if int(data[edge,15].item()) == previous:
alt = int(data[edge,16].item())
if alt == -1:
alt = -2
alt_idx.append(alt)
position = 0
#bifurcations.append([f_terminal,f_terminal_sister])
else:
alt = int(data[edge,15].item())
if alt == -1:
alt = -2
alt_idx.append(alt)
position = 1
#bifurcations.append([f_terminal_sister,f_terminal])
if alt == -2:
f_changed = np.array([1.0])
f_stagnant = np.array([0.0])
f_terminal = f_terminal*f_changed
f_terminal_sister = f_terminal_sister*f_changed
f_parent = f_changed
R_0 = (8*nu/np.pi)*data[edge,20].item() + R_0
L_0 = f_changed ** 2 *(upstream_length+L_0)
else:
f_changed = (1+((data[alt,22]*data[alt,25])/((data[previous,22]+Qterm)*R_0)) ** (gamma/4)) ** (-1/gamma)
f_stagnant = (1+((data[alt,22]*data[alt,25])/((data[previous,22]+Qterm)*R_0)) ** (-gamma/4)) ** (-1/gamma)
f_terminal = f_terminal*f_changed
f_terminal_sister = f_terminal_sister*f_changed
f_parent = f_changed
R_0 = (8*nu/np.pi)*data[edge,20] + ((f_changed ** 4) /R_0 + (f_stagnant ** 4) /data[alt,25]) ** -1
L_0 = f_changed ** 2 *(upstream_length+L_0) + f_stagnant ** 2 * (data[alt,20] + data[alt,27])
reduced_resistances.append(R_0)
reduced_lengths.append(L_0)
flows.append(data[edge,22].item()+Qterm)
main_idx.append(edge)
new_scale.append(f_changed)
alt_scale.append(f_stagnant)
if position == 0:
bifurcations.append(f_changed)
bifurcations.append(f_stagnant)
else:
bifurcations.append(f_stagnant)
bifurcations.append(f_changed)
if edge == 0:
L_0 = data[edge,20]+L_0
R_0 = (((data[edge,22]+Qterm)*R_0)/(Pperm-Pterm))**(1/4)
return (R_0,L_0,f_terminal,f_terminal_sister,f_parent,x,reduced_resistances,
reduced_lengths,bifurcations,flows,main_idx,alt_idx,new_scale,alt_scale,R_terminal,
R_terminal_sister)
previous = edge
edge = int(data[edge,17].item())
while edge >= 0:
if int(data[edge, 15].item()) == previous:
alt = int(data[edge,16].item())
if alt == -1:
alt = -2
alt_idx.append(alt)
position = 0
else:
alt = int(data[edge,15].item())
if alt == -1:
alt = -2
alt_idx.append(alt)
position = 1
if alt == -2:
f_changed = np.array([1.0])
f_stagnant = np.array([0.0])
R_0 = (8*nu/np.pi)*data[edge,20] + R_0
L_0 = f_changed ** 2 * (data[previous, 20] + L_0)
f_terminal = f_terminal*f_changed
f_terminal_sister = f_terminal_sister*f_changed
f_parent = f_parent*f_changed
else:
f_changed = (1+((data[alt, 22]*data[alt,25])/((Qterm+data[previous,22])*R_0)) ** (gamma/4)) ** (-1/gamma)
f_stagnant = (1+((data[alt, 22]*data[alt,25])/((Qterm+data[previous,22])*R_0)) ** (-gamma/4)) ** (-1/gamma)
f_terminal = f_terminal*f_changed
f_terminal_sister = f_terminal_sister*f_changed
f_parent = f_parent*f_changed
R_0 = (8*nu/np.pi)*data[edge,20] + ((f_changed ** 4 / R_0) + (f_stagnant ** 4 / data[alt, 25])) ** -1
L_0 = f_changed ** 2 * (data[previous, 20] + L_0) + f_stagnant ** 2 *(data[alt, 20] + data[alt, 27])
reduced_resistances.append(R_0)
reduced_lengths.append(L_0)
flows.append(data[edge,22].item()+Qterm)
main_idx.append(edge)
if edge >= 0:
for j in range(len(new_scale)):
new_scale[j] = new_scale[j]*f_changed
alt_scale[j] = alt_scale[j]*f_changed
new_scale.append(f_changed)
#alt_scale = [bif*f_changed for bif in alt_scale]
alt_scale.append(f_stagnant)
#else:
# new_scale.append(np.ones(f_changed.shape))
# alt_scale.append(np.ones(f_changed.shape))
if position == 0:
bifurcations.append(f_changed)
bifurcations.append(f_stagnant)
else:
bifurcations.append(f_stagnant)
bifurcations.append(f_changed)
previous = edge
edge = int(data[edge,17].item())
L_0 = data[0,20] + L_0
R_0 = (((data[0, 22]+Qterm)*R_0)/(Pperm-Pterm))**(1/4)
return (R_0,L_0,f_terminal,f_terminal_sister,f_parent,x,reduced_resistances,
reduced_lengths,bifurcations,flows,main_idx,alt_idx,new_scale,alt_scale,R_terminal,
R_terminal_sister)
[docs]def constructor(data,terminal,edge,gamma,nu,Qterm,Pperm,Pterm,lam,mu,maxiter,method='L-BFGS-B'):
proximal = data[edge,0:3]
distal=data[edge,3:6]
d_min = min([np.linalg.norm(proximal-distal),
np.linalg.norm(terminal-distal),
np.linalg.norm(terminal-proximal)])*0.25
d_sides = [np.linalg.norm(proximal-distal),
np.linalg.norm(terminal-distal),
np.linalg.norm(terminal-proximal)]
s0 = (d_sides[0]+d_sides[1]+d_sides[2])/2
area = (s0*abs(s0-d_sides[0])*abs(s0-d_sides[1])*abs(s0-d_sides[2]))**0.5
#rescale = deepcopy(data[:,28])
def cost(st,func=volume,terminal=terminal,proximal=data[edge,0:3],distal=data[edge,3:6],data=data,edge=edge,gamma=gamma,nu=nu,Qterm=Qterm,Pperm=Pperm,Pterm=Pterm,d_min=d_min,d_sides=d_sides,area=area,lam=lam,mu=mu):
s = st[0]
t = st[1]
if s > 1:
s = 1
elif s < 0:
s = 0
if t > 1:
t = 1
elif t < 0:
t = 0
x = proximal.reshape(1,-1)*(1-t)*s + \
distal.reshape(1,-1)*(t*s)+\
terminal.reshape(1,-1)*(1-s)
d = [np.linalg.norm(proximal-x),
np.linalg.norm(distal-x),
np.linalg.norm(terminal-x)]
dd = min(d)
if dd < d_min:
return 10000
else:
res = volume(x,data,terminal,edge,gamma,nu,Qterm,Pperm,Pterm)
return np.pi*res[0]**lam*res[1]**mu
"""
s1 = (d[0]+d[1]+d_sides[0])/2
s2 = (d[1]+d[2]+d_sides[1])/2
s3 = (d[2]+d[0]+d_sides[2])/2
a1 = (s1*abs(s1-d[0])*abs(s1-d[1])*abs(s1-d_sides[0]))**0.5
a2 = (s2*abs(s2-d[1])*abs(s2-d[2])*abs(s2-d_sides[1]))**0.5
a3 = (s3*abs(s3-d[2])*abs(s3-d[0])*abs(s3-d_sides[2]))**0.5
at = a1+a2+a3
"""
#if not np.isclose(at,area):
# return 10000
#else:
# res = volume(x,data,terminal,edge,gamma,nu,Qterm,Pperm,Pterm)
# return np.pi*res[0]**lam*res[1]**mu
x0 = np.array([0.5,0.5])
if method == 'Newton-CG' or method == 'dogleg' or method == 'trust-ncg':
jac = lambda x: approx_fprime(x,cost,max(d_sides)/maxiter)
res = minimize(cost,x0,method=method,options={'maxiter':maxiter},jac=jac)
else:
res = minimize(cost,x0,method=method,options={'maxiter':maxiter})
st = res.x
s = st[0]
t = st[1]
if s > 1:
s = 1
elif s < 0:
s = 0
if t > 1:
t = 1
elif t < 0:
t = 0
x = proximal.reshape(1,-1)*(1-t)*s + \
distal.reshape(1,-1)*(t*s)+\
terminal.reshape(1,-1)*(1-s)
return volume(x,data,terminal,edge,gamma,nu,Qterm,Pperm,Pterm)