@@ -160,6 +160,7 @@ def vertical_flip_path(path, overlay):
160160
161161
162162def 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
380383def 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+
751776def 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
912951def 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