Skip to content

Commit 6a92269

Browse files
author
Mike Hearne
authored
Merge pull request #252 from mhearne-usgs/nullmagfix
Adding support for negative and null magnitudes in searches
2 parents 18278d0 + 062d647 commit 6a92269

26 files changed

Lines changed: 28097 additions & 20746 deletions

libcomcat/classes.py

Lines changed: 337 additions & 335 deletions
Large diffs are not rendered by default.

libcomcat/search.py

Lines changed: 173 additions & 157 deletions
Large diffs are not rendered by default.

libcomcat/utils.py

Lines changed: 83 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -25,34 +25,39 @@
2525

2626
# use this to set the user agent for each request, giving us a way
2727
# to distinguish libcomcat requests from other browser requests
28-
HEADERS = {'User-Agent': 'libcomcat v%s' % libversion}
28+
HEADERS = {"User-Agent": "libcomcat v%s" % libversion}
2929

3030
# constants
31-
CATALOG_SEARCH_TEMPLATE = 'https://earthquake.usgs.gov/fdsnws/event/1/catalogs'
32-
CONTRIBUTORS_SEARCH_TEMPLATE = ('https://earthquake.usgs.gov/fdsnws/event/'
33-
'1/contributors')
31+
CATALOG_SEARCH_TEMPLATE = "https://earthquake.usgs.gov/fdsnws/event/1/catalogs"
32+
CONTRIBUTORS_SEARCH_TEMPLATE = (
33+
"https://earthquake.usgs.gov/fdsnws/event/" "1/contributors"
34+
)
3435
TIMEOUT = 60
35-
TIMEFMT1 = '%Y-%m-%dT%H:%M:%S'
36-
TIMEFMT2 = '%Y-%m-%dT%H:%M:%S.%f'
37-
DATEFMT = '%Y-%m-%d'
38-
COUNTRYFILE = 'ne_10m_admin_0_countries.shp'
36+
TIMEFMT1 = "%Y-%m-%dT%H:%M:%S"
37+
TIMEFMT2 = "%Y-%m-%dT%H:%M:%S.%f"
38+
DATEFMT = "%Y-%m-%d"
39+
COUNTRYFILE = "ne_10m_admin_0_countries.shp"
3940

4041
# where is the PAGER fatality model found?
41-
FATALITY_URL = ('https://raw.githubusercontent.com/usgs/pager/master/'
42-
'losspager/data/fatality.xml')
43-
ECONOMIC_URL = ('https://raw.githubusercontent.com/usgs/pager/master/'
44-
'losspager/data/economy.xml')
45-
46-
COUNTRIES_SHP = 'ne_50m_admin_0_countries.shp'
42+
FATALITY_URL = (
43+
"https://raw.githubusercontent.com/usgs/pager/master/" "losspager/data/fatality.xml"
44+
)
45+
ECONOMIC_URL = (
46+
"https://raw.githubusercontent.com/usgs/pager/master/" "losspager/data/economy.xml"
47+
)
48+
49+
COUNTRIES_SHP = "ne_50m_admin_0_countries.shp"
4750
BUFFER_DISTANCE_KM = 100
4851
KM_PER_DEGREE = 119.191
4952

5053
TIMEOUT = 60 # how long should we wait for a response from ComCat?
5154

5255

53-
class CombinedFormatter(argparse.ArgumentDefaultsHelpFormatter,
54-
argparse.RawTextHelpFormatter,
55-
argparse.RawDescriptionHelpFormatter):
56+
class CombinedFormatter(
57+
argparse.ArgumentDefaultsHelpFormatter,
58+
argparse.RawTextHelpFormatter,
59+
argparse.RawDescriptionHelpFormatter,
60+
):
5661
pass
5762

5863

@@ -77,30 +82,32 @@ def get_mag_src(mag):
7782
if c2:
7883
magsrc = mag.creation_info.agency_id.lower()
7984
else:
80-
has_gcmt = mag.resource_id.id.lower().find('gcmt') > -1
81-
has_at = mag.resource_id.id.lower().find('at') > -1
82-
has_pt = mag.resource_id.id.lower().find('pt') > -1
83-
has_ak = (mag.resource_id.id.lower().find('ak') > -1 or
84-
mag.resource_id.id.lower().find('alaska') > -1)
85-
has_pr = mag.resource_id.id.lower().find('pr') > -1
86-
has_dup = mag.resource_id.id.lower().find('duputel') > -1
87-
has_us = mag.resource_id.id.lower().find('us') > -1
85+
has_gcmt = mag.resource_id.id.lower().find("gcmt") > -1
86+
has_at = mag.resource_id.id.lower().find("at") > -1
87+
has_pt = mag.resource_id.id.lower().find("pt") > -1
88+
has_ak = (
89+
mag.resource_id.id.lower().find("ak") > -1
90+
or mag.resource_id.id.lower().find("alaska") > -1
91+
)
92+
has_pr = mag.resource_id.id.lower().find("pr") > -1
93+
has_dup = mag.resource_id.id.lower().find("duputel") > -1
94+
has_us = mag.resource_id.id.lower().find("us") > -1
8895
if has_gcmt:
89-
magsrc = 'gcmt'
96+
magsrc = "gcmt"
9097
elif has_dup:
91-
magsrc = 'duputel'
98+
magsrc = "duputel"
9299
elif has_at:
93-
magsrc = 'at'
100+
magsrc = "at"
94101
elif has_pt:
95-
magsrc = 'pt'
102+
magsrc = "pt"
96103
elif has_ak:
97-
magsrc = 'ak'
104+
magsrc = "ak"
98105
elif has_pr:
99-
magsrc = 'pr'
106+
magsrc = "pr"
100107
elif has_us:
101-
magsrc = 'us'
108+
magsrc = "us"
102109
else:
103-
magsrc = 'unknown'
110+
magsrc = "unknown"
104111

105112
return magsrc
106113

@@ -117,30 +124,30 @@ def read_phases(filename):
117124
dataframe - Pandas dataframe containing phase data.
118125
"""
119126
if not os.path.isfile(filename):
120-
raise FileNotFoundError('Filename %s does not exist.' % filename)
127+
raise FileNotFoundError("Filename %s does not exist." % filename)
121128
header_dict = {}
122-
if filename.endswith('xlsx'):
129+
if filename.endswith("xlsx"):
123130
wb = load_workbook(filename=filename, read_only=True)
124131
ws = wb.active
125-
key = ''
132+
key = ""
126133
rowidx = 1
127134

128-
while key != 'Channel':
129-
key = ws['A%i' % rowidx].value
130-
if not key.startswith('#'):
131-
value = ws['B%i' % rowidx].value
135+
while key != "Channel":
136+
key = ws["A%i" % rowidx].value
137+
if not key.startswith("#"):
138+
value = ws["B%i" % rowidx].value
132139
header_dict[key] = value
133140
rowidx += 1
134141
wb.close()
135142
dataframe = pd.read_excel(filename, skiprows=rowidx - 2)
136-
elif filename.endswith('csv'):
137-
f = open(filename, 'rt')
143+
elif filename.endswith("csv"):
144+
f = open(filename, "rt")
138145
tline = f.readline()
139146
rowidx = 0
140-
while tline.startswith('#'):
141-
if not tline.startswith('#%'):
142-
line = tline.replace('#', '').strip()
143-
key, value = line.split('=')
147+
while tline.startswith("#"):
148+
if not tline.startswith("#%"):
149+
line = tline.replace("#", "").strip()
150+
key, value = line.split("=")
144151
key = key.strip()
145152
value = value.strip()
146153
header_dict[key] = value
@@ -150,19 +157,20 @@ def read_phases(filename):
150157
dataframe = pd.read_csv(filename, skiprows=rowidx)
151158
else:
152159
f, ext = os.path.splitext(filename)
153-
raise Exception('Filenames with extension %s are not supported.' % ext)
160+
raise Exception("Filenames with extension %s are not supported." % ext)
154161
return (header_dict, dataframe)
155162

156163

157164
def makedict(dictstring):
158165
try:
159-
parts = dictstring.split(':')
166+
parts = dictstring.split(":")
160167
key = parts[0]
161168
value = parts[1]
162169
return {key: value}
163170
except Exception:
164171
raise Exception(
165-
'Could not create a single key dictionary out of %s' % dictstring)
172+
"Could not create a single key dictionary out of %s" % dictstring
173+
)
166174

167175

168176
def maketime(timestring):
@@ -176,8 +184,7 @@ def maketime(timestring):
176184
try:
177185
outtime = HistoricTime.strptime(timestring, DATEFMT)
178186
except Exception:
179-
raise Exception(
180-
'Could not parse time or date from %s' % timestring)
187+
raise Exception("Could not parse time or date from %s" % timestring)
181188
return outtime
182189

183190

@@ -196,7 +203,7 @@ def get_catalogs():
196203
raise ConnectionError(fmt % (CATALOG_SEARCH_TEMPLATE, str(e)))
197204

198205
root = minidom.parseString(data)
199-
catalogs = root.getElementsByTagName('Catalog')
206+
catalogs = root.getElementsByTagName("Catalog")
200207
catlist = []
201208
for catalog in catalogs:
202209
catlist.append(catalog.firstChild.data)
@@ -218,7 +225,7 @@ def get_contributors():
218225
fmt = 'Could not connect to url %s. Error: "%s"'
219226
raise ConnectionError(fmt % (CONTRIBUTORS_SEARCH_TEMPLATE, str(e)))
220227
root = minidom.parseString(data)
221-
contributors = root.getElementsByTagName('Contributor')
228+
contributors = root.getElementsByTagName("Contributor")
222229
conlist = []
223230
for contributor in contributors:
224231
conlist.append(contributor.firstChild.data)
@@ -235,12 +242,12 @@ def check_ccode(ccode):
235242
bool: True if valid country code found in bounds file, False otherwise.
236243
"""
237244
ccode = ccode.upper()
238-
datapath = os.path.join('data', COUNTRIES_SHP)
239-
shpfile = pkg_resources.resource_filename('libcomcat', datapath)
245+
datapath = os.path.join("data", COUNTRIES_SHP)
246+
shpfile = pkg_resources.resource_filename("libcomcat", datapath)
240247
ccodes = []
241-
with fiona.open(shpfile, 'r') as shapes:
248+
with fiona.open(shpfile, "r") as shapes:
242249
for shape in shapes:
243-
isocode = shape['properties']['ADM0_A3']
250+
isocode = shape["properties"]["ADM0_A3"]
244251
ccodes.append(isocode)
245252
if ccode not in ccodes:
246253
return False
@@ -260,17 +267,16 @@ def get_country_bounds(ccode, buffer_km=BUFFER_DISTANCE_KM):
260267
"""
261268
xmin = xmax = ymin = ymax = None
262269
ccode = ccode.upper()
263-
datapath = os.path.join('data', COUNTRIES_SHP)
264-
shpfile = pkg_resources.resource_filename('libcomcat', datapath)
270+
datapath = os.path.join("data", COUNTRIES_SHP)
271+
shpfile = pkg_resources.resource_filename("libcomcat", datapath)
265272
bounds = []
266-
with fiona.open(shpfile, 'r') as shapes:
273+
with fiona.open(shpfile, "r") as shapes:
267274
for shape in shapes:
268-
if shape['properties']['ADM0_A3'] == ccode:
269-
country = sShape(shape['geometry'])
275+
if shape["properties"]["ADM0_A3"] == ccode:
276+
country = sShape(shape["geometry"])
270277
if isinstance(country, MultiPolygon):
271278
for polygon in country:
272-
xmin, ymin, xmax, ymax = _buffer(
273-
polygon.bounds, buffer_km)
279+
xmin, ymin, xmax, ymax = _buffer(polygon.bounds, buffer_km)
274280
bounds.append((xmin, xmax, ymin, ymax))
275281
else:
276282
xmin, ymin, xmax, ymax = _buffer(country.bounds, buffer_km)
@@ -282,7 +288,7 @@ def get_country_bounds(ccode, buffer_km=BUFFER_DISTANCE_KM):
282288

283289
def _buffer(bounds, buffer_km):
284290
xmin, ymin, xmax, ymax = bounds
285-
km2deg = (1 / KM_PER_DEGREE)
291+
km2deg = 1 / KM_PER_DEGREE
286292
ymin -= buffer_km * km2deg
287293
ymax += buffer_km * km2deg
288294
yav = (ymin + ymax) / 2
@@ -292,39 +298,24 @@ def _buffer(bounds, buffer_km):
292298

293299

294300
def _get_country_shape(ccode):
295-
datapath = os.path.join('data', COUNTRIES_SHP)
296-
shpfile = pkg_resources.resource_filename('libcomcat', datapath)
301+
datapath = os.path.join("data", COUNTRIES_SHP)
302+
shpfile = pkg_resources.resource_filename("libcomcat", datapath)
297303
country = None
298-
with fiona.open(shpfile, 'r') as shapes:
304+
with fiona.open(shpfile, "r") as shapes:
299305
for shape in shapes:
300-
if shape['properties']['ADM0_A3'] == ccode:
301-
country = sShape(shape['geometry'])
306+
if shape["properties"]["ADM0_A3"] == ccode:
307+
country = sShape(shape["geometry"])
302308

303309
return country
304310

305311

306312
def _get_utm_proj(lat, lon):
307313
zone = str((math.floor((lon + 180) / 6) % 60) + 1)
308-
alphabet = string.ascii_uppercase
309-
alphabet = alphabet.replace('I', '')
310-
alphabet = alphabet.replace('O', '')
311-
alphabet = alphabet[2:-2]
312-
if lat < -80:
313-
band = 'C'
314-
elif lat > 84:
315-
band = 'X'
316-
else:
317-
band_starts = np.arange(-80, 80, 8)
318-
# band_ends = np.append(np.arange(-72, 80, 8), [84])
319-
dstarts = lat - band_starts
320-
sidx = np.where(dstarts >= 0)[0].max()
321-
band = alphabet[sidx]
322-
fmt = ("+proj=utm +zone=%s%s, %s +ellps=WGS84 "
323-
"+datum=WGS84 +units=m +no_defs")
324-
south = ''
314+
fmt = "+proj=utm +zone=%s %s +ellps=WGS84 " "+datum=WGS84 +units=m +no_defs"
315+
south = ""
325316
if lat < 0:
326-
south = '+south'
327-
tpl = (zone, band, south)
317+
south = "+south"
318+
tpl = (zone, south)
328319
proj = pyproj.Proj(fmt % tpl)
329320
return proj
330321

@@ -339,10 +330,7 @@ def _get_pshape(polygon, buffer_km):
339330
center_lon -= 360
340331
center_lat = (bounds[1] + bounds[3]) / 2
341332
utmproj = _get_utm_proj(center_lat, center_lon)
342-
project = partial(
343-
pyproj.transform,
344-
pyproj.Proj(init='epsg:4326'),
345-
utmproj)
333+
project = partial(pyproj.transform, pyproj.Proj(init="epsg:4326"), utmproj)
346334

347335
pshape = transform(project, polygon)
348336
pshape = pshape.buffer(buffer_km * 1000)
@@ -372,8 +360,8 @@ def filter_by_country(df, ccode, buffer_km=BUFFER_DISTANCE_KM):
372360

373361
df2 = pd.DataFrame(columns=df.columns)
374362
for idx, row in df.iterrows():
375-
lat = row['latitude']
376-
lon = row['longitude']
363+
lat = row["latitude"]
364+
lon = row["longitude"]
377365
point_inside = False
378366
for pshape, utmproj in pshapes:
379367
x, y = utmproj(lon, lat)

0 commit comments

Comments
 (0)