0

I am trying to find a way to calculate the FWHM of a spectra peak using R programming.

The following dataset is used to get one of the peaks:

theta <- c(32.1, 32.2, 32.3,32.4,32.5, 32.6, 32.7, 32.8, 32.9, 33.0, 33.1)
intensity <- c(0, 0, 18, 138, 405, 449, 187, 29, 2, 0, 0)

Geom_line is the way I chose to plot this. The code used:

pacman::p_load(pacman, ggplot2, dplyr, tidyverse, svglite)
DataOne <- data.frame(thetaOne, intensityOne)
view (DataOne)
PlotOne <- ggplot(data = DataOne) +
  geom_line(aes(x = thetaOne, y = intensityOne))
PlotOne

My wish is after plotting the spectra I can calculate the Full Width at Half Maximum of the peaks (the width at half the height of the peak) in each spectrum. The dataset I use is much bigger than the one provided above. If possible, I would like a function that allowed me to select the region in the x axis that the peak starts and ends.

I found this: Determining FWHM from a distribution in R. However, it seems outdated, almost 5 years old. Also, I didn't understand what they proposed as a solution.

1 Answers1

2

This little function will return a data frame of the x, y co-ordinates of the FWHM given the input x, y values of a peaked curve:

fwhm <- function(x, y) {
  peak <- which.max(y)
  pre  <- seq(peak)
  post <- peak:length(x)
  half <- y[peak]/2
  xvals <- suppressWarnings(c(approx(y[pre], x[pre], xout = half)$y, 
                              approx(y[post], x[post], xout = half)$y))
  
  ss <- which(x > min(xvals) & x < max(xvals))
  data.frame(x = c(min(xvals), x[ss], max(xvals)),
             y = c(half, y[ss], half))
}

To use it in your case, we can just do:

half_width <- fwhm(DataOne$thetaOne, DataOne$intensityOne)

We can get the x values of our width at half-maximum with:

range(half_width$x)
#> [1] 32.43240 32.68569

And plotting it can be done like this:

ggplot(data = DataOne, aes(x = thetaOne, y = intensityOne)) +
  geom_line() +
  geom_area(data = half_width, aes(x, y), fill = "red", alpha = 0.3) +
  theme_minimal(base_size = 16)

enter image description here

Allan Cameron
  • 147,086
  • 7
  • 49
  • 87
  • Great! What package should I get to ue that FWHM function? I tried running the code you suggested and I get "Error in fwhm(DataOne$thetaOne, DataOne$intensityOne) : could not find function "fwhm". Thank you! – Giovanni Saboia Feb 15 '23 at 11:21
  • @GiovanniSaboia the fwhm function is at the top of my answer. Just run the code I have provided. – Allan Cameron Feb 15 '23 at 11:24
  • Ok, my bad. It works now. In case I have more than one peak, how can I select which peak it will calculate the FWHM? For exemple, if I have the following dataset: theta <- c(32.1, 32.2, 32.3,32.4,32.5, 32.6, 32.7, 32.8, 32.9, 33.0, 33.1, 33.2, 33.3, 33.4, 33.5 38, 38.1, 38.2, 38.3, 38.4, 38.5, 38.6, 38.7, 38.8, 38.9, 39) intensity <- c(0, 0, 18, 138, 405, 449, 187, 29, 2, 0, 0, 0, 0, 0 ,0, 0, 21, 149, 227, 468, 675, 429, 190, 40, 1,0) – Giovanni Saboia Feb 15 '23 at 13:40