---  
title:  "Explore Interpolation of SDMs"  
editor:  visual  
execute:  
  warning: false  
editor_options:    
  chunk_output_type: console  
---  
 
 Sources: 
 
-    AquaMaps raster from env REsuitability 
    -    Get a few species with different geographic traits, starting with species in Gulf of America: 
        -    small range, high density 
        -    large range, low density 
-    Bottom Trawl from IDW 
-    Other: GoMex hexagons from complex SDM 
 
 Topologies: 
 
-  raster: 
  -  1/12° (0.083°)\ 
     CopernicusMarine 
     VGPM 
  -  1/20° (0.050°)\ 
     BioOracle 
-  hexagon: 
  -  Uber H3 
 
 Methods: 
 
-    "chunky": interpolate from underlying values 
-    "smooth": interpolate from centroid points 
-    "remap": re-ramp environmental envelope from higher resolution data 
    -  only AquaMaps, possibly DisMAP 
 
 Background: 
 
-  [ MarineSDMs - Explorations ](https://marinebon.github.io/MarineSDMs/explorations.html)  
-  [ MarineSDMs - AquaMaps Downscaled ](https://marinebon.github.io/MarineSDMs/explorations/am-fine.html)  
-  [ marinebon/aquamaps-downscaled: initial attempt to downscale AquaMaps species distribution models to finer spatial resolution a la GEBCO bathymetry (15 arc second) ](https://github.com/marinebon/aquamaps-downscaled/tree/main)  
-  [ aquamaps-downscaled/index.qmd at main · marinebon/aquamaps-downscaled ](https://github.com/marinebon/aquamaps-downscaled/blob/503c62f39552c4ad2417413b13c49d4d4405f3ab/index.qmd)  
-  [ Downscaling AquaMaps ](https://marinebon.github.io/aquamaps-downscaled/)  
-  [ aquamaps-downscaled/am-env\_to\_ee.qmd at main · marinebon/aquamaps-downscaled ](https://github.com/marinebon/aquamaps-downscaled/blob/main/am-env_to_ee.qmd)  
 
## AquaMaps duckdb database  
 
```{r}  
#| label: setup  
 
 librarian:: shelf ( 
   cmocean, DBI, dplyr, DT, duckdb, fs, glue, here, htmltools, janitor, knitr, 
   leaflet, leaflet.extras, librarian, mapview, 
   # raquamaps/raquamaps,  
   marinesensitivity/ msens, 
   RColorBrewer, readr, sf, stringr, terra, tibble, tidyr, 
   quiet =  T)  # zeallot  
mapviewOptions (basemaps =  "Esri.OceanBasemap" ) 
 
 dir_data <-  "~/My Drive/projects/msens/data"  
 path_dd  <-  glue ("{dir_data}/derived/aquamaps/am.duckdb" ) 
 
 con_dd   <-  dbConnect ( 
   duckdb ( 
     dbdir     =  path_dd, 
     read_only =  T)) 
# dbDisconnect(con_dd, shutdown = T)  
# dbListTables(con_dd)  
#   "_tbl_fld_renames" "cells" "spp" "spp_cells" "spp_occs" "spp_prefs"  
tbl (con_dd, "_tbl_fld_renames" ) |>   
   collect () |>   
   datatable () 
```  
 
## Gulf of America  
 
 R package [ `msens` ](https://marinesensitivity.org/msens/news/index.html#msens-020) : `ply_boemrgns`  \>  `ply_ecorgns`  \| `ply_planareas`  \>  `ply_ecoareas`  
 
 TODO: 
 
-    [ ]  Rename Gulf of Mexico to Gulf of America 
    -    `boemrgn_key` : "brGOM" -\>  "brGOA" 
    -    `boemrgn_name` : "Gulf of Mexico" -\>  "Gulf of America" 
 
```{r}  
#| label: spp_goa  
 
# st_bbox(msens::ply_boemrgns)  
#      xmin      ymin      xmax      ymax   
# 166.95776  23.78077 295.89167  74.99636  
#   so [0,360], not [-180, 180]  
 
 goa <-  msens:: ply_boemrgns |>   
   filter (boemrgn_key ==  "brGOM" ) |>   
   st_wrap_dateline ()    # [   0, 360] -> [-180, 180]  
# st_shift_longitude()  # [-180, 180] -> [    0,360]  
 
# st_bbox(goa)  
# xmin      ymin      xmax      ymax   
# -97.23899  23.78077 -81.17011  30.28910  
mapView (goa) 
```  
 
## Get species in Gulf of America  
 
```{r}  
# get cells within goa  
 pt_cell <-  tbl (con_dd, "cells" ) |>   
   collect () |>   
   st_as_sf ( 
     coords =  c ("center_long" , "center_lat" ), crs =  4326 , remove =  F) 
 pt_cell_goa <-  st_intersection (pt_cell, goa) 
 
# get species in gom  
 d_sp_goa <-  tbl (con_dd, "spp_cells" ) |>   
   filter (cell_id %in%  pt_cell_goa$ cell_id) |>  
   group_by (sp_key) |>  
   collect () 
 
# get species ranges by n_cells  
 d_sp_goa_rng <-  tbl (con_dd, "spp_cells" ) |>   
   filter (sp_key %in%  d_sp_goa$ sp_key) |>   
   group_by (sp_key) |>  
   summarize ( 
     n_cells =  n (), .groups =  "drop" ) |>  
   left_join ( 
     tbl (con_dd, "spp" ),  
     by =  "sp_key" ) |>  
   arrange (n_cells) |>   
   collect () 
 
bind_rows ( 
   slice (d_sp_goa_rng, 1 : 100 ), 
   slice (d_sp_goa_rng, (n () -  99 ): n ())) |>   
   datatable ( 
     caption =  htmltools:: tags$ caption ( 
       style =  'caption-side: top; text-align: left;' , 
       withTags (div (HTML ( 
         glue ("  
      Table. <i>Species in Gulf of America (n = {format(nrow(d_sp_goa_rng), big.mark=',')}),   
      subset to first 100 species and last 100 species,  
      sorted by range size (n_cells).</i>" )))))) 
```  
 
## Get AquaMaps env data  
 
```{r}  
#| label: am_hcaf_env  
 
# source: https://github.com/marinebon/aquamaps-downscaled/blob/main/am-env_to_ee.qmd  
 
 h_tif  <-  here ("data/am-hcaf.tif" ) 
 
if  (! file.exists (h_tif)){ 
   # get aquamaps table of env values ----  
   # d_cells <- tbl(con_dd, "cells") |>   
   #   collect()  
    
   # raster template ----  
   # range(d$ctr_lon)  # -179.75  179.75  
   # range(d$ctr_lat)  # - 78.25   89.75  
   # r_template <- rast(  
   #   xmin       = min(d_cells$center_long) - 0.25,  
   #   xmax       = max(d_cells$center_long) + 0.25,  
   #   ymin       = min(d_cells$center_lat) - 0.25,  
   #   ymax       = max(d_cells$center_lat) + 0.25,  
   #   resolution = c(0.5, 0.5),  
   #   crs = "epsg:4326")  
    
   # Create the global template raster  
   xmin <-  - 180 ; xmax <-  180  
   ymin <-   - 90 ; ymax <-   90  
   res  <-     0.5   # Half-degree resolution  
    
   r_g <-  rast ( 
     nrows =  (ymax -  ymin) /  res, 
     ncols =  (xmax -  xmin) /  res, 
     xmin =  xmin, 
     xmax =  xmax, 
     ymin =  ymin, 
     ymax =  ymax, 
     crs =  "EPSG:4326" ) 
    
   # data frame to points ----  
   p <-  tbl (con_dd, "cells" ) |>   
     collect () |>  
     st_as_sf ( 
       coords =  c ("center_long" , "center_lat" ), 
       remove =  F, 
       crs    =  4326 ) |>   
     arrange (center_long, center_lat) 
 
   # points to raster ----  
   get_r <-  function (v){ 
     r <-  rasterize (p, r_g, field =  v) 
     names (r) <-  v 
     r 
   } 
    
   r_h <-  NULL  
   for  (v in  setdiff (names (p), "geometry" )){ 
     message (glue ("v: {v}" )) 
      
     if  (is.null (r_h)){ 
       r_h <-  get_r (v) 
     } else  { 
       r_h <-  rast (list (r_h, get_r (v))) 
     } 
   } 
    
   writeRaster (r_h, h_tif, overwrite= T) 
 } 
 r_h <-  rast (h_tif) 
 
# names(r_h)  
#  [1] "cell_id"            "cell_idx"           "csquare_code"       "loiczid"             
#  [5] "n_limit"            "s_limit"            "w_limit"            "e_limit"             
#  [9] "center_lat"         "center_long"        "cell_area"          "ocean_area"          
# [13] "p_water"            "clim_zone_code"     "fao_area_m"         "fao_area_in"         
# [17] "country_main"       "country_second"     "country_third"      "country_sub_main"    
# [21] "country_sub_second" "country_sub_third"  "eez"                "lme"                 
# [25] "lme_border"         "meow"               "ocean_basin"        "islands_no"          
# [29] "area0_20"           "area20_40"          "area40_60"          "area60_80"           
# [33] "area80_100"         "area_below100"      "elevation_min"      "elevation_max"       
# [37] "elevation_mean"     "elevation_sd"       "depth_min"          "depth_max"           
# [41] "depth_mean"         "depth_sd"           "sst_an_mean"        "sbt_an_mean"         
# [45] "salinity_mean"      "salinity_b_mean"    "prim_prod_mean"     "ice_con_ann"         
# [49] "oxy_mean"           "oxy_b_mean"         "land_dist"          "shelf"               
# [53] "slope"              "abyssal"            "tidal_range"        "coral"               
# [57] "estuary"            "seamount"           "mpa"  
 
# plot to check  
#  static:  
#    plot(r_h[["center_lat"]])  
#    plot(r_h[["center_long"]])  
#  dynamic:  
#    plet(r_h[["center_lat"]])  
#    plet(r_h[["center_long"]])  
 
 lyr <-  "depth_mean" ; clr <-  "dense"  
mapView ( 
   r_h[[lyr]], layer.name =  lyr, 
   col.regions =  cmocean (clr), 
   alpha.regions =  0.9 ) 
 
 lyr <-  "prim_prod_mean" ; clr <-  "algae"  
mapView ( 
   r_h[[lyr]], layer.name =  lyr, 
   col.regions =  cmocean (clr), 
   alpha.regions =  0.9 ) 
 
 lyr <-  "sst_an_mean" ; clr <-  "thermal"  
mapView ( 
   r_h[[lyr]], layer.name =  lyr, 
   col.regions =  cmocean (clr), 
   alpha.regions =  0.9 ) 
 
 lyr <-  "sbt_an_mean" ; clr <-  "thermal"  
mapView ( 
   r_h[[lyr]], layer.name =  lyr, 
   col.regions =  cmocean (clr), 
   alpha.regions =  0.9 ) 
```  
 
## Get species attributes  
 
-  [ Computer Generated Native Distribution Map for _Crepidula depressa_ ](https://aquamaps.org/preMap2.php?cache=1&SpecID=W-Msc-419703)  
     
-  [ Mapping Parameters ](https://www.aquamaps.org/ShowMapParam.php?SpecID=W-Msc-419703&graph=&user_session=1&bp=-1)  
 
-  `"W-Msc-419703"` : _Crepidula depressa_ (class = Gastropoda) n_cells = 50 
 
```{r}  
#| label: get_sp_pref  
 
 sp_key <-  "W-Msc-419703"  
 
 d_sp_pref <-  tbl (con_dd, "spp_prefs" ) |>   
   filter (sp_key ==  !! sp_key) |>   
   collect () 
 
 d_sp_pref |>   
   mutate (across (everything (), as.character)) |>   
   pivot_longer (everything ()) |>   
   kable () 
```  
 
 TODO: 
 
-  [ ]  Reconcile differences in bbox and FAO areas vs online. 
 
```{r}  
 librarian:: shelf ( 
   ggplot2, listviewer, scales) 
 
 get_sp_info <-  function (sp_key){ 
# source: https://github.com/marinebon/aquamaps-downscaled/blob/503c62f39552c4ad2417413b13c49d4d4405f3ab/sp-map/functions.R#L92C5-L93C30  
 
   d_prefs <-  tbl (con_dd, "spp_prefs" ) |>   
       filter (sp_key ==  !! sp_key) |>  
       collect () 
 
   vars_yes <-  d_prefs |>   
     select (ends_with ("_yn" )) |>   
     pivot_longer ( 
       everything ()) |>   
     filter (value ==  1 ) |>   
     pull (name) |>   
     str_replace ("_yn$" ,"" ) |>   
     setdiff ("extn_rule" ) 
    
   d_probs <-  tribble ( 
     ~ prob_name, ~ prob_value, 
     "min"      , 0 , 
     "pref_min" , 1 , 
     "pref_max" , 1 , 
     "max"      , 0 ) 
    
   # browser()  
   d_env <-  d_prefs |>   
     select (starts_with (vars_yes)) |>  
     select (! ends_with ("_yn" )) |>   
     pivot_longer ( 
       everything (), 
       values_to =  "var_value" ) |>   
     separate_wider_regex ( 
       name, 
       c (var       =  paste (vars_yes, collapse =  "|" ), 
         "_" , 
         prob_name =  paste (d_probs$ prob_name, collapse =  "|" ))) |>   
     left_join ( 
       d_probs, 
       by =  "prob_name" ) 
    
   l_env <-  d_env |>   
     group_by (var) |>   
     summarise ( 
       vec =  list (var_value)) |>   
     deframe () 
    
   sp_info <-  list () 
    
   d_sp <-  tbl (con_dd, "spp" ) |>   
     filter (sp_key ==  !! sp_key) |>   
     collect () |>   
     mutate ( 
       sp_sci =  glue ("{genus} {species}" )) 
   sp_info["sp_scientific" ] <-  list (d_sp$ sp_sci) 
   sp_info["sp_key" ]        <-  list (d_sp$ sp_key) 
   sp_info["sp_int" ]        <-  list (d_sp$ sp_int) 
    
   sp_info["fao_areas" ] <-  d_prefs$ fao_areas |>   
     str_split (", \\ s*" ) |>   
     str_trim () |>   
     unlist () |>   
     as.numeric () |>   
     sort () 
    
   sp_info["env" ] <-  list (l_env) 
    
   sp_info$ taxa <-  d_sp |>   
       select (kingdom, phylum, class, order, family) |>   
       pivot_longer (everything ()) |>   
       deframe () |>   
       as.list () 
    
   sp_info$ attr <-  d_sp |>   
     select ( 
       deepwater, angling, diving, dangerous, m_invertebrates,  
       highseas, invasive, resilience) |>   
     mutate (across (everything (), as.character)) |>   
     pivot_longer (everything ()) |>   
     deframe () |>   
     as.list () 
    
   sp_info$ iucn <-  d_sp |>   
     select ( 
       iucn_id, iucn_code, iucn_version, provider) |>   
     mutate (across (everything (), as.character)) |>   
     pivot_longer (everything ()) |>   
     deframe () |>   
     as.list () 
    
   # deepwater,        # Does the species occur in the deep-sea (i.e. tagged bathypelagic or bathydemersal in FishBase or SeaLifeBase)? 0=No, 1=Yes  
   # angling,          # Is the species a sport fish (i.e. tagged as a GameFish in FishBase)? 0=No, 1=Yes  
   # diving,           # Is the species found on a dive (i.e. where DepthPrefMin in HSPEN < 20 meters)? 0=No, 1=Yes  
   # dangerous,        # Is the species dangerous (i.e. tagged as ‘traumatogenic or venonous’ in FishBase or SeaLifeBase)? 0=No, 1=Yes  
   # m_invertebrates,  # Is the species a marine invertebrate? 0=No, 1=Yes  
   # highseas,         # Is the species an open ocean fish species (i.e. tagged as pelagic-oceanic in FishBase)? 0=No, 1=Yes  
   # invasive,         # Is the species recorded to be invasive (i.e. in FishBase or SeaLifeBase)? 0=No, 1=Yes  
   # resilience,       # Resilience of the species (i.e. as recorded in FishBase/SeaLifeBase) [varchar]  
   # iucn_id,          # IUCN species identifier [int]  
   # iucn_code,        # IUCN Red list classification assigned to the species [varchar]  
   # iucn_version,     # IUCN version [varchar]  
   # provider) |>      # FishBase (FB) or SeaLifeBase (SLB)? [varchar]  
    
   sp_info 
 } 
 
 sp_info <-  get_sp_info (sp_key) 
 
 plot_sp_env <-  function (sp_info){ 
 
     d <-  sp_info$ env |>   
       enframe (name =  "variable" ) |>   
       mutate ( 
         suitability =  list (c (0 ,1 ,1 ,0 ))) |>   
       unnest (c (value, suitability)) 
      
     g <-  ggplot (d, aes (value, suitability)) +  
       geom_area () +  
       scale_y_continuous (labels =  percent) +  
       facet_wrap ( 
         vars (variable),  
         scales =  "free" ) +  
       labs ( 
         title    =  sp_info$ sp_scientific, 
         subtitle =  "environmental envelope" , 
         x        =  NULL , 
         y        =  "Suitability" ) +  
       theme_gray () 
      
     g 
 } 
 
plot_sp_env (sp_info) 
 
jsonedit ( 
   sp_info, mode =  "view" , modes =  c ("view" ,"code" )) 
```  
 
 
## Compare with native `aquamapsdata`  
 
```{r}  
# dependency for aquamapsdata:  
#  - Terminal: brew install gnupg  
 librarian:: shelf ( 
   cran/ rcrypt, 
   raquamaps/ aquamapsdata, 
   dplyr) 
 
# initial run-once step required to install remote db locally  
# download_db(force = TRUE)  
 
default_db ("sqlite" ) 
 
# get the identifier for the species  
 ras <-  am_raster (sp_key) 
 b <-  ext (ras) |>  as.vector () |>  as.numeric () 
 
# show the native habitat map  
am_map_leaflet (ras, title =  sp_key) |>   
   leaflet:: fitBounds ( 
     lng1 =  b[1 ], lat1 =  b[3 ], lng2 =  b[2 ], lat2 =  b[4 ]) 
#   xmin   xmax   ymin   ymax   
# -97.75 -76.75  26.25  29.75  
    
# use one or more keys for species  
am_hspen () |>   
   filter (SpeciesID ==  sp_key) |>   
   head (1 ) |>   
   collapse () |>   
   glimpse () 
# $ FAOAreas        <chr> "31"  
# $ FAOComplete     <int> NA  
# $ NMostLat        <dbl> 30  
# $ SMostLat        <dbl> 26  
# $ WMostLong       <dbl> 97  
# $ EMostLong       <dbl> 80  
```  
 
## Custom Leaflet functions  
 
```{r}  
#| label: custom leaflet functions  
 
 add_ocean_basemap <-  function (m){ 
   # m: leaflet() map  
    
   m |>  
     # add base: blue bathymetry and light brown/green topography  
     addProviderTiles ( 
       "Esri.OceanBasemap" , 
       options =  providerTileOptions ( 
         variant =  "Ocean/World_Ocean_Base" )) |>  
     # add reference: placename labels and borders  
     addProviderTiles ( 
       "Esri.OceanBasemap" , 
       options =  providerTileOptions ( 
         variant =  "Ocean/World_Ocean_Reference" )) 
 } 
 
 
# show the native habitat map  
 add_am_rast <-  function ( 
     m,  
     r, 
     id =  "am_rast" , 
     title, 
     cols =  c ("#FEB24C" , "#FD8D3C" , "#FC4E2A" , "#E31A1C" , "#B10026" ), 
     truncate_to_zero =  T){ 
   # m: leaflet() map  
   # r: raster   
   #  TODO : migrate to terra::rast()  
    
   # r     = r_gebco_bb  
   # title = "GEBCO depth (m)"  
   # cols  = RColorBrewer::brewer.pal(7, "Blues")  
    
   r   <-  leaflet:: projectRasterForLeaflet (r, method =  "bilinear" ) 
    
   # truncate to 0 to prevent negative values   
   #   that were generated by projecting the raster   
   #   from geographic projection (decimal degrees) to Web Mercator (meters)  
   if  (truncate_to_zero){ 
     v <-  values (r) 
     v[v< 0 ] <-  0  
     values (r) <-  v 
   } 
    
   pal <-  leaflet:: colorBin ( 
     cols, na.omit (unique (values (r))),  
     bins =  length (cols), pretty =  TRUE , na.color =  "#00000000" ) 
    
   e <-  terra:: ext (r) |>   
     sf:: st_bbox () |>   
     st_as_sfc () |>   
     st_as_sf (crs= 3857 ) |>   
     st_transform (4326 ) |>   
     st_bbox () 
      
   m |>   
     leaflet:: addRasterImage ( 
       r,  
       layerId =  id, group =  id, 
       project =  F, colors =  pal, opacity =  0.8 ) |>   
     leaflet:: addLegend ( 
       values =  raster:: values (r),  
       title =  title, pal =  pal) |>   
     leaflet:: fitBounds ( 
       lng1 =  e[["xmin" ]],  
       lat1 =  e[["ymin" ]],  
       lng2 =  e[["xmax" ]],  
       lat2 =  e[["ymax" ]]) |>   
     addImageQuery ( 
       r, 
       layerId =  id,  
       project =  F) |>   
     addLayersControl (overlayGroups =  id) 
 } 
```  
 
```{r}  
 librarian:: shelf ( 
   leaflet.extras2) 
 
 compare_sp <-  function ( 
   r_left, r_right, 
   lbl_left =  "native →" , lbl_right =  "← replicated" , 
   legend_title =  "AquaMaps<br>suitability" ){ 
    
   cols =  RColorBrewer:: brewer.pal (5 , "YlOrRd" ) 
   pal <-  leaflet:: colorBin ( 
     cols, c (0 , 1 ),  
     bins =  length (cols), pretty =  TRUE , na.color =  "transparent" ) 
    
   leaflet ( 
     options =  leafletOptions ( 
       attributionControl =  F, 
       zoomControl =  F)) |>   
     addMapPane ("left" ,  zIndex =  1 ) |>   
     addMapPane ("right" , zIndex =  1 ) |>   
     addProviderTiles ( 
       providers$ Esri.OceanBasemap, 
       group =  "base" , layerId =  "base_left" ,  
       options =  pathOptions (pane =  "left" )) |>   
     addProviderTiles ( 
       providers$ Esri.OceanBasemap, 
       group =  "base" , layerId =  "base_right" ,  
       options =  pathOptions (pane =  "right" )) |>   
     addRasterImage ( 
       r_left, colors =  pal, opacity =  0.8 ,  
       options =  leafletOptions (pane =  "left" ),  
       group =  lbl_left) |>   
     addRasterImage ( 
       r_right, colors =  pal, opacity =  0.8 ,  
       options =  leafletOptions (pane =  "right" ),  
       group =  lbl_right) |>   
     addLegend ( 
       values    =  seq (0 , 1 , length.out =  10 ),  
       pal       =  pal, 
       title     =  legend_title, 
       position  =  "bottomright" , 
       labFormat =  \(x, type){ 
         b <-  x[1 : length (x)- 1 ]* 100  
         e <-  x[2 : length (x)]* 100  
         glue ("{str_pad(b,2)} - {e}%" )}) |>   
     addControl (lbl_left, position =  "topleft" ) |>   
     addControl (lbl_right, position =  "topright" ) |>   
     # addLayersControl(  
     #   overlayGroups = c(lbl_left, lbl_right)) |>  
     addSidebyside ( 
       layerId =  "sidecontrols" , 
       rightId =  "base_right" , 
       leftId  =  "base_left" ) 
 } 
```  
 
 
 
[ Content - Introduction to aquamapsdata • aquamapsdata ](https://raquamaps.github.io/aquamapsdata/articles/intro.html#content)  
-    `depth/temp/salinity/prim_prod/ice_con/oxy/land_dist_yn` : Is the depth/temperature/salinity primary production/ice concentration/oxygen/distance to land parameter used in computing map data? 0=No, 1=Yes 
 
-    `layer` : Indicates whether the **temperature** and **salinity** parameters are based on ***bottom*** (=b) or ***surface*** (=s) values of half-degree cells used to compute the envelope. 
 
-    `spp_prefs.map_opt` : Indicates how native map (predicted probabilities) is plotted: 1 = area covered by both species’ bounding box and FAO areas, 2 = area covered by species’ FAO areas only, 3 = area covered by species’ bounding box only. 
 
    -    `spp_prefs.extn_rule_yn` : Was the FAO extension rule applied in the generation of the species envelope? 0=No, 1=Yes, null 
 
    -    `spp_cells.fao_area_yn` : Does this cell fall within an FAO area where the species is known to occur (endemic/native)? 0=No, 1=Yes 
 
    -    `spp_cells.bound_box_yn` : Does this cell fall within the geographical bounding box known for the species? 0=No, 1=Yes 
 
-  `mean_depth` : Is mean depth used to fit the depth envelope? By default, marine mammals use mean depth. 0=No, 1=Yes 
 
 
 FAOComplete Are the FAO areas listed in FAOAreas complete for this species? 0=No, 1=Yes 
 
 TODO: 
 
-    [ ]  inspect all "pelagic" references 
    -    `pelagic` : Does the species occurs in the water column well above and largely independent of the bottom? 0=No, 1=Yes 
    -    `deepwater` : Does the species occur in the deep-sea (i.e. tagged bathypelagic or bathydemersal in FishBase or SeaLifeBase)? 0=No, 1=Yes 
    -    `highseas` : Is the species an open ocean fish species (i.e. tagged as pelagic-oceanic in FishBase)? 0=No, 1=Yes 
-    `diving` : Is the species found on a dive (i.e. where DepthPrefMin in HSPEN < 20 meters)? 0=No, 1=Yes     
      
## Get species raster  
 
```{r}  
 d_sp_cell <-  tbl (con_dd, "spp_cells" ) |>   
   filter (sp_key ==  !! sp_key) |>   
   collect () 
# d_sp_cell  
# # A tibble: 50 × 5  
#    sp_key       probability fao_area_yn bound_box_yn cell_id  
#    <chr>              <dbl>       <int>        <int>   <int>  
#  1 W-Msc-419703        0.18           1            1  211899  
#  2 W-Msc-419703        0.96           1            1  211900  
#  3 W-Msc-419703        0.85           1            1  211901  
#  4 W-Msc-419703        1              1            1  211902  
 
# table(d_sp_cell$fao_area_yn, d_sp_cell$bound_box_yn, useNA = "always")  
#         1 <NA>  
#   1    50    0  
#   <NA>  0    0  
 
 d <-  tbl (con_dd, "cells" ) |>   
   filter (cell_id %in%  d_sp_cell$ cell_id) |>   
   collect () 
   # View(d)  
 
# range(d_sp_cell$probability)  
#   0.03 1.00  
# c(min(d$w_limit), max(d$e_limit), min(d$s_limit), max(d$n_limit))  
#   -98.0 -76.5  26.0  30.0  
 
# get_sp(sp_key) ----  
 r_sp <-  with ( 
   d_sp_cell, 
   subst (  # substitute cell_id with probability  
     r_h[["cell_id" ]],  
     from   =  cell_id, 
     to     =  probability, 
     others =  NA )) |>   
   trim () 
names (r_sp) <-  "probability"  
# ext(r_sp) # -98, -76.5, 26, 30 (xmin, xmax, ymin, ymax)  
 
 pal_col   <-  "YlOrRd"  
 pal_rmp   <-  colorRampPalette (brewer.pal (n= 5 , name= pal_col)) 
 pal_at    <-  c (0 , 0.2 , 0.4 , 0.6 , 0.8 , 1 ) 
 pal_alpha <-  0.9  
 
plet (r_sp, col =  pal_col, tiles =  "Esri.OceanBasemap" ) 
```  
 
## Get species raster with env as diagnostic polygons  
 
```{r}  
 r_sp_h <-  c ( 
   r_sp, 
   r_h |>  
     crop (r_sp) |>   
     mask (r_sp)) 
 
 p_sp_h <-  terra:: as.polygons ( 
   r_sp_h[["cell_id" ]]) |>   
   st_as_sf () |>   
   left_join ( 
     as.data.frame (r_sp_h), 
     by =  "cell_id" ) |>   
   relocate (probability) |>   
   as_tibble () |>  st_as_sf () 
 
# apply yellow to red color ramp to probability  
mapView ( 
   p_sp_h, zcol =  "probability" ,  
   col.regions =  pal_rmp, at =  pal_at, alpha.regions =  pal_alpha) 
```  
 
 TODO: 
 
-  [ ]  Limit ply attrs to relevant fields, esp env values and RES min/max 
 
## Develop raster topology  
 
-  1/12° (`r round(1/12, 4)` °: `r 360 * 1/12`  x `r 90 * 1/12` ) -- Copernicus Marine 
-  1/20° (`r round(1/20, 4)` °: `r 360 * 1/20`  x `r 90 * 1/20` ) -- Bio-Oracle (new sdmpredictors) 
 
```{r}  
#| label: topo_raster  
 
 res <-  1 / 12  
 r_g <-  rast ( 
   xmin =  - 180 , xmax =  180 ,  
   ymin =  - 90 ,  ymax =  90 ,  
   resolution =  res,  
   crs =  "EPSG:4326" ) 
 r_g 
```  
 
## Resample nearest  
 
 Use `terra::resample(method = "near")`  to get the higher resolution data using nearest neighbor. 
 
```{r}  
 r_sp_n <-  resample ( 
   r_sp, r_g,  
   method =  "near" ) |>   
   trim () 
names (r_sp_n) <-  "pr_near"  
 
plet (r_sp_n, col =  pal_col, tiles =  "Esri.OceanBasemap" ) 
```  
 
## Resample bilinear  
 
 Use `terra::resample(method = "bilinear")`  to get the higher resolution data using bilinear interpolation. 
 
```{r}  
 r_sp_b <-  resample ( 
   r_sp, r_g,  
   method =  "bilinear" ) |>   
   trim () 
names (r_sp_b) <-  "pr_bilinear"  
 
plet (r_sp_b, col =  pal_col, tiles =  "Esri.OceanBasemap" ) 
```  
 
## Reinterpolate  
 
 Get a smooth interpolation to nearly original extent by: 
 
-   
 
```{r}  
 pts_sp <-  as.points (r_sp) |>   
   st_as_sf () 
# mapView(pts_sp, cex = 2)  
 
 ply_sp <-  as.polygons (r_sp >  0 ) |>   
   st_as_sf () 
# mapView(ply_sp, cex = 2)  
 
 w <-  res (r_sp)[1 ] 
 r_0 <-  setValues (r_sp |>  extend (1 ), 0 ) 
 
sf_use_s2 (F) 
 ply_0 <-  ply_sp |>   
   st_buffer (w) |>  
   st_union () |>   
   st_make_valid () |>   
   st_as_sf () |>   
   st_difference (ply_sp) 
sf_use_s2 (T) 
# mapView(ply_0, cex = 2)  
 
 pts_0 <-  r_0 |>   
   crop (ply_0) |>  
   mask (ply_0) |>   
   as.points () |>   
   st_as_sf () 
names (pts_0)[1 ] <-  names (pts_sp)[1 ] 
 
# mapView(pts_sp, cex = 4) +  
#   mapView(pts_0, cex = 2, col.regions = "gray")  
 
 pts_sp0 <-  bind_rows ( 
   pts_sp, 
   pts_0) 
 
 pwr     =  2  
 rad     =  w    # to include cardinal neighbors, w * sqrt(2) ~= w * 1.4   
 val_min =   0.1  # 10% min  
 
 r_idw <-  interpIDW ( 
   x      =  r_g |>  crop (r_0),  
   y      =  pts_sp0 |>  vect (),  
   field  =  names (pts_sp0)[1 ], 
   radius =  rad, # 2/3,  
   power  =  pwr) # /2)  
 r_idw <-  mask (r_idw, r_idw >=  val_min, maskvalue =  F) |>   
   trim () 
# plot(  
#   r_idw,   
#   main = glue("idw(radius = {rad}, power = {pwr})"))  
 m <-  mapView (r_idw) +   
   mapView (pts_sp, cex =  4 ) +  
   mapView (pts_0, cex =  2 , col.regions =  "gray" ) 
 
 m@ map |>   
   addFullscreenControl () 
```  
 
## Mask by land  
 
 Use rnaturalearth medium resolution and mask by a percent of land. 
 
```{r}  
 librarian:: shelf ( 
   rnaturalearth, 
   rnaturalearthdata, 
   quiet =  T) 
 
# if (!requireNamespace("rnaturalearthhires", quietly = TRUE)) {  
#   install.packages(  
#     "rnaturalearthhires",  
#     repos = "https://ropensci.r-universe.dev",  
#     type = "source")  
# }  
# library(rnaturalearthhires)  
 
# ne_states_x <- rnaturalearthhires::states10 |>  
 ne_states_x <-  rnaturalearthdata:: states50 |>  
# ne_states_x <- rnaturalearth::ne_states() |>  
   st_make_valid () |>   
   st_filter ( 
     ext (r_idw) |>  vect () |>  st_as_sf () |>  st_set_crs (4326 ), 
     .predicate =  st_intersects) |>   
   tibble () |>   
   st_as_sf () 
# ne_states_x_0 <- ne_states_x  
# ne_states_x <- ne_states_x |>   
#   st_transform(st_crs(r_idw)) |>   
#   tibble() |>   
#   st_as_sf()  
 
 pct_land =  0.95  
 
 r_land <-  rasterize ( 
   ne_states_x |>   
     mutate (one =  1 ), 
   r_idw, "one" ,  
   cover =  T) 
# r_land <- mask(  
#   r_land,  
#   r_land > pct_land,   
#   maskvalue = F)  
# plot(r_land) #, main = glue("land (pct = {pct_land})"))  
# plot(r_land >= pct_land) #, main = glue("land (pct = {pct_land})"))  
 
 r_idw_m <-  mask ( 
   r_idw,  
   r_land >  pct_land,  
   maskvalue =  T) 
# plot(r_idw_m)  
# plot(r_idw)  
 
# mapView(r_idw) +   
mapView (r_idw_m) +   
   mapView (ne_states_x, col.regions =  "gray" , alpha =  0 ) 
```  
 
## Replicate AquaMaps species Probability from env layers  
 
```{r}  
# parameters  
# sp_key:   
 
#  TODO : fetch d_sp_pref based on sp_key  
 
 vars_yes <-  d_sp_pref |>   
   select (ends_with ("_yn" )) |>   
   # names() |>   
   #  |>   
   pivot_longer (everything ()) |>   
   filter (value ==  1 ) |>   
   pull (name) |>   
   str_replace ("_yn" , "" ) 
# "depth"     "temp"      "salinity"  "prim_prod" "ice_con"   "oxy"       "land_dist" "extn_rule"  
 
 r_env <-  r_h 
 
# bbox ----  
 bbox_yes <-  d_sp_pref$ map_opt %in%  c (1 ,3 ) 
if  (bbox_yes){ 
    
   # OLD bbox: off  
   # bbox_ext <- d_sp_pref |>   
   #   # 45  -28 -95 -33  
   #   select(w_most_long, e_most_long, s_most_lat, n_most_lat) |>  
   #   mutate(  
   #     w_most_long = w_most_long * -1,  
   #     e_most_long = e_most_long * -1) |>   
   #   pivot_longer(everything()) |>   
   #   deframe() |>   
   #   as.vector() |>   
   #   ext()  
    
   # NEW bbox: from species occurrences  
   #   goal: approximate native r_sp_old vs r_sp_new; using spp_occs  
   # r_sp_old: -98   , -76.5 ,  26  , 30    (xmin, xmax, ymin, ymax)  
   # r_sp_new: -97   , -80   ,  26  , 30  
   # pts_occs: -97.25, -77.25, 23.25, 30.25  
   # pts_good: -97.25, -77.25, 26.25, 29.25  
   # pts_ibnd: -97.25, -77.25, 26.25, 29.25  
   #  bb_occs: -97.5 , -77.0 , 26.0 , 29.5  
   #   bb_pad: -98.0,  -76.5 , 25.5 , 30.0   
   pad <-  0.5    # bb_pad  
   bbox_ext <-  tbl (con_dd, "spp_occs" ) |>   
     filter ( 
       sp_key    ==  !! sp_key, 
       good_cell ==  1 ) |>  
     left_join ( 
       tbl (con_dd, "cells" ), 
       by =  "cell_id" ) |>  
     summarize ( 
       xmin =  min (w_limit, na.rm =  T) -  pad, 
       xmax =  max (e_limit, na.rm =  T) +  pad, 
       # ymin = min(s_limit, na.rm = T) - pad,  
       ymin =  min (s_limit, na.rm =  T), 
       ymax =  max (n_limit, na.rm =  T) +  pad) |>   
     collect () |>  
     pivot_longer (everything ()) |>  
     deframe () |>   
     as.vector () |>   
     ext () 
    
   r_env <-  crop (r_env, bbox_ext) 
 } 
 
# fao ----  
if  (( 
   "extn_rule"  %in%  vars_yes |   
   d_sp_pref$ map_opt %in%  c (1 ,2 )) &&  
   ! is.na (d_sp_pref$ fao_areas)){ 
    
   # d_fao <- tbl(con_dd, "spp_prefs") |>   
   #   distinct(fao_areas) |>   
   #   collect() |>   
   #   mutate(  
   #     n = str_split(fao_areas, ",\\s*") |>   
   #       purrr::map_dbl(length)) |>  
   #   arrange(n)  
   # View(d_fao)  
   # Conclusion: all species have at least 1 FAO area  
    
   # example: fao_areas = "57, 61, 71"  
   fao_areas <-  d_sp_pref$ fao_areas |>   
     str_split (", \\ s*" ) |>   
     str_trim () |>   
     unlist () |>   
     as.numeric () |>   
     sort () 
    
   r_fao <-  r_env[["fao_area_m" ]] %in%  fao_areas 
   r_env <-  mask ( 
     r_env, 
     r_fao, 
     maskvalue =  F) 
 } 
 vars_yes <-  setdiff (vars_yes, "extn_rule" ) 
 
 ramp_env <-  function (v, p){ 
   # p = c(-1, 0, 0, 0) # dput(p) for var = "ice_con"; sp_key = "W-Msc-419703"  
   # v = 0  
    
   approx ( 
     x      =  p,  # c(min, min_pref, max, max_pref)  
     y      =  c (0 , 1 , 1 , 0 ),  
     xout   =  v,  
     # yleft  = 0,  # v < y_min -> 0  
     # yright = 0,  # v > y_max -> 0  
     # rule   = 2,  # 2: return nearest vs 1: NA  
     rule   =  1 ,  # return NA if outside range  
     method =  "linear" , 
     ties   =  max)$ y 
     # ties   = "ordered")$y  # assume x is ordered  
 } 
 
# match species preference var to AquaMaps env raster layers  
 is_surface <-  d_sp_pref$ layer ==  "s"  # vs "b" bottom  
 var_lyr <-  list ( 
   "depth"      =  "depth_mean" , 
   #  TODO : use depth_min, depth_max, depth_sd?  
   "temp"       =  ifelse ( 
     is_surface, 
     "sst_an_mean" , 
     "sbt_an_mean" ), 
   "salinity"   =  ifelse ( 
     is_surface, 
     "salinity_mean" , 
     "salinity_b_mean" ), 
   # "oxy"       = ifelse(  
   #   is_surface,  
   #   "oxy_mean",  
   #   "oxy_b_mean"),  
   "oxy"        =  "oxy_b_mean" , 
   "prim_prod"  =  "prim_prod_mean" , 
   "ice_con"    =  "ice_con_ann" , 
   "land_dist"  =  "land_dist" ) 
 
 r_sp_env <-  list () 
for  (var in  vars_yes){ # var = vars_yes[1] # var = "depth" # var = "prim_prod"  
 
   # get Relative Env Suitability (res) parameters  
   p <-  d_sp_pref |>   
     select ( 
       sprintf ( 
         "%s_%s" , var,  
         c ("min" , "pref_min" , "pref_max" , "max" ))) |>   
     pivot_longer (everything ()) |>   
     deframe () |>   
     as.vector () 
    
   # check that p is ordered  
   stopifnot ( 
     length (p) ==  4 , 
     all (is.finite (p)), 
     all (diff (p) >=  0 )) 
    
   lyr   <-  var_lyr[[var]] 
   r_var <-  r_env[[lyr]] 
   # plot(r_var)  
   r_sp_env[[var]] <-  terra:: app ( 
     x   =  r_var,  
     fun =  ramp_env,  
     p   =  p) 
   # plot(r_sp_env[[var]])  
   # mapView(r_sp_env[[var]])  
    
   if  (var ==  "depth" ){ 
     # pad depth with 0s if within depth_min/max  
     r_depth <-  r_sp_env[["depth" ]] 
     r_ok <-  r_env[["depth_min" ]] <  p[4 ] &  
       r_env[["depth_max" ]] >  p[1 ] 
     r_sp_env[["depth" ]] <-  ifel ( 
       is.na (r_depth), 
       ifel (r_ok, 0 , NA ), 
       r_depth) 
   } 
 } 
 
 r_sp_env <-  rast (r_sp_env) 
 
# show env layers transformed by species preferences  
plet ( 
   r_sp_env, 
   y        =  1 : nlyr (r_sp_env),  
   col      =  rev (RColorBrewer:: brewer.pal (11 , "Spectral" )), 
   shared   =  T, # shared legend  
   collapse =  F,  
   tiles    =  "Esri.OceanBasemap" ) 
 
 r_sp_old <-  r_sp 
# summary(values(r_sp_old, na.rm = T, mat = F))  
#   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.   
# 0.0300  0.6750  0.9000  0.7968  1.0000  1.0000  
 
 r_sp_new <-  app (r_sp_env, fun =  mean) 
# summary(values(r_sp_new, na.rm = T, mat = F))  
#   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.   
# 0.5776  0.7355  0.7837  0.7769  0.8000  1.0000  
 
# without ice_con  
# r_sp_new <- r_sp_env |>   
#   terra::subset(  
#     setdiff(  
#       names(r_sp_env),  
#       "ice_con")) |>  
#   app(fun = mean)  
# summary(values(r_sp_new, na.rm = T, mat = F))  
#   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.   
# 0.4719  0.6694  0.7297  0.7211  0.7500  1.0000   
   
# as product  
# r_sp_new <- app(r_sp_env, fun = prod)  
# summary(values(r_sp_new, na.rm = T, mat = F))  
#    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.   
# 0.00000 0.00000 0.00000 0.09531 0.00000 1.00000   
 
compare_sp ( 
   r_sp_old, r_sp_new) 
 
mapView (r_sp_new -  r_sp_old, layer.name =  "new - old" ) 
```  
 
 
```{r}  
#| label: ck_prim_prod  
#| eval: false  
 
# https://github.com/marinebon/aquamaps-downscaled/blob/503c62f39552c4ad2417413b13c49d4d4405f3ab/sp-map/functions.R#L92C5-L93C30  
# if (b == "PrimProd")  
#     im <- im$multiply(1000)  
 
tbl (con_dd, "spp_prefs" ) |>   
   select (prim_prod_max) |>   
   collect () |>   
   pull (prim_prod_max) |>   
   summary () 
#   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.   
#   1.62   27.19   43.27   52.55   69.46  253.40   
 
# names(r_h)  
summary (values (r_h[["prim_prod_mean" ]], na.rm =  T, mat =  F)) 
#  Min. 1st Qu.  Median    Mean 3rd Qu.    Max.   
# 0.089   1.145   2.668   4.284   5.348 250.926  
```  
 
 
```{r}  
#| label: get sp occurrences  
#| eval: false  
 
# dbListTables(con_dd)  
# tbl(con_dd, "_tbl_fld_renames") |>   
#   group_by(tbl_old, tbl_new) |>  
#   summarize(n = n(), .groups = "drop") |>   
#   collect()  
#  
#   tbl_old             tbl_new       n  
#   <chr>               <chr>     <dbl>  
# 1 hspen_r             spp_prefs    56  
# 2 speciesoccursum_r   spp          25  
# 3 occurrencecells_r   spp_occs     17  
# 4 hcaf_r              cells        58  
# 5 hcaf_species_native spp_cells     7  
 
 pts_occs <-  tbl (con_dd, "spp_occs" ) |>   
   filter (sp_key ==  !! sp_key) |>   
   collect () |>   
   st_as_sf ( 
     coords =  c ("center_long" , "center_lat" ),  
     remove =  F, 
     crs    =  4326 ) 
 
# r_sp_old: -98   , -76.5 ,  26  , 30     
# r_sp_new: -97   , -80   ,  26  , 30  
# pts_occs: -97.25, -77.25, 23.25, 30.25 (xmin, xmax, ymin, ymax)  
# pts_good: -97.25, -77.25, 26.25, 29.25  
# pts_ibnd: -97.25, -77.25, 26.25, 29.25  
#  bb_occs: -97.5 , -77.0 , 26.0 , 29.5  
#   bb_pad: -98.0,  -76.5 , 25.5 , 30.0   
 
 pts_occs |>  ext ()  
 pts_occs |>  filter (good_cell ==  1 ) |>  ext ()  
 pts_occs |>  filter (in_bound_box ==  1 ) |>  ext () 
 
# pad <- 0   # bb_occs  
 pad <-  0.5    # bb_pad  
 bb_occs <-  tbl (con_dd, "spp_occs" ) |>   
   filter ( 
     sp_key    ==  !! sp_key, 
     good_cell ==  1 ) |>  
   left_join ( 
     tbl (con_dd, "cells" ), 
     by =  "cell_id" ) |>  
   summarize ( 
     xmin =  min (w_limit, na.rm =  T) -  pad, 
     xmax =  max (e_limit, na.rm =  T) +  pad, 
     ymin =  min (s_limit, na.rm =  T) -  pad, 
     ymax =  max (n_limit, na.rm =  T) +  pad) |>   
   collect () |>  
   pivot_longer (everything ()) |>  
   deframe () 
```  
 
 
-  `fao_area_m` : Code number of FAO statistical area to which the cell belongs, for all oceanic and coastal cells. `r # range(values(r_h[["fao_area_m"]], na.rm = T))`  [ 18, 88 ]  
 
-  `fao_area_in` : Code number of FAO statistical area to which the cell belongs, for all inland and coastal cells. `r # range(values(r_h[["fao_area_in"]], na.rm = T))`  [ 1, 8 ]  
 
 
## Get Bio-Oracle v3 higher resolution data  
 
-  [ Bio-ORACLE : Marine data layers for ecological modelling ](https://www.bio-oracle.org/documentation.php)  
-  [ Bio-ORACLE : Marine data layers for ecological modelling ](https://www.bio-oracle.org/downloads-to-email.php)  
-  [ bio-oracle/biooracler: R package to access Bio-Oracle data via ERDDAP ](https://github.com/bio-oracle/biooracler)  
-  [ ERDDAP - List of All Datasets ](https://erddap.bio-oracle.org/erddap/info/index.html?page=1&itemsPerPage=1000)  
-  [ Copernicus Marine Data Store | Copernicus Marine Service ](https://data.marine.copernicus.eu/products)  
 
 
```{r}  
#| label: bio-oracle  
 
 librarian:: shelf ( 
   bio- oracle/ biooracler, 
   quiet =  T) 
 
# biooracler:::erddap.bio_oracle.org()  
# http://erddap.bio-oracle.org/erddap/  
 
 biooracler:: list_layers () |>   
   DT:: datatable () 
```  
 
## Match AquaMaps env to Bio-Oracle layers  
 
```{r}  
 librarian:: shelf ( 
   dplyr,  
   quiet =  T) 
 
 d_sp_pref |>   
   select (ends_with ("_yn" )) |>   
   names () |>   
   str_replace ("_yn" , "" ) 
 
# "depth"     "temp"      "salinity"  "prim_prod" "ice_con"   "oxy"       "land_dist" "extn_rule"  
```  
 
 
-  `depth` : terrain_characteristics.bathymetry_min|mean|max 
 
## Taxonomic comparisons  
 
-  Aquamaps: [ Computer Generated Native Distribution Map for _Crepidula depressa_ ](https://aquamaps.org/preMap2.php?cache=1&SpecID=W-Msc-419703)  
  -  [ Mapping Parameters ](https://www.aquamaps.org/ShowMapParam.php?SpecID=W-Msc-419703&graph=&user_session=1&bp=-1)  
  -  `"W-Msc-419703"` : _Crepidula depressa_ (class = Gastropoda) n_cells = 50 
 
 
```{r}  
 sp_key <-  "W-Msc-419703"  
 
tbl (con_dd, "spp" ) |>   
   filter (sp_key ==  !! sp_key) |>   
   collect () |>   
   mutate (across (everything (), as.character)) |>   
   pivot_longer (everything ()) |>   
   kable () 
```  
 
-  [ Crepidula depressa | **SeaLifebase.se** ](https://www.sealifebase.se/summary/Crepidula-depressa.html)  
  -  [ **Ecology** ](https://www.sealifebase.se/Ecology/SpeciesEcologySummary.php?StockCode=92041&GenusName=Crepidula&SpeciesName=depressa)  
    -  `Substrate` : Benthic: mobile; 
    -  `Feeding habit` : filtering plankton 
  -  [ **Ecosystems** ](https://www.sealifebase.se/trophiceco/EcosysList.php?ID=151110&GenusName=Crepidula&SpeciesName=depressa)  
    -  Ecosystem: Atlantic Ocean, Gulf of Mexico, ...; Type: Sea/Bay/Gulf 
  -  [ **Synonyms** ](https://www.sealifebase.se/Nomenclature/SynonymsList.php?ID=151110&SynCode=179777&GenusName=Crepidula&SpeciesName=depressa)  
    
     Synonym | Author    | CoL | Status | Valid | Synonymy | Combination 
     ----|----|----|----|----|----|---- 
     [ Crepidula depressa ](https://www.sealifebase.se/Nomenclature/SynonymSummary.php?ID=179777&CAS_SPC=&Status=accepted%20name&Synonymy=senior%20synonym&Combination=original%20combination&GenusName=Crepidula&SpeciesName=depressa&SpecCode=151110&SynonymsRef=83435&Author=Say,%201822&Misspelling=0)  |   Say, 1822   | accepted name | Yes   | senior synonym | original combination 
 
-  [ WoRMS - World Register of Marine Species - Crepidula depressa Say, 1822 ](https://www.marinespecies.org/aphia.php?p=taxdetails&id=419703)  
  -  unaccepted: [ WoRMS - World Register of Marine Species - Crepidula depressa Deshayes, 1830 ](https://www.marinespecies.org/aphia.php?p=taxdetails&id=572470)  
-  [ Crepidula depressa - Wikipedia ](https://en.wikipedia.org/wiki/Crepidula_depressa)  
-  [ Search "Crepidula depressa" | GBIF.org ](https://www.gbif.org/search?q=Crepidula%20depressa)  
  -  [ Crepidula depressa Say, 1822 ](https://www.gbif.org/species/5856498)  
    -  [ Crepidula depressa Say, 1822 ](https://www.gbif.org/species/155138324) \ 
       This is the interpretation of the species as published in World Register of Marine Species. 
  -  [ Crepidula depressa Deshayes, 1830 ](https://www.gbif.org/species/8275070)  
-  [ Crepidula depressa Say, 1822 - OBIS.org ](https://obis.org/taxon/419703)