Individual persistence
In [1]:
Copied!
# Uncomment below to run in Google Collab
# pip install ecospat
# Uncomment below to run in Google Collab
# pip install ecospat
Categorizing and visualizing individual persistence¶
In [2]:
Copied!
import ecospat.ecospat as ecospat_full
from ecospat.stand_alone_functions import (
process_species_historical_range,
analyze_species_distribution,
analyze_northward_shift,
calculate_rate_of_change_first_last,
merge_category_dataframes,
prepare_gdf_for_rasterization,
cat_int_mapping,
rasterize_multiband_gdf_match,
compute_propagule_pressure_range,
compute_individual_persistence,
)
import ecospat.ecospat as ecospat_full
from ecospat.stand_alone_functions import (
process_species_historical_range,
analyze_species_distribution,
analyze_northward_shift,
calculate_rate_of_change_first_last,
merge_category_dataframes,
prepare_gdf_for_rasterization,
cat_int_mapping,
rasterize_multiband_gdf_match,
compute_propagule_pressure_range,
compute_individual_persistence,
)
Historic range edges¶
In [3]:
Copied!
hist_pipeline = ecospat_full.Map()
hist_range = process_species_historical_range(
new_map=hist_pipeline, species_name="Populus angustifolia"
)
hist_pipeline = ecospat_full.Map()
hist_range = process_species_historical_range(
new_map=hist_pipeline, species_name="Populus angustifolia"
)
No overlapping polygons found — returning original classifications.
Modern range edges and historical population data¶
In [4]:
Copied!
classified_modern, classified_historic = analyze_species_distribution(
"Populus angustifolia", record_limit=1000, continent="north_america"
)
classified_modern, classified_historic = analyze_species_distribution(
"Populus angustifolia", record_limit=1000, continent="north_america"
)
Modern records (>= 1976): 1000 Historic records (< 1976): 254
Northward shift¶
In [5]:
Copied!
northward_rate_df = analyze_northward_shift(
gdf_hist=hist_range,
gdf_new=classified_modern,
species_name="Populus angustifolia",
)
northward_rate_df = northward_rate_df[
northward_rate_df["category"].isin(["leading", "core", "trailing"])
]
northward_rate_df["category"] = northward_rate_df["category"].str.title()
northward_rate_df = analyze_northward_shift(
gdf_hist=hist_range,
gdf_new=classified_modern,
species_name="Populus angustifolia",
)
northward_rate_df = northward_rate_df[
northward_rate_df["category"].isin(["leading", "core", "trailing"])
]
northward_rate_df["category"] = northward_rate_df["category"].str.title()
Population density change¶
In [6]:
Copied!
change = calculate_rate_of_change_first_last(
classified_historic, classified_modern, "Populus angustifolia", custom_end_year=2025
)
change = change[change["collapsed_category"].isin(["leading", "core", "trailing"])]
change = change.rename(
columns={
"collapsed_category": "Category",
"rate_of_change_first_last": "Rate of Change",
"start_time_period": "Start Years",
"end_time_period": "End Years",
}
)
change["Category"] = change["Category"].str.title()
change = calculate_rate_of_change_first_last(
classified_historic, classified_modern, "Populus angustifolia", custom_end_year=2025
)
change = change[change["collapsed_category"].isin(["leading", "core", "trailing"])]
change = change.rename(
columns={
"collapsed_category": "Category",
"rate_of_change_first_last": "Rate of Change",
"start_time_period": "Start Years",
"end_time_period": "End Years",
}
)
change["Category"] = change["Category"].str.title()
Prepare data for rasterization¶
In [7]:
Copied!
merged = merge_category_dataframes(northward_rate_df, change)
preped_gdf = prepare_gdf_for_rasterization(classified_modern, merged)
preped_gdf_new = cat_int_mapping(preped_gdf)
preped_gdf_new.head()
merged = merge_category_dataframes(northward_rate_df, change)
preped_gdf = prepare_gdf_for_rasterization(classified_modern, merged)
preped_gdf_new = cat_int_mapping(preped_gdf)
preped_gdf_new.head()
Out[7]:
| geometry | category | density | northward_rate_km_per_year | Rate of Change | category_int | |
|---|---|---|---|---|---|---|
| 0 | POLYGON ((-112.16175 40.79402, -112.1358 40.81... | Core | 0.003597 | -1.736134 | 1.115629 | 1.0 |
| 188 | POLYGON ((-108.48788 37.47497, -107.24964 39.5... | Core | 0.001869 | -1.736134 | 1.115629 | 1.0 |
| 446 | POLYGON ((-112.38734 38.88478, -110.89519 38.3... | Trailing (0.05) | 0.001117 | 0.000000 | 0.000000 | NaN |
| 481 | POLYGON ((-111.90918 43.82033, -111.86789 43.8... | Leading (0.95) | 0.005273 | 0.000000 | 0.000000 | NaN |
| 515 | POLYGON ((-108.24095 32.90245, -108.271 33.225... | Relict (0.01 Latitude) | 0.010924 | 0.000000 | 0.000000 | NaN |
In [8]:
Copied!
value_columns = [
"density",
"northward_rate_km_per_year",
"Rate of Change",
"category_int",
]
raster_show, transform, show_bounds = rasterize_multiband_gdf_match(
preped_gdf_new, value_columns
)
value_columns = [
"density",
"northward_rate_km_per_year",
"Rate of Change",
"category_int",
]
raster_show, transform, show_bounds = rasterize_multiband_gdf_match(
preped_gdf_new, value_columns
)
Rasterize data and compute propagule pressure¶
In [9]:
Copied!
pressure_show = compute_propagule_pressure_range(raster_show)
pressure_show = compute_propagule_pressure_range(raster_show)
Compute individual persistence¶
In [10]:
Copied!
points = compute_individual_persistence(
points_gdf=classified_modern,
raster_stack_arrays=raster_show,
propagule_array=pressure_show,
baseline_death=0.10,
transform=transform,
)
points.head()
points = compute_individual_persistence(
points_gdf=classified_modern,
raster_stack_arrays=raster_show,
propagule_array=pressure_show,
baseline_death=0.10,
transform=transform,
)
points.head()
Out[10]:
| point_id | P_1y | P_5y | density_vals | northward_vals | abundance_change_vals | edge_vals | propagule_vals | risk_decile | baseline_death | P_1y_vs_baseline | P_5y_vs_baseline | north_south_of_category_centroid | point_geometry | geometry | geometry_id | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0 | 0.867547 | 0.491434 | 0.003597 | -1.736134 | 1.115629 | core | 0.169574 | 7 | 0.1 | lower | lower | north | POINT (-111.840163 40.880712) | POLYGON ((-112.16175 40.79402, -112.1358 40.81... | cb869cb2640256dc655c5ffd650a009f |
| 1 | 1 | 0.868386 | 0.493814 | 0.003597 | -1.736134 | 1.115629 | core | 0.186114 | 6 | 0.1 | lower | lower | north | POINT (-111.467794 40.775008) | POLYGON ((-112.16175 40.79402, -112.1358 40.81... | cb869cb2640256dc655c5ffd650a009f |
| 2 | 2 | 0.863260 | 0.479412 | 0.003597 | -1.736134 | 1.115629 | core | 0.078682 | 10 | 0.1 | lower | lower | north | POINT (-110.869423 39.731437) | POLYGON ((-112.16175 40.79402, -112.1358 40.81... | cb869cb2640256dc655c5ffd650a009f |
| 3 | 3 | 0.867735 | 0.491968 | 0.003597 | -1.736134 | 1.115629 | core | 0.173321 | 7 | 0.1 | lower | lower | north | POINT (-111.826781 40.765911) | POLYGON ((-112.16175 40.79402, -112.1358 40.81... | cb869cb2640256dc655c5ffd650a009f |
| 4 | 4 | 0.867247 | 0.490584 | 0.003597 | -1.736134 | 1.115629 | core | 0.163558 | 8 | 0.1 | lower | lower | north | POINT (-111.830586 40.497927) | POLYGON ((-112.16175 40.79402, -112.1358 40.81... | cb869cb2640256dc655c5ffd650a009f |
In [11]:
Copied!
point_map_new = ecospat_full.Map()
point_map_new.add_basemap("GBIF.Classic")
point_map_new.add_point_data(points, use_gradient=True)
point_map_new
point_map_new = ecospat_full.Map()
point_map_new.add_basemap("GBIF.Classic")
point_map_new.add_point_data(points, use_gradient=True)
point_map_new
Out[11]: