Skip to content

Commit 975fdf0

Browse files
author
Mike Hearne
authored
Merge pull request #146 from mhearne-usgs/depfix
Cleaned up command line behavior a bit, modified origin description p…
2 parents 07f68eb + 6983aa1 commit 975fdf0

2 files changed

Lines changed: 108 additions & 43 deletions

File tree

bin/geteventhist

Lines changed: 76 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,31 @@ import textwrap
99
import pandas as pd
1010
from openpyxl import load_workbook
1111
from obspy.geodetics.base import gps2dist_azimuth
12+
import numpy as np
1213

1314
# local imports
1415
from libcomcat.search import search
1516
from libcomcat.dataframes import (get_history_data_frame, split_history_frame,
1617
PRODUCTS, TIMEFMT, PRODUCT_COLUMNS)
1718

1819

20+
DISPLAY_TIME_FMT = '%Y-%m-%d %H:%M:%S'
21+
22+
23+
class MyFormatter(argparse.RawTextHelpFormatter,
24+
argparse.ArgumentDefaultsHelpFormatter):
25+
pass
26+
27+
1928
def get_parser():
2029
desc = '''Print out ComCat event history.
2130
2231
Usage:
2332
geteventhist ci38457511
2433
2534
'''
26-
formatter = argparse.RawDescriptionHelpFormatter
2735
parser = argparse.ArgumentParser(description=desc,
28-
formatter_class=formatter)
36+
formatter_class=MyFormatter)
2937
# positional arguments
3038
parser.add_argument('eventid',
3139
metavar='EVENTID', help='ComCat event ID.')
@@ -53,7 +61,7 @@ def get_parser():
5361
parser.add_argument('-o', '--outdir', help=ohelp,
5462
default=None)
5563

56-
parser.add_argument('-w', '--web', help='Produce HTML output.',
64+
parser.add_argument('-w', '--web', help='Print HTML tables to stdout.',
5765
default=False, action='store_true')
5866

5967
parser.add_argument('-f', '--format', help='Control output format',
@@ -113,10 +121,10 @@ def save_dataframe(outdir, format, event, dataframe, product=None):
113121
wb.save(outfile)
114122
else:
115123
if product is not None:
116-
outfile = os.path.join(args.outdir,
117-
event.id + '_' + products[0] + '.csv')
124+
outfile = os.path.join(outdir,
125+
event.id + '_' + product + '.csv')
118126
else:
119-
outfile = os.path.join(args.outdir, event.id + '.csv')
127+
outfile = os.path.join(outdir, event.id + '.csv')
120128
dataframe.to_csv(outfile, index=False)
121129
cdata = open(outfile, 'rt').read()
122130
with open(outfile, 'wt') as f:
@@ -131,10 +139,43 @@ def save_dataframe(outdir, format, event, dataframe, product=None):
131139
return outfile
132140

133141

142+
def web_print(event, dataframe):
143+
etable_fmt = '''
144+
<pre>
145+
Event ID: %s
146+
Origin Time: %s
147+
Magnitude: %.1f
148+
Latitude: %.4f
149+
Longitude: %.4f
150+
Depth: %.1f
151+
</pre>
152+
'''
153+
etable_tpl = (event.id,
154+
event.time.strftime(TIMEFMT),
155+
event.magnitude,
156+
event.latitude,
157+
event.longitude,
158+
event.depth)
159+
etable = etable_fmt % etable_tpl
160+
print(textwrap.dedent(etable))
161+
print(dataframe.to_html(index=False, border=0, max_rows=None, max_cols=None))
162+
163+
164+
def simplify_times(dataframe):
165+
# re-format all time columns to be like: 2019-01-01 17:34:16.1
166+
# first figure out all the time-like columns
167+
# df['date'] = pd.to_datetime(df["date"].dt.strftime('%Y-%m'))
168+
dtypes = dataframe.dtypes
169+
for idx, dtype in dtypes.iteritems():
170+
if np.issubdtype(dtype, np.datetime64):
171+
dataframe[idx] = pd.to_datetime(
172+
dataframe[idx].dt.strftime(DISPLAY_TIME_FMT))
173+
174+
134175
def main():
135176
pd.set_option('display.width', 1000)
136177
pd.set_option('display.max_rows', 1000)
137-
pd.set_option('display.max_colwidth', 120)
178+
pd.set_option('display.max_colwidth', -1)
138179
pd.set_option('display.max_columns', 1000)
139180
pd.set_option("display.colheader_justify", "left")
140181
parser = get_parser()
@@ -155,6 +196,16 @@ def main():
155196
print(fmt % (','.join(unsupported)))
156197
sys.exit(1)
157198

199+
# web output and directory output are mutually exclusive
200+
if args.outdir and args.web:
201+
msg = '''The -o and -w options are mutually exclusive, meaning
202+
that you cannot choose to write files to a directory and print
203+
HTML output to the screen simultaneously. Please choose one of
204+
those two options and try again.
205+
'''
206+
print(msg)
207+
sys.exit(1)
208+
158209
if args.products:
159210
products = args.products
160211
else:
@@ -196,8 +247,14 @@ def main():
196247
# now re-sort by update time
197248
dataframe = dataframe.sort_values('Update Time')
198249
dataframe = dataframe[PRODUCT_COLUMNS]
250+
else:
251+
# since "Authoritative Event ID" and "Associated" columns are only applicable when
252+
# we're including other events in our results, drop those columns
253+
# if we're not doing that.
254+
drop_columns = ['Authoritative Event ID', 'Associated']
255+
dataframe = dataframe.drop(drop_columns, axis='columns')
199256

200-
if not os.path.isdir(args.outdir):
257+
if args.outdir is not None and not os.path.isdir(args.outdir):
201258
os.makedirs(args.outdir)
202259

203260
if args.split:
@@ -207,36 +264,23 @@ def main():
207264
# somehow in this process
208265
for product in available_products:
209266
pframe = split_history_frame(dataframe, product=product)
210-
outfile = save_dataframe(args.outdir, args.format, event,
211-
pframe, product=product)
212-
print('%i rows saved to %s' % (len(pframe), outfile))
267+
simplify_times(pframe)
268+
if args.web:
269+
web_print(event, pframe)
270+
else:
271+
outfile = save_dataframe(args.outdir, args.format, event,
272+
pframe, product=product)
273+
print('%i rows saved to %s' % (len(pframe), outfile))
274+
sys.exit(0)
275+
213276
if args.outdir:
214277
outfile = save_dataframe(args.outdir, args.format, event,
215278
dataframe, product=None)
216279

217280
print('%i rows saved to %s' % (len(dataframe), outfile))
218281
elif args.web:
219-
etable_fmt = '''
220-
<pre>
221-
Event ID: %s
222-
Origin Time: %s
223-
Magnitude: %.1f
224-
Latitude: %.4f
225-
Longitude: %.4f
226-
Depth: %.1f
227-
</pre>
228-
'''
229-
etable_tpl = (event.id,
230-
event.time.strftime(TIMEFMT),
231-
event.magnitude,
232-
event.latitude,
233-
event.longitude,
234-
event.depth)
235-
etable = etable_fmt % etable_tpl
236-
print(textwrap.dedent(etable))
237-
print(dataframe.to_html(index=False, border=0))
238-
else:
239-
print(dataframe.to_string(index=False))
282+
simplify_times(dataframe)
283+
web_print(event, dataframe)
240284

241285
sys.exit(0)
242286

libcomcat/dataframes.py

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import requests
1717
from scipy.special import erfcinv
1818
from obspy.geodetics.base import gps2dist_azimuth
19+
from impactutils.mapping.compass import get_compass_dir_azimuth
1920

2021
# local imports
2122
from libcomcat.classes import VersionOption
@@ -54,9 +55,9 @@
5455
'Hypocentral distance': 'distance'
5556
}
5657

57-
PRODUCT_COLUMNS = ['Product', 'Authoritative Event ID', 'Code', 'Associated',
58+
PRODUCT_COLUMNS = ['Update Time', 'Product', 'Authoritative Event ID', 'Code', 'Associated',
5859
'Product Source', 'Product Version',
59-
'Update Time', 'Elapsed (min)', 'Description']
60+
'Elapsed (min)', 'Description']
6061

6162
SECSPERDAY = 86400
6263
TIMEFMT = '%Y-%m-%d %H:%M:%S'
@@ -1284,7 +1285,7 @@ def _describe_origin(event, product):
12841285
if product.hasProperty('magnitude-type'):
12851286
magtype = product['magnitude-type']
12861287

1287-
otime = 'unknown'
1288+
otime = 'NaT'
12881289
tdiff = np.nan
12891290
if product.hasProperty('eventtime'):
12901291
otime_str = product['eventtime']
@@ -1295,26 +1296,47 @@ def _describe_origin(event, product):
12951296
elapsed_sec = elapsed.days * SECSPERDAY + \
12961297
elapsed.seconds + elapsed.microseconds / 1e6
12971298
elapsed_min = elapsed_sec / 60
1299+
12981300
olat = np.nan
12991301
olon = np.nan
1302+
odepth = np.nan
13001303
dist = np.nan
1301-
1304+
az = np.nan
13021305
if product.hasProperty('latitude'):
13031306
olat = float(product['latitude'])
13041307
olon = float(product['longitude'])
13051308
odepth = float(product['depth'])
1306-
dist_m, _, _ = gps2dist_azimuth(authlat, authlon, olat, olon)
1309+
dist_m, az, _ = gps2dist_azimuth(authlat, authlon, olat, olon)
13071310
dist = dist_m / 1000.0
1311+
else:
1312+
if len(product.getContentsMatching('quakeml.xml')):
1313+
unpickler = Unpickler()
1314+
cbytes, url = product.getContentBytes('quakeml.xml')
1315+
catalog = unpickler.loads(cbytes)
1316+
evt = catalog.events[0]
1317+
if hasattr(evt, 'origin'):
1318+
origin = evt.origin
1319+
olat = origin.latitude
1320+
olon = origin.longitude
1321+
odepth = origin.depth/1000
1322+
dist_m, az, _ = gps2dist_azimuth(authlat, authlon, olat, olon)
1323+
dist = dist_m / 1000.0
13081324

13091325
loc_method = 'unknown'
13101326
if product.hasProperty('cube-location-method'):
13111327
loc_method = product['cube-location-method']
13121328

1313-
fmt = ('Magnitude# %.1f|Depth# %.1f|Time# %s |Time Offset (sec)# %.1f|'
1329+
# convert azimuth to cardinal direction
1330+
if not np.isnan(az):
1331+
azstr = get_compass_dir_azimuth(az, resolution='meteorological')
1332+
else:
1333+
azstr = ''
1334+
1335+
fmt = ('Magnitude# %.1f|Time# %s |Time Offset (sec)# %.1f|'
13141336
'Location# (%.3f,%.3f)|Distance from Auth. Origin (km)# %.1f|'
1315-
'Magnitude Type# %s|Location Method# %s')
1316-
desc = fmt % (omag, odepth, otime, tdiff,
1317-
olat, olon, dist, magtype, loc_method)
1337+
'Azimuth# %s|Depth# %.1f|Magnitude Type# %s|Location Method# %s')
1338+
desc = fmt % (omag, otime, tdiff,
1339+
olat, olon, dist, azstr, odepth, magtype, loc_method)
13181340
productsource = product['eventsource']
13191341
pversion = product.version
13201342
row = {'Product': product.name,
@@ -1630,15 +1652,14 @@ def split_history_frame(dataframe, product=None):
16301652
newval = float(val)
16311653
except ValueError:
16321654
try:
1633-
newval = datetime.strptime(val, TIMEFMT3)
1655+
newval = pd.Timestamp(val)
16341656
except ValueError:
16351657
newval = val
16361658
newvalues.append(newval)
16371659
ddict = dict(zip(columns, newvalues))
16381660
row = pd.Series(ddict)
16391661
df2 = df2.append(row, ignore_index=True)
16401662

1641-
# todo: something weird happening in concat step
16421663
dataframe = dataframe.reset_index(drop=True)
16431664
df2 = df2.reset_index(drop=True)
16441665
dataframe = pd.concat([dataframe, df2], axis=1)

0 commit comments

Comments
 (0)