import os import subprocess def call_lastools(tool_name, input, output=None, args=None, verbose=True): """Send commands to the lastools library. Requires lastools in system path. Args: tool_name: name of lastools binary input: bytes from stdout, or path to main input data output: '-stdout' to pipe output, or path to main output data args: list of additional arguments, formatted for lastools verbose: show all warnings and messages from lastools (boolean) Returns: bytes of output las, if output='-stdout' None, if output='path/to/las/file' Examples: # Convert xyz file to las and pipe stdout to a python bytes object las_data = call_lastools('txt2las', input='points.xyz', output='-stdout', args=['-parse', 'sxyz']) # Clip las_data with a shapefile, and save to a new las file call_lastools('lasclip', input=las_data, output='points.las', args=['-poly', 'boundary.shp']) """ # Start building command string cmd = [tool_name] # Parse input if type(input) == bytes: # Pipe input las bytes to stdin cmd += ['-stdin'] stdin = input else: # Load las from file path cmd += ['-i', input] stdin = None # Parse output if output == '-stdout': # Pipe output las to stdout cmd += ['-stdout'] elif output: # Save output las to file cmd += ['-o', output] # Append additional lastools arguments, if provided if args: cmd += args process = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) stdout, stderr = process.communicate(input=stdin) # Handle errors, if detected if process.returncode != 0: print("Error: {} failed on {}".format(tool_name, os.path.basename(input))) print(stderr.decode()) elif verbose: # Print addional messages if verbose mode is being used print(stderr.decode()) # Output piped stdout if required if output == '-stdout': return stdout else: return None