def test_get_roi(self): roi = CraterRoi(self.cds, 0, 0, 50) arr = roi._get_roi() self.assertIsNotNone(arr) roi180 = CraterRoi(self.cds, 0, 180, 50) arr180 = roi180.roi self.assertIsNotNone(arr180)
def test_get_extent(self): """Test _get_extent""" roi = CraterRoi(self.cds, 0, 0, 16) actual = roi._get_extent() expected = (-0.5278, 0.5278, -0.5278, 0.5278) np.testing.assert_almost_equal(actual, expected, 4) roi = CraterRoi(self.cds, 20, 20, 16) actual = roi.extent expected = (19.4384, 20.5616, 19.4722, 20.5278) np.testing.assert_almost_equal(actual, expected, 4)
def ejecta_stats(df, cds, ejrad=2, stats=None, plot=False, vmin=float('-inf'), vmax=float('inf'), strict=False): """Compute the specified stats from acestats.py on a circular ejecta ROI extending ejsize crater radii from the crater center. Return results as DataFrame with stats appended as extra columns. Parameters ---------- df : pandas.DataFrame object Contains the crater locations and sizes to locate ROIs in aceDS. Also form the basis of the returned DataFrame cds : CraterpyDataset object CraterpyDataset of image data used to compute stats. ejrad : int, float The radius of ejecta blanket measured in crater radii from the crater center to the ejecta extent. stats : Array-like of str Indicates the stat names to compute. Stat functions must be defined in acestats.py. Default: all stats in acestats.py. plot : bool Plot the ejecta ROI. vmin : int, float The minimum valid image pixel value. Filter all values lower. vmax : int, float The maximum valid image pixel value. Filter all values higher. strict : bool How strict the (vmin, vmax) range is. If true, exclude values <= vmin and values >= vmax, if they are specified. Returns ------- DataFrame Copy of df with stats appended as new columns. """ # If stats and index not provided, assume use all stats and all rows in cdf if stats is None: stats = _list_quickstats() # Initialize return Dataframe with stats as individual columns ret_df = df.copy() for stat in stats: ret_df.loc[:, stat] = ret_df.index latcol, loncol, radcol = ch.get_crater_cols(df) # Main computation loop for i in df.index: # Get lat, lon, rad and compute roi for current crater lat, lon, rad = df.loc[i, latcol], df.loc[i, loncol], df.loc[i, radcol] croi = CraterRoi(cds, lat, lon, rad, ejrad) mask = masking.crater_ring_mask(croi, rad, rad*ejrad) croi.filter(vmin, vmax, strict) croi.mask(~mask) data_arr = croi.roi[~np.isnan(croi.roi)] # Collapses to 1D for stat, function in _get_quickstats_functions(stats): ret_df.loc[i, stat] = function(data_arr) if plot: # plot filtered and masked roi croi.plot() return ret_df
class TestCraterRoi(unittest.TestCase): """Test CraterpyDataset object""" def setUp(self): import craterpy self.data_path = p.join(craterpy.__path__[0], 'data') self.moon_tif = p.join(self.data_path, 'moon.tif') self.cds = CraterpyDataset(self.moon_tif, radius=1737) self.roi = CraterRoi(self.cds, 0, 0, 100) def test_roi_import(self): """Test import""" roi = CraterRoi(self.cds, 0, 0, 100) self.assertIsNotNone(roi) def test_get_extent(self): """Test _get_extent""" roi = CraterRoi(self.cds, 0, 0, 16) actual = roi._get_extent() expected = (-0.5278, 0.5278, -0.5278, 0.5278) np.testing.assert_almost_equal(actual, expected, 4) roi = CraterRoi(self.cds, 20, 20, 16) actual = roi._get_extent() expected = (19.4384, 20.5616, 19.4722, 20.5278) np.testing.assert_almost_equal(actual, expected, 4) def test_get_roi(self): roi = CraterRoi(self.cds, 0, 0, 50) arr = roi.get_roi() self.assertIsNotNone(arr) roi180 = CraterRoi(self.cds, 0, 180, 50) arr180 = roi.get_roi() self.assertIsNotNone(arr180) def test_filter(self): roi = self.roi roi.filter(0, 100) self.assertTrue(roi.roi.max() <= 100) roi.filter(0, 50, strict=True) self.assertTrue(roi.roi.max() < 50) # TODO: fix this test # def test_mask(self): # shape, rad = self.roi.roi.shape, self.roi.rad # mask = circle_mask(shape, rad) # masked_roi = self.roi.mask(mask) # self.assertTrue(np.isnan(self.roi.roi[*(shape/2)])) def test_plot(self): self.assertIsNotNone(self.roi.plot())
def compute_stats(df, cds, stats=[], plot=False, vmin=float('-inf'), vmax=float('inf'), strict=False, maskfunc=None, mask_out=False, ejrad=None): """Computes stats on craters in df with image data from cds. """ # If stats and index not provided, assume use all stats and all rows in cdf if not stats: stats = _list_quickstats() # Initialize return Dataframe with stats as individual columns ret_df = df.copy() for stat in stats: ret_df.loc[:, stat] = ret_df.index latcol, loncol, radcol = ch.get_crater_cols(df) # Main computation loop for i in df.index: # Get lat, lon, rad and compute roi for current crater lat, lon, rad = df.loc[i, latcol], df.loc[i, loncol], df.loc[i, radcol] try: print(lat, lon, rad) croi = CraterRoi(cds, lat, lon, rad, ejrad) croi.filter(vmin, vmax, strict) if maskfunc: if maskfunc == "crater": mask = masking.crater_floor_mask(croi) elif maskfunc == "ejecta": mask = masking.crater_ring_mask(croi, rad, rad * ejrad) croi.mask(mask, mask_out) data_arr = croi.roi[~np.isnan(croi.roi)] # Collapses to 1D for stat, function in _get_quickstats_functions(stats): ret_df.loc[i, stat] = function(data_arr) except Exception as e: print(e) print(lat, lon, rad) break if plot: # plot filtered and masked roi croi.plot() return ret_df
def ejecta_profile_stats(df, cds, ejrad=2, rspacing=0.25, stats=None, plot_roi=False, vmin=None, vmax=None, strict=False, plot_stats=False, savepath=None, timer=False, dt=60): """Compute stat profiles across ejecta blankets by computing stats in a series of concentric rings beginning at the crater rim and extending to ejrad crater radii from the crater centre. Each ring is rspacing thick and the crater floor is excluded. Output is a dictionary of cdf.index values to pandas.DataFrame of stats containing the computed stats as columns and ring radius as rows. Parameters ---------- Returns ------- stat_df : dict of (index: pandas.DataFrame) Dictionary of stats with cdf index as keys and pandas.DataFrame of statistics as values (see example). Example ------- >>> compute_ejecta_profile_stats(my_df, my_cds, 2, 0.25, stats=['mean', 'median','maximum'],savepath='/tmp/') /tmp/index1_ejecta_stats.csv radius,mean,median,maximum 1, 55, 45, 70 1.25, 50, 40, 65 1.5, 35, 35, 45 1.75, 30, 33, 42 """ if timer: from timeit import default_timer as timer Tstart, Tnow = timer(), timer() count = 1 # count craters if savepath: import os.path as p savename = p.join(savepath, '{}_ejpstats.csv') if stats is None: stats = _list_quickstats() stat_dict = {} latcol, loncol, radcol = ch.get_crater_cols(df) for i in df.index: # Main DataFrame loop lat, lon, rad = df.loc[i, latcol], df.loc[i, loncol], df.loc[i, radcol] try: croi = CraterRoi(cds, lat, lon, rad, ejrad) ring_array = np.arange(1, ejrad+rspacing, rspacing) # inner radius ring_darray = ring_array*rad # convert inner radius to km stat_df = pd.DataFrame(index=ring_array[:-1], columns=stats) for i in range(len(ring_array)-1): # Loop through radii rad_inner = ring_darray[i] rad_outer = ring_darray[i+1] mask = masking.crater_ring_mask(cds, croi, lat, lon, rad_inner, rad_outer) ejecta_roi = croi.mask(~mask).filter(vmin, vmax, strict) ejecta_roi = ejecta_roi[~np.isnan(ejecta_roi)] for stat, function in _get_quickstats_functions(stats): stat_df.loc[ring_array[i], stat] = function(ejecta_roi) if plot_roi: ejecta_roi.plot() stat_dict[i] = stat_df if plot_stats: plotting.plot_ejecta_profile_stats(stat_df) if savepath: stat_df.to_csv(savename.format(i)) except ImportError as e: # Catches and prints out of bounds exceptions print(e, ". Skipping....") if timer: # Print a status update approx every dt seconds if (timer() - Tnow > dt) or (count == len(df)): update = 'Finished crater {} out of {}'.format(count, len(df)) elapsed = timer()-Tstart update += '\n Time elapsed: \ {}h:{}m:{}s'.format(int(elapsed//3600), int((elapsed % 3600)//60), round((elapsed % 3600) % 60, 2)) print(update) Tnow = timer() count += 1 return stat_dict
def test_roi_import(self): """Test import""" roi = CraterRoi(self.cds, 0, 0, 100) self.assertIsNotNone(roi)
def setUp(self): import craterpy self.data_path = p.join(craterpy.__path__[0], 'data') self.moon_tif = p.join(self.data_path, 'moon.tif') self.cds = CraterpyDataset(self.moon_tif, radius=1737) self.roi = CraterRoi(self.cds, 0, 0, 100)