Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -853,36 +853,69 @@ async def predict_bloom(req: BloomPredictionRequest):
|
|
| 853 |
|
| 854 |
# Decide status based on peak_score and bell shape
|
| 855 |
bell_ok, bell_diag = is_bell_shaped(list(monthly_perc))
|
| 856 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 857 |
status = "NO_BLOOM"
|
| 858 |
top_species = None
|
| 859 |
bloom_window = None
|
| 860 |
peak_month_out = None
|
| 861 |
peak_prob_out = None
|
| 862 |
-
elif peak_score < MIN_BLOOM_THRESHOLD:
|
| 863 |
-
status = "LOW_CONFIDENCE"
|
| 864 |
-
top_species = None
|
| 865 |
-
bloom_window = [i+1 for i, p in enumerate(monthly_scores) if p > (MIN_BLOOM_THRESHOLD * 0.5)]
|
| 866 |
-
peak_month_out = peak_month
|
| 867 |
-
peak_prob_out = peak_score
|
| 868 |
else:
|
| 869 |
-
|
| 870 |
-
|
| 871 |
-
|
| 872 |
-
|
| 873 |
-
|
| 874 |
-
|
| 875 |
-
|
| 876 |
-
|
| 877 |
-
|
| 878 |
-
|
| 879 |
-
|
| 880 |
-
|
| 881 |
-
|
| 882 |
-
|
| 883 |
-
|
| 884 |
-
|
|
|
|
|
|
|
|
|
|
| 885 |
top_species = None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 886 |
|
| 887 |
processing_time = round(time.time() - start_time, 2)
|
| 888 |
|
|
|
|
| 853 |
|
| 854 |
# Decide status based on peak_score and bell shape
|
| 855 |
bell_ok, bell_diag = is_bell_shaped(list(monthly_perc))
|
| 856 |
+
mean_score = float(np.mean(monthly_scores))
|
| 857 |
+
median_score = float(np.median(monthly_scores))
|
| 858 |
+
near_peak_count = sum(1 for s in monthly_scores if s >= (peak_score * 0.9))
|
| 859 |
+
months_above_threshold = sum(1 for s in monthly_scores if s >= MIN_BLOOM_THRESHOLD)
|
| 860 |
+
|
| 861 |
+
print(f"DEBUG detection: peak_score={peak_score}, mean={mean_score:.2f}, median={median_score:.2f}, near_peak_count={near_peak_count}, months_above_{MIN_BLOOM_THRESHOLD}={months_above_threshold}, bell_ok={bell_ok}, bell_diag={bell_diag}")
|
| 862 |
+
|
| 863 |
+
# Heuristic decision:
|
| 864 |
+
# 1) If the absolute peak is below MIN_PEAK_FOR_BELL -> NO_BLOOM
|
| 865 |
+
if peak_score < MIN_PEAK_FOR_BELL:
|
| 866 |
status = "NO_BLOOM"
|
| 867 |
top_species = None
|
| 868 |
bloom_window = None
|
| 869 |
peak_month_out = None
|
| 870 |
peak_prob_out = None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 871 |
else:
|
| 872 |
+
# 2) If peak is high enough, accept bloom even if not perfectly bell-shaped,
|
| 873 |
+
# unless the season is extremely ambiguous (many months nearly at peak).
|
| 874 |
+
# Use a dominance ratio: peak relative to mean/median.
|
| 875 |
+
dominance_ratio = (peak_score / (mean_score + 1e-9))
|
| 876 |
+
# Criteria to accept bloom:
|
| 877 |
+
accept_bloom = False
|
| 878 |
+
# a) clear bell-shaped + peak high -> accept
|
| 879 |
+
if bell_ok:
|
| 880 |
+
accept_bloom = True
|
| 881 |
+
# b) peak strongly dominates the rest -> accept
|
| 882 |
+
elif dominance_ratio >= 1.25 and near_peak_count <= 4:
|
| 883 |
+
accept_bloom = True
|
| 884 |
+
# c) several months above bloom threshold (broad season) but peak high -> accept but mark low confidence
|
| 885 |
+
elif months_above_threshold >= 3 and peak_score >= (MIN_BLOOM_THRESHOLD + 10):
|
| 886 |
+
accept_bloom = True
|
| 887 |
+
|
| 888 |
+
if not accept_bloom:
|
| 889 |
+
# Ambiguous/flat high-months case -> LOW_CONFIDENCE
|
| 890 |
+
status = "LOW_CONFIDENCE"
|
| 891 |
top_species = None
|
| 892 |
+
bloom_window = [i+1 for i, s in enumerate(monthly_scores) if s > (MIN_BLOOM_THRESHOLD * 0.5)]
|
| 893 |
+
peak_month_out = peak_month
|
| 894 |
+
peak_prob_out = peak_score
|
| 895 |
+
else:
|
| 896 |
+
# Strong enough to declare bloom
|
| 897 |
+
# If the peak is only moderately high, use LOW_CONFIDENCE; otherwise BLOOM_DETECTED
|
| 898 |
+
if peak_score < (MIN_BLOOM_THRESHOLD + 5):
|
| 899 |
+
status = "LOW_CONFIDENCE"
|
| 900 |
+
else:
|
| 901 |
+
status = "BLOOM_DETECTED"
|
| 902 |
+
|
| 903 |
+
bloom_window = [i+1 for i, p in enumerate(monthly_scores) if p > MIN_BLOOM_THRESHOLD]
|
| 904 |
+
peak_month_out = peak_month
|
| 905 |
+
peak_prob_out = peak_score
|
| 906 |
+
|
| 907 |
+
# species prediction when we accept bloom
|
| 908 |
+
try:
|
| 909 |
+
peak_result = monthly_results[peak_idx]
|
| 910 |
+
if isinstance(peak_result, dict):
|
| 911 |
+
doy = peak_result.get("day_of_year")
|
| 912 |
+
else:
|
| 913 |
+
doy = date(year, peak_month, 15).timetuple().tm_yday
|
| 914 |
+
species_predictions = predict_species_by_elevation(elevation, doy=doy, top_k=TOP_K_SPECIES)
|
| 915 |
+
top_species = [SpeciesResult(name=sp, probability=round(prob * 100.0, 2)) for sp, prob in species_predictions]
|
| 916 |
+
except Exception as e:
|
| 917 |
+
print(f"❌ species prediction error at final stage: {e}")
|
| 918 |
+
top_species = None
|
| 919 |
|
| 920 |
processing_time = round(time.time() - start_time, 2)
|
| 921 |
|