def get_albedo(self, grid): """ Retrieve the Rayleigh single scattering albedo. Parameters ---------- grid: shdom.Grid The new grid to which the data will be resampled Returns ------- albedo: list of shdom.GridData A list of GridData objects containing the single scattering albedo [0,1] on a grid. The length of the list is the number of wavelengths. """ if self.num_wavelengths == 1: albedo = shdom.GridData(grid, data=np.full(shape=grid.shape, fill_value=1.0, dtype=np.float32)) else: albedo = [ shdom.GridData(grid, data=np.full(shape=grid.shape, fill_value=1.0, dtype=np.float32)) for wavelength in self._wavelength ] return albedo
def get_extinction(self, grid): """ Retrieve the Rayleigh extinction profile (as a function of altitude). Parameters ---------- grid: shdom.Grid The new grid to which the data will be resampled Returns ------- extinction_profile: list of shdom.GridData A list of GridData objects containing the extinction on a 1D grid. The length of the list is the number of wavelengths. """ if self.num_wavelengths == 1: ext_profile = core.rayleigh_extinct( nzt=grid.nz, zlevels=grid.z, temp=self.temperature_profile.data, raysfcpres=self.surface_pressure, raylcoef=self._raylcoef) extinction = shdom.GridData(grid, ext_profile) else: ext_profile = [ core.rayleigh_extinct(nzt=grid.nz, zlevels=grid.z, temp=self.temperature_profile.data, raysfcpres=self.surface_pressure, raylcoef=raylcoef) for raylcoef in self._raylcoef ] extinction = [shdom.GridData(grid, ext) for ext in ext_profile] return extinction
def load_from_csv(self, path, veff=0.1): """ A utility function to load a microphysical medium. Parameters ---------- path: str Path to file. veff: float If effective variance is not specified in the csv file as a 6th column, this value is used as a homogeneous value. Default value is veff=0.1 Notes ----- CSV format should be as follows: # comment line (description) nx ny nz dz dy dz z_levels[0] z_levels[1] ... z_levels[nz-1] ix iy iz lwc[ix, iy, iz] reff[ix, iy, iz] veff[ix, iy, iz](optional) . . . ix iy iz lwc[ix, iy, iz] reff[ix, iy, iz] veff[ix, iy, iz](optional) """ grid = self.load_grid(path) data = np.genfromtxt(path, skip_header=3) grid_index = data[:, :3].astype(int) lwc = data[:, 3] reff = data[:, 4] if data.shape[1] == 6: veff = data[:, 5] else: veff = veff * np.ones_like(reff) lwc_data = np.full(shape=(grid.nx, grid.ny, grid.nz), fill_value=np.nan) reff_data = np.full(shape=(grid.nx, grid.ny, grid.nz), fill_value=np.nan) veff_data = np.full(shape=(grid.nx, grid.ny, grid.nz), fill_value=np.nan) lwc_data[grid_index[:, 0], grid_index[:, 1], grid_index[:, 2]] = lwc reff_data[grid_index[:, 0], grid_index[:, 1], grid_index[:, 2]] = reff veff_data[grid_index[:, 0], grid_index[:, 1], grid_index[:, 2]] = veff self.set_microphysics(lwc=shdom.GridData(grid, lwc_data).squeeze_dims(), reff=shdom.GridData(grid, reff_data).squeeze_dims(), veff=shdom.GridData(grid, veff_data).squeeze_dims())
def get_phase(self, grid): """ Retrieve the Rayleigh phase function. Parameters ---------- grid: shdom.Grid The new grid to which the data will be resampled Returns ------- phase: list of shdom.GridPhase A list of GridPhase objects containing the phase function on a grid. The length of the list is the number of wavelengths. """ phase = [] for wavelength in self._wavelength: index = shdom.GridData(grid, data=np.ones(shape=grid.shape, dtype=np.int32)) table, table_type = core.rayleigh_phase_function( wavelen=wavelength) table = LegendreTable(table.astype(np.float32), table_type.decode()) phase.append(GridPhase(table, index)) if self.num_wavelengths == 1: phase = phase[0] return phase
def compute_extinction(self, veff=0.1): # extrarc grid data: bounding_box = shdom.BoundingBox(self.bounding_box_xmin, self.bounding_box_ymin, self.bounding_box_xmin, self.bounding_box_xmax, self.bounding_box_ymax, self.bounding_box_zmax) grid = shdom.Grid(bounding_box=bounding_box, nx=self.nx, ny=self.ny, nz=self.nz) # self.extinction = np.zeros([self.nx,self.ny,self.nz]) veff = veff * np.ones_like(self.re) lwc = shdom.GridData(grid, self.lwc).squeeze_dims() reff = shdom.GridData(grid, self.re).squeeze_dims() veff = shdom.GridData(grid, veff).squeeze_dims() extinction = self.mie.get_extinction(lwc, reff, veff) self.extinction = extinction.data
def get_mask(self, threshold): """ Get a mask based on the optical extinction. Parameters ---------- threshold: float A threshold which above this value it is considered a populated voxel. Returns ------- mask: shdom.GridData object A boolean mask with True for dense voxels and False for optically thin regions. """ data = self.extinction.data > threshold return shdom.GridData(self.grid, data)
def get_mask(self, threshold): """ Get a mask based on the liquid water content. Parameters ---------- threshold: float A threshold which above this value it is considered a populated voxel. Returns ------- mask: shdom.GridData object A boolean mask with True for dense voxels and False for thin voxels. """ data = self.lwc.data > threshold return shdom.GridData(self.grid, data)
def get_albedo(self, reff, veff): """ Interpolate the single scattering albedo over a grid. Parameters ---------- reff: shdom.GridData A shdom.GridData object containing the effective radii (micron) on a 3D grid. veff: shdom.GridData A GridData object containing effective variances on a 3D grid. Returns ------- albedo: shdom.GridData object A shdom.GridData object containing the single scattering albedo unitless in range [0, 1] on a 3D grid """ grid = veff.grid + reff.grid data = self._ssalb_interpolator( (reff.resample(grid).data, veff.resample(grid).data)) albedo = shdom.GridData(grid, data) return albedo
def get_extinction(self, lwc, reff, veff): """ Retrieve the extinction coefficient over a grid. Parameters ---------- lwc: shdom.GridData A GridData object containing liquid water content (g/m^3) on a grid. reff: shdom.GridData A GridData object containing effective radii (micron) on a grid. veff: shdom.GridData A GridData object containing effective variances on a grid. Returns ------- extinction: shdom.GridData object A GridData object containing the extinction (1/km) on a grid """ grid = lwc.grid + veff.grid + reff.grid data = self._ext_interpolator( (reff.resample(grid).data, veff.resample(grid).data)) extinction = lwc.resample(grid) * shdom.GridData(grid, data) return extinction
def get_phase(self, reff, veff, squeeze_table=True): """ Interpolate the phase function over a grid. Parameters ---------- reff: shdom.GridData A shdom.GridData object containing the effective radii (micron) on a 3D grid. veff: shdom.GridData A GridData object containing effective variances on a 3D grid. squeeze_table: boolean True: return compact table containing the range of provided reff, veff. False will return the current table. Returns ------- phase: GridPhase A GridPhase object containing the phase function legendre coeffiecients as a table. """ grid = veff.grid + reff.grid index = self._legen_index_interpolator( (reff.resample(grid).data, veff.resample(grid).data)).astype(np.int32) nre, nve = self.size_distribution.nretab, self.size_distribution.nvetab # Clip table to make it compact if squeeze_table: max_re_idx = min( nre - 1, find_nearest(self.size_distribution.reff, reff.data.max())) max_ve_idx = min( nve - 1, find_nearest(self.size_distribution.veff, veff.data.max())) min_re_idx = max( 0, find_nearest(self.size_distribution.reff, reff.data[reff.data > 0.0].min())) min_ve_idx = max( 0, find_nearest(self.size_distribution.veff, veff.data[veff.data > 0.0].min())) legcoef = self.legcoef_2d[..., min_re_idx:max_re_idx + 1, min_ve_idx:max_ve_idx + 1] nre, nve = legcoef.shape[-2:] legcoef = legcoef.reshape(self.legcoef.shape[:-1] + (-1, ), order='F') index[..., 0] -= min_re_idx index[..., 1] -= min_ve_idx else: legcoef = self.legcoef legen_table = shdom.LegendreTable(legcoef, self.table_type) index = np.ravel_multi_index(np.rollaxis(index, axis=-1), dims=(nre, nve), order='F', mode='clip') + 1 legen_index = shdom.GridData(grid, index.astype(np.int32)) phase = GridPhase(legen_table, legen_index) return phase