As of radR rev. 420, there is a new mechanism for obtaining and using complete sample data for multiple blips.
It is mainly intended for development on the tracker plugin and in calibration studies.
Basic idea
- interactively build a list of blips by scanning through a blipmovie (or other source) and selecting blips individually
- save the retained list of blips as a data.frame in an R binary file
- load the data.frame from the R binary file, and work with it
Quick start
- from the radR main menu: Source an R script... radR/util/export_blips.R
- when the radR plot window has focus, use these keys and controls:
- a: adds the blip or patch under the pointer to the set of retained blips
- s: save the set of retained blips; reset list to empty
- Shift + MouseWheel Up: go forward one scan
- Shift + MouseWheel Down: go backward one scan
(The pointerinfo window displays a short message when a blip is retained or when the set is saved.)
- from the radR main menu: Source an R script... radR/util/slice_blips.R, which does this:
- load the saved blip data.frame
- extract the angular cross section through each blip's brightest sample
- plot echo strength vs. beam-axis-to-target separation angle for each blip on one graph
This is just an example of what can be done with the saved data. The slice_blips.R script can be used in a stand-alone R session (i.e. without running radR),
provided you have defined the function deg <- function(x) x*(180/pi)
Details
Why use a binary R file?
The .CSV files we use in other contexts to save blip information are not intended for data with varying numbers of columns. We could reserve a maximum number of columns corresponding to the maximum number of samples in a blip, but this is very inefficient.
How can a data.frame hold varying numbers of items in each row?
R's data.frame object is flexible enough to allow this. Each column in a data.frame is a vector, and usually these are atomic vectors (numeric, character, etc.). However, R allows a data.frame column to be a list, which is a vector whose elements are arbitrary R objects. In both cases, each slot in the column vector corresponds to one cell in the data.frame, but for list columns, the slot can hold a vector, instead of just a single item. In our script, we use list columns to hold data for every sample in a blip:
- samp.r: the sample range in metres (note that the column "range" is the mean range for the entire blip)
- samp.theta: the azimuth angle in degrees clockwise from North
- samp.phi: the elevation angle in degrees above the horizontal
- samp.dbm: the echo strength in dbm
Here is an R session transcript showing how we can use the binary data saved by export_blips.R:
> load("blips.RData") ## a file saved by export_blips.R
> dim(blips) ## the name of the variable, "blips", is saved in the .RData file
[1] 6 17 ## there are 6 blips; each row of the dataframe corresponds to one blip
> names(blips) ## some columns describe the blip overall, others describe each sample in the blip
[1] "x" "y" "z" "t" "ns"
[6] "area" "int" "max" "aspan" "rspan"
[11] "perim" "range" "samp.r" "samp.theta" "samp.phi"
[16] "samp.dbm" "r"
> class(blips$x) ## a standard, atomic vector column
[1] "numeric"
> class(blips$samp.r) ## a list vector column, which holds multiple items for each row
[1] "list"
> blips[1, "samp.r"] ## getting data from list columns works by indexing, as usual
[[1]] ## except that the results are in a list (this is a small blip with only 8 samples)
[1] 1797.5 1797.5 1797.5 1797.5 1797.5 1797.5 1797.5 1797.5
> sapply(blips$samp.r, length) ## to get the number of samples in each blip, we apply length to each slot in the samp.r list
[1] 8 18 17 19 19 11 ## we used sapply instead of lapply so that the answer would be an atomic vector
> i.max <- sapply(blips$samp.dbm, which.max) ## for each blip, which sample is brightest?
> i.max
[1] 7 6 5 9 17 6 ## for blip #1, the 7th sample is brightest
> blips$samp.dbm[[1]] ## another way to get the data from a list column; here, for blip # 1; note that the 7th sample is indeed brightest
[1] -75.65866 -74.96346 -75.11988 -75.06774 -75.34582 -74.28564 -73.06904
[8] -74.44206
## Now, for something a bit trickier, select for each blip those samples which are at the same range as the brightest sample.
> xc <- mapply(function(x, y) which(x == x[y]), blips$samp.r, i.max)
## For each blip, mapply passes the corresponding element of blips$samp.r and of i.max to the
## supplied function. Here, the function determines which of the sample ranges equals the brightest sample's range.
## This is the "angular cross section" of the blip, passing through the brightest sample.
## The result is a list of index vectors:
> xc
[[1]]
[1] 2 6 7
[[2]]
[1] 1 3 6 11 18
[[3]]
[1] 3 5 8 14
[[4]]
[1] 9 10 15 19
[[5]]
[1] 5 11 17
[[6]]
[1] 5 6 7 10
## Here's how to extract the echo strength along the cross-section for each blip:
> blips$samp.dbm <- mapply("[", blips$samp.dbm, xc)
## Notice that we've replaced the samp.dbm list column in the blips data.frame; we could just as easily have added
## a new column instead, like this:
> blips$xc.dbm <- mapply("[", blips$samp.dbm, xc)
See the script radR/util/slice_blips.R for more examples of how to work with saved blip data.