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.""" 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 = adp.area() return daylight_area / total_area
def area_coverage(self, area_of_interest): """Get the ratio of coverage (between 0 and 1) of the pass with the area of interest. """ try: area_boundary = area_of_interest.poly except AttributeError: area_boundary = AreaDefBoundary(area_of_interest, frequency=100) area_boundary = area_boundary.contour_poly inter = self.boundary.contour_poly.intersection(area_boundary) if inter is None: return 0 return inter.area() / area_boundary.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 granule_inside_area(start_time, end_time, platform_name, instrument, area_def, thr_area_coverage, tle_file=None): """Check if a satellite data granule is over area interest, using the start and end times from the filename """ try: metop = Orbital(platform_name, tle_file) except KeyError: LOG.exception( 'Failed getting orbital data for {0}'.format(platform_name)) LOG.critical( 'Cannot determine orbit! Probably TLE file problems...\n' + 'Granule will be set to be inside area of interest disregarding') return True tle1 = metop.tle.line1 tle2 = metop.tle.line2 mypass = Pass(platform_name, start_time, end_time, instrument=instrument, tle1=tle1, tle2=tle2) acov = mypass.area_coverage(area_def) LOG.debug("Granule coverage of area %s: %f", area_def.area_id, acov) is_inside = (acov > thr_area_coverage) if is_inside: from pyresample.boundary import AreaDefBoundary from trollsched.drawing import save_fig area_boundary = AreaDefBoundary(area_def, frequency=100) area_boundary = area_boundary.contour_poly save_fig(mypass, poly=area_boundary, directory='/tmp') return
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 _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 single_station(self, sched, start_time, tle_file): """Calculate passes, graph, and schedule for one station.""" logger.debug("station: %s coords: %s area: %s scores: %s", self.id, self.coords, self.area.area_id, self.satellites) opts = sched.opts pattern = sched.patterns pattern_args = { "station": self.id, "output_dir": opts.output_dir, "date": start_time.strftime("%Y%m%d"), "time": start_time.strftime("%H%M%S") } if opts.xml: pattern_args['mode'] = "request" elif opts.report: pattern_args['mode'] = "report" logger.info("Computing next satellite passes") allpasses = get_next_passes( self.satellites, start_time, sched.forward, self.coords, tle_file, aqua_terra_dumps=(sched.dump_url or True if opts.no_aqua_terra_dump else None), min_pass=self.min_pass, local_horizon=self.local_horizon) logger.info("Computation of next overpasses done") logger.debug(str(sorted(allpasses, key=lambda x: x.risetime))) area_boundary = AreaDefBoundary(self.area, frequency=500) self.area.poly = area_boundary.contour_poly if opts.plot: logger.info("Saving plots to %s", build_filename("dir_plots", pattern, pattern_args)) from threading import Thread image_saver = Thread(target=save_passes, args=(allpasses, self.area.poly, build_filename("dir_plots", pattern, pattern_args), sched.plot_parameters, sched.plot_title)) image_saver.start() if opts.avoid is not None: avoid_list = get_passes_from_xml_file(opts.avoid) else: avoid_list = None logger.info("computing best schedule for area %s" % self.area.area_id) schedule, (graph, labels) = get_best_sched(allpasses, self.area, timedelta(seconds=opts.delay), avoid_list) logger.debug(pformat(schedule)) for opass in schedule: opass.rec = True logger.info("generating file") if opts.scisys: generate_sch_file( build_filename("file_sci", pattern, pattern_args), allpasses, self.coords) if opts.meos: generate_meos_file( build_filename("file_meos", pattern, pattern_args), allpasses, self.coords, start_time + timedelta(hours=sched.start), True) # Ie report mode if opts.plot: logger.info("Waiting for images to be saved...") image_saver.join() logger.info("Done!") if opts.metno_xml: generate_metno_xml_file( build_filename("file_metno_xml", pattern, pattern_args), allpasses, self.coords, start_time + timedelta(hours=sched.start), start_time + timedelta(hours=sched.forward), self.id, sched.center_id, True) if opts.xml or opts.report: url = urlparse(opts.output_url or opts.output_dir) if opts.xml or opts.report: """Allways create xml-file in request-mode""" pattern_args['mode'] = "request" xmlfile = generate_xml_file( allpasses, start_time + timedelta(hours=sched.start), start_time + timedelta(hours=sched.forward), build_filename("file_xml", pattern, pattern_args), self.id, sched.center_id, False) logger.info("Generated " + str(xmlfile)) send_file(url, xmlfile) if opts.report: """'If report-mode was set""" pattern_args['mode'] = "report" xmlfile = generate_xml_file( allpasses, start_time + timedelta(hours=sched.start), start_time + timedelta(hours=sched.forward), build_filename("file_xml", pattern, pattern_args), self.id, sched.center_id, True) logger.info("Generated " + str(xmlfile)) if opts.graph or opts.comb: graph.save(build_filename("file_graph", pattern, pattern_args)) graph.export( labels=[str(label) for label in labels], filename=build_filename("file_graph", pattern, pattern_args) + ".gv") if opts.comb: import pickle ph = open( os.path.join( build_filename("dir_output", pattern, pattern_args), "allpasses.%s.pkl" % self.id), "wb") pickle.dump(allpasses, ph) ph.close() return graph, allpasses