def checkSequence(self, cclass, class_frame, proj): classrows = class_frame[class_frame['class'] == cclass] sqstats = self.getSequenceStats(classrows, proj) cname = sqstats['name'] clat = sqstats['center_lat'] clon = sqstats['center_lon'] radius = sqstats['radius'] seq_query = 'SELECT id, name, center_lat, center_lon, radius FROM sequence WHERE sequence_ended = 0' self._cursor.execute(seq_query) seq_rows = self._cursor.fetchall() if not len(seq_rows): return None for row in seq_rows: sid = row['id'] name = row['name'] center_lat = row['center_lat'] center_lon = row['center_lon'] sradius = row['radius'] # what is the distance in km from one center to another? dist = geodetic_distance(clat, clon, center_lat, center_lon) if name[0:7] == cname[0:7] and name.startswith('West'): foo = 1 cmp_dist = max(radius + sradius, EQDIST2) if dist < cmp_dist: return sid return None
def getSequenceStats(self, class_frame, proj): start_time = class_frame['time'].min() end_time = class_frame['time'].max() class_lat = class_frame['latitude'].tolist() class_lon = class_frame['longitude'].tolist() x, y = proj(class_lon, class_lat) x = np.array(x) y = np.array(y) cx = np.mean(x) cy = np.mean(y) clon, clat = proj(cx, cy, inverse=True) near_cities = self._cities.limitByRadius( clat, clon, CITY_SEARCH_RADIUS).getDataFrame() citylat = near_cities['lat'] citylon = near_cities['lon'] dist = geodetic_distance(clon, clat, citylon, citylat) near_cities['distance'] = dist near_cities = near_cities.sort_values('distance') # get the distance from the center of mass to all the points dxsq = np.power((x - cx), 2) dysq = np.power((y - cy), 2) cdist = np.sqrt(dxsq + dysq) radius = cdist.max() / 1000 xmin = x.min() xmax = x.max() ymin = y.min() ymax = y.max() ulx, uly = proj(xmin, ymax, inverse=True) lrx, lry = proj(xmax, ymin, inverse=True) # Earthquake name should NearestCity_YYYY, followed by _1, _2 # when there are multiple sequences near that city in that year try: nearest_city = near_cities.iloc[0] name = nearest_city['name'] + start_time.strftime('%Y%m%d%H%M%S') name = re.sub('\s+', '_', name) except IndexError: name = 'No_Nearest_City' + start_time.strftime('%Y%m%d%H%M%S') nearest_city = {'name': 'No_Nearest_City', 'distance': np.nan} sequence = { 'name': name, 'start_time': start_time, 'end_time': end_time, 'n_earthquakes': len(class_frame), 'center_lat': clat, 'center_lon': clon, 'nearest_city': nearest_city['name'], 'dist_nearest_city': nearest_city['distance'], 'radius': radius, 'projstr': proj.srs, 'xmin': ulx, 'xmax': lrx, 'ymin': lry, 'ymax': uly } return sequence
def selectByRadius(self, clat, clon, radius): """Select events by restricting to those within a search radius around a set of coordinates.""" lons = self._dataframe["Lon"] lats = self._dataframe["Lat"] distances = geodetic_distance(clon, clat, lons, lats) iclose = pd.Series(distances < radius) newdf = self._dataframe[iclose] d1 = distances[distances < radius] newdf = newdf.assign(Distance=d1) return ExpoCat(newdf)
def getSequenceStats(self, class_frame, proj): start_time = class_frame['time'].min() end_time = class_frame['time'].max() class_lat = class_frame['latitude'].tolist() class_lon = class_frame['longitude'].tolist() xmin = np.min(class_lon) xmax = np.max(class_lon) ymin = np.min(class_lat) ymax = np.max(class_lat) clon = (xmin + xmax) / 2 clat = (ymin + ymax) / 2 cradius = self._config['CITY_SEARCH_RADIUS'] near_cities = self._cities.limitByRadius( clat, clon, cradius).getDataFrame() citylat = near_cities['lat'] citylon = near_cities['lon'] dist = geodetic_distance(clon, clat, citylon, citylat) near_cities['distance'] = dist near_cities = near_cities.sort_values('distance') dlon = (xmax - xmin) / 2 * 111 * np.cos(np.radians(clat)) dlat = (ymax - ymin) / 2 * 111 radius = np.mean([dlon, dlat]) if radius > 200: foo = 1 # Earthquake name should NearestCity_YYYY, followed by _1, _2 # when there are multiple sequences near that city in that year try: nearest_city = near_cities.iloc[0] name = nearest_city['name'] + start_time.strftime('%Y%m%d%H%M%S') name = re.sub('\s+', '_', name) except IndexError: name = 'No_Nearest_City' + start_time.strftime('%Y%m%d%H%M%S') nearest_city = {'name': 'No_Nearest_City', 'distance': np.nan} sequence = {'name': name, 'start_time': start_time, 'end_time': end_time, 'n_earthquakes': len(class_frame), 'center_lat': clat, 'center_lon': clon, 'nearest_city': nearest_city['name'], 'dist_nearest_city': nearest_city['distance'], 'radius': radius, 'projstr': proj.srs, 'xmin': xmin, 'xmax': xmax, 'ymin': ymin, 'ymax': ymax} return sequence
def limitByRadius(self,lat,lon,radius): """Search for cities within a radius (km) around a central point. :param lat: Central latitude coordinate (dd). :param lon: Central longitude coordinate (dd). :param radius: Radius (km) around which cities will be searched. :returns: New Cities instance containing smaller cities data set. """ #TODO - figure out what to do with a meridian crossing? newdf = self._dataframe.copy() dist = geodetic_distance(lon,lat,self._dataframe['lon'],self._dataframe['lat']) newdf['dist'] = dist newdf = newdf[newdf['dist'] <= radius] del newdf['dist'] return type(self)(newdf)
def checkSequence(self, sqstats): clat = sqstats['center_lat'] clon = sqstats['center_lon'] radius = sqstats['radius'] seq_query = 'SELECT id, name, center_lat, center_lon, radius FROM sequence WHERE sequence_ended = 0' self._cursor.execute(seq_query) seq_rows = self._cursor.fetchall() if not len(seq_rows): return None for row in seq_rows: sid = row['id'] center_lat = row['center_lat'] center_lon = row['center_lon'] sradius = row['radius'] # what is the distance in km from one center to another? dist = geodetic_distance(clat, clon, center_lat, center_lon) # cmp_dist=max(radius + sradius, self._config['EQDIST2']) cmp_dist = radius + sradius if dist < cmp_dist: return sid return None
def get_quake_desc(event, lat, lon, isMainEvent): ndeaths = event["TotalDeaths"] # summarize the exposure values exposures = np.array([ event["MMI1"], event["MMI2"], event["MMI3"], event["MMI4"], event["MMI5"], event["MMI6"], event["MMI7"], event["MMI8"], event["MMI9+"], ]) exposures = np.array([round_to_nearest(exp, 1000) for exp in exposures]) # get the highest two exposures greater than zero iexp = np.where(exposures > 0)[0][::-1] romans = [ "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX or greater" ] if len(iexp) >= 2: exposures = [exposures[iexp[1]], exposures[iexp[0]]] ilevels = [romans[iexp[1]], romans[iexp[0]]] expfmt = ", with estimated population exposures of %s at intensity" expfmt = expfmt + " %s and %s at intensity %s" exptxt = expfmt % ( commify(int(exposures[0])), ilevels[0], commify(int(exposures[1])), ilevels[1], ) else: exptxt = "" # create string describing this most impactful event dfmt = "A magnitude %.1f earthquake %i km %s of this event struck %s on %s (UTC)%s" mag = event["Magnitude"] etime = pd.Timestamp(event["Time"]) etime = etime.strftime("%B %d, %Y") etime = re.sub(" 0", " ", etime) country = Country() if pd.isnull(event["Name"]): # hack for persistent error in expocat if event["CountryCode"] == "UM" and event["Lat"] > 40: cdict = country.getCountry("US") else: cdict = country.getCountry(event["CountryCode"]) if cdict: cname = cdict["Name"] else: cname = "in the open ocean" else: cname = event["Name"].replace('"', "") cdist = round(geodetic_distance(event["Lat"], event["Lon"], lat, lon)) cdir = get_compass_dir(lat, lon, event["Lat"], event["Lon"], format="long").lower() if ndeaths and str(ndeaths) != "nan": dfmt = dfmt + ", resulting in a reported %s %s." if ndeaths > 1: dstr = "fatalities" else: dstr = "fatality" ndeathstr = commify(int(ndeaths)) eqdesc = dfmt % (mag, cdist, cdir, cname, etime, exptxt, ndeathstr, dstr) else: dfmt = dfmt + ", with no reported fatalities." eqdesc = dfmt % (mag, cdist, cdir, cname, etime, exptxt) return eqdesc