0.1.33
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 171 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[RisleyPrismgetScanRisleyPrisms (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.
 
 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 via the native cache-linear columnar path.
 
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 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.
 
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 180 of file LiDARCloud.py.

◆ __del__()

pyhelios.LiDARCloud.LiDARCloud.__del__ ( self)

Fallback destructor for cleanup without context manage.

Definition at line 220 of file LiDARCloud.py.

Member Function Documentation

◆ __enter__()

pyhelios.LiDARCloud.LiDARCloud.__enter__ ( self)

Context manager entry.

Definition at line 210 of file LiDARCloud.py.

◆ __exit__()

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

Context manager exit - cleanup resources.

Definition at line 214 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 2389 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 2115 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 2757 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 2565 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 2899 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 418 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, matching the native addGrid(). :meth:addGridCell takes its rotation in radians — the two native entry points genuinely differ, and PyHelios passes each through unchanged. :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 1526 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. This asymmetry is inherited from the native API — the native addGridCell() stores the angle directly in the cell's radian field while addGrid() converts from degrees. :meth:getCellRotation reports degrees.

Definition at line 1591 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 933 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 987 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 2598 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 1028 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 277 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 361 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 561 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 644 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 485 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 2350 of file LiDARCloud.py.

◆ calculateHitGridCell()

pyhelios.LiDARCloud.LiDARCloud.calculateHitGridCell ( self)

Calculate hit point grid cell assignments.

Definition at line 1749 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.
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 2200 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 2932 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 2282 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 2267 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 1313 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 1295 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 2450 of file LiDARCloud.py.

◆ deleteHitPoint()

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

Delete a hit point from the cloud.

Definition at line 1234 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 2623 of file LiDARCloud.py.

◆ disableCDGPUAcceleration()

pyhelios.LiDARCloud.LiDARCloud.disableCDGPUAcceleration ( self)

Disable GPU acceleration (use CPU ray tracing)

Definition at line 2399 of file LiDARCloud.py.

◆ disableMessages()

pyhelios.LiDARCloud.LiDARCloud.disableMessages ( self)

Disable console output messages.

Definition at line 1482 of file LiDARCloud.py.

◆ distanceFilter()

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

Filter hit points by maximum distance from scanne.

Definition at line 1420 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 1112 of file LiDARCloud.py.

◆ enableCDGPUAcceleration()

pyhelios.LiDARCloud.LiDARCloud.enableCDGPUAcceleration ( self)

Enable GPU acceleration for collision detection ray tracing.

Definition at line 2394 of file LiDARCloud.py.

◆ enableMessages()

pyhelios.LiDARCloud.LiDARCloud.enableMessages ( self)

Enable console output messages.

Definition at line 1486 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 1948 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 2323 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 2317 of file LiDARCloud.py.

◆ exportLeafAreas()

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

Export leaf areas for each grid cell to file.

Definition at line 2311 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 1457 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 1445 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 1470 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 2305 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 2294 of file LiDARCloud.py.

◆ firstHitFilter()

pyhelios.LiDARCloud.LiDARCloud.firstHitFilter ( self)

Keep only first return hit points.

Definition at line 1429 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.

   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 1770 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 1792 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 1682 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 1627 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 1643 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 2980 of file LiDARCloud.py.

◆ getCellGtheta()

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

Get G(theta) value for a grid cell.

Definition at line 1737 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 1704 of file LiDARCloud.py.

◆ getCellLeafArea()

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

Get leaf area of a grid cell (m²)

Definition at line 1667 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 1716 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 1673 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 1694 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 1688 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 1661 of file LiDARCloud.py.

◆ getCellSize()

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

Get size of a grid cell.

Definition at line 1650 of file LiDARCloud.py.

◆ getCroppedReturnStats()

dict pyhelios.LiDARCloud.LiDARCloud.getCroppedReturnStats ( self)

Returns 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 1848 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 1986 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 2036 of file LiDARCloud.py.

◆ getGridCellCount()

int pyhelios.LiDARCloud.LiDARCloud.getGridCellCount ( self)

Get total number of grid cells.

Definition at line 1617 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 2995 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 1728 of file LiDARCloud.py.

◆ getHitColor()

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

Get color of a hit point.

Definition at line 1094 of file LiDARCloud.py.

◆ getHitCount()

int pyhelios.LiDARCloud.LiDARCloud.getHitCount ( self)

Get total number of hit points in cloud.

Definition at line 1064 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 1122 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 1135 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 1176 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 via the native cache-linear columnar path.

   Faster than :meth:`getHitDataAll` for whole-field reads (a single cache-linear pass over
   the contiguous native column rather than per-hit tree lookups), 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 1190 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 1209 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 2502 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 2514 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 1202 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 2542 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 2554 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 2476 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 1226 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 1079 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 3010 of file LiDARCloud.py.

◆ getHitRaydir()

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

Get ray direction of a hit point.

Definition at line 1086 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 1101 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 1217 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 1925 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 1147 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 1167 of file LiDARCloud.py.

◆ getHitXYZ()

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

Get coordinates of a hit point.

Definition at line 1068 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 1911 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 1976 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 1286 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 734 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 752 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 772 of file LiDARCloud.py.

◆ getScanCount()

int pyhelios.LiDARCloud.LiDARCloud.getScanCount ( self)

Get total number of scans in the cloud.

Definition at line 699 of file LiDARCloud.py.

◆ getScanDetectionThreshold()

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

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

Definition at line 911 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 1892 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 2780 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 2851 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 2869 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 2888 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 2804 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): the scan's stored returns are
   located through an index built once and kept until the cloud changes, and its
   virtualized misses are walked in occupancy order rather than resolved one at a time.
   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 2827 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 855 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 782 of file LiDARCloud.py.

◆ getScanOrigin()

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

Get origin of a specific scan.

Definition at line 703 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 763 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 897 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 725 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 822 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 800 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 809 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 816 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 794 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 837 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 716 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 710 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 788 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 746 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 740 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 893 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 1347 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 1379 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 1363 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 1812 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 1254 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 1857 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 2363 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 3043 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 2412 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 2408 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 1245 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 1280 of file LiDARCloud.py.

◆ lastHitFilter()

pyhelios.LiDARCloud.LiDARCloud.lastHitFilter ( self)

Keep only last return hit points.

Definition at line 1433 of file LiDARCloud.py.

◆ loadXML()

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

Load scan metadata from XML file.

Definition at line 1476 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 1871 of file LiDARCloud.py.

◆ reflectanceFilter()

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

Filter hit points by minimum reflectance value.

Definition at line 1425 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 reallocates geometrically, and
   during every reallocation the old and new buffers are both live. For a cloud of
   tens of millions of returns that transient is gigabytes on top of the steady-state
   cost, and on Windows it is charged against the system commit limit at allocation
time    so a load that would comfortably fit once settled can still fail while
   growing. Reserving the final size once removes the transient entirely.

   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 2009 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 1743 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 2027 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 1403 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 1967 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 3019 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 917 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 861 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 903 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 831 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 849 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`` cannot propagate through the native call
       (a Python exception in a ctypes callback is swallowed and reported to C++ as
       success, which would let the scan continue as though nothing failed). It 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 2726 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 883 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 2422 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`` cannot propagate through the native call
       (a Python exception in a ctypes callback is swallowed and reported to C++ as
       success). It 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 2663 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 2086 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.

Parameters
LmaxMaximum triangle edge length
max_aspect_ratioMaximum triangle aspect ratio (default 4.0)

Definition at line 1332 of file LiDARCloud.py.

Member Data Documentation

◆ _cd_context

pyhelios.LiDARCloud.LiDARCloud._cd_context = context
protected

Definition at line 2382 of file LiDARCloud.py.

◆ _cloud_ptr

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

Definition at line 193 of file LiDARCloud.py.

◆ _progress_callback_ref

pyhelios.LiDARCloud.LiDARCloud._progress_callback_ref = None
protected

Definition at line 199 of file LiDARCloud.py.

◆ _synthetic_hit_sink_error

pyhelios.LiDARCloud.LiDARCloud._synthetic_hit_sink_error = None
protected

Definition at line 207 of file LiDARCloud.py.

◆ _synthetic_hit_sink_ref

pyhelios.LiDARCloud.LiDARCloud._synthetic_hit_sink_ref = None
protected

Definition at line 206 of file LiDARCloud.py.

◆ _triangulation_sink_error

pyhelios.LiDARCloud.LiDARCloud._triangulation_sink_error = None
protected

Definition at line 205 of file LiDARCloud.py.

◆ _triangulation_sink_ref

pyhelios.LiDARCloud.LiDARCloud._triangulation_sink_ref = None
protected

Definition at line 204 of file LiDARCloud.py.


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