15
15
from sourcespec .ssp_setup import ssp_exit
16
16
from sourcespec ._version import get_versions
17
17
logger = logging .getLogger (__name__ .split ('.' )[- 1 ])
18
+ # Current supported DB version
19
+ DB_VERSION = 2
18
20
19
21
20
- def _log_db_write_error (db_err , db_file ):
21
- logger .error (f'Unable to insert values: { db_err } ' )
22
- logger .info ('Maybe your sqlite database has an old format.' )
23
- logger .info ('Try to remove or rename your database file.' )
24
- logger .info (f'(Current database file: { db_file } )' )
25
- ssp_exit (1 )
22
+ def _db_file_exists (db_file ):
23
+ """
24
+ Check if SQLite database file exists.
26
25
26
+ :param db_file: SQLite database file
27
+ :type db_file: str
28
+ :return: True if file exists, False otherwise
29
+ :rtype: bool
30
+ """
31
+ return os .path .isfile (db_file )
27
32
28
- def write_sqlite (config , sspec_output ):
29
- try :
30
- database_file = config .database_file
31
- except KeyError :
32
- database_file = None
33
- if not database_file :
34
- return
35
33
36
- event = config .event
37
- evid = event .event_id
38
- runid = config .options .run_id
39
-
40
- # Current supported DB version
41
- DB_VERSION = 2
34
+ def _open_sqlite_db (db_file ):
35
+ """
36
+ Open SQLite database.
42
37
43
- # only check version if database_file exists
44
- check_version = os .path .isfile (database_file )
45
-
46
- # Open SQLite database
38
+ :param db_file: SQLite database file
39
+ :type db_file: str
40
+ :return: SQLite connection and cursor
41
+ :rtype: tuple
42
+ """
47
43
try :
48
- conn = sqlite3 .connect (database_file , timeout = 60 )
44
+ conn = sqlite3 .connect (db_file , timeout = 60 )
49
45
except Exception as msg :
50
46
logger .error (msg )
51
47
logger .info (
52
- f'Please check whether "{ database_file } " is a valid SQLite file.' )
48
+ f'Please check whether "{ db_file } " is a valid SQLite file.' )
53
49
ssp_exit (1 )
54
- c = conn .cursor ()
55
-
56
- if check_version :
57
- # Get current DB version
58
- db_version = c .execute ('PRAGMA user_version' ).fetchone ()[0 ]
59
- if db_version < DB_VERSION :
60
- logger .error (
61
- f'"{ database_file } " has an old database version: '
62
- f'"{ db_version } " Current supported version is "{ DB_VERSION } ".'
63
- )
64
- logger .info (
65
- 'Remove or rename your old database file, '
66
- 'so that a new one can be created.'
67
- )
68
- ssp_exit (1 )
69
- else :
70
- # Set the DB version
71
- c .execute ('PRAGMA user_version = {v:d}' .format (v = DB_VERSION ))
50
+ return conn , conn .cursor ()
51
+
52
+
53
+ def _check_db_version (cursor , db_file ):
54
+ """
55
+ Check database version.
56
+
57
+ :param cursor: SQLite cursor
58
+ :type cursor: sqlite3.Cursor
59
+ :param db_file: SQLite database file
60
+ :type db_file: str
61
+ """
62
+ db_version = cursor .execute ('PRAGMA user_version' ).fetchone ()[0 ]
63
+ if db_version < DB_VERSION :
64
+ logger .error (
65
+ f'"{ db_file } " has an old database version: '
66
+ f'"{ db_version } " Current supported version is "{ DB_VERSION } ".'
67
+ )
68
+ logger .info (
69
+ 'Remove or rename your old database file, '
70
+ 'so that a new one can be created.'
71
+ )
72
+ ssp_exit (1 )
73
+
74
+
75
+ def _set_db_version (cursor ):
76
+ """
77
+ Set database version.
78
+
79
+ :param cursor: SQLite cursor
80
+ :type cursor: sqlite3.Cursor
81
+ """
82
+ cursor .execute ('PRAGMA user_version = {v:d}' .format (v = DB_VERSION ))
83
+
84
+
85
+ def _log_db_write_error (db_err , db_file ):
86
+ """
87
+ Log database write error.
72
88
73
- # Create Station table
89
+ :param db_err: database error
90
+ :type db_err: Exception
91
+ :param db_file: SQLite database file
92
+ :type db_file: str
93
+ """
94
+ logger .error (f'Unable to insert values: { db_err } ' )
95
+ logger .info ('Maybe your sqlite database has an old format.' )
96
+ logger .info ('Try to remove or rename your database file.' )
97
+ logger .info (f'(Current database file: { db_file } )' )
98
+ ssp_exit (1 )
99
+
100
+
101
+ def _create_stations_table (cursor , db_file ):
102
+ """
103
+ Create Stations table.
104
+
105
+ :param cursor: SQLite cursor
106
+ :type cursor: sqlite3.Cursor
107
+ """
74
108
sql_create_stations_table = """CREATE TABLE IF NOT EXISTS Stations (
75
109
stid TEXT,
76
110
evid TEXT,
@@ -106,24 +140,36 @@ def write_sqlite(config, sspec_output):
106
140
Er REAL,
107
141
Er_is_outlier INT,
108
142
dist REAL,
109
- azimuth REAL
143
+ azimuth REAL,
144
+ PRIMARY KEY (stid, evid, runid)
110
145
);"""
111
- c .execute (sql_create_stations_table )
112
- # Write station source parameters to database
113
- nobs = 0
146
+ try :
147
+ cursor .execute (sql_create_stations_table )
148
+ except Exception as db_err :
149
+ _log_db_write_error (db_err , db_file )
150
+
151
+
152
+ def _write_stations_table (cursor , db_file , sspec_output , config ):
153
+ """
154
+ Write station source parameters to database.
155
+
156
+ :param cursor: SQLite cursor
157
+ :type cursor: sqlite3.Cursor
158
+ :param db_file: SQLite database file
159
+ :type db_file: str
160
+ :param sspec_output: sspec output object
161
+ :type sspec_output: ssp_data_types.SourceSpecOutput
162
+ :param config: sspec configuration object
163
+ :type config: config.Config
164
+ """
165
+ event = config .event
166
+ evid = event .event_id
167
+ runid = config .options .run_id
114
168
stationpar = sspec_output .station_parameters
115
- sql_delete_from_stations = \
116
- 'DELETE FROM Stations WHERE stid=? AND evid=? AND runid=?;'
169
+ nobs = 0
117
170
for statId in sorted (stationpar .keys ()):
118
171
nobs += 1
119
172
par = stationpar [statId ]
120
- # Remove existing line, if present
121
- t = (statId , evid , runid )
122
- try :
123
- c .execute (sql_delete_from_stations , t )
124
- except Exception as msg :
125
- _log_db_write_error (msg , database_file )
126
- ssp_exit (1 )
127
173
# Insert new line
128
174
t = (
129
175
statId , evid , runid ,
@@ -148,16 +194,23 @@ def write_sqlite(config, sspec_output):
148
194
)
149
195
# Create a string like ?,?,?,?
150
196
values = ',' .join ('?' * len (t ))
151
- sql_insert_into_stations = f'INSERT INTO Stations VALUES({ values } );'
197
+ sql_insert_into_stations = \
198
+ f'INSERT OR REPLACE INTO Stations VALUES({ values } );'
152
199
try :
153
- c .execute (sql_insert_into_stations , t )
200
+ cursor .execute (sql_insert_into_stations , t )
154
201
except Exception as msg :
155
- _log_db_write_error (msg , database_file )
202
+ _log_db_write_error (msg , db_file )
156
203
ssp_exit (1 )
157
- # Commit changes
158
- conn . commit ()
204
+ return nobs
205
+
159
206
160
- # Create Event table
207
+ def _create_events_table (cursor , db_file ):
208
+ """
209
+ Create Events table.
210
+
211
+ :param cursor: SQLite cursor
212
+ :type cursor: sqlite3.Cursor
213
+ """
161
214
sql_create_events_table = """CREATE TABLE IF NOT EXISTS Events (
162
215
/* Event info */
163
216
evid TEXT,
@@ -263,9 +316,33 @@ def write_sqlite(config, sspec_output):
263
316
author_email TEXT,
264
317
agency_full_name TEXT,
265
318
agency_short_name TEXT,
266
- agency_url TEXT
319
+ agency_url TEXT,
320
+ PRIMARY KEY (evid, runid)
267
321
);"""
268
- c .execute (sql_create_events_table )
322
+ try :
323
+ cursor .execute (sql_create_events_table )
324
+ except Exception as db_err :
325
+ _log_db_write_error (db_err , db_file )
326
+
327
+
328
+ def _write_events_table (cursor , db_file , sspec_output , config , nobs ):
329
+ """
330
+ Write Events table.
331
+
332
+ :param cursor: SQLite cursor
333
+ :type cursor: sqlite3.Cursor
334
+ :param db_file: SQLite database file
335
+ :type db_file: str
336
+ :param sspec_output: SSP output object
337
+ :type sspec_output: ssp_data_types.SourceSpecOutput
338
+ :param config: SSP configuration object
339
+ :type config: config.Config
340
+ :param nobs: Number of observations
341
+ :type nobs: int
342
+ """
343
+ event = config .event
344
+ evid = event .event_id
345
+ runid = config .options .run_id
269
346
means = sspec_output .mean_values ()
270
347
mean_errors = sspec_output .mean_uncertainties ()
271
348
wmeans = sspec_output .weighted_mean_values ()
@@ -274,14 +351,6 @@ def write_sqlite(config, sspec_output):
274
351
percentile_errors = sspec_output .percentiles_uncertainties ()
275
352
run_completed = f'{ config .end_of_run } { config .end_of_run_tz } '
276
353
ssp_version = get_versions ()['version' ]
277
- # Remove event from Event table, if present
278
- t = (evid , runid )
279
- sql_delete_from_events = 'DELETE FROM Events WHERE evid=? AND runid=?;'
280
- try :
281
- c .execute (sql_delete_from_events , t )
282
- except Exception as msg :
283
- _log_db_write_error (msg , database_file )
284
- ssp_exit (1 )
285
354
ev_lon = event .hypocenter .longitude .value_in_deg
286
355
ev_lat = event .hypocenter .latitude .value_in_deg
287
356
ev_depth = event .hypocenter .depth .value_in_km
@@ -370,13 +439,45 @@ def write_sqlite(config, sspec_output):
370
439
)
371
440
# Create a string like ?,?,?,?
372
441
values = ',' .join ('?' * len (t ))
373
- sql_insert_into_events = f'INSERT INTO Events VALUES({ values } );'
442
+ sql_insert_into_events = f'INSERT OR REPLACE INTO Events VALUES({ values } );'
374
443
try :
375
- c .execute (sql_insert_into_events , t )
444
+ cursor .execute (sql_insert_into_events , t )
376
445
except Exception as msg :
377
- _log_db_write_error (msg , database_file )
446
+ _log_db_write_error (msg , db_file )
378
447
ssp_exit (1 )
448
+
449
+
450
+ def write_sqlite (config , sspec_output ):
451
+ """
452
+ Write SSP output to SQLite database.
453
+
454
+ :param config: SSP configuration object
455
+ :type config: config.Config
456
+ :param sspec_output: SSP output object
457
+ :type sspec_output: ssp_data_types.SourceSpecOutput
458
+ """
459
+ db_file = config .get ('database_file' , None )
460
+ if not db_file :
461
+ return
462
+
463
+ db_file_exists = _db_file_exists (db_file )
464
+ conn , cursor = _open_sqlite_db (db_file )
465
+ if db_file_exists :
466
+ _check_db_version (cursor , db_file )
467
+ else :
468
+ _set_db_version (cursor )
469
+
470
+ # Create Stations table
471
+ _create_stations_table (cursor , db_file )
472
+ # Write station source parameters to database
473
+ nobs = _write_stations_table (cursor , db_file , sspec_output , config )
474
+ # Commit changes
475
+ conn .commit ()
476
+ # Create Events table
477
+ _create_events_table (cursor , db_file )
478
+ # Write event source parameters to database
479
+ _write_events_table (cursor , db_file , sspec_output , config , nobs )
379
480
# Commit changes and close database
380
481
conn .commit ()
381
482
conn .close ()
382
- logger .info (f'Output written to SQLite database: { database_file } ' )
483
+ logger .info (f'Output written to SQLite database: { db_file } ' )
0 commit comments