|
9 | 9 | import copy |
10 | 10 | import logging |
11 | 11 | import datetime as dt |
12 | | -import itertools |
13 | 12 | import warnings |
14 | 13 | import numpy as np |
15 | 14 | from scipy import sparse |
16 | | -from pathos.multiprocessing import ProcessingPool as Pool |
17 | 15 |
|
18 | 16 | from climada.hazard.tag import Tag as TagHazard |
19 | 17 | from climada.hazard.centroids.base import Centroids |
|
22 | 20 | import climada.util.plot as u_plot |
23 | 21 | import climada.util.checker as check |
24 | 22 | import climada.util.dates_times as u_dt |
| 23 | +from climada.util.config import CONFIG |
25 | 24 |
|
26 | 25 | LOGGER = logging.getLogger(__name__) |
27 | 26 |
|
@@ -237,13 +236,23 @@ def local_exceedance_inten(self, return_periods=(25, 50, 100, 250)): |
237 | 236 | """ |
238 | 237 | LOGGER.info('Computing exceedance intenstiy map for return periods: %s', |
239 | 238 | return_periods) |
240 | | - cen_pos = range(self.intensity.shape[1]) |
241 | | - inten_stats = np.zeros((len(return_periods), len(cen_pos))) |
242 | | - chunksize = min(len(cen_pos), 1000) |
243 | | - for cen_idx, inten_loc in enumerate(Pool().map(self._loc_return_inten,\ |
244 | | - itertools.repeat(np.array(return_periods), len(cen_pos)), cen_pos,\ |
245 | | - chunksize=chunksize)): |
246 | | - inten_stats[:, cen_idx] = inten_loc |
| 239 | + num_cen = self.intensity.shape[1] |
| 240 | + inten_stats = np.zeros((len(return_periods), num_cen)) |
| 241 | + cen_step = int(CONFIG['impact']['max_matrix_size']/self.intensity.shape[0]) |
| 242 | + if not cen_step: |
| 243 | + LOGGER.error('Increase max_matrix_size configuration parameter to'\ |
| 244 | + ' > %s', str(self.intensity.shape[0])) |
| 245 | + raise ValueError |
| 246 | + # separte in chunks |
| 247 | + chk = -1 |
| 248 | + for chk in range(int(num_cen/cen_step)): |
| 249 | + self._loc_return_inten(np.array(return_periods), \ |
| 250 | + self.intensity[:, chk*cen_step:(chk+1)*cen_step].todense(), \ |
| 251 | + inten_stats[:, chk*cen_step:(chk+1)*cen_step]) |
| 252 | + self._loc_return_inten(np.array(return_periods), \ |
| 253 | + self.intensity[:, (chk+1)*cen_step:].todense(), \ |
| 254 | + inten_stats[:, (chk+1)*cen_step:]) |
| 255 | + |
247 | 256 | return inten_stats |
248 | 257 |
|
249 | 258 | def plot_rp_intensity(self, return_periods=(25, 50, 100, 250), **kwargs): |
@@ -725,41 +734,61 @@ def _centr_plot(self, centr_id, mat_var, col_name): |
725 | 734 | graph.set_x_lim(range(len(array_val))) |
726 | 735 | return graph.get_elems() |
727 | 736 |
|
728 | | - def _loc_return_inten(self, return_periods, cen_pos): |
| 737 | + def _loc_return_inten(self, return_periods, inten, exc_inten): |
729 | 738 | """ Compute local exceedence intensity for given return period. |
730 | 739 |
|
731 | 740 | Parameters: |
732 | 741 | return_periods (np.array): return periods to consider |
733 | 742 | cen_pos (int): centroid position |
| 743 | +
|
734 | 744 | Returns: |
735 | 745 | np.array |
736 | 746 | """ |
737 | | - inten_pos = np.argwhere(self.intensity[:, cen_pos] > |
738 | | - self.intensity_thres)[:, 0] |
739 | | - if inten_pos.size == 0: |
740 | | - return np.zeros((return_periods.size, )) |
741 | | - inten_nz = np.asarray(self.intensity[inten_pos, cen_pos].todense()). \ |
742 | | - squeeze() |
743 | | - sort_pos = inten_nz.argsort()[::-1] |
744 | | - try: |
745 | | - inten_sort = inten_nz[sort_pos] |
746 | | - except IndexError as err: |
747 | | - if inten_nz.shape == () and inten_nz.size == 1: |
748 | | - inten_sort = np.array([inten_nz]) |
749 | | - else: |
750 | | - raise err |
751 | | - freq_sort = self.frequency[inten_pos[sort_pos]] |
752 | | - np.cumsum(freq_sort, out=freq_sort) |
| 747 | + # sorted intensity |
| 748 | + sort_pos = np.argsort(inten, axis=0)[::-1, :] |
| 749 | + columns = np.ones(inten.shape, int) |
| 750 | + columns *= np.arange(columns.shape[1]) |
| 751 | + inten_sort = inten[sort_pos, columns] |
| 752 | + # cummulative frequency at sorted intensity |
| 753 | + freq_sort = self.frequency[sort_pos] |
| 754 | + np.cumsum(freq_sort, axis=0, out=freq_sort) |
| 755 | + |
| 756 | + for cen_idx in range(inten.shape[1]): |
| 757 | + exc_inten[:, cen_idx] = self._cen_return_inten( |
| 758 | + inten_sort[:, cen_idx], freq_sort[:, cen_idx], |
| 759 | + self.intensity_thres, return_periods) |
| 760 | + |
| 761 | + @staticmethod |
| 762 | + def _cen_return_inten(inten, freq, inten_th, return_periods): |
| 763 | + """From ordered intensity and cummulative frequency at centroid, get |
| 764 | + exceedance intensity at input return periods. |
| 765 | +
|
| 766 | + Parameters: |
| 767 | + inten (np.array): sorted intensity at centroid |
| 768 | + freq (np.array): cummulative frequency at centroid |
| 769 | + inten_th (float): intensity threshold |
| 770 | + return_periods (np.array): return periods |
| 771 | +
|
| 772 | + Returns: |
| 773 | + np.array |
| 774 | + """ |
| 775 | + inten_th = np.asarray(inten > inten_th).squeeze() |
| 776 | + inten_cen = inten[inten_th] |
| 777 | + freq_cen = freq[inten_th] |
| 778 | + if not inten_cen.size: |
| 779 | + return np.zeros((return_periods.size,)) |
753 | 780 | try: |
754 | 781 | with warnings.catch_warnings(): |
755 | 782 | warnings.simplefilter("ignore") |
756 | | - pol_coef = np.polyfit(np.log(freq_sort), inten_sort, deg=1) |
| 783 | + pol_coef = np.polyfit(np.log(freq_cen), inten_cen, deg=1) |
757 | 784 | except ValueError: |
758 | | - pol_coef = np.polyfit(np.log(freq_sort), inten_sort, deg=0) |
| 785 | + pol_coef = np.polyfit(np.log(freq_cen), inten_cen, deg=0) |
759 | 786 | inten_fit = np.polyval(pol_coef, np.log(1/return_periods)) |
760 | | - wrong_inten = np.logical_and(return_periods > np.max(1/freq_sort), \ |
761 | | - np.isnan(inten_fit)) |
762 | | - return inten_fit[np.logical_not(wrong_inten)] |
| 787 | + wrong_inten = np.logical_and(return_periods > np.max(1/freq_cen), \ |
| 788 | + np.isnan(inten_fit)) |
| 789 | + inten_fit[wrong_inten] = 0. |
| 790 | + |
| 791 | + return inten_fit |
763 | 792 |
|
764 | 793 | def __str__(self): |
765 | 794 | return self.tag.__str__() |
|
0 commit comments