Skip to content

Commit 506993a

Browse files
committed
ENH: updated anchor point finding
1 parent 1ab0be7 commit 506993a

File tree

1 file changed

+93
-44
lines changed

1 file changed

+93
-44
lines changed

cortex/dartboards.py

Lines changed: 93 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ def vertical_flip_path(path, overlay):
160160

161161

162162
def determine_path_hemi(overlay, path, percent_cutoff=.4):
163+
"""Returns 0 (False) for left, 1 (True) for right hemisphere"""
163164
if isinstance(path, matplotlib.path.Path):
164165
path = path.vertices
165166
middle_x = overlay.svgshape[0]/2
@@ -178,7 +179,9 @@ def center_of_mass(X):
178179
-------
179180
center_of_mass
180181
array of shape (2,) that contains (x, y) center of mass
181-
"""
182+
"""
183+
if not np.all(np.isclose(X[0], X[-1])):
184+
X = np.vstack([X, X[0]])
182185
# calculate center of mass of a closed polygon
183186
x = X[:, 0]
184187
y = X[:, 1]
@@ -378,6 +381,7 @@ def _angles_from_vertex(overlay, start_idx, target_idxs=None, period=2*np.pi, th
378381

379382

380383
def get_roi_paths(overlay, roi, cleaned=True, filter_zeros=True, vertical_flip=True, overlay_file=None):
384+
"""returns left, right hemisphere paths"""
381385
if roi in list(overlay.rois.shapes.keys()):
382386
paths = overlay.rois[roi].splines
383387
elif roi in list(overlay.sulci.shapes.keys()):
@@ -670,7 +674,7 @@ def show_dartboard(data,
670674
"""
671675
if max_radius is None:
672676
max_radius = 1
673-
data = np.array(data).astype(np.float)
677+
data = np.array(data).astype(float)
674678
if isinstance(data2, np.ndarray):
675679
data = np.stack([data, data2], axis=0)
676680
else:
@@ -748,6 +752,27 @@ def show_dartboard(data,
748752
return axis
749753

750754

755+
def clockwise_test(pts):
756+
"""Test for clockwise ordering of points
757+
758+
Parameters
759+
----------
760+
pts : array
761+
2D array (n_pts, xy) defining polygon points to be evaluated for clockwise rotation
762+
763+
Returns
764+
-------
765+
is_clockwise : bool
766+
True for clockwise, False for counter-clockwise
767+
"""
768+
if not np.all(pts[0] == pts[-1]):
769+
pts = np.vstack([pts, pts[0]])
770+
sum = 0
771+
for c0, c1 in zip(pts[:-1], pts[1:]):
772+
sum += (c1[0] - c0[0]) * (c1[1] + c0[1])
773+
return sum > 0
774+
775+
751776
def interpolate_outlines(phi, rho, resolution=50):
752777
new_phi = np.linspace(0,2*np.pi,resolution)
753778
new_rho = np.interp(new_phi, phi, rho, period=2*np.pi)
@@ -873,40 +898,54 @@ def sort_roi_border(xy, angles, start_angle=0, start_index=None, max_deg_from_ze
873898
if start_index is None:
874899
start_index = np.argmin(
875900
np.abs(circ_dist(angles, start_angle, degrees=False)))
876-
vertex_order = [start_index]
877-
ct = 0
878-
for i_vert in range(len(xy)):
879-
# Special case for first one: go clockwise
880-
if i_vert == 0:
881-
new_verts = np.argsort(dsts[start_index])[:5]
882-
new_verts = np.array([x for x in new_verts if x not in vertex_order])
883-
angles_from_origin = circ_dist(angles[new_verts], angles[start_index], degrees=False)
884-
is_clockwise = angles_from_origin > 0
885-
#if ~any(is_clockwise):
886-
# plt.plot(*xy.T)
887-
# plt.plot()
888-
min_clockwise_angle = np.min(angles_from_origin[is_clockwise])
889-
j = new_verts[angles_from_origin == min_clockwise_angle][0]
890-
vertex_order.append(j)
891-
else:
892-
success = False
893-
n = 3
894-
while (not success) and (n<15):
895-
new_verts = np.argsort(dsts[vertex_order[-1]])[:n]
896-
new_verts = np.array([x for x in new_verts if x not in vertex_order])
897-
success = len(new_verts==1)
898-
n += 1
899-
#if n > 4:
900-
# print(n)
901-
if len(new_verts) > 0:
902-
vertex_order.append(new_verts[-1])
903-
else:
904-
ct += 1
905-
if verbose:
906-
print(f"Skipped a vertex ({ct} skipped)")
907-
#1/0
908-
vertex_order.append(vertex_order[0])
909-
return np.array(vertex_order)
901+
is_clockwise = clockwise_test(xy)
902+
n = len(xy)
903+
if is_clockwise:
904+
print('Detected CLOCKWISE order')
905+
vertex_order = np.hstack([np.arange(start_index, n),
906+
np.arange(0, start_index),
907+
start_index])
908+
else:
909+
print('Detected COUNTER-CLOCKWISE order')
910+
vertex_order = np.hstack([np.arange(start_index, 0, -1),
911+
np.arange(n-1, start_index, -1),
912+
start_index])
913+
914+
# vertex_order = [start_index]
915+
# ct = 0
916+
# for i_vert in range(len(xy)):
917+
# # Special case for first one: go clockwise
918+
# if i_vert == 0:
919+
# new_verts = np.argsort(dsts[start_index])[:5]
920+
# new_verts = np.array([x for x in new_verts if x not in vertex_order])
921+
# angles_from_origin = circ_dist(angles[new_verts], angles[start_index], degrees=False)
922+
# is_clockwise = angles_from_origin > 0
923+
# #if ~any(is_clockwise):
924+
# # plt.plot(*xy.T)
925+
# # plt.plot()
926+
# min_clockwise_angle = np.min(angles_from_origin[is_clockwise])
927+
# j = new_verts[angles_from_origin == min_clockwise_angle][0]
928+
# vertex_order.append(j)
929+
# else:
930+
# success = False
931+
# n = 3
932+
# while (not success) and (n<15):
933+
# new_verts = np.argsort(dsts[vertex_order[-1]])[:n]
934+
# new_verts = np.array([x for x in new_verts if x not in vertex_order])
935+
# success = len(new_verts==1)
936+
# n += 1
937+
# #if n > 4:
938+
# # print(n)
939+
# if len(new_verts) > 0:
940+
# vertex_order.append(new_verts[-1])
941+
# else:
942+
# ct += 1
943+
# if verbose:
944+
# print(f"Skipped a vertex ({ct} skipped)")
945+
# #1/0
946+
# vertex_order.append(vertex_order[0])
947+
# return np.array(vertex_order)
948+
return vertex_order
910949

911950

912951
def get_interpolated_outlines(overlay,
@@ -926,15 +965,18 @@ def get_interpolated_outlines(overlay,
926965
svgoverlay for a given subject
927966
outline_roi : str
928967
name of ROI to plot (must sexist in overlays.svg)
929-
center_roi : str
930-
name of center ROI for dartboard
931-
anchor_angles : array
932-
array of angles ??
933968
geodesic_distances : bool, optional
934969
Flag for whether to compute geodesic distances for eccentricity bins,
935970
by default True
936971
resolution : int, optional
937972
number of points estimated for outline, by default 100
973+
every_n : int, optional
974+
smooth path by fitting a cubic spline to `every_n` vertices on border
975+
recache : bool, optional
976+
whether to force re-computation (recache=True) or allow loading from cached
977+
file (recache=False)
978+
verbose : bool, optional
979+
verbose output or not
938980
939981
Returns
940982
-------
@@ -1163,8 +1205,8 @@ def show_dartboard_pair(dartboard_data,
11631205
space, a little smoothing usually helps aesthetically. 1 is no smoothing
11641206
, by default 5
11651207
even_sampling_over : str, optional
1166-
How to resample ROI paths, by angle or along path length. 'angle' is perhaps slightly
1167-
more principled for convex ROIs, but 'path_length' gives better results for non-convex
1208+
How to resample ROI paths, by angle or along path length. 'polar angle' is slightly
1209+
more principled for convex ROIs, but 'path length' gives better results for non-convex
11681210
ROIs, by default 'path length'
11691211
roi_linewidth : int, optional
11701212
width of lines for drawn ROIs, by default 1
@@ -1566,10 +1608,17 @@ def _get_anchor_points(svg, center_roi, anchors, return_indices=True):
15661608
anchor_name, anchor_type = anchor, 'centroid'
15671609
if j == 0:
15681610
center_name, center_type = anchor_name, anchor_type
1569-
if anchor_type == 'nearest':
1570-
centroids[anchor_name] = _get_closest_vertex_to_roi(svg, anchor_name, center_name, return_indices=return_indices)
1611+
if 'nearest' in anchor_type:
1612+
if '_to_' in anchor_type:
1613+
_, _, roi_to = anchor_type.split('_')
1614+
centroids[f'{anchor_name}-{roi_to}'] = _get_closest_vertex_to_roi(svg, anchor_name, roi_to, return_indices=return_indices)
1615+
else:
1616+
centroids[anchor_name] = _get_closest_vertex_to_roi(svg, anchor_name, center_name, return_indices=return_indices)
15711617
elif anchor_type == 'centroid':
15721618
centroids[anchor_name] = get_roi_centroids(svg, anchor_name, return_indices=return_indices)
1619+
elif anchor_type == 'superior':
1620+
pass
1621+
#centroids[anchor_name] = _get_closest_vertex_to_roi(svg, anchor_name, center_name, return_indices=return_indices)
15731622
else:
15741623
raise ValueError("unknown anchor type specified: %s\n(Must be 'nearest' or 'centroid')"%(anchor_type))
15751624
return centroids

0 commit comments

Comments
 (0)