sourceextensions/http/demos/Seismic.xtl
1⍝# Seismic.xtl -- the earthquake report (quakes.xtl, quakes-live.xtl): a
2⍝# USGS feed CSV into SQLite, SQL to select and group, X_eTaL arrays to
3⍝# compute, pictures to see it. An ordinary X_eTaL library beside them
4⍝# (not Quakes.xtl: on a case-insensitive file system that is quakes.xtl).
5⍝# Import: "se:" u_se< "Seismic"
6
7"sq:" u̲se< "Sqlite"
8
9db ← "work/quakes.db"
10
11ʰr̲ound ← { v → (f̲loat f̲loor 0.5 + 100.0 × v) ÷ 100.0 }
12ʰm̲ean ← { v → ('+ r̲/ v) ÷ f̲loat t̲ally v }
13
14⍝# se:r_eport "path.csv": prints the report and draws its pictures
15ˡr̲eport ← { csv →
16 x ← db sq:e̲xec "drop table if exists quakes"
17 n ← db sq:i̲mport "quakes=" c̲at csv
18
19 ⍝ -- 1. SQL: what is there
20 a ← p̲rint! "quakes, the smallest and largest magnitude, the mean depth (km):"
21 a ← p̲rint! ʰr̲ound r̲avel db sq:n̲ums "select count(*), min(mag), max(mag), avg(depth) from quakes"
22 a ← p̲rint! "from, to (UTC):"
23 a ← p̲rint! db sq:t̲exts "select substr(min(time), 1, 16), substr(max(time), 1, 16) from quakes"
24
25 ⍝ -- 2. SQL groups: the largest three, and quakes per day
26 a ← p̲rint! "the largest three: magnitude, place"
27 a ← p̲rint! db sq:t̲exts "select printf('%.1f', mag) || ' ' || place from quakes order by mag desc limit 3"
28 a ← p̲rint! "quakes per day:"
29 a ← p̲rint! r̲avel db sq:n̲ums "select count(*) from quakes group by substr(time, 1, 10) order by substr(time, 1, 10)"
30
31 ⍝ -- 3. arrays: magnitudes in half-unit bins (2.45 rounds into the
32 ⍝ first), and the Gutenberg-Richter law: the count at or above each
33 ⍝ magnitude falls about tenfold per unit -- its b-value is about 1.
34 ⍝ Outside the US this feed lists quakes from about 4.5 up, so b is
35 ⍝ estimated above 4.5 (Aki's maximum likelihood: log10 e over the
36 ⍝ mean magnitude's excess, magnitudes given to 0.1)
37 m ← r̲avel db sq:n̲ums "select mag from quakes"
38 b ← 1 + 0 m̲ax f̲loor (m − 2.5) ÷ 0.5
39 h ← '+ r̲/₂ (r̲ange 10) '= t̲able b
40 a ← p̲rint! "quakes in [2.5, 3), [3, 3.5), ... [7, 7.5):"
41 a ← p̲rint! h
42 t ← 2.5 + 0.5 × f̲loat (r̲ange 8) − 1
43 c ← '+ r̲/₂ t '≤ t̲able m
44 k ← '+ r̲/ c > 0
45 t ← k t̲ake t
46 g ← (l̲og f̲loat k t̲ake c) ÷ l̲og 10.0
47 a ← p̲rint! "log10 of the count at or above 2.5, 3, 3.5, ...:"
48 a ← p̲rint! ʰr̲ound g
49 big ← (m ≥ 4.5) r̲eplicate m
50 a ← p̲rint! "quakes of 4.5 and up, and their b-value (Aki):"
51 a ← p̲rint! (f̲loat t̲ally big) c̲at ʰr̲ound 0.4342944819 ÷ (ʰm̲ean big) − 4.45
52
53 ⍝ -- 4. pictures
54 ⍝ a world map: quakes counted in 10-degree cells, 18 rows (north at
55 ⍝ the top) by 36 columns (from 180 W), one array index per quake
56 ll ← db sq:n̲ums "select latitude, longitude from quakes"
57 row ← 17 m̲in f̲loor (90.0 − 1 s̲elect₂ ll) ÷ 10.0
58 col ← 35 m̲in f̲loor (180.0 + 2 s̲elect₂ ll) ÷ 10.0
59 w ← '+ r̲/₂ (r̲ange 648) '= t̲able 1 + col + 36 × row
60 p ← ⎕S̲HOW ⎕G̲RID 18 36 r̲eshape (w > 0) + (w > 2) + w > 8
61 ⍝ the magnitude histogram as bars, a cell per 5 quakes, and the law
62 ⍝ as a line
63 h5 ← c̲eiling (f̲loat h) ÷ 5.0
64 p ← ⎕S̲HOW ⎕G̲RID (r̲ev r̲ange 'm̲ax r̲/ h5) '≤ t̲able h5
65 p ← ⎕S̲HOW ⎕P̲ATH (2 c̲at t̲ally t) r̲eshape t c̲at g
66 "drawn: the map, the histogram, the Gutenberg-Richter line"
67}