DEprot 
v2.1.0 - August 24th 2026
- added
estimate.powerfunction to compute sample size and power estimation - updated overview vignette, manual and tests accordingly
- added
heatmap.counts.anno(): the heatmap ofheatmap.counts(), with the same data selection (which.data,contrast,top.n,sample.subset,protein.subset,group.by.metadata.column,scale), drawn withComplexHeatmapinstead ofggplot2. It returns the usualDEprot.counts.heatmapobject, whoseheatmapslot contains aHeatmapobject, hence it can be customized, drawn and concatenated with the standardComplexHeatmapsyntax ComplexHeatmapandcirclizeadded to the dependencies- added function
generate.mmto generate materials and methods paragraph DEprot.analysesis now defined as an extension of theDEprotclass (contains = "DEprot") instead of repeating its slot list: the two classes cannot drift apart anymoreanalyses.result.list,contrastsanddifferential.analyses.paramsare no longer slots ofDEprot, where they were declared but never filled- the functions accepting both classes test the input with
methods::is(x, "DEprot"), which is satisfied byDEprot.analysesobjects as well - added an
updateObject()method forDEprot: it removes the three unused slots from the objects restored from a.rdsfile written with a previous version - added
perform.sPLSDA(): sparse Partial Least Squares Discriminant Analysis (sPLS-DA) on aDEprotobject. Differently from the PCA and the PCoA, which show the largest source of variability whatever its origin, it looks for the directions separating a set of classes given by the user and selects the proteins responsible for that separation - the tuning of
keepXand the estimation of the classification performances happen insideperform.sPLSDA(): neither of them changes as long as the model does not change. The tuning runs whenkeepX = NULL, the validation whenvalidate = TRUE ncompis raised to 3 when a lower value is requested, and the number of folds is capped to the size of the smallest class (leave-one-out below 3 samples per class)- the sign of each component is fixed so that
reference.groupalways sits on the positive side: the orientation returned bymixOmicsis arbitrary and would change from one run to the next. The object stored in thesplsdaslot keeps the original mixOmics orientation - alongside the sparse model, a plain PLS-DA is fitted on the same data: it involves no resampling, and its loading vector covers every protein of the matrix, which is what a GSEA needs. The sparse loadings are zero for every protein that was not selected, hence a ranking made mostly of ties
- added the
DEprot.sPLSDAclass, with itsshow,summaryandplotmethods - added
get.sPLSDA.results(),get.sPLSDA.proteins()andget.sPLSDA.ranking() - added
sPLSDA.enrichment(): GSEA on the complete ranking, over-representation on the selected proteins, using as background the proteins that entered the model. It returns the usualDEprot.enrichResultobject, henceNES.plot(),plot.GSEA(),simplify.enrichment(),combine.enrichments()anddivergent.enrichment()work on it unchanged - added
plot.sPLSDA.scatter(),plot.sPLSDA.scatter.123(),plot.sPLSDA.cumulative(),plot.sPLSDA.biplot(),plot.sPLSDA.loadings(),plot.sPLSDA.tuning(),plot.sPLSDA.performance(),plot.sPLSDA.stability()andplot.sPLSDA.auroc() .ordination.slots()acceptsDEprot.sPLSDAobjects- added the internal
.append.protein.info(), used byget.sPLSDA.results()to append theprotein.infoannotation mixOmicsadded to the dependenciescompare.imp.methods()gainsmasking, which defines how the values of the test dataset are hidden. With"MCAR"(default, previous behaviour) every measured value has the same probability of being masked; with"intensity"the probability follows a logistic dropout curve estimated on the data, so that the masked values come from the low-intensity range at the rate at which the values are really lost- one dropout curve is estimated for each group of replicates (
dropout.by = "group") or for each sample (dropout.by = "sample"): an IgG control and an IP do not have the same detection depth and cannot be masked with the same curve. The curves are fitted on the complete table, since the proteins absent from an entire group carry the information about the detection limit and cannot belong to the test dataset max.NA.per.rowdefines how many missing values a protein can already have to be usable in the test dataset. The error is computed only on the masked cells, hence a protein does not need to be complete: keeping only the complete ones restricted the comparison to the abundant proteins, which hold less than a fifth of the values of the bottom 3% of the distribution.max.NA.fractioncaps the missingness reached after the masking, so that the table stays usable bymissForestand by the other methods needing a minimum number of values per protein- the number of missing values to introduce per group is now read from the names of the missingness table instead of the position in it: a group containing proteins missing in 0 and in all the replicates, without any of the intermediate cases, received 1 missing value where the pattern required all of them
- the proteins that do not have enough measured values left in a group are excluded from the candidates, and a value already missing can no longer be selected for the masking
- the settings and the estimated curves are stored in the new
maskingslot of theDEprot.RMSEobjects - the default parameters reproduce exactly the draw of the previous versions for a given
seed - in
load.counts*the columns of the counts are now reordered to match the same order fo the metadata table - in
impute.countsthe missForest mode was not using the seed provided by the user, now fixed diff.analyses.prolfqua: the counts are handed toprolfquadirectly in log2 scale and flagged as already transformed. They were converted back to the linear scale (2^x - 1) before the fit and log2-transformed again byprolfqua: the round trip does not return the starting values, the distortion grows towards the bottom of the distribution and does not cancel out in the contrast, and a value at or below 1 fell on 0 or on a negative intensity, switching the conversion of the whole contrast. The"logistf"strategy has been removed: Firth’s regression models the detection of a protein through a binary response and cannot return a fold change, while it was receiving the log2 abundances as response and its coefficients were reported as log2(FoldChange)- now
heatmap.countskeeps the order of samples/proteins provided for a subset (if no cluster is involved) - updated overview vignette, manual and tests accordingly
v2.0.0 - August 7th 2026
- added the protein.info slot to the DEprot and DEprot.analyses objects: an optional annotation table with one row per protein (gene symbol, description, number of peptides, etc.), kept row-by-row aligned with the counts
load.counts2()(andload.counts()) accept a protein.info table at loading; the IDs can be given as row names, in a prot.id column or in any column indicated by protein.info.id.column. The table is re-ordered on the counts: unannotated proteins are filled with NA and annotations of proteins absent from the counts are discarded- added
add.protein.info()to attach, replace or remove the annotation of an object built previously - added
get.protein.info()to extract the annotation table from an object, in the same fashion as get.metadata() - the annotation is propagated by
filter.proteins(),remove.undetected.proteins(),harmonize.batches(),filter.samples()and by all thediff.analyses*()functions get.results()gains protein.info.columns and protein.info.prefix: the annotation is appended only on request, using the keywords “none” (default) and “all” or a vector of column names. The columns are bound to the results by protein ID (not by position) and colliding names are made uniqueexport.analyses()writes the annotated results tables- objects created with previous versions of the package remain usable: the missing slot is interpreted as an absent annotation
- added
missingness.diagnostic(): classifies the missing values as MNAR-like or MCAR-like following the same rule of the double-imputation strategy, estimates the limit of detection by a logistic dropout model (LOD50), and returns the diagnostic plots (detection vs abundance densities, dropout curve, imputation map, Jaccard similarity of the detection patterns with dendrogram, per-sample and per-class summaries, UpSet of the MNAR-like patterns) - the parameters of
randomize.missing.values(group.column,percentage.missing,tail.percentage) are retrieved automatically when the randomization has already been run; the counts are selected at the lowest level available (raw > normalized > randomized > imputed) - contrast-level diagnostics are computed when a
DEprot.analysesobject is provided, including the directional MNAR classification and thetestableflag for the proteins missing in both groups - added class
DEprot.missingnesswithshow,summaryandplotmethods - fixed the
ComplexUpsetthemes inplot.upset(), which were not valid anymore sinceggplot2v4.0.0 - added time-course analyses:
analyze.timecourse()returns an object of the new classDEprot.timecourse(withshow,summaryandplotmethods). Time is handled as a numeric covariate: a natural-spline basis is fitted bylimmaand all the time coefficients are tested jointly by a moderated F-test, resulting in a single test per protein and therefore in no contrast to define analyze.timecourse(): the spline degrees of freedom are capped automatically atn.timepoints - 2(a saturated spline being equivalent to treating the time as a factor), and a linear trend is fitted below 4 timepoints; thetime.transformoption (log2,log10,log1p,sqrt) re-spaces log-spaced designs so that the last timepoint does not dominate the fitanalyze.timecourse(): the results table reports the kinetic descriptors of each fitted trajectory (amplitude,initial.slope,peak.time,trend.shape: monotone/transient/complex) together with the cluster assignment, the membership and the ranking scoreanalyze.timecourse(): the trending proteins are soft-clustered (c-means, or PAM) on the Z-scored fitted curves rather than on the raw timepoint means, which makes the clustering robust to unequal time spacing and to missing values; the fuzzifier and the number of clusters are estimated from the data when not provided- added
rank.timecourse()to re-rank the proteins, globally and within each cluster, without refitting the model, andget.timecourse.results()to retrieve the results with cluster/top-N subsetting - added
plot.timecourse.protein()(measured points, mean ± SEM and fitted trajectory of individual proteins) andplot.timecourse.profiles()(one panel per cluster, lines colored by membership). Both acceptvalues = "counts","log2FC"(relative toreference.time) or"zscore" - added
heatmap.timecourse(): heatmap of the trending proteins with the rows split by cluster, sortable byrank,membership,peak.time,amplitudeorhclust, and displaying either the measured means or the smooth fitted trajectories - added
timecourse.enrichment(): over-representation analyses run independently on each cluster, using all the quantified proteins as universe, returning an object of the new classDEprot.timecourse.enrichment(withshowandplotmethods). The dotplot shows the enrichment as dot size, the significance as color, and the number of proteins of the geneset written inside each dot splines,e1071andclusteradded to the dependencies- added
combine.enrichments(): merges a named list of enrichments in a single dotplot, with the discoveries on the x-axis and the genesets on the y-axis; the dots are sized by fold enrichment or gene ratio, colored by significance, and carry the protein count inside - added
divergent.enrichment(): plots two enrichments back-to-back, the second one with the sign inverted, to show together the two sides of the same contrast (e.g. ORA of the up- and down-regulated proteins); bar length can beFoldEnrichment,GeneRatio,Count,NESorpadj - both functions accept a mix of
DEprot.enrichResult,DEprot.timecourse.enrichment,enrichResult/gseaResult(clusterProfiler) objects and plain result tables; aDEprot.timecourse.enrichmentis expanded into one discovery per cluster - added the internal helpers
.parse.ratio(),.get.enrichment.table()and.collect.enrichments(), which harmonize the columns of GSEA and ORA results (for a GSEA the leading edge is used as equivalent of the ORACount);timecourse.enrichment()now uses the exported.parse.ratio()instead of its local copy - added
export.external(): converts aDEprot/DEprot.analysesobject into aSummarizedExperiment,QFeatures,MSnSet,limma::EListor a plain list of tables, with the shortcutsas.SummarizedExperiment(),as.QFeatures()andas.MSnSet() - all the count matrices available are exported as assays, the metadata become the column annotation, and
protein.infotogether with the differential results become the row annotation - the parameters that the destination classes cannot store (log base, normalization/imputation methods, contrasts, thresholds) are kept in the metadata of the exported object;
keep.object = TRUEallows a lossless round-trip SummarizedExperiment,QFeaturesandMSnbaseare optional dependencies: requested only when needed and never installed without confirmation- added
detect.outliers(): automatic per-sample QC flagging combining median inter-sample correlation, robust Mahalanobis distance in PC space and missing rate; returns aDEprot.outliersobject (withshowandplotmethods) whoseoutliersslot can be passed directly tofilter.samples() - added
diff.analyses.proDA(): differential analyses on left-censored data using proDA. The missing values are not replaced but modelled as observations below the detection limit, so that the uncertainty on the undetected values propagates into lfcSE instead of being compressed by the imputation. It requires counts that still contain the missing values (which.data = “normalized”) and it is the natural continuation of a strongly-MNAR verdict of missingness.diagnostic(), whose output can be passed directly through missingness.object the results table ofdiff.analyses.proDA()keeps the columns of the other differential functions and adds n.detected.and n.approx; each contrast stores a proDA.fit element with the fitted model and the per-sample dropout curves filter.samples()recognizes the new engine and re-runs the contrasts with the stored parametersdiff.analyses.limma()now returns the lfdr column when padj.method = “fdrtool”, as already stated in the manual proDA added to the dependencies- updated overview vignette, manual and tests accordingly
- added time-course vignette
v1.3.1 - August 3rd 2026
- added
import.external(): builds aDEprotobject directly from DIA-NN, Spectronaut, FragPipe, MaxQuant and Proteome Discoverer reports, with the shortcutsread.diann(),read.diann.matrix(),read.spectronaut(),read.fragpipe()andread.maxquant() - added
import.msstats()for the summarized objects ofMSstats(label-free) andMSstatsTMT(isobaric); the metadata are reconstructed from the object annotation when not provided iq(MaxLFQ summarization) andnanoparquet(DIA-NN.parquetreports) are optional dependencies: they are requested only when needed and never installed without confirmation- updated vignette and manual accordingly
v1.3.0 - July 30th 2026
plot.volcanoandplot.MAcan automatically plot the top N differential proteinsexport.reportwill plot the top.n proteins in the volcano- updated vignette and manual accordingly
- added Principal Coordinate Analysis:
perform.PCoA()withplot.PCoA.scatter(),plot.PCoA.scatter.123(),plot.PCoA.cumulative()andplot.PCoA.biplot(), computed from aDEprot.correlationobject - updated correlation class, now contains also a slot with the correlation method used
- re-arrangement of internal functions
- update vignette and manual
v1.2.0 - July 12th 2026
expression.boxplotfunction can now show pair-wise comparisonsdiff.analyses.limmacan usefdrtoolto adjust the p-values- added
plotmethod for objects of classDEprot,DEprot.analyses,DEprot.normality - added function
filter.samples - added function
export.reportto export an HTML QC-report - bug-fixed in
check.pvalueswhen prolfqua tables are provided - updated vignette and manual accordingly
v1.1.3 - July 8th 2026
harmonize.batches(): addedalgorithm(ComBat/limma),ComBat.mode, andblock; limma helps on sparse designs where ComBat hits a singular matrixharmonize.batches(): drop uncorrectable proteins with a warning, error on an empty result, and fix thealgorithm/blockdefaultsload.counts2automatically converts the counts into log2 transformed.diff.analyses,diff.analyses.limmaanddiff.analyses.prolfquanow return, for each group, the standard deviation (sd.<group>) and standard error of the mean (sem.<group>) of the log2 expression values, pluslfcSE, the standard error of the log2(FoldChange). The new columns are appended at the end of theresultstable.lfcSEisNAwhenstat.test = "wilcoxon"- updated manual and vignette accordingly to take into account for these exceptions and modifications
v1.1.2 - June 16th 2026
- Update labeling of groups for
NES.plotfunction - Bug fixing for heatmap function for showing the dendrogram in the plots
v1.1.1 - June 8th 2026
- Bug fixed in the PCA calculation, functions/objects concerned:
perform.PCA,diff.analyses*,plot.PC.buplotand thetest.toolbox, as well as the vignette and manual.
v1.1.0 - May 31st 2026
- Added the function
plot.PC.biplot. - Added the function
SAINTqand therime.dpoandrime.saintqdatasets. - Updated
plot.PC.scatterto allow for the separate plotting of x and y zero-lines. - Updated the vignette to include the new functions.
v1.0.0 - May 23rd 2026
- The result from
randomize.missing.valuesis now included in a separate slot. Also the a newboxplot.randomandrandomization.methodslots for the randomized scores have been added. - In the DEprot.objects the slot
imputationhas been renamed intoimputation.method. Many functions have been changed accordingly. - Due to the addition of new slots, multiple functions have been adapted.
- In the differential result tables now degrees of freedom and test statistic columns have been added.
- For power calculation analyses, an estimation of the distribution of the statistics has been added in the results list. For this also the dependencies of the package have been updated.
- For GSEA, gene ranking can be based now also on the test statistic value. Accordingly, the
compare.rankingfunction have been updated to compare all three methods. - Update of the vignette to include the
compare.imp.methodsfunction and the new updates. - Fixing a bug in handling single-sample groups for
randomize.missing.valuesfunction.
v0.1.1 - February 16th 2026
- Bug fixing on the
check.normalityfunction, which was inverting the evaluation of the AD’s test p-value. - Update of the vignette
- Update of the CITATION files
v0.1.0 - January 13th 2026
First release.