Time Period - AIS data between 01/01/2021 and 12/31/2023
Spatial Filter
Box
Shapefile - MPA
Raster resolution of 0.01x0.01° (lat/lon)
Filter fishing vessel if fished less than 1 day in a month in an area
Zoning: Galapagos Marine Park
Figure 1: Galapagos Marine Protected Area zoning as provided by the Galapagos National Park Service.
Steps in the analysis
Get the AIS data for the period
Select the AIS data inside the MPA
Assign each AIS message to the Zone and its Area
Run the analysis for each Zone and Area
Spatial fishing dynamics
Temporal fishing dynamics
Fishing by gear and/or class
Write the report
Re-Do everything - Version 2
Get the AIS data V1
-------------------------------------------------------------- Query - Fishing effort aggregated to 0.1° resolution-- author: Nate & Cian and a bit of Jorge Cornejo-- date: Nov 13, 2023------------------------------------------------------------CREATE TEMP FUNCTION start_date() AS (CAST('2021-01-01'ASDATE));CREATE TEMP FUNCTION end_date() AS (CAST('2023-10-31'ASDATE)); #Fecha de corte, considerando el delay de GFW para tener los datosWITH------------------------------------------------------------ Load shapefiles of MPAs---------------------------------------------------------- mpa AS (SELECT ST_GEOGFROMTEXT(WKT, make_valid =>TRUE) AS polygon, Codigo AS zone_id, nombre as DesignacionFROM `world-fishing-827.scratch_JorgeCornejo.galapagosMPA_zoning` ),------------------------------------------------------------ This subquery identifies good segments---------------------------------------------------------- good_segments AS (SELECT seg_idFROM `pipe_production_v20201001.research_segs`WHERE good_segAND positions >10ANDNOT overlapping_and_short),------------------------------------------------------------ Get the list of active fishing vessels that pass the noise filters---------------------------------------------------------- fishing_vessels AS (SELECT ssvid,year, best_flag, best_vessel_classFROM-- IMPORTANT: change below to most up to date table `gfw_research.fishing_vessels_ssvid_v20230901` ),------------------------------------------------------------ Query fishing effort but include original lon and lat-- positions for spatial joining with mpas---------------------------------------------------------- fishing AS (SELECT ssvid, lon, lat, ## We need more resolution forthe zoning to works #FLOOR(lat *0.1) AS lat_bin,round(lat, 2) AS lat_bin, #FLOOR(lon *0.1) AS lon_bin,round(lon, 2) AS lon_bin,EXTRACT(dateFROM _partitiontime) ASdate,EXTRACT(yearFROM _partitiontime) ASyear, hours, nnet_score, night_loitering-- eezFROM `pipe_production_v20201001.research_messages`--, aoi-- LEFT JOIN UNNEST(regions.eez) AS eez-- Restrict query to specific time rangeWHERE is_fishing_vessel =TRUEANDCAST(_partitiontime ASDATE) BETWEEN start_date()AND end_date()-- Use spatial join to restrict to aoi--AND ST_CONTAINS(aoi.polygon, ST_GEOGPOINT(lon, lat))-- Use good_segments subquery to only include positions from good segmentsAND seg_id IN (SELECT seg_idFROM good_segments) ),------------------------------------------------------------ Spatial join with mpas---------------------------------------------------------- fishing_mpas AS (SELECT*FROM fishing aLEFTJOIN (SELECT*FROM mpa ) bON ST_WITHIN(ST_GEOGPOINT(a.lon, a.lat), b.polygon) ),------------------------------------------------------------ Filter fishing to just the list of active fishing vessels in that year---------------------------------------------------------- fishing_filtered AS (SELECT*FROM fishing_mpasJOIN fishing_vessels-- Only keep positions for fishing vessels active that yearUSING (ssvid,year) ),------------------------------------------------------------ Create fishing_hours attribute. Use night_loitering instead of nnet_score as indicator of fishing for squid jiggers---------------------------------------------------------- fishing_hours_filtered AS (SELECT*,CASEWHEN best_vessel_class ='squid_jigger'AND night_loitering =1THEN hoursWHEN best_vessel_class !='squid_jigger'AND nnet_score >0.5THEN hoursELSENULLENDAS fishing_hoursFROM fishing_filtered ),------------------------------------------------------------ This subquery sums fishing hours and converts coordinates back to-- decimal degrees-- drop lon and lat but keep mpa---------------------------------------------------------- fishing_binned AS (SELECTdate,-- keep ssvid as we're interested in counting number of vessels ssvid, lat_bin , #/0.1AS lat_bin, lon_bin , #/0.1AS lon_bin, best_vessel_class, best_flag, zone_id, Designacion,SUM(hours) AS hours,SUM(fishing_hours) AS fishing_hours,FROM fishing_hours_filteredGROUPBYdate, ssvid, lat_bin, lon_bin, best_vessel_class, best_flag, zone_id, Designacion )------------------------------------------------------------ Return fishing data----------------------------------------------------------SELECT*FROM fishing_binnedWHERE zone_id ISNOTNULL-- only within one of the zones.
Get the AIS data V2
-------------------------------------------------------------- Query - Fishing effort aggregated to 0.1° resolution-- author: Nate & Cian and a bit of Jorge Cornejo-- date: Nov 13, 2023------------------------------------------------------------CREATE TEMP FUNCTION start_date() AS (CAST('2021-01-01'ASDATE));CREATE TEMP FUNCTION end_date() AS (CAST('2023-12-31'ASDATE)); #Fecha de corte, considerando el delay de GFW para tener los datosWITH------------------------------------------------------------ Load shapefiles of MPAs---------------------------------------------------------- mpa AS (SELECT ST_GEOGFROMTEXT(WKT, make_valid =>TRUE) AS polygon, Codigo AS zone_id, nombre as DesignacionFROM `world-fishing-827.scratch_JorgeCornejo.galapagosMPA_zoning` ),------------------------------------------------------------ This subquery identifies good segments---------------------------------------------------------- good_segments AS (SELECT seg_idFROM `pipe_production_v20201001.research_segs`WHERE good_segAND positions >10ANDNOT overlapping_and_short ),------------------------------------------------------------ Add galapagos fishing vessel list with manual MMSI----------------------------------------------------------galapagos_vessel_list AS (SELECTCAST(MMSI AS STRING) AS ssvidFROM scratch_nate.galapagos_vessel_list_v20240116 -- <-- HERE!! #############),------------------------------------------------------------ Get the list of active fishing vessels that pass the noise filters---------------------------------------------------------- fishing_vessels AS (SELECT ssvid,year, IFNULL(gfw_best_flag, mmsi_flag) AS best_flag, IFNULL(best_vessel_class, prod_geartype) AS best_vessel_classFROM-- IMPORTANT: change below to most up to date table pipe_production_v20201001.all_vessels_byyear_v2_v20231201 -- <- New Table ###########--`gfw_research.fishing_vessels_ssvid_v20230901`WHERE (on_fishing_list_best OR on_fishing_list_sr OR--#potential_fishing OR ssvid IN (SELECT ssvid FROM galapagos_vessel_list))),-- SELECT * FROM fishing_vessels WHERE ssvid = '735059559'------------------------------------------------------------ Query fishing effort but include original lon and lat-- positions for spatial joining with mpas---------------------------------------------------------- fishing AS (SELECT ssvid, lon, lat, ## We need more resolution forthe zoning to worksFLOOR(lat *100) /100AS lat_bin, #round(lat, 2) AS lat_bin,FLOOR(lon *100) /100AS lon_bin, #round(lon, 2) AS lon_bin,EXTRACT(dateFROM _partitiontime) ASdate,EXTRACT(yearFROM _partitiontime) ASyear,EXTRACT(dayFROM _partitiontime) ASday, hours, nnet_score, night_loitering-- eezFROM `pipe_production_v20201001.research_messages`--, aoi-- LEFT JOIN UNNEST(regions.eez) AS eez-- Restrict query to specific time rangeWHERE lat >-4and lat <4and lon >-95and lon <-87andCAST(_partitiontime ASDATE) BETWEEN start_date()AND end_date()-- Use spatial join to restrict to aoi--AND ST_CONTAINS(aoi.polygon, ST_GEOGPOINT(lon, lat))-- Use good_segments subquery to only include positions from good segmentsAND seg_id IN (SELECT seg_idFROM good_segments) ),------------------------------------------------------------ Spatial join with mpas---------------------------------------------------------- fishing_mpas AS (SELECT*FROM fishing aLEFTJOIN (SELECT*FROM mpa ) bON ST_WITHIN(ST_GEOGPOINT(a.lon, a.lat), b.polygon)),------------------------------------------------------------ Filter fishing to just the list of active fishing vessels in that year---------------------------------------------------------- fishing_filtered AS (SELECT*FROM fishing_mpasJOIN fishing_vessels-- Only keep positions for fishing vessels active that yearUSING (ssvid,year) ),------------------------------------------------------------ Create fishing_hours attribute. Use night_loitering instead of nnet_score as indicator of fishing for squid jiggers---------------------------------------------------------- fishing_hours_filtered AS (SELECT* ,CASEWHEN best_vessel_class ='squid_jigger'AND night_loitering =1THEN hoursWHEN best_vessel_class !='squid_jigger'AND nnet_score >=0.5THEN hoursELSENULLENDAS fishing_hoursFROM fishing_filtered ),------------------------------------------------------------ This subquery sums fishing hours and converts coordinates back to-- decimal degrees-- drop lon and lat but keep mpa---------------------------------------------------------- fishing_binned AS (SELECTdate, #day,-- keep ssvid as we're interested in counting number of vessels ssvid, lat_bin , #/0.1AS lat_bin, lon_bin , #/0.1AS lon_bin, best_vessel_class, best_flag, zone_id, Designacion, nnet_score,SUM(hours) AS hours,SUM(fishing_hours) AS fishing_hours,FROM fishing_hours_filteredGROUPBYdate, #day, ssvid, lat_bin, lon_bin, best_vessel_class, best_flag, nnet_score, zone_id, Designacion )------------------------------------------------------------ Return fishing data----------------------------------------------------------SELECT*FROM fishing_binnedWHERE--#fishing_hours > 0 AND zone_id ISNOTNULL-- only within one of the zones.
Results in Version 1
Presence and apparent fishing
Table 1: Yealy hours of presence and apparent fishing effort by zoning area (01-01-2021 al 31-10-2023).
Presencia (hrs)
Pesca Aparente (hrs)
Designación
2021
2022
2023
Total
2021
2022
2023
Total
APROVECHAMIENTO SUSTENTABLE
12.268
14.694
13.873
40.835
2.332
2.664
2.789
7.784
AREA ESPECIAL
1
0
0
1
0
0
0
0
CONSERVACION
5.067
4.719
4.775
14.561
746
759
383
1.888
INTANGIBLE
29
6
42
77
0
0
0
0
TRANSICION
3.452
3.980
6.521
13.953
240
439
330
1.009
Presence and apparent fishing
Table 2: Total hours of presence and apparent fishing effort by zoning area (01-01-2021 al 31-10-2023).
Horas de
Zona
Designación
Presencia
Pesca aparente
SC
APROVECHAMIENTO SUSTENTABLE
40.836
11.217
ZC20
CONSERVACION
3.423
1.384
SC
TRANSICION
13.953
1.098
ZC30
CONSERVACION
1.784
625
ZC35
CONSERVACION
1.808
594
ZC06
CONSERVACION
282
274
ZC16
CONSERVACION
642
230
ZC31
CONSERVACION
975
222
ZC21
CONSERVACION
371
174
ZC01
CONSERVACION
345
76
ZC08
CONSERVACION
120
56
ZC04
CONSERVACION
305
50
ZC09
CONSERVACION
967
49
ZC18
CONSERVACION
1.298
49
ISLOTES
CONSERVACION
84
42
ZC07
CONSERVACION
132
31
ZC27
CONSERVACION
411
30
ZC29
CONSERVACION
64
27
ZC10
CONSERVACION
748
20
ZC12
CONSERVACION
58
18
ZC11
CONSERVACION
281
17
ZC19
CONSERVACION
66
17
SC
URBANO
643
16
ZC03
CONSERVACION
88
14
ZI09
INTANGIBLE
49
11
ZI08
INTANGIBLE
16
2
ZC02
CONSERVACION
20
1
ZC05
CONSERVACION
4
1
ZI14
INTANGIBLE
1
1
ZI18
INTANGIBLE
2
1
BALTRA
AREA ESPECIAL
1
0
BALTRA (AREA ESPECIAL)
CONSERVACION
1
0
SC
RURAL
3
0
ZC15
CONSERVACION
280
0
ZC17
CONSERVACION
3
0
ZI02
INTANGIBLE
0
0
ZI05
INTANGIBLE
2
0
ZI11
INTANGIBLE
6
0
Fishing by month
Figure 2: Total apparent fishing effoprt by month (01-01-2021 al 31-10-2023).
Heatmap: apparent fishing
Figure 3: Apparent fishing effort by spatial unit (0.01°x0.01° lat/lon).
Aprovechamiento sustentable
Summary
Table 3: Yearly apparent fishing effort and number of vessels detected inside the area SC (01-01-2021 al 31-10-2023).
Año
Zona
2021
2022
2023
N Barcos
SC
2.332
2.664
2.789
47
Aprovechamiento sustentable
Heatmap: apparent fishing
Figure 4: Apparent fishing effort inside the area SC by spatial unit (0.01°x0.01° lat/lon).
Results in Version 2
Presence and apparent fishing
Table 4: Yealy hours of presence and apparent fishing effort by zoning area (01-01-2021 al 31-12-2023).
Presencia (hrs)
Pesca Aparente (hrs)
Designación
2021
2022
2023
Total
2021
2022
2023
Total
APROVECHAMIENTO SUSTENTABLE
204.700
235.138
247.968
687.806
44.147
39.028
50.999
134.173
AREA ESPECIAL
1
0
1
2
0
0
0
0
CONSERVACION
92.154
97.879
111.570
301.603
22.069
20.235
20.464
62.768
INTANGIBLE
980
1.274
1.176
3.430
0
0
79
79
TRANSICION
95.001
169.816
224.373
489.190
2.993
4.798
10.219
18.010
Presence and apparent fishing
V1
Presencia (hrs)
Pesca Aparente (hrs)
Designación
2021
2022
2023
Total
2021
2022
2023
Total
APROVECHAMIENTO SUSTENTABLE
12.268
14.694
13.873
40.835
2.332
2.664
2.789
7.784
AREA ESPECIAL
1
0
0
1
0
0
0
0
CONSERVACION
5.067
4.719
4.775
14.561
746
759
383
1.888
INTANGIBLE
29
6
42
77
0
0
0
0
TRANSICION
3.452
3.980
6.521
13.953
240
439
330
1.009
V2
Presencia (hrs)
Pesca Aparente (hrs)
Designación
2021
2022
2023
Total
2021
2022
2023
Total
APROVECHAMIENTO SUSTENTABLE
204.700
235.138
247.968
687.806
44.147
39.028
50.999
134.173
AREA ESPECIAL
1
0
1
2
0
0
0
0
CONSERVACION
92.154
97.879
111.570
301.603
22.069
20.235
20.464
62.768
INTANGIBLE
980
1.274
1.176
3.430
0
0
79
79
TRANSICION
95.001
169.816
224.373
489.190
2.993
4.798
10.219
18.010
Presence and apparent fishing
Table 5: Yealy hours of presence and apparent fishing effort by zoning area (01-01-2021 al 31-12-2023).
Horas de
Zona
Designación
Presencia
Pesca aparente
SC
APROVECHAMIENTO SUSTENTABLE
704.577
134.173
ZC06
CONSERVACION
23.528
19.115
SC
TRANSICION
509.970
18.010
ZC20
CONSERVACION
58.291
10.669
ZC01
CONSERVACION
35.614
8.067
ZC35
CONSERVACION
33.850
4.501
ZC16
CONSERVACION
11.762
3.490
ZC30
CONSERVACION
16.695
3.366
ZC03
CONSERVACION
7.681
2.750
ZC07
CONSERVACION
5.027
1.890
ZC21
CONSERVACION
7.038
1.864
ZC31
CONSERVACION
13.048
1.750
ZC04
CONSERVACION
5.057
1.024
ZC02
CONSERVACION
3.302
860
ZC09
CONSERVACION
7.272
804
ZC18
CONSERVACION
15.759
766
ZC27
CONSERVACION
6.014
610
ZC12
CONSERVACION
1.049
398
ZC11
CONSERVACION
987
246
ZC10
CONSERVACION
1.996
229
ZC15
CONSERVACION
657
205
ZC29
CONSERVACION
379
128
ZI09
INTANGIBLE
111
79
ZC05
CONSERVACION
46
34
Fishing by month
Figure 5: Total apparent fishing effoprt by month (01-01-2021 al 31-12-2023).
Fishing by month
Time series: V1 vs V2
Heatmap apparent fishing
Figure 6: Apparent fishing effort by spatial unit (0.01°x0.01° lat/lon).
Heatmap: V1 vs V2
Aprovechamiento sustentable
Summary
Table 6: Yearly apparent fishing effort and number of vessels detected inside the area SC (01-01-2021 al 31-12-2023).
Año
Zona
2021
2022
2023
N Barcos
SC
44.147
39.028
50.999
278
Aprovechamiento Sustentable
Summary: V1 vs V2
V1
Año
Zona
2021
2022
2023
N Barcos
SC
2.332
2.664
2.789
47
V2
Año
Zona
2021
2022
2023
N Barcos
SC
44.147
39.028
50.999
278
Aprovechamiento sustentable
Heatmat: apparent fishing
Figure 7: Apparent fishing effort by spatial unit (0.01°x0.01° lat/lon).
Aprovechamiento sustentable
Heatmap: V1 vs V2
Functions
Heatmap
haceRaster <-function(df=fishingHours, pol, transicion=F, best_proj="ESPG:4326", title=F, expRast=F)## Pol=Polygon name, If is the "Transicion" zone,## Title or not, Raster export{if(transicion==F) ## { mpa_zona <- galapagos_sf %>%filter(Codigo == pol) %>%st_set_crs(4326) } if(transicion == T) { ## Transicion area name is SC, same as Aprovechamiento sustentable mpa_zona <- pol %>%st_set_crs(4326) pol <-unique(pol$Codigo) } df1 <- df %>%filter(zone_id == pol) bbox_temp <-data.frame(x_min =st_bbox(mpa_zona)$xmin,x_max =st_bbox(mpa_zona)$xmax,y_min =st_bbox(mpa_zona)$ymin,y_max =st_bbox(mpa_zona)$ymax) bounding_1 <-transform_box(xlim =c(bbox_temp[1,"x_min"], bbox_temp[1, "x_max"]),ylim =c(bbox_temp[1, "y_min"], bbox_temp[1, "y_max"]),output_crs =4326)if (pol =="ZC01") ## This poligon need a different bounding box { bounding_1 <-transform_box(xlim =c(bbox_temp[1,"x_min"], bbox_temp[1, "x_max"]),ylim =c(0, bbox_temp[1, "y_max"]),output_crs =4326) }## Here I create the dataframe of fishing hours by spatial unit raster4map <- df1 %>%filter(zone_id == pol) %>%group_by(lat_bin, lon_bin) %>%summarise(fh =sum(fishing_hours, na.rm=T))## Create the map map <-ggplot(raster4map) +geom_tile(aes(x = lon_bin, y = lat_bin, fill =log10(fh))) +## Figuregeom_sf(data=galapagos_sf, color='darkgrey', fill="NA") +## Zoning Shapefilegeom_sf(data=mpa_zona, color='lightyellow', fill="NA") +## MPA shapefilegeom_sf(data=tierra, color="NA", ## Land Shapefilefill=gfw_palette("map_country_dark")[1]) +## Color scale on log10scale_fill_gradientn(colors =gfw_palette("map_presence_dark"),oob = scales::squish,na.value =NA, name="Pesca aparente (hrs)",breaks =seq(-1, log10(max(raster4map$fh))), labels =10^seq(-1, log10(max(raster4map$fh))) ) +scale_x_continuous(breaks =seq(from =round(bbox_temp$x_min, 0), to =round(bbox_temp$x_max, 0))) +scale_y_continuous(breaks =seq(from =round(bbox_temp$y_min, 0), to =round(bbox_temp$y_max, 0))) +theme_gfw_map() +theme(axis.title =element_text(size =10),axis.text =element_text(size =10),legend.key.width=unit(1,"cm")) +ylab("") +xlab("")if(title==T) {map <- map +ggtitle(pol)} ## Title or notprint(map)if(expRast==T) {return(raster4map)} ## Raster as an output?}
Time series
fhMes <-function(df=fishingHours, pol, yl =-10, yl2=-10){ yl & yl2: used to reposicion the months labels dateRange <-data.frame(month=seq.Date(from =as.Date('2021-01-01'), to =as.Date('2023-12-31'), by ='month'),fh =NA)## Create the DF, filter by area and get the monthly Fishing Hours fhmes <- df %>%filter(zone_id == pol) %>%mutate(month = lubridate::floor_date(date, "month")) %>%group_by(month) %>%summarise(fh =round(sum(fishing_hours, na.rm =TRUE), 0))## Combine the month list with the data, select and rename the columns fhmes <-merge(dateRange, fhmes, by="month", all.x=T) %>%select(-fh.x) %>%rename(fh = fh.y) %>%mutate(fh =if_else(is.na(fh), 0, fh))## Create a vector with the months letters in spanish## This is used as labels in the X axis m <-c("E", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D","E", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D","E", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D") serieFH <-ggplot(fhmes) +geom_col(aes(x = month, y = fh), fill =gfw_palette("chart")[1]) +geom_vline(xintercept =ymd('2021-01-01', '2022-01-01', '2023-01-01'),color =gfw_palette('cyan')[1]) +## Add the vertical line for each year## Add month as X labels - here yl2 is usedannotate("text",x=fhmes$month,y=yl2,label=m, size =3, col="darkgrey")+## Make sure the Y axis is consistent across plotscoord_cartesian(ylim=c(yl,max(fhmes$fh)),clip="off") +## Here yl is usedlabs(x ="Mes", y ="Pesca aparente (hrs)") +theme_gfw() +theme(axis.title =element_text(size =10),axis.text =element_text(size =10),axis.title.x =element_text(margin =margin(t =0.5, r =0, b =0, l =0, unit ="cm"))) print(serieFH)}
## Funcion para determinar el número de horas de pesca por flotaxFlota <-function(df=fishingHours, pol){## Create the DF grouping vessel_class and sum FH and count Vessels top_fleet_raw <- df %>%filter(zone_id == pol) %>%filter(!is.na(best_vessel_class)) %>%group_by(best_vessel_class) %>%summarise(fh =sum(fishing_hours, na.rm =TRUE),n_vessels =n_distinct(ssvid, na.rm =TRUE))## Fishing hours by gear p_hours <- top_fleet_raw %>%ggplot() +geom_col(aes(x =reorder(best_vessel_class, fh, decreasing =TRUE), y = fh), fill =gfw_palette("chart")[1]) +labs(x ="Arte de pesca", y ="Pesca aparente (hrs)") +theme_gfw() +theme(axis.title =element_text(size =12),axis.text =element_text(size =12),axis.title.x =element_text(margin =margin(t =0.5, r =0, b =0, l =0, unit ="cm")),axis.text.x =element_text(angle =45, hjust =1, vjust =1))## Vessel number by gear p_vessels <- top_fleet_raw %>%ggplot() +geom_col(aes(x =reorder(best_vessel_class, fh, decreasing =TRUE), y = n_vessels), fill =gfw_palette("chart")[1]) +scale_x_discrete(position ="bottom") +labs(x ="Arte de pesca", y ="Barcos (n)") +theme_gfw() +theme(axis.title =element_text(size =12),axis.text =element_text(size =12),axis.title.x =element_text(margin =margin(t =0.5, r =0, b =0, l =0, unit ="cm")),axis.text.x =element_text(angle =45, hjust =1, vjust =1))## Check if there are data: If not data, make an empty plotif(dim(top_fleet_raw)[1] >0) {print(p_hours)print(p_vessels) } else {print(ggplot() +geom_point(aes(x=1, y=1))) }return(top_fleet_raw)}