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}