asp_plot.sensors#
Sensor-specific metadata readers for stereo scenes.
This package isolates the sensor-specific work of discovering scene files and
extracting per-scene metadata from the sensor-agnostic stereo-pair geometry
math in asp_plot.stereopair_metadata_parser.
The goal is flexibility: WorldView (and other DigitalGlobe-heritage) XML camera
files, the Airbus DIMAP v2 family (Pléiades 1A/1B and Neo, SPOT 6/7, PeruSat-1),
the DIMAP v1 family (SPOT 5, ALOS PRISM), ASTER gen_aster camera files, and
RPC-only products (Cartosat-1, Deimos, anything ASP runs with -t rpc) are
supported, and adding a new sensor is a matter of writing a new
SensorMetadata subclass in its own module and registering it in
SENSORS — no changes to the pair-level geometry code are required.
Most readers parse metadata a vendor wrote down; asp_plot.sensors.aster
and asp_plot.sensors.rpc instead derive their scene dicts (footprint,
view angles, GSD, satellite positions) from look vectors, because their camera
files record no summary geometry at all. Both kinds fill the same schema.
Most readers also claim XML files; the RPC reader claims images, because
that is where an RPC-only product keeps its camera model. It is therefore
marked fallback and consulted only after every XML reader has declined,
since a WorldView or Pléiades delivery ships images alongside its camera XMLs.
Each reader is responsible for turning a directory of camera/metadata files into a list of scene dicts, one per scene, each containing the sensor-agnostic keys the geometry code consumes:
xml_fn, catid, sensor, date, scandir, tdi, geom
(a Shapely polygon footprint in EPSG:4326), the mean view-angle/GSD/sun
attributes (meansataz, meansatel, meanoffnadirviewangle,
meanintrackviewangle, meancrosstrackviewangle, meanproductgsd,
meansunaz, meansunel, cloudcover), and — when geteph is True —
eph_gdf (ephemeris GeoDataFrame in EPSG:4978), att_df (attitude
DataFrame), and fp_gdf (footprint GeoDataFrame in EPSG:4326).
eph_gdf and fp_gdf are the trajectory block’s own optional members:
fp_gdf is always provided, while eph_gdf is omitted entirely by a
reader that can recover no satellite positions at all (an RPC-only product
whose look rays do not converge). Consumers use d.get("eph_gdf") and plot
the footprint alone when it is absent.
att_df comes in one of two shapes, depending on what the sensor reports:
quaternions (q1..q4, scalar-last) or the vendor’s own roll/pitch/yaw
(roll/pitch/yaw in degrees, with attrs["rpy_frame"] naming the
frame they are defined in). Both carry NaN-filled cov_* columns when the
format has no covariance. Consumers dispatch on which columns are present, and
must tolerate att_df being None: a sensor whose camera files record no
attitude at all (ASTER) reports it that way rather than inventing one.
eph_gdf is time-indexed for every sensor that timestamps its trajectory;
ASTER and RPC-only products, which timestamp nothing, index it by image line
number instead.
Layout: asp_plot.sensors.base holds the SensorMetadata ABC and
shared helpers; each sensor family lives in its own module
(asp_plot.sensors.worldview, asp_plot.sensors.dimap,
asp_plot.sensors.dimap_v1, asp_plot.sensors.aster,
asp_plot.sensors.rpc); this
__init__ holds the SENSORS registry and the detection entry points, and
re-exports every public name so from asp_plot.sensors import ... is stable
across the package split.
Submodules#
Attributes#
Classes#
Metadata reader for ASP |
|
Metadata reader for Airbus-family DIMAP v2 camera files. |
|
Metadata reader for ALOS PRISM DIMAP-style scene metadata. |
|
Metadata reader for images whose only camera model is an RPC. |
|
Abstract base class for a single sensor's metadata reader. |
|
Metadata reader for SPOT 5 DIMAP v1 scene metadata. |
|
Metadata reader for WorldView satellite XML camera files. |
Functions#
|
Expand inputs into every candidate camera file: XMLs and images. |
|
Expand files, directories, and glob patterns into XML file paths. |
|
Detect and instantiate the appropriate sensor reader for a directory. |
|
Detect and instantiate the appropriate sensor reader for explicit inputs. |
Package Contents#
- class asp_plot.sensors.AsterMetadata(directory=None, image_list=None)#
Bases:
asp_plot.sensors.base.SensorMetadataMetadata reader for ASP
gen_asterASTER camera XMLs.One scene per band file, so a 3N/3B pair goes through the existing N-choose-2 pair machinery with no special-casing: the derived view angles reproduce ASTER’s nadir/backward stereo geometry (~31° convergence at the ground for the nominal 27.6° backward pointing).
See the module docstring for what is derived and what is unavailable. In short: footprint, view angles, GSD and a positions-only trajectory are derived; attitude does not exist (
att_dfis None), sun angles and cloud cover are absent, and the date comes from a neighbouring L1A granule name if there is one.- get_scene_dict(xml, geteph=True)#
Get a dictionary of metadata for one ASTER band.
- get_scene_dicts()#
Return one sensor-agnostic scene dict per camera XML.
- name = 'ASTER'#
- class asp_plot.sensors.PleiadesMetadata(directory=None, image_list=None)#
Bases:
asp_plot.sensors.base.SensorMetadataMetadata reader for Airbus-family DIMAP v2 camera files.
Parses DIMAP v2 primary-product metadata (
DIM_*.XML, root tagDimap_Document) as delivered with Pléiades 1A/1B, Pléiades Neo, SPOT 6/7, and PeruSat-1 SEN(sor) products. Each scene is delivered as a single DIM XML, so unlike WorldView there is no tile mosaicking step. The sidecarRPC_*.XMLfiles share the DIMAP root but carry no ephemeris, attitude, or acquisition-angle information, so discovery keeps only files whoseMETADATA_SUBPROFILEisPRODUCTand whoseMETADATA_PROFILEis one ofSUPPORTED_DIMAP_PROFILES(products from other DIMAP profiles are skipped with an explanatory warning). Profiles inSPEC_ONLY_DIMAP_PROFILESare implemented from ASP’s reader spec but not yet validated against real deliveries (#168).Notes
Airbus quaternions are scalar-first (
Q0is the scalar part). They are reordered to the scalar-lastq1..q4layout shared with WorldView, as consumed by the roll/pitch/yaw computation inasp_plot.stereo_geometry.StereoGeometryPlotter._compute_roll_pitch_yaw().Attitude comes in two shapes: tabulated quaternion samples (
Quaternion_List; Pléiades Neo, SPOT 6/7, PeruSat-1) or one degree-3 polynomial per quaternion component (Polynomial_Quaternions; Pléiades 1A/1B), which is evaluated at the ephemeris timestamps so both shapes yield the same tabulatedatt_dfdownstream.DIMAP reports no ephemeris/attitude covariance and no scan direction or TDI level: the
cov_*columns are filled with NaN andscandir/tdiare None. Consumers treat those as “not provided”.The mean view/sun angles and GSD are averaged over the
Located_Geometric_Valuesblocks — nine for Pléiades/SPOT (corners, edge midpoints, center), a single center block for PeruSat-1.meansatelis derived as 90° minus the mean target incidence angle, matching the WorldViewMEANSATELconvention.
- getAtt_df(root)#
Create an attitude DataFrame from a parsed DIMAP document.
Pléiades Neo, SPOT 6/7, and PeruSat-1 products tabulate quaternion samples in a
Quaternion_List; Pléiades 1A/1B products instead provide one polynomial per quaternion component (Polynomial_Quaternions), which is evaluated at the ephemeris timestamps so both shapes come out as the same tabulated DataFrame.- Parameters:
root (xml.etree.ElementTree.Element) – Parsed
Dimap_Documentroot element.- Returns:
Time-indexed DataFrame with scalar-last quaternions
q1..q4(AirbusQ0is the scalar part and lands inq4), plus NaNcov_*columns (DIMAP provides no attitude covariance).- Return type:
pandas.DataFrame
- getEphem_gdf(root)#
Create an ephemeris GeoDataFrame from a parsed DIMAP document.
- Parameters:
root (xml.etree.ElementTree.Element) – Parsed
Dimap_Documentroot element.- Returns:
Time-indexed GeoDataFrame with
x, y, zpositions (m) anddx, dy, dzvelocities (m/s) in ECEF (EPSG:4978), plus NaNcov_*columns (DIMAP provides no ephemeris covariance).- Return type:
geopandas.GeoDataFrame
- get_scene_dict(xml, geteph=True)#
Get a dictionary of metadata for one DIMAP scene.
- get_scene_dicts()#
Return one sensor-agnostic scene dict per DIMAP product XML.
- name = 'Pleiades'#
- class asp_plot.sensors.PrismMetadata(directory=None, image_list=None)#
Bases:
DimapV1MetadataMetadata reader for ALOS PRISM DIMAP-style scene metadata.
Parses the ALOS PRISM
*.DIMA/*.XMLmetadata that ASP’sPRISM_XML.ccreads (used byprism2aspto build CSM linescan cameras). A PRISM triplet delivers one file per view (forward, nadir, backward), each of which is one scene here.Notes
Attitude is tabulated as roll/pitch/yaw in degrees under
Satellite_Attitudes/Angles_List/Angles/Angle; ASP applies them withrollPitchYaw(), which converts degrees to radians.Those angles are the satellite’s attitude relative to the nominal (along, across, down) orbital frame, composed as
Rz(yaw) Ry(pitch) Rx(roll)— the same frame and Euler convention as the roll/pitch/yaw this package derives from quaternion sensors’ attitude, so PRISM curves are directly comparable to those. The fixed per-view mounting rotation ASP applies on top (cam2sat) is camera geometry, not satellite attitude, and is deliberately not folded in here.PRISM reports no view or GSD summary angles in the metadata header, so those degrade to NaN; the sun angles are filled when present.
- getAtt_df(root)#
Create an attitude DataFrame from a parsed PRISM document.
- Parameters:
root (xml.etree.ElementTree.Element) – Parsed
Dimap_Documentroot element.- Returns:
Time-indexed DataFrame with
roll,pitch,yawin degrees (as delivered) and NaNcov_*columns.- Return type:
pandas.DataFrame
- get_scene_dict(xml, geteph=True)#
Get a dictionary of metadata for one ALOS PRISM scene.
- name = 'PRISM'#
- rpy_frame = 'orbital frame (along, across, down)'#
- class asp_plot.sensors.RpcMetadata(directory=None, image_list=None)#
Bases:
asp_plot.sensors.base.SensorMetadataMetadata reader for images whose only camera model is an RPC.
Covers everything ASP runs with
-t rpc— Cartosat-1, Deimos, and the tail of commercial products delivered with rational polynomials and nothing else — as one reader, because the camera model is the format.Unlike every other reader in this package, the file it claims is the image, not a sidecar XML. That makes it a
fallbackreader: a WorldView or Pléiades delivery ships images alongside its camera XMLs and those images carry RPCs too, so this reader is only consulted once every XML-based reader has declined the input at every search depth.See the module docstring for what is derived and what is unavailable.
- get_scene_dict(image_fn, geteph=True)#
Get a dictionary of metadata for one RPC image.
- Parameters:
- Returns:
Sensor-agnostic scene dict (see the package docstring).
- Return type:
- Raises:
ValueError – If
image_fncarries no usable RPC camera model.
- get_scene_dicts()#
Return one sensor-agnostic scene dict per image.
- fallback = True#
- name = 'RPC-only'#
- class asp_plot.sensors.SensorMetadata(directory)#
Bases:
abc.ABCAbstract base class for a single sensor’s metadata reader.
A concrete reader discovers the scene files for one sensor in a directory and extracts a list of sensor-agnostic scene dicts (see the package docstring for the schema) that the stereo-pair geometry code can consume without knowing which sensor produced them.
Subclasses must implement
_is_camera_file()(the content check that decides which files the sensor claims; discovery and detection are built on it here) andget_scene_dicts().- fallback#
Whether this reader is a last-resort match, tried only after every other reader has failed at every search depth. Set on readers that claim files a more specific reader’s delivery also contains — the RPC reader claims images, and every WorldView or Pléiades delivery ships images next to its camera XMLs (issue #177).
- Type:
- classmethod detect(directory, recursive=True)#
Return True if this reader can handle the files in
directory.- Parameters:
directory (str) – Path to directory to inspect.
recursive (bool, optional) – If True (default), also match metadata files nested in subdirectories.
asp_plot.sensors.sensor_for_directory()first asks every sensor to detect shallowly and only then recursively, so a sensor matching at the top level wins over one matching a nested delivery.
- Returns:
Whether this sensor’s metadata files are present.
- Return type:
- classmethod detect_files(image_list)#
Return True if this reader can handle the files in
image_list.The file-list counterpart of
detect(), used when the sensor must be chosen from an explicit list of inputs rather than a directory.
- abstractmethod get_scene_dicts()#
Return a list of per-scene metadata dictionaries.
- directory#
- fallback = False#
- name = 'sensor'#
- class asp_plot.sensors.Spot5Metadata(directory=None, image_list=None)#
Bases:
DimapV1MetadataMetadata reader for SPOT 5 DIMAP v1 scene metadata.
Parses the
METADATA.DIM/*.XMLscene metadata delivered with SPOT 5 HRG/HRS products, mirroring ASP’sSPOT_XML.cc(thespot5session). Ephemeris and attitude both live inData_Strip; the scene footprint comes fromDataset_Frame.Notes
Attitude is tabulated as yaw/pitch/roll in radians under
Corrected_Attitudes/Corrected_Attitude/Anglesand converted to degrees here. ASP feeds the raw values straight tosin/cosinget_look_rotation_matrix, which is what fixes the unit.The angles are defined in the SPOT 123-4-5 Geometry Handbook navigation frame, relative to its local orbital frame (X across-track, Y along-track, Z up), composed as
Mp*Mr*My. That is a different axis assignment from the (along, across, down) frame the quaternion sensors’ roll/pitch/yaw are computed in, so the values are reported as delivered and labeled with their own frame rather than silently mixed with the others.DIMAP v1 reports no satellite azimuth, so
meansatazstays NaN and the pair convergence angle degrades to NaN; the incidence, viewing and sun angles that are inScene_Sourceare filled.
- getAtt_df(root)#
Create an attitude DataFrame from a parsed SPOT 5 document.
- Parameters:
root (xml.etree.ElementTree.Element) – Parsed
Dimap_Documentroot element.- Returns:
Time-indexed DataFrame with
roll,pitch,yawin degrees (converted from the radians on disk) and NaNcov_*columns.- Return type:
pandas.DataFrame
- get_scene_dict(xml, geteph=True)#
Get a dictionary of metadata for one SPOT 5 scene.
- name = 'SPOT5'#
- rpy_frame = 'SPOT Geometry Handbook navigation frame'#
- class asp_plot.sensors.WorldViewMetadata(directory=None, image_list=None)#
Bases:
asp_plot.sensors.base.SensorMetadataMetadata reader for WorldView satellite XML camera files.
Parses WorldView (and other DigitalGlobe-heritage products that share the same XML format, e.g. GeoEye-1, QuickBird, IKONOS) satellite XML files to extract per-scene metadata, handling both single XML files and multiple XML tiles per scene (mosaicked with
dg_mosaic).This class is named for the sensor family (the stable WorldView name) and governs which reader parses the XML. It is intentionally distinct from the attribution check
asp_plot.utils.detect_vantor_satellite(), which is named for the rights-holder (Vantor) and decides whether the “© Vantor” overlay applies. The two concerns use different names on purpose; see #137.- getAtt(xml)#
Extract attitude data from XML file.
Retrieves satellite attitude (orientation quaternion and covariance) data from the XML file.
- Parameters:
xml (str) – Path to the XML file
- Returns:
Array of shape (N, 15) containing attitude data with columns: point_num, q1, q2, q3, q4, and 10 covariance matrix elements (upper triangle of 4x4 matrix)
- Return type:
- getAtt_df(xml)#
Create a DataFrame from attitude data.
Converts attitude data to a DataFrame with time index.
- Parameters:
xml (str) – Path to the XML file
- Returns:
DataFrame with attitude quaternions and covariance, time-indexed
- Return type:
pandas.DataFrame
- getEphem(xml)#
Extract ephemeris data from XML file.
Retrieves satellite ephemeris (position and velocity) data from the XML file.
- Parameters:
xml (str) – Path to the XML file
- Returns:
Array containing ephemeris data with columns: point_num, Xpos, Ypos, Zpos, Xvel, Yvel, Zvel, and covariance matrix elements
- Return type:
Notes
All coordinates are in Earth-Centered Fixed (ECF) reference frame. Units are meters for positions, meters/sec for velocities, and m^2 for covariance.
- getEphem_gdf(xml)#
Create a GeoDataFrame from ephemeris data.
Converts ephemeris data to a GeoDataFrame with time index and Point geometry.
- Parameters:
xml (str) – Path to the XML file
- Returns:
GeoDataFrame with ephemeris data and Point geometries in EPSG:4978
- Return type:
geopandas.GeoDataFrame
Notes
The GeoDataFrame uses EPSG:4978 (Earth-Centered Earth-Fixed) CRS and has a time index corresponding to the acquisition times.
- get_catid_xmls()#
Get a single representative XML file for each catalog ID.
Groups the discovered XML files by their catalog ID (read from the XML content, not the filename) and resolves each scene to one XML: a scene delivered as a single XML is used as-is, while a scene tiled across multiple XMLs is mosaicked into one with
dg_mosaic.- Returns:
Dictionary mapping catalog IDs to a single XML file path.
- Return type:
- Raises:
ValueError – If none of the discovered XML files contain a
CATIDtag.
Notes
Mosaicking is decided per catalog ID, so a directory holding many distinct single-tile scenes is not mosaicked just because it contains more than two XML files. Mosaicking a tiled scene requires
dg_mosaicfrom the NASA Ames Stereo Pipeline on the system path.
- get_id_dict(catid, xml, geteph=True)#
Get a dictionary of metadata for a specific catalog ID.
Extracts metadata from XML file for a given catalog ID, including satellite parameters, acquisition angles, and geometry.
- Parameters:
- Returns:
Dictionary containing metadata for the catalog ID
- Return type:
Notes
The dictionary includes satellite ID, acquisition date, scan direction, TDI level, geometry information, and various mean angles and parameters. If geteph is True, also includes ephemeris and footprint GeoDataFrames.
The identity core (xml_fn, catid, sensor, date, geom) is read strictly — a camera XML without those is an error. The summary fields degrade to “not provided” (None/NaN) when their tags are absent (issue #163):
dg_mosaiccan strip image tags, and Multi products carry per-band TDI instead of a singleTDILEVEL.
- get_scene_dicts()#
Get dictionaries of metadata for each catalog ID.
Builds dictionaries of metadata for each catalog ID found in the XML files.
- Returns:
List of dictionaries, one for each catalog ID, containing metadata
- Return type:
- xml2poly(xml)#
Convert XML corner coordinates to Shapely Polygon.
Reads XML file and converts corner coordinates to a Shapely Polygon geometry.
- Parameters:
xml (str) – Path to the XML file
- Returns:
Polygon geometry representing the image footprint
- Return type:
shapely.geometry.Polygon
- xml2wkt(xml)#
Convert XML corner coordinates to WKT polygon string.
Extracts corner coordinates from XML file and converts them to a Well-Known Text (WKT) polygon string.
- Parameters:
xml (str) – Path to the XML file
- Returns:
WKT polygon string representation of image footprint
- Return type:
Notes
Uses ULLON/ULLAT, URLON/URLAT, LRLON/LRLAT, LLLON/LLLAT tags (Upper-Left, Upper-Right, Lower-Right, Lower-Left corners).
- name = 'WorldView'#
- asp_plot.sensors.resolve_camera_inputs(inputs, recursive=True)#
Expand inputs into every candidate camera file: XMLs and images.
resolve_xml_inputs()covers the readers whose camera model is a sidecar XML; RPC-only products carry theirs inside the image (issue #177), so directory inputs also contribute candidate rasters here. Explicitly named files are included whatever their extension, sostereo_geom fore.tif aft.tifworks.Mixing the two kinds in one list is safe: every reader filters the list through its own
SensorMetadata._is_camera_file()content check, so a WorldView delivery’s images are ignored by the WorldView reader and its XMLs by the RPC reader.- Parameters:
inputs (str or os.PathLike or iterable of those) – One or more files, directories, and/or glob patterns.
recursive (bool, optional) – Passed through to directory discovery and
**glob expansion. Default True.
- Returns:
Sorted, de-duplicated candidate camera file paths.
- Return type:
- asp_plot.sensors.resolve_xml_inputs(inputs, recursive=True)#
Expand files, directories, and glob patterns into XML file paths.
Lets a user point the tools at messy inputs without a fixed directory structure — e.g.
geom_plot *.XML(already expanded by the shell),geom_plot scene1.xml scene2.xml,geom_plot delivery_dir/, or a mix.Each item of
inputsmay be:a path to an XML file (included directly),
a directory (searched with the sensor-neutral
asp_plot.sensors.base.list_candidate_xmls(), which is shallow-first and falls back to a recursive search), ora glob pattern (expanded with
glob.glob()).
Results are de-duplicated (by absolute path) and returned sorted. Directory inputs get only the generic basename filter (
README.XML, ortho products); the sensor-specific content checks are applied by the readers, not here.- Parameters:
inputs (str or os.PathLike or iterable of those) – One or more files, directories, and/or glob patterns.
recursive (bool, optional) – Passed through to directory discovery and
**glob expansion. Default True.
- Returns:
Sorted, de-duplicated XML file paths.
- Return type:
- asp_plot.sensors.sensor_for_directory(directory)#
Detect and instantiate the appropriate sensor reader for a directory.
Iterates the
SENSORSregistry and returns an instance of the first reader whoseSensorMetadata.detect()matches the directory contents.- Parameters:
directory (str) – Path to directory containing camera/metadata files.
- Returns:
An initialized reader for the detected sensor.
- Return type:
- Raises:
ValueError – If no registered sensor reader matches the directory contents.
- asp_plot.sensors.sensor_for_inputs(inputs)#
Detect and instantiate the appropriate sensor reader for explicit inputs.
The file-list counterpart of
sensor_for_directory(). Resolvesinputs(files, directories, and/or globs) into a list of candidate camera files, then returns an instance of the first registered reader whoseSensorMetadata.detect_files()matches —fallbackreaders last, so a delivery’s images cannot outrank its own camera XMLs.- Parameters:
inputs (str or os.PathLike or iterable of those) – One or more files, directories, and/or glob patterns.
- Returns:
An initialized reader for the detected sensor.
- Return type:
- Raises:
ValueError – If no candidate files are found, or no registered sensor reader matches them.
- asp_plot.sensors.SENSORS#