1package events
2
3import (
4 "ewdetect/config"
5 "ewdetect/locate"
6 "ewdetect/stations"
7 "math"
8 "strings"
9 "time"
10
11 "github.com/rs/zerolog/log"
12)
13
14var Events []*Event
15
16type Detection struct {
17 PWaveArrival time.Time
18 SWaveArrival time.Time
19}
20
21type Event struct {
22 FirstDetectionLat float64 //rad
23 FirstDetectionLon float64 //rad
24 FirstPWaveDetection time.Time
25 Detections map[string]Detection
26 LastPWaveArrival time.Time
27 FinalConclusionReached bool
28}
29
30func IsEventOver(time time.Time, index int) bool {
31 return time.Sub(Events[index].LastPWaveArrival) > config.EventTimeout
32}
33
34func FinalConclusionCheck(index int) {
35 if IsEventOver(time.Now(), index) {
36 if !Events[index].FinalConclusionReached {
37 Events[index].FinalConclusionReached = true
38 log.Info().Msgf("Final conclusion reached for event %d", index)
39 Predict(index, true)
40 }
41 }
42}
43
44func Predict(index int, finalPrediction bool) {
45 log.Info().Int("index", index).Bool("isFinalPrediction", finalPrediction).Msg("Predicting")
46 formattedObservationList := []locate.Observation{}
47 for detection := range Events[index].Detections {
48 currentDetection := Events[index].Detections[detection]
49 splitString := strings.Split(detection, "@")
50 connection := splitString[0]
51 stationID := splitString[1]
52 formattedObservationList = append(formattedObservationList, locate.Observation{
53 StationName: detection,
54 Lat: (*stations.Stations[connection])[stationID].Lat * math.Pi / 180,
55 Lon: (*stations.Stations[connection])[stationID].Lon * math.Pi / 180,
56 PWaveArrival: Events[index].FirstPWaveDetection.Sub(currentDetection.PWaveArrival).Seconds(),
57 SWaveArrival: Events[index].FirstPWaveDetection.Sub(currentDetection.SWaveArrival).Seconds(),
58 })
59 }
60 if len(formattedObservationList) >= config.NumberOfDetectionsThreshold {
61 log.Debug().Interface("observations", formattedObservationList).Msg("Formatted observation list")
62 eventName := GetEventName(index)
63 finalGuess := locate.NelderMeadOptimization(eventName, &formattedObservationList, finalPrediction)
64 dateOfEarthquake := Events[index].FirstPWaveDetection.Add(time.Duration(int64(finalGuess.Epoch) * 1e9))
65
66 guessType := "Partial Earthquake Guess"
67 if finalPrediction {
68 guessType = "Final Earthquake Guess"
69 }
70
71 log.Info().
72 Str("type", guessType).
73 Int("detections", len(Events[index].Detections)).
74 Str("date", dateOfEarthquake.Format("2006-01-02T15:04:05.000")).
75 Float64("latitude", finalGuess.Lat*180/math.Pi).
76 Float64("longitude", finalGuess.Lon*180/math.Pi).
77 Float64("depth_km", finalGuess.Depth).
78 Msg("Earthquake prediction")
79 }
80}
81
82func GetEventName(index int) string {
83 return Events[index].FirstPWaveDetection.Format("2006-01-02T15:04:05.000")
84}
85
86func NewDetection(connection, stationID string, pWaveArrival, sWaveArrival time.Time) (string, bool) {
87 stationLat := (*stations.Stations[connection])[stationID].Lat * math.Pi / 180
88 stationLon := (*stations.Stations[connection])[stationID].Lon * math.Pi / 180
89 groupableEvent := false
90 var index int
91 for i, event := range Events {
92 if locate.GreatCircleAngle(event.FirstDetectionLat, event.FirstDetectionLon, stationLat, stationLon) < config.EventExtent && !IsEventOver(pWaveArrival, i) {
93 groupableEvent = true
94 index = i
95 log.Debug().Int("event_index", i).Msg("Found groupable event")
96 break
97 }
98 }
99 if !groupableEvent {
100 Events = append(Events, &Event{
101 FirstDetectionLat: stationLat,
102 FirstDetectionLon: stationLon,
103 FirstPWaveDetection: pWaveArrival,
104 Detections: make(map[string]Detection),
105 LastPWaveArrival: pWaveArrival,
106 FinalConclusionReached: false,
107 })
108 index = len(Events) - 1
109 log.Info().
110 Int("event_index", index).
111 Float64("lat", stationLat*180/math.Pi).
112 Float64("lon", stationLon*180/math.Pi).
113 Msg("Created new event")
114 }
115
116 _, ok := Events[index].Detections[connection+"@"+stationID]
117 if !ok {
118 Events[index].LastPWaveArrival = pWaveArrival
119 go FinalConclusionCheck(index)
120 }
121 Events[index].Detections[connection+"@"+stationID] = Detection{
122 PWaveArrival: pWaveArrival,
123 SWaveArrival: sWaveArrival,
124 }
125
126 Predict(index, false)
127 return GetEventName(index), !ok
128}