Skip to contents
1. How should I format my data for analysis in chromatographR?

chromatographR functions expect chromatograms to be in wide format with retention times as rownames. Thus, if you have a csv file with retention times in the first column, you should be able to read the files into R as follows:

lapply(vector_of_file_paths, function(f){
  read.csv(f, row.names = 1)
})

If you have chromatograms in “long” format, you will need to reshape them into wide format before proceeding with the analysis.

2. Some of my peaks aren’t being integrated when I run get_peaks.

get_peaks keeps every peak it fits, but filter_peaks with max_fwhm discards peaks wider than that, so your widest peaks are the first to go. What counts as a sensible value depends on your data, so measure your peak widths first (see the peak-finding article). In the example below, max_fwhm = 0.12 drops many of the wider peaks that get_peaks found. If peaks are still missing, try adjusting smooth_window, which is passed to find_peaks.

data(Sa_warp)
par(mfrow=c(2,1))
pks <- get_peaks(Sa_warp, lambdas = "210", fit = "egh")
plot(pks, main = "All peaks")
plot(filter_peaks(pks, max_fwhm = 0.12), main = "`max_fwhm` = 0.12")

3. Why don’t my peak areas match ChemStation (or Empower, LabSolutions, Chromeleon)?

Check the units and the signal first. Vendor software usually reports areas in mAU·s, while get_peaks reports them in the units of the time axis, usually mAU·min. Set time_unit = "s" in get_peaks or multiply by 60 before comparing. Vendor signals are also often defined with a bandwidth and a reference wavelength (e.g. 229 nm, with a reference at 360 nm and a bandwidth of 100 nm). Integrate at the same wavelength and set reference_wavelengths in preprocess to the same band (here, c(310, 410)).

If isolated peaks now agree but peaks in clusters do not, the difference is in how the baseline is drawn. Vendor integrators find where each peak starts and ends from slope thresholds and draw a straight baseline between those points. Peaks that are not resolved to baseline share one straight line and are split by vertical drop lines at the valleys, or skimmed off the tail of a larger peak. By default, chromatographR instead subtracts one baseline across the whole chromatogram (preprocess) and fits a peak shape to each peak (get_peaks), so overlapping peaks are separated by their fitted shapes. With baseline = "flat" or "sloped", get_peaks also fits a local baseline under each peak, within that peak’s own integration window. Unlike in drop-line integration, neighboring peaks never share a baseline (see Local baselines in get_peaks).

The two approaches diverge most in long chains of overlapping peaks. A straight baseline shared by the whole chain can run below the background on either side of it, adding a roughly fixed amount of area to each peak in the chain. This inflates small peaks the most and pulls ratios between samples towards one. In ChemStation reports, these peaks have the baseline codes BV, VV or VB rather than BB. Vendor software does not report where it drew the baseline, but its height under the apex is the signal at the apex minus the reported peak height, which you can compare with the background before the peak.

Neither result is ground truth. Vendor integration can be tuned with timed events (e.g. skims, valley-to-valley baselines, or baseline hold), and chromatographR’s baseline estimators have their own failure modes: too flexible a baseline absorbs small or broad peaks (see baseline_estimators). A useful check is to compare well-resolved (BB) peaks first. If those agree, the remaining differences likely come from how each program handles overlapping peaks.