6. Tutorial: spatial_mod

6.1. Sample data

Sample imagery captured from a Resonon Pika II VIS-NIR line scanning imager and ancillary sample files can be downloaded from this link.

Before trying this tutorial on your own machine, please download the sample files and place into a local directory of your choosing (and do not change the file names). Indicate the location of your sample files by modifying data_dir:

[1]:
data_dir = r'F:\\nigo0024\Documents\hs_process_demo'

6.2. Confirm your environment

Before trying the tutorials, be sure hs_process and its dependencies are properly installed. If you installed in a virtual environment, first check we are indeed using the Python instance that was installed with the virtual environment:

[2]:
import sys
import hs_process
print('Python install location: {0}'.format(sys.executable))
print('Version: {0}'.format(hs_process.__version__))
Python install location: C:\Users\nigo0024\Anaconda3\envs\hs_process\python.exe
Version: 0.0.4

The spec folder that contains python.exe tells me that the activated Python instance is indeed in the spec environment, just as I intend. If you created a virtual environment, but your python.exe is not in the envs\spec directory, you either did not properly create your virtual environment or you are not pointing to the correct Python installation in your IDE (e.g., Spyder, Jupyter notebook, etc.).


6.3. spatial_mod.crop_many_gdf

Crops many plots from a single image by comparing the image to a polygon file (geopandas.GoeDataFrame) that contains plot information and geometry of plot boundaries. [API]

Load the geopandas, hsio and spatial_mod modules

[3]:
import geopandas as gpd
import os
from hs_process import hsio
from hs_process import spatial_mod

Read datacube and spatial plot boundaries (refer to the API for more information about the parameter meanings and options).

[4]:
fname_in = os.path.join(data_dir, 'Wells_rep2_20180628_16h56m_pika_gige_7-Radiance Conversion-Georectify Airborne Datacube-Convert Radiance Cube to Reflectance from Measured Reference Spectrum.bip.hdr')
fname_gdf = os.path.join(data_dir, 'plot_bounds.geojson')

gdf = gpd.read_file(fname_gdf)
io = hsio(fname_in)
my_spatial_mod = spatial_mod(io.spyfile)
dir_out = os.path.join(io.base_dir, 'spatial_mod', 'crop_many_gdf')
if not os.path.isdir(os.path.join(io.base_dir, 'spatial_mod')):  # create a new folder named "spatial_mod" if it does not exist
    os.mkdir(os.path.join(io.base_dir, 'spatial_mod'))
if not os.path.isdir(dir_out):  # create a new folder named "crop_many_gdf" if it does not exist
    os.mkdir(dir_out)

name_append = '-crop-many-gdf'

Get instructions on how plots should be cropped via spatial_mod.crop_many_gdf; note that a pandas.DataFrame is returned with information describing how each plot should be cropped.

[5]:
df_plots = my_spatial_mod.crop_many_gdf(spyfile=io.spyfile, gdf=gdf)
df_plots.head(5)
[5]:
directory name_short name_long ext plot_id_ref pix_e_ul pix_n_ul buf_e_m buf_n_m buf_e_pix buf_n_pix crop_e_m crop_n_m crop_e_pix crop_n_pix gdf_shft_e_m gdf_shft_n_m gdf_shft_e_pix gdf_shft_n_pix
0 None None None .bip 1018 113 0 NaN NaN NaN NaN NaN NaN 229 76 NaN NaN NaN NaN
1 None None None .bip 918 342 0 NaN NaN NaN NaN NaN NaN 229 76 NaN NaN NaN NaN
2 None None None .bip 818 571 0 NaN NaN NaN NaN NaN NaN 229 76 NaN NaN NaN NaN
3 None None None .bip 718 800 0 NaN NaN NaN NaN NaN NaN 229 76 NaN NaN NaN NaN
4 None None None .bip 618 1029 0 NaN NaN NaN NaN NaN NaN 229 76 NaN NaN NaN NaN

Use the data from the first frow of df_plots to crop a single plot from the original image (uses spatial_mod.crop_single)

[6]:
pix_e_ul=113
pix_n_ul=0
crop_e_pix=229
crop_n_pix=75
plot_id_ref=1018
array_crop, metadata = my_spatial_mod.crop_single(
    pix_e_ul=pix_e_ul, pix_n_ul=pix_n_ul, crop_e_pix=crop_e_pix, crop_n_pix=crop_n_pix,
    spyfile=io.spyfile, plot_id_ref=plot_id_ref)

Save the cropped datacube and geotiff to a new directory

[7]:
fname_out = os.path.join(dir_out, io.name_short + '_plot_' + str(1018) + name_append + '.' + io.defaults.envi_write.interleave)
fname_out_tif = os.path.join(dir_out, io.name_short + '_plot_' + str(1018) + '.tif')

io.write_cube(fname_out, array_crop, metadata=metadata, force=True)
io.write_tif(fname_out_tif, spyfile=array_crop, metadata=metadata)
Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Using a for loop, use spatial_mod.crop_single and hsio.write_cube to crop by plot and save cropped datacubes and geotiffs to file

[8]:
for idx, row in df_plots.iterrows():
    io.read_cube(fname_in, name_long=io.name_long,
                 name_plot=row['plot_id_ref'],
                 name_short=io.name_short)
    my_spatial_mod.load_spyfile(io.spyfile)
    array_crop, metadata = my_spatial_mod.crop_single(
            pix_e_ul=row['pix_e_ul'], pix_n_ul=row['pix_n_ul'],
            crop_e_pix=row['crop_e_pix'], crop_n_pix=row['crop_n_pix'],
            buf_e_m=2.0, buf_n_m=0.75,
            plot_id_ref=row['plot_id_ref'])

    fname_out = os.path.join(dir_out, io.name_short + '_plot_' + str(row['plot_id_ref']) + name_append + '.bip.hdr')
    fname_out_tif = os.path.join(dir_out, io.name_short + '_plot_' + str(row['plot_id_ref']) + '.tif')

    io.write_cube(fname_out, array_crop, metadata=metadata, force=True)  # force=True to overwrite the plot_1018 image
    io.write_tif(fname_out_tif, spyfile=array_crop, metadata=metadata)
Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

The size of ``spyfile`` is zero; thus there is nothing to write to file and ``write_cube()`` is being aborted.
Filename: Wells_rep2_20180628_16h56m_pika_gige_7_plot_1010-crop-many-gdf.bip.hdr

The size of ``spyfile`` is zero; thus there is nothing to write to file and ``write_tif()`` is being aborted.
Filename: Wells_rep2_20180628_16h56m_pika_gige_7_plot_1010.tif

The size of ``spyfile`` is zero; thus there is nothing to write to file and ``write_cube()`` is being aborted.
Filename: Wells_rep2_20180628_16h56m_pika_gige_7_plot_910-crop-many-gdf.bip.hdr

The size of ``spyfile`` is zero; thus there is nothing to write to file and ``write_tif()`` is being aborted.
Filename: Wells_rep2_20180628_16h56m_pika_gige_7_plot_910.tif

The size of ``spyfile`` is zero; thus there is nothing to write to file and ``write_cube()`` is being aborted.
Filename: Wells_rep2_20180628_16h56m_pika_gige_7_plot_810-crop-many-gdf.bip.hdr

The size of ``spyfile`` is zero; thus there is nothing to write to file and ``write_tif()`` is being aborted.
Filename: Wells_rep2_20180628_16h56m_pika_gige_7_plot_810.tif

The size of ``spyfile`` is zero; thus there is nothing to write to file and ``write_cube()`` is being aborted.
Filename: Wells_rep2_20180628_16h56m_pika_gige_7_plot_710-crop-many-gdf.bip.hdr

The size of ``spyfile`` is zero; thus there is nothing to write to file and ``write_tif()`` is being aborted.
Filename: Wells_rep2_20180628_16h56m_pika_gige_7_plot_710.tif

The size of ``spyfile`` is zero; thus there is nothing to write to file and ``write_cube()`` is being aborted.
Filename: Wells_rep2_20180628_16h56m_pika_gige_7_plot_610-crop-many-gdf.bip.hdr

The size of ``spyfile`` is zero; thus there is nothing to write to file and ``write_tif()`` is being aborted.
Filename: Wells_rep2_20180628_16h56m_pika_gige_7_plot_610.tif

Open cropped geotiff images in QGIS to visualize the extent of the cropped images compared to the original datacube and the plot boundaries (the full extent image is darkened and displayed in the background): crop_many_gdf


6.4. spatial_mod.crop_single

Crops a single plot from an image. If plot_id_ref and gdf are explicitly passed (i.e., they will not be loaded from spatial_mod class), the “map info” tag in the metadata will be adjusted to center the cropped area within the appropriate plot geometry. [API]

Load and initialize the hsio and spatial_mod modules

[9]:
from hs_process import hsio
from hs_process import spatial_mod

fname_in = os.path.join(data_dir, 'Wells_rep2_20180628_16h56m_pika_gige_7-Radiance Conversion-Georectify Airborne Datacube-Convert Radiance Cube to Reflectance from Measured Reference Spectrum.bip.hdr')
io = hsio(fname_in)
my_spatial_mod = spatial_mod(io.spyfile)

Crop an area with a width (easting) 200 pixels and a height (northing) of 50 pixels, with a northwest/upper left origin at the 342nd column (easting) and 75th row (northing).

[10]:
pix_e_ul = 342
pix_n_ul = 75
array_crop, metadata = my_spatial_mod.crop_single(
        pix_e_ul, pix_n_ul, crop_e_pix=200, crop_n_pix=50)

Save as a geotiff using io.write_tif, then load into QGIS to visualize.

[11]:
fname_tif = os.path.join(data_dir, 'spatial_mod', 'crop_single', 'crop_single.tif')
if not os.path.isdir(os.path.dirname(fname_tif)):  # create a new folder named "crop_single" if it does not exist
    os.mkdir(os.path.dirname(fname_tif))

io.write_tif(fname_tif, array_crop, metadata=metadata)
Either `projection_out` is `None` or `geotransform_out` is `None` (or both are). Retrieving projection and geotransform information by loading `hsio.fname_in` via GDAL. Be sure this is appropriate for the data you are trying to write.

Open cropped geotiff image in QGIS to visualize the extent of the cropped image compared to the original datacube and the plot boundaries (the full extent image is darkened and displayed in the background): crop_single


6.5. spatial_mod.load_spyfile

Loads a SpyFile (Spectral Python object) for data access and/or manipulation by the hstools class. [API]

Load and initialize the hsio and spatial_mod modules

[12]:
from hs_process import hsio
from hs_process import spatial_mod

fname_in = os.path.join(data_dir, 'Wells_rep2_20180628_16h56m_pika_gige_7-Radiance Conversion-Georectify Airborne Datacube-Convert Radiance Cube to Reflectance from Measured Reference Spectrum.bip.hdr')
io = hsio(fname_in)
my_spatial_mod = spatial_mod(io.spyfile)

Load datacube using spatial_mod.load_spyfile

[13]:
my_spatial_mod.load_spyfile(io.spyfile)
my_spatial_mod.spyfile
[13]:
        Data Source:   'F:\\nigo0024\Documents\hs_process_demo\Wells_rep2_20180628_16h56m_pika_gige_7-Radiance Conversion-Georectify Airborne Datacube-Convert Radiance Cube to Reflectance from Measured Reference Spectrum.bip'
        # Rows:            617
        # Samples:        1300
        # Bands:           240
        Interleave:        BIP
        Quantization:  32 bits
        Data format:   float32