Loading [MathJax]/extensions/tex2jax.js
Python script opalsQuality
See also
python.workflows.opalsQuality

Aim of module

Package script providing a complete processing chain for quality assessment of ALS flight strips.

General description

opalsQuality calculates DSMs and visualizations thereof, point density maps, strip difference maps, and estimates of strip difference vectors.

See also
Script documentation

The Python script opalsQuality is the main script for the corresponding opalsQuality package. It uses multiple sub-scripts to create different products for checking and documenting the quality of an ALS flight campaign. The following aspects are covered:

  • Data import: This is a pre-requisite for all other steps. ALS point cloud data files are read into the ODM (one ODM per flight strip, script: python._import).
  • Strip outline: Based on the ODMs, strip outlines (minimum bounding rectangle, convex hull, or alpha shape) are derived (script: python._bounds).
  • Overlapping pairs: Based on the strip outlines the overlapping strip pairs are identified (script: python._overlap).
  • Point density: Raster based analysis is performed based on the ODM and point density maps are created for each strip and for the overall project area (Python script qltDensity)
  • DSM and visualizations: For each strip a digital surface model (DSM) is calculated and a color coded hypsometric map as well as a shaded relief map are derived (Python script qltDSM).
  • Strip differences: Based on the DSMs and the list of overlapping strip pairs, difference models and color coded raster maps of the relative strip differences are derived. This is a basic product for assessing the quality of the flight strips orientation via visual inspection (Python script qltStripDiff).
  • strip difference vectors: A more quantitative analysis is carried out for all overlapping strip pairs, by estimating a best fitting 3D-affine-transformation via an Least Squares Matching approach (Python script qltLSM).
  • point- or patchwise deviations between ALS data and independently measured control points/patches. This checks the absoute accuracy of the captured ALS data.
  • precision: Raster based analysis of the measurement noise, measured as standard deviation of the plane fit during DEM grid interpolation (Python script qltPrecision).

Masking out areas for quality assessment

For estimating the actual quality of the captured ALS data, it is recommended to devide the area into parts considered for the derivation of quality measures and those, which should be exluded or masked out, replectively. Reasons for masking areas are manifold; examples are: rugged surface areas, areas covered by vegetation, scan shadows, water bodies, etc.

For controlling the masked areas, Python script opalsQuality contains the following parameters mask, gridMask and recalcMaskFiles, which are explained in detail in the following:

The mask parameter enables the user to create masked files using custom formulas for attributes calculated by opalsGrid, namely the opalsGridFeature. In the documentation of this module you can find the complete list of GridFeatures that can be calculated and later used as masks. The formulas should be given as Generic filter formulas. The syntax for specifying n formulas for n GridFeatures in the mask parameter should look like this.

opalsQuality -inf strip*.laz -mask (Gridfeature1):("formula1") (Gridfeature2):("formula2") [...] (Gridfeature n):("formula n")

The formulas are then combined and used in the computation. The standard formula for masked computations is specified at the top cfg file, which looks like this.

[script.variables]
# Defines grid size for overall quality analyses. The variable will be used within
# opalsGrid and the mask definition (see below). If the value is changed one should
# also adapt the cell size of the density analyses (typically 3 to 5 times larger
# than the grid size)
qltGridSize=1
densityCellSize=3
[script.opalsQuality]
mask = sigma0:r<0.1 excentricity:r<0.8*${qltGridSize} gridMask:!r

Parameter gridMask allows to specify a formula, which whether a negative mask (gridMask:"!r") is being used, for example to mask out unwanted areas like lakes or rivers. A positive mask (gridMask:"r") can be used to only compute certain areas of interests and mask out all areas which are not within the specified rasterfile.

As shown above implicitly, the script parameter mask can either be set in the commandline with the known syntax or as a paramater in the [script.opalsQuality]-section in the cfg-File.

Within the subscript *_grid*, the mask is combined and the final formula string is reported to the user via the opalsLog. Figure 1 shows an example of how the formula looks like with the above provided components.

Figure 1: formula for the masked computations

The example 6 and the example 7 aim to show two uses cases for masking.

Finally, the boolean parameter recalcMaskFiles can be used to improve the masking in case the results of a previous run of opalsQuality call for an adaption of the masked areas. When activated in the repeat call of opalsQuality, this forces the re-creation of the mask files even if skipIfExists is set and the mask files (from the previous run) exist on disk.

Storage structure of intermediate and final results

Python script opalsQuality produces a series of intermediate and final results, which are stored in separate folders. The default folder structure is documented in the following tables:

opalsQuality: intermediate results
Default Directory Produced by Comments
import qltDSM, qltStripDiff, qltDensity, qltLSM, qltPrecision The folder contains the imported ODM files. All sub scripts start with importing the data into the OPALS Datamanager format.
grid qltDSM, qltStripDiff, qltLSM, qltPrecision The folder contains the DEM raster files for each strip of the flight block as well as additional grid feature raster files (sigma0, excentricity...) used for (i) masking and (ii) precision calculation. In addition, the folder conains the calculated mask for each strip and the masked/unmasked versions of the primary DEM and the sigma0 feature raster file.
bounds qltStripDiff The folder contains the outlines of each strip (vector files contiaining the strip boundary polygon) as basis for the derivation of strip overlaps.
cell qltDensity The folder contains the point density raster maps for each strip and the mosaic composed of all strips.
diff qltStripDiff The folder contains the strip height difference raster maps for each strip pair and the mosaic composed of all strip pairs. If masking is activated, a separate raster is created for the masked and the unmasked version.
overlap qltStripDiff The folder contains the file stripPairs.txt containing the list of overlapping strip pairs.
opalsQuality: final results
Default Directory Produced by Comments
opalsQuality\Density qltDensity The folder contains sub-folders for the color-coded density maps (visu) and statistical point density analysis (histo).
opalsQuality\DSM qltDSM The folder contains sub-folders for the hill shadings (shading) and color coded height maps (zcoding).
opalsQuality\LSM qltLSM The folder contains the estimated transformation parameters for overlapping strip pairs in tabular form (LSM_TrafPars.csv) and as a parameter XML file (lsmOutput.xml).
opalsQuality\Precision qltPrecision The folder contains sub-folders for masked and unmasked versions of the precision estimates (masked / unmasked). Each of the two folders consists of two sub-folders containing the color-coded height precision maps (zcoding) and the statistical analysis (histo). Separate files are generated for each strip and the mosaic composed of all strips.
opalsQuality\StripDiff qltStripDiff As above, the folder contains sub-folders for masked and unmasked versions of the strip height differences. Each of the two folders consists of two sub-folders containing the color-coded height difference maps (zcoding) and the statistical analysis (histo). Separate files are generated for each strip pair and the mosaic composed of all strip pairs.

Parameter description

-mosaic create mosaics
Type : Boolean
Remark : optional, default: True
possible inputevaluates to
1, true, yes, Boolean(True), TrueBoolean(True)
0, false, no, Boolean(False), FalseBoolean(False)
-mask create grid masks (sigma0, eccentricity)
Type : String
Remark : optional, default: ['sigma0:r<0.1', 'excentricity:r<0.8*1', 'gridMask:!r']
-gridMask raster file containing user-defined mask areas (e.g. water) that should not be calculated
Type : Path
Remark : optional
-slopeLimits slope limits (in degrees)
Type : Floating-point number
Remark : optional, default: []
Description: optional slope limits (in degrees) for slope classes based analyses. e.g. 20 30 will result in three classes: <20, >=20 to <30, >=30
-flatmode if True, all output files are stored in the same folder
Type : Boolean
Remark : optional, default: False
possible inputevaluates to
1, true, yes, Boolean(True), TrueBoolean(True)
0, false, no, Boolean(False), FalseBoolean(False)
-qgisProject path to qgis project file, if one should be written. A QGIS installation is required.
Type : Path
Remark : optional
-activeScripts list of sub-scripts to be executed
Type : String
Remark : optional, default: ('qltDSM', 'qltDensity', 'qltStripDiff', 'qltLSM', 'qltPrecision')
-recalcMaskFiles if True, masked outputfiles will be recalculated.
Type : Boolean
Remark : optional, default: False
Description: This parameter could be used if a new mask is applied and only the masked outputfilesshould be recalculated.
possible inputevaluates to
1, true, yes, Boolean(True), TrueBoolean(True)
0, false, no, Boolean(False), FalseBoolean(False)
Common Package/Script Options
Settings concerning the general options for (package) scripts.
-infile input text file, directory or strip file
Type : Path
Remark : mandatory
Description: Test
-outfile output directory or settings file (.txt)
Type : Path
Remark : optional
Description: Specifies the directory where the final results are stored. If not specified, the results are created in the current working directory.
-tempdir temporary directory
Type : Path
Remark : optional, default: current directory
Description: Specifies the directory where all intermediate results are stored. If not specified, a TEMP subdirectory is created in the current working directory. Additional subdirectories (one per involved module) are created.
-cfg Path to configuration file
Type : Path
Remark : optional, default: $OPALS_ROOT/cfg/opalsQuality.cfg
Description: The name of a configuration file containing all relevant calculation parameters is expected. If not specified, the default cfg files as provided by the OPALS distribution are used.
-projectDir project directory
Type : Path
Remark : optional, default: current directory
Description: The default project directory is the current working directory, but can be easily changed by this parameter. All path parameters, if not specified as absolute paths, are interpreted relative to the project directory.
-skipIfExists skip processing if result already exists
Type : Boolean
Remark : optional, default: True
Description: Skip processing if result already exists. In order to re-run current script it is useful to repeat the processing only if the respective output does not already exist. This allows for incremental processing of large projects.
possible inputevaluates to
1, true, yes, Boolean(True), TrueBoolean(True)
0, false, no, Boolean(False), FalseBoolean(False)
-distribute determine how many local processes should be used
Type : String
Remark : optional
Description: according to the number chosen as the value, independent processes are being started to parallelise (parts of) the program and therefore enhance the runtime.
Logging Options
Settings concerning the verbosity level of logging.
-fileLogLevel Log level in the logfile
Type : LogLevel
Remark : optional, default: info
-screenLogLevel Log level on screen
Type : LogLevel
Remark : optional, default: info
-logger Logger
Type : Logger
Remark : optional
Description: Logger is usually provided by the opals framework.The user may provide their own logger object, but it has to function in the same way as the opals Logger.

Examples

The data used in the following examples can be found in the $OPALS_ROOT/demo/ directory.

Example 1

In the first example, only the strip data file list is specified as input parameter:

opalsQuality -i striplist.txt

striplist.txt may, e.g., contain the following lines:

strip11.laz
strip12.laz
strip21.laz
strip22.laz
#strip31.laz
#strip32.laz

Please note, that in the above example, strip31 and strip32 are ignored, since the corresponding line starts with a hash (=comment) character. Thus, the quality assessment is only carried out for the rest of the strips (strip11, strip21, strip21 and strip 22). Since no further parameters are specified, the output files are created in the current working directory ($OPALS_ROOT/demo/), all intermediate files are stored in subfolders of $OPALS_ROOT/demo/ and the default configuration files stored in $OPALS_ROOT/packages/cfg are used.

Example 2

To use all strip*.laz files and store the resulting and temporary files each in a separate folders, type:

opalsQuality -i strip*.laz -o resultsQuality -t tempdir

Example 3

For examples 1 and 2 to work, it is necessary that the current working directory is $OPALS_ROOT/demo/. To achieve the same results from any current working directory, using the -p parameter, pointing to the directory containing the strip files, is recommended.

opalsQuality -i strip*.laz -o resultsQuality -t tempdir -p C:\OPALS\demo

Example 4

If only the strip differences should be calculated (disregarding already calculated intermediate outputs) for the overlapping strip pairs but not for the entire block, use the following command:

opalsQuality -i strip*.laz -activeScripts qltStripDiff -mosaic 0 -skipIfExists 0

Please note, that parameter names can be abbreviated as long as they can be unique resolved. E.g. -m is too short since it matches -mosaic and -mask, but -mo is ok. Hence, the very same command as above can also be written as:

opalsQuality -i strip*.laz -active qltStripDiff -mo 0 -skip 0

Example 5: Slope dependent analysis

Text to come...

opalsQuality -i strip*.laz -skip 0 -slopeLimits 15 35

Example 6: standard (negative) mask

Figure 2: (a) Street mask (b) (negatively) masked files (qltPrecision)

This first example should demonstrate the use of a negative mask. In this computation, the quality evaluation of the streets are not of interest, hence they are masked out. The raster file containing the approximate shape of the street is a rasterized shapefile called street_mask_ras.tif (see Figure 2a), which can be found in $OPALS_ROOT/demo/. Since a negative mask is desired, we do not need to change the default values in the cfg file. opalsQuality can therefore be called using the following command,

opalsQuality -inf strip*.laz -gridMask street_mask_ras.tif

resulting in masked computations as shown in Figure 2b. It is clear to see that the masked out areas where excluded from the computation.

Example 7: positive mask (aoi) and -recalcMaskFiles parameter

Following up on the hypothetical example of the street masks above: Let's say the streets are the only thing that is interesting for a certain application. In this case our mask file can be used as a positive mask to treat the street as an aoi. As only the masked files should be recaculated and all other files need not be computed again, the recalcMaskFiles parameter can be used to only compute files necessary for mask creation and reuse everything else. The opalsQuality call could therefore look like this:

opalsQuality -inf strip*.laz -gridMask street_mask_ras.tif -mask "sigmaz:r<0.1" "excentricity:r<0.8" gridMask:r -recalcMaskFiles True

Note the subtle change in the formula of GridMask within the mask parameter. Since "<" and ">" are reserved for redirections in the command shell, quotation signs are necessary to specify formulas that contain those symbols. The same can be achieved if the formula is changed within the cfg like so.

#############################################################################
########################### common parameters ###############################
#############################################################################
[script.opalsQuality]
mask = sigmaz:r<0.1 excentricity:r<0.8 gridMask:r
[...]

Then the call can look like this:

opalsQuality -inf strip*.laz -gridMask street_mask_ras.tif -cfg opalsQuality.cfg -recalcMaskFiles True

The result can be seen in Figure 3, now in the masked files only the street areas are taken into account.

Figure 3: (positively) masked files (qltPrecision)
@ nbThreads
number of concurrent threads
@ gridMask
grid mask file
@ excentricity
distance between grid points - c.o.g. of data points
Definition: GridFeature.hpp:15
@ strip
strip ID of an image (opalsStripAdjust)
@ sigmaz
sigma z of grid post adjustment (i.e. std.dev. of the interpolated height)
Definition: GridFeature.hpp:11
@ info
Some progress that may be interesting in everyday-use.
@ screenLogLevel
verbosity level of screen output