def split(self, n_parts): """ Split the measurements and projection. Parameters ---------- n_parts: int The number of parts to split the measurements to Returns ------- measurements: list A list of measurements each with n_parts Notes ----- An even split doesnt always exist, in which case some parts will have slightly more pixels. """ projections = self.camera.projection.split(n_parts) pixels = np.array_split(self.pixels, n_parts) measurements = [ shdom.Measurements(camera=shdom.Camera(self.camera.sensor, projection), pixels=pixel) for projection, pixel in zip(projections, pixels) ] return measurements
def render(self, scatterer, rte_solver): """ Define a sensor and render an orthographic image at the top domain. Parameters ---------- bounding_box: shdom.BoundingBox object Used to compute the projection that will see the entire bounding box. rte_solver: shdom.RteSolverArray A solver that contains the solution to the RTE in the medium Returns ------- measurements: shdom.Measurements object Encapsulates the measurements and sensor geometry for later optimization """ com_x, com_y, com_z = self.calccenterofmass(droplets=scatterer) com = np.array([com_x, com_y, com_z]) projections = shdom.MultiViewProjection() for azimuth, zenith in zip(self.args.azimuth, self.args.zenith): y_shift = (np.sign(azimuth)) * ( self.args.camera_height - com_z) * np.tan(np.deg2rad(zenith)) projection = shdom.PerspectiveProjection(fov=30, nx=200, ny=200, x=com_x, y=com_y+y_shift, z=self.args.camera_height) projection.look_at_transform(point=com, up=[1.0, 0.0, 0.0]) projections.add_projection(projection) camera = shdom.Camera(self.sensor, projections) images = camera.render(rte_solver, self.args.n_jobs) measurements = shdom.Measurements(camera, images=images, wavelength=rte_solver.wavelength) return measurements
def render(self, bounding_box, rte_solver): """ Define a sensor and render an orthographic image at the top domain. Parameters ---------- bounding_box: shdom.BoundingBox object Used to compute the projection that will see the entire bounding box. rte_solver: shdom.RteSolverArray A solver that contains the solution to the RTE in the medium Returns ------- measurements: shdom.Measurements object Encapsulates the measurements and sensor geometry for later optimization """ projection = shdom.MultiViewProjection() for azimuth, zenith in zip(self.args.azimuth, self.args.zenith): projection.add_projection( shdom.OrthographicProjection(bounding_box=bounding_box, x_resolution=self.args.x_res, y_resolution=self.args.y_res, azimuth=azimuth, zenith=zenith, altitude='TOA')) camera = shdom.Camera(self.sensor, projection) images = camera.render(rte_solver, self.args.n_jobs) measurements = shdom.Measurements(camera, images=images, wavelength=rte_solver.wavelength) return measurements
def apply(self, measurements): """ Apply the AirMSPI poisson noise model according to the modulation and de-modulation matrices. Parameters ---------- measurements: shdom.Measurements input clean measurements Returns ------- noisy_measurements: shdom.Measurements output noisy measurements """ images = [] for view in measurements.images: multi_spectral_image = [] for i, wavelength in enumerate(measurements.wavelength): image = view[..., i] if isinstance(measurements.camera.sensor, shdom.StokesSensor): if wavelength not in self.polarized_bands: raise AttributeError( 'wavelength {} is not in AirMSPI polarized channels ({})' .format(wavelength, self.polarized_bands)) image0 = np.matmul(self.pq[wavelength], np.rollaxis(image, 1)) image45 = np.matmul(self.pu[wavelength], np.rollaxis(image, 1)) image0_sign = np.sign(image0) image45_sign = np.sign(image45) image0_mag = np.abs(image0) image45_mag = np.abs(image45) # Gain g0 = (1.0 / self.qe) * 0.85 * self.full_well / image0_mag.max() g45 = (1.0 / self.qe ) * 0.85 * self.full_well / image45_mag.max() # Digital number d with Poisson noise d0 = (self.qe * image0_mag.max() / (0.85 * self.full_well)) * \ np.random.poisson(np.round(g0 * image0_mag)).astype(np.float32) * image0_sign d45 = (self.qe * image45_mag.max() / (0.85 * self.full_well)) * \ np.random.poisson(np.round(g45 * image45_mag)).astype(np.float32) * image45_sign d = np.concatenate((d0, d45), axis=1) # Back to I, Q, U using W demodulation matrix noisy_image = np.rollaxis(np.matmul(self.w[wavelength], d), 1) else: g = 0.85 * self.full_well / image.max() noisy_image = ( image.max() / (0.85 * self.full_well)) * np.random.poisson( np.round(g * image)).astype(np.float32) multi_spectral_image.append(noisy_image) images.append(np.stack(multi_spectral_image, axis=-1)) noisy_measurements = shdom.Measurements( measurements.camera, images=images, wavelength=measurements.wavelength) return noisy_measurements