Skip to content

Commit

Permalink
Merge changes from tobac-project#251 into hotfix_v1.4.2
Browse files Browse the repository at this point in the history
  • Loading branch information
Juli committed Feb 21, 2023
2 parents 09baabb + 8dcb567 commit a99d1cc
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 18 deletions.
51 changes: 38 additions & 13 deletions tobac/feature_detection.py
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,7 @@ def feature_detection_multithreshold(
# Loop over DataFrame to remove features that are closer than distance_min to each other:
if min_distance > 0:
features_thresholds = filter_min_distance(
features_thresholds, dxy, min_distance
features_thresholds, dxy, min_distance, target=target
)
list_features_timesteps.append(features_thresholds)

Expand All @@ -701,7 +701,7 @@ def feature_detection_multithreshold(
return features


def filter_min_distance(features, dxy, min_distance):
def filter_min_distance(features, dxy, min_distance, target="maximum"):
"""Perform feature detection based on contiguous regions.
Regions are above/below a threshold.
Expand All @@ -716,6 +716,10 @@ def filter_min_distance(features, dxy, min_distance):
min_distance : float, optional
Minimum distance (in meter) between detected features.
target : str {maximum | minimum}, optional
Whether the threshod target is a maxima or minima (defaults to
maximum)
Returns
-------
features : pandas.DataFrame
Expand All @@ -724,6 +728,11 @@ def filter_min_distance(features, dxy, min_distance):

from itertools import combinations

if target not in ["minimum", "maximum"]:
raise ValueError(
"target parameter must be set to either 'minimum' or 'maximum'"
)

remove_list_distance = []
# create list of tuples with all combinations of features at the timestep:
indices = combinations(features.index.values, 2)
Expand All @@ -737,26 +746,42 @@ def filter_min_distance(features, dxy, min_distance):
** 2
)
if distance <= min_distance:
# logging.debug('distance<= min_distance: ' + str(distance))
# If same threshold value, remove based on number of pixels
if (
features.loc[index_1, "threshold_value"]
> features.loc[index_2, "threshold_value"]
):
remove_list_distance.append(index_2)
elif (
features.loc[index_1, "threshold_value"]
< features.loc[index_2, "threshold_value"]
):
remove_list_distance.append(index_1)
elif (
features.loc[index_1, "threshold_value"]
== features.loc[index_2, "threshold_value"]
):
if features.loc[index_1, "num"] > features.loc[index_2, "num"]:
remove_list_distance.append(index_2)
elif features.loc[index_1, "num"] < features.loc[index_2, "num"]:
remove_list_distance.append(index_1)
# Tie break if both have the same number of pixels
elif features.loc[index_1, "num"] == features.loc[index_2, "num"]:
remove_list_distance.append(index_2)
# Else remove based on comparison of thresholds and target
elif target == "maximum":
if (
features.loc[index_1, "threshold_value"]
> features.loc[index_2, "threshold_value"]
):
remove_list_distance.append(index_2)
elif (
features.loc[index_1, "threshold_value"]
< features.loc[index_2, "threshold_value"]
):
remove_list_distance.append(index_1)

elif target == "minimum":
if (
features.loc[index_1, "threshold_value"]
< features.loc[index_2, "threshold_value"]
):
remove_list_distance.append(index_2)
elif (
features.loc[index_1, "threshold_value"]
> features.loc[index_2, "threshold_value"]
):
remove_list_distance.append(index_1)

features = features[~features.index.isin(remove_list_distance)]
return features
20 changes: 17 additions & 3 deletions tobac/tests/test_feature_detection.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ def test_filter_min_distance(test_threshs, min_distance, dxy):
## add another blob with smaller value
test_hdim_1_pt2 = 25.0
test_hdim_2_pt2 = 25.0
test_hdim_1_sz2 = 2
test_hdim_2_sz2 = 2
test_hdim_1_sz2 = 3
test_hdim_2_sz2 = 3
test_amp2 = 3
test_data = tbtest.make_feature_blob(
test_data,
Expand All @@ -107,7 +107,9 @@ def test_filter_min_distance(test_threshs, min_distance, dxy):
)

# check if it function to filter
fd_filtered = feat_detect.filter_min_distance(fd_output, dxy, min_distance)
fd_filtered = feat_detect.filter_min_distance(
fd_output, dxy, min_distance, target="maximum"
)

# Make sure we have only one feature (small feature in minimum distance should be removed )
assert len(fd_output.index) == 2
Expand All @@ -116,6 +118,18 @@ def test_filter_min_distance(test_threshs, min_distance, dxy):
assert fd_filtered.iloc[0]["hdim_1"] == pytest.approx(test_hdim_1_pt)
assert fd_filtered.iloc[0]["hdim_2"] == pytest.approx(test_hdim_2_pt)

# check if it function to filter
fd_filtered = feat_detect.filter_min_distance(
fd_output, dxy, min_distance, target="minimum"
)

# Make sure we have only one feature (small feature in minimum distance should be removed )
assert len(fd_output.index) == 2
assert len(fd_filtered.index) == 1
# Make sure that the locations of the features is correct (should correspond to locations of second feature)
assert fd_filtered.iloc[0]["hdim_1"] == pytest.approx(test_hdim_1_pt2)
assert fd_filtered.iloc[0]["hdim_2"] == pytest.approx(test_hdim_2_pt2)


@pytest.mark.parametrize(
"position_threshold", [("center"), ("extreme"), ("weighted_diff"), ("weighted_abs")]
Expand Down
8 changes: 6 additions & 2 deletions tobac/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -557,11 +557,15 @@ def add_coordinates(t, variable_cube):

if variable_cube.coord_dims(coord) == (hdim_1, hdim_2):
f = interp2d(dimvec_2, dimvec_1, variable_cube.coord(coord).points)
coordinate_points = [f(a, b) for a, b in zip(t["hdim_2"], t["hdim_1"])]
coordinate_points = np.asarray(
[f(a, b) for a, b in zip(t["hdim_2"], t["hdim_1"])]
)

if variable_cube.coord_dims(coord) == (hdim_2, hdim_1):
f = interp2d(dimvec_1, dimvec_2, variable_cube.coord(coord).points)
coordinate_points = [f(a, b) for a, b in zip(t["hdim_1"], t["hdim_2"])]
coordinate_points = np.asarray(
[f(a, b) for a, b in zip(t["hdim_1"], t["hdim_2"])]
)

# interpolate 3D coordinates:
# mainly workaround for wrf latitude and longitude (to be fixed in future)
Expand Down

0 comments on commit a99d1cc

Please sign in to comment.