def test_decimal_year(self): '''Tests the function utils.decimal_year''' self.year = np.array([1990., 1995., 2000.]) self.month = np.array([1., 6., 12.]) self.day = np.array([1., 30., 31.]) self.assertTrue(np.allclose( utils.decimal_year(self.year, self.month, self.day), np.array([1990., 1995.49315068, 2000.99726027])))
def test_decimal_year(self): '''Tests the function utils.decimal_year''' self.year = np.array([1990., 1995., 2000.]) self.month = np.array([1., 6., 12.]) self.day = np.array([1., 30., 31.]) self.assertTrue( np.allclose(utils.decimal_year(self.year, self.month, self.day), np.array([1990., 1995.49315068, 2000.99726027])))
def decluster(self, catalogue, config): """ catalogue_matrix, window_opt=TDW_GARDNERKNOPOFF, time_window=60.): :param catalogue: a catalogue object :type catalogue: Instance of the hmtk.seismicity.catalogue.Catalogue() class :keyword window_opt: method used in calculating distance and time windows :type window_opt: string :keyword time_window: Length (in days) of moving time window :type time_window: positive float :returns: **vcl vector** indicating cluster number, **flagvector** indicating which earthquakes belong to a cluster :rtype: numpy.ndarray """ # Convert time window from days to decimal years time_window = config['time_window'] / 365. # Pre-processing steps are the same as for Gardner & Knopoff # Get relevent parameters mag = catalogue.data['magnitude'] neq = np.shape(mag)[0] # Number of earthquakes # Get decimal year (needed for time windows) year_dec = decimal_year(catalogue.data['year'], catalogue.data['month'], catalogue.data['day']) # Get space windows corresponding to each event sw_space, _ = ( config['time_distance_window'].calc(catalogue.data['magnitude'])) # Pre-allocate cluster index vectors vcl = np.zeros(neq, dtype=int) flagvector = np.zeros(neq, dtype=int) # Rank magnitudes into descending order id0 = np.flipud(np.argsort(mag, kind='heapsort')) iloc = 0 clust_index = 0 for imarker in id0: # Earthquake not allocated to cluster - perform calculation if vcl[imarker] == 0: # Perform distance calculation mdist = haversine( catalogue.data['longitude'], catalogue.data['latitude'], catalogue.data['longitude'][imarker], catalogue.data['latitude'][imarker]).flatten() # Select earthquakes inside distance window, later than # mainshock and not already assigned to a cluster vsel1 = np.where( np.logical_and(vcl==0, np.logical_and(mdist <= sw_space[imarker], year_dec > year_dec[imarker])))[0] has_aftershocks = False if len(vsel1) > 0: # Earthquakes after event inside distance window temp_vsel1, has_aftershocks = self._find_aftershocks( vsel1, year_dec, time_window, imarker, neq) if has_aftershocks: flagvector[temp_vsel1] = 1 vcl[temp_vsel1] = clust_index + 1 # Select earthquakes inside distance window, earlier than # mainshock and not already assigned to a cluster has_foreshocks = False vsel2 = np.where( np.logical_and(vcl == 0, np.logical_and(mdist <= sw_space[imarker], year_dec < year_dec[imarker])))[0] if len(vsel2) > 0: # Earthquakes before event inside distance window temp_vsel2, has_foreshocks = self._find_foreshocks( vsel2, year_dec, time_window, imarker, neq) if has_foreshocks: flagvector[temp_vsel2] = -1 vcl[temp_vsel2] = clust_index + 1 if has_aftershocks or has_foreshocks: # Assign mainshock to cluster vcl[imarker] = clust_index + 1 clust_index += 1 iloc += 1 return vcl, flagvector
def decluster(self, catalogue, config): """ The configuration of this declustering algorithm requires two objects: - A time-distance window object (key is 'time_distance_window') - A value in the interval [0,1] expressing the fraction of the time window used for aftershocks (key is 'fs_time_prop') :param catalogue: Catalogue of earthquakes :type catalogue: Dictionary :param config: Configuration parameters :type config: Dictionary :returns: **vcl vector** indicating cluster number, **flagvector** indicating which eq events belong to a cluster :rtype: numpy.ndarray """ # Get relevant parameters neq = len(catalogue.data['magnitude']) # Number of earthquakes # Get decimal year (needed for time windows) year_dec = decimal_year(catalogue.data['year'], catalogue.data['month'], catalogue.data['day']) # Get space and time windows corresponding to each event sw_space, sw_time = (config['time_distance_window'].calc( catalogue.data['magnitude'])) # Initial Position Identifier eqid = np.arange(0, neq, 1) # Pre-allocate cluster index vectors vcl = np.zeros(neq, dtype=int) # Sort magnitudes into descending order id0 = np.flipud( np.argsort(catalogue.data['magnitude'], kind='heapsort')) longitude = catalogue.data['longitude'][id0] latitude = catalogue.data['latitude'][id0] sw_space = sw_space[id0] sw_time = sw_time[id0] year_dec = year_dec[id0] eqid = eqid[id0] flagvector = np.zeros(neq, dtype=int) # Begin cluster identification clust_index = 0 for i in range(0, neq - 1): if vcl[i] == 0: # Find Events inside both fore- and aftershock time windows dt = year_dec - year_dec[i] vsel = np.logical_and( vcl == 0, np.logical_and( dt >= (-sw_time[i] * config['fs_time_prop']), dt <= sw_time[i])) # Of those events inside time window, # find those inside distance window vsel1 = haversine(longitude[vsel], latitude[vsel], longitude[i], latitude[i]) <= sw_space[i] vsel[vsel] = vsel1 temp_vsel = np.copy(vsel) temp_vsel[i] = False if any(temp_vsel): # Allocate a cluster number vcl[vsel] = clust_index + 1 flagvector[vsel] = 1 # For those events in the cluster before the main event, # flagvector is equal to -1 temp_vsel[dt >= 0.0] = False flagvector[temp_vsel] = -1 flagvector[i] = 0 clust_index += 1 # Re-sort the catalog_matrix into original order id1 = np.argsort(eqid, kind='heapsort') eqid = eqid[id1] vcl = vcl[id1] flagvector = flagvector[id1] return vcl, flagvector
def decluster(self, catalogue, config): """ The configuration of this declustering algorithm requires two objects: - A time-distance window object (key is 'time_distance_window') - A value in the interval [0,1] expressing the fraction of the time window used for aftershocks (key is 'fs_time_prop') :param catalogue: Catalogue of earthquakes :type catalogue: Dictionary :param config: Configuration parameters :type config: Dictionary :returns: **vcl vector** indicating cluster number, **flagvector** indicating which eq events belong to a cluster :rtype: numpy.ndarray """ # Check declustering configuration self._check_config(config) # Get relevant parameters neq = len(catalogue.data['magnitude']) # Number of earthquakes # Get decimal year (needed for time windows) year_dec = decimal_year( catalogue.data['year'], catalogue.data['month'], catalogue.data['day']) # Get space and time windows corresponding to each event sw_space, sw_time = ( config['time_distance_window'].calc(catalogue.data['magnitude'])) # Initial Position Identifier eqid = np.arange(0, neq, 1) # Pre-allocate cluster index vectors vcl = np.zeros(neq, dtype=int) # Sort magnitudes into descending order id0 = np.flipud(np.argsort(catalogue.data['magnitude'], kind='heapsort')) longitude = catalogue.data['longitude'][id0] latitude = catalogue.data['latitude'][id0] sw_space = sw_space[id0] sw_time = sw_time[id0] year_dec = year_dec[id0] eqid = eqid[id0] flagvector = np.zeros(neq, dtype=int) # Begin cluster identification clust_index = 0 for i in range(0, neq - 1): if vcl[i] == 0: # Find Events inside both fore- and aftershock time windows dt = year_dec - year_dec[i] vsel = np.logical_and( vcl == 0, np.logical_and( dt >= (-sw_time[i] * config['fs_time_prop']), dt <= sw_time[i])) # Of those events inside time window, # find those inside distance window vsel1 = haversine(longitude[vsel], latitude[vsel], longitude[i], latitude[i]) <= sw_space[i] vsel[vsel] = vsel1 temp_vsel = np.copy(vsel) temp_vsel[i] = False if any(temp_vsel): # Allocate a cluster number vcl[vsel] = clust_index + 1 flagvector[vsel] = 1 # For those events in the cluster before the main event, # flagvector is equal to -1 temp_vsel[dt >= 0.0] = False flagvector[temp_vsel] = -1 flagvector[i] = 0 clust_index += 1 # Re-sort the catalog_matrix into original order id1 = np.argsort(eqid, kind='heapsort') eqid = eqid[id1] vcl = vcl[id1] flagvector = flagvector[id1] return vcl, flagvector