@@ -51,7 +51,7 @@ def get_islands(data):
5151
5252
5353def get_slope_islands (slope_flags ):
54- flags = slope_flags .astype (np .uint8 )
54+ flags = slope_flags .astype (np .uint16 )
5555 islands = get_islands (flags )
5656 idx = int (np .argmax ([val .sum () for val in islands ]))
5757 islands = [val * (1 if i == idx else 0 ) for i , val in enumerate (islands )]
@@ -443,7 +443,10 @@ def filter_candidates_to_ranges(
443443 views = np .lib .stride_tricks .sliding_window_view (candidate , (window , candidate .shape [1 ]))[
444444 ::stride_ , 0
445445 ]
446- skews = scipy .stats .skew (views , axis = (1 , 2 ))
446+ with warnings .catch_warnings ():
447+ # handle cases with mono-valued data
448+ warnings .simplefilter ('ignore' , category = RuntimeWarning )
449+ skews = scipy .stats .skew (views , axis = (1 , 2 ))
447450
448451 # Center and clip the skew values
449452 skew_thresh = calculate_mean_within_stddev_window (skews , skew_stddev )
@@ -452,7 +455,7 @@ def filter_candidates_to_ranges(
452455 skews = normalize_skew (skews , skew_thresh )
453456
454457 # Calculate the largest contiguous island of non-zeros
455- skews = (skews > 0 ).astype (np .uint8 )
458+ skews = (skews > 0 ).astype (np .uint16 )
456459 islands = get_islands (skews )
457460 area = float (max ([val .sum () for val in islands ]))
458461 area /= len (skews )
@@ -555,7 +558,7 @@ def normalize_skew(skews, skew_thresh):
555558
556559 with warnings .catch_warnings ():
557560 warnings .simplefilter ('ignore' , category = RuntimeWarning )
558- skews /= skews . max ( )
561+ skews /= np . nanmax ( skews )
559562
560563 skews = np .nan_to_num (skews , nan = 0.0 , posinf = 0.0 , neginf = - 0.0 )
561564
@@ -564,8 +567,8 @@ def normalize_skew(skews, skew_thresh):
564567
565568def calculate_mean_within_stddev_window (values , window ):
566569 # Calculate the average skew within X standard deviations (temperature scaling)
567- values_mean = np .mean (values )
568- values_std = np .std (values )
570+ values_mean = np .nanmean (values )
571+ values_std = np .nanstd (values )
569572 values_flags = np .abs (values - values_mean ) <= (values_std * window )
570573 values_mean_windowed = values [values_flags ].mean ()
571574 return values_mean_windowed
@@ -585,19 +588,22 @@ def tighten_ranges(
585588 # Extract the candidate window of the STFT
586589 candidate = stft_db [:, start :stop ]
587590
588- # Create a vertical (frequency ) sliding window of Numpy views
591+ # Create a horizontal (time ) sliding window of Numpy views
589592 views = np .lib .stride_tricks .sliding_window_view (candidate , (candidate .shape [0 ], window ))[
590593 0 , ::stride_
591594 ]
592- skews = scipy .stats .skew (views , axis = (1 , 2 ))
595+ with warnings .catch_warnings ():
596+ # handle cases with mono-valued data
597+ warnings .simplefilter ('ignore' , category = RuntimeWarning )
598+ skews = scipy .stats .skew (views , axis = (1 , 2 ))
593599
594600 # Center and clip the skew values
595601 skew_thresh = calculate_mean_within_stddev_window (skews , skew_stddev )
596602 skews = normalize_skew (skews , skew_thresh )
597603
598604 # Calculate the largest contiguous island of non-zeros
599605 skew_flags = skews > 0
600- skews = skew_flags .astype (np .uint8 )
606+ skews = skew_flags .astype (np .uint16 )
601607 islands = get_islands (skews )
602608 islands = [(index + 1 ) * val for index , val in enumerate (islands )]
603609 island = np .hstack (islands )
@@ -1212,14 +1218,15 @@ def find_contour_and_peak(
12121218 # (note that these were computed prior to CDF weighting)
12131219 threshold = peak_db - threshold_std * peak_db_std
12141220
1215- # pad left and right edges to handle signal that extends beyond segment edge
1216- segment_pad = np .pad (segment , ((0 , 0 ),(1 , 1 )))
1221+ # pad all edges to handle signal that butts up against segment edges
1222+ segment_pad = np .pad (segment , ((2 , 2 ),(2 , 2 )))
12171223 contours = measure .find_contours (
12181224 segment_pad , level = threshold , fully_connected = 'high' , positive_orientation = 'high'
12191225 )
12201226 # remove padding in output contour
12211227 for contour in contours :
1222- contour [:,1 ] -= 1
1228+ contour [:,0 ] -= 2
1229+ contour [:,1 ] -= 2
12231230
12241231 # Display the image and plot all contours found
12251232 if output_path :
@@ -1249,6 +1256,11 @@ def find_contour_and_peak(
12491256
12501257 contour_ = np .vstack ((y , x ), dtype = contour .dtype ).T
12511258 polygon_ = Polygon (contour ).convex_hull
1259+
1260+ # Add small buffer to smoothed contour be sure to include maximum value location.
1261+ polygon = Polygon (contour ).buffer (1.0 )
1262+ xx , yy = polygon .exterior .coords .xy
1263+ contour_ = np .vstack ((xx , yy )).T
12521264 assert idx not in counter
12531265 counter [idx ] = (found , polygon_ )
12541266
@@ -1299,13 +1311,16 @@ def calculate_harmonic_and_echo_flags(
12991311 write_contour_debug_image (negative_ , index , 7 , 'negative' , output_path = output_path )
13001312
13011313 negative_skew = scipy .stats .skew (original [np .logical_and (nonzeros , negative )])
1302- harmonic_skew = scipy .stats .skew (original [np .logical_and (nonzeros , harmonic )]) - negative_skew
1303- if echo .any ():
1304- echo_skew = (
1305- scipy .stats .skew (original [np .logical_and (np .logical_and (nonzeros , echo ), ~ harmonic )])
1306- - negative_skew
1307- )
1308- else :
1314+ with warnings .catch_warnings ():
1315+ # allow for nan outputs in cases of empty or mono-valued selections
1316+ warnings .simplefilter ('ignore' , category = RuntimeWarning )
1317+ selection = np .logical_and (nonzeros , harmonic )
1318+ harmonic_skew = scipy .stats .skew (original [selection ]) - negative_skew
1319+ selection = np .logical_and (np .logical_and (nonzeros , echo ), ~ harmonic )
1320+ echo_skew = scipy .stats .skew (original [selection ]) - negative_skew
1321+ if np .isnan (harmonic_skew ):
1322+ harmonic_skew = - np .inf
1323+ if np .isnan (echo_skew ):
13091324 echo_skew = - np .inf
13101325
13111326 skew_thresh = np .abs (negative_skew * 0.1 )
0 commit comments