Quantification of Intact Monoclonal Antibody with LC-DAD
Ricardo Cunha
cunha@iuta.de19 August, 2025
Source:vignettes/articles/demo_lc_dad_quantification_antibody.Rmd
demo_lc_dad_quantification_antibody.Rmd
Introduction
This document demonstrates the quantification of the intact monoclonal antibody Bevacizumab using Liquid Chromatography with Diode Array Detection (LC-DAD). The files include a blank, a calibration set with 10 points from 0.5 to 5 mg/L, a QC triplicate with 2.5 mg/L, and a sample in triplicate to be quantified. The data was acquired with an Agilent 1260 Infinity II system coupled to a DAD detecter. The raw data files are in Agilent’s .d format.
basename(files)
[1] "0.5.d" "1.5.d"
[3] "1.d" "2.5.d"
[5] "2.d" "20240815_67_BVCZ_1.d"
[7] "20240815_67_BVCZ_2.d" "20240815_67_BVCZ_3.d"
[9] "3.5.d" "3.d"
[11] "4.5.d" "4.d"
[13] "5.d" "Blank.d"
[15] "QC_BVCZ_1608_2_5mgmL_1.d" "QC_BVCZ_1608_2_5mgmL_2.d"
[17] "QC_BVCZ_1608_2_5mgmL_3.d"
Processing Engine
The StreamFind
package provides a flexible and powerful
framework for processing mass spectrometry data. In this example, we
will use the MassSpecEngine
class to handle the LC-DAD
data. The engine will be initialized with the raw files, and we will
specify that the data should be centroided and processed at level 1.
Note that The msconvert
from ProteoWizard was used in
the background to convert the files to the open format mzML.
# Starts engine for quantification
ms <- StreamFind::MassSpecEngine$new(
metadata = list(name = "Quantification of Bevacizumab"),
analyses = files,
centroid = TRUE,
levels = 1
)
# Edit to assign analysis replicate groups
ms$Analyses <- set_replicate_names(
ms$Analyses,
c(
"cal_0.5",
"cal_1",
"cal_1.5",
"cal_2",
"cal_2.5",
rep("Sample", 3),
"cal_3",
"cal_3.5",
"cal_4",
"cal_4.5",
"cal_5",
"Blank",
rep("QC_2.5", 3)
)
)
# Concentration was obtained by attempting to convert the file names to numeric
# Alternatively, you can use the setter method ms$Analyses$concentrations to manually add the
# concentration values with NA_Real_ when the concentration is to be calculated
DT::datatable(
info(ms$Analyses)
)
Available Chromatograms
chroms = data.frame(
"name" = unique(ms$Analyses$analyses[[1]]$chromatograms_headers$id)
)
DT::datatable(chroms)
The chromatogram of interest is the DAD1 A: Sig=214,4 Ref=off, which is the second, and we know that our analyte elutes between 250 and 400 seconds.
Workflow
ms$run(
MassSpecMethod_LoadChromatograms_native(
chromatograms = chroms$name[2],
rtmin = 250,
rtmax = 400
)
)
plot_chromatograms(
ms$Results$MassSpecResults_Chromatograms,
colorBy = "replicates",
normalized = FALSE
)
ms$run(
MassSpecMethod_SmoothChromatograms_movingaverage(
windowSize = 3
)
)
ms$run(
MassSpecMethod_CorrectChromatogramsBaseline_airpls(
lambda = 25,
differences = 1,
itermax = 20
)
)
plot_chromatograms(
ms$Results$MassSpecResults_Chromatograms,
colorBy = "replicates",
normalized = FALSE
)
ms$run(
MassSpecMethod_IntegrateChromatograms_pracma(
merge = TRUE,
closeByThreshold = 5,
minPeakHeight = 10,
minPeakDistance = 3,
minPeakWidth = 5,
maxPeakWidth = 50,
minSN = 1
)
)
plot_chromatograms_peaks(
ms$Results$MassSpecResults_Chromatograms,
colorBy = "replicates+targets"
)
# Note that concentration values of the calibration curve
# were automatically obtained by the file name
ms$run(
MassSpecMethod_QuantifyChromatographicPeaks_native(
calibration = NA_real_,
value = "area",
model = "linear"
)
)
model <- ms$Results$MassSpecResults_Chromatograms$calibration_model
fitted_values <- stats::predict(model)
r_squared <- summary(model)$r.squared
dt_cal <- data.table::data.table(
fitted_values = fitted_values,
calibration_values = model$model$calibration,
values = model$model$values
)
fig <- plotly::plot_ly(
model$model,
x = ~calibration_values,
y = ~values,
type = 'scatter',
mode = 'markers',
name = "Data"
) %>%
add_lines(x = ~fitted_values, y = ~values, name = "Fitted Line") %>%
layout(
title = paste("Linear Regression (R² =", round(r_squared, 4), ")"),
xaxis = list(title = "mg/L"),
yaxis = list(title = "Intensity / counts"),
showlegend = TRUE
)
fig
peaks <- get_chromatograms_peaks(ms$Results$MassSpecResults_Chromatograms)
DT::datatable(peaks)