Python Lidar – Handling NoData Values in Lidar Packages

nodatapythonraster

I am attempting to use the python lidar package function lidar.ExtractSinks(). I have a raster dataset that looks like the following.

enter image description here

Not a very useful image, but it gets the point across that I am only interested in the white area. The rest of it has been clipped, masked, or something to remove actual elevation values. This area is causing problems with the fucntion.

At this stage, I have attempted to replace 0 values with nodata I believe based on another post using rasterio src.nodata = 0 # set the nodata value. The reason I think This worked is that my data histogram now looks like the following, whereas before the histogram showed that I had a huge number of cells of value 0.

enter image description here

Regardless of whether I apply this change to the black cells in the raster image, I receive the following error: AttributeError: module 'numpy' has no attribute 'float'., which can be traced back to a line in the source code of the function: max_elev = np.float(np.max(dem[dem != no_data])). This line is what makes me think this is a NoData cells issue. The documentation of the error suggests that np.float is deprecated and to use float instead, but this is not my code, so I cannot change it.

Reading in raster, attempting to convert o values to NoData values:

#read in original tiff file "full_pa"
full_pa_path = os.path.join(data_dir, 'full_pa.tif')
with rio.open(full_pa_path) as dem_src:
    lidar_dem_im = dem_src.read(1, masked=True)
    

#Try to reset the 0 values to no data and write them to file
source_raster_path = os.path.join(data_dir, 'full_pa.tif')
distination_raster_path = os.path.join(out_dir, 'full_pa_nodat.tif')
with rasterio.open(source_raster_path, "r+") as src:
    src.nodata = 0 # set the nodata value
    profile = src.profile
    profile.update(
            dtype=rasterio.uint8,
            compress='lzw'
    )

    with rasterio.open(distination_raster_path, 'w',  **profile) as dst:
        for i in range(1, src.count + 1):
            band = src.read(i)
            # band = np.where(band!=1,0,band) # if value is not equal to 1 assign no data value i.e. 0
            band = np.where(band==0,0,band) # for completeness
            dst.write(band,i)

#Now read in the new tiff file with nodata instead of 0 values
full_pa_nodat_path = os.path.join(out_dir, 'full_pa_nodat.tif')
with rio.open(full_pa_nodat_path) as dem_src:
    lidar_dem_im = dem_src.read(1, masked=True)

ep.hist(lidar_dem_im,
        figsize=(10, 6),
        title="Histogram of Cell Values")
plt.show()   

pyplot.imshow(lidar_dem_im, cmap='pink')

Attempt to apply the function:

# parameters for identifying sinks and delineating nested depressions
min_size = 10            # minimum number of pixels as a depression
min_depth = 0.2             # minimum depth as a depression
interval = 0.3      # slicing interval for the level-set method
bool_shp = True      # output shapefiles for each individual level

# extracting sinks based on user-defined minimum depression size
#extract sinks fucntion takes a string file path and loads it rather than a loaded rasterio tif
sink_path = lidar.ExtractSinks(full_pa_path, min_size, out_dir)
dep_id_path, dep_level_path = lidar.DelineateDepressions(sink_path, min_size, min_depth, interval, out_dir, bool_shp)

The ExtractSinks function was that which caused the error: AttributeError: module 'numpy' has no attribute 'float'

Any suggestions as to how to get around this, or if I am even correct about the issue?

Best Answer

Looks like that package was built with an old version of numpy. The newer versions did away with the np.float function.

You could downgrade your numpy version to 1.20 (you will get a deprecation warning rather than the error) or you could try changing the source code to use the built in Python float function such as: max_elev = float(np.max(dem[dem != no_data]))

See this post:

https://stackoverflow.com/questions/74844262/how-to-solve-error-numpy-has-no-attribute-float-in-python

A side note: I prefer to use PDAL for this type of lidar manipulation. There is a learning curve but it is a very powerful suite of tools. https://pypi.org/project/pdal/

Related Question