def _get_sunlight_coverage(area_def, start_time, overpass=None): """Get the sunlight coverage of *area_def* at *start_time* as a value between 0 and 1.""" if area_def.proj_dict.get('proj') == 'geos': adp = Boundary(*get_geostationary_bounding_box( area_def, nb_points=100)).contour_poly else: adp = AreaDefBoundary(area_def, frequency=100).contour_poly poly = get_twilight_poly(start_time) if overpass is not None: ovp = overpass.boundary.contour_poly cut_area_poly = adp.intersection(ovp) else: cut_area_poly = adp if cut_area_poly is None: if not adp._is_inside(ovp): return 0.0 else: # Should already have been taken care of in pyresample.spherical.intersection cut_area_poly = adp daylight = cut_area_poly.intersection(poly) if daylight is None: if sun_zenith_angle(start_time, *area_def.get_lonlat(0, 0)) < 90: return 1.0 else: return 0.0 else: daylight_area = daylight.area() total_area = cut_area_poly.area() return daylight_area / total_area
def get_area_slices(data_area, area_to_cover): """Compute the slice to read from an *area* based on an *area_to_cover*.""" if data_area.proj_dict['proj'] != 'geos': raise NotImplementedError('Only geos supported') # Intersection only required for two different projections if area_to_cover.proj_dict['proj'] == data_area.proj_dict['proj']: LOGGER.debug('Projections for data and slice areas are' ' identical: {}'.format(area_to_cover.proj_dict['proj'])) # Get xy coordinates llx, lly, urx, ury = area_to_cover.area_extent x, y = data_area.get_xy_from_proj_coords([llx, urx], [lly, ury]) return slice(x[0], x[1] + 1), slice(y[1], y[0] + 1) data_boundary = Boundary(*get_geostationary_bounding_box(data_area)) area_boundary = AreaDefBoundary(area_to_cover, 100) intersection = data_boundary.contour_poly.intersection( area_boundary.contour_poly) x, y = data_area.get_xy_from_lonlat(np.rad2deg(intersection.lon), np.rad2deg(intersection.lat)) return slice(min(x), max(x) + 1), slice(min(y), max(y) + 1)
def check_file_covers_area(file_handler, check_area): """Checks if the file covers the current area. If the file doesn't provide any bounding box information or 'area' was not provided in `filter_parameters`, the check returns True. """ try: gbb = Boundary(*file_handler.get_bounding_box()) except NotImplementedError as err: logger.debug("Bounding box computation not implemented: %s", str(err)) else: abb = AreaDefBoundary(get_area_def(check_area), frequency=1000) intersection = gbb.contour_poly.intersection(abb.contour_poly) if not intersection: return False return True
def _get_sunlight_coverage(area_def, start_time, sza_threshold=90, overpass=None): """Get the sunlight coverage of *area_def* at *start_time* as a value between 0 and 1.""" if isinstance(area_def, SwathDefinition): lons, lats = area_def.get_lonlats() freq = int(lons.shape[-1] * 0.10) lons, lats = da.compute(lons[::freq, ::freq], lats[::freq, ::freq]) adp = Boundary(lons.ravel(), lats.ravel()).contour_poly elif area_def.is_geostationary: adp = Boundary(*get_geostationary_bounding_box( area_def, nb_points=100)).contour_poly else: adp = AreaDefBoundary(area_def, frequency=100).contour_poly poly = get_twilight_poly(start_time) if overpass is not None: ovp = overpass.boundary.contour_poly cut_area_poly = adp.intersection(ovp) else: cut_area_poly = adp if cut_area_poly is None: if not adp._is_inside(ovp): return 0.0 else: # Should already have been taken care of in pyresample.spherical.intersection cut_area_poly = adp daylight = cut_area_poly.intersection(poly) if daylight is None: if sun_zenith_angle(start_time, *area_def.get_lonlat( 0, 0)) < sza_threshold: return 1.0 else: return 0.0 else: daylight_area = daylight.area() total_area = adp.area() return daylight_area / total_area
def boundary_for_area(area_def: PRGeometry) -> Boundary: """Create Boundary object representing the provided area.""" if not FIXED_PR and isinstance(area_def, SwathDefinition): # TODO: Persist lon/lats if requested lons, lats = area_def.get_bbox_lonlats() freq = int(area_def.shape[0] * 0.05) if hasattr(lons[0], "compute") and da is not None: lons, lats = da.compute(lons, lats) lons = [lon_side.astype(np.float64) for lon_side in lons] lats = [lat_side.astype(np.float64) for lat_side in lats] adp = AreaBoundary(*zip(lons, lats)) adp.decimate(freq) elif getattr(area_def, "is_geostationary", False): adp = Boundary( *get_geostationary_bounding_box(area_def, nb_points=100)) else: freq_fraction = 0.05 if isinstance(area_def, SwathDefinition) else 0.30 adp = AreaDefBoundary(area_def, frequency=int(area_def.shape[0] * freq_fraction)) return adp
def __init__(self, overpass, scan_step=50, frequency=200): # compute area covered by pass Boundary.__init__(self) self.overpass = overpass self.orb = overpass.orb # compute sides scanlength_seconds = ((overpass.falltime - overpass.risetime).seconds + (overpass.falltime - overpass.risetime).microseconds / 1000000.0) logger.debug("Instrument = %s", self.overpass.instrument) if self.overpass.instrument == 'viirs': sec_scan_duration = 1.779166667 along_scan_reduce_factor = 1 elif self.overpass.instrument.startswith("avhrr"): sec_scan_duration = 1./6. along_scan_reduce_factor = 0.1 elif self.overpass.instrument == 'ascat': sec_scan_duration = 3.74747474747 along_scan_reduce_factor = 1 # Overwrite the scan step scan_step = 1 else: # Assume AVHRR! logmsg = ("Instrument scan duration not known. Setting it to AVHRR. Instrument: ") logger.info(logmsg + "%s", str(self.overpass.instrument)) sec_scan_duration = 1./6. along_scan_reduce_factor = 0.1 # From pass length in seconds and the seconds for one scan derive the number of scans in the swath: scans_nb = scanlength_seconds/sec_scan_duration * along_scan_reduce_factor # Devide by the scan step to a reduced number of scans: scans_nb = np.floor(scans_nb/scan_step) scans_nb = int(max(scans_nb, 1)) sides_lons, sides_lats = self.get_instrument_points(self.overpass, overpass.risetime, scans_nb, np.array([0, self.overpass.number_of_fovs-1]), scan_step=scan_step) side_shape = sides_lons[::-1, 0].shape[0] nmod = 1 if side_shape != scans_nb: nmod = side_shape // scans_nb logger.debug('Number of scan lines (%d) does not match number of scans (%d)', side_shape, scans_nb) logger.info('Take every %d th element on the sides...', nmod) self.left_lons = sides_lons[::-1, 0][::nmod] self.left_lats = sides_lats[::-1, 0][::nmod] self.right_lons = sides_lons[:, 1][::nmod] self.right_lats = sides_lats[:, 1][::nmod] # compute bottom maxval = self.overpass.number_of_fovs rest = maxval % frequency mid_range = np.arange(rest / 2, maxval, frequency) if mid_range[0] == 0: start_idx = 1 else: start_idx = 0 reduced = np.hstack([0, mid_range[start_idx::], maxval - 1]).astype('int') lons, lats = self.get_instrument_points(self.overpass, overpass.falltime, 1, reduced) self.bottom_lons = lons[0][::-1] self.bottom_lats = lats[0][::-1] # compute top lons, lats = self.get_instrument_points(self.overpass, overpass.risetime, 1, reduced) self.top_lons = lons[0] self.top_lats = lats[0]
def __init__(self, overpass, scan_step=50, frequency=200): # compute area covered by pass Boundary.__init__(self) self.overpass = overpass self.orb = overpass.orb # compute sides scanlength_seconds = ( (overpass.falltime - overpass.risetime).seconds + (overpass.falltime - overpass.risetime).microseconds / 1000000.0) logger.debug("Instrument = %s", self.overpass.instrument) if self.overpass.instrument == 'viirs': sec_scan_duration = 1.779166667 along_scan_reduce_factor = 1 elif self.overpass.instrument.startswith("avhrr"): sec_scan_duration = 1. / 6. along_scan_reduce_factor = 0.1 elif self.overpass.instrument == 'ascat': sec_scan_duration = 3.74747474747 along_scan_reduce_factor = 1 # Overwrite the scan step scan_step = 1 elif self.overpass.instrument == 'mhs': sec_scan_duration = 8 / 3. along_scan_reduce_factor = 1 # Overwrite the scan step scan_step = 1 elif self.overpass.instrument == 'atms': sec_scan_duration = 8 / 3. along_scan_reduce_factor = 1 # Overwrite the scan step scan_step = 1 elif self.overpass.instrument == 'mwhs-2': sec_scan_duration = 8 / 3. along_scan_reduce_factor = 1 # Overwrite the scan step scan_step = 1 else: # Assume AVHRR! logmsg = ( "Instrument scan duration not known. Setting it to AVHRR. Instrument: " ) logger.info(logmsg + "%s", str(self.overpass.instrument)) sec_scan_duration = 1. / 6. along_scan_reduce_factor = 0.1 # From pass length in seconds and the seconds for one scan derive the number of scans in the swath: scans_nb = scanlength_seconds / sec_scan_duration * along_scan_reduce_factor # Devide by the scan step to a reduced number of scans: scans_nb = np.floor(scans_nb / scan_step) scans_nb = int(max(scans_nb, 1)) sides_lons, sides_lats = self.get_instrument_points( self.overpass, overpass.risetime, scans_nb, np.array([0, self.overpass.number_of_fovs - 1]), scan_step=scan_step) side_shape = sides_lons[::-1, 0].shape[0] nmod = 1 if side_shape != scans_nb: nmod = side_shape // scans_nb logger.debug( 'Number of scan lines (%d) does not match number of scans (%d)', side_shape, scans_nb) logger.info('Take every %d th element on the sides...', nmod) self.left_lons = sides_lons[::-1, 0][::nmod] self.left_lats = sides_lats[::-1, 0][::nmod] self.right_lons = sides_lons[:, 1][::nmod] self.right_lats = sides_lats[:, 1][::nmod] # compute bottom maxval = self.overpass.number_of_fovs rest = maxval % frequency mid_range = np.arange(rest / 2, maxval, frequency) if mid_range[0] == 0: start_idx = 1 else: start_idx = 0 reduced = np.hstack([0, mid_range[start_idx::], maxval - 1]).astype('int') lons, lats = self.get_instrument_points(self.overpass, overpass.falltime, 1, reduced) self.bottom_lons = lons[0][::-1] self.bottom_lats = lats[0][::-1] # compute top lons, lats = self.get_instrument_points(self.overpass, overpass.risetime, 1, reduced) self.top_lons = lons[0] self.top_lats = lats[0]