0.1.39
Loading...
Searching...
No Matches
pyhelios.LiDARCloud.LiDARCloud Class Reference

High-level interface for LiDAR point cloud operations. More...

Detailed Description

High-level interface for LiDAR point cloud operations.

Supports synthetic scanning, point cloud filtering, triangulation, and leaf area density calculations.

Example
>>> from pyhelios import LiDARCloud >>> from pyhelios.types import vec3 >>> >>> with LiDARCloud() as lidar: ... # Add a scan ... scan_id = lidar.addScan( ... origin=vec3(0, 0, 1), ... Ntheta=100, theta_range=(0, 1.57), ... Nphi=100, phi_range=(-3.14, 3.14), ... exit_diameter=0.01, beam_divergence=0.001 ... ) ... ... # Add hit points ... lidar.addHitPoint(scan_id, vec3(1, 0, 0), vec3(1, 0, 0)) ... ... # Export point cloud ... lidar.exportPointCloud("output.xyz")

Definition at line 169 of file LiDARCloud.py.

Public Member Functions

 __init__ (self)
 Initialize LiDARCloud.
 
 __enter__ (self)
 Context manager entry.
 
 __exit__ (self, exc_type, exc_val, exc_tb)
 Context manager exit - cleanup resources.
 
 __del__ (self)
 Fallback destructor for cleanup without context manage.
 
int addScan (self, Union[vec3, List[float], Tuple[float, float, float]] origin, int Ntheta, Tuple[float, float] theta_range, int Nphi, Tuple[float, float] phi_range, float exit_diameter, float beam_divergence, Optional[List[str]] column_format=None, float range_noise_stddev=0.0, float angle_noise_stddev=0.0, float scan_tilt_roll=0.0, float scan_tilt_pitch=0.0, float scan_azimuth_offset=0.0)
 Add a LiDAR scan to the point cloud.
 
int addScanMoving (self, int Ntheta, Tuple[float, float] theta_range, int Nphi, Tuple[float, float] phi_range, float exit_diameter, float beam_divergence, List[float] traj_t, List[Union[vec3, List[float], Tuple[float, float, float]]] traj_pos, List[List[float]] traj_rot, float pulse_rate_hz, bool rot_is_quaternion=True, Optional[Union[vec3, List[float], Tuple[float, float, float]]] lever_arm=None, Optional[Union[vec3, List[float], Tuple[float, float, float]]] boresight_rpy=None, Optional[List[str]] column_format=None, float range_noise_stddev=0.0, float angle_noise_stddev=0.0, float t0=0.0)
 Add a moving-platform (mobile/airborne) raster LiDAR scan driven by a 6-DOF pose trajectory.
 
int addScanSpinning (self, List[float] beam_elevation_angles, float azimuth_step, float pulse_rate_hz, List[float] traj_t, List[Union[vec3, List[float], Tuple[float, float, float]]] traj_pos, List[List[float]] traj_rot, bool rot_is_quaternion=True, float exit_diameter=0.0, float beam_divergence=0.0, Optional[Union[vec3, List[float], Tuple[float, float, float]]] lever_arm=None, Optional[Union[vec3, List[float], Tuple[float, float, float]]] boresight_rpy=None, Optional[List[str]] column_format=None, float range_noise_stddev=0.0, float angle_noise_stddev=0.0, float t0=0.0)
 Add a continuously-spinning multibeam scan from physical instrument parameters.
 
int addScanMovingRaster (self, int Ntheta, Tuple[float, float] theta_range, int Nphi, Tuple[float, float] phi_range, float pulse_rate_hz, List[float] traj_t, List[Union[vec3, List[float], Tuple[float, float, float]]] traj_pos, List[List[float]] traj_quat, float exit_diameter=0.0, float beam_divergence=0.0, Optional[Union[vec3, List[float], Tuple[float, float, float]]] lever_arm=None, Optional[Union[vec3, List[float], Tuple[float, float, float]]] boresight_rpy=None, Optional[List[str]] column_format=None, float range_noise_stddev=0.0, float angle_noise_stddev=0.0, float t0=0.0)
 Add a moving-platform raster scan: a fixed angular fan swept along a quaternion trajectory.
 
int addScanRisley (self, List[Union['RisleyPrism', List[float], Tuple[float,...]]] prisms, float refractive_index_air, float pulse_rate_hz, List[float] traj_t, List[Union[vec3, List[float], Tuple[float, float, float]]] traj_pos, List[List[float]] traj_rot, bool rot_is_quaternion=True, float exit_diameter=0.0, float beam_divergence=0.0, Optional[Union[vec3, List[float], Tuple[float, float, float]]] lever_arm=None, Optional[Union[vec3, List[float], Tuple[float, float, float]]] boresight_rpy=None, Optional[List[str]] column_format=None, float range_noise_stddev=0.0, float angle_noise_stddev=0.0, float t0=0.0)
 Add a rotating-Risley-prism (Livox-style rosette) scan from physical instrument parameters.
 
int getScanCount (self)
 Get total number of scans in the cloud.
 
vec3 getScanOrigin (self, int scanID)
 Get origin of a specific scan.
 
int getScanSizeTheta (self, int scanID)
 Get number of zenith scan points for a scan.
 
int getScanSizePhi (self, int scanID)
 Get number of azimuthal scan points for a scan.
 
float getScanRangeNoiseStdDev (self, int scanID)
 Get the range (along-beam) measurement noise standard deviation for a scan (meters).
 
float getScanAngleNoiseStdDev (self, int scanID)
 Get the angular (beam-pointing) jitter standard deviation for a scan (radians).
 
float getScanTiltRoll (self, int scanID)
 Get the global scanner tilt roll angle for a scan (radians; 0.0 if level).
 
float getScanTiltPitch (self, int scanID)
 Get the global scanner tilt pitch angle for a scan (radians; 0.0 if level).
 
float getScanAzimuthOffset (self, int scanID)
 Get the global scanner azimuth (heading) offset for a scan (radians; 0.0 if none).
 
int getScanPattern (self, int scanID)
 Get the scan pattern for a scan.
 
List[float] getScanBeamZenithAngles (self, int scanID)
 Get the per-channel beam zenith angles (radians) for a multibeam scan.
 
ScanMode getScanMode (self, int scanID)
 Get the high-level acquisition mode of a scan as a :class:ScanMode.
 
int getScanStepsPerRev (self, int scanID)
 Get the number of azimuth firing steps per revolution (spinning scans; 0 otherwise).
 
float getScanRotationRate (self, int scanID)
 Get the sensor-head rotation rate in revolutions/second (spinning scans; 0 otherwise).
 
float getScanRevolutions (self, int scanID)
 Get the number of revolutions the sensor head made (spinning scans; 0 otherwise).
 
List[RisleyPrism] getScanRisleyPrisms (self, int scanID)
 Get the rotating wedge prisms of a Risley-prism scan as a list of :class:RisleyPrism.
 
float getScanRisleyRefractiveIndexAir (self, int scanID)
 Get the refractive index of the medium surrounding a Risley scan's prisms (1.0 for non-Risley).
 
ReturnMode getScanReturnMode (self, int scanID)
 Get the return-reporting mode of a scan as a :class:ReturnMode (MULTI or SINGLE).
 
 setScanReturnMode (self, int scanID, Union[ReturnMode, int] return_mode)
 Set the return-reporting mode of a scan (ReturnMode.MULTI or ReturnMode.SINGLE).
 
SingleReturnSelection getScanSingleReturnSelection (self, int scanID)
 Get the single/limited-return selection policy as a :class:SingleReturnSelection.
 
 setScanSingleReturnSelection (self, int scanID, Union[SingleReturnSelection, int] selection)
 Set the single/limited-return selection policy (STRONGEST, FIRST, LAST, or STRONGEST_PLUS_LAST).
 
int getScanMaxReturns (self, int scanID)
 Get the maximum returns per pulse used in single/limited-return mode (1 = single, N = N-return).
 
 setScanMaxReturns (self, int scanID, int max_returns)
 Set the maximum returns per pulse used in single/limited-return mode (must be >= 1).
 
 setSyntheticScanMemoryBudget (self, int bytes)
 Set the soft memory budget (bytes) for :meth:syntheticScan's transient buffers.
 
int getSyntheticScanMemoryBudget (self)
 Get the soft memory budget (bytes) for :meth:syntheticScan's transient buffers.
 
float getScanPulseWidth (self, int scanID)
 Get the pulse width / range resolution (meters) of a scan (0 = use syntheticScan argument).
 
 setScanPulseWidth (self, int scanID, float pulse_width)
 Set the pulse width / range resolution (meters) of a scan (0 = use syntheticScan argument).
 
float getScanDetectionThreshold (self, int scanID)
 Get the detection threshold (energy fraction, noise floor) of a scan.
 
 setScanDetectionThreshold (self, int scanID, float detection_threshold)
 Set the detection threshold (energy fraction, noise floor) of a scan.
 
bool getScanRecordPartialMisses (self, int scanID)
 Whether a scan's partly intercepted multi-return pulses also record a partial-miss point.
 
 setScanRecordPartialMisses (self, int scanID, bool record_partial_misses)
 Set whether a scan's partly intercepted multi-return pulses record the escaped energy as a miss.
 
 addHitPoint (self, int scanID, Union[vec3, List[float], Tuple[float, float, float]] xyz, Union[vec3, SphericalCoord, List[float], Tuple[float, float]] direction, Optional[Union[RGBcolor, List[float], Tuple[float, float, float]]] color=None)
 Add a hit point to the point cloud.
 
 addHitPoints (self, int scanID, xyz_array, direction_array, color_array=None)
 Add many hit points to the point cloud in a single bulk call.
 
 addHitPointsWithData (self, int scanID, xyz_array, direction_array, data_labels=None, data_values=None, color_array=None)
 Add many hit points carrying a per-hit data map in a single bulk call.
 
int getHitCount (self)
 Get total number of hit points in cloud.
 
vec3 getHitXYZ (self, int index)
 Get coordinates of a hit point.
 
vec3 getHitOrigin (self, int index)
 Get the (x,y,z) beam-emission origin of a hit point.
 
SphericalCoord getHitRaydir (self, int index)
 Get ray direction of a hit point.
 
RGBcolor getHitColor (self, int index)
 Get color of a hit point.
 
int getHitScanID (self, int index)
 Get the scan ID a hit point belongs to.
 
bool doesHitDataExist (self, int index, str label)
 Check whether a named scalar data value exists for a hit point.
 
float getHitData (self, int index, str label)
 Get a named scalar data value for a hit point.
 
List[float] getHitDataAll (self, str label)
 Bulk-export a named scalar data value for all hits in a single FFI call.
 
Tuple[List[vec3], List[RGBcolor]] getHitsXYZRGB (self)
 Bulk-export coordinates and colors for all hits in a single FFI call.
 
 getHitsXYZRGBArrays (self)
 Bulk-export hit coordinates + colors as numpy arrays.
 
 getHitDataArray (self, str label)
 Bulk-export a named scalar field as an (getHitCount(),) float32 array, NaN where the label is absent for a hit.
 
List[float] getHitDataColumn (self, str label, float absent_value=-9999.0)
 Bulk-export a named scalar column.
 
int getHitDataColumnIndex (self, str label)
 Get the internal column slot index for a hit-data label.
 
 getHitDataColumnArray (self, str label, float absent_value=-9999.0)
 Bulk-export a named scalar column as an (getHitCount(),) float64 numpy array via the columnar path (absent_value where the label is absent for a hit).
 
 getHitScanIDArray (self)
 Bulk-export the scan ID of every hit as an (getHitCount(),) int32 array.
 
 getHitMissArray (self)
 Bulk-export the miss flag of every hit as an (getHitCount(),) int32 array (1 == sky/miss, 0 == real surface return).
 
 deleteHitPoint (self, int index)
 Delete a hit point from the cloud.
 
bool isHitMiss (self, int index)
 Return True if a hit is a "miss" (a fired pulse that returned nothing).
 
bool hasMisses (self)
 Return True if the cloud contains at least one miss.
 
bool isMultiReturnData (self)
 Return True if the cloud contains multi-return data.
 
 coordinateShift (self, Union[vec3, List[float], Tuple[float, float, float]] shift)
 Translate all hit points by a shift vector.
 
 coordinateRotation (self, Union[SphericalCoord, List[float], Tuple[float, float]] rotation)
 Rotate all hit points by spherical rotation angles.
 
 triangulateHitPoints (self, float Lmax, float max_aspect_ratio=4.0)
 Generate triangle mesh from hit points using Delaunay triangulation.
 
int getTriangleCount (self)
 Get number of triangles in the mesh.
 
dict getTriangulationStats (self)
 Filter diagnostics from the most recent triangulateHitPoints() call.
 
 getTriangleVerticesAll (self)
 Bulk-export every triangle's vertices and source scan in one call.
 
 setExternalTriangulation (self, vertices, scan_ids)
 Replace the internal triangulation with an externally-supplied mesh.
 
 distanceFilter (self, float maxdistance)
 Filter hit points by maximum distance from scanne.
 
 reflectanceFilter (self, float minreflectance)
 Filter hit points by minimum reflectance value.
 
 firstHitFilter (self)
 Keep only first return hit points.
 
 lastHitFilter (self)
 Keep only last return hit points.
 
 exportPointCloud (self, str filename, bool write_header=True)
 Export point cloud to ASCII file.
 
 exportLeafAreaUncertainty (self, str filename)
 Export per-voxel leaf-area sampling uncertainty to a self-describing ASCII file.
 
 exportScans (self, str filename)
 Export all scans to an XML metadata file plus one ASCII data file per scan.
 
 loadXML (self, str filename)
 Load scan metadata from XML file.
 
 disableMessages (self)
 Disable console output messages.
 
 enableMessages (self)
 Enable console output messages.
 
 addGrid (self, Union[vec3, List[float], Tuple[float, float, float]] center, Union[vec3, List[float], Tuple[float, float, float]] size, Union[List[int], Tuple[int, int, int]] ndiv, float rotation=0.0, Optional[Union[List[float], Tuple[float,...]]] column_z_offsets=None)
 Add a rectangular grid of voxel cells.
 
 addGridCell (self, Union[vec3, List[float], Tuple[float, float, float]] center, Union[vec3, List[float], Tuple[float, float, float]] size, float rotation=0.0)
 Add a single grid cell.
 
int getGridCellCount (self)
 Get total number of grid cells.
 
vec3 getCellCenter (self, int index)
 Get the true world-space center position of a grid cell.
 
vec3 getCellCenterUnrotated (self, int index)
 Get the UNROTATED (axis-aligned lattice) center position of a grid cell.
 
vec3 getCellSize (self, int index)
 Get size of a grid cell.
 
float getCellRotation (self, int index)
 Get the azimuthal rotation of a grid cell about the z-axis, in degrees.
 
float getCellLeafArea (self, int index)
 Get leaf area of a grid cell (m²)
 
float getCellLeafAreaDensity (self, int index)
 Get leaf area density of a grid cell (m²/m³)
 
int getCellBeamCount (self, int index)
 Get the beam count N that entered a grid cell during the leaf-area inversion.
 
float getCellRelativeDensityIndex (self, int index)
 Get the relative density index (I_rdi) for a grid cell.
 
float getCellMeanPathLength (self, int index)
 Get the mean beam path length (m) through a grid cell.
 
float getCellLADVariance (self, int index)
 Get the per-voxel LAD sampling variance for a grid cell.
 
 getCellLeafAreaConfidenceInterval (self, int index, float confidence_level=0.95)
 Get the leaf-area confidence interval for a single grid cell.
 
 getGroupLADConfidenceInterval (self, List[int] indices, float confidence_level=0.95)
 Get the group-scale LAD confidence interval over a set of grid cells (recommended).
 
float getCellGtheta (self, int index)
 Get G(theta) value for a grid cell.
 
 setCellGtheta (self, float Gtheta, int index)
 Set G(theta) value for a grid cell.
 
 calculateHitGridCell (self)
 Calculate hit point grid cell assignments.
 
 gapfillMisses (self)
 Gapfill sky/miss points where rays didn't hit geometry.
 
int gapfillMissesCount (self, Optional[int] scanID=None, bool gapfill_grid_only=False, bool add_flags=False)
 Gapfill missing points and return only how many were added.
 
int getVirtualMissCount (self)
 Number of gap-filled misses currently held in virtualized form.
 
dict getCroppedReturnStats (self)
 Returns counts of the removed returns that the last :meth:calculateLeafArea call inferred from target_count.
 
bool hasVirtualMisses (self)
 Whether any gap-filled miss is currently held in virtualized form.
 
None materializeMisses (self)
 Convert every virtualized gap-filled miss into a stored hit point.
 
SphericalCoord getScanGridDirection (self, int scanID, int row, int column)
 Beam direction at a scan-grid cell, from the model fitted during gap-filling.
 
 getHitXYZColumn (self)
 Read every hit's position in index order in one pass.
 
 getHitScanIDColumn (self)
 Read every hit's scan ID in index order in one pass.
 
int estimateHitPointMemory (self, int hit_count)
 Estimate the resident memory a cloud of hit_count points will occupy, in bytes.
 
None setMaxHitPoints (self, int max_hits)
 Set the cap on stored hit points before loading fails with a diagnostic.
 
int getMaxHitPoints (self)
 Current cap on stored hit points, or 0 if the check is disabled.
 
None reserveHitPoints (self, int hit_count)
 Reserve capacity for hit points and every scalar-data column at once.
 
None setExactPathLengths (self, bool exact)
 Keep every beam path length exactly, instead of binning them.
 
bool getExactPathLengths (self)
 Whether path lengths are accumulated exactly.
 
 syntheticScan (self, Context context, Optional[int] rays_per_pulse=None, Optional[float] pulse_distance_threshold=None, bool scan_grid_only=False, bool record_misses=True, bool append=False, Optional[Union[ReturnMode, int]] return_mode=None, cancel_flag=None)
 Perform synthetic LiDAR scan of geometry in Context.
 
 calculateLeafArea (self, Context context, Optional[int] min_voxel_hits=None, Optional[float] element_width=None, Optional[Union[float, List[float]]] Gtheta=None)
 Calculate leaf area for each grid cell.
 
 calculateSyntheticLeafArea (self, Context context)
 Calculate synthetic leaf area (for validation of synthetic scans).
 
 calculateSyntheticGtheta (self, Context context)
 Calculate synthetic G(theta) (for validation of synthetic scans).
 
 exportTriangleNormals (self, str filename)
 Export triangle normal vectors to file.
 
 exportTriangleAreas (self, str filename)
 Export triangle areas to file.
 
 exportLeafAreas (self, str filename)
 Export leaf areas for each grid cell to file.
 
 exportLeafAreaDensities (self, str filename)
 Export leaf area densities for each grid cell to file.
 
 exportGtheta (self, str filename)
 Export G(theta) values for each grid cell to file.
 
 addTrianglesToContext (self, Context context)
 Add triangulated mesh to Context as triangle primitives.
 
 initializeCollisionDetection (self, Context context)
 Initialize CollisionDetection plugin for ray tracing.
 
 enableCDGPUAcceleration (self)
 Enable GPU acceleration for collision detection ray tracing.
 
 disableCDGPUAcceleration (self)
 Disable GPU acceleration (use CPU ray tracing)
 
bool isGPUAvailable (self)
 Return True if a CUDA-capable GPU is available for collision-detection ray tracing.
 
bool isGPUAccelerationEnabled (self)
 Return True if GPU acceleration is currently enabled for collision-detection ray tracing.
 
 setSyntheticScanProgressPointer (self, ptr)
 Register an external per-scan progress counter polled during :meth:syntheticScan.
 
None createHitDataColumn (self, str label, HitDataType column_type)
 Create a per-hit scalar-data column with an explicit storage type.
 
HitDataType getHitDataType (self, str label)
 Storage type of an existing per-hit scalar-data column.
 
List[float] getHitDataColumnFloat32 (self, str label, float absent_value=-9999.0)
 Bulk-export a named scalar column as 32-bit floats.
 
 getHitDataColumnFloat32Array (self, str label, float absent_value=-9999.0)
 Bulk-export a named scalar column as a (getHitCount(),) float32 numpy array.
 
List[int] getHitDataColumnInt32 (self, str label, int absent_value=-9999)
 Bulk-export a named scalar column as 32-bit signed integers.
 
 getHitDataColumnInt32Array (self, str label, int absent_value=-9999)
 Bulk-export a named scalar column as a (getHitCount(),) int32 numpy array.
 
None addHitPointsBulk (self, int scanID, xyz, dir_spherical=None, Optional[List[str]] labels=None, values=None)
 Bulk-ingest hit points through the native bulk path, with double-precision positions.
 
None deleteHitPoints (self, int first, int count)
 Delete a contiguous range of hit points, preserving the order of the rest.
 
None setTriangulationSink (self, callback)
 Register a sink that receives each scan's triangles as :meth:triangulateHitPoints finishes it.
 
None setSyntheticScanHitSink (self, callback)
 Register a sink fired after each chunk of a :meth:syntheticScan lands in the cloud.
 
int getScanHitCount (self, int scanID)
 Number of hit points (stored returns plus virtualized misses) belonging to one scan.
 
List[int] getScanHitIndices (self, int scanID)
 Global indices of one scan's hit points, in the order the per-scan readers use.
 
 getScanHitXYZColumn (self, int scanID)
 Read one scan's hit positions in a single pass.
 
List[float] getScanHitDataColumn (self, int scanID, str label, float absent_value=-9999.0)
 Read one scan's values of a scalar-data label in a single pass, as doubles.
 
List[float] getScanHitDataColumnFloat32 (self, int scanID, str label, float absent_value=-9999.0)
 Read one scan's values of a scalar-data label as 32-bit floats.
 
List[int] getScanHitDataColumnInt32 (self, int scanID, str label, int absent_value=-9999)
 Read one scan's values of a scalar-data label as 32-bit signed integers.
 
None calculateLeafAreaBlock (self, Context context, ijk_min, ijk_max, int min_voxel_hits, float element_width, Optional[Union[float, List[float]]] Gtheta=None)
 Calculate leaf area for only a block of the voxel grid.
 
Tuple[int, int, int] getCellGlobalIJK (self, int index)
 Lattice index (i, j, k) of a grid cell along x, y and z.
 
Tuple[int, int, int] getGridGlobalCount (self)
 Number of lattice cells along x, y and z (the ndiv passed to :meth:addGrid).
 
int getHitPointCapacity (self)
 Number of hit points the cloud can hold before its arrays reallocate.
 
 setProgressCallback (self, callback)
 Register a progress callback fired with (progress_fraction, message) during :meth:syntheticScan.
 
None deleteHitData (self, str label)
 Remove a per-hit scalar-data column from every hit in the cloud.
 
Tuple[int, int] getNominalScanGridCell (self, int scanID, vec3 point)
 Scan-grid cell (row, column) a point lies in, from the scan's declared raster.
 
bool is_available (self)
 Check if LiDAR is available in current build.
 

Static Public Member Functions

float getMissDistance ()
 Return the LIDAR_MISS_DISTANCE constant (meters): the distance at which a miss point is placed along its beam.
 
int getDefaultMaxHitPoints ()
 Default cap on the number of stored hit points in a cloud (100 million).
 

Protected Member Functions

 _dispatch_synthetic_scan (self, context_ptr, rays_per_pulse, pulse_distance_threshold, scan_grid_only, record_misses, append, return_mode)
 
 _check_cd_context_alive (self)
 Raise if the Context bound to collision detection has been destroyed.
 
None _validate_label (self, str label)
 Validate a scalar-data label argument (shared by the column readers).
 
None _raise_pending_callback_error (self)
 Re-raise an exception captured inside a streaming-sink callback, if any.
 
None _validate_scan_id (self, int scanID)
 Validate a scan index argument (shared by the per-scan readers).
 

Static Protected Member Functions

 _validate_trajectory (traj_t, traj_pos, traj_rot, rot_stride, method)
 Shared trajectory validation/marshalling for moving/spinning scans.
 

Protected Attributes

 _cloud_ptr = lidar_wrapper.createLiDARcloud()
 
 _progress_callback_ref = None
 
 _triangulation_sink_ref = None
 
 _triangulation_sink_error = None
 
 _synthetic_hit_sink_ref = None
 
 _synthetic_hit_sink_error = None
 
 _cd_context = context
 

Constructor & Destructor Documentation

◆ __init__()

pyhelios.LiDARCloud.LiDARCloud.__init__ ( self)

Initialize LiDARCloud.

Exceptions
LiDARErrorIf plugin not available in current build
RuntimeErrorIf cloud initialization fails

Definition at line 178 of file LiDARCloud.py.

◆ __del__()

pyhelios.LiDARCloud.LiDARCloud.__del__ ( self)

Fallback destructor for cleanup without context manage.

Definition at line 218 of file LiDARCloud.py.

Member Function Documentation

◆ __enter__()

pyhelios.LiDARCloud.LiDARCloud.__enter__ ( self)

Context manager entry.

Definition at line 208 of file LiDARCloud.py.

◆ __exit__()

pyhelios.LiDARCloud.LiDARCloud.__exit__ ( self,
exc_type,
exc_val,
exc_tb )

Context manager exit - cleanup resources.

Definition at line 212 of file LiDARCloud.py.

◆ _check_cd_context_alive()

pyhelios.LiDARCloud.LiDARCloud._check_cd_context_alive ( self)
protected

Raise if the Context bound to collision detection has been destroyed.

Definition at line 2449 of file LiDARCloud.py.

◆ _dispatch_synthetic_scan()

pyhelios.LiDARCloud.LiDARCloud._dispatch_synthetic_scan ( self,
context_ptr,
rays_per_pulse,
pulse_distance_threshold,
scan_grid_only,
record_misses,
append,
return_mode )
protected

Definition at line 2167 of file LiDARCloud.py.

◆ _raise_pending_callback_error()

None pyhelios.LiDARCloud.LiDARCloud._raise_pending_callback_error ( self)
protected

Re-raise an exception captured inside a streaming-sink callback, if any.

   A Python exception raised inside a ctypes callback never propagates -- ctypes returns 0
   and C++ takes that for success -- so the sink trampolines stash the exception and this
   re-raises it once the native call has returned.

Definition at line 2814 of file LiDARCloud.py.

◆ _validate_label()

None pyhelios.LiDARCloud.LiDARCloud._validate_label ( self,
str label )
protected

Validate a scalar-data label argument (shared by the column readers).

Definition at line 2625 of file LiDARCloud.py.

◆ _validate_scan_id()

None pyhelios.LiDARCloud.LiDARCloud._validate_scan_id ( self,
int scanID )
protected

Validate a scan index argument (shared by the per-scan readers).

Definition at line 2954 of file LiDARCloud.py.

◆ _validate_trajectory()

pyhelios.LiDARCloud.LiDARCloud._validate_trajectory ( traj_t,
traj_pos,
traj_rot,
rot_stride,
method )
staticprotected

Shared trajectory validation/marshalling for moving/spinning scans.

   Returns (t_list, pos_list, rot_list) of plain Python floats. rot_stride is 4 for
   quaternions or 3 for Euler triples; pass rot_stride=None to skip rotation validation.

Definition at line 416 of file LiDARCloud.py.

◆ addGrid()

pyhelios.LiDARCloud.LiDARCloud.addGrid ( self,
Union[vec3, List[float], Tuple[float, float, float]] center,
Union[vec3, List[float], Tuple[float, float, float]] size,
Union[List[int], Tuple[int, int, int]] ndiv,
float rotation = 0.0,
Optional[Union[List[float], Tuple[float, ...]]] column_z_offsets = None )

Add a rectangular grid of voxel cells.

Parameters
centerGrid center position (vec3 or 3-element list)
sizeGrid dimensions [x, y, z] (vec3 or 3-element list)
ndivNumber of divisions [nx, ny, nz] (3-element list)
rotationAzimuthal rotation angle (degrees, default 0.0)
column_z_offsetsOptional per-(x,y)-column vertical offset for terrain following, row-major as [j*ndiv[0] + i] with length ndiv[0]*ndiv[1]. Each vertical column of voxels is shifted in z by its column's offset so the grid can track an external terrain surface (e.g. a DEM). None (the default) builds an axis-regular grid.
Note
rotation is in degrees here; :meth:addGridCell takes its rotation in radians. :meth:getCellRotation reports degrees.
Example
>>> lidar.addGrid( ... center=vec3(0, 0, 0.5), ... size=vec3(10, 10, 1), ... ndiv=[10, 10, 5], ... rotation=0.0 ... )
Terrain-following grid over a 2x2 column layout:
>>> lidar.addGrid( ... center=vec3(0, 0, 0.5), ... size=vec3(10, 10, 1), ... ndiv=[2, 2, 5], ... column_z_offsets=[0.0, 0.1, 0.2, 0.3] ... )

Definition at line 1574 of file LiDARCloud.py.

◆ addGridCell()

pyhelios.LiDARCloud.LiDARCloud.addGridCell ( self,
Union[vec3, List[float], Tuple[float, float, float]] center,
Union[vec3, List[float], Tuple[float, float, float]] size,
float rotation = 0.0 )

Add a single grid cell.

Parameters
centerCell center position (vec3 or 3-element list)
sizeCell dimensions [x, y, z] (vec3 or 3-element list)
rotationAzimuthal rotation angle (radians, default 0.0)
Note
rotation is in radians here, whereas :meth:addGrid takes degrees. :meth:getCellRotation reports degrees.

Definition at line 1637 of file LiDARCloud.py.

◆ addHitPoint()

pyhelios.LiDARCloud.LiDARCloud.addHitPoint ( self,
int scanID,
Union[vec3, List[float], Tuple[float, float, float]] xyz,
Union[vec3, SphericalCoord, List[float], Tuple[float, float]] direction,
Optional[Union[RGBcolor, List[float], Tuple[float, float, float]]] color = None )

Add a hit point to the point cloud.

Parameters
scanIDScan ID this hit belongs to
xyzHit point coordinates (vec3 or 3-element list)
directionRay direction (vec3/SphericalCoord or 2-3 element list)
colorOptional RGB color (RGBcolor or 3-element list)

Definition at line 980 of file LiDARCloud.py.

◆ addHitPoints()

pyhelios.LiDARCloud.LiDARCloud.addHitPoints ( self,
int scanID,
xyz_array,
direction_array,
color_array = None )

Add many hit points to the point cloud in a single bulk call.

   This skips the per-point Python loop by passing contiguous buffers
   straight to the native library in one FFI call.
Parameters
scanIDScan ID these hits belong to
xyz_arrayHit point coordinates, shape (N, 3) [x, y, z]
direction_arrayRay directions, shape (N, 3) [radius, elevation, azimuth] (azimuth is currently ignored, matching addHitPoint)
color_arrayOptional RGB colors, shape (N, 3) [r, g, b]

Definition at line 1034 of file LiDARCloud.py.

◆ addHitPointsBulk()

None pyhelios.LiDARCloud.LiDARCloud.addHitPointsBulk ( self,
int scanID,
xyz,
dir_spherical = None,
Optional[List[str]] labels = None,
values = None )

Bulk-ingest hit points through the native bulk path, with double-precision positions.

   This is the native ``addHitPoints`` entry point, distinct from :meth:`addHitPoints`
   (a per-point shim taking float positions). It takes float64 coordinates, can derive
   beam directions automatically, and writes scalar-data columns directly.
Parameters
scanIDScan ID these hits belong to (the scan must already exist)
xyzHit point coordinates, shape (N, 3) float64
dir_sphericalBeam directions, shape (N, 3) as (radius, elevation, azimuth), or None to derive each direction from the point's position relative to the scan origin (what the ASCII loader does)
labelsOptional list of scalar-data column names (length k)
valuesRequired when labels is given: (N, k) float64 values. A NaN entry leaves that label absent on that point.
Exceptions
ValueErrorIf an array has the wrong shape, row counts disagree, or ``values`` is missing while labels was supplied
RuntimeErrorIf the native library predates helios-core v1.3.86
Example
>>> import numpy as np >>> lidar.addHitPointsBulk(0, np.zeros((10, 3)), ... labels=["intensity"], values=np.ones((10, 1)))

Definition at line 2658 of file LiDARCloud.py.

◆ addHitPointsWithData()

pyhelios.LiDARCloud.LiDARCloud.addHitPointsWithData ( self,
int scanID,
xyz_array,
direction_array,
data_labels = None,
data_values = None,
color_array = None )

Add many hit points carrying a per-hit data map in a single bulk call.

   Like addHitPoints, but also populates each hit's named-scalar data map —
   the in-memory equivalent of what the ASCII loader does for non-standard
   columns. This is the path multi-return LAD needs (timestamp/target_index/
   target_count land in the map so gapfillMisses() can group beams by pulse).
Parameters
scanIDScan ID these hits belong to (the scan must already exist)
xyz_arrayHit point coordinates, shape (N, 3) [x, y, z]
direction_arrayRay directions, shape (N, 3) [radius, elevation, azimuth]. Pass cart2sphere(xyz - origin) to match loadASCIIFile; the full SphericalCoord (incl. radius) is used.
data_labelsOptional list of data-map key names (length k)
data_valuesOptional (N, k) values for those keys (float64)
color_arrayOptional RGB colors, shape (N, 3) [r, g, b]

Definition at line 1075 of file LiDARCloud.py.

◆ addScan()

int pyhelios.LiDARCloud.LiDARCloud.addScan ( self,
Union[vec3, List[float], Tuple[float, float, float]] origin,
int Ntheta,
Tuple[float, float] theta_range,
int Nphi,
Tuple[float, float] phi_range,
float exit_diameter,
float beam_divergence,
Optional[List[str]] column_format = None,
float range_noise_stddev = 0.0,
float angle_noise_stddev = 0.0,
float scan_tilt_roll = 0.0,
float scan_tilt_pitch = 0.0,
float scan_azimuth_offset = 0.0 )

Add a LiDAR scan to the point cloud.

Parameters
originScanner position (vec3 or 3-element list/tuple)
NthetaNumber of scan points in zenith direction
theta_rangeZenith angle range (min, max) in radians
NphiNumber of scan points in azimuthal direction
phi_rangeAzimuthal angle range (min, max) in radians
exit_diameterLaser beam exit diameter (meters)
beam_divergenceBeam divergence angle (radians)
column_formatOptional list of column-format labels. Non-standard labels (anything other than geometry/standard tokens like x/y/z/r/g/b/raydir) cause syntheticScan to sample that named primitive data from the struck primitive onto each hit's data map, retrievable via getHitData(). Defaults to None (empty format).

One label is special: "reflectivity_lidar" modulates each hit's "intensity" (intensity *= reflectivity) rather than being stored as its own hit-data key, so getHitData(i, "reflectivity_lidar") will NOT return it.

Parameters
range_noise_stddevStandard deviation of Gaussian range (along-beam) measurement noise in meters. Only affects synthetic-scan generation. Defaults to 0.0 (noise disabled).
angle_noise_stddevStandard deviation of Gaussian angular (beam-pointing) jitter in radians. Only affects synthetic-scan generation. Defaults to 0.0 (jitter disabled).
scan_tilt_rollGlobal scanner tilt roll angle in radians, modeling residual tilt of the scanner spin axis away from plumb (right-hand rotation about the body lateral axis). Only affects synthetic-scan generation. Defaults to 0.0 (level).
scan_tilt_pitchGlobal scanner tilt pitch angle in radians (right-hand rotation about the body forward/azimuth-zero axis). Only affects synthetic-scan generation. Defaults to 0.0 (level).
scan_azimuth_offsetGlobal scanner azimuth (heading) offset in radians, a right-hand rotation about the world +z axis applied on top of the azimuth sweep. Only affects synthetic-scan generation. Defaults to 0.0 (no offset).
Returns
Scan ID for referencing this scan
Example
>>> scan_id = lidar.addScan( ... origin=vec3(0, 0, 1), ... Ntheta=100, theta_range=(0, 1.57), ... Nphi=100, phi_range=(-3.14, 3.14), ... exit_diameter=0.01, beam_divergence=0.001, ... column_format=["my_scalar"] ... )

Definition at line 275 of file LiDARCloud.py.

◆ addScanMoving()

int pyhelios.LiDARCloud.LiDARCloud.addScanMoving ( self,
int Ntheta,
Tuple[float, float] theta_range,
int Nphi,
Tuple[float, float] phi_range,
float exit_diameter,
float beam_divergence,
List[float] traj_t,
List[Union[vec3, List[float], Tuple[float, float, float]]] traj_pos,
List[List[float]] traj_rot,
float pulse_rate_hz,
bool rot_is_quaternion = True,
Optional[Union[vec3, List[float], Tuple[float, float, float]]] lever_arm = None,
Optional[Union[vec3, List[float], Tuple[float, float, float]]] boresight_rpy = None,
Optional[List[str]] column_format = None,
float range_noise_stddev = 0.0,
float angle_noise_stddev = 0.0,
float t0 = 0.0 )

Add a moving-platform (mobile/airborne) raster LiDAR scan driven by a 6-DOF pose trajectory.

   Unlike :meth:`addScan`, the scanner pose changes during the sweep. For each pulse the synthetic-scan
   generator computes its acquisition time ``t = t0 + ordinal / pulse_rate_hz``, interpolates the platform
   pose at that time (linear position, SLERP orientation), and emits a per-pulse origin
   ``o = pos + R(q) * lever_arm`` and direction ``d = R(q) * R(boresight) * d_body``. Every resulting hit
   and miss stores its own origin (hit-data "origin_x"/"origin_y"/"origin_z", retrievable via
   :meth:`getHitOrigin`), timestamp ("timestamp"), and firing index ("pulse_id").

   The static tilt roll/pitch/azimuth fields are NOT applied in this mode; attitude comes entirely
   from the trajectory and the boresight misalignment. Because the pulses do not lie on a fixed
   theta-phi grid they cannot be triangulated, so leaf-area inversion must use
   :meth:`calculateLeafArea` with an explicit ``Gtheta``.
Parameters
NthetaNumber of scan points in zenith direction (raster grid rows)
theta_rangeZenith angle range (min, max) in radians
NphiNumber of scan points in azimuthal direction (raster grid columns)
phi_rangeAzimuthal angle range (min, max) in radians
exit_diameterLaser beam exit diameter (meters)
beam_divergenceBeam divergence angle (radians)
traj_tMonotonically increasing trajectory sample times in seconds (length M)
traj_posPlatform positions in world coordinates, one [x, y, z] (or vec3) per traj_t entry
traj_rotPlatform orientations, one entry per traj_t entry. Each entry is a length-4 quaternion (qx, qy, qz, qw, Hamilton body->world) when rot_is_quaternion is True, otherwise a length-3 roll/pitch/yaw Euler triple in radians (intrinsic Z-Y-X).
pulse_rate_hzPulse repetition rate in Hz (must be > 0)
rot_is_quaternionWhether traj_rot holds quaternions (default True) or Euler angles
lever_armSensor optical center in the platform body frame [x, y, z] meters (default origin)
boresight_rpyFixed sensor rotational misalignment [roll, pitch, yaw] radians (default 0)
column_formatOptional list of column-format labels (see addScan)
range_noise_stddevStd. dev. of Gaussian range noise in meters (default 0)
angle_noise_stddevStd. dev. of Gaussian angular jitter in radians (default 0)
t0Time of the first pulse in seconds (relative time; default 0)
Returns
Scan ID for referencing this scan

Definition at line 359 of file LiDARCloud.py.

◆ addScanMovingRaster()

int pyhelios.LiDARCloud.LiDARCloud.addScanMovingRaster ( self,
int Ntheta,
Tuple[float, float] theta_range,
int Nphi,
Tuple[float, float] phi_range,
float pulse_rate_hz,
List[float] traj_t,
List[Union[vec3, List[float], Tuple[float, float, float]]] traj_pos,
List[List[float]] traj_quat,
float exit_diameter = 0.0,
float beam_divergence = 0.0,
Optional[Union[vec3, List[float], Tuple[float, float, float]]] lever_arm = None,
Optional[Union[vec3, List[float], Tuple[float, float, float]]] boresight_rpy = None,
Optional[List[str]] column_format = None,
float range_noise_stddev = 0.0,
float angle_noise_stddev = 0.0,
float t0 = 0.0 )

Add a moving-platform raster scan: a fixed angular fan swept along a quaternion trajectory.

   High-level wrapper around :meth:`addScanMoving` for a non-spinning sensor on a moving platform.
   Specify the per-frame angular fan resolution plus the trajectory and PRF; Helios derives the
   per-pulse time sampling along the trajectory. Sets the scan's :class:`ScanMode` to ``MOVING_RASTER``.
Parameters
NthetaNumber of zenith samples in the angular fan
theta_rangeZenith angle range (min, max) in radians
NphiNumber of azimuth samples in the angular fan
phi_rangeAzimuthal angle range (min, max) in radians
pulse_rate_hzPulse repetition rate (PRF) in Hz (must be > 0)
traj_tMonotonically increasing trajectory sample times in seconds (length M)
traj_posPlatform positions in world coordinates, one [x, y, z] (or vec3) per traj_t entry
traj_quatPlatform orientation quaternions (qx, qy, qz, qw, Hamilton body->world), one per traj_t entry
exit_diameterLaser beam exit diameter (meters, default 0)
beam_divergenceBeam divergence angle (radians, default 0)
lever_armSensor optical center in the platform body frame [x, y, z] meters (default origin)
boresight_rpyFixed sensor rotational misalignment [roll, pitch, yaw] radians (default 0)
column_formatOptional list of column-format labels (default ["x", "y", "z"])
range_noise_stddevStd. dev. of Gaussian range noise in meters (default 0)
angle_noise_stddevStd. dev. of Gaussian angular jitter in radians (default 0)
t0Time of the first pulse in seconds (relative time; default 0)
Returns
Scan ID for referencing this scan

Definition at line 559 of file LiDARCloud.py.

◆ addScanRisley()

int pyhelios.LiDARCloud.LiDARCloud.addScanRisley ( self,
List[Union['RisleyPrism', List[float], Tuple[float, ...]]] prisms,
float refractive_index_air,
float pulse_rate_hz,
List[float] traj_t,
List[Union[vec3, List[float], Tuple[float, float, float]]] traj_pos,
List[List[float]] traj_rot,
bool rot_is_quaternion = True,
float exit_diameter = 0.0,
float beam_divergence = 0.0,
Optional[Union[vec3, List[float], Tuple[float, float, float]]] lever_arm = None,
Optional[Union[vec3, List[float], Tuple[float, float, float]]] boresight_rpy = None,
Optional[List[str]] column_format = None,
float range_noise_stddev = 0.0,
float angle_noise_stddev = 0.0,
float t0 = 0.0 )

Add a rotating-Risley-prism (Livox-style rosette) scan from physical instrument parameters.

   High-level entry point for a Livox rosette-pattern sensor (Mid-40/Mid-70/Avia). A single beam is
   refracted through a stack of continuously rotating wedge prisms, tracing a non-repetitive rosette
   that fills a circular field of view. The scan is stored as an Ntheta=1, Nphi=Npulses table, where
   Npulses = round(pulse_rate_hz * trajectory_duration). Sets the scan's :class:`ScanMode` to
   ``RISLEY_PRISM`` and :class:`ScanPattern` to ``RISLEY_PRISM``. Like a spinning scan it is always
   trajectory-driven; a stationary tripod capture is two coincident poses (same position and
   orientation) separated in time by the acquisition duration.
Parameters
prismsRotating wedge prisms in beam-traversal order (at least one; a Livox sensor uses two counter-rotating prisms). Each entry is a :class:RisleyPrism or a 4-element [wedge_angle, refractive_index, rotor_rate, phase] list/tuple (radians / unitless / rad-per-s / radians).
refractive_index_airRefractive index of the medium surrounding the prisms (typically 1.0)
pulse_rate_hzPulse repetition rate (PRF) in Hz (must be > 0)
traj_tMonotonically increasing trajectory sample times in seconds (length M)
traj_posPlatform positions in world coordinates, one [x, y, z] (or vec3) per traj_t entry
traj_rotPlatform orientations, one per traj_t entry. Length-4 quaternion (qx, qy, qz, qw, Hamilton body->world) when rot_is_quaternion is True, otherwise length-3 roll/pitch/yaw Euler triple in radians (intrinsic Z-Y-X).
rot_is_quaternionWhether traj_rot holds quaternions (default True) or Euler angles
exit_diameterLaser beam exit diameter (meters, default 0)
beam_divergenceBeam divergence angle (radians, default 0)
lever_armSensor optical center in the platform body frame [x, y, z] meters (default origin)
boresight_rpyFixed sensor rotational misalignment [roll, pitch, yaw] radians (default 0)
column_formatOptional list of column-format labels (default ["x", "y", "z"])
range_noise_stddevStd. dev. of Gaussian range noise in meters (default 0)
angle_noise_stddevStd. dev. of Gaussian angular jitter in radians (default 0)
t0Time of the first pulse in seconds (relative time; default 0)
Returns
Scan ID for referencing this scan

Definition at line 642 of file LiDARCloud.py.

◆ addScanSpinning()

int pyhelios.LiDARCloud.LiDARCloud.addScanSpinning ( self,
List[float] beam_elevation_angles,
float azimuth_step,
float pulse_rate_hz,
List[float] traj_t,
List[Union[vec3, List[float], Tuple[float, float, float]]] traj_pos,
List[List[float]] traj_rot,
bool rot_is_quaternion = True,
float exit_diameter = 0.0,
float beam_divergence = 0.0,
Optional[Union[vec3, List[float], Tuple[float, float, float]]] lever_arm = None,
Optional[Union[vec3, List[float], Tuple[float, float, float]]] boresight_rpy = None,
Optional[List[str]] column_format = None,
float range_noise_stddev = 0.0,
float angle_noise_stddev = 0.0,
float t0 = 0.0 )

Add a continuously-spinning multibeam scan from physical instrument parameters.

   High-level entry point for a rotating multi-channel sensor (Velodyne/Ouster/Hesai) on a moving
   (or stationary) platform. The azimuth grid, rotation rate, and revolution count are derived
   internally from the azimuth resolution, PRF, and trajectory duration; you never specify an
   azimuth range or step count. Sets the scan's :class:`ScanMode` to ``SPINNING``. For a stationary
   "spin in place" capture (a tripod), supply two coincident poses (same position and orientation)
   separated in time by the acquisition duration.
Parameters
beam_elevation_anglesPer-channel beam ELEVATION angles above the horizon, in radians (NOT zenith — elevation above the horizon, where zenith = pi/2 - elevation; this matches manufacturer spec sheets)
azimuth_stepAzimuth angular resolution in radians per firing step (must be > 0)
pulse_rate_hzPulse repetition rate (PRF) in Hz (must be > 0)
traj_tMonotonically increasing trajectory sample times in seconds (length M)
traj_posPlatform positions in world coordinates, one [x, y, z] (or vec3) per traj_t entry
traj_rotPlatform orientations, one per traj_t entry. Length-4 quaternion (qx, qy, qz, qw, Hamilton body->world) when rot_is_quaternion is True, otherwise length-3 roll/pitch/yaw Euler triple in radians (intrinsic Z-Y-X).
rot_is_quaternionWhether traj_rot holds quaternions (default True) or Euler angles
exit_diameterLaser beam exit diameter (meters, default 0)
beam_divergenceBeam divergence angle (radians, default 0)
lever_armSensor optical center in the platform body frame [x, y, z] meters (default origin)
boresight_rpyFixed sensor rotational misalignment [roll, pitch, yaw] radians (default 0)
column_formatOptional list of column-format labels (default ["x", "y", "z"])
range_noise_stddevStd. dev. of Gaussian range noise in meters (default 0)
angle_noise_stddevStd. dev. of Gaussian angular jitter in radians (default 0)
t0Time of the first pulse in seconds (relative time; default 0)
Returns
Scan ID for referencing this scan

Definition at line 483 of file LiDARCloud.py.

◆ addTrianglesToContext()

pyhelios.LiDARCloud.LiDARCloud.addTrianglesToContext ( self,
Context context )

Add triangulated mesh to Context as triangle primitives.

   Converts the triangulated point cloud mesh into Context triangle
   primitives that can be used for further analysis or visualization.

   .. warning::
       Raises once a run's triangles have been streamed to a sink registered with
       :meth:`setTriangulationSink` -- the mesh is released rather than stored, so there
       is nothing to add. Clear the sink before triangulating if you need the stored mesh.
Parameters
contextHelios Context instance
Example
>>> with Context() as context: ... with LiDARCloud() as lidar: ... lidar.loadXML("scan.xml") ... lidar.triangulateHitPoints(Lmax=0.5, max_aspect_ratio=5) ... lidar.addTrianglesToContext(context) ... print(f"Added {context.getPrimitiveCount()} triangles to context")

Definition at line 2410 of file LiDARCloud.py.

◆ calculateHitGridCell()

pyhelios.LiDARCloud.LiDARCloud.calculateHitGridCell ( self)

Calculate hit point grid cell assignments.

Definition at line 1795 of file LiDARCloud.py.

◆ calculateLeafArea()

pyhelios.LiDARCloud.LiDARCloud.calculateLeafArea ( self,
Context context,
Optional[int] min_voxel_hits = None,
Optional[float] element_width = None,
Optional[Union[float, List[float]]] Gtheta = None )

Calculate leaf area for each grid cell.

   Requires triangulation to have been performed first, UNLESS a ``Gtheta`` is supplied
   (see below).

   .. note::
       The cloud must contain misses (transmitted beams that returned nothing) — the
       inversion fails fast without them. Misses are produced by
       ``syntheticScan(..., record_misses=True)`` (the default) or by
       :meth:`gapfillMisses`. Use :meth:`hasMisses` to check.

   .. note::
       Returns are grouped into beams by their shared ``timestamp``, so timestamps must
       identify one pulse each. The inversion rejects a scan whose returns sharing a
       timestamp point in different directions (timestamps rounded on export, e.g. to
       32-bit floats), and one whose per-pulse data contradicts the grouping (two returns
       of a pulse with the same ``target_index``, or more returns than its
       ``target_count``). The error names the scan and how many beams are affected.
Parameters
contextHelios Context instance
min_voxel_hitsOptional minimum number of hits required per voxel
element_widthOptional characteristic vegetation element width (meters). When provided, per-voxel sampling uncertainty (Pimont et al. 2018) is computed alongside the leaf-area estimate and becomes available via :meth:getCellLADVariance, :meth:getCellLeafAreaConfidenceInterval, and :meth:getGroupLADConfidenceInterval. element_width <= 0 yields a sampling-only variance.
GthetaOptional caller-supplied mean leaf-projection coefficient G(theta), in (0,1] (0.5 = spherical/random leaf-angle distribution). May be a single scalar (broadcast to every voxel) or a sequence of one value per grid cell in grid-cell order — the latter supports a spatially-varying (e.g. vertically-varying) leaf-angle distribution. When provided, leaf area is computed via a beam-based inversion that uses each hit's per-pulse beam origin and does NOT require triangulation — the only supported path for moving-platform scans (see :meth:addScanMoving). Requires both min_voxel_hits and element_width to also be specified.

A single float applies one G(theta) to every voxel. A sequence supplies one G(theta) per grid cell, in grid-cell order (the order of :meth:getCellCenter), for a canopy whose leaf-angle distribution varies in space, typically with height. Its length must equal :meth:getGridCellCount and every value must be in (0,1]. The per-cell form requires helios-core v1.3.85.

Exceptions
TypeErrorIf ``context`` is not a Context
ValueErrorIf the argument combination is invalid, a G(theta) value is outside (0,1], or a per-cell sequence is empty or does not match the grid cell count
HeliosErrorIf the native inversion fails (for example, the cloud has no misses)
RuntimeErrorIf a per-cell ``Gtheta`` is given and the native library predates helios-core v1.3.85
Example
>>> from pyhelios import Context, LiDARCloud >>> with Context() as context: ... with LiDARCloud() as lidar: ... # ... load data, add grid, triangulate ... ... lidar.calculateLeafArea(context)

Definition at line 2260 of file LiDARCloud.py.

◆ calculateLeafAreaBlock()

None pyhelios.LiDARCloud.LiDARCloud.calculateLeafAreaBlock ( self,
Context context,
ijk_min,
ijk_max,
int min_voxel_hits,
float element_width,
Optional[Union[float, List[float]]] Gtheta = None )

Calculate leaf area for only a block of the voxel grid.

   The block form of :meth:`calculateLeafArea`, for inverting a large grid a tile at a
   time. Requires a regular lattice grid (as built by :meth:`addGrid`); use
   :meth:`getGridGlobalCount` for the lattice dimensions and :meth:`getCellGlobalIJK` to
   map a cell index to its lattice coordinate.
Parameters
contextHelios Context instance
ijk_minLattice index (i, j, k) of the block's first cell
ijk_maxLattice index (i, j, k) of the block's last cell, inclusive
min_voxel_hitsMinimum number of beams that must have entered a voxel
element_widthCharacteristic vegetation element width (m); <= 0 yields a sampling-only variance
GthetaOptional caller-supplied G(theta) in (0,1]. A single float applies one value to every voxel; a sequence supplies one value per grid cell (the whole grid, not just the block) in grid-cell order. When omitted, triangulation supplies G(theta) and must have been run.
Exceptions
TypeErrorIf ``context`` is not a Context
ValueErrorIf a lattice index is not 3 elements, or a G(theta) sequence is empty
HeliosErrorIf the grid is not a regular lattice, the block is out of range, or the inversion fails (for example, the cloud has no misses)
RuntimeErrorIf the native library predates helios-core v1.3.86

Definition at line 2987 of file LiDARCloud.py.

◆ calculateSyntheticGtheta()

pyhelios.LiDARCloud.LiDARCloud.calculateSyntheticGtheta ( self,
Context context )

Calculate synthetic G(theta) (for validation of synthetic scans).

   Uses exact primitive geometry to calculate G(theta), useful for
   validating synthetic scan accuracy.
Parameters
contextHelios Context instance containing primitive geometry

Definition at line 2342 of file LiDARCloud.py.

◆ calculateSyntheticLeafArea()

pyhelios.LiDARCloud.LiDARCloud.calculateSyntheticLeafArea ( self,
Context context )

Calculate synthetic leaf area (for validation of synthetic scans).

   Uses exact primitive geometry to calculate leaf area, useful for
   validating synthetic scan accuracy.
Parameters
contextHelios Context instance containing primitive geometry

Definition at line 2327 of file LiDARCloud.py.

◆ coordinateRotation()

pyhelios.LiDARCloud.LiDARCloud.coordinateRotation ( self,
Union[SphericalCoord, List[float], Tuple[float, float]] rotation )

Rotate all hit points by spherical rotation angles.

Parameters
rotationRotation angles (SphericalCoord or 2-3 element list)

Definition at line 1359 of file LiDARCloud.py.

◆ coordinateShift()

pyhelios.LiDARCloud.LiDARCloud.coordinateShift ( self,
Union[vec3, List[float], Tuple[float, float, float]] shift )

Translate all hit points by a shift vector.

Parameters
shiftTranslation vector (vec3 or 3-element list)

Definition at line 1341 of file LiDARCloud.py.

◆ createHitDataColumn()

None pyhelios.LiDARCloud.LiDARCloud.createHitDataColumn ( self,
str label,
HitDataType column_type )

Create a per-hit scalar-data column with an explicit storage type.

   Call this *before* adding data carrying ``label`` to fix the column's storage type
   instead of letting it be inferred from the label name. An explicitly typed column is
never   an INT32 column rejects a value that is not a 32-bit integer, and a
   FLOAT32 column stores values at float precision.
Parameters
labelLabel of the data value (e.g. "intensity")
column_typeA :class:HitDataType member
Exceptions
TypeErrorIf ``label`` is not a str or ``column_type`` is not a HitDataType
ValueErrorIf ``label`` is empty
HeliosErrorIf the column already exists with a different type
RuntimeErrorIf the native library predates helios-core v1.3.86

Definition at line 2510 of file LiDARCloud.py.

◆ deleteHitData()

None pyhelios.LiDARCloud.LiDARCloud.deleteHitData ( self,
str label )

Remove a per-hit scalar-data column from every hit in the cloud.

   Use this to discard hit data that is wrong and that later processing would otherwise
trust   for example timestamps rounded more coarsely than the scanner fires, which
   can then no longer group returns into pulses, or a ``target_index`` rewritten on
   export. Every other column keeps its values.

   Misses synthesized by :meth:`gapfillMisses` report some labels themselves. Removing
   ``"timestamp"`` or ``"gapfillMisses_code"`` also removes it from those misses. The
   labels they need to exist (``"is_miss"``, ``"row"``, ``"column"``, ``"nRaysHit"``,
   and ``"origin_x"``/``"origin_y"``/``"origin_z"`` on a moving scan) cannot be removed
   while any scan has synthesized misses.

   A static raster scan whose timestamps were rounded can be gap-filled by removing
   them (and ``"target_index"`` for multi-return data) first, so that
   :meth:`gapfillMisses` places the returns on the declared raster by direction.
Parameters
labelLabel of the data value
Exceptions
TypeErrorIf ``label`` is not a str
ValueErrorIf ``label`` is empty
HeliosErrorIf no column exists for the label, or the label is one that synthesized misses depend on
RuntimeErrorIf the native library predates helios-core v1.3.89

Definition at line 3124 of file LiDARCloud.py.

◆ deleteHitPoint()

pyhelios.LiDARCloud.LiDARCloud.deleteHitPoint ( self,
int index )

Delete a hit point from the cloud.

Definition at line 1280 of file LiDARCloud.py.

◆ deleteHitPoints()

None pyhelios.LiDARCloud.LiDARCloud.deleteHitPoints ( self,
int first,
int count )

Delete a contiguous range of hit points, preserving the order of the rest.

   Removes hits ``[first, first+count)``. Unlike :meth:`deleteHitPoint`, which fills the
   freed slot with the last hit, this keeps every surviving hit in its relative order --
   so draining the tail of the cloud (the release step of a streaming
   :meth:`syntheticScan`, see :meth:`setSyntheticScanHitSink`) costs O(count) and leaves
   earlier indices unchanged.
Parameters
firstIndex of the first hit to delete
countNumber of hits to delete
Exceptions
ValueErrorIf ``first`` or ``count`` is negative
HeliosErrorIf the range extends past the end of the cloud
RuntimeErrorIf the native library predates helios-core v1.3.86

Definition at line 2683 of file LiDARCloud.py.

◆ disableCDGPUAcceleration()

pyhelios.LiDARCloud.LiDARCloud.disableCDGPUAcceleration ( self)

Disable GPU acceleration (use CPU ray tracing)

Definition at line 2459 of file LiDARCloud.py.

◆ disableMessages()

pyhelios.LiDARCloud.LiDARCloud.disableMessages ( self)

Disable console output messages.

Definition at line 1531 of file LiDARCloud.py.

◆ distanceFilter()

pyhelios.LiDARCloud.LiDARCloud.distanceFilter ( self,
float maxdistance )

Filter hit points by maximum distance from scanne.

Definition at line 1469 of file LiDARCloud.py.

◆ doesHitDataExist()

bool pyhelios.LiDARCloud.LiDARCloud.doesHitDataExist ( self,
int index,
str label )

Check whether a named scalar data value exists for a hit point.

   Per-hit data computed by syntheticScan includes 'intensity', 'distance',
   'timestamp', 'target_index', 'target_count', 'deviation', 'nRaysHit', plus any
   primitive-data labels listed in the scan's column_format.

Definition at line 1159 of file LiDARCloud.py.

◆ enableCDGPUAcceleration()

pyhelios.LiDARCloud.LiDARCloud.enableCDGPUAcceleration ( self)

Enable GPU acceleration for collision detection ray tracing.

Definition at line 2454 of file LiDARCloud.py.

◆ enableMessages()

pyhelios.LiDARCloud.LiDARCloud.enableMessages ( self)

Enable console output messages.

Definition at line 1535 of file LiDARCloud.py.

◆ estimateHitPointMemory()

int pyhelios.LiDARCloud.LiDARCloud.estimateHitPointMemory ( self,
int hit_count )

Estimate the resident memory a cloud of hit_count points will occupy, in bytes.

   Each stored point costs the size of a hit point plus, for every scalar-data label
   the cloud carries, one double of value and one byte of presence -- the columnar
   store is dense, so every label costs on every point. Excludes virtualized misses
   and the transient of growing the arrays; see :meth:`reserveHitPoints` for that.

   Most accurate once at least one point exists, since it reads the labels created
   so far.
Parameters
hit_countNumber of hit points to estimate for
Returns
Estimated resident bytes
Exceptions
RuntimeErrorIf the native library predates helios-core v1.3.84

Definition at line 2002 of file LiDARCloud.py.

◆ exportGtheta()

pyhelios.LiDARCloud.LiDARCloud.exportGtheta ( self,
str filename )

Export G(theta) values for each grid cell to file.

Definition at line 2383 of file LiDARCloud.py.

◆ exportLeafAreaDensities()

pyhelios.LiDARCloud.LiDARCloud.exportLeafAreaDensities ( self,
str filename )

Export leaf area densities for each grid cell to file.

Definition at line 2377 of file LiDARCloud.py.

◆ exportLeafAreas()

pyhelios.LiDARCloud.LiDARCloud.exportLeafAreas ( self,
str filename )

Export leaf areas for each grid cell to file.

Definition at line 2371 of file LiDARCloud.py.

◆ exportLeafAreaUncertainty()

pyhelios.LiDARCloud.LiDARCloud.exportLeafAreaUncertainty ( self,
str filename )

Export per-voxel leaf-area sampling uncertainty to a self-describing ASCII file.

   The file has a ``#``-prefixed header and one row per grid cell:
   ``cell_index leaf_area beam_count I_rdi LAD_std_error ci_valid``. Requires that
   :meth:`calculateLeafArea` has been run with an ``element_width`` (the uncertainty
   overload).

Definition at line 1506 of file LiDARCloud.py.

◆ exportPointCloud()

pyhelios.LiDARCloud.LiDARCloud.exportPointCloud ( self,
str filename,
bool write_header = True )

Export point cloud to ASCII file.

Parameters
filenameOutput file path.
write_headerIf True (default), prepend a #-prefixed comment line listing the column field names (CloudCompare convention). The loader skips #-prefixed lines, so headered files round-trip through loadXML(). Set False for a bare data file.

Definition at line 1494 of file LiDARCloud.py.

◆ exportScans()

pyhelios.LiDARCloud.LiDARCloud.exportScans ( self,
str filename )

Export all scans to an XML metadata file plus one ASCII data file per scan.

Parameters
filenamePath of the XML metadata file to write (e.g. "output/scans.xml"). One ASCII data file is auto-generated per scan, named by stripping the XML extension and appending "_<scanID>.xyz" (e.g. "output/scans_0.xyz"). The resulting XML can be re-loaded with loadXML() from the same working directory.

Definition at line 1519 of file LiDARCloud.py.

◆ exportTriangleAreas()

pyhelios.LiDARCloud.LiDARCloud.exportTriangleAreas ( self,
str filename )

Export triangle areas to file.

   .. warning::
       Raises once a run's triangles have been streamed to a sink registered with
       :meth:`setTriangulationSink` -- the mesh is released rather than stored.

Definition at line 2365 of file LiDARCloud.py.

◆ exportTriangleNormals()

pyhelios.LiDARCloud.LiDARCloud.exportTriangleNormals ( self,
str filename )

Export triangle normal vectors to file.

   .. warning::
       Raises once a run's triangles have been streamed to a sink registered with
       :meth:`setTriangulationSink` -- the mesh is released rather than stored.

Definition at line 2354 of file LiDARCloud.py.

◆ firstHitFilter()

pyhelios.LiDARCloud.LiDARCloud.firstHitFilter ( self)

Keep only first return hit points.

Definition at line 1478 of file LiDARCloud.py.

◆ gapfillMisses()

pyhelios.LiDARCloud.LiDARCloud.gapfillMisses ( self)

Gapfill sky/miss points where rays didn't hit geometry.

   Important for accurate leaf area calculations with real LiDAR data.
   Should be called before triangulation when processing real data.

   Each scan is reconstructed from its returns' ``row``/``column`` data if present,
   otherwise from their ``timestamp`` data. A static raster scan with neither is placed
   on its declared raster by direction (through the scan's tilt and azimuth offset),
   after checking that the returns lie on that raster; moving-platform, spinning
   multibeam and Risley-prism scans still need timestamps or row/column data. Raises
   an error if a scan's timestamps were rounded more coarsely than the scanner fires
   (returns sharing a timestamp point in different directions).

   Misses synthesized here are stored in virtualized form -- as a per-cell occupancy
   bit plus a scan-wide angular model rather than as stored points -- so they cost no
   per-point storage. They are counted by :meth:`getHitCount` and readable through
   every accessor regardless. See :meth:`hasVirtualMisses` and
   :meth:`getVirtualMissCount`.
Note
Reading the whole cloud back afterwards should go through the bulk accessors (:meth:getHitsXYZRGB, :meth:getHitScanIDArray, :meth:getHitDataArray), which read virtualized misses in one pass. A Python loop over the per-index getters costs O(Nphi) on each such point.

Definition at line 1824 of file LiDARCloud.py.

◆ gapfillMissesCount()

int pyhelios.LiDARCloud.LiDARCloud.gapfillMissesCount ( self,
Optional[int] scanID = None,
bool gapfill_grid_only = False,
bool add_flags = False )

Gapfill missing points and return only how many were added.

   Identical to :meth:`gapfillMisses` except that the count is returned instead of the
   filled positions, which for a fine scan grid is a large allocation most callers
   discard.
Parameters
scanIDScan to gapfill. None (the default) gapfills every scan, in which case gapfill_grid_only and add_flags are not used.
gapfill_grid_onlyFill only within the voxel grid's bounding box
add_flagsAdd gapfillMisses_code as hit point data (0=original, 1=gapfilled)
Returns
Number of missing points added
Exceptions
RuntimeErrorIf the native library predates helios-core v1.3.84

Definition at line 1846 of file LiDARCloud.py.

◆ getCellBeamCount()

int pyhelios.LiDARCloud.LiDARCloud.getCellBeamCount ( self,
int index )

Get the beam count N that entered a grid cell during the leaf-area inversion.

   Returns -1 if :meth:`calculateLeafArea` has not been run for this cell.

Definition at line 1728 of file LiDARCloud.py.

◆ getCellCenter()

vec3 pyhelios.LiDARCloud.LiDARCloud.getCellCenter ( self,
int index )

Get the true world-space center position of a grid cell.

   For a grid created with a non-zero azimuthal ``rotation``, this is the lattice
   center rotated about the grid anchor (about +z), so it lies in the same rotated
   world frame as the hit points, scan origins, and grid bounding box. For an
   un-rotated grid it is simply the lattice center.

Definition at line 1673 of file LiDARCloud.py.

◆ getCellCenterUnrotated()

vec3 pyhelios.LiDARCloud.LiDARCloud.getCellCenterUnrotated ( self,
int index )

Get the UNROTATED (axis-aligned lattice) center position of a grid cell.

   Companion to :meth:`getCellCenter`, which applies the grid's azimuthal rotation.
   This returns the center on the axis-aligned lattice instead; for an un-rotated
   grid the two are identical.

   Use this when the caller applies the grid rotation itself (e.g. rotating a whole
   voxel group about the grid center for display) — passing the rotated center to
   such code rotates the lattice twice.

Definition at line 1689 of file LiDARCloud.py.

◆ getCellGlobalIJK()

Tuple[int, int, int] pyhelios.LiDARCloud.LiDARCloud.getCellGlobalIJK ( self,
int index )

Lattice index (i, j, k) of a grid cell along x, y and z.

   For a grid built by :meth:`addGrid` this is the cell's position in the
   ``ndiv.x`` by ``ndiv.y`` by ``ndiv.z`` lattice; cells are stored in the order
   ``k*ny*nx + j*nx + i``. It is the coordinate :meth:`calculateLeafAreaBlock` takes.
Parameters
indexIndex of a grid cell
Returns
(i, j, k) tuple
Exceptions
ValueErrorIf ``index`` is negative
HeliosErrorIf ``index`` is out of range
RuntimeErrorIf the native library predates helios-core v1.3.86

Definition at line 3035 of file LiDARCloud.py.

◆ getCellGtheta()

float pyhelios.LiDARCloud.LiDARCloud.getCellGtheta ( self,
int index )

Get G(theta) value for a grid cell.

Definition at line 1783 of file LiDARCloud.py.

◆ getCellLADVariance()

float pyhelios.LiDARCloud.LiDARCloud.getCellLADVariance ( self,
int index )

Get the per-voxel LAD sampling variance for a grid cell.

   Returns -1 if uncertainty has not been computed (call :meth:`calculateLeafArea`
   with an ``element_width``).

Definition at line 1750 of file LiDARCloud.py.

◆ getCellLeafArea()

float pyhelios.LiDARCloud.LiDARCloud.getCellLeafArea ( self,
int index )

Get leaf area of a grid cell (m²)

Definition at line 1713 of file LiDARCloud.py.

◆ getCellLeafAreaConfidenceInterval()

pyhelios.LiDARCloud.LiDARCloud.getCellLeafAreaConfidenceInterval ( self,
int index,
float confidence_level = 0.95 )

Get the leaf-area confidence interval for a single grid cell.

   Returns a ``(valid, lower, upper)`` tuple. ``valid`` is False when the interval is
   gated out by the Pimont validity envelope (single-voxel intervals are often
   untrustworthy; prefer :meth:`getGroupLADConfidenceInterval`). Requires
   :meth:`calculateLeafArea` to have been run with an ``element_width``.

Definition at line 1762 of file LiDARCloud.py.

◆ getCellLeafAreaDensity()

float pyhelios.LiDARCloud.LiDARCloud.getCellLeafAreaDensity ( self,
int index )

Get leaf area density of a grid cell (m²/m³)

Definition at line 1719 of file LiDARCloud.py.

◆ getCellMeanPathLength()

float pyhelios.LiDARCloud.LiDARCloud.getCellMeanPathLength ( self,
int index )

Get the mean beam path length (m) through a grid cell.

Definition at line 1740 of file LiDARCloud.py.

◆ getCellRelativeDensityIndex()

float pyhelios.LiDARCloud.LiDARCloud.getCellRelativeDensityIndex ( self,
int index )

Get the relative density index (I_rdi) for a grid cell.

Definition at line 1734 of file LiDARCloud.py.

◆ getCellRotation()

float pyhelios.LiDARCloud.LiDARCloud.getCellRotation ( self,
int index )

Get the azimuthal rotation of a grid cell about the z-axis, in degrees.

   The units match the ``rotation`` argument of :meth:`addGrid`. Note that
   :meth:`addGridCell` takes its rotation in radians.

Definition at line 1707 of file LiDARCloud.py.

◆ getCellSize()

vec3 pyhelios.LiDARCloud.LiDARCloud.getCellSize ( self,
int index )

Get size of a grid cell.

Definition at line 1696 of file LiDARCloud.py.

◆ getCroppedReturnStats()

dict pyhelios.LiDARCloud.LiDARCloud.getCroppedReturnStats ( self)

Returns counts of the removed returns that the last :meth:calculateLeafArea call inferred from target_count.

   A pulse's returns are ordered by range and a beam crosses the (convex) voxel grid
   in one contiguous segment. So when a cloud has had returns removed -- cropped to the
   grid, say -- but its surviving returns still carry the per-pulse ``target_index`` and
   ``target_count`` the scanner wrote, the inversion places each missing return from the
   surviving indices alone: indices below the smallest surviving index were before the
   first surviving return, indices above the largest were beyond the last one, and only
   indices between two surviving returns cannot be placed. Under the crop-to-grid
   assumption the second group is counted as transmitted through every voxel the beam
   pierces, so a cropped beam keeps the transmittance its full record implied; the third
   is left out and reported as ambiguous. A stand-in miss (a return flagged ``is_miss``
   sharing the pulse's timestamp) is ignored for counting when the inference applies.
Returns
dict with integer counts:
  • beams_with_hidden_returns – pulses with at least one return recovered
  • hidden_before – removed returns placed before the first surviving return (expected after any near-field culling; changes nothing)
  • hidden_after – removed returns placed beyond the last surviving return (counted as transmitted)
  • hidden_ambiguous – removed returns between two surviving returns (not counted; a non-zero value means the cloud was cropped INSIDE the grid)
  • beams_ambiguous – pulses carrying at least one ambiguous removed return
  • standins_ignored – stand-in misses left out because the count covered them

All zero before the first inversion and for a cloud whose pulses are complete.

Exceptions
RuntimeErrorIf the native library predates this feature

Definition at line 1902 of file LiDARCloud.py.

◆ getDefaultMaxHitPoints()

int pyhelios.LiDARCloud.LiDARCloud.getDefaultMaxHitPoints ( )
static

Default cap on the number of stored hit points in a cloud (100 million).

Exceptions
RuntimeErrorIf the native library predates helios-core v1.3.84

Definition at line 2040 of file LiDARCloud.py.

◆ getExactPathLengths()

bool pyhelios.LiDARCloud.LiDARCloud.getExactPathLengths ( self)

Whether path lengths are accumulated exactly.

Exceptions
RuntimeErrorIf the native library predates helios-core v1.3.84

Definition at line 2088 of file LiDARCloud.py.

◆ getGridCellCount()

int pyhelios.LiDARCloud.LiDARCloud.getGridCellCount ( self)

Get total number of grid cells.

Definition at line 1663 of file LiDARCloud.py.

◆ getGridGlobalCount()

Tuple[int, int, int] pyhelios.LiDARCloud.LiDARCloud.getGridGlobalCount ( self)

Number of lattice cells along x, y and z (the ndiv passed to :meth:addGrid).

Returns
(nx, ny, nz) tuple
Exceptions
HeliosErrorIf the grid is empty or its cells do not form a regular lattice
RuntimeErrorIf the native library predates helios-core v1.3.86

Definition at line 3050 of file LiDARCloud.py.

◆ getGroupLADConfidenceInterval()

pyhelios.LiDARCloud.LiDARCloud.getGroupLADConfidenceInterval ( self,
List[int] indices,
float confidence_level = 0.95 )

Get the group-scale LAD confidence interval over a set of grid cells (recommended).

   Returns a ``(valid, mean_lad, lower, upper)`` tuple (Pimont et al. 2018, Eq. 39,
   assuming voxel independence). Requires :meth:`calculateLeafArea` to have been run
   with an ``element_width``.

Definition at line 1774 of file LiDARCloud.py.

◆ getHitColor()

RGBcolor pyhelios.LiDARCloud.LiDARCloud.getHitColor ( self,
int index )

Get color of a hit point.

Definition at line 1141 of file LiDARCloud.py.

◆ getHitCount()

int pyhelios.LiDARCloud.LiDARCloud.getHitCount ( self)

Get total number of hit points in cloud.

Definition at line 1111 of file LiDARCloud.py.

◆ getHitData()

float pyhelios.LiDARCloud.LiDARCloud.getHitData ( self,
int index,
str label )

Get a named scalar data value for a hit point.

   Raises HeliosError if the label does not exist for this hit; guard with
   doesHitDataExist() when unsure.

Definition at line 1169 of file LiDARCloud.py.

◆ getHitDataAll()

List[float] pyhelios.LiDARCloud.LiDARCloud.getHitDataAll ( self,
str label )

Bulk-export a named scalar data value for all hits in a single FFI call.

   Returns a list of length getHitCount(); entries are NaN where the label is
   absent for that hit. Much faster than looping getHitData() for large clouds.
Note
values are returned at float32 precision (vs. getHitData(), which returns full float64). Use getHitData() per-hit if full precision is required.

Definition at line 1182 of file LiDARCloud.py.

◆ getHitDataArray()

pyhelios.LiDARCloud.LiDARCloud.getHitDataArray ( self,
str label )

Bulk-export a named scalar field as an (getHitCount(),) float32 array, NaN where the label is absent for a hit.

Definition at line 1223 of file LiDARCloud.py.

◆ getHitDataColumn()

List[float] pyhelios.LiDARCloud.LiDARCloud.getHitDataColumn ( self,
str label,
float absent_value = -9999.0 )

Bulk-export a named scalar column.

   Faster than :meth:`getHitDataAll` for whole-field reads, and returns full float64
   precision. Entries are ``absent_value`` where the label is absent for a hit. Returns a list
   of length getHitCount().

Definition at line 1236 of file LiDARCloud.py.

◆ getHitDataColumnArray()

pyhelios.LiDARCloud.LiDARCloud.getHitDataColumnArray ( self,
str label,
float absent_value = -9999.0 )

Bulk-export a named scalar column as an (getHitCount(),) float64 numpy array via the columnar path (absent_value where the label is absent for a hit).

Definition at line 1255 of file LiDARCloud.py.

◆ getHitDataColumnFloat32()

List[float] pyhelios.LiDARCloud.LiDARCloud.getHitDataColumnFloat32 ( self,
str label,
float absent_value = -9999.0 )

Bulk-export a named scalar column as 32-bit floats.

   Reads a ``FLOAT32`` column without widening it to 8 bytes per hit; a ``FLOAT64`` or
   ``INT32`` column is converted element-wise. See :meth:`getHitDataColumn` for the
   double-precision counterpart.
Parameters
labelLabel of the data value
absent_valueValue reported for hits that lack the label
Returns
List of floats of length :meth:getHitCount
Exceptions
TypeErrorIf ``label`` is not a str
ValueErrorIf ``label`` is empty
RuntimeErrorIf the native library predates helios-core v1.3.86

Definition at line 2562 of file LiDARCloud.py.

◆ getHitDataColumnFloat32Array()

pyhelios.LiDARCloud.LiDARCloud.getHitDataColumnFloat32Array ( self,
str label,
float absent_value = -9999.0 )

Bulk-export a named scalar column as a (getHitCount(),) float32 numpy array.

   See :meth:`getHitDataColumnFloat32`.

Definition at line 2574 of file LiDARCloud.py.

◆ getHitDataColumnIndex()

int pyhelios.LiDARCloud.LiDARCloud.getHitDataColumnIndex ( self,
str label )

Get the internal column slot index for a hit-data label.

   Per-hit scalar data is stored column-wise; this resolves a label to its column slot for
   repeated bulk access without re-resolving the label by string. Returns -1 if the label has
   never been set on any hit.

Definition at line 1248 of file LiDARCloud.py.

◆ getHitDataColumnInt32()

List[int] pyhelios.LiDARCloud.LiDARCloud.getHitDataColumnInt32 ( self,
str label,
int absent_value = -9999 )

Bulk-export a named scalar column as 32-bit signed integers.

   Reads an ``INT32`` column without widening it.
Parameters
labelLabel of the data value
absent_valueValue reported for hits that lack the label
Returns
List of ints of length :meth:getHitCount
Exceptions
TypeErrorIf ``label`` is not a str
ValueErrorIf ``label`` is empty
HeliosErrorIf any value is not an integer in the 32-bit range (a fractional value, a NaN, or a timestamp) – read such a label with :meth:getHitDataColumn instead
RuntimeErrorIf the native library predates helios-core v1.3.86

Definition at line 2602 of file LiDARCloud.py.

◆ getHitDataColumnInt32Array()

pyhelios.LiDARCloud.LiDARCloud.getHitDataColumnInt32Array ( self,
str label,
int absent_value = -9999 )

Bulk-export a named scalar column as a (getHitCount(),) int32 numpy array.

   See :meth:`getHitDataColumnInt32`.

Definition at line 2614 of file LiDARCloud.py.

◆ getHitDataType()

HitDataType pyhelios.LiDARCloud.LiDARCloud.getHitDataType ( self,
str label )

Storage type of an existing per-hit scalar-data column.

   A column typed implicitly may since have widened to ``FLOAT64``.
Parameters
labelLabel of the data value
Returns
The column's current :class:HitDataType
Exceptions
TypeErrorIf ``label`` is not a str
ValueErrorIf ``label`` is empty
HeliosErrorIf no column exists for the label (use :meth:getHitDataColumnIndex to test for existence without raising)
RuntimeErrorIf the native library predates helios-core v1.3.86

Definition at line 2536 of file LiDARCloud.py.

◆ getHitMissArray()

pyhelios.LiDARCloud.LiDARCloud.getHitMissArray ( self)

Bulk-export the miss flag of every hit as an (getHitCount(),) int32 array (1 == sky/miss, 0 == real surface return).

Definition at line 1272 of file LiDARCloud.py.

◆ getHitOrigin()

vec3 pyhelios.LiDARCloud.LiDARCloud.getHitOrigin ( self,
int index )

Get the (x,y,z) beam-emission origin of a hit point.

   For moving-platform scans (see :meth:`addScanMoving`) this is the per-pulse emission origin
   recorded on the hit; for static scans it falls back to the single scan origin of the hit's scan.

Definition at line 1126 of file LiDARCloud.py.

◆ getHitPointCapacity()

int pyhelios.LiDARCloud.LiDARCloud.getHitPointCapacity ( self)

Number of hit points the cloud can hold before its arrays reallocate.

   The counterpart of :meth:`reserveHitPoints`: use it to confirm a reservation took
   effect, or to see how much headroom remains before the next growth reallocation.
Returns
Current hit-point capacity
Exceptions
RuntimeErrorIf the native library predates helios-core v1.3.86

Definition at line 3065 of file LiDARCloud.py.

◆ getHitRaydir()

SphericalCoord pyhelios.LiDARCloud.LiDARCloud.getHitRaydir ( self,
int index )

Get ray direction of a hit point.

Definition at line 1133 of file LiDARCloud.py.

◆ getHitScanID()

int pyhelios.LiDARCloud.LiDARCloud.getHitScanID ( self,
int index )

Get the scan ID a hit point belongs to.

Definition at line 1148 of file LiDARCloud.py.

◆ getHitScanIDArray()

pyhelios.LiDARCloud.LiDARCloud.getHitScanIDArray ( self)

Bulk-export the scan ID of every hit as an (getHitCount(),) int32 array.

Definition at line 1263 of file LiDARCloud.py.

◆ getHitScanIDColumn()

pyhelios.LiDARCloud.LiDARCloud.getHitScanIDColumn ( self)

Read every hit's scan ID in index order in one pass.

   See :meth:`getHitXYZColumn` for why this is preferred over a per-index loop.
Returns
List of scan indices, one per hit
Exceptions
RuntimeErrorIf the native library predates helios-core v1.3.84

Definition at line 1979 of file LiDARCloud.py.

◆ getHitsXYZRGB()

Tuple[List[vec3], List[RGBcolor]] pyhelios.LiDARCloud.LiDARCloud.getHitsXYZRGB ( self)

Bulk-export coordinates and colors for all hits in a single FFI call.

   Returns (positions, colors) where positions is a list of vec3 and colors a list
   of RGBcolor, each of length getHitCount(). Much faster than looping
   getHitXYZ()/getHitColor() for large clouds.

Definition at line 1194 of file LiDARCloud.py.

◆ getHitsXYZRGBArrays()

pyhelios.LiDARCloud.LiDARCloud.getHitsXYZRGBArrays ( self)

Bulk-export hit coordinates + colors as numpy arrays.

   Returns (xyz, rgb), each (getHitCount(), 3) float32. Empty (0,3) arrays
   when there are no hits.

Definition at line 1214 of file LiDARCloud.py.

◆ getHitXYZ()

vec3 pyhelios.LiDARCloud.LiDARCloud.getHitXYZ ( self,
int index )

Get coordinates of a hit point.

Definition at line 1115 of file LiDARCloud.py.

◆ getHitXYZColumn()

pyhelios.LiDARCloud.LiDARCloud.getHitXYZColumn ( self)

Read every hit's position in index order in one pass.

   Costs O(1) per hit even for virtualized gap-filled misses, which the per-index
   accessors resolve in O(Nphi). Prefer this to a Python loop over
   :meth:`getHitXYZ` whenever the whole cloud is being read.
Returns
List of (x, y, z) tuples, one per hit
Exceptions
RuntimeErrorIf the native library predates helios-core v1.3.84

Definition at line 1965 of file LiDARCloud.py.

◆ getMaxHitPoints()

int pyhelios.LiDARCloud.LiDARCloud.getMaxHitPoints ( self)

Current cap on stored hit points, or 0 if the check is disabled.

Exceptions
RuntimeErrorIf the native library predates helios-core v1.3.84

Definition at line 2030 of file LiDARCloud.py.

◆ getMissDistance()

float pyhelios.LiDARCloud.LiDARCloud.getMissDistance ( )
static

Return the LIDAR_MISS_DISTANCE constant (meters): the distance at which a miss point is placed along its beam.

Definition at line 1332 of file LiDARCloud.py.

◆ getNominalScanGridCell()

Tuple[int, int] pyhelios.LiDARCloud.LiDARCloud.getNominalScanGridCell ( self,
int scanID,
vec3 point )

Scan-grid cell (row, column) a point lies in, from the scan's declared raster.

   The inverse of the raster the synthetic scanner fires: the point's direction from
   the scan origin is taken back through the scan's azimuth offset and tilt into the
   scanner's frame; the row is its zenith on the uniform [thetaMin, thetaMax] grid, and
   the column its azimuth from phiMin on the uniform [phiMin, phiMax] grid after the
   head's continuous rotation during each column is removed. The cell is not clamped: a
   point outside the declared raster maps to a row or column outside ``[0, Ntheta)`` or
   ``[0, Nphi)``, which :meth:`gapfillMisses` ignores.

   Use it to give returns ``row``/``column`` hit data when their timestamps cannot
   identify their pulses (rounded on export, say), so that :meth:`gapfillMisses` places
   the misses through its row/column path. The cells are only as good as the declared
raster  the scan's angular ranges, size, tilt and azimuth offset must describe the
   instrument.
Parameters
scanIDScan index; must be a static raster scan (not a moving, spinning multibeam or Risley-prism scan)
point(x, y, z) of the return
Returns
(row, column): row is the zenith index, column the azimuth index
Exceptions
ValueErrorIf ``point`` is not a vec3
HeliosErrorIf the scan does not exist or is not a static raster scan
RuntimeErrorIf the native library predates helios-core v1.3.89

Definition at line 3158 of file LiDARCloud.py.

◆ getScanAngleNoiseStdDev()

float pyhelios.LiDARCloud.LiDARCloud.getScanAngleNoiseStdDev ( self,
int scanID )

Get the angular (beam-pointing) jitter standard deviation for a scan (radians).

   Returns the value supplied to addScan() as ``angle_noise_stddev`` (0.0 if disabled).

Definition at line 732 of file LiDARCloud.py.

◆ getScanAzimuthOffset()

float pyhelios.LiDARCloud.LiDARCloud.getScanAzimuthOffset ( self,
int scanID )

Get the global scanner azimuth (heading) offset for a scan (radians; 0.0 if none).

Definition at line 750 of file LiDARCloud.py.

◆ getScanBeamZenithAngles()

List[float] pyhelios.LiDARCloud.LiDARCloud.getScanBeamZenithAngles ( self,
int scanID )

Get the per-channel beam zenith angles (radians) for a multibeam scan.

   Returns an empty list for a raster scan.

Definition at line 770 of file LiDARCloud.py.

◆ getScanCount()

int pyhelios.LiDARCloud.LiDARCloud.getScanCount ( self)

Get total number of scans in the cloud.

Definition at line 697 of file LiDARCloud.py.

◆ getScanDetectionThreshold()

float pyhelios.LiDARCloud.LiDARCloud.getScanDetectionThreshold ( self,
int scanID )

Get the detection threshold (energy fraction, noise floor) of a scan.

   The default is 0.001 (-30 dB) as of helios-core 1.3.92 (it was 0.05), matching the noise
   floor of terrestrial RIEGL scans. A threshold under 1/N has no effect with N sub-rays per
   pulse, so at ~40 rays/pulse every resolved return is reported. Only used for synthetic
   scan generation.

Definition at line 915 of file LiDARCloud.py.

◆ getScanGridDirection()

SphericalCoord pyhelios.LiDARCloud.LiDARCloud.getScanGridDirection ( self,
int scanID,
int row,
int column )

Beam direction at a scan-grid cell, from the model fitted during gap-filling.

   Available once :meth:`gapfillMisses` has run on the scan through the row/column
   path. This is the same reconstruction used to place synthesized misses, exposed so
   a caller can check the fitted geometry against known directions.
Parameters
scanIDScan index
rowScan-grid row (zenith index)
columnScan-grid column (azimuth index)
Returns
Unit direction of that cell's beam
Exceptions
RuntimeErrorIf the native library predates helios-core v1.3.84

Definition at line 1946 of file LiDARCloud.py.

◆ getScanHitCount()

int pyhelios.LiDARCloud.LiDARCloud.getScanHitCount ( self,
int scanID )

Number of hit points (stored returns plus virtualized misses) belonging to one scan.

   This is the length the per-scan readers fill -- :meth:`getScanHitIndices`,
   :meth:`getScanHitXYZColumn` and :meth:`getScanHitDataColumn`.
Parameters
scanIDScan index
Returns
Number of hits in that scan
Exceptions
ValueErrorIf ``scanID`` is negative
RuntimeErrorIf the native library predates helios-core v1.3.86

Definition at line 2837 of file LiDARCloud.py.

◆ getScanHitDataColumn()

List[float] pyhelios.LiDARCloud.LiDARCloud.getScanHitDataColumn ( self,
int scanID,
str label,
float absent_value = -9999.0 )

Read one scan's values of a scalar-data label in a single pass, as doubles.

   The per-scan counterpart of :meth:`getHitDataColumn`; see
   :meth:`getScanHitXYZColumn` for why this is preferred over filtering the whole cloud.
Parameters
scanIDScan index
labelLabel of the data value
absent_valueValue reported for hits that lack the label
Returns
List of floats, one per hit in the scan, in local order
Exceptions
TypeErrorIf ``label`` is not a str
ValueErrorIf ``scanID`` is negative or ``label`` is empty
RuntimeErrorIf the native library predates helios-core v1.3.86

Definition at line 2906 of file LiDARCloud.py.

◆ getScanHitDataColumnFloat32()

List[float] pyhelios.LiDARCloud.LiDARCloud.getScanHitDataColumnFloat32 ( self,
int scanID,
str label,
float absent_value = -9999.0 )

Read one scan's values of a scalar-data label as 32-bit floats.

   See :meth:`getScanHitDataColumn` and :meth:`getHitDataColumnFloat32`.
Exceptions
TypeErrorIf ``label`` is not a str
ValueErrorIf ``scanID`` is negative or ``label`` is empty
RuntimeErrorIf the native library predates helios-core v1.3.86

Definition at line 2924 of file LiDARCloud.py.

◆ getScanHitDataColumnInt32()

List[int] pyhelios.LiDARCloud.LiDARCloud.getScanHitDataColumnInt32 ( self,
int scanID,
str label,
int absent_value = -9999 )

Read one scan's values of a scalar-data label as 32-bit signed integers.

   See :meth:`getScanHitDataColumn` and :meth:`getHitDataColumnInt32`.
Exceptions
TypeErrorIf ``label`` is not a str
ValueErrorIf ``scanID`` is negative or ``label`` is empty
HeliosErrorIf any value is not an integer in the 32-bit range
RuntimeErrorIf the native library predates helios-core v1.3.86

Definition at line 2943 of file LiDARCloud.py.

◆ getScanHitIndices()

List[int] pyhelios.LiDARCloud.LiDARCloud.getScanHitIndices ( self,
int scanID )

Global indices of one scan's hit points, in the order the per-scan readers use.

   A scan's hits need not be contiguous in the global index space (a filter's
   swap-and-pop deletion reorders the cloud, and gap-filled misses live above every
   stored return), so the per-scan readers present a scan's hits in their own local
   order. This maps each local position back to the global index used by
   :meth:`getHitXYZ` and friends. Stored returns come first, in stored order, followed
   by the scan's virtualized misses.
Parameters
scanIDScan index
Returns
List of global hit indices, one per hit in the scan
Exceptions
ValueErrorIf ``scanID`` is negative
RuntimeErrorIf the native library predates helios-core v1.3.86

Definition at line 2861 of file LiDARCloud.py.

◆ getScanHitXYZColumn()

pyhelios.LiDARCloud.LiDARCloud.getScanHitXYZColumn ( self,
int scanID )

Read one scan's hit positions in a single pass.

   Costs O(hits in the scan), not O(hits in the cloud).
   Prefer this to filtering :meth:`getHitXYZColumn` by scan.
Parameters
scanIDScan index
Returns
List of (x, y, z) tuples, one per hit in the scan, in local order
Exceptions
ValueErrorIf ``scanID`` is negative
RuntimeErrorIf the native library predates helios-core v1.3.86

Definition at line 2882 of file LiDARCloud.py.

◆ getScanMaxReturns()

int pyhelios.LiDARCloud.LiDARCloud.getScanMaxReturns ( self,
int scanID )

Get the maximum returns per pulse used in single/limited-return mode (1 = single, N = N-return).

Definition at line 853 of file LiDARCloud.py.

◆ getScanMode()

ScanMode pyhelios.LiDARCloud.LiDARCloud.getScanMode ( self,
int scanID )

Get the high-level acquisition mode of a scan as a :class:ScanMode.

   STATIC_RASTER (fixed-origin grid), MOVING_RASTER (fan swept along a trajectory),
   SPINNING (continuously-rotating multi-channel sensor), or RISLEY_PRISM (Livox-style rosette).

Definition at line 780 of file LiDARCloud.py.

◆ getScanOrigin()

vec3 pyhelios.LiDARCloud.LiDARCloud.getScanOrigin ( self,
int scanID )

Get origin of a specific scan.

Definition at line 701 of file LiDARCloud.py.

◆ getScanPattern()

int pyhelios.LiDARCloud.LiDARCloud.getScanPattern ( self,
int scanID )

Get the scan pattern for a scan.

   Returns an integer: 0 = raster (uniform angular grid), 1 = spinning multibeam
   (rotating multi-channel sensor), 2 = Risley-prism (Livox-style rosette). Compare against
   ``ScanPattern.RASTER`` / ``ScanPattern.SPINNING_MULTIBEAM`` / ``ScanPattern.RISLEY_PRISM``.

Definition at line 761 of file LiDARCloud.py.

◆ getScanPulseWidth()

float pyhelios.LiDARCloud.LiDARCloud.getScanPulseWidth ( self,
int scanID )

Get the pulse width / range resolution (meters) of a scan (0 = use syntheticScan argument).

Definition at line 895 of file LiDARCloud.py.

◆ getScanRangeNoiseStdDev()

float pyhelios.LiDARCloud.LiDARCloud.getScanRangeNoiseStdDev ( self,
int scanID )

Get the range (along-beam) measurement noise standard deviation for a scan (meters).

   Returns the value supplied to addScan() as ``range_noise_stddev`` (0.0 if disabled).

Definition at line 723 of file LiDARCloud.py.

◆ getScanRecordPartialMisses()

bool pyhelios.LiDARCloud.LiDARCloud.getScanRecordPartialMisses ( self,
int scanID )

Whether a scan's partly intercepted multi-return pulses also record a partial-miss point.

   See :meth:`setScanRecordPartialMisses`. The default is True.
Exceptions
ValueErrorIf ``scanID`` is negative
RuntimeErrorIf the native library predates helios-core v1.3.92

Definition at line 936 of file LiDARCloud.py.

◆ getScanReturnMode()

ReturnMode pyhelios.LiDARCloud.LiDARCloud.getScanReturnMode ( self,
int scanID )

Get the return-reporting mode of a scan as a :class:ReturnMode (MULTI or SINGLE).

Definition at line 820 of file LiDARCloud.py.

◆ getScanRevolutions()

float pyhelios.LiDARCloud.LiDARCloud.getScanRevolutions ( self,
int scanID )

Get the number of revolutions the sensor head made (spinning scans; 0 otherwise).

Definition at line 798 of file LiDARCloud.py.

◆ getScanRisleyPrisms()

List[RisleyPrism] pyhelios.LiDARCloud.LiDARCloud.getScanRisleyPrisms ( self,
int scanID )

Get the rotating wedge prisms of a Risley-prism scan as a list of :class:RisleyPrism.

   Returns the prism stack in beam-traversal order (empty for non-Risley scans).

Definition at line 807 of file LiDARCloud.py.

◆ getScanRisleyRefractiveIndexAir()

float pyhelios.LiDARCloud.LiDARCloud.getScanRisleyRefractiveIndexAir ( self,
int scanID )

Get the refractive index of the medium surrounding a Risley scan's prisms (1.0 for non-Risley).

Definition at line 814 of file LiDARCloud.py.

◆ getScanRotationRate()

float pyhelios.LiDARCloud.LiDARCloud.getScanRotationRate ( self,
int scanID )

Get the sensor-head rotation rate in revolutions/second (spinning scans; 0 otherwise).

Definition at line 792 of file LiDARCloud.py.

◆ getScanSingleReturnSelection()

SingleReturnSelection pyhelios.LiDARCloud.LiDARCloud.getScanSingleReturnSelection ( self,
int scanID )

Get the single/limited-return selection policy as a :class:SingleReturnSelection.

Definition at line 835 of file LiDARCloud.py.

◆ getScanSizePhi()

int pyhelios.LiDARCloud.LiDARCloud.getScanSizePhi ( self,
int scanID )

Get number of azimuthal scan points for a scan.

Definition at line 714 of file LiDARCloud.py.

◆ getScanSizeTheta()

int pyhelios.LiDARCloud.LiDARCloud.getScanSizeTheta ( self,
int scanID )

Get number of zenith scan points for a scan.

Definition at line 708 of file LiDARCloud.py.

◆ getScanStepsPerRev()

int pyhelios.LiDARCloud.LiDARCloud.getScanStepsPerRev ( self,
int scanID )

Get the number of azimuth firing steps per revolution (spinning scans; 0 otherwise).

Definition at line 786 of file LiDARCloud.py.

◆ getScanTiltPitch()

float pyhelios.LiDARCloud.LiDARCloud.getScanTiltPitch ( self,
int scanID )

Get the global scanner tilt pitch angle for a scan (radians; 0.0 if level).

Definition at line 744 of file LiDARCloud.py.

◆ getScanTiltRoll()

float pyhelios.LiDARCloud.LiDARCloud.getScanTiltRoll ( self,
int scanID )

Get the global scanner tilt roll angle for a scan (radians; 0.0 if level).

Definition at line 738 of file LiDARCloud.py.

◆ getSyntheticScanMemoryBudget()

int pyhelios.LiDARCloud.LiDARCloud.getSyntheticScanMemoryBudget ( self)

Get the soft memory budget (bytes) for :meth:syntheticScan's transient buffers.

   Returns the explicitly configured budget set via :meth:`setSyntheticScanMemoryBudget`, or
   0 if using the automatic path-dependent default (8 GiB on a GPU build, 4 GiB otherwise).

Definition at line 891 of file LiDARCloud.py.

◆ getTriangleCount()

int pyhelios.LiDARCloud.LiDARCloud.getTriangleCount ( self)

Get number of triangles in the mesh.

   .. warning::
       Reports zero once a run's triangles have been streamed to a sink registered with
       :meth:`setTriangulationSink` -- the mesh is released rather than stored. Clear the
       sink before triangulating if you need the stored mesh.

Definition at line 1396 of file LiDARCloud.py.

◆ getTriangleVerticesAll()

pyhelios.LiDARCloud.LiDARCloud.getTriangleVerticesAll ( self)

Bulk-export every triangle's vertices and source scan in one call.

   Returns (xyz_flat, scan_ids): xyz_flat is a (T*9,) float32 array laid out
   [v0x,v0y,v0z, v1x,v1y,v1z, v2x,v2y,v2z] per triangle, scan_ids is a (T,)
   int32 array. Avoids the Context round-trip and the per-triangle
   getPrimitiveVertices loop.

   .. warning::
       Raises once a run's triangles have been streamed to a sink registered with
       :meth:`setTriangulationSink` -- the mesh is released rather than stored, and the
       native consumers refuse to operate on an empty mesh. Clear the sink before
       triangulating if you need the stored mesh.

Definition at line 1428 of file LiDARCloud.py.

◆ getTriangulationStats()

dict pyhelios.LiDARCloud.LiDARCloud.getTriangulationStats ( self)

Filter diagnostics from the most recent triangulateHitPoints() call.

   Returns a dict::

       {"candidates", "dropped_lmax", "dropped_aspect", "dropped_degenerate"}

   Each dropped triangle is attributed to one primary reason (Lmax, then
   aspect, then degenerate), so ``candidates == getTriangleCount() +
   dropped_lmax + dropped_aspect + dropped_degenerate``. All zero if
   triangulation has not been run. Use this to tell whether an empty or
   sparse mesh is data-limited (few candidates) or filter-limited (many
   candidates dropped by Lmax/aspect).

Definition at line 1412 of file LiDARCloud.py.

◆ getVirtualMissCount()

int pyhelios.LiDARCloud.LiDARCloud.getVirtualMissCount ( self)

Number of gap-filled misses currently held in virtualized form.

   A miss synthesized by :meth:`gapfillMisses` is a pure function of its scan-grid
   cell, so it is stored implicitly rather than as an element of the hit array. Such
   points are counted by :meth:`getHitCount` and readable through every accessor, but
   occupy no per-point storage.
Exceptions
RuntimeErrorIf the native library predates helios-core v1.3.84

Definition at line 1866 of file LiDARCloud.py.

◆ hasMisses()

bool pyhelios.LiDARCloud.LiDARCloud.hasMisses ( self)

Return True if the cloud contains at least one miss.

   :meth:`calculateLeafArea` requires misses and fails fast without them.

Definition at line 1300 of file LiDARCloud.py.

◆ hasVirtualMisses()

bool pyhelios.LiDARCloud.LiDARCloud.hasVirtualMisses ( self)

Whether any gap-filled miss is currently held in virtualized form.

Exceptions
RuntimeErrorIf the native library predates helios-core v1.3.84

Definition at line 1911 of file LiDARCloud.py.

◆ initializeCollisionDetection()

pyhelios.LiDARCloud.LiDARCloud.initializeCollisionDetection ( self,
Context context )

Initialize CollisionDetection plugin for ray tracing.

   Required before performing synthetic scans.
Parameters
contextHelios Context instance containing geometry

Definition at line 2423 of file LiDARCloud.py.

◆ is_available()

bool pyhelios.LiDARCloud.LiDARCloud.is_available ( self)

Check if LiDAR is available in current build.

Returns
True if plugin is available, False otherwise

Definition at line 3170 of file LiDARCloud.py.

◆ isGPUAccelerationEnabled()

bool pyhelios.LiDARCloud.LiDARCloud.isGPUAccelerationEnabled ( self)

Return True if GPU acceleration is currently enabled for collision-detection ray tracing.

Definition at line 2472 of file LiDARCloud.py.

◆ isGPUAvailable()

bool pyhelios.LiDARCloud.LiDARCloud.isGPUAvailable ( self)

Return True if a CUDA-capable GPU is available for collision-detection ray tracing.

   Reports capability (compiled with CUDA, a device present, and HELIOS_NO_GPU not set); use
   :meth:`isGPUAccelerationEnabled` to query whether GPU acceleration is currently toggled on.

Definition at line 2468 of file LiDARCloud.py.

◆ isHitMiss()

bool pyhelios.LiDARCloud.LiDARCloud.isHitMiss ( self,
int index )

Return True if a hit is a "miss" (a fired pulse that returned nothing).

   Misses are the transmitted beams that form the denominator of the per-voxel
   transmission probability used by :meth:`calculateLeafArea`. They are produced by
   ``syntheticScan(..., record_misses=True)`` and by :meth:`gapfillMisses`.

Definition at line 1291 of file LiDARCloud.py.

◆ isMultiReturnData()

bool pyhelios.LiDARCloud.LiDARCloud.isMultiReturnData ( self)

Return True if the cloud contains multi-return data.

   Multi-return data is data in which a single laser pulse produced more than one
   recorded return (any hit with ``target_count`` greater than 1). This is a behavioral
   switch, not just a descriptive property: :meth:`triangulateHitPoints` branches on
   it, triangulating first returns only (with an adaptive separation filter) for
   multi-return data and treating every return as an independent single return
   otherwise. The two branches can differ substantially in reconstructed surface
   area, so a cloud assembled by hand (for example through :meth:`addHitPoints` or
   the native ASCII loader) can use this to confirm which one will run.

   Multi-return data must also carry the ``timestamp`` and ``target_index`` hit-data
   fields, which triangulation needs to group returns into beams and select first
   returns. If ``target_count > 1`` is found but either field is absent, this raises
   rather than reporting an answer the rest of the pipeline cannot act on.

   Requires helios-core v1.3.85 or newer.
Exceptions
HeliosErrorIf multi-return data is present but ``timestamp`` or target_index is missing
RuntimeErrorIf the native library predates helios-core v1.3.85

Definition at line 1326 of file LiDARCloud.py.

◆ lastHitFilter()

pyhelios.LiDARCloud.LiDARCloud.lastHitFilter ( self)

Keep only last return hit points.

Definition at line 1482 of file LiDARCloud.py.

◆ loadXML()

pyhelios.LiDARCloud.LiDARCloud.loadXML ( self,
str filename )

Load scan metadata from XML file.

Definition at line 1525 of file LiDARCloud.py.

◆ materializeMisses()

None pyhelios.LiDARCloud.LiDARCloud.materializeMisses ( self)

Convert every virtualized gap-filled miss into a stored hit point.

   Every observable is unchanged by this call -- it trades the memory saving for real
   storage. It happens automatically before any operation that renumbers the hit index
   space (adding or deleting a hit point, writing hit data or a grid cell), so calling
   it explicitly is only needed to pay that cost at a chosen moment.
Exceptions
RuntimeErrorIf the native library predates helios-core v1.3.84

Definition at line 1925 of file LiDARCloud.py.

◆ reflectanceFilter()

pyhelios.LiDARCloud.LiDARCloud.reflectanceFilter ( self,
float minreflectance )

Filter hit points by minimum reflectance value.

Definition at line 1474 of file LiDARCloud.py.

◆ reserveHitPoints()

None pyhelios.LiDARCloud.LiDARCloud.reserveHitPoints ( self,
int hit_count )

Reserve capacity for hit points and every scalar-data column at once.

   Growing the hit-point array by repeated insertion temporarily needs both the old and
   new buffers, which for a cloud of tens of millions of returns adds gigabytes of
   transient memory, so a load that would fit once settled can still fail while growing.
   Reserving the final size once avoids this.

   This only reserves capacity; it does not create hit points, and
   :meth:`getHitCount` is unchanged. Reserving less than the eventual total is
   harmless, as is reserving more.
Parameters
hit_countExpected total number of hit points in the cloud
Exceptions
RuntimeErrorIf the native library predates helios-core v1.3.84

Definition at line 2061 of file LiDARCloud.py.

◆ setCellGtheta()

pyhelios.LiDARCloud.LiDARCloud.setCellGtheta ( self,
float Gtheta,
int index )

Set G(theta) value for a grid cell.

Definition at line 1789 of file LiDARCloud.py.

◆ setExactPathLengths()

None pyhelios.LiDARCloud.LiDARCloud.setExactPathLengths ( self,
bool exact )

Keep every beam path length exactly, instead of binning them.

   The leaf-area inversion bins per-beam voxel path lengths once a voxel accumulates
   many samples, which bounds memory that would otherwise grow without limit with scan
   size. Binning recovers the extinction coefficient far inside the solver's
   tolerance, so this is an escape hatch for unusual geometry, or for confirming that
   binning is not responsible for a difference between two results.
Parameters
exactTrue to keep every sample; False (the default) to bin above the threshold
Exceptions
RuntimeErrorIf the native library predates helios-core v1.3.84

Definition at line 2079 of file LiDARCloud.py.

◆ setExternalTriangulation()

pyhelios.LiDARCloud.LiDARCloud.setExternalTriangulation ( self,
vertices,
scan_ids )

Replace the internal triangulation with an externally-supplied mesh.

   Bypasses the internal Delaunay triangulation so a mesh produced elsewhere
   (a re-used Helios triangulation, or a per-scan open3d Ball-Pivot mesh) can
   drive leaf-area inversion without a recompute. After this call,
   ``calculateLeafArea()`` runs unchanged.
Parameters
verticesTriangle vertices in world coordinates, accepted as a (T, 9) array laid out [v0x,v0y,v0z, v1x,v1y,v1z, v2x,v2y,v2z] per triangle, a (T, 3, 3) array, or a flat (T*9,) array – the same layout :meth:getTriangleVerticesAll exports, so a Helios mesh round-trips directly.
scan_idsSource scan index for each triangle, shape (T,). Required; every entry must be a valid scan index (see :meth:addScan), since the leaf-angle G(theta) term needs each triangle's ray direction. A merged mesh with no scan association is not valid.

A grid must already be defined (see :meth:addGrid).

Definition at line 1452 of file LiDARCloud.py.

◆ setMaxHitPoints()

None pyhelios.LiDARCloud.LiDARCloud.setMaxHitPoints ( self,
int max_hits )

Set the cap on stored hit points before loading fails with a diagnostic.

   Exceeding the cap raises an error naming the projected point count and the limit,
   rather than throwing from inside the allocator where neither the scan responsible
   nor the size is visible. The default (:meth:`getDefaultMaxHitPoints`) is
deliberately    it guards against a mis-specified scan grid exhausting the
   machine, and is not a statement about machine capacity. Raise it when the machine
   genuinely has the memory.
Parameters
max_hitsMaximum stored hit points, or 0 to disable the check
Exceptions
RuntimeErrorIf the native library predates helios-core v1.3.84

Definition at line 2021 of file LiDARCloud.py.

◆ setProgressCallback()

pyhelios.LiDARCloud.LiDARCloud.setProgressCallback ( self,
callback )

Register a progress callback fired with (progress_fraction, message) during :meth:syntheticScan.

   ``progress_fraction`` is a float in [0, 1]; ``message`` is a ``str`` describing the current
   phase. Pass ``None`` to clear the callback. The callback bridge is kept alive on this
   :class:`LiDARCloud` for as long as it is registered.

Definition at line 3074 of file LiDARCloud.py.

◆ setScanDetectionThreshold()

pyhelios.LiDARCloud.LiDARCloud.setScanDetectionThreshold ( self,
int scanID,
float detection_threshold )

Set the detection threshold (energy fraction, noise floor) of a scan.

Definition at line 921 of file LiDARCloud.py.

◆ setScanMaxReturns()

pyhelios.LiDARCloud.LiDARCloud.setScanMaxReturns ( self,
int scanID,
int max_returns )

Set the maximum returns per pulse used in single/limited-return mode (must be >= 1).

Definition at line 859 of file LiDARCloud.py.

◆ setScanPulseWidth()

pyhelios.LiDARCloud.LiDARCloud.setScanPulseWidth ( self,
int scanID,
float pulse_width )

Set the pulse width / range resolution (meters) of a scan (0 = use syntheticScan argument).

Definition at line 901 of file LiDARCloud.py.

◆ setScanRecordPartialMisses()

pyhelios.LiDARCloud.LiDARCloud.setScanRecordPartialMisses ( self,
int scanID,
bool record_partial_misses )

Set whether a scan's partly intercepted multi-return pulses record the escaped energy as a miss.

   With miss recording on, a multi-return pulse that is only partly intercepted also writes
   a miss point (intensity 0) for the part of the beam that left the scene. A real
   instrument never records that point: it reports the returns it detected and nothing for
   the escaped energy. Set this to False to produce the record a real instrument provides
   (plus a gap-filled miss for each fully transmitted pulse, which is always recorded when
   miss recording is on). Single-return mode never records a partial miss.

   Leaf-area inversion that weights a pulse's returns equally reads close to unbiased with
   these points and high without them, so validating an inversion only on default
   synthetic scans understates its bias on real data. Only used for synthetic scan
   generation; the XML equivalent is ``<recordPartialMisses>``.
Parameters
scanIDID of the scan
record_partial_missesTrue (default) to record partial-miss points
Exceptions
ValueErrorIf ``scanID`` is negative or ``record_partial_misses`` is not a bool
RuntimeErrorIf the native library predates helios-core v1.3.92

Definition at line 963 of file LiDARCloud.py.

◆ setScanReturnMode()

pyhelios.LiDARCloud.LiDARCloud.setScanReturnMode ( self,
int scanID,
Union[ReturnMode, int] return_mode )

Set the return-reporting mode of a scan (ReturnMode.MULTI or ReturnMode.SINGLE).

   Only affects analytic-waveform synthetic scans (more than one ray per pulse).

Definition at line 829 of file LiDARCloud.py.

◆ setScanSingleReturnSelection()

pyhelios.LiDARCloud.LiDARCloud.setScanSingleReturnSelection ( self,
int scanID,
Union[SingleReturnSelection, int] selection )

Set the single/limited-return selection policy (STRONGEST, FIRST, LAST, or STRONGEST_PLUS_LAST).

   Used when the scan's return mode is SINGLE and a pulse resolves more returns than maxReturns.
   STRONGEST_PLUS_LAST is a dual-return mode that intrinsically yields 1 or 2 returns and
   ignores maxReturns.

Definition at line 847 of file LiDARCloud.py.

◆ setSyntheticScanHitSink()

None pyhelios.LiDARCloud.LiDARCloud.setSyntheticScanHitSink ( self,
callback )

Register a sink fired after each chunk of a :meth:syntheticScan lands in the cloud.

   Without a sink, every chunk's returns accumulate in the cloud until the scan finishes,
   so a very large scan holds every return before the caller can read any. With a sink,
   ``callback(first, count)`` is invoked after each chunk with the index of the first new
   hit and the number of new hits. Inside the callback the new hits can be read (through
   the per-scan column readers), written out, and then released with
   :meth:`deleteHitPoints` -- they are always the tail of the cloud, so the cloud never
   holds more than one chunk.

   Chunk size is bounded by :meth:`setSyntheticScanMemoryBudget`. Pass ``None`` to clear.

   .. note::
       An exception raised inside ``callback`` is captured and re-raised from the call
       that triggered it -- typically
       :meth:`syntheticScan`.
Parameters
callbackCallable taking (first, count), or None to clear
Exceptions
TypeErrorIf ``callback`` is neither callable nor None
RuntimeErrorIf the native library predates helios-core v1.3.86

Definition at line 2783 of file LiDARCloud.py.

◆ setSyntheticScanMemoryBudget()

pyhelios.LiDARCloud.LiDARCloud.setSyntheticScanMemoryBudget ( self,
int bytes )

Set the soft memory budget (bytes) for :meth:syntheticScan's transient buffers.

   :meth:`syntheticScan` fans each pulse into ``rays_per_pulse`` sub-rays; for a
   large scan the simultaneously-traced sub-rays can demand many gigabytes if
   traced in one batch. This caps the live trace scratch buffers, so the per-scan
   beam fan-out is processed in chunks sized to stay near this budget regardless of
   scan resolution. It bounds only the transient buffers, not the output cloud.

   If never called, the budget is automatic and path-dependent (8 GiB on a GPU
   build, 4 GiB otherwise). Call this to override that with a fixed cap, typically
   to lower peak memory on a constrained host.
Parameters
bytesSoft cap in bytes on the live ray-tracing scratch buffers. Must be > 0.

Definition at line 881 of file LiDARCloud.py.

◆ setSyntheticScanProgressPointer()

pyhelios.LiDARCloud.LiDARCloud.setSyntheticScanProgressPointer ( self,
ptr )

Register an external per-scan progress counter polled during :meth:syntheticScan.

   ``ptr`` is a ``ctypes.c_int`` into which syntheticScan writes the 0-based index of the scan
   currently being ray-traced (set to :meth:`getScanCount` when the batch finishes), letting a
   host thread poll progress while the blocking scan runs. The counter is owned by the caller and
   must outlive the scan. Pass ``None`` to clear.

Definition at line 2482 of file LiDARCloud.py.

◆ setTriangulationSink()

None pyhelios.LiDARCloud.LiDARCloud.setTriangulationSink ( self,
callback )

Register a sink that receives each scan's triangles as :meth:triangulateHitPoints finishes it.

   With a sink set, triangulation hands each scan's finished triangles to ``callback`` and
   then releases them, keeping only the per-voxel leaf-angle sums the leaf-area inversion
   needs. Retained memory becomes one scan's triangles at a time, and
   :meth:`calculateLeafArea` still works and gives the same result.

   ``callback`` is called as ``callback(scanID, vertices, ids)`` where ``vertices`` is a
   ``(T, 9)`` float32 numpy array laid out ``[v0x,v0y,v0z, v1x,v1y,v1z, v2x,v2y,v2z]`` per
   triangle and ``ids`` is a ``(T, 2)`` int32 array of ``[scanID, gridcell]``. Both are
   copies owned by the caller. Pass ``None`` to clear the sink.

   .. warning::
       Once a run's triangles have been streamed, the mesh is not retained:
       :meth:`getTriangleCount` reports zero and :meth:`getTriangleVerticesAll`,
       :meth:`addTrianglesToContext`, :meth:`exportTriangleNormals` and
       :meth:`exportTriangleAreas` raise rather than silently operating on an empty mesh.
       Clear the sink before triangulating if you need the stored mesh.

   .. note::
       An exception raised inside ``callback`` is captured and re-raised from the call
       that triggered it --
       typically :meth:`triangulateHitPoints`.
Parameters
callbackCallable taking (scanID, vertices, ids), or None to clear
Exceptions
TypeErrorIf ``callback`` is neither callable nor None
RuntimeErrorIf the native library predates helios-core v1.3.86

Definition at line 2722 of file LiDARCloud.py.

◆ syntheticScan()

pyhelios.LiDARCloud.LiDARCloud.syntheticScan ( self,
Context context,
Optional[int] rays_per_pulse = None,
Optional[float] pulse_distance_threshold = None,
bool scan_grid_only = False,
bool record_misses = True,
bool append = False,
Optional[Union[ReturnMode, int]] return_mode = None,
cancel_flag = None )

Perform synthetic LiDAR scan of geometry in Context.

   Requires scan metadata to be defined first via addScan() or loadXML().
   Uses ray tracing to simulate LiDAR instrument measurements.
Parameters
contextHelios Context containing geometry to scan
rays_per_pulseNumber of rays per pulse (None=discrete-return, typical: 100)
pulse_distance_thresholdDistance threshold for aggregating hits (meters, required for waveform)
scan_grid_onlyIf True, only scan within defined grid cells
record_missesIf True, record miss/sky points where rays don't hit geometry
appendIf True, append to existing hits; if False, clear existing hits
return_modeOptional :class:ReturnMode (MULTI or SINGLE) for analytic-waveform scans. Overrides each scan's stored return mode for this call only. Only valid when rays_per_pulse is set (waveform mode); raises ValueError otherwise. In SINGLE mode up to each scan's getScanMaxReturns() returns per pulse are reported, selected by the scan's single-return selection policy.
cancel_flagOptional ctypes.c_int polled during the ray trace. Setting it non-zero from another thread aborts the scan mid-pass. It is cleared when the call returns, so a later scan on this cloud is not pre-cancelled.
   Example (Discrete-return):
       >>> from pyhelios import Context, LiDARCloud
       >>> from pyhelios.types import vec3
       >>> with Context() as context:
       ...     # Add geometry
       ...     context.addPatch(center=vec3(0, 0, 0.5), size=vec2(1, 1))
...... with LiDARCloud() as lidar: ... # Define scan parameters ... scan_id = lidar.addScan( ... origin=vec3(0, 0, 2), ... Ntheta=100, theta_range=(0, 1.57), ... Nphi=100, phi_range=(0, 6.28), ... exit_diameter=0, beam_divergence=0 ... )
...... # Perform discrete-return scan ... lidar.syntheticScan(context)

Example (Full-waveform): >>> lidar.syntheticScan( ... context, ... rays_per_pulse=100, ... pulse_distance_threshold=0.02, ... record_misses=True ... )

Definition at line 2138 of file LiDARCloud.py.

◆ triangulateHitPoints()

pyhelios.LiDARCloud.LiDARCloud.triangulateHitPoints ( self,
float Lmax,
float max_aspect_ratio = 4.0 )

Generate triangle mesh from hit points using Delaunay triangulation.

   For multi-return data only first returns are triangulated (the lowest
   ``target_index``, whether the scan counts returns from 0 or from 1).
Parameters
LmaxMaximum triangle edge length
max_aspect_ratioMaximum triangle aspect ratio (default 4.0)

Definition at line 1381 of file LiDARCloud.py.

Member Data Documentation

◆ _cd_context

pyhelios.LiDARCloud.LiDARCloud._cd_context = context
protected

Definition at line 2442 of file LiDARCloud.py.

◆ _cloud_ptr

pyhelios.LiDARCloud.LiDARCloud._cloud_ptr = lidar_wrapper.createLiDARcloud()
protected

Definition at line 191 of file LiDARCloud.py.

◆ _progress_callback_ref

pyhelios.LiDARCloud.LiDARCloud._progress_callback_ref = None
protected

Definition at line 197 of file LiDARCloud.py.

◆ _synthetic_hit_sink_error

pyhelios.LiDARCloud.LiDARCloud._synthetic_hit_sink_error = None
protected

Definition at line 205 of file LiDARCloud.py.

◆ _synthetic_hit_sink_ref

pyhelios.LiDARCloud.LiDARCloud._synthetic_hit_sink_ref = None
protected

Definition at line 204 of file LiDARCloud.py.

◆ _triangulation_sink_error

pyhelios.LiDARCloud.LiDARCloud._triangulation_sink_error = None
protected

Definition at line 203 of file LiDARCloud.py.

◆ _triangulation_sink_ref

pyhelios.LiDARCloud.LiDARCloud._triangulation_sink_ref = None
protected

Definition at line 202 of file LiDARCloud.py.


The documentation for this class was generated from the following file: