From fc0612600d271be2e02cbf6c32395e0b1441fc8d Mon Sep 17 00:00:00 2001 From: Alicia Key Date: Wed, 28 Dec 2022 09:39:15 -0700 Subject: [PATCH] Issue #15 Create the fft_plot() function, its tests, and its documentation. --- DESCRIPTION | 3 +- NAMESPACE | 4 +++ R/fft_plot.R | 58 ++++++++++++++++++++++++++++++++++ man/fft_plot.Rd | 34 ++++++++++++++++++++ tests/testthat/test-fft_plot.R | 7 ++++ 5 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 R/fft_plot.R create mode 100644 man/fft_plot.Rd create mode 100644 tests/testthat/test-fft_plot.R diff --git a/DESCRIPTION b/DESCRIPTION index 6a09393..e284c1b 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -17,4 +17,5 @@ Config/testthat/parallel: true Imports: dplyr, ggplot2, - magrittr + magrittr, + tidyr diff --git a/NAMESPACE b/NAMESPACE index ea35b4e..c7db33e 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -4,14 +4,18 @@ export("%>%") export(compute_fft) export(cos_sum) export(exp_decay) +export(fft_plot) export(length_norm) export(waveform) export(waveform_plot) +importFrom(dplyr,filter) importFrom(dplyr,mutate) +importFrom(dplyr,transmute) importFrom(ggplot2,aes) importFrom(ggplot2,geom_line) importFrom(ggplot2,ggplot) importFrom(ggplot2,labs) importFrom(magrittr,"%>%") importFrom(stats,fft) +importFrom(tidyr,pivot_longer) importFrom(utils,tail) diff --git a/R/fft_plot.R b/R/fft_plot.R new file mode 100644 index 0000000..990a84c --- /dev/null +++ b/R/fft_plot.R @@ -0,0 +1,58 @@ +utils::globalVariables(c(".idx", ".value", ".mod", ".re", ".im", "component", "value")) + +#' fft_plot() +#' +#' @param incoming Required. A data.frame with the incoming waveform. +#' @param show Optional. Either "half" (which shows the modulus of the FFT up to half of its values to display frequencies up to the Nyquist limit) or "everything" (which shows modulus, real, and imaginary components of all values.) +#' @param ... Optional. If specified, passed to the ggplot2 labs() function. +#' +#' @return ggplot() object of the FFT +#' @export +#' @importFrom ggplot2 ggplot +#' @importFrom ggplot2 aes +#' @importFrom ggplot2 geom_line +#' @importFrom ggplot2 labs +#' @importFrom dplyr transmute +#' @importFrom dplyr filter +#' @importFrom tidyr pivot_longer +#' +#' @examples +#' waveform(duration_s = 1.0, sr = 10) %>% +#' cos_sum(freqs = c(2.0, 3.0), amplitudes = c(0.5, 1.0)) %>% +#' length_norm() %>% +#' compute_fft() %>% +#' fft_plot(show = "everything") +#' +#' waveform(duration_s = 1.0, sr = 10) %>% +#' cos_sum(freqs = c(2.0, 3.0), amplitudes = c(0.5, 1.0)) %>% +#' length_norm() %>% +#' compute_fft() %>% +#' fft_plot(show = "half") +fft_plot <- function(incoming, show = "everything", ...) { + stopifnot("incoming must be a data.frame with an FFT." = is.data.frame(incoming)) + stopifnot("show argument must be \"everything\" or \"half\"." = show %in% c("half", "everything")) + + plot_data <- incoming %>% + dplyr::transmute( + .idx, + .re = Re(.value), + .im = Im(.value), + .mod = Mod(.value) + ) %>% + tidyr::pivot_longer(-.idx, names_to = "component", values_to = "value") + + if (show == "everything") { + result <- ggplot2::ggplot(plot_data, aes(x = .idx, y = value)) + + ggplot2::geom_point() + + ggplot2::facet_wrap(~ component, nrow = 3) + } + else { + result <- plot_data %>% + dplyr::filter(component == ".mod", .idx <= max(incoming$.idx) / 2) %>% + ggplot2::ggplot(aes(x = .idx, y = value)) + + ggplot2::geom_point() + } + + result + + labs(...) +} diff --git a/man/fft_plot.Rd b/man/fft_plot.Rd new file mode 100644 index 0000000..534621b --- /dev/null +++ b/man/fft_plot.Rd @@ -0,0 +1,34 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/fft_plot.R +\name{fft_plot} +\alias{fft_plot} +\title{fft_plot()} +\usage{ +fft_plot(incoming, show = "everything", ...) +} +\arguments{ +\item{incoming}{Required. A data.frame with the incoming waveform.} + +\item{show}{Optional. Either "half" (which shows the modulus of the FFT up to half of its values to display frequencies up to the Nyquist limit) or "everything" (which shows modulus, real, and imaginary components of all values.)} + +\item{...}{Optional. If specified, passed to the ggplot2 labs() function.} +} +\value{ +ggplot() object of the FFT +} +\description{ +fft_plot() +} +\examples{ +waveform(duration_s = 1.0, sr = 10) \%>\% + cos_sum(freqs = c(2.0, 3.0), amplitudes = c(0.5, 1.0)) \%>\% + length_norm() \%>\% + compute_fft() \%>\% + fft_plot(show = "everything") + +waveform(duration_s = 1.0, sr = 10) \%>\% + cos_sum(freqs = c(2.0, 3.0), amplitudes = c(0.5, 1.0)) \%>\% + length_norm() \%>\% + compute_fft() \%>\% + fft_plot(show = "half") +} diff --git a/tests/testthat/test-fft_plot.R b/tests/testthat/test-fft_plot.R new file mode 100644 index 0000000..bf65894 --- /dev/null +++ b/tests/testthat/test-fft_plot.R @@ -0,0 +1,7 @@ +test_that("fft_plot() expects incoming to be a data.frame", { + expect_error(fft_plot(show = "half")) +}) + +test_that("fft_plot() expects show to be \"half\" or \"everything\".", { + expect_error(fft_plot(data.frame(), show = "nothing")) +})