library(plotly)
## Loading required package: ggplot2
## 
## Attaching package: 'plotly'
## The following object is masked from 'package:ggplot2':
## 
##     last_plot
## The following object is masked from 'package:stats':
## 
##     filter
## The following object is masked from 'package:graphics':
## 
##     layout
library(sf)
## Warning: package 'sf' was built under R version 4.5.2
## Linking to GEOS 3.13.0, GDAL 3.8.5, PROJ 9.5.1; sf_use_s2() is TRUE
library(zip)
## 
## Attaching package: 'zip'
## The following objects are masked from 'package:utils':
## 
##     unzip, zip
# Load the data
quakes <- read.csv("Bay-SC.1975-2025.csv")
quakes$time <- as.POSIXct(quakes$time)
quakes$time_numeric <- as.numeric(quakes$time)

# Load faults from KMZ
unzip("qfaults.kmz", exdir = tempdir())
faults <- st_read(file.path(tempdir(), "doc.kml"))
## Multiple layers are present in data source /private/var/folders/l8/gpvbxn2j5dggc88kzrfyy7pr0000gn/T/RtmpRRtkpA/doc.kml, reading layer `Historic Faults'.
## Use `st_layers' to list all layer names and their type in a data source.
## Set the `layer' argument in `st_read' to read a particular layer.
## Warning in CPL_read_ogr(dsn, layer, query, as.character(options), quiet, :
## automatically selected the first layer in a data source containing more than
## one.
## Reading layer `Historic Faults' from data source 
##   `/private/var/folders/l8/gpvbxn2j5dggc88kzrfyy7pr0000gn/T/RtmpRRtkpA/doc.kml' 
##   using driver `KML'
## Simple feature collection with 14260 features and 2 fields
## Geometry type: MULTILINESTRING
## Dimension:     XYZ
## Bounding box:  xmin: -180 ymin: 18.89354 xmax: 180 ymax: 63.53205
## z_range:       zmin: 0 zmax: 0
## Geodetic CRS:  WGS 84
# Get quakes boundaries
lon_range <- range(quakes$longitude)
lat_range <- range(quakes$latitude)

# Crop faults to quakes extent
faults <- st_crop(faults, xmin = lon_range[1], xmax = lon_range[2], ymin = lat_range[1], ymax = lat_range[2])
## st_as_s2(): dropping Z and/or M coordinate
## Warning: attribute variables are assumed to be spatially constant throughout
## all geometries
# Create yearly tick positions from 1975 to 2025
years <- seq(1975, 2025, by = 5)
year_dates <- as.POSIXct(paste0(years, "-01-01"))
year_numerics <- as.numeric(year_dates)

# Start with earthquakes
p <- plot_ly()

# Add fault lines first
for (i in seq_len(nrow(faults))) {
  coords <- st_coordinates(st_geometry(faults[i, ]))
  p <- add_trace(p, x = coords[, 1], y = coords[, 2], z = rep(0, nrow(coords)), 
                 type = 'scatter3d', mode = 'lines',
                 line = list(color = 'red', width = 6), showlegend = (i == 1), 
                 name = 'Faults', hoverinfo = 'skip')
}

# Add earthquake points
p <- add_trace(p, data = quakes, x = ~longitude, y = ~latitude, z = ~depth, 
               type = 'scatter3d', mode = 'markers',
               marker = list(size = ~mag^2, color = ~time_numeric, colorscale = "Rainbow", 
                           opacity = 0.4, showscale = TRUE, 
                           colorbar = list(title = "Year", tickvals = year_numerics, 
                                         ticktext = as.character(years), len = 0.8, 
                                         thickness = 15, tickfont = list(size = 8), 
                                         titlefont = list(size = 10))),
               text = ~paste("Mag:", mag, "<br>Depth:", round(depth, 1), "km<br>Time:", format(time, "%Y-%m-%d")),
               hoverinfo = 'text', name = 'Earthquakes')

p <- layout(p, title = "Bay-SC Earthquakes (1975-Present) with Faults", 
    scene = list(xaxis = list(title = "Longitude"), yaxis = list(title = "Latitude"), zaxis = list(title = "Depth (km)", autorange = "reversed"), aspectratio = list(x = 8, y = 8, z = 6)))

p