Skip to content

TAT-C v3.6.0

Latest

Choose a tag to compare

@ptgrogan ptgrogan released this 26 Oct 06:27
f670d9b

What's Changed

Added new observing capabilities for limb sounding, ground-based radar, fixed surface platforms, and regions (polygons), with support for shapely points. Changed how general perturbations orbits are propagated, with options to model orbits maintained on a repeat ground track. Also changed the tangent point for GNSS radio occultation (RO) and limb sounding to the point of minimum WGS 84 geodetic altitude along the line of sight.

Added:

  • Analysis method collect_limb_observations (with enumeration ScanDirection) for limb sounding observations from periodic scans at a constant angular rate.
  • Analysis method collect_space_observations for the periods when satellites can observe other satellites (as by a sensor or a radio frequency link), subject to slant range limits and Earth occlusion (a minimum WGS 84 geodetic altitude of the line of sight). Each observation records the lines of sight at its start and end as its geometry, and the satellites' closest approach during the period (closest_time and closest_range).
  • Object schemas RadarStation (with RadarBand and RadarStation.from_band) and TerrainMask, and analysis methods collect_radar_track and compute_radar_track, for ground-based radar coverage. AllSurfaceObjects includes RadarStation.
  • Object schema SurfacePlatform (included in AllSurfaceObjects) for instruments on platforms fixed above the Earth's surface, such as towers or tethered balloons, with a heading that orients their views, and analysis methods collect_platform_track and compute_platform_track for the static footprints of their Instrument and PointedInstrument views at a target elevation, either below the instruments (looking down) or above them (looking up, as at clouds), with views clipped to the horizon of the ground below (argument ground_elevation of the footprint and pixel methods) and to an optional terrain_mask (a TerrainMask, as for a RadarStation), with method SurfacePlatform.compute_visible_region for the region of a target above the instruments visible over them. Utility method compute_static_track gives a fixed position the form of an orbit track, from which instruments project their views as from a satellite.
  • Module preprocess to derive inputs from external datasets, including terrain masks from Copernicus DEM data (compute_terrain_mask, compute_terrain_mask_for_station, compute_terrain_mask_for_platform, get_copernicus_dem_tile_urls, and sample_dem_elevation, with an effective_earth_radius_factor for refraction, also an argument of compute_terrain_elevation_angle), and gridded weights from GeoTIFF rasters (read_raster_weights).
  • Generation method generate_points_random for random points, uniform by area or weighted by a raster (for example, of population counts or densities), optionally within a mask, with a seed for reproducibility.
  • Analysis methods collect_region_observations and collect_multi_region_observations to collect the periods (start and end) when an instrument observes any part of a region (shapely Polygon or MultiPolygon), using the footprints of pointed and conical instruments and the field of regard of other instruments. Each observation records its swath (the part of the region swept by the footprint) as its geometry and identifies the region by the hash of its geometry (target_hash). Methods aggregate_observations and reduce_observations combine the swaths of a region into the part of it observed.
  • Analysis methods find_coincident_observations, the periods when two or more satellites observe the same point at once (or within a maximum time difference), comparing their observation periods or, with instantaneous, their epochs (as the times scanning instruments sample the point), and find_coincident_ground_track, the overlapping footprints of pairs of satellites at the same time (or within a maximum time difference), with example notebook FindCoincidentObservations (Metop-SG-B ICI and NASA FALCON).
  • Analysis method collect_feature_observations for the observations of features: regions that exist for a period of time (start to end), such as the storms of a nature run in an observing system simulation experiment (OSSE), sampled by the footprints of the ground track. Each observation is a satellite's view of the part of a feature inside its swath, with the fraction and area viewed and the viewing geometry (elevation angle, azimuth, slant range, and satellite height) at the viewed part.
  • Analysis method compute_sample_sizes for the sizes of the samples of point or feature observations: the extent on the ground of a PointedInstrument's pixel at each target, along and across track, and the spacing between pixels (which bound the detail an observation can resolve), with the satellite's slant range and the target's scan angle. Methods PointedInstrument.compute_sample_size, compute_sample_spacing, get_cross_track_sample_spacing, and get_along_track_sample_spacing, and utility method compute_ground_sample_size (the size on the ground of an angular extent centered on the line of sight to a target). Field PointedInstrument.scan_period for scanning instruments, whose scans are spaced along track by the distance they advance on the ground in one period (as for microwave sounders with one beam per scan position), and utility method compute_ground_advance.
  • Fields ConicalInstrument.beam_width and scan_sample_spacing, and methods ConicalInstrument.compute_sample_size (the footprint of the beam, longer in the oblique direction of the view) and compute_sample_spacing (the distance the scanned arc advances per scan, and between samples along the arc), for the sample sizes of conical scanners.
  • Analysis methods compute_access_periods, the periods when a satellite is in view of a point above a minimum elevation angle, and compute_region_access_periods, a conservative superset of the periods when an instrument's field of regard may observe any part of a region (for example, to cull analysis times).
  • Support for shapely Point objects (longitude, latitude, and optional elevation) wherever a TAT-C Point is accepted (collect_observations, collect_multi_observations, compute_dop, and GeneralPerturbationsOrbit.get_observation_events), in anticipation of replacing TAT-C points.
  • Object schema ConicalInstrument (included in AllInstruments) for conically scanning instruments, observed when a point crosses the scanned cone, and utility method compute_cone_and_azimuth.
  • Object schemas Attitude and AttitudeSchedule (with AttitudeSegment), and field attitude of satellites and constellations, for the attitude of a spacecraft's body: its velocity frame (yaw steering) and yaw, roll, and pitch angles (constant or by argument of latitude), or a schedule of attitudes over time (for example, the yaw flips of a satellite that alternately flies forward and backward, or alternating observing modes). Instruments point relative to the body (their roll and pitch angles, scan azimuths, and pixels are measured from its axes), while their fields of regard remain measured from nadir. Method get_instrument of satellites and constellations gets an instrument bound to the attitude (see Instrument.bind_attitude and Instrument.platform_attitude), and projection utilities accept an attitude.
  • Object schema TargetAttitude for a spacecraft that points its body at ground targets (as an agile satellite imaging sites, or a target mode): at each time, at the target closest to nadir within a maximum off-nadir angle, and otherwise along nadir, so that its instruments' views follow the targets. Schedules may switch to and from target pointing.
  • Sun glint: utility methods compute_specular_point (the specular point, or center of the sun glint, on the WGS 84 ellipsoid seen from a satellite) and compute_glint_angle (the angle between the directions toward the satellite and of the Sun's specular reflection at a target); fields Instrument.min_target_glint_angle and max_target_glint_angle to avoid or require sun glint (for example, for ocean color or glint observations); a glint_angle column of observations and ground tracks with solar angles; and object schema GlintAttitude for a spacecraft that points its body at the specular point, or short of it toward nadir by an offset angle (constant or a function of the specular point's angle from nadir), as for a glint observing mode, which schedules may switch to and from.
  • Instrument pointing options: fields PointedInstrument.velocity_frame (enumeration VelocityFrame, for spacecraft without yaw steering), Instrument.nadir_reference (enumeration NadirReference, for a geocentric nadir), PointedInstrument.view_geometry (enumeration ViewGeometry, for cross-track scanners), and PointedInstrument.roll_angle_profile and pitch_angle_profile (with methods get_roll_angle and get_pitch_angle) to vary pointing around the orbit. Projection functions accept matching arguments, including tilt_angle.
  • Fields Instrument.min_target_solar_elevation and Instrument.max_target_solar_elevation to require a range of solar elevation angles at the target.
  • Fields GeneralPerturbationsOrbit.remove_drag, to propagate without drag, and GeneralPerturbationsOrbit.repeat_cycle, to propagate the elements directly (None, the default), maintained on a repeat ground track with a repeat cycle found from the elements ("auto"), or with a declared repeat cycle (a duration), also accepted by from_tle, from_omm_csv, and from_omm_json. Related methods GeneralPerturbationsOrbit.get_repeat_element and GeneralPerturbationsElements.get_repeat_element, refine_repeat_cycle, without_drag, is_sun_synchronous, and property has_drag.
  • Field GeneralPerturbationsOrbit.element_switch_times (with method get_element_index) to switch between elements at given times rather than midway between their epochs, and utility method align_element_switches to switch satellites whose elements are published together (as for a formation or a constellation) at common times, so that their relative positions do not jump while their elements switch at slightly different times.
  • Field inclination of MolniyaOrbit and TundraOrbit (by default, the critical inclination), and methods from_apogee_longitude and get_apogee_longitude to place an orbit by the longitude of its apogee.
  • Field WalkerConstellation.seam_spacing (and method get_seam_spacing) to set the seam of a star configuration.
  • Argument during_contact of compute_latencies to choose when an observation that ends during a downlink is downlinked ("end", "next", or "immediate").
  • Argument systems of compute_dop to estimate a receiver clock bias for each navigation system.
  • Utility methods compute_view_tangents, compute_view_angles, compute_along_track_field_of_view, compute_argument_of_latitude, geodesic_destination, pressure_to_altitude, and altitude_to_pressure, radar geometry methods (compute_radar_beam_height, compute_radar_ground_range, compute_radar_ground_range_bounds, compute_radar_slant_range, compute_terrain_elevation_angle, compute_radar_footprint, and compute_radar_footprint_profile), and method PointedInstrument.is_in_field_of_view.
  • Utility methods for the WGS 84 ellipsoid (module tatc.utils.ellipsoid): geodetic_to_rectangular, rectangular_to_geodetic, compute_ellipsoid_intersection (intersections of rays with the ellipsoid), and compute_tangent_point (the point of minimum geodetic altitude on a line), utility method compute_vnb_frame (a satellite's velocity, normal, and binormal frame), and utility method hash_geometry (a compact hash identifying a geometry).
  • Runtime configurations footprint_points_radar_azimuthal, repeat_cycle_delta_semimajor_axis_m, and nutation_interpolation_minutes (the step of a cached table from which nutation angles are interpolated, or null to compute them for every time), and constants EFFECTIVE_EARTH_RADIUS_FACTOR, EARTH_ROTATION_RATE, and TROPICAL_YEAR_S.
  • Utility method compute_local_incidence_angle, the angle between the line of sight to a satellite and the normal to sloped terrain at a target, and preprocessing methods compute_terrain_slope_aspect (the slope and aspect of a DEM, by central differences of bilinearly interpolated elevations, across the seams of adjacent tiles) and add_local_incidence_angles (the terrain slope, aspect, and local incidence angle at the targets of ground pixels or observations with satellite angles), to constrain observations of mountainous terrain, as by side-looking instruments.
  • Validation notebooks in docs/validation comparing TAT-C with data from operational missions, with a summary of their results by capability, modeling guidance, and the limits of what TAT-C models (docs/validation/summary.rst).
  • Example notebook docs/examples/RunOSSEMonsoon.ipynb, an observing system simulation experiment (OSSE) that samples cold cloud top features of the 7-km GEOS-5 Nature Run over the American Southwest with the swaths of current (ATMS, CrIS) and notional future sounders, compares their horizontal resolution, and trades the number of satellites and orbit planes of the constellation.
  • A section of example notebook docs/examples/CollectOrbitGroundTrack.ipynb comparing the nadir field of regard model of NOAA-20 VIIRS with a detailed model from its validation (a PointedInstrument with the measured scan extent, scan view geometry, an along-track field of view tailored to the scan period, and the inertial velocity frame): their footprints, scans at nadir and the swath edge, and swaths over a pass.
  • Example notebook docs/examples/RunOSSEHurricane.ipynb, an OSSE of a simulated North Atlantic hurricane in the GEOS-5 Nature Run (located with its coarsened 0.5 degree collection), which samples its cold cloud tops and heavy precipitation with the same sensors.
  • Optional dependencies preprocess and validation, and development dependency pytest-xdist to run tests in parallel (e.g. pytest -n 8).

Changed:

  • GeneralPerturbationsOrbit propagates orbit tracks and observation events consistently, as selected by its repeat_cycle: if set, times before the first and after the last element's epoch are propagated with that element maintained on its repeat ground track; other times use the closest element. Orbits are now propagated directly with SGP4 by default; use remove_drag=True and repeat_cycle="auto" for the former default. Removed the runtime settings repeat_cycle_for_orbit_track and repeat_cycle_for_observation_events, the try_repeat arguments, and methods get_observation_repeat_cycle, get_repeat_shifts, and get_repeat_orbit_track. A warning is issued when elements with drag are propagated far from their epoch.
  • get_repeat_cycle verifies repeat cycles without drag, reports a whole number of nodal days (or mean solar days for a sun-synchronous orbit), and also confirms repeat cycles for elements within repeat_cycle_delta_semimajor_axis_m of an exact repeat. Cached repeat cycles are recomputed when the search options change. Elements with a perigee below the Earth's surface (for example, from a mean motion in revolutions per day rather than radians per minute) have no repeat cycle, with a warning, rather than a search lasting minutes.
  • Removed the runtime settings repeat_cycle_lazy_load and gp_orbit_lazy_load and the lazy_load arguments of to_gp_orbit and get_repeat_cycle: converted general perturbations orbits and repeat cycles are always cached, and recomputed when the fields or search options they depend on change.
  • Guards against common input errors: orbit and general perturbations element epochs must be timezone-aware, orbits with a perigee below the Earth's surface (for example, from a semimajor axis in kilometers) raise a validation error, and analyses warn of satellites with a perigee below 100 km (for example, from an altitude in kilometers). Analysis time windows must have timezone-aware start and end datetimes with end no earlier than start (a ValueError), and an instrument_index out of range raises an IndexError naming the satellite.
  • get_observation_events refines rise and set times to a millisecond, and finds passes that culminate outside the search period or span a switch between elements.
  • get_observation_events completes passes whose rise or set Skyfield misses (grazing passes, which barely exceed the minimum elevation angle), finding the missing event from the culmination and dropping culminations below the minimum. compute_access_periods and collect_observations no longer treated such a pass as visible from the start (or to the end) of the analysis period, which made a conical instrument observe points through the Earth.
  • collect_observations refines access periods to the instrument's field of regard, uses the time the view sweeps over the point as the epoch of a PointedInstrument observation, and evaluates orbits with a repeat cycle consistently.
  • collect_observations and collect_region_observations accept one or more points or regions and one or more satellites, and instrument_index=None for every instrument of each satellite, computing all of their observations together (concatenated and sorted by start). collect_multi_observations and collect_multi_region_observations are kept as wrappers for backwards compatibility.
  • collect_observations computes the observations of all points by each satellite and instrument together, vectorized across the points: the orbit is propagated once to screen the windows in which each point may be observed, and the periods, epochs, and validity of the observations are refined in all windows at once (in blocks that bound memory). Many points are about 50 times faster to collect (for example, 649 points, 24 satellites, and one day, from about 220 to 4.5 seconds), and a point's observations do not depend on the other points (to within a microsecond). Observation times are always in nanoseconds (datetime64[ns, UTC]), as are those of collect_downlinks.
  • collect_orbit_track, collect_ground_track, collect_ground_pixels, collect_limb_observations, and collect_downlinks accept one or more satellites (and the track methods instrument_index=None for every instrument), and collect_ro_observations one or more receivers, with the results of several concatenated and sorted by time (or start). Downlinks and RO observations of several satellites are computed together.
  • PointedInstrument roll and pitch angles rotate the view rigidly (roll, then pitch about the rolled cross-track axis), and compute_view_tangents accepts them. Documented the pointing conventions (positive roll looks left, positive pitch looks forward, and cross-track pixel indices run from right to left).
  • compute_latencies downlinks an observation that ends during a downlink at the end of that downlink by default (during_contact="end"; formerly "next").
  • PointedInstrument.cross_track_oversampling and along_track_oversampling may be negative, for gaps between pixels (as of an undersampling sounder).
  • collect_ro_observations uses the point of minimum WGS 84 geodetic altitude on the receiver-transmitter line as the tangent point.
  • SOCConstellation uses the polar streets-of-coverage pattern for near-polar orbits (new field polar and methods is_polar, get_footprint_angle, get_polar_design, get_satellites_per_plane, and get_number_planes; generate_walker raises a ValueError for polar designs) and a continuously covering hexagonal lattice for inclined orbits, which requires more satellites at a given packing distance.
  • collect_ground_track and collect_ground_pixels cull times with a mask using the periods when the instrument's field of regard may observe it, which no longer misses footprints near the poles or across the anti-meridian. Masks are split along the anti-meridian and poles before use, and results are sorted by time.
  • Observations of points (collect_observations, collect_multi_observations, and compute_latencies) identify each point by the hash of its geometry (target_hash, see hash_geometry) rather than a point_id, and aggregate_observations, reduce_observations, and reduce_latencies group observations by target_hash. The id of a TAT-C Point is no longer used.
  • Generated points and cells are identified by the hashes of their geometries (point_id and cell_id) rather than integer indices, so that a generated point's point_id equals the target_hash of its observations.
  • Generating points and cells is about 3 to 15 times faster (vectorized geometry construction, hashing, and clipping). Points and cells clipped to a mask keep the grid or lattice order rather than the arbitrary order of geopandas.clip.
  • Analysis methods that accept satellites raise a TypeError for a constellation (use its generate_members method).
  • Deprecated utility method buffer_target.
  • collect_observations accepts a GeoDataFrame or GeoSeries of points (for example, generated points), as the list of its geometries.
  • Moved joblib, used only by the example and validation notebooks, from the required to the examples optional dependencies.
  • Replaced the deprecated shapely.ops.transform with shapely.transform in buffer_footprint and buffer_target.
  • Fixed SunSynchronousOrbit to place the ascending node in local mean solar time and to keep the local time of its equator crossings constant as propagated.
  • Fixed TrainConstellation for long intervals between members, and MolniyaOrbit and TundraOrbit periods to repeat the ground track as propagated.
  • Fixed rectangular footprints of wide, elongated views.
  • Fixed PointedInstrument.compute_footprint_pixel_array for a single-time (scalar) orbit track.
  • Fixed collect_observations missing short observations (and misplacing the ends of long ones) when a field of regard extends to the horizon of a long access period, as near the perigee of a Molniya orbit, which were refined from too few samples of the access period.
  • Fixed the pixel positions of a PointedInstrument with oversampling (compute_projected_pixel_position, compute_footprint_pixel_array, and collect_ground_pixels), which spaced the pixels by a fraction of the field of view rather than across all of it.
  • Fixed split_polygon for polygons around a pole whose boundary is not monotonic in longitude (such as Antarctica's coastline), which it reconstructed by sorting their vertices by longitude, removing and adding strips of the polygon: they are now reconstructed in their vertex order, unrolled across the anti-meridian.
  • Fixed grid_observations for cells whose points each have a single sample (and so no revisit), which raised an error, and to average the revisit of a cell over only the points with a revisit.
  • Fixed compute_ground_track to identify orbits with the period of the element that propagates the orbit (as selected by element_switch_times), rather than the element whose epoch is closest.
  • Fixed collect_ro_observations labeling some occultations of transmitters nearly abeam of the receiver (yaw angles near 90 degrees) as setting rather than rising: is_rising follows the direction of the tangent point through sample_elevation. collect_ro_observations also splits a grazing occultation, whose tangent point descends and rises again, into a setting and a rising observation where the tangent point turns, so that each observation crosses sample_elevation at most once.
  • Fixed compute_latencies for observations and downlinks whose times have different units (for example, microseconds and nanoseconds).
  • Fixed split_polygon for longitudes beyond 180 degrees, for polygons spanning -180 to 180 degrees of longitude, and for holes across the anti-meridian or around a pole (holes are now split like exteriors), and to drop degenerate (zero-area) parts left by repairing invalid polygons.
  • Fixed compute_along_track_field_of_view to subtend the ground track's advance from the satellite's height above the WGS 84 ellipsoid rather than its mean altitude above the mean Earth radius: at low latitudes, where a satellite is about 7 km lower above the ellipsoid, consecutive footprints left gaps of up to about 0.7% of their length (83 m per scan for NOAA-20 VIIRS). Tailored fields of view are about 1% larger in low Earth orbit.
  • Fixed cached orbit computations for copies with changed fields, and orbits and satellites to be picklable after propagation.
  • Fixed numba-compiled utility methods (in tatc.utils.orbital, observation, radar, atmosphere, and surface) returning nan for integer inputs, which overflowed in compiled integer arithmetic (for example, semimajor_axis_to_mean_motion(7000000)): inputs are now converted to floats.
  • Improved the performance of footprints (rays projected together from one view frame, vectorized ray and limb intersections, polygon assembly, splitting along the anti-meridian, and split_polygon), masked ground tracks, multi-element orbit propagation, collect_ro_observations (observation periods of all transmitters searched and sampled together, with sample times and profiles built at once), collect_limb_observations (all scans sampled together, with sample times built at once), radar footprints (terrain masks interpolated at all azimuths at once, and a closed-form local projection instead of PROJ transformers for each station), collect_observations (linear-time pairing of rise and set events, and validity checks of all epochs at once), collect_region_observations (validity checks and swaths of all periods at once), collect_orbit_track (masks tested and points built for all times at once), observations of several points, regions, or satellites (Earth orientation computed together at each step of their searches), rise and set times (each bracketed near Skyfield's estimate and bisected only until it is narrower than a millisecond), orbit propagation (IAU 2000A nutation angles interpolated from a cached table, to within about a microarcsecond, rather than computed for every time), instrument validity checks (without iterating over Skyfield times), and the searches that refine observation periods (times built from offsets without datetime objects). to_datetime64_ns and GeneralPerturbationsOrbit.get_closest_element_index accept Skyfield Time objects.
  • find_coincident_observations and aggregate_observations compute all targets together rather than one at a time, with the same results: for a day of observations of about 100,000 to 250,000 points, in seconds rather than 5 to 13 minutes.
  • collect_region_observations is about 3 times faster for detailed regions (for example, 30 days of observations of four regions of 2000 vertices each, from about 13 to 4 seconds), computing the distances to a region's boundary with a numba-compiled function.
  • Numba-compiled functions cache their machine code (cache=True) in __pycache__ directories next to the source files (or in the directory set by NUMBA_CACHE_DIR), so that new processes (for example, the workers of a multiprocessing pool) load rather than recompile them. After editing a constant or compiled function in an editable install, clear the cache (see the README).
  • Unit tests run numba-compiled functions compiled rather than as Python (set NUMBA_DISABLE_JIT=1 to include them in a coverage report).
  • Reorganized modules: tatc.analysis.coverage is split into point_sampling, region_sampling, sampling (shared by both), and coverage_metrics (the aggregation, reduction, and gridding of observations), and tatc.analysis.track into orbit_track and ground_track; tatc.analysis.ro_coverage, latency, and dop are renamed ro_sampling, latency_sampling, and dop_sampling; tangent point geometry moved from tatc.analysis to tatc.utils.ellipsoid, and the radar footprint functions from tatc.utils.projection to tatc.utils.radar. Public functions remain available from tatc.analysis and tatc.utils. Orbit propagation algorithms moved to tatc.utils.propagation, with the conversion of Skyfield times in tatc.utils.time, interpolated nutation angles in tatc.utils.earth_orientation, and computations run together in tatc.utils.computation.
  • Updated example notebooks.

Full Changelog: v3.5.1...v3.6.0