Estimates the canopy structure from a discrete returns scan from different TLS.

canopy_structure(
  TLS.type,
  scan,
  zenith.range,
  zenith.rings,
  azimuth.range,
  vertical.resolution,
  TLS.pulse.counts,
  TLS.resolution = NULL,
  TLS.coordinates = c(0, 0, 0),
  TLS.frame = NULL,
  TLS.angles = NULL,
  threads = 1
)

Arguments

TLS.type

A character describing is the TLS used. It most be one of "single" return, "multiple" return, or "fixed.angle" scanner.

scan

If TLS.type is equal to "single" or "fixed.angle", a data.table with three columns describing *XYZ* coordinates of the discrete return. If TLS.type is equal to "multiple", a data.table with four columns describing *XYZ* coordinates and the target count pulses. Currently, "fixed.angle" present errors, use with discretion.

zenith.range

If TLS.type is equal to "single" or "multiple", a numeric vector of length two describing the min and max range of the zenith angle to use. Theoretically, the max range should be lower than 90 degrees.

zenith.rings

If TLS.type is equal to "single" or "multiple", a numeric vector of length one describing the number of zenith rings to use between zenith.range. This is used to estimate the frequency of laser shots from the scanner and returns in scan. If TLS.type = "fixed.angle", zenith.rings = 1 be default.

azimuth.range

A numeric vector of length two describing the range of the azimuth angle to use. Theoretically, it should be between 0 and 360 degrees.

vertical.resolution

A numeric vector of length one describing the vertical resolution to extract the vertical profiles. Low values lead to more variable profiles. The scale used needs to be in congruence with the scale of scan.

TLS.pulse.counts

If TLS.type is equal to "single" or "multiple", a numeric vector of length two describing the horizontal and vertical pulse counts of the scanner. If TLS.type is equal to "fixed.angle", a numeric vector of length one describing the horizontal pulse counts resolution. Preferred parameter over TLS.resolution to estimate the number of pulses.

TLS.resolution

If TLS.pulse.counts = NULL, the code use the angles resolution to estimate the pulse counts in a given TLS.frame. If TLS.type is equal to "single" or "multiple", a numeric vector of length two describing the horizontal and vertical angle resolution of the scanner. If TLS.type is equal to "fixed.angle", a numeric vector of length one describing the horizontal angle resolution.

TLS.coordinates

A numeric vector of length three describing the scanner coordinates within scan. It assumes that the coordinates are c(X = 0, Y = 0, Z = 0) for default.

TLS.frame

If TLS.type is equal to "single" or "multiple", a numeric vector of length four describing the min and max of the zenith and azimuth angle of the scanner frame. If TLS.type = "fixed.angle", a numeric vector of length three describing the fixed zenith angle and the min and max of the azimuth angle of the scanner frame. If NULL, it assumes that a complete hemisphere (c(zenith.min = 0, zenith.max = 90, azimuth.min = 0, azimuth.max = 360)), or a cone projection (c(zenith = 57.5, azimuth.min = 0, azimuth.max = 360)) depending on TLS.type.

TLS.angles

A numeric vector of length three describing the roll (*X*), pitch (*Y*), and yaw (*Z*) angles of the scanner during the scan. If NULL, it assumes that there is no need to to correction of angles. This needs to be used if TLS.type is equal to "single" or "multiple", since it assumes that "fixed.angle" scanner is previously balanced. NULL as default.

threads

An integer specifying the number of threads to use. Experiment to see what works best for your data on your hardware.

Value

For any TLS.type, it returns a data.table with the height profiles defined by vertical.resolution, the gap probability based on the zenith.range and zenith.rings, and the accumulative L(z) profiles based on the closest zenith ring to 57.5 degrees (hinge angle). If TLS.type is equal to "fixed.angle", it returns f(z) or commonly named PAVD based on on the ratio of the derivative of L(z) and the derivative of height (z). If TLS.type is equal to "single" or "multiple", it returns the normalized average weighting L/LAI, and PAVD: based on the L (hinge angle) at the highest height and the ratio between the derivative of L/LAI average weighted and the derivative of z.

Details

Since scan describes discrete returns measured by the TLS, canopy_structre first simulates the number of pulses emitted based on Danson et al. (2007). The simulated pulses are created based on the TLS properties (TLS.pulse.counts, TLS.resolution, TLS.frame) assuming that the scanner is perfectly balance. Then these pulses are rotated (rotate3D) based on the TLS.angles roll, pitch, and yaw, and move to TLS.coordintates to simulate the positioning of the scanner during the scan. Rotated simulated-pulses of interest and scan returns are then extracted based on the zenith.range and azimuth.range for a given number of zenith.rings, azimuth.rings and vertical profiles. The probability of gap (Pgap) is then estimated using the frequency of pulses and returns. For TLS.type = "multiple", the frequency of returns is estimated using the sum of 1/target count following Lovell et al. (2011).

Using the Pgap estimated per each zenith ring and vertical profile, canopy_structure then estimates the accumulative L(z) profiles based on the closest zenith ring to 57.5 (hinge region) and, if TLS.type = "fixed.angle", the f(z) or commonly named PAVD based on the ratio of the derivative of L(z) and height (z) following Jupp et al. 2009 (Equation 18). If TLS.type is equal to "single" or "multiple", canopy_structure also estimates the normalized average weighted L/LAI, and then PAVD based on the L (hinge angle) at the highest height (LAI) and the ratio between the derivative of L/LAI (average weighted) and the derivative of z (Jupp et al. 2009; Equation 21).

Jupp et al. 2009 excludes the zero zenith or fist ring to conduct the average weighted L/LAI estimations, canopy_structre does not excludes this sections since it depends on the regions of interest of the user. Therefore, user should consider this difference since it may introduce more variability to profile estimations.

References

Danson F.M., Hetherington D., Morsdorf F., Koetz B., Allgower B. 2007. Forest canopy gap fraction from terrestrial laser scanning. IEEE Geosci. Remote Sensing Letters 4:157-160. doi: 10.1109/LGRS.2006.887064

Lovell J.L., Jupp D.L.B., van Gorsel E., Jimenez-Berni J., Hopkinson C., Chasmer L. 2011. Foliage profiles from ground based waveform and discrete point LiDAR. In: SilviLaser 2011, Hobart, Australia, 16–20 October 2011.

Jupp D.L.B., Culvenor D.S., Lovell J.L., Newnham G.J., Strahler A.H., Woodcock C.E. 2009. Estimating forest LAI profiles and structural parameters using a ground-based laser called “Echidna®”. Tree Physiology 29(2): 171-181. doi: 10.1093/treephys/tpn022

Author

J. Antonio Guzmán Q.

Examples


# \donttest{
data(TLS_scan)
#Using a multiple return file
#Select the four columns required
TLS_scan <- TLS_scan[, 1:4]

#This will take a while#
a <- canopy_structure(TLS.type = "multiple",
                 scan = TLS_scan,
                 zenith.range = c(50, 70),
                 zenith.rings = 4,
                 azimuth.range = c(0, 360),
                 vertical.resolution = 0.25,
                 TLS.pulse.counts = c(2082, 580),
                 TLS.frame = c(30, 130.024, 0, 359.90),
                 TLS.angles =  c(1.026, 0.760, -110.019))

#Using a single return file

data(TLS_scan)
#Subset to first return observations
TLS_scan <- TLS_scan[Target_index == 1, 1:3]
#> Error in .checkTypos(e, names_x): Object 'Target_index' not found amongst X, Y, Z, Target_count

#This will take a while#
canopy_structure(TLS.type = "single",
                 scan = TLS_scan,
                 zenith.range = c(50, 70),
                 zenith.rings = 4,
                 azimuth.range = c(0, 360),
                 vertical.resolution = 0.25,
                 TLS.pulse.counts = c(2082, 580),
                 TLS.frame = c(30, 130.024, 0, 359.90),
                 TLS.angles =  c(1.026, 0.760, -110.019))
#>     height Pgap(52.5) Pgap(57.5) Pgap(62.5) Pgap(67.5)  L (hinge)
#>  1:   0.25 1.00000000 1.00000000  1.0000000  1.0000000 0.00000000
#>  2:   0.50 1.00000000 1.00000000  1.0000000  0.9764347 0.00000000
#>  3:   0.75 0.99818031 0.97200862  0.9672550  0.9281773 0.03122967
#>  4:   1.00 0.98459764 0.92356646  0.9212362  0.8729762 0.08746377
#>  5:   1.25 0.94280979 0.85510441  0.8373519  0.7223373 0.17218487
#>  6:   1.50 0.92588019 0.80260192  0.7051786  0.5266560 0.24188607
#>  7:   1.75 0.82755203 0.65435863  0.5908526  0.4360572 0.46650968
#>  8:   2.00 0.74826561 0.58629433  0.4879443  0.3728684 0.58732668
#>  9:   2.25 0.63084697 0.45266821  0.3863783  0.3421441 0.87185543
#> 10:   2.50 0.48523940 0.38261518  0.3260419  0.2860812 1.05679810
#> 11:   2.75 0.40296349 0.27543918  0.2677438  0.2394478 1.41832729
#> 12:   3.00 0.34656940 0.21761684  0.2330599  0.1870805 1.67752133
#> 13:   3.25 0.31087426 0.19022207  0.2074737  0.1616260 1.82551938
#> 14:   3.50 0.25394401 0.17048392  0.1750104  0.1474073 1.94602570
#> 15:   3.75 0.21595802 0.14526019  0.1437070  0.1421706 2.12215159
#> 16:   4.00 0.20278152 0.10790520  0.1326705  0.1409443 2.44915240
#> 17:   4.25 0.16398317 0.08945973  0.1233574  0.1406128 2.65536339
#> 18:   4.50 0.14835334 0.06872721  0.1158174  0.1406128 2.94537106
#> 19:   4.75 0.13751645 0.05619821  0.1105311  0.1405631 3.16675741
#> 20:   5.00 0.12871046 0.04255883  0.1099843  0.1405631 3.47255463
#> 21:   5.25 0.11623260 0.03559828  0.1098848  0.1405631 3.66900386
#> 22:   5.50 0.10573689 0.03395757  0.1098848  0.1405631 3.72090770
#> 23:   5.75 0.08919722 0.03002983  0.1098848  0.1405631 3.85612043
#> 24:   6.00 0.07704431 0.02512430  0.1098848  0.1405631 4.05231194
#> 25:   6.25 0.07124405 0.02499171  0.1098848  0.1405631 4.05813206
#> 26:   6.50 0.06901818 0.02492542  0.1098848  0.1405631 4.06105371
#> 27:   6.75 0.06659735 0.02492542  0.1098848  0.1405631 4.06105371
#> 28:   7.00 0.06575249 0.02477627  0.1098848  0.1405631 4.06765593
#> 29:   7.25 0.06557377 0.02466026  0.1098848  0.1405631 4.07281853
#> 30:   7.50 0.06549253 0.02466026  0.1098848  0.1405631 4.07281853
#> 31:   7.75 0.06549253 0.02466026  0.1098848  0.1405631 4.07281853
#> 32:   8.00 0.06549253 0.02466026  0.1098848  0.1405631 4.07281853
#>     height Pgap(52.5) Pgap(57.5) Pgap(62.5) Pgap(67.5)  L (hinge)
#>     L/LAI (weighted mean)         PAVD
#>  1:           0.000000000 0.0792017904
#>  2:           0.004861608 0.2680908352
#>  3:           0.021317708 0.3646951846
#>  4:           0.043703630 0.9340795288
#>  5:           0.101039816 1.4961111526
#>  6:           0.192874938 1.2652301743
#>  7:           0.270537997 1.1002953598
#>  8:           0.338076935 1.1317610455
#>  9:           0.407547318 1.2749174884
#> 10:           0.485805009 1.4272248720
#> 11:           0.573411715 1.4241631995
#> 12:           0.660830489 0.9264699570
#> 13:           0.717699580 0.8997225967
#> 14:           0.772926850 0.7940195737
#> 15:           0.821665799 0.5048485224
#> 16:           0.852654690 0.4607920015
#> 17:           0.880939280 0.4314586220
#> 18:           0.907423312 0.3270122704
#> 19:           0.927496160 0.2951670462
#> 20:           0.945614267 0.2201061983
#> 21:           0.959124947 0.0980857835
#> 22:           0.965145703 0.2098353951
#> 23:           0.978025935 0.2444928039
#> 24:           0.993033528 0.0514349745
#> 25:           0.996190738 0.0213080163
#> 26:           0.997498678 0.0213397832
#> 27:           0.998808569 0.0129122739
#> 28:           0.999601157 0.0057567814
#> 29:           0.999954523 0.0007408768
#> 30:           1.000000000 0.0000000000
#> 31:           1.000000000 0.0000000000
#> 32:           1.000000000           NA
#>     L/LAI (weighted mean)         PAVD
# }