Top-Tips#
PyProj#
If special transformation grids are included in the coordinate transformation use:
# PROJ activate network grid/data
pyproj.network.set_network_enabled(True) # pyright: ignore[reportPrivateImportUsage]
Or specify data-dir via
pyproj.datadir.set_data_dir(proj_data_dir)
Results#
The most important functions, mapping(mapper.map_points, mapper.map_footprint, mapper.map_center_point)
and coordinate projections (image.project) return MappingResult and ProjectionResult
MappingResultis eitherResultFailureorMappingResultSuccessProjectionResultis eitherResultFailureorProjectionResultSuccess
You can test whether it’s Success or Failure be checking .ok.
The results will always be in the same order as the input pixel/coordinates.
Always check for issues to catch reasons for invalid results
Tip
Most mapping functions return results with a CRS attached (res.crs). You can use that CRS to transform the
mapped output (e.g. footprint coordinates) to another coordinate system via CoordinateTransformer.
from pyproj import CRS
from weitsicht.transform import CoordinateTransformer
res = image.map_footprint()
if res.ok and res.crs is not None:
crs_target = CRS.from_epsg(4979) # WGS84 ell with ellipsoid heights
transformer = CoordinateTransformer.from_crs(res.crs, crs_target)
coords_src = res.coordinates[res.mask]
# Always check that transfomer is not None which is the case if source and target crs are equal
coords_target = coords_src if transformer is None else transformer.transform(coords_src)
Errors#
Most functions either raise a WeitsichtError (invalid inputs / missing state) or
return a result object (MappingResult / ProjectionResult) that can be a ResultFailure.
from weitsicht import WeitsichtError
try:
res = image.map_points([[200, 300], [50, 50]])
except WeitsichtError as err:
print("weitsicht error:", err)
else:
if not res.ok:
print("mapping failed:", res.error, "issues:", res.issues)
else:
coords_valid = res.coordinates[res.mask] # keep input order
See Error Handling for more patterns and the exception hierarchy.
Perspective Images#
Tip
For drone photos, prefer building your ImagePerspective from EXIF/XMP metadata (e.g. ExifTool -> PyExifToolTags
-> image_from_meta()) or use ImageFromMetaBuilder if you want IOR/EOR separately. See Metadata for Camera and Pose Extraction and
04-01 - Digitize Dugongs.
‘’image_from_meta()’’ and other EOR related functions feature an input parameter to_utm=True which will convert EOR (position and orientation) to WGS84/UTM.
Otherwise standard output of images loaded by meta builder are in WGS84 geocentric (EPG:4978) coordiantes
CRS quick reference#
CRS / units |
Perspective Image (EOR) |
Coordiantes for Projection |
Orthophoto CRS |
Mapper Horizontal |
MapperRaster GeorefArray |
Mapper Trimesh |
|---|---|---|---|---|---|---|
|
OK |
OK |
OK |
OK |
OK ( |
OK |
Projected (e.g., UTM) (0) |
OK |
OK |
OK |
OK |
OK |
OK |
Geocentric Cartesian (ECEF) (e.g. |
OK |
OK |
Not possible - Rare (never seen such thing) |
Limited (1) |
Not possible - Rare (never seen such thing) |
OK |
Geodetic lon/lat (degrees) (e.g. |
Not working (2) |
OK |
Possible (but units for gsd/area are degrees) |
Possible (3) |
Possible (only with 3D CRS) (4) |
Not working (would need transformation first) |
EPSG:25833+3855)Mapping#
For raster-based mapping you can trade disk IO for memory:
MappingRaster(default) keeps the raster on disk and reads only the needed values.If you cache a window/full raster (
preload_window,preload_full_rasterorload_window),MappingRasterautomatically uses an in-memoryMappingGeorefArraybackend.
Tip
With MappingRaster in default mode, you can use extremely large raster datasets (e.g. a DTM of your whole country) without loading the full raster into RAM.
from pyproj import CRS
from weitsicht import MappingRaster
mapper = MappingRaster(
raster_path="dem.tif",
crs=CRS.from_epsg(32633),
preload_window=(600_000, 5_340_000, 602_000, 5_342_000),
)
# mapper.map_* now uses the cached backend
res = mapper.map_heights_from_coordinates([[601_000, 5_341_000]], crs_s=mapper.crs)
# Or cache later (returns MappingGeorefArray)
georef = mapper.load_window((600_000, 5_340_000, 602_000, 5_342_000))
Important
If you cache only a window, mapping is limited to that cached extent (outside points/rays will report
Issue.OUTSIDE_RASTER).