A Bioconductor workflow for processing, evaluating, and interpreting expression proteomics data

preprint OA: closed
Full text JSON View at publisher

Abstract

Background: Expression proteomics involves the global evaluation of protein abundances within a system. In turn, differential expression analysis can be used to investigate changes in protein abundance upon perturbation to such a system. Methods Here, we provide a workflow for the processing, analysis and interpretation of quantitative mass spectrometry-based expression proteomics data. This workflow utilises open-source R software packages from the Bioconductor project and guides users end-to-end and step-by-step through every stage of the analyses. As a use-case we generated expression proteomics data from HEK293 cells with and without a treatment. Of note, the experiment included cellular proteins labelled using tandem mass tag (TMT) technology and secreted proteins quantified using label-free quantitation (LFQ). Results The workflow explains the software infrastructure before focusing on data import, pre-processing and quality control. This is done individually for TMT and LFQ datasets. The application of statistical differential expression analysis is demonstrated, followed by interpretation via gene ontology enrichment analysis. Conclusions A comprehensive workflow for the processing, analysis and interpretation of expression proteomics is presented. The workflow is a valuable resource for the proteomics community and specifically beginners who are at least familiar with R who wish to understand and make data-driven decisions with regards to their analyses.
Full text 428,298 characters · extracted from preprint-html · click to expand
A Bioconductor workflow for processing, evaluating,... | F1000Research "use strict";function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}!function(){var t=function(){var t,e,o=[],n=window,r=n;for(;r;){try{if(r.frames.__tcfapiLocator){t=r;break}}catch(t){}if(r===n.top)break;r=r.parent}t||(!function t(){var e=n.document,o=!!n.frames.__tcfapiLocator;if(!o)if(e.body){var r=e.createElement("iframe");r.style.cssText="display:none",r.name="__tcfapiLocator",e.body.appendChild(r)}else setTimeout(t,5);return!o}(),n.__tcfapi=function(){for(var t=arguments.length,n=new Array(t),r=0;r 3&&2===parseInt(n[1],10)&&"boolean"==typeof n[3]&&(e=n[3],"function"==typeof n[2]&&n[2]("set",!0)):"ping"===n[0]?"function"==typeof n[2]&&n[2]({gdprApplies:e,cmpLoaded:!1,cmpStatus:"stub"}):o.push(n)},n.addEventListener("message",(function(t){var e="string"==typeof t.data,o={};if(e)try{o=JSON.parse(t.data)}catch(t){}else o=t.data;var n="object"===_typeof(o)&&null!==o?o.__tcfapiCall:null;n&&window.__tcfapi(n.command,n.version,(function(o,r){var a={__tcfapiReturn:{returnValue:o,success:r,callId:n.callId}};t&&t.source&&t.source.postMessage&&t.source.postMessage(e?JSON.stringify(a):a,"*")}),n.parameter)}),!1))};"undefined"!=typeof module?module.exports=t:t()}(); dataLayer = dataLayer || []; // Standard GTM initialization - Google Consent Mode handles consent automatically (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl+ '>m_auth=hzk0Vc3qFsQYhCrIoHz68A>m_preview=env-1>m_cookies_win=x';f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-MWFK8L5J'); ;window.NREUM||(NREUM={});NREUM.init={distributed_tracing:{enabled:true},privacy:{cookies_enabled:true},ajax:{deny_list:["bam.nr-data.net"]}}; ;NREUM.loader_config={accountID:"438030",trustKey:"438030",agentID:"772317073",licenseKey:"97f8f67f26",applicationID:"772317073"} ;NREUM.info={beacon:"bam.nr-data.net",errorBeacon:"bam.nr-data.net",licenseKey:"97f8f67f26",applicationID:"772317073",sa:1} ;/*! For license information please see nr-loader-spa-1.236.0.min.js.LICENSE.txt */ (()=>{"use strict";var e,t,r={5763:(e,t,r)=>{r.d(t,{P_:()=>l,Mt:()=>g,C5:()=>s,DL:()=>v,OP:()=>T,lF:()=>D,Yu:()=>y,Dg:()=>h,CX:()=>c,GE:()=>b,sU:()=>_});var n=r(8632),i=r(9567);const o={beacon:n.ce.beacon,errorBeacon:n.ce.errorBeacon,licenseKey:void 0,applicationID:void 0,sa:void 0,queueTime:void 0,applicationTime:void 0,ttGuid:void 0,user:void 0,account:void 0,product:void 0,extra:void 0,jsAttributes:{},userAttributes:void 0,atts:void 0,transactionName:void 0,tNamePlain:void 0},a={};function s(e){if(!e)throw new Error("All info objects require an agent identifier!");if(!a[e])throw new Error("Info for ".concat(e," was never set"));return a[e]}function c(e,t){if(!e)throw new Error("All info objects require an agent identifier!");a[e]=(0,i.D)(t,o),(0,n.Qy)(e,a[e],"info")}var u=r(7056);const d=()=>{const e={blockSelector:"[data-nr-block]",maskInputOptions:{password:!0}};return{allow_bfcache:!0,privacy:{cookies_enabled:!0},ajax:{deny_list:void 0,enabled:!0,harvestTimeSeconds:10},distributed_tracing:{enabled:void 0,exclude_newrelic_header:void 0,cors_use_newrelic_header:void 0,cors_use_tracecontext_headers:void 0,allowed_origins:void 0},session:{domain:void 0,expiresMs:u.oD,inactiveMs:u.Hb},ssl:void 0,obfuscate:void 0,jserrors:{enabled:!0,harvestTimeSeconds:10},metrics:{enabled:!0},page_action:{enabled:!0,harvestTimeSeconds:30},page_view_event:{enabled:!0},page_view_timing:{enabled:!0,harvestTimeSeconds:30,long_task:!1},session_trace:{enabled:!0,harvestTimeSeconds:10},harvest:{tooManyRequestsDelay:60},session_replay:{enabled:!1,harvestTimeSeconds:60,sampleRate:.1,errorSampleRate:.1,maskTextSelector:"*",maskAllInputs:!0,get blockClass(){return"nr-block"},get ignoreClass(){return"nr-ignore"},get maskTextClass(){return"nr-mask"},get blockSelector(){return e.blockSelector},set blockSelector(t){e.blockSelector+=",".concat(t)},get maskInputOptions(){return e.maskInputOptions},set maskInputOptions(t){e.maskInputOptions={...t,password:!0}}},spa:{enabled:!0,harvestTimeSeconds:10}}},f={};function l(e){if(!e)throw new Error("All configuration objects require an agent identifier!");if(!f[e])throw new Error("Configuration for ".concat(e," was never set"));return f[e]}function h(e,t){if(!e)throw new Error("All configuration objects require an agent identifier!");f[e]=(0,i.D)(t,d()),(0,n.Qy)(e,f[e],"config")}function g(e,t){if(!e)throw new Error("All configuration objects require an agent identifier!");var r=l(e);if(r){for(var n=t.split("."),i=0;i {r.d(t,{D:()=>i});var n=r(50);function i(e,t){try{if(!e||"object"!=typeof e)return(0,n.Z)("Setting a Configurable requires an object as input");if(!t||"object"!=typeof t)return(0,n.Z)("Setting a Configurable requires a model to set its initial properties");const r=Object.create(Object.getPrototypeOf(t),Object.getOwnPropertyDescriptors(t)),o=0===Object.keys(r).length?e:r;for(let a in o)if(void 0!==e[a])try{"object"==typeof e[a]&&"object"==typeof t[a]?r[a]=i(e[a],t[a]):r[a]=e[a]}catch(e){(0,n.Z)("An error occurred while setting a property of a Configurable",e)}return r}catch(e){(0,n.Z)("An error occured while setting a Configurable",e)}}},6818:(e,t,r)=>{r.d(t,{Re:()=>i,gF:()=>o,q4:()=>n});const n="1.236.0",i="PROD",o="CDN"},385:(e,t,r)=>{r.d(t,{FN:()=>a,IF:()=>u,Nk:()=>f,Tt:()=>s,_A:()=>o,il:()=>n,pL:()=>c,v6:()=>i,w1:()=>d});const n="undefined"!=typeof window&&!!window.document,i="undefined"!=typeof WorkerGlobalScope&&("undefined"!=typeof self&&self instanceof WorkerGlobalScope&&self.navigator instanceof WorkerNavigator||"undefined"!=typeof globalThis&&globalThis instanceof WorkerGlobalScope&&globalThis.navigator instanceof WorkerNavigator),o=n?window:"undefined"!=typeof WorkerGlobalScope&&("undefined"!=typeof self&&self instanceof WorkerGlobalScope&&self||"undefined"!=typeof globalThis&&globalThis instanceof WorkerGlobalScope&&globalThis),a=""+o?.location,s=/iPad|iPhone|iPod/.test(navigator.userAgent),c=s&&"undefined"==typeof SharedWorker,u=(()=>{const e=navigator.userAgent.match(/Firefox[/\s](\d+\.\d+)/);return Array.isArray(e)&&e.length>=2?+e[1]:0})(),d=Boolean(n&&window.document.documentMode),f=!!navigator.sendBeacon},1117:(e,t,r)=>{r.d(t,{w:()=>o});var n=r(50);const i={agentIdentifier:"",ee:void 0};class o{constructor(e){try{if("object"!=typeof e)return(0,n.Z)("shared context requires an object as input");this.sharedContext={},Object.assign(this.sharedContext,i),Object.entries(e).forEach((e=>{let[t,r]=e;Object.keys(i).includes(t)&&(this.sharedContext[t]=r)}))}catch(e){(0,n.Z)("An error occured while setting SharedContext",e)}}}},8e3:(e,t,r)=>{r.d(t,{L:()=>d,R:()=>c});var n=r(2177),i=r(1284),o=r(4322),a=r(3325);const s={};function c(e,t){const r={staged:!1,priority:a.p[t]||0};u(e),s[e].get(t)||s[e].set(t,r)}function u(e){e&&(s[e]||(s[e]=new Map))}function d(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"feature";if(u(e),!e||!s[e].get(t))return a(t);s[e].get(t).staged=!0;const r=[...s[e]];function a(t){const r=e?n.ee.get(e):n.ee,a=o.X.handlers;if(r.backlog&&a){var s=r.backlog[t],c=a[t];if(c){for(var u=0;s&&u {let[t,r]=e;return r.staged}))&&(r.sort(((e,t)=>e[1].priority-t[1].priority)),r.forEach((e=>{let[t]=e;a(t)})))}function f(e,t){var r=e[1];(0,i.D)(t[r],(function(t,r){var n=e[0];if(r[0]===n){var i=r[1],o=e[3],a=e[2];i.apply(o,a)}}))}},2177:(e,t,r)=>{r.d(t,{c:()=>f,ee:()=>u});var n=r(8632),i=r(2210),o=r(1284),a=r(5763),s="nr@context";let c=(0,n.fP)();var u;function d(){}function f(e){return(0,i.X)(e,s,l)}function l(){return new d}function h(){u.aborted=!0,u.backlog={}}c.ee?u=c.ee:(u=function e(t,r){var n={},c={},f={},g=!1;try{g=16===r.length&&(0,a.OP)(r).isolatedBacklog}catch(e){}var p={on:b,addEventListener:b,removeEventListener:y,emit:v,get:x,listeners:w,context:m,buffer:A,abort:h,aborted:!1,isBuffering:E,debugId:r,backlog:g?{}:t&&"object"==typeof t.backlog?t.backlog:{}};return p;function m(e){return e&&e instanceof d?e:e?(0,i.X)(e,s,l):l()}function v(e,r,n,i,o){if(!1!==o&&(o=!0),!u.aborted||i){t&&o&&t.emit(e,r,n);for(var a=m(n),s=w(e),d=s.length,f=0;fn,p:()=>i});var n=r(2177).ee.get("handle");function i(e,t,r,i,o){o?(o.buffer([e],i),o.emit(e,t,r)):(n.buffer([e],i),n.emit(e,t,r))}},4322:(e,t,r)=>{r.d(t,{X:()=>o});var n=r(5546);o.on=a;var i=o.handlers={};function o(e,t,r,o){a(o||n.E,i,e,t,r)}function a(e,t,r,i,o){o||(o="feature"),e||(e=n.E);var a=t[o]=t[o]||{};(a[r]=a[r]||[]).push([e,i])}},3239:(e,t,r)=>{r.d(t,{bP:()=>s,iz:()=>c,m$:()=>a});var n=r(385);let i=!1,o=!1;try{const e={get passive(){return i=!0,!1},get signal(){return o=!0,!1}};n._A.addEventListener("test",null,e),n._A.removeEventListener("test",null,e)}catch(e){}function a(e,t){return i||o?{capture:!!e,passive:i,signal:t}:!!e}function s(e,t){let r=arguments.length>2&&void 0!==arguments[2]&&arguments[2],n=arguments.length>3?arguments[3]:void 0;window.addEventListener(e,t,a(r,n))}function c(e,t){let r=arguments.length>2&&void 0!==arguments[2]&&arguments[2],n=arguments.length>3?arguments[3]:void 0;document.addEventListener(e,t,a(r,n))}},4402:(e,t,r)=>{r.d(t,{Ht:()=>u,M:()=>c,Rl:()=>a,ky:()=>s});var n=r(385);const i="xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx";function o(e,t){return e?15&e[t]:16*Math.random()|0}function a(){const e=n._A?.crypto||n._A?.msCrypto;let t,r=0;return e&&e.getRandomValues&&(t=e.getRandomValues(new Uint8Array(31))),i.split("").map((e=>"x"===e?o(t,++r).toString(16):"y"===e?(3&o()|8).toString(16):e)).join("")}function s(e){const t=n._A?.crypto||n._A?.msCrypto;let r,i=0;t&&t.getRandomValues&&(r=t.getRandomValues(new Uint8Array(31)));const a=[];for(var s=0;s {r.d(t,{Bq:()=>n,Hb:()=>o,oD:()=>i});const n="NRBA",i=144e5,o=18e5},7894:(e,t,r)=>{function n(){return Math.round(performance.now())}r.d(t,{z:()=>n})},7243:(e,t,r)=>{r.d(t,{e:()=>o});var n=r(385),i={};function o(e){if(e in i)return i[e];if(0===(e||"").indexOf("data:"))return{protocol:"data"};let t;var r=n._A?.location,o={};if(n.il)t=document.createElement("a"),t.href=e;else try{t=new URL(e,r.href)}catch(e){return o}o.port=t.port;var a=t.href.split("://");!o.port&&a[1]&&(o.port=a[1].split("/")[0].split("@").pop().split(":")[1]),o.port&&"0"!==o.port||(o.port="https"===a[0]?"443":"80"),o.hostname=t.hostname||r.hostname,o.pathname=t.pathname,o.protocol=a[0],"/"!==o.pathname.charAt(0)&&(o.pathname="/"+o.pathname);var s=!t.protocol||":"===t.protocol||t.protocol===r.protocol,c=t.hostname===r.hostname&&t.port===r.port;return o.sameOrigin=s&&(!t.hostname||c),"/"===o.pathname&&(i[e]=o),o}},50:(e,t,r)=>{function n(e,t){"function"==typeof console.warn&&(console.warn("New Relic: ".concat(e)),t&&console.warn(t))}r.d(t,{Z:()=>n})},2587:(e,t,r)=>{r.d(t,{N:()=>c,T:()=>u});var n=r(2177),i=r(5546),o=r(8e3),a=r(3325);const s={stn:[a.D.sessionTrace],err:[a.D.jserrors,a.D.metrics],ins:[a.D.pageAction],spa:[a.D.spa],sr:[a.D.sessionReplay,a.D.sessionTrace]};function c(e,t){const r=n.ee.get(t);e&&"object"==typeof e&&(Object.entries(e).forEach((e=>{let[t,n]=e;void 0===u[t]&&(s[t]?s[t].forEach((e=>{n?(0,i.p)("feat-"+t,[],void 0,e,r):(0,i.p)("block-"+t,[],void 0,e,r),(0,i.p)("rumresp-"+t,[Boolean(n)],void 0,e,r)})):n&&(0,i.p)("feat-"+t,[],void 0,void 0,r),u[t]=Boolean(n))})),Object.keys(s).forEach((e=>{void 0===u[e]&&(s[e]?.forEach((t=>(0,i.p)("rumresp-"+e,[!1],void 0,t,r))),u[e]=!1)})),(0,o.L)(t,a.D.pageViewEvent))}const u={}},2210:(e,t,r)=>{r.d(t,{X:()=>i});var n=Object.prototype.hasOwnProperty;function i(e,t,r){if(n.call(e,t))return e[t];var i=r();if(Object.defineProperty&&Object.keys)try{return Object.defineProperty(e,t,{value:i,writable:!0,enumerable:!1}),i}catch(e){}return e[t]=i,i}},1284:(e,t,r)=>{r.d(t,{D:()=>n});const n=(e,t)=>Object.entries(e||{}).map((e=>{let[r,n]=e;return t(r,n)}))},4351:(e,t,r)=>{r.d(t,{P:()=>o});var n=r(2177);const i=()=>{const e=new WeakSet;return(t,r)=>{if("object"==typeof r&&null!==r){if(e.has(r))return;e.add(r)}return r}};function o(e){try{return JSON.stringify(e,i())}catch(e){try{n.ee.emit("internal-error",[e])}catch(e){}}}},3960:(e,t,r)=>{r.d(t,{K:()=>a,b:()=>o});var n=r(3239);function i(){return"undefined"==typeof document||"complete"===document.readyState}function o(e,t){if(i())return e();(0,n.bP)("load",e,t)}function a(e){if(i())return e();(0,n.iz)("DOMContentLoaded",e)}},8632:(e,t,r)=>{r.d(t,{EZ:()=>u,Qy:()=>c,ce:()=>o,fP:()=>a,gG:()=>d,mF:()=>s});var n=r(7894),i=r(385);const o={beacon:"bam.nr-data.net",errorBeacon:"bam.nr-data.net"};function a(){return i._A.NREUM||(i._A.NREUM={}),void 0===i._A.newrelic&&(i._A.newrelic=i._A.NREUM),i._A.NREUM}function s(){let e=a();return e.o||(e.o={ST:i._A.setTimeout,SI:i._A.setImmediate,CT:i._A.clearTimeout,XHR:i._A.XMLHttpRequest,REQ:i._A.Request,EV:i._A.Event,PR:i._A.Promise,MO:i._A.MutationObserver,FETCH:i._A.fetch}),e}function c(e,t,r){let i=a();const o=i.initializedAgents||{},s=o[e]||{};return Object.keys(s).length||(s.initializedAt={ms:(0,n.z)(),date:new Date}),i.initializedAgents={...o,[e]:{...s,[r]:t}},i}function u(e,t){a()[e]=t}function d(){return function(){let e=a();const t=e.info||{};e.info={beacon:o.beacon,errorBeacon:o.errorBeacon,...t}}(),function(){let e=a();const t=e.init||{};e.init={...t}}(),s(),function(){let e=a();const t=e.loader_config||{};e.loader_config={...t}}(),a()}},7956:(e,t,r)=>{r.d(t,{N:()=>i});var n=r(3239);function i(e){let t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],r=arguments.length>2?arguments[2]:void 0,i=arguments.length>3?arguments[3]:void 0;return void(0,n.iz)("visibilitychange",(function(){if(t)return void("hidden"==document.visibilityState&&e());e(document.visibilityState)}),r,i)}},1214:(e,t,r)=>{r.d(t,{em:()=>v,u5:()=>N,QU:()=>S,_L:()=>I,Gm:()=>L,Lg:()=>M,gy:()=>U,BV:()=>Q,Kf:()=>ee});var n=r(2177);const i="nr@original";var o=Object.prototype.hasOwnProperty,a=!1;function s(e,t){return e||(e=n.ee),r.inPlace=function(e,t,n,i,o){n||(n="");var a,s,c,u="-"===n.charAt(0);for(c=0;c 2?n-2:0),o=2;o {r(A[T],e,w),r(E[T],e,w)})),r(l._A,"fetch",y),t.on(y+"end",(function(e,r){var n=this;if(r){var i=r.headers.get("content-length");null!==i&&(n.rxSize=i),t.emit(y+"done",[null,r],n)}else t.emit(y+"done",[e],n)})),t}const O={},j=["pushState","replaceState"];function S(e){const t=function(e){return(e||n.ee).get("history")}(e);return!l.il||O[t.debugId]++||(O[t.debugId]=1,s(t).inPlace(window.history,j,"-")),t}var P=r(3239);const C={},R=["appendChild","insertBefore","replaceChild"];function I(e){const t=function(e){return(e||n.ee).get("jsonp")}(e);if(!l.il||C[t.debugId])return t;C[t.debugId]=!0;var r=s(t),i=/[?&](?:callback|cb)=([^&#]+)/,o=/(.*)\.([^.]+)/,a=/^(\w+)(\.|$)(.*)$/;function c(e,t){var r=e.match(a),n=r[1],i=r[3];return i?c(i,t[n]):t[n]}return r.inPlace(Node.prototype,R,"dom-"),t.on("dom-start",(function(e){!function(e){if(!e||"string"!=typeof e.nodeName||"script"!==e.nodeName.toLowerCase())return;if("function"!=typeof e.addEventListener)return;var n=(a=e.src,s=a.match(i),s?s[1]:null);var a,s;if(!n)return;var u=function(e){var t=e.match(o);if(t&&t.length>=3)return{key:t[2],parent:c(t[1],window)};return{key:e,parent:window}}(n);if("function"!=typeof u.parent[u.key])return;var d={};function f(){t.emit("jsonp-end",[],d),e.removeEventListener("load",f,(0,P.m$)(!1)),e.removeEventListener("error",l,(0,P.m$)(!1))}function l(){t.emit("jsonp-error",[],d),t.emit("jsonp-end",[],d),e.removeEventListener("load",f,(0,P.m$)(!1)),e.removeEventListener("error",l,(0,P.m$)(!1))}r.inPlace(u.parent,[u.key],"cb-",d),e.addEventListener("load",f,(0,P.m$)(!1)),e.addEventListener("error",l,(0,P.m$)(!1)),t.emit("new-jsonp",[e.src],d)}(e[0])})),t}var k=r(5763);const H={};function L(e){const t=function(e){return(e||n.ee).get("mutation")}(e);if(!l.il||H[t.debugId])return t;H[t.debugId]=!0;var r=s(t),i=k.Yu.MO;return i&&(window.MutationObserver=function(e){return this instanceof i?new i(r(e,"fn-")):i.apply(this,arguments)},MutationObserver.prototype=i.prototype),t}const z={};function M(e){const t=function(e){return(e||n.ee).get("promise")}(e);if(z[t.debugId])return t;z[t.debugId]=!0;var r=n.c,o=s(t),a=k.Yu.PR;return a&&function(){function e(r){var n=t.context(),i=o(r,"executor-",n,null,!1);const s=Reflect.construct(a,[i],e);return t.context(s).getCtx=function(){return n},s}l._A.Promise=e,Object.defineProperty(e,"name",{value:"Promise"}),e.toString=function(){return a.toString()},Object.setPrototypeOf(e,a),["all","race"].forEach((function(r){const n=a[r];e[r]=function(e){let i=!1;[...e||[]].forEach((e=>{this.resolve(e).then(a("all"===r),a(!1))}));const o=n.apply(this,arguments);return o;function a(e){return function(){t.emit("propagate",[null,!i],o,!1,!1),i=i||!e}}}})),["resolve","reject"].forEach((function(r){const n=a[r];e[r]=function(e){const r=n.apply(this,arguments);return e!==r&&t.emit("propagate",[e,!0],r,!1,!1),r}})),e.prototype=a.prototype;const n=a.prototype.then;a.prototype.then=function(){var e=this,i=r(e);i.promise=e;for(var a=arguments.length,s=new Array(a),c=0;c e())),t};function m(e,t){i.inPlace(t,["onreadystatechange"],"fn-",E)}function b(){var e=this,t=r.context(e);e.readyState>3&&!t.resolved&&(t.resolved=!0,r.emit("xhr-resolved",[],e)),i.inPlace(e,f,"fn-",E)}if(function(e,t){for(var r in e)t[r]=e[r]}(o,p),p.prototype=o.prototype,i.inPlace(p.prototype,J,"-xhr-",E),r.on("send-xhr-start",(function(e,t){m(e,t),function(e){h.push(e),a&&(y?y.then(A):u?u(A):(w=-w,x.data=w))}(t)})),r.on("open-xhr-start",m),a){var y=c&&c.resolve();if(!u&&!c){var w=1,x=document.createTextNode(w);new a(A).observe(x,{characterData:!0})}}else t.on("fn-end",(function(e){e[0]&&e[0].type===d||A()}));function A(){for(var e=0;e {r.d(t,{t:()=>n});const n=r(3325).D.ajax},6660:(e,t,r)=>{r.d(t,{A:()=>i,t:()=>n});const n=r(3325).D.jserrors,i="nr@seenError"},3081:(e,t,r)=>{r.d(t,{gF:()=>o,mY:()=>i,t9:()=>n,vz:()=>s,xS:()=>a});const n=r(3325).D.metrics,i="sm",o="cm",a="storeSupportabilityMetrics",s="storeEventMetrics"},4649:(e,t,r)=>{r.d(t,{t:()=>n});const n=r(3325).D.pageAction},7633:(e,t,r)=>{r.d(t,{Dz:()=>i,OJ:()=>a,qw:()=>o,t9:()=>n});const n=r(3325).D.pageViewEvent,i="firstbyte",o="domcontent",a="windowload"},9251:(e,t,r)=>{r.d(t,{t:()=>n});const n=r(3325).D.pageViewTiming},3614:(e,t,r)=>{r.d(t,{BST_RESOURCE:()=>i,END:()=>s,FEATURE_NAME:()=>n,FN_END:()=>u,FN_START:()=>c,PUSH_STATE:()=>d,RESOURCE:()=>o,START:()=>a});const n=r(3325).D.sessionTrace,i="bstResource",o="resource",a="-start",s="-end",c="fn"+a,u="fn"+s,d="pushState"},7836:(e,t,r)=>{r.d(t,{BODY:()=>A,CB_END:()=>E,CB_START:()=>u,END:()=>x,FEATURE_NAME:()=>i,FETCH:()=>_,FETCH_BODY:()=>v,FETCH_DONE:()=>m,FETCH_START:()=>p,FN_END:()=>c,FN_START:()=>s,INTERACTION:()=>l,INTERACTION_API:()=>d,INTERACTION_EVENTS:()=>o,JSONP_END:()=>b,JSONP_NODE:()=>g,JS_TIME:()=>T,MAX_TIMER_BUDGET:()=>a,REMAINING:()=>f,SPA_NODE:()=>h,START:()=>w,originalSetTimeout:()=>y});var n=r(5763);const i=r(3325).D.spa,o=["click","submit","keypress","keydown","keyup","change"],a=999,s="fn-start",c="fn-end",u="cb-start",d="api-ixn-",f="remaining",l="interaction",h="spaNode",g="jsonpNode",p="fetch-start",m="fetch-done",v="fetch-body-",b="jsonp-end",y=n.Yu.ST,w="-start",x="-end",A="-body",E="cb"+x,T="jsTime",_="fetch"},5938:(e,t,r)=>{r.d(t,{W:()=>o});var n=r(5763),i=r(2177);class o{constructor(e,t,r){this.agentIdentifier=e,this.aggregator=t,this.ee=i.ee.get(e,(0,n.OP)(this.agentIdentifier).isolatedBacklog),this.featureName=r,this.blocked=!1}}},9144:(e,t,r)=>{r.d(t,{j:()=>m});var n=r(3325),i=r(5763),o=r(5546),a=r(2177),s=r(7894),c=r(8e3),u=r(3960),d=r(385),f=r(50),l=r(3081),h=r(8632);function g(){const e=(0,h.gG)();["setErrorHandler","finished","addToTrace","inlineHit","addRelease","addPageAction","setCurrentRouteName","setPageViewName","setCustomAttribute","interaction","noticeError","setUserId"].forEach((t=>{e[t]=function(){for(var r=arguments.length,n=new Array(r),i=0;i 1?r-1:0),i=1;i {e.exposed&&e.api[t]&&o.push(e.api[t](...n))})),o.length>1?o:o[0]}(t,...n)}}))}var p=r(2587);function m(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},m=arguments.length>2?arguments[2]:void 0,v=arguments.length>3?arguments[3]:void 0,{init:b,info:y,loader_config:w,runtime:x={loaderType:m},exposed:A=!0}=t;const E=(0,h.gG)();y||(b=E.init,y=E.info,w=E.loader_config),(0,i.Dg)(e,b||{}),(0,i.GE)(e,w||{}),(0,i.sU)(e,x),y.jsAttributes??={},d.v6&&(y.jsAttributes.isWorker=!0),(0,i.CX)(e,y),g();const T=function(e,t){t||(0,c.R)(e,"api");const h={};var g=a.ee.get(e),p=g.get("tracer"),m="api-",v=m+"ixn-";function b(t,r,n,o){const a=(0,i.C5)(e);return null===r?delete a.jsAttributes[t]:(0,i.CX)(e,{...a,jsAttributes:{...a.jsAttributes,[t]:r}}),x(m,n,!0,o||null===r?"session":void 0)(t,r)}function y(){}["setErrorHandler","finished","addToTrace","inlineHit","addRelease"].forEach((e=>h[e]=x(m,e,!0,"api"))),h.addPageAction=x(m,"addPageAction",!0,n.D.pageAction),h.setCurrentRouteName=x(m,"routeName",!0,n.D.spa),h.setPageViewName=function(t,r){if("string"==typeof t)return"/"!==t.charAt(0)&&(t="/"+t),(0,i.OP)(e).customTransaction=(r||"http://custom.transaction")+t,x(m,"setPageViewName",!0)()},h.setCustomAttribute=function(e,t){let r=arguments.length>2&&void 0!==arguments[2]&&arguments[2];if("string"==typeof e){if(["string","number"].includes(typeof t)||null===t)return b(e,t,"setCustomAttribute",r);(0,f.Z)("Failed to execute setCustomAttribute.\nNon-null value must be a string or number type, but a type of was provided."))}else(0,f.Z)("Failed to execute setCustomAttribute.\nName must be a string type, but a type of was provided."))},h.setUserId=function(e){if("string"==typeof e||null===e)return b("enduser.id",e,"setUserId",!0);(0,f.Z)("Failed to execute setUserId.\nNon-null value must be a string type, but a type of was provided."))},h.interaction=function(){return(new y).get()};var w=y.prototype={createTracer:function(e,t){var r={},i=this,a="function"==typeof t;return(0,o.p)(v+"tracer",[(0,s.z)(),e,r],i,n.D.spa,g),function(){if(p.emit((a?"":"no-")+"fn-start",[(0,s.z)(),i,a],r),a)try{return t.apply(this,arguments)}catch(e){throw p.emit("fn-err",[arguments,this,"string"==typeof e?new Error(e):e],r),e}finally{p.emit("fn-end",[(0,s.z)()],r)}}}};function x(e,t,r,i){return function(){return(0,o.p)(l.xS,["API/"+t+"/called"],void 0,n.D.metrics,g),i&&(0,o.p)(e+t,[(0,s.z)(),...arguments],r?null:this,i,g),r?void 0:this}}function A(){r.e(439).then(r.bind(r,7438)).then((t=>{let{setAPI:r}=t;r(e),(0,c.L)(e,"api")})).catch((()=>(0,f.Z)("Downloading runtime APIs failed...")))}return["actionText","setName","setAttribute","save","ignore","onEnd","getContext","end","get"].forEach((e=>{w[e]=x(v,e,void 0,n.D.spa)})),h.noticeError=function(e,t){"string"==typeof e&&(e=new Error(e)),(0,o.p)(l.xS,["API/noticeError/called"],void 0,n.D.metrics,g),(0,o.p)("err",[e,(0,s.z)(),!1,t],void 0,n.D.jserrors,g)},d.il?(0,u.b)((()=>A()),!0):A(),h}(e,v);return(0,h.Qy)(e,T,"api"),(0,h.Qy)(e,A,"exposed"),(0,h.EZ)("activatedFeatures",p.T),T}},3325:(e,t,r)=>{r.d(t,{D:()=>n,p:()=>i});const n={ajax:"ajax",jserrors:"jserrors",metrics:"metrics",pageAction:"page_action",pageViewEvent:"page_view_event",pageViewTiming:"page_view_timing",sessionReplay:"session_replay",sessionTrace:"session_trace",spa:"spa"},i={[n.pageViewEvent]:1,[n.pageViewTiming]:2,[n.metrics]:3,[n.jserrors]:4,[n.ajax]:5,[n.sessionTrace]:6,[n.pageAction]:7,[n.spa]:8,[n.sessionReplay]:9}}},n={};function i(e){var t=n[e];if(void 0!==t)return t.exports;var o=n[e]={exports:{}};return r[e](o,o.exports,i),o.exports}i.m=r,i.d=(e,t)=>{for(var r in t)i.o(t,r)&&!i.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},i.f={},i.e=e=>Promise.all(Object.keys(i.f).reduce(((t,r)=>(i.f[r](e,t),t)),[])),i.u=e=>(({78:"page_action-aggregate",147:"metrics-aggregate",242:"session-manager",317:"jserrors-aggregate",348:"page_view_timing-aggregate",412:"lazy-feature-loader",439:"async-api",538:"recorder",590:"session_replay-aggregate",675:"compressor",733:"session_trace-aggregate",786:"page_view_event-aggregate",873:"spa-aggregate",898:"ajax-aggregate"}[e]||e)+"."+{78:"ac76d497",147:"3dc53903",148:"1a20d5fe",242:"2a64278a",317:"49e41428",348:"bd6de33a",412:"2f55ce66",439:"30bd804e",538:"1b18459f",590:"cf0efb30",675:"ae9f91a8",733:"83105561",786:"06482edd",860:"03a8b7a5",873:"e6b09d52",898:"998ef92b"}[e]+"-1.236.0.min.js"),i.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),e={},t="NRBA:",i.l=(r,n,o,a)=>{if(e[r])e[r].push(n);else{var s,c;if(void 0!==o)for(var u=document.getElementsByTagName("script"),d=0;d {s.onerror=s.onload=null,clearTimeout(h);var i=e[r];if(delete e[r],s.parentNode&&s.parentNode.removeChild(s),i&&i.forEach((e=>e(n))),t)return t(n)},h=setTimeout(l.bind(null,void 0,{type:"timeout",target:s}),12e4);s.onerror=l.bind(null,s.onerror),s.onload=l.bind(null,s.onload),c&&document.head.appendChild(s)}},i.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.j=364,i.p="https://js-agent.newrelic.com/",(()=>{var e={364:0,953:0};i.f.j=(t,r)=>{var n=i.o(e,t)?e[t]:void 0;if(0!==n)if(n)r.push(n[2]);else{var o=new Promise(((r,i)=>n=e[t]=[r,i]));r.push(n[2]=o);var a=i.p+i.u(t),s=new Error;i.l(a,(r=>{if(i.o(e,t)&&(0!==(n=e[t])&&(e[t]=void 0),n)){var o=r&&("load"===r.type?"missing":r.type),a=r&&r.target&&r.target.src;s.message="Loading chunk "+t+" failed.\n("+o+": "+a+")",s.name="ChunkLoadError",s.type=o,s.request=a,n[1](s)}}),"chunk-"+t,t)}};var t=(t,r)=>{var n,o,[a,s,c]=r,u=0;if(a.some((t=>0!==e[t]))){for(n in s)i.o(s,n)&&(i.m[n]=s[n]);if(c)c(i)}for(t&&t(r);u {i.r(o);var e=i(3325),t=i(5763);const r=Object.values(e.D);function n(e){const n={};return r.forEach((r=>{n[r]=function(e,r){return!1!==(0,t.Mt)(r,"".concat(e,".enabled"))}(r,e)})),n}var a=i(9144);var s=i(5546),c=i(385),u=i(8e3),d=i(5938),f=i(3960),l=i(50);class h extends d.W{constructor(e,t,r){let n=!(arguments.length>3&&void 0!==arguments[3])||arguments[3];super(e,t,r),this.auto=n,this.abortHandler,this.featAggregate,this.onAggregateImported,n&&(0,u.R)(e,r)}importAggregator(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};if(this.featAggregate||!this.auto)return;const r=c.il&&!0===(0,t.Mt)(this.agentIdentifier,"privacy.cookies_enabled");let n;this.onAggregateImported=new Promise((e=>{n=e}));const o=async()=>{let t;try{if(r){const{setupAgentSession:e}=await Promise.all([i.e(860),i.e(242)]).then(i.bind(i,3228));t=e(this.agentIdentifier)}}catch(e){(0,l.Z)("A problem occurred when starting up session manager. This page will not start or extend any session.",e)}try{if(!this.shouldImportAgg(this.featureName,t))return void(0,u.L)(this.agentIdentifier,this.featureName);const{lazyFeatureLoader:r}=await i.e(412).then(i.bind(i,8582)),{Aggregate:o}=await r(this.featureName,"aggregate");this.featAggregate=new o(this.agentIdentifier,this.aggregator,e),n(!0)}catch(e){(0,l.Z)("Downloading and initializing ".concat(this.featureName," failed..."),e),this.abortHandler?.(),n(!1)}};c.il?(0,f.b)((()=>o()),!0):o()}shouldImportAgg(r,n){return r!==e.D.sessionReplay||!1!==(0,t.Mt)(this.agentIdentifier,"session_trace.enabled")&&(!!n?.isNew||!!n?.state.sessionReplay)}}var g=i(7633),p=i(7894);class m extends h{static featureName=g.t9;constructor(r,n){let i=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];if(super(r,n,g.t9,i),("undefined"==typeof PerformanceNavigationTiming||c.Tt)&&"undefined"!=typeof PerformanceTiming){const n=(0,t.OP)(r);n[g.Dz]=Math.max(Date.now()-n.offset,0),(0,f.K)((()=>n[g.qw]=Math.max((0,p.z)()-n[g.Dz],0))),(0,f.b)((()=>{const t=(0,p.z)();n[g.OJ]=Math.max(t-n[g.Dz],0),(0,s.p)("timing",["load",t],void 0,e.D.pageViewTiming,this.ee)}))}this.importAggregator()}}var v=i(1117),b=i(1284);class y extends v.w{constructor(e){super(e),this.aggregatedData={}}store(e,t,r,n,i){var o=this.getBucket(e,t,r,i);return o.metrics=function(e,t){t||(t={count:0});return t.count+=1,(0,b.D)(e,(function(e,r){t[e]=w(r,t[e])})),t}(n,o.metrics),o}merge(e,t,r,n,i){var o=this.getBucket(e,t,n,i);if(o.metrics){var a=o.metrics;a.count+=r.count,(0,b.D)(r,(function(e,t){if("count"!==e){var n=a[e],i=r[e];i&&!i.c?a[e]=w(i.t,n):a[e]=function(e,t){if(!t)return e;t.c||(t=x(t.t));return t.min=Math.min(e.min,t.min),t.max=Math.max(e.max,t.max),t.t+=e.t,t.sos+=e.sos,t.c+=e.c,t}(i,a[e])}}))}else o.metrics=r}storeMetric(e,t,r,n){var i=this.getBucket(e,t,r);return i.stats=w(n,i.stats),i}getBucket(e,t,r,n){this.aggregatedData[e]||(this.aggregatedData[e]={});var i=this.aggregatedData[e][t];return i||(i=this.aggregatedData[e][t]={params:r||{}},n&&(i.custom=n)),i}get(e,t){return t?this.aggregatedData[e]&&this.aggregatedData[e][t]:this.aggregatedData[e]}take(e){for(var t={},r="",n=!1,i=0;i t.max&&(t.max=e),e 2&&void 0!==arguments[2])||arguments[2];super(e,r,j.t,n),c.il&&((0,t.OP)(e).initHidden=Boolean("hidden"===document.visibilityState),(0,N.N)((()=>(0,s.p)("docHidden",[(0,p.z)()],void 0,j.t,this.ee)),!0),(0,O.bP)("pagehide",(()=>(0,s.p)("winPagehide",[(0,p.z)()],void 0,j.t,this.ee))),this.importAggregator())}}var P=i(3081);class C extends h{static featureName=P.t9;constructor(e,t){let r=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];super(e,t,P.t9,r),this.importAggregator()}}var R,I=i(2210),k=i(1214),H=i(2177),L={};try{R=localStorage.getItem("__nr_flags").split(","),console&&"function"==typeof console.log&&(L.console=!0,-1!==R.indexOf("dev")&&(L.dev=!0),-1!==R.indexOf("nr_dev")&&(L.nrDev=!0))}catch(e){}function z(e){try{L.console&&z(e)}catch(e){}}L.nrDev&&H.ee.on("internal-error",(function(e){z(e.stack)})),L.dev&&H.ee.on("fn-err",(function(e,t,r){z(r.stack)})),L.dev&&(z("NR AGENT IN DEVELOPMENT MODE"),z("flags: "+(0,b.D)(L,(function(e,t){return e})).join(", ")));var M=i(6660);class B extends h{static featureName=M.t;constructor(r,n){let i=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];super(r,n,M.t,i),this.skipNext=0;try{this.removeOnAbort=new AbortController}catch(e){}const o=this;o.ee.on("fn-start",(function(e,t,r){o.abortHandler&&(o.skipNext+=1)})),o.ee.on("fn-err",(function(t,r,n){o.abortHandler&&!n[M.A]&&((0,I.X)(n,M.A,(function(){return!0})),this.thrown=!0,(0,s.p)("err",[n,(0,p.z)()],void 0,e.D.jserrors,o.ee))})),o.ee.on("fn-end",(function(){o.abortHandler&&!this.thrown&&o.skipNext>0&&(o.skipNext-=1)})),o.ee.on("internal-error",(function(t){(0,s.p)("ierr",[t,(0,p.z)(),!0],void 0,e.D.jserrors,o.ee)})),this.origOnerror=c._A.onerror,c._A.onerror=this.onerrorHandler.bind(this),c._A.addEventListener("unhandledrejection",(t=>{const r=function(e){let t="Unhandled Promise Rejection: ";if(e instanceof Error)try{return e.message=t+e.message,e}catch(t){return e}if(void 0===e)return new Error(t);try{return new Error(t+(0,D.P)(e))}catch(e){return new Error(t)}}(t.reason);(0,s.p)("err",[r,(0,p.z)(),!1,{unhandledPromiseRejection:1}],void 0,e.D.jserrors,this.ee)}),(0,O.m$)(!1,this.removeOnAbort?.signal)),(0,k.gy)(this.ee),(0,k.BV)(this.ee),(0,k.em)(this.ee),(0,t.OP)(r).xhrWrappable&&(0,k.Kf)(this.ee),this.abortHandler=this.#e,this.importAggregator()}#e(){this.removeOnAbort?.abort(),this.abortHandler=void 0}onerrorHandler(t,r,n,i,o){"function"==typeof this.origOnerror&&this.origOnerror(...arguments);try{this.skipNext?this.skipNext-=1:(0,s.p)("err",[o||new F(t,r,n),(0,p.z)()],void 0,e.D.jserrors,this.ee)}catch(t){try{(0,s.p)("ierr",[t,(0,p.z)(),!0],void 0,e.D.jserrors,this.ee)}catch(e){}}return!1}}function F(e,t,r){this.message=e||"Uncaught error with no additional information",this.sourceURL=t,this.line=r}let U=1;const q="nr@id";function G(e){const t=typeof e;return!e||"object"!==t&&"function"!==t?-1:e===c._A?0:(0,I.X)(e,q,(function(){return U++}))}function V(e){if("string"==typeof e&&e.length)return e.length;if("object"==typeof e){if("undefined"!=typeof ArrayBuffer&&e instanceof ArrayBuffer&&e.byteLength)return e.byteLength;if("undefined"!=typeof Blob&&e instanceof Blob&&e.size)return e.size;if(!("undefined"!=typeof FormData&&e instanceof FormData))try{return(0,D.P)(e).length}catch(e){return}}}var X=i(7243);class W{constructor(e){this.agentIdentifier=e,this.generateTracePayload=this.generateTracePayload.bind(this),this.shouldGenerateTrace=this.shouldGenerateTrace.bind(this)}generateTracePayload(e){if(!this.shouldGenerateTrace(e))return null;var r=(0,t.DL)(this.agentIdentifier);if(!r)return null;var n=(r.accountID||"").toString()||null,i=(r.agentID||"").toString()||null,o=(r.trustKey||"").toString()||null;if(!n||!i)return null;var a=(0,_.M)(),s=(0,_.Ht)(),c=Date.now(),u={spanId:a,traceId:s,timestamp:c};return(e.sameOrigin||this.isAllowedOrigin(e)&&this.useTraceContextHeadersForCors())&&(u.traceContextParentHeader=this.generateTraceContextParentHeader(a,s),u.traceContextStateHeader=this.generateTraceContextStateHeader(a,c,n,i,o)),(e.sameOrigin&&!this.excludeNewrelicHeader()||!e.sameOrigin&&this.isAllowedOrigin(e)&&this.useNewrelicHeaderForCors())&&(u.newrelicHeader=this.generateTraceHeader(a,s,c,n,i,o)),u}generateTraceContextParentHeader(e,t){return"00-"+t+"-"+e+"-01"}generateTraceContextStateHeader(e,t,r,n,i){return i+"@nr=0-1-"+r+"-"+n+"-"+e+"----"+t}generateTraceHeader(e,t,r,n,i,o){if(!("function"==typeof c._A?.btoa))return null;var a={v:[0,1],d:{ty:"Browser",ac:n,ap:i,id:e,tr:t,ti:r}};return o&&n!==o&&(a.d.tk=o),btoa((0,D.P)(a))}shouldGenerateTrace(e){return this.isDtEnabled()&&this.isAllowedOrigin(e)}isAllowedOrigin(e){var r=!1,n={};if((0,t.Mt)(this.agentIdentifier,"distributed_tracing")&&(n=(0,t.P_)(this.agentIdentifier).distributed_tracing),e.sameOrigin)r=!0;else if(n.allowed_origins instanceof Array)for(var i=0;i 2&&void 0!==arguments[2])||arguments[2];super(r,n,Z.t,i),(0,t.OP)(r).xhrWrappable&&(this.dt=new W(r),this.handler=(e,t,r,n)=>(0,s.p)(e,t,r,n,this.ee),(0,k.u5)(this.ee),(0,k.Kf)(this.ee),function(r,n,i,o){function a(e){var t=this;t.totalCbs=0,t.called=0,t.cbTime=0,t.end=E,t.ended=!1,t.xhrGuids={},t.lastSize=null,t.loadCaptureCalled=!1,t.params=this.params||{},t.metrics=this.metrics||{},e.addEventListener("load",(function(r){_(t,e)}),(0,O.m$)(!1)),c.IF||e.addEventListener("progress",(function(e){t.lastSize=e.loaded}),(0,O.m$)(!1))}function s(e){this.params={method:e[0]},T(this,e[1]),this.metrics={}}function u(e,n){var i=(0,t.DL)(r);i.xpid&&this.sameOrigin&&n.setRequestHeader("X-NewRelic-ID",i.xpid);var a=o.generateTracePayload(this.parsedOrigin);if(a){var s=!1;a.newrelicHeader&&(n.setRequestHeader("newrelic",a.newrelicHeader),s=!0),a.traceContextParentHeader&&(n.setRequestHeader("traceparent",a.traceContextParentHeader),a.traceContextStateHeader&&n.setRequestHeader("tracestate",a.traceContextStateHeader),s=!0),s&&(this.dt=a)}}function d(e,t){var r=this.metrics,i=e[0],o=this;if(r&&i){var a=V(i);a&&(r.txSize=a)}this.startTime=(0,p.z)(),this.listener=function(e){try{"abort"!==e.type||o.loadCaptureCalled||(o.params.aborted=!0),("load"!==e.type||o.called===o.totalCbs&&(o.onloadCalled||"function"!=typeof t.onload)&&"function"==typeof o.end)&&o.end(t)}catch(e){try{n.emit("internal-error",[e])}catch(e){}}};for(var s=0;s 1?e[1]=i:e.push(i)}else e[0]&&e[0].headers&&s(e[0].headers,n)&&(this.dt=n);function s(e,t){var r=!1;return t.newrelicHeader&&(e.set("newrelic",t.newrelicHeader),r=!0),t.traceContextParentHeader&&(e.set("traceparent",t.traceContextParentHeader),t.traceContextStateHeader&&e.set("tracestate",t.traceContextStateHeader),r=!0),r}}function x(e,t){this.params={},this.metrics={},this.startTime=(0,p.z)(),this.dt=t,e.length>=1&&(this.target=e[0]),e.length>=2&&(this.opts=e[1]);var r,n=this.opts||{},i=this.target;"string"==typeof i?r=i:"object"==typeof i&&i instanceof Y?r=i.url:c._A?.URL&&"object"==typeof i&&i instanceof URL&&(r=i.href),T(this,r);var o=(""+(i&&i instanceof Y&&i.method||n.method||"GET")).toUpperCase();this.params.method=o,this.txSize=V(n.body)||0}function A(t,r){var n;this.endTime=(0,p.z)(),this.params||(this.params={}),this.params.status=r?r.status:0,"string"==typeof this.rxSize&&this.rxSize.length>0&&(n=+this.rxSize);var o={txSize:this.txSize,rxSize:n,duration:(0,p.z)()-this.startTime};i("xhr",[this.params,o,this.startTime,this.endTime,"fetch"],this,e.D.ajax)}function E(t){var r=this.params,n=this.metrics;if(!this.ended){this.ended=!0;for(var o=0;o 2&&void 0!==arguments[2])||arguments[2];super(e,t,we.t,r),this.importAggregator()}}new class{constructor(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:(0,_.ky)(16);c._A?(this.agentIdentifier=t,this.sharedAggregator=new y({agentIdentifier:this.agentIdentifier}),this.features={},this.desiredFeatures=new Set(e.features||[]),this.desiredFeatures.add(m),Object.assign(this,(0,a.j)(this.agentIdentifier,e,e.loaderType||"agent")),this.start()):(0,l.Z)("Failed to initial the agent. Could not determine the runtime environment.")}get config(){return{info:(0,t.C5)(this.agentIdentifier),init:(0,t.P_)(this.agentIdentifier),loader_config:(0,t.DL)(this.agentIdentifier),runtime:(0,t.OP)(this.agentIdentifier)}}start(){const t="features";try{const r=n(this.agentIdentifier),i=[...this.desiredFeatures];i.sort(((t,r)=>e.p[t.featureName]-e.p[r.featureName])),i.forEach((t=>{if(r[t.featureName]||t.featureName===e.D.pageViewEvent){const n=function(t){switch(t){case e.D.ajax:return[e.D.jserrors];case e.D.sessionTrace:return[e.D.ajax,e.D.pageViewEvent];case e.D.sessionReplay:return[e.D.sessionTrace];case e.D.pageViewTiming:return[e.D.pageViewEvent];default:return[]}}(t.featureName);n.every((e=>r[e]))||(0,l.Z)("".concat(t.featureName," is enabled but one or more dependent features has been disabled (").concat((0,D.P)(n),"). This may cause unintended consequences or missing data...")),this.features[t.featureName]=new t(this.agentIdentifier,this.sharedAggregator)}})),(0,T.Qy)(this.agentIdentifier,this.features,t)}catch(e){(0,l.Z)("Failed to initialize all enabled instrument classes (agent aborted) -",e);for(const e in this.features)this.features[e].abortHandler?.();const r=(0,T.fP)();return delete r.initializedAgents[this.agentIdentifier]?.api,delete r.initializedAgents[this.agentIdentifier]?.[t],delete this.sharedAggregator,r.ee?.abort(),delete r.ee?.get(this.agentIdentifier),!1}}}({features:[J,m,S,class extends h{static featureName=oe;constructor(t,r){if(super(t,r,oe,!(arguments.length>2&&void 0!==arguments[2])||arguments[2]),!c.il)return;const n=this.ee;let i;(0,k.QU)(n),this.eventsEE=(0,k.em)(n),this.eventsEE.on(se,(function(e,t){this.bstStart=(0,p.z)()})),this.eventsEE.on(ae,(function(t,r){(0,s.p)("bst",[t[0],r,this.bstStart,(0,p.z)()],void 0,e.D.sessionTrace,n)})),n.on(ce+ne,(function(e){this.time=(0,p.z)(),this.startPath=location.pathname+location.hash})),n.on(ce+ie,(function(t){(0,s.p)("bstHist",[location.pathname+location.hash,this.startPath,this.time],void 0,e.D.sessionTrace,n)}));try{i=new PerformanceObserver((t=>{const r=t.getEntries();(0,s.p)(te,[r],void 0,e.D.sessionTrace,n)})),i.observe({type:re,buffered:!0})}catch(e){}this.importAggregator({resourceObserver:i})}},C,xe,B,class extends h{static featureName=de;constructor(e,r){if(super(e,r,de,!(arguments.length>2&&void 0!==arguments[2])||arguments[2]),!c.il)return;if(!(0,t.OP)(e).xhrWrappable)return;try{this.removeOnAbort=new AbortController}catch(e){}let n,i=0;const o=this.ee.get("tracer"),a=(0,k._L)(this.ee),s=(0,k.Lg)(this.ee),u=(0,k.BV)(this.ee),d=(0,k.Kf)(this.ee),f=this.ee.get("events"),l=(0,k.u5)(this.ee),h=(0,k.QU)(this.ee),g=(0,k.Gm)(this.ee);function m(e,t){h.emit("newURL",[""+window.location,t])}function v(){i++,n=window.location.hash,this[ve]=(0,p.z)()}function b(){i--,window.location.hash!==n&&m(0,!0);var e=(0,p.z)();this[pe]=~~this[pe]+e-this[ve],this[ye]=e}function y(e,t){e.on(t,(function(){this[t]=(0,p.z)()}))}this.ee.on(ve,v),s.on(be,v),a.on(be,v),this.ee.on(ye,b),s.on(ge,b),a.on(ge,b),this.ee.buffer([ve,ye,"xhr-resolved"],this.featureName),f.buffer([ve],this.featureName),u.buffer(["setTimeout"+le,"clearTimeout"+fe,ve],this.featureName),d.buffer([ve,"new-xhr","send-xhr"+fe],this.featureName),l.buffer([me+fe,me+"-done",me+he+fe,me+he+le],this.featureName),h.buffer(["newURL"],this.featureName),g.buffer([ve],this.featureName),s.buffer(["propagate",be,ge,"executor-err","resolve"+fe],this.featureName),o.buffer([ve,"no-"+ve],this.featureName),a.buffer(["new-jsonp","cb-start","jsonp-error","jsonp-end"],this.featureName),y(l,me+fe),y(l,me+"-done"),y(a,"new-jsonp"),y(a,"jsonp-end"),y(a,"cb-start"),h.on("pushState-end",m),h.on("replaceState-end",m),window.addEventListener("hashchange",m,(0,O.m$)(!0,this.removeOnAbort?.signal)),window.addEventListener("load",m,(0,O.m$)(!0,this.removeOnAbort?.signal)),window.addEventListener("popstate",(function(){m(0,i>1)}),(0,O.m$)(!0,this.removeOnAbort?.signal)),this.abortHandler=this.#e,this.importAggregator()}#e(){this.removeOnAbort?.abort(),this.abortHandler=void 0}}],loaderType:"spa"})})(),window.NRBA=o})(); window.jQuery || document.write(' ') CKEDITOR_BASEPATH='https://f1000research.com/js/vendor/ckeditor/' window.reactTheme = 'research'; window.MathJax = { CommonHTML: { linebreaks: { automatic: true } }, 'HTML-CSS': { linebreaks: { automatic: true } }, SVG: { linebreaks: { automatic: true } }, AuthorInit: function() { MathJax.Hub.Register.MessageHook('End Process', function () { let timeout = false; // holder for timeout id const delay = 250; // delay after event is "complete" to run callback const reflowMath = function() { const dispFormulas = document.querySelectorAll('.disp-formula.panel'); if (!dispFormulas) { return; } for (const dispFormula of dispFormulas) { const child = dispFormula.querySelector('.MathJax_Preview').nextSibling.firstChild; const isMultiline = MathJax.Hub.getAllJax(dispFormula)[0].root.isMultiline; if (dispFormula.offsetWidth < child.offsetWidth || isMultiline) { MathJax.Hub.Queue(['Rerender', MathJax.Hub, dispFormula]); } } }; window.addEventListener('resize', function() { clearTimeout(timeout); // clear the timeout timeout = setTimeout(reflowMath, delay); // start timing for event "completion" }); }); }, }; if (window.location.hash == '#_=_'){ window.location = window.location.href.split('#')[0] } !function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function() {n.callMethod? n.callMethod.apply(n,arguments):n.queue.push(arguments)} ;if(!f._fbq)f._fbq=n; n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0; t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window, document,'script','https://connect.facebook.net/en_US/fbevents.js'); fbq('init', '1641728616063202'); fbq('track', "PixelInitialized", {}); (function(h,o,t,j,a,r){ h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)}; h._hjSettings={hjid:2318163,hjsv:6}; a=o.getElementsByTagName('head')[0]; r=o.createElement('script');r.async=1; r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv; a.appendChild(r); })(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv='); search file_upload Submit your research search menu close search Browse Gateways & Collections How to Publish Submit your Research My Submissions Article Guidelines Article Guidelines (New Versions) Open Data, Software and Code Guidelines Open Data and Accessible Source Materials Guidelines (HSS) Open Data, Software and Code Guidelines (PSE) Prepublication Checks Production Process Posters and Slides Guidelines Document Guidelines Article Processing Charges Peer Review Finding Article Reviewers About How it Works For Reviewers Our Advisors Policies Glossary FAQs For Developers Newsroom Contact My Research Submissions Content and Tracking Alerts My Details Sign In file_upload Submit your research { "@context": "https://schema.org", "@type": "ScholarlyArticle", "mainEntityOfPage": { "@type": "WebPage", "@id": "https://f1000research.com/articles/12-1402" }, "headline": "A Bioconductor workflow for processing, evaluating, and interpreting expression proteomics data", "datePublished": "2023-10-24T16:27:07", "dateModified": "2024-09-25T09:43:58", "author": [ { "@type": "Person", "name": "Charlotte Hutchings" }, { "@type": "Person", "name": "Charlotte S. Dawson" }, { "@type": "Person", "name": "Thomas Krueger" }, { "@type": "Person", "name": "Kathryn S. Lilley" }, { "@type": "Person", "name": "Lisa M. Breckels" } ], "publisher": { "@type": "Organization", "name": "F1000Research", "logo": { "@type": "ImageObject", "url": "https://f1000research.com/img/AMP/F1000Research_image.png", "height": 480, "width": 60 } }, "image": { "@type": "ImageObject", "url": "https://f1000research.com/img/AMP/F1000Research_image.png", "height": 1200, "width": 150 }, "description": " Background Expression proteomics involves the global evaluation of protein abundances within a system. In turn, differential expression analysis can be used to investigate changes in protein abundance upon perturbation to such a system. Methods Here, we provide a workflow for the processing, analysis and interpretation of quantitative mass spectrometry-based expression proteomics data. This workflow utilises open-source R software packages from the Bioconductor project and guides users end-to-end and step-by-step through every stage of the analyses. As a use-case we generated expression proteomics data from HEK293 cells with and without a treatment. Of note, the experiment included cellular proteins labelled using tandem mass tag (TMT) technology and secreted proteins quantified using label-free quantitation (LFQ). Results The workflow explains the software infrastructure before focusing on data import, pre-processing and quality control. This is done individually for TMT and LFQ datasets. The application of statistical differential expression analysis is demonstrated, followed by interpretation via gene ontology enrichment analysis. Conclusions A comprehensive workflow for the processing, analysis and interpretation of expression proteomics is presented. The workflow is a valuable resource for the proteomics community and specifically beginners who are at least familiar with R who wish to understand and make data-driven decisions with regards to their analyses. " } { "@context": "http://schema.org", "@type": "BreadcrumbList", "itemListElement": [ { "@type": "ListItem", "position": "1", "item": { "@id": "https://f1000research.com/", "name": "Home" } }, { "@type": "ListItem", "position": "2", "item": { "@id": "https://f1000research.com/browse/articles", "name": "Browse" } }, { "@type": "ListItem", "position": "3", "item": { "@id": "https://f1000research.com/articles/12-1402/v2", "name": "A Bioconductor workflow for processing, evaluating, and interpreting..." } } ] } Home Browse A Bioconductor workflow for processing, evaluating, and interpreting... ALL Metrics - Views Downloads Get PDF Get XML Cite How to cite this article Hutchings C, Dawson CS, Krueger T et al. A Bioconductor workflow for processing, evaluating, and interpreting expression proteomics data [version 2; peer review: 4 approved, 1 approved with reservations] . F1000Research 2024, 12 :1402 ( https://doi.org/10.12688/f1000research.139116.2 ) NOTE: If applicable, it is important to ensure the information in square brackets after the title is included in all citations of this article. Close Copy Citation Details Export Export Citation Sciwheel EndNote Ref. Manager Bibtex ProCite Sente EXPORT Select a format first Track Share ▬ ✚ Software Tool Article Revised A Bioconductor workflow for processing, evaluating, and interpreting expression proteomics data [version 2; peer review: 4 approved, 1 approved with reservations] Charlotte Hutchings 1 , Charlotte S. Dawson 1 , Thomas Krueger https://orcid.org/0000-0002-8132-8870 2 , Kathryn S. Lilley 1 , Lisa M. Breckels https://orcid.org/0000-0001-8918-7171 1 Charlotte Hutchings 1 , Charlotte S. Dawson 1 , [...] Thomas Krueger https://orcid.org/0000-0002-8132-8870 2 , Kathryn S. Lilley 1 , Lisa M. Breckels https://orcid.org/0000-0001-8918-7171 1 PUBLISHED 25 Sep 2024 Author details Author details 1 Cambridge Centre for Proteomics, University of Cambridge, Cambridge, CB2 1QR, UK 2 Department of Biochemistry, University of Cambridge, Cambridge, CB2 1QR, UK Charlotte Hutchings Roles: Conceptualization, Data Curation, Formal Analysis, Investigation, Methodology, Project Administration, Software, Visualization, Writing – Original Draft Preparation, Writing – Review & Editing Charlotte S. Dawson Roles: Software, Writing – Review & Editing Thomas Krueger Roles: Methodology, Supervision, Writing – Review & Editing Kathryn S. Lilley Roles: Funding Acquisition, Supervision, Writing – Review & Editing Lisa M. Breckels Roles: Conceptualization, Methodology, Supervision, Writing – Review & Editing OPEN PEER REVIEW DETAILS REVIEWER STATUS This article is included in the Bioconductor gateway. Abstract Background Expression proteomics involves the global evaluation of protein abundances within a system. In turn, differential expression analysis can be used to investigate changes in protein abundance upon perturbation to such a system. Methods Here, we provide a workflow for the processing, analysis and interpretation of quantitative mass spectrometry-based expression proteomics data. This workflow utilises open-source R software packages from the Bioconductor project and guides users end-to-end and step-by-step through every stage of the analyses. As a use-case we generated expression proteomics data from HEK293 cells with and without a treatment. Of note, the experiment included cellular proteins labelled using tandem mass tag (TMT) technology and secreted proteins quantified using label-free quantitation (LFQ). Results The workflow explains the software infrastructure before focusing on data import, pre-processing and quality control. This is done individually for TMT and LFQ datasets. The application of statistical differential expression analysis is demonstrated, followed by interpretation via gene ontology enrichment analysis. Conclusions A comprehensive workflow for the processing, analysis and interpretation of expression proteomics is presented. The workflow is a valuable resource for the proteomics community and specifically beginners who are at least familiar with R who wish to understand and make data-driven decisions with regards to their analyses. READ ALL READ LESS Keywords Bioconductor, QFeatures, proteomics, shotgun proteomics, bottom-up proteomics, differential expression, mass spectrometry, quality control, data processing, limma Corresponding Author(s) Lisa M. Breckels ( [email protected] ) Close Corresponding author: Lisa M. Breckels Competing interests: No competing interests were disclosed. Grant information: C. H. is funded through a BBSRC CASE award with AstraZeneca (BB/W509929/1). C. S. D. is funded by a Herchel Smith Research Studentship at the University of Cambridge, United Kingdom. T. K. is funded by a Gordon and Betty Moore Foundation Grant (#7872). K. S. L. is funded by Wellcome Trust (110071/Z/15/Z) and European Union Horizon 2020 program INFRAIA project EPIC-XS (project no.: 823839). L. M. B. is funded by European Union Horizon 2020 program INFRAIA project EPIC-XS (project no.: 823839). The funders had no role in study design, data collection and analysis, decision to publish, or preparation of the manuscript. The funders had no role in study design, data collection and analysis, decision to publish, or preparation of the manuscript. Copyright: © 2024 Hutchings C et al . This is an open access article distributed under the terms of the Creative Commons Attribution License , which permits unrestricted use, distribution, and reproduction in any medium, provided the original work is properly cited. How to cite: Hutchings C, Dawson CS, Krueger T et al. A Bioconductor workflow for processing, evaluating, and interpreting expression proteomics data [version 2; peer review: 4 approved, 1 approved with reservations] . F1000Research 2024, 12 :1402 ( https://doi.org/10.12688/f1000research.139116.2 ) First published: 24 Oct 2023, 12 :1402 ( https://doi.org/10.12688/f1000research.139116.1 ) Latest published: 25 Sep 2024, 12 :1402 ( https://doi.org/10.12688/f1000research.139116.2 ) Revised Amendments from Version 1 In response to software updates in the QFeatures R package in Bioconductor (April 2024) we have updated the code in this workflow for compatibility with QFeatures >= v1.14.0, specifically code relating to data import and the downstream plotting of the data. Following suggestions from the reviewers and to help users make the most out of this workflow, we have provided information on how to adapt the workflow from Proteome Discoverer files to those generated by MaxQuant, a free and accessible search software. This information is provided in a new section in the Appendix located in the associated Github repository (https://github.com/CambridgeCentreForProteomics/f1000_expression_proteomics/blob/main/appendix.pdf). We have added a few sentences in the manuscript to further discuss the expectation of missing values in quantitative proteomics data. We have also simplified the section on normalisation to enhance readability for users. Lastly, for completeness, we have added a short section "Controlling the false discovery rate”. In response to software updates in the QFeatures R package in Bioconductor (April 2024) we have updated the code in this workflow for compatibility with QFeatures >= v1.14.0, specifically code relating to data import and the downstream plotting of the data. Following suggestions from the reviewers and to help users make the most out of this workflow, we have provided information on how to adapt the workflow from Proteome Discoverer files to those generated by MaxQuant, a free and accessible search software. This information is provided in a new section in the Appendix located in the associated Github repository (https://github.com/CambridgeCentreForProteomics/f1000_expression_proteomics/blob/main/appendix.pdf). We have added a few sentences in the manuscript to further discuss the expectation of missing values in quantitative proteomics data. We have also simplified the section on normalisation to enhance readability for users. Lastly, for completeness, we have added a short section "Controlling the false discovery rate”. See the authors' detailed response to the review by Diogo Borges Lima See the authors' detailed response to the review by Amit Kumar Yadav See the authors' detailed response to the review by Marie Locard-Paulet READ REVIEWER RESPONSES Introduction Proteins are responsible for carrying out a multitude of biological tasks, implementing cellular functionality and determining phenotype. Mass spectrometry (MS)-based expression proteomics allows protein abundance to be quantified and compared between samples. In turn, differential protein abundance can be used to explore how biological systems respond to a perturbation. Many research groups have applied such methodologies to understand mechanisms of disease, elucidate cellular responses to external stimuli, and discover diagnostic biomarkers (see Refs. 1 – 3 for recent examples). As the potential of proteomics continues to be realised, there is a clear need for resources demonstrating how to deal with expression proteomics data in a robust and standardised manner. The data generated during an expression proteomics experiment are complex, and unfortunately there is no one-size-fits-all method for the processing and analysis of such data. The reason for this is two-fold. Firstly, there are a wide range of experimental methods that can be used to generate expression proteomics data. Researchers can analyze full-length proteins (top-down proteomics) or complete an enzymatic digestion and analyze the resulting peptides. This proteolytic digestion can be either partial (middle-down proteomics) or complete (bottom-up proteomics). The latter approach is most commonly used as peptides have a more favourable ionization capacity, predictable fragmentation patterns, and can be separated via reversed phase liquid chromatography, ultimately making them more compatible with MS. 4 Within bottom-up proteomics, the relative quantitation of peptides can be determined using one of two approaches: (1) label-free or (2) label-based quantitation. Moreover, the latter can be implemented with a number of different peptide labelling chemistries, for example, using tandem mass tag (TMT), stable-isotope labelling by amino acids in cell culture (SILAC), isobaric tags for relative and absolute quantitation (iTRAQ), among others. 5 MS analysis can also be used in either data-dependent or data-independent acquisition (DDA or DIA) mode. 6 , 7 Although all of these experimental methods typically result in a similar output, a matrix of quantitative values, the data are different and must be treated as such. Secondly, data processing is dependent upon the experimental goal and biological question being asked. Here, we provide a step-by-step workflow for processing, analysing and interpreting expression proteomics data derived from a bottom-up experiment using DDA and either LFQ or TMT label-based peptide quantitation. We outline how to process the data starting from a peptide spectrum match (PSM)- or peptide-level .txt file. Such files are the outputs of most major third-party search software (e.g., Proteome Discoverer, MaxQuant, FragPipe). As an example, we use output files generated by Proteome Discoverer. Nonetheless, the key processing steps remain the same for files generated using alternative third party software and this workflow provides a framework for and discussion of such common steps. We begin with data import and then guide users through the stages of data processing including data cleaning, quality control filtering, management of missing values, imputation, and aggregation to protein-level. Finally, we finish with how to discover differentially abundant proteins and carry out biological interpretation of the resulting data. The latter will be achieved through the application of gene ontology (GO) enrichment analysis. Hence, users can expect to generate lists of proteins that are significantly up- or downregulated in their system of interest, as well as the GO terms that are significantly over-represented in these proteins. Using the R statistical programming environment 8 we make use of several state-of-the-art packages from the open-source, open-development Bioconductor project 9 to analyze use-case expression proteomics datasets 10 from both LFQ and label-based technologies. Package installation In this workflow we make use of open-source software from the R Bioconductor 9 project. The Bioconductor initiative provides R software packages dedicated to the processing of high-throughput complex biological data. Packages are open-source, well-documented and benefit from an active community of developers. We recommend users to download the RStudio integrated development environment (IDE) which provides a graphical interface to R programming language. Detailed instructions for the installation of Bioconductor packages are documented on the Bioconductor Installation page. The main packages required for this workflow are installed using the code below. if ( ! require( "BiocManager" , quietly = TRUE )) { install.packages ( "BiocManager" ) } BiocManager :: install ( c ( "QFeatures" , "ggplot2" , "stringr" , "corrplot" , "Biostrings" , "limma" , "impute" , "dplyr" , "tibble" , "org.Hs.eg.db" , "clusterProfiler" , "enrichplot" )) After installation, each package must be loaded before it can be used in the R session. This is achieved via the library function. For example, to load the QFeatures package one would type library("QFeatures") after installation. Here we load all packages included in this workflow. library ( "QFeatures" ) library ( "ggplot2" ) library ( "stringr" ) library ( "dplyr" ) library ( "tibble" ) library ( "corrplot" ) library ( "Biostrings" ) library ( "limma" ) library ( "org.Hs.eg.db" ) library ( "clusterProfiler" ) library ( "enrichplot" ) Methods The use-case: exploring changes in protein abundance in HEK293 cells upon perturbation As a use-case, we analyze two quantitative proteomics datasets derived from a single experiment. The aim of the experiment was to reveal the differential abundance of proteins in HEK293 cells upon a particular treatment, the exact details of which are anonymised for the purpose of this workflow. An outline of the experimental method is provided in Figure 1 . Figure 1. A schematic summary of the experimental protocol used to generate the use-case data. Briefly, HEK293 cells were either (i) left untreated, or (ii) provided with the treatment of interest. These two conditions are referred to as ‘control’ and ‘treated’, respectively. Each condition was evaluated in triplicate. At 96-hours post-treatment, samples were collected and separated into cell pellet and supernatant fractions containing cellular and secreted proteins, respectively. Both fractions were denatured, alkylated and digested to peptides using trypsin. The supernatant fractions were de-salted and analysed over a two-hour gradient in an Orbitrap Fusion™ Lumos™ Tribrid™ mass spectrometer coupled to an UltiMate™ 3000 HPLC system (Thermo Fisher Scientific). LFQ was achieved at the MS1 level based on signal intensities. Cell pellet fractions were labelled using TMT technology before being pooled and subjected to high pH reversed-phase peptide fractionation giving a total of 8 fractions. As before, each fraction was analysed over a two-hour gradient in an Orbitrap Fusion™ Lumos™ Tribrid™ mass spectrometer coupled to an UltiMate™ 3000 HPLC system (Thermo Fisher Scientific). To improve the accuracy of the quantitation of TMT-labelled peptides, synchronous precursor selection (SPS)-MS3 data acquisition was employed. 11 , 12 Of note, TMT labelling of cellular proteins was achieved using a single TMT6plex. Hence, this workflow will not include guidance on multi-batch TMT effects or the use of internal reference scaling. For more information about the use of multiple TMTplexes users are directed to Refs. 13 , 14 The cell pellet and supernatant datasets were handled independently and we take advantage of this to discuss the processing of TMT-labelled and LFQ proteomics data. In both cases, the raw MS data were processed using Proteome Discoverer v2.5 (Thermo Fisher Scientific). As a result, this workflow uses the specific columns and files output by Proteome Discoverer. Nevertheless, most third-party software output similar data structures and this workflow can be adapted. As an example, information on how to adapt this workflow for data processed by MaxQuant is provided in the appendix, which is available at https://zenodo.org/records/13753944 . 10 While the focus in the workflow presented below is differential protein expression analysis, the data processing and quality control steps described here are applicable to any TMT or LFQ proteomics dataset. Importantly, however, the experimental aim will influence data-guided decisions and the considerations discussed here likely differ from those of spatial proteomics, for example. Downloading the data The files required for this workflow can be found deposited to the ProteomeXchange Consortium via the PRIDE 15 , 16 partner repository with the dataset identifier PXD041794, Zenodo at https://zenodo.org/records/13753944 and at the Github repository https://github.com/CambridgeCentreForProteomics/f1000_expression_proteomics/ . Users are advised to download these files into their current working directory. In R the setwd function can be used to specify a working directory, or if using RStudio one can use the Session -> Set Working Directory menu. The infrastructure: QFeatures and SummarizedExperiments To be able to conveniently track each step of this workflow, users should make use of the Quantitative features for mass spectrometry, or QFeatures , Bioconductor package . 17 Prior to utilizing the QFeatures infrastructure, it is first necessary to understand the structure of a SummarizedExperiment 18 object as QFeatures objects are based on the SummarizedExperiment class. A SummarizedExperiment , often referred to as an SE, is a data container and S4 object comprised of three components: (1) the colData (column data) containing sample metadata, (2) the rowData containing data features, and (3) the assay storing quantitation data, as illustrated in Figure 2 . The sample metadata includes annotations such as condition and replicate, and can be accessed using the colData function. Data features, accessed via the rowData function, represent information derived from the identification search. Examples include peptide sequence, master protein accession, and confidence scores. Finally, quantitative data is stored in the assay slot. These three independent data structures are neatly stored within a single SummarizedExperiment object. Figure 2. A graphic representation of the SummarizedExperiment (SE) object structure. Figure reproduced from the SummarizedExperiment package 18 vignette with permission. A QFeatures object holds each level of quantitative proteomics data, namely (but not limited to) the PSM, peptide and protein-level data. Each level of the data is stored as its own SummarizedExperiment within a single QFeatures object. The lowest level data e.g. PSM, is first imported into a QFeatures object before aggregating upward towards protein-level ( Figure 3 ). During this process of aggregation, QFeatures maintains the hierarchical links between quantitative levels whilst allowing easy access to all data levels for individual proteins of interest. This key aspect of QFeatures will be exemplified throughout this workflow. Additional guidance on the use of QFeatures can be found in Ref. 17 . For visualisation of the data, all plots are generated using standard ggplot functionality, but could equally be produced using base R. Figure 3. A graphic representation of the QFeatures object structure showing the relationship between assays. Figure modified from the QFeatures 17 vignette with permission. Processing and analysing quantitative TMT data First, we provide a workflow for the processing and quality control of quantitative TMT-labelled data. As outlined above, the cell pellet fractions of triplicate control and treated HEK293 cells were labelled using a TMT6plex. Labelling was as outlined in Table 1 . Table 1. TMT labelling strategy in the use-case experiment. Sample name Condition Replicate Tag S1 Treated 1 TMT128 S2 Treated 2 TMT127 S3 Treated 3 TMT131 S4 Control 1 TMT129 S5 Control 2 TMT126 S6 Control 3 TMT130 Identification search of raw data The first processing step in any MS-based proteomics experiment involves an identification search using the raw data. The aim of this search is to identify which peptide sequences, and therefore proteins, correspond to the raw spectra output from the mass spectrometer. Several third-party software exist to facilitate identification searches of raw MS data but ultimately the output of any search is a list of PSMs, peptides and protein identifications along with their corresponding quantification data. The use-case data presented here was processed using Proteome Discoverer 2.5 and additional information about this search is provided in the appendix. 10 Further, we provide template workflows for both the processing and consensus steps of the Proteome Discoverer identification run in the supplementary information. We also provide details on how to adapt this workflow for data processed with MaxQuant in the appendix. 10 It is also possible to determine several of the key parameter settings during the preliminary data exploration. This step will be particularly important for those using publicly available data without detailed knowledge of the identification search parameters. For now, we simply export the PSM-level .txt file from the Proteome Discoverer output. Data import, housekeeping and exploration Importing data into R and creating a QFeatures object Data cleaning, exploration and filtering at the PSM-level is performed in R using QFeatures . First, data is imported from our PSM-level .txt file into a data.frame using the base R read.delim function (the equivalent for .csv files would be read.csv ). This file should be stored within the user’s working directory. Next, we use the names function to inspect the column names and identify which columns contain quantitative data. ## Locate the PSM .txt file cp_psm <- "cell_pellet_tmt_results_psms.txt" ## Import into a dataframe cp_df % names () ## [1] "PSMs.Workflow.ID" "PSMs.Peptide.ID" ## [3] "Checked" "Tags" ## [5] "Confidence" "Identifying.Node.Type" ## [7] "Identifying.Node" "Search.ID" ## [9] "Identifying.Node.No" "PSM.Ambiguity" ## [11] "Sequence" "Annotated.Sequence" ## [13] "Modifications" "Number.of.Proteins" ## [15] "Master.Protein.Accessions" "Master.Protein.Descriptions" ## [17] "Protein.Accessions" "Protein.Descriptions" ## [19] "Number.of.Missed.Cleavages" "Charge" ## [21] "Original.Precursor.Charge" "Delta.Score" ## [23] "Delta.Cn" "Rank" ## [25] "Search.Engine.Rank" "Concatenated.Rank" ## [27] "mz.in.Da" "MHplus.in.Da" ## [29] "Theo.MHplus.in.Da" "Delta.M.in.ppm" ## [31] "Delta.mz.in.Da" "Ions.Matched" ## [33] "Matched.Ions" "Total.Ions" ## [35] "Intensity" "Activation.Type" ## [37] "NCE.in.Percent" "MS.Order" ## [39] "Isolation.Interference.in.Percent" "SPS.Mass.Matches.in.Percent" ## [41] "Average.Reporter.SN" "Ion.Inject.Time.in.ms" ## [43] "RT.in.min" "First.Scan" ## [45] "Last.Scan" "Master.Scans" ## [47] "Spectrum.File" "File.ID" ## [49] "Abundance.126" "Abundance.127" ## [51] "Abundance.128" "Abundance.129" ## [53] "Abundance.130" "Abundance.131" ## [55] "Quan.Info" "Peptides.Matched" ## [57] "XCorr" "Number.of.Protein.Groups" ## [59] "Percolator.q.Value" "Percolator.PEP" ## [61] "Percolator.SVMScore" We see that our data contains six quantitative columns in positions 49 to 54. Now that the quantitative data columns have been identified, we can pass our data.frame to the readQFeatures function and specify where our quantitative columns are. The latter is done by passing either a numeric or character vector to an argument called quantCols ( ecols in previous package versions). Of note, the readQFeatures function can also take fnames as an argument to specify a column to be used as the row names of the imported object. Whilst previous QFeatures vignettes used the “Sequence” or “Annotated.Sequence” as row names, we advise against this because of the presence of PSMs matched to the same peptide sequence with different modifications. In such cases, multiple rows would have the same name forcing the readQFeatures function to output a “making assay row names unique” message and add an identifying number to the end of each duplicated row name. These sequences would then be considered as unique during the aggregation of PSM to peptide, thus resulting in two independent peptide- level quantitation values rather than one. Therefore, we do not pass a fnames argument and the row names automatically become indices. Finally, we pass the name argument to indicate the type of data added. ## Create QFeatures cp_qf <- readQFeatures ( assayData = cp_df, quantCols = 49 : 54 , name = "psms_raw" ) ## Checking arguments. ## Loading data as a 'SummarizedExperiment' object. ## Formatting sample annotations (colData). ## Formatting data as a 'QFeatures' object. Accessing the QFeatures infrastructure As outlined above, a QFeatures data object is a list of SummarizedExperiment objects. As such, an individual SummarizedExperiment can be accessed using the standard double bracket nomenclature, as demonstrated in the code chunk below. ## Index using position cp_qf[[ 1 ]] ## class: SummarizedExperiment ## dim: 48832 6 ## metadata(0): ## assays(1): '' ## rownames(48832): 1 2 … 48831 48832 ## rowData names(55): PSMs.Workflow.ID PSMs.Peptide.ID … Percolator.PEP ## Percolator.SVMScore ## colnames(6): Abundance.126 Abundance.127 … Abundance.130 ## Abundance.131 ## colData names(0): ## Index using name cp_qf[[ "psms_raw" ]] ## class: SummarizedExperiment ## dim: 48832 6 ## metadata(0): ## assays(1): '' ## rownames(48832): 1 2 … 48831 48832 ## rowData names(55): PSMs.Workflow.ID PSMs.Peptide.ID … Percolator.PEP ## Percolator.SVMScore ## colnames(6): Abundance.126 Abundance.127 … Abundance.130 ## Abundance.131 ## colData names(0): A summary of the data contained in the slots is printed to the screen. To retrieve the rowData , colData or assay data from a particular SummarizedExperiment within a QFeatures object users can make use of the rowData , colData and assay functions. For plotting or data transformation it is necessary to convert to a data.frame or tibble . ## Access feature information with rowData ## The output should be converted to data.frame/tibble for further processing cp_qf[[ "psms_raw" ]] %>% rowData () %>% as_tibble () %>% summarise ( mean_intensity = mean (Intensity)) ## # A tibble: 1 x 1 ## mean_intensity ## ## 1 13281497. To ensure that quantitative data has been correctly imported as a numeric variable, we can look at the assay slot. ## Look at top 6 rows of the assay (quantitative data) cp_qf[[ "psms_raw" ]] %>% assay () %>% head () ## Abundance.126 Abundance.127 Abundance.128 Abundance.129 Abundance.130 ## 1 NA NA NA NA NA ## 2 NA NA NA NA NA ## 3 NA NA NA NA NA ## 4 14.1 18.1 11.8 9.4 18.9 ## 5 NA 2.5 NA 3.4 3.2 ## 6 16.7 26.2 18.7 22.4 25.3 ## Abundance.131 ## 1 NA ## 2 NA ## 3 NA ## 4 13.5 ## 5 NA ## 6 17.2 ## Confirm numeric assay cp_qf[[ "psms_raw" ]] %>% assay () %>% type () ## [1] "double" Our assay contains data of type double , a sub-type of numeric data in R. If users find that their quantitative data is of type character , it is necessary to correct this before moving on with the rest of the workflow. Adding metadata Having imported the data, each sample is first annotated with its TMT label, sample reference and condition. As this information is experimental metadata, it is added to the colData slot. It is important for users check that the colData annotations correspond to their correct samples, particularly if the column order in the imported results file does not align with the sample order. This is the case for the use-case data since TMT labels were randomised in an attempt to minimze the effect of TMT channel leakage. ## Add sample info as colData to QFeatures object cp_qf $ label <- c ( "TMT126" , "TMT127" , "TMT128" , "TMT129" , "TMT130" , "TMT131" ) cp_qf $ sample <- c ( "S5" , "S2" , "S1" , "S4" , "S6" , "S3" ) cp_qf $ condition <- c ( "Control" , "Treated" , "Treated" , "Control" , "Control" , "Treated" ) ## Verify colData (cp_qf) ## DataFrame with 6 rows and 3 columns ## label sample condition ## ## Abundance.126 TMT126 S5 Control ## Abundance.127 TMT127 S2 Treated ## Abundance.128 TMT128 S1 Treated ## Abundance.129 TMT129 S4 Control ## Abundance.130 TMT130 S6 Control ## Abundance.131 TMT131 S3 Treated ## Assign the colData to first assay as well colData (cp_qf[[ "psms_raw" ]]) <- colData (cp_qf) It is also useful to clean up sample names such that they are short, intuitive and informative. This is done by editing the colnames . These steps may not always be necessary depending upon the identification search output. ## Clean sample names colnames (cp_qf[[ "psms_raw" ]]) <- c ( "S5" , "S2" , "S1" , "S4" , "S6" , "S3" ) Preliminary data exploration As well as cleaning and annotating the data, it is always advisable to check that the import worked and that the data looks as expected. Further, preliminary exploration of the data can provide an early sign of whether the experiment and subsequent identification search were successful. Importantly, however, the names of key parameters will vary depending on the software used, and will likely change over time. Users will need to be aware of this and modify the code in this workflow accordingly. ## Check what information has been imported cp_qf[[ "psms_raw" ]] %>% rowData () %>% colnames () ## [1] "PSMs.Workflow.ID" "PSMs.Peptide.ID" ## [3] "Checked" "Tags" ## [5] "Confidence" "Identifying.Node.Type" ## [7] "Identifying.Node" "Search.ID" ## [9] "Identifying.Node.No" "PSM.Ambiguity" ## [11] "Sequence" "Annotated.Sequence" ## [13] "Modifications" "Number.of.Proteins" ## [15] "Master.Protein.Accessions" "Master.Protein.Descriptions" ## [17] "Protein.Accessions" "Protein.Descriptions" ## [19] "Number.of.Missed.Cleavages" "Charge" ## [21] "Original.Precursor.Charge" "Delta.Score" ## [23] "Delta.Cn" "Rank" ## [25] "Search.Engine.Rank" "Concatenated.Rank" ## [27] "mz.in.Da" "MHplus.in.Da" ## [29] "Theo.MHplus.in.Da" "Delta.M.in.ppm" ## [31] "Delta.mz.in.Da" "Ions.Matched" ## [33] "Matched.Ions" "Total.Ions" ## [35] "Intensity" "Activation.Type" ## [37] "NCE.in.Percent" "MS.Order" ## [39] "Isolation.Interference.in.Percent" "SPS.Mass.Matches.in.Percent" ## [41] "Average.Reporter.SN" "Ion.Inject.Time.in.ms" ## [43] "RT.in.min" "First.Scan" ## [45] "Last.Scan" "Master.Scans" ## [47] "Spectrum.File" "File.ID" ## [49] "Quan.Info" "Peptides.Matched" ## [51] "XCorr" "Number.of.Protein.Groups" ## [53] "Percolator.q.Value" "Percolator.PEP" ## [55] "Percolator.SVMScore" ## Find out how many PSMs are in the data cp_qf[[ "psms_raw" ]] %>% dim () ## [1] 48832 6 original_psms % nrow () %>% as.numeric () We can see that the original data includes 48832 PSMs across the 6 samples. It is also useful to make note of how many peptides and protein groups the raw PSM data corresponds to, and to track how many we remove during the subsequent filtering steps. This can be done by checking how many unique entries are located within the “Sequence” and “Master.Protein.Accessions” for peptides and protein groups, respectively. Of note, searching for unique peptide sequences means that the number of peptides does not include duplicated sequences with different modifications. ## Find out how many peptides and master proteins are in the data original_peps % rowData () %>% as_tibble () %>% pull (Sequence) %>% unique () %>% length () %>% as.numeric () original_prots % rowData () %>% as_tibble () %>% pull (Master.Protein.Accessions) %>% unique () %>% length () %>% as.numeric () print ( c (original_peps, original_prots)) ## [1] 25969 5040 Hence, the output of the identification search contains 48832 PSMs corresponding to 25969 peptide sequences and 5040 master proteins or protein groups. Finally, we confirm that the identification search was carried out as expected. For this, we print summaries of the key search parameters using the table function for discrete parameters and summary for those which are continuous. This is also helpful for users who are analyzing publicly available data and have limited knowledge about the identification search parameters. ## Check missed cleavages cp_qf[[ "psms_raw" ]] %>% rowData () %>% as_tibble () %>% pull (Number.of.Missed.Cleavages) %>% table () ## . ## 0 1 2 ## 46164 2592 76 ## Check precursor mass tolerance cp_qf[[ "psms_raw" ]] %>% rowData () %>% as_tibble () %>% pull (Delta.M.in.ppm) %>% summary () ## Min. 1st Qu. Median Mean 3rd Qu. Max. ## -8.9300 -0.6000 0.3700 0.6447 1.3100 9.6700 ## Check fragment mass tolerance cp_qf[[ "psms_raw" ]] %>% rowData () %>% as_tibble () %>% pull (Delta.mz.in.Da) %>% summary () ## Min. 1st Qu. Median Mean 3rd Qu. Max. ## -0.0110400 -0.0004100 0.0002500 0.0006812 0.0010200 0.0135100 ## Check PSM confidence allocations cp_qf[[ "psms_raw" ]] %>% rowData () %>% as_tibble () %>% pull (Confidence) %>% table () ## . ## High ## 48832 Experimental quality control checks Experimental quality control of TMT-labelled quantitive proteomics data takes place in two steps: (1) assessment of the raw mass spectrometry data, and (2) evaluation of TMT labelling efficiency. Quality control of the raw mass spectrometry data Having taken an initial look at the output of the identification search, it is possible to create some simple plots to inspect the raw mass spectrometry data. Such plots are useful in revealing problems that may have occurred during the mass spectrometry run but are far from extensive. Users who wish to carry out a more in-depth evaluation of the raw mass spectrometry data may benefit from use of the Spectra Bioconductor package which allows for visualisation and exploration of raw chromatograms and spectra, among other features. 19 The first plot we generate looks at the delta precursor mass, that is the difference between observed and estimated precursor mass, across retention time. Importantly, exploration of this raw data feature can only be done when using the raw data prior to recalibration. For users of Proteome Discoverer, this means using the spectral files node rather than the spectral files recalibration node. ## Generate scatter plot of mass accuracy cp_qf[[ "psms_raw" ]] %>% rowData () %>% as_tibble () %>% ggplot ( aes ( x = RT.in.min, y = Delta.M.in.ppm)) + geom_point ( size = 0.5 , shape = 4 ) + geom_hline ( yintercept = 5 , linetype = "dashed" , color = "red" ) + geom_hline ( yintercept = - 5 , linetype = "dashed" , color = "red" ) + labs ( x = "RT (min)" , y = "Delta precursor mass (ppm)" ) + scale_x_continuous ( limits = c ( 0 , 120 ), breaks = seq ( 0 , 120 , 20 )) + scale_y_continuous ( limits = c ( - 10 , 10 ), breaks = c ( - 10 , - 5 , 0 , 5 , 10 )) + ggtitle ( "PSM retention time against delta precursor mass" ) + theme_bw () Since we applied a precursor mass tolerance of 10 ppm during the identification search, all of the PSMs are within ±10 ppm. Ideally, however, we want the majority of the data to be within ±5 ppm since smaller delta masses correspond to a greater rate of correct peptide identifications. From the graph we have plotted we can see that indeed the majority of PSMs are within ±5 ppm. If users find that too many PSMs are outside of the desired ±5 ppm, it is advisable to check the calibration of the mass spectrometer. The second quality control plot of raw data is that of MS2 ion inject time across the retention time gradient. Here, it is desirable to achieve an average MS2 injection time of 50 ms or less, although the exact target threshold will depend upon the sample load. If the average ion inject time is longer than desired, then the ion transfer tube and/or front end optics of the instrument may require cleaning. ## Generate scatter plot of ion inject time across retention time cp_qf[[ "psms_raw" ]] %>% rowData () %>% as_tibble () %>% ggplot ( aes ( x = RT.in.min, y = Ion.Inject.Time.in.ms)) + geom_point ( size = 0.5 , shape = 4 ) + geom_hline ( yintercept = 50 , linetype = "dashed" , color = "red" ) + labs ( x = "RT (min)" , y = "Ion inject time (ms)" ) + scale_x_continuous ( limits = c ( 0 , 120 ), breaks = seq ( 0 , 120 , 20 )) + scale_y_continuous ( limits = c ( 0 , 60 ), breaks = seq ( 0 , 60 , 10 )) + ggtitle ( "PSM retention time against ion inject time" ) + theme_bw () From this plot we can see that whilst there is a high density of PSMs at low inject times, there are also many data points found at the 50 ms threshold. This indicates that by increasing the time allowed for ions to accumulate in the ion trap, the number of PSMs could also have been increased. Finally, we inspect the distribution of PSMs across both the ion injection time and retention time by plotting histograms. ## Plot histogram of PSM ion inject time cp_qf[[ "psms_raw" ]] %>% rowData () %>% as_tibble () %>% ggplot ( aes ( x = Ion.Inject.Time.in.ms)) + geom_histogram ( binwidth = 1 ) + labs ( x = "Ion inject time (ms)" , y = "Frequency" ) + scale_x_continuous ( limits = c ( - 0.5 , 52.5 ), breaks = seq ( 0 , 50 , 5 )) + ggtitle ( "PSM frequency across ion injection time" ) + theme_bw () ## Plot histogram of PSM retention time cp_qf[[ "psms_raw" ]] %>% rowData () %>% as_tibble () %>% ggplot ( aes ( x = RT.in.min)) + geom_histogram ( binwidth = 1 ) + labs ( x = "RT (min)" , y = "Frequency" ) + scale_x_continuous ( breaks = seq ( 0 , 120 , 20 )) + ggtitle ( "PSM frequency across retention time" ) + theme_bw () The four plots that we have generated look relatively standard with no obvious problems indicated. Therefore, we continue by evaluating the quality of the processed data. Checking the efficiency of TMT labelling The most fundamental data quality control step in a TMT experiment is to check the TMT labelling efficiency. TMT labels react with amine groups present at the peptide N-terminus as well as the side chain of lysine (K) residues. Of note, lysine residues can be TMT modified regardless of whether they are present at the C-terminus of a tryptic peptide or internally following miscleavage. To evaluate the TMT labelling efficiency, a separate identification search of the raw data was completed with lysine (K) and peptide N-termini TMT labels considered as dynamic modifications rather than static. No additional residues (S or T) were evaluated for labelling in the search. This allows the search engine to assess the presence of both the modified (TMT labelled) and unmodified (original) forms of each peptide. The relative proportions of modified and unmodified peptides can then be used to calculate the TMT labelling efficiency. To demonstrate how to check for TMT labelling efficiency, only two of the eight fractions were utilised for this search. As we will only look at TMT efficiency at the PSM-level, here we upload the .txt into a data.frame to format into a SummarizedExperiment object. This is done using the readSummarizedExperiment function and the same arguments as those in readQFeatures . The reason for this is that we only need the PSM-level data, so do not need to generate a QFeatures object with the function of holding multiple SummarizedExperiments across different levels. ## Locate the PSM .txt file tmt_psm <- "cell_pellet_tmt_efficiency_psms.txt" ## Import into a data.frame tmt_df % names () ## [1] "PSMs.Workflow.ID" "PSMs.Peptide.ID" ## [3] "Checked" "Tags" ## [5] "Confidence" "Identifying.Node.Type" ## [7] "Identifying.Node" "Search.ID" ## [9] "Identifying.Node.No" "PSM.Ambiguity" ## [11] "Sequence" "Annotated.Sequence" ## [13] "Modifications" "Number.of.Proteins" ## [15] "Master.Protein.Accessions" "Master.Protein.Descriptions" ## [17] "Protein.Accessions" "Protein.Descriptions" ## [19] "Number.of.Missed.Cleavages" "Charge" ## [21] "Original.Precursor.Charge" "Delta.Score" ## [23] "Delta.Cn" "Rank" ## [25] "Search.Engine.Rank" "Concatenated.Rank" ## [27] "mz.in.Da" "MHplus.in.Da" ## [29] "Theo.MHplus.in.Da" "Delta.M.in.ppm" ## [31] "Delta.mz.in.Da" "Ions.Matched" ## [33] "Matched.Ions" "Total.Ions" ## [35] "Intensity" "Activation.Type" ## [37] "NCE.in.Percent" "MS.Order" ## [39] "Isolation.Interference.in.Percent" "SPS.Mass.Matches.in.Percent" ## [41] "Average.Reporter.SN" "Ion.Inject.Time.in.ms" ## [43] "RT.in.min" "First.Scan" ## [45] "Last.Scan" "Master.Scans" ## [47] "Spectrum.File" "File.ID" ## [49] "Abundance.126" "Abundance.127" ## [51] "Abundance.128" "Abundance.129" ## [53] "Abundance.130" "Abundance.131" ## [55] "Quan.Info" "Peptides.Matched" ## [57] "XCorr" "Number.of.Protein.Groups" ## [59] "Contaminant" "Percolator.q.Value" ## [61] "Percolator.PEP" "Percolator.SVMScore" ## Read in as a SummarizedExperiment tmt_se <- readSummarizedExperiment ( assayData = tmt_df, quantCols = 49 : 54 ) ## Clean sample names colnames (tmt_se) <- c ( "S5" , "S2" , "S1" , "S4" , "S6" , "S3" ) ## Add sample info as colData to QFeatures object tmt_se $ label <- c ( "TMT126" , "TMT127" , "TMT128" , "TMT129" , "TMT130" , "TMT131" ) tmt_se $ sample <- c ( "S5" , "S2" , "S1" , "S4" , "S6" , "S3" ) tmt_se $ condition <- c ( "Control" , "Treated" , "Treated" , "Control" , "Control" , "Treated" ) ## Verify colData (tmt_se) ## DataFrame with 6 rows and 3 columns ## label sample condition ## ## S5 TMT126 S5 Control ## S2 TMT127 S2 Treated ## S1 TMT128 S1 Treated ## S4 TMT129 S4 Control ## S6 TMT130 S6 Control ## S3 TMT131 S3 Treated Information about the presence of labels is stored within the ‘Modifications’ feature of the rowData . Using this information, the TMT labelling efficiency of the experiment is calculated using the code chunks below. Users should alter this code if TMTpro reagents are being used such that “TMT6plex” is replaced by “TMTpro”. First we consider the efficiency of peptide N-termini TMT labelling. We use the grep function to identify PSMs which are annotated as having an N-Term TMT6plex modification. We then calculate the number of PSMs with this annotation as a proportion of the total number of PSMs. ## Count the total number of PSMs tmt_total <- length (tmt_se) ## Count the number of PSMs with an N-terminal TMT modification nterm_labelled_rows <- grep ( "N-Term \\ (TMT6plex \\ )" , rowData (tmt_se) $ Modifications) nterm_psms_labelled <- length (nterm_labelled_rows) ## Calculate N-terminal TMT labelling efficiency efficiency_nterm % round ( digits = 1 ) %>% print () ## [1] 96.8 Secondly, we consider the TMT labelling efficiency of lysine (K) residues. As mentioned above, lysine residues can be TMT labelled regardless of their position within a peptide. Hence, we here calculate lysine labelling efficiency on a per lysine residue basis. ## Count the number of lysine TMT6plex modifications in the PSM data k_tmt % sum () %>% as.numeric () ## Count the number of lysine residues in the PSM data k_total % sum () %>% as.numeric () ## Determine the percentage of TMT labelled lysines efficiency_k % round ( digits = 1 ) %>% print () ## [1] 98.5 Users should aim for an overall TMT labelling efficiency >90 % in order to achieve reliable quantitation. In cases where labelling efficiency is towards the lower end of the acceptable range, TMT labels should be set as dynamic modifications during the final identification search, although this will increase the search space and time as well as influencing FDR calculations. A summary of the current advice from Thermo Fisher is provided in Table 2 . Where labelling efficiency is calculated as being between categories, how to progress is ultimately decided by the user. Table 2. ThermoFisher search strategy recommendations based on TMT labelling efficiency. N-term efficiency K efficiency Suggested search method > 98 % > 98 % Both modifications as ‘static’ - 95 % > 98 % N-terminal modification ‘dynamic’ and K modification ‘static’ < 84 % < 84 % Data not suitable for quantitation Since the use-case data has a sufficiently high TMT labelling efficiency, we can continue to use the output of the identification search. This search considered TMT labelling of lysines as a static modification whilst N-terminal labelling was kept as dynamic, to investigate the presence of protein N-terminal modifications. Basic data cleaning Being confident that the experiment and identification search were successful, we can now begin with some basic data cleaning. However, we also want to keep a copy of the raw PSM data. Therefore, we first create a second copy of the PSM SummarizedExperiment , called “psms_filtered”, and add it to the QFeatures object. This is done using the addAssay function. All changes made at the PSM level will then only be applied to this second copy, so that we can refer back to the original data if needed. ## Extract the "psms_raw" SummarizedExperiment data_copy <- cp_qf[[ "psms_raw" ]] ## Add copy of SummarizedExperiment cp_qf <- addAssay ( x = cp_qf, y = data_copy, name = "psms_filtered" ) ## Verify cp_qf ## An instance of class QFeatures containing 2 assays: ## [1] psms_raw: SummarizedExperiment with 48832 rows and 6 columns ## [2] psms_filtered: SummarizedExperiment with 48832 rows and 6 columns Of note, manually adding an assay (or SummarizedExperiment ) to the QFeatures object does not automatically generate links between these assays. We will manually add the explicit links later, after we complete data cleaning and filtering. The cleaning steps included in this section are non-specific and should be applied to all quantitative proteomics datasets. The names of key parameters will vary in data outputs from alternative third-party software, however, and users should remain aware of both terminology changes over time as well as the introduction of new filters. All data cleaning steps are completed in the same way. We first determine how many rows, here PSMs, meet the conditions for removal. This is achieved by using the dplyr::count function. The unwanted rows are removed using the filterFeatures function. Since we only wish to apply the filters to the “psms_filtered” level, we specify this by using the i = argument. If this argument is not used, filterFeatures will remove features from all levels ( SummarizedExperiments ) within a QFeatures object. Removing PSMs not matched to a master protein The first common cleaning step we carry out is the removal of PSMs that have not been assigned to a master protein during the identification search. This can happen when the search software is unable to resolve conflicts caused by the presence of the isobaric amino acids leucine and isoleucine. Before implementing the filter, it is useful to find out how many PSMs we expect to remove. This is easily done by using the dplyr::count on the master protein column. Any master proteins that return TRUE will be removed by filtering. If this returns no TRUE values, users should move on to the next filtering step without removing rows as this will introduce an error. ## Find out how many PSMs we expect to lose cp_qf[[ "psms_filtered" ]] %>% rowData () %>% as_tibble () %>% dplyr :: count(Master.Protein.Accessions == "" ) ## # A tibble: 2 x 2 ## 'Master.Protein.Accessions == ""' n ## ## 1 FALSE 48660 ## 2 TRUE 172 For users who wish to explicitly track the process of data cleaning, the code chunk below demonstrates how to print a message containing the number of features removed. paste ( "Removing" , length ( which ( rowData ( cp_qf[[ "psms_filtered" ]]) $ Master.Protein.Accessions == "" )), "PSMs without a master protein accession" ) %>% message () ## Removing 172 PSMs without a master protein accession This code could be adapted to each cleaning and filtering step. To maintain simplicity of this workflow, we will not print explicit messages at each step. Instead, the decision to do so is left to the user. ## Remove PSMs without a master protein accession using filterFeatures cp_qf % filterFeatures ( ~ ! Master.Protein.Accessions == "" , i = "psms_filtered" ) Removing PSMs matched to a contaminant protein Next we remove PSMs corresponding to contaminant proteins. Such proteins can be introduced intentionally as reagents during sample preparation, as is the case for digestive enzymes, or accidentally, as seen with human keratins derived from skin and hair. Since these proteins do not contribute to the biological question being asked it is standard practice to remove them from the data. This is done by using a carefully curated, sample-specific contaminant database. Critically, the database used for filtering should be the same one that was used during the identification search. Whilst it is possible to remove contaminants using the filterFeatures function on a contaminants annotation column (as per the QFeatures processing vignette ), we demonstrate how to filter using only contaminant protein accessions for users who do not have contaminant annotations within their identification data. For this experiment, a contaminant database from Ref. 20 was used. The .fasta file for this database is available at the Hao Group’s Github Repository for Protein Contaminant Libraries for DDA and DIA Proteomics and specifically can be found at https://github.com/HaoGroup-ProtContLib/Protein-Contaminant-Libraries-for-DDA-and-DIA-Proteomics/tree/main/Universal%20protein%20contaminant%20FASTA . Here, we import this file using the fasta.index function from the Biostrings package. 21 This function requires a file path to the .fasta file and the asks users to specify the sequence type. In this case we have amino acid sequences so pass seqtype = "AA" . The function returns a data.frame with one row per FASTA entry. We then can extract the protein accessions from the fasta file. Users will need to alter the below code according to the contaminant file used. ## Load Hao group .fasta file used in search cont_fasta <- "220813_universal_protein_contaminants_Haogroup.fasta" conts <- Biostrings :: fasta.index (cont_fasta, seqtype = "AA" ) ## Extract only the protein accessions (not Cont_ at the start) cont_acc <- regexpr ( "(?% regmatches (conts $ desc, .) Now we have our contaminant list by accession number, we can identify and remove PSMs with any contaminant protein within their “Protein.Accessions”. Importantly, filtering on “Protein.Accessions” ensures the removal of PSMs which matched to a protein group containing a contaminant protein, even if the contaminant protein is not the group’s master protein. ## Define function to find contaminants find_cont <- function (se, cont_acc) { cont_indices <- c () for (i in 1 : length (cont_acc)) { cont_protein <- cont_acc[i] cont_present <- grep (cont_protein, rowData (se) $ Protein.Accessions) output <- c (cont_present) cont_indices <- append (cont_indices, output) } cont_psm_indices <- cont_indices } ## Store row indices of PSMs matched to a contaminant-containing protein group cont_psms 0 ) cp_qf[[ "psms_filtered" ]] <- cp_qf[[ "psms_filtered" ]][ - cont_psms, ] At this point, users can also remove any additional proteins which may not have been included in the contaminant database. For example, users may wish to remove human trypsin (accession P35050) should it appear in their data. Several third-party software also have the option to directly annotate which fasta file (here, the human proteome or contaminant database) a PSM is derived from. In such cases, filtering can be simplified by removing PSMs annotated as contaminants in the output file. Removing PSMs which lack quantitative data Now that we are left with only PSMs matched to proteins of interest, we filter out PSMs which cannot be used for quantitation. This includes some PSMs which lack quantitative information altogether. In outputs derived from Proteome Discoverer this information is included in the “Quan.Info” column where PSMs are annotated as having “NoQuanLabels”. For users who have considered both lysine and N-terminal TMT labels as static modifications, the data should not contain any PSMs without quantitative information. However, since the use-case data was derived from a search in which N-terminal TMT modifications were dynamic, the data does include this annotation. Users are reminded that column names are typically software-specific as the “Quan.Info” column is found only in outputs derived from Proteome Discoverer. However, the majority of alternative third party software will have an equivalent column containing the same information. ## Find out how many PSMs we expect to lose cp_qf[[ "psms_filtered" ]] %>% rowData () %>% as_tibble () %>% dplyr :: count (Quan.Info == "NoQuanLabels" ) ## # A tibble: 2 x 2 ## 'Quan.Info == "NoQuanLabels"' n ## ## 1 FALSE 47241 ## 2 TRUE 228 ## Drop these rows from the data cp_qf % filterFeatures ( ~ ! Quan.Info == "NoQuanLabels" , i = "psms_filtered" ) This point in the workflow is a good time to check whether there are any other annotations within the “Quan.Info” column. For example, if there are any PSMs which have been “ExcludedByMethod”, this indicates that a PSM-level filter was applied in Proteome Discoverer during the identification search. If this is the case, users should determine which filter has been applied to the data and decide whether to remove the PSMs which were “ExcludedByMethod” (thereby applying the pre-set threshold) or leave them in (disregard the threshold). ## Are there any remaining annotations in the Quan.Info column? cp_qf[[ "psms_filtered" ]] %>% rowData () %>% as_tibble () %>% pull (Quan.Info) %>% table () ## . ## ## 47241 In the above code chunk we see that there are no remaining annotations in the “Quan.Info” column so we can continue. Removing PSMs which are not unique to a protein The next step is to consider which PSMs are to be used for quantitation. There are two ways in which a PSM can be considered as unique. The first and most pure form of uniqueness comes from a PSM corresponding to a single protein only. This results in the PSM being allocated to one protein and one protein group. However, it is common to expand the definition of unique to include PSMs that map to multiple proteins within a single protein group. That is PSMs which are allocated to more than one protein but only one protein group. In other cases, these peptides may be referred to as ‘shared peptides’. This distinction is ultimately up to the user. By contrast, PSMs corresponding to razor peptides are linked to multiple proteins across multiple protein groups. Overall, the definitions of unique, shared and razor peptides are complex and are directly influenced by the strategy used for protein inference as well as the inclusion or exclusion of protein isoforms from the database search. Therefore, it is important for users to be aware of these definitions and explicitly define which peptides they wish to use for quantitation. In this workflow, the final grouping of peptides to proteins will be done based on master protein accession. Therefore, differential expression analysis will be based on protein groups, and we here consider unique as any PSM linked to only one protein group. This means removing PSMs where “Number.of.Protein.Groups” is not equal to 1. In the below code chunk we count the number of PSMs linked to more than 1 protein group. ## Find out how many PSMs we expect to lose cp_qf[[ "psms_filtered" ]] %>% rowData () %>% as_tibble () %>% dplyr :: count (Number.of.Protein.Groups != 1 ) ## # A tibble: 2 x 2 ## 'Number.of.Protein.Groups != 1' n ## ## 1 FALSE 44501 ## 2 TRUE 2740 We again use the filterFeatures function to retain PSMs linked to only 1 protein group and discard any PSMs linked to more 1 group. ## Remove these rows from the data cp_qf % filterFeatures ( ~ Number.of.Protein.Groups == 1 , i = "psms_filtered" ) Removing PSMs that are not rank 1 Another filter that is important for quantitation is that of PSM rank. Since individual spectra can have multiple candidate peptide matches, Proteome Discoverer uses a scoring algorithm to determine the probability of a PSM being incorrect. Once each candidate PSM has been given a score, the one with the lowest score (lowest probability of being incorrect) is allocated rank 1. The PSM with the second lowest probability of being incorrect is rank 2, and so on. For the analysis, we only want rank 1 PSMs to be retained. ## Find out how many PSMs we expect to lose cp_qf[[ "psms_filtered" ]] %>% rowData () %>% as_tibble () %>% dplyr :: count (Rank != 1 ) ## # A tibble: 2 x 2 ## 'Rank != 1' n ## ## 1 FALSE 43426 ## 2 TRUE 1075 ## Drop these rows from the data cp_qf % filterFeatures ( ~ Rank == 1 , i = "psms_filtered" ) The majority of search engines, including SequestHT, also provide their own PSM rank. To be conservative and ensure accurate quantitation, we also only retain PSMs that have a search engine rank of 1. ## Find out how many PSMs we expect to lose cp_qf[[ "psms_filtered" ]] %>% rowData () %>% as_tibble () %>% dplyr :: count (Search.Engine.Rank != 1 ) ## # A tibble: 2 x 2 ## 'Search.Engine.Rank != 1' n ## ## 1 FALSE 43153 ## 2 TRUE 273 ## Drop these rows from the data cp_qf % filterFeatures ( ~ Search.Engine.Rank == 1 , i = "psms_filtered" ) Removing ambiguous PSMs We also retain only unambiguous PSMs. Since there are several candidate peptides for each spectra, Proteome Discoverer allocates each PSM a level of ambiguity to indicate whether it was possible to determine a definite PSM or whether one had to be selected from a number of candidates. The allocation of PSM ambiguity takes place during the process of protein grouping and the definitions of each ambiguity assignment are given below in Table 3 . Table 3. Definitions of PSM ambiguity categories based on Proteome Discoverer outputs. PSM category Definition Unambiguous The only candidate PSM Selected PSM was selected from a group of candidates Rejected PSM was rejected from a group of candidates Ambiguous Two or more candidate PSMs could not be distinguished Unconsidered PSM was not considered suitable Importantly, depending upon the software being used, output files may already have excluded some of these categories. It is still good to check before proceeding with the data. ## Find out how many PSMs we expect to lose cp_qf[[ "psms_filtered" ]] %>% rowData () %>% as_tibble () %>% dplyr :: count (PSM.Ambiguity != "Unambiguous" ) ## # A tibble: 1 x 2 ## 'PSM.Ambiguity != "Unambiguous"' n ## ## 1 FALSE 43153 ## No PSMs to remove so proceed Controlling false discovery rate Finally, it is necessary to control the false discovery rate. During a database search, peptide spectrum matches (PSMs) are generated by matching raw mass spectra to peptide sequences. However, only a number of these PSMs will be true positive matches, whilst the rest are false positives, or ‘false discoveries’. Most third party software contain internal algorithms to determine the number of false discoveries and the probability of a given feature (PSM, peptide or protein) being a false discovery. This information can then be used to control the false discovery rate (FDR), typically to keep this below 5% for exploratory analyses or 1% for stringent analyses. During the database search of the use-case data, only high confidence PSMs with an FDR % rowData () %>% as_tibble () %>% pull (Confidence) %>% table () ## . ## High ## 43153 Importantly, however, FDR becomes inflated as you aggregate up from PSM to peptide and then from peptide to protein. Therefore, a 1% FDR at PSM-level does not ensure a 1% FDR at protein-level. To access information about protein-level FDR, we have to import the protein-level .txt file from our database search. As before, users should store this file in their working directory. ## Import protein-level data protein_cp % names () ## [1] "Proteins.Unique.Sequence.ID" ## [2] "Checked" ## [3] "Tags" ## [4] "Protein.FDR.Confidence.Combined" ## [5] "Master" ## [6] "Protein.Group.IDs" ## [7] "Accession" ## [8] "Description" ## [9] "Sequence" ## [10] "FASTA.Title.Lines" ## [11] "Exp.q.value.Combined" ## [12] "Sum.PEP.Score" ## [13] "Number.of.Decoy.Protein.Combined" ## [14] "Coverage.in.Percent" ## [15] "Number.of.Peptides" ## [16] "Number.of.PSMs" ## [17] "Number.of.Protein.Unique.Peptides" ## [18] "Number.of.Unique.Peptides" ## [19] "Number.of.AAs" ## [20] "MW.in.kDa" ## [21] "calc.pI" ## [22] "Score.Sequest.HT.Sequest.HT" ## [23] "Coverage.in.Percent.by.Search.Engine.Sequest.HT" ## [24] "Number.of.PSMs.by.Search.Engine.Sequest.HT" ## [25] "Number.of.Peptides.by.Search.Engine.Sequest.HT" ## [26] "Abundance.F1.126.Sample" ## [27] "Abundance.F1.127.Sample" ## [28] "Abundance.F1.128.Sample" ## [29] "Abundance.F1.129.Sample" ## [30] "Abundance.F1.130.Sample" ## [31] "Abundance.F1.131.Sample" ## [32] "Abundances.Count.F1.126.Sample" ## [33] "Abundances.Count.F1.127.Sample" ## [34] "Abundances.Count.F1.128.Sample" ## [35] "Abundances.Count.F1.129.Sample" ## [36] "Abundances.Count.F1.130.Sample" ## [37] "Abundances.Count.F1.131.Sample" ## [38] "Found.in.Fraction.F11" ## [39] "Found.in.Fraction.F12" ## [40] "Found.in.Fraction.F13" ## [41] "Found.in.Fraction.F14" ## [42] "Found.in.Fraction.F15" ## [43] "Found.in.Fraction.F16" ## [44] "Found.in.Fraction.F17" ## [45] "Found.in.Fraction.F18" ## [46] "Found.in.Sample.in.S1.F1.126.Sample" ## [47] "Found.in.Sample.in.S2.F1.127.Sample" ## [48] "Found.in.Sample.in.S3.F1.128.Sample" ## [49] "Found.in.Sample.in.S4.F1.129.Sample" ## [50] "Found.in.Sample.in.S5.F1.130.Sample" ## [51] "Found.in.Sample.in.S6.F1.131.Sample" ## [52] "Found.in.Sample.Group.in.S1.F1.126.Sample" ## [53] "Found.in.Sample.Group.in.S2.F1.127.Sample" ## [54] "Found.in.Sample.Group.in.S3.F1.128.Sample" ## [55] "Found.in.Sample.Group.in.S4.F1.129.Sample" ## [56] "Found.in.Sample.Group.in.S5.F1.130.Sample" ## [57] "Found.in.Sample.Group.in.S6.F1.131.Sample" ## [58] "Number.of.Protein.Groups" The FDR information is contained in a column called Protein.FDR.Confidence.Combined . We can get an overview of the data in this column by using the table function. protein_cp %>% pull (Protein.FDR.Confidence.Combined) %>% table () ## . ## High Low Medium ## 4824 75 467 We see proteins that are annotated as high confidence = FDR < 1%, medium confidence = FDR 5%. In order to use the filterFeatures function to remove PSMs corresponding to proteins which do not pass our FDR threshold (1%), we first need to add this annotation to the rowData of our "psms_filtered" experiment. To do this, we extract the master protein accessions from our PSM-level data. Next, we extract these proteins from our protein-level search output along with their corresponding confidence ratings. ## Extract master protein accessions from our PSM-level data proteins_in_data % rowData () %>% as_tibble () %>% select (Master.Protein.Accessions) ## Extract protein accessions and confidence from search output file protein_search_output % select (Accession, Protein.FDR.Confidence.Combined) Now we can use the left_join function to merge these two datasets. ## Combine data protein_fdr % head () ## # A tibble: 6 x 2 ## Master.Protein.Accessions Protein.FDR.Confidence.Combined ## ## 1 Q92597 High ## 2 Q9UGP4 High ## 3 Q9BRX2 High ## 4 P14868 High ## 5 O00154 High ## 6 P48651 High Finally, we add the annotations from our "Protein.FDR.Confidence.Combined" column to the rowData of our "psms_filtered" experiment. rowData (cp_qf[[ "psms_filtered" ]]) $ Protein.Confidence <- protein_fdr $ Protein.FDR.Confidence.Combined We can now use filterFeatures to remove PSMs corresponding to low or medium confidence master proteins. cp_qf % filterFeatures ( ~ Protein.Confidence == "High" , i = "psms_filtered" ) ## 'Protein.Confidence' found in 1 out of 2 assay(s) ## No filter applied to the following assay(s) because one or more filtering variables are missing in the rowData: psms_raw. ## You can control whether to remove or keep the features using the 'keep' argument (see '?filterFeature'). Assessing the impact of non-specific data cleaning Now that we have finished the non-specific data cleaning, we can pause and check to see what this has done to the data. We determine the number and proportion of PSMs, peptides, and protein groups lost from the original dataset. ## Determine number and proportion of PSMs removed psms_remaining % nrow () %>% as.numeric () psms_removed <- original_psms - psms_remaining psms_removed_prop % round ( digits = 2 ) ## Determine number and proportion of peptides removed peps_remaining % rowData () %>% as_tibble () %>% pull (Sequence) %>% unique () %>% length () %>% as.numeric () peps_removed <- original_peps - peps_remaining peps_removed_prop % round ( digits = 2 ) ## Determine number and proportion of proteins removed prots_remaining % rowData () %>% as_tibble () %>% pull (Master.Protein.Accessions) %>% unique () %>% length () %>% as.numeric () prots_removed <- original_prots - prots_remaining prots_removed_prop % round ( digits = 2 ) ## Print as a table data.frame ( "Feature" = c ( "PSMs" , "Peptides (stripped)" , "Protein groups" ), "Number lost" = c (psms_removed, peps_removed, prots_removed), "Percentage lost" = c (psms_removed_prop, peps_removed_prop, prots_removed_prop)) ## Feature Number.lost Percentage.lost ## 1 PSMs 6066 12.42 ## 2 Peptides (stripped) 1925 7.41 ## 3 Protein groups 812 16.11 PSM quality control filtering The next step is to take a look at the data and make informed decisions about in-depth filtering. Here, we focus on three key quality control filters for TMT data: 1) average reporter ion signal-to-noise (S/N) ratio, 2) percentage co-isolation interference, and 3) percentage SPS mass match. It is possible to set thresholds for these three parameters during the identification search. However, specifying thresholds prior to exploring the data could lead to unnecessarily excessive data exclusion or the retention of poor quality PSMs. We suggest that users set the thresholds for all three aforementioned filters to 0 during the identification search, thus allowing maximum flexibility during data processing. In all cases, quality control filtering represents a trade-off between ensuring high quality data and losing potentially informative data. This means that the thresholds used for such filtering will likely depend upon the initial quality of the data and the number of PSMs, as well as the experimental goal being stringent or exploratory. Quality control: Average reporter ion signal-to-noise Intensity measurements derived from a small number of ions tend to be more variable and less accurate. Therefore, reporter ion spectra with peaks generated from a small number of ions should be filtered out to ensure accurate quantitation and avoid stochastic ion effects. When using an orbitrap analyzer, as was the case in the collection of the use-case data, the number of ions is proportional to the S/N value of a peak. Hence, the average reporter ion S/N ratio can be used to filter out quantification based on too few ions. To determine an appropriate reporter ion S/N threshold we need to understand the original, unfiltered data. Here, we print a summary of the average reporter S/N before plotting a simple histogram to visualise the data. The default threshold for average reporter ion S/N when filtering within Proteome Discoverer is 10, or 1 on the base-10 logarithmic scale displayed here. We include a line to show where this threshold would be on the data distribution. ## Get summary information cp_qf[[ "psms_filtered" ]] %>% rowData () %>% as_tibble () %>% pull (Average.Reporter.SN) %>% summary () ## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's ## 0.3 84.3 216.4 322.1 451.1 3008.2 138 ## Plot histogram of reporter ion signal-to-noise} cp_qf[[ "psms_filtered" ]] %>% rowData () %>% as_tibble () %>% ggplot ( aes ( x = log10 (Average.Reporter.SN))) + geom_histogram ( binwidth = 0.05 ) + geom_vline ( xintercept = 1 , linetype = "dashed" , color = "red" ) + labs ( x = "log10(average reporter SN)" , y = "Frequency" ) + ggtitle ( "Average reporter ion S/N" ) + theme_bw () From the distribution of the data it is clear that applying such a threshold would not result in dramatic data loss. Whilst we could set a higher threshold for more stringent analysis, this would lead to unnecessary data loss. Therefore, we keep PSMs with an average reporter ion S/N threshold of 10 or more. We also remove PSMs that have an NA value for their average reporter ion S/N since their quality cannot be guaranteed. This is done by including na.rm = TRUE . ## Find out how many PSMs we expect to lose cp_qf[[ "psms_filtered" ]] %>% rowData () %>% as_tibble () %>% dplyr :: count (Average.Reporter.SN < 10 ) ## # A tibble: 3 x 2 ## 'Average.Reporter.SN < 10' n ## ## 1 FALSE 41696 ## 2 TRUE 932 ## 3 NA 138 ## Drop these rows from the data cp_qf % filterFeatures ( ~ Average.Reporter.SN >= 10 , na.rm = TRUE , i = "psms_filtered" ) Quality control: Isolation interference A second data-dependent quality control parameter which should be considered is the isolation interference. The first type of interference that occurs during a TMT experiment is reporter ion interference, also known as cross-label isotopic impurity. This type of interference arises from manufacturing-level impurities and experimental error. The former should be reduced somewhat by the inclusion of lot-specific correction factors in the search set-up and users should ensure that these corrections are applied. In Proteome Discoverer this means setting “Apply Quan Value Corrections” to “TRUE” within the reporter ions quantifier node. The second form of interference is co-isolation interference which occurs during the MS run when multiple labelled precursor peptides are co-isolated in a single data acquisition window. Following fragmentation of the co-isolated peptides, this results in an MS2 or MS3 reporter ion peak (depending upon the experimental design) derived from multiple precursor peptides. Hence, co-isolation interference leads to inaccurate quantitation of the identified peptide. This problem is reduced by filtering out PSMs with a high percentage isolation interference value. As was the case for reporter ion S/N, Proteome Discoverer has a suggested default threshold for isolation interference - 50% for MS2 experiments and 75% for SPS-MS3 experiments. Again, we get a summary and visualise the data using the code chunk below. ## Get summary information cp_qf[[ "psms_filtered" ]] %>% rowData () %>% as_tibble () %>% pull (Isolation.Interference.in.Percent) %>% summary () ## Min. 1st Qu. Median Mean 3rd Qu. Max. ## 0.000 0.000 8.365 12.623 21.035 84.379 ## Plot histogram of co-isolation interference cp_qf[[ "psms_filtered" ]] %>% rowData () %>% as_tibble () %>% ggplot ( aes ( x = Isolation.Interference.in.Percent)) + geom_histogram ( binwidth = 2 ) + geom_vline ( xintercept = 75 , linetype = "dashed" , color = "red" ) + labs ( x = "Isolation inteference (%)" , y = "Frequency" ) + ggtitle ( "Co-isolation interference %" ) + theme_bw () Looking at the data, very few PSMs have an isolation interference above the suggested threshold, and hence minimal data will be lost. Again, we choose to apply the standard threshold with the understanding that decreasing the threshold would result in greater data loss. Importantly, we are able to apply relatively standard thresholds here as the preliminary exploration did not expose any problems with the experimental data (in terms of labelling or MS analysis). If users have reason to believe the data is of poorer quality then more stringent thresholding should be considered. ## Find out how many PSMs we expect to lose cp_qf[[ "psms_filtered" ]] %>% rowData () %>% as_tibble () %>% dplyr :: count (Isolation.Interference.in.Percent > 75 ) ## # A tibble: 2 x 2 ## `Isolation.Interference.in.Percent > 75` n ## ## 1 FALSE 41638 ## 2 TRUE 58 ## Remove these rows from the data cp_qf % filterFeatures ( ~ Isolation.Interference.in.Percent <= 75 , na.rm = TRUE , i = "psms_filtered" ) Quality control: SPS mass match The final quality control filter that we will apply is a percentage SPS mass match threshold. SPS mass match is a metric which has been introduced by Proteome Discoverer versions 2.3 and above to quantify the percentage of SPS-MS3 fragments that can still be explicitly traced back to the precursor peptide. This parameter is of particular importance given that quantitation is based on the SPS-MS3 spectra. Unfortunately, the SPS Mass Match percentage is currently only a feature of Proteome Discoverer (2.3 and above) and will not be available to users of other third-party software. We follow the same format as before to investigate the SPS Mass Match (%) distribution of the data. The default threshold within Proteome Discoverer is a SPS Mass Match above 65%. In reality, since SPS Mass Match is only reported to the nearest 10%, removing PSMs annotated with a value below 65% means removing those with 60% or less. Hence, only PSMs with 70% SPS Mass Match or above would be retained. We can see how many PSMs would be lost based on such thresholds using the code chunk below. ## Get summary information cp_qf[[ "psms_filtered" ]] %>% rowData () %>% as_tibble () %>% pull (SPS.Mass.Matches.in.Percent) %>% summary () ## Min. 1st Qu. Median Mean 3rd Qu. Max. ## 0.00 50.00 70.00 64.46 80.00 100.00 ## Plot histogram of SPS mass match % cp_qf[[ "psms_filtered" ]] %>% rowData () %>% as_tibble () %>% ggplot ( aes ( x = SPS.Mass.Matches.in.Percent)) + geom_histogram ( binwidth = 10 ) + geom_vline ( xintercept = 65 , linetype = "dashed" , color = "red" ) + labs ( x = "SPS mass matches (%)" , y = "Frequency" ) + scale_x_continuous ( breaks = seq ( 0 , 100 , 10 )) + ggtitle ( "SPS mass match %" ) + theme_bw () From the summary and histogram we can see that the distribution of SPS Mass Matches is much less skewed than that of average reporter ion S/N or isolation interference. This means that whilst the application of thresholds on average reporter ion S/N and isolation interference led to minimal data loss, attempting to impose a threshold on SPS Mass Match represents a much greater trade-off between data quality and quantity. For simplicity, here we choose to use the standard threshold of 65%. ## Find out how many PSMs we expect to lose cp_qf[[ "psms_filtered" ]] %>% rowData () %>% as_tibble () %>% dplyr :: count (SPS.Mass.Matches.in.Percent < 65 ) ## # A tibble: 2 x 2 ## 'SPS.Mass.Matches.in.Percent < 65' n ## ## 1 FALSE 21631 ## 2 TRUE 20007 ## Drop these rows from the data cp_qf % filterFeatures ( ~ SPS.Mass.Matches.in.Percent >= 65 , na.rm = TRUE , i = "psms_filtered" ) Assessing the impact of data-specific filtering As we did after the non-specific cleaning steps, we check to see how many PSMs, peptides and protein groups have been removed throughout the in-depth data-specific filtering. ## Summarise the effect of data-specific filtering ## Determine the number and proportion of PSMs removed psms_remaining_2 % nrow () %>% as.numeric () psms_removed_2 <- psms_remaining - psms_remaining_2 psms_removed_prop_2 % round ( digits = 2 ) ## Determine number and proportion of peptides removed peps_remaining_2 % unique () %>% length () %>% as.numeric () peps_removed_2 <- peps_remaining - peps_remaining_2 peps_removed_prop_2 % round ( digits = 2 ) ## Determine number and proportion of proteins removed prots_remaining_2 % rowData () %>% as_tibble () %>% pull (Master.Protein.Accessions) %>% unique () %>% length () %>% as.numeric () prots_removed_2 <- prots_remaining - prots_remaining_2 prots_removed_prop_2 % round ( digits = 2 ) ## Print as a table data.frame ( "Feature" = c ( "PSMs" , "Peptides (stripped)" , "Protein groups" ), "Number lost" = c (psms_removed_2, peps_removed_2, prots_removed_2), "Percentage lost" = c (psms_removed_prop_2, peps_removed_prop_2, prots_removed_prop_2)) ## Feature Number.lost Percentage.lost ## 1 PSMs 21135 43.28 ## 2 Peptides (stripped) 9861 37.97 ## 3 Protein groups 998 19.80 Managing missing data Having finished the data cleaning at the PSM-level, the final step is to deal with missing data. Missing values represent a common challenge in quantitative proteomics and there is no consensus within the literature on how this challenge should be addressed. Indeed, missing values fall into different categories based on the reason they were generated, and each category is best dealt with in a different way. There are three main categories of missing data: missing completely at random (MCAR), missing at random (MAR) and missing not at random (MNAR). Within proteomics, values which are MCAR arise due to technical variation or stochastic fluctuations and emerge in a uniform, intensity-independent distribution. Examples include values for peptides which cannot be consistently identified or are unable to be efficiently ionised. By contrast, MNAR values are expected to occur in an intensity-dependent manner due to the presence of peptides at abundances below the limit of detection. 17 , 22 , 23 In many cases this is due to the biological condition being evaluated, for example the cell type or treatment applied. To simplify this process, we consider the management of missing data in three steps. The first step is to determine the presence and pattern of missing values within the data. Next, we filter out data which exceed the desired proportion of missing values. This includes removing PSMs with a greater number of missing values across samples than we deem acceptable, as well as whole samples in cases where the proportion of missing values is substantially higher than the average. Finally, imputation can be used to replace any remaining NA values within the dataset. This final step is optional and can equally be done prior to filtering if the user wishes to impute all missing values without removing any PSMs, although this is not recommended. Further, whilst it is possible to complete such steps at the peptide- or protein-level, we advise management of missing values at the lowest data level to minimise the effect of implicit imputation during aggregation. Exploring the presence of missing values First, to determine the presence of missing values in the PSM-level data we use the nNA function within the QFeatures infrastructure. This function will return the absolute number (nNA) and proportion (pNA) of missing values both per sample and as an average. Importantly, alternative third-party software may output missing values in formats other than NA, such as zero, or infinite. In such cases, missing values can be converted directly into NA values through use of the zeroIsNA or infIsNA functions within the QFeatures infrastructure. ## Determine whether there are any NA values in the data cp_qf[[ "psms_filtered" ]] %>% assay () %>% anyNA () ## [1] TRUE ## Determine the amount and distribution of NA values in the data cp_qf[[ "psms_filtered" ]] %>% nNA () ## $nNA ## DataFrame with 1 row and 2 columns ## nNA pNA ## ## 1 4 3.082e-05 ## ## $nNArows ## DataFrame with 21631 rows and 3 columns ## name nNA pNA ## ## 1 13 0 0 ## 2 20 0 0 ## 3 25 0 0 ## 4 26 0 0 ## 5 29 0 0 ## … … … … ## 21627 48786 0 0 ## 21628 48792 0 0 ## 21629 48797 0 0 ## 21630 48810 0 0 ## 21631 48819 0 0 ## ## $nNAcols ## DataFrame with 6 rows and 3 columns ## name nNA pNA ## ## 1 S5 1 4.62299e-05 ## 2 S2 2 9.24599e-05 ## 3 S1 0 0.00000e+00 ## 4 S4 1 4.62299e-05 ## 5 S6 0 0.00000e+00 ## 6 S3 0 0.00000e+00 We can see that the proportion of missing values in our data is only 0.00003, corresponding to 4 NA values. This low proportion is due to a combination of the TMT labelling strategy and the stringent PSM quality control filtering. In particular, co-isolation interference when using TMT labels often results in very low quantification values for peptides which should actually be missing or ‘NA’. Nevertheless, we continue and check for sample-specific bias in the distribution of NAs by plotting a simple bar chart. We will plot percentage instead of proportion as this is easier to visualise. We also use colour to indicate the condition of each sample as to check for condition-specific bias. ## Plot histogram to visualise the distribution of NAs nNA (cp_qf[[ "psms_filtered" ]]) $ nNAcols %>% as_tibble () %>% mutate ( Condition = c ( "Control" , "Treated" , "Treated" , "Control" , "Control" , "Treated" )) %>% ggplot ( aes ( x = name, y = (pNA * 100 ), group = Condition, fill = Condition)) + geom_bar ( stat = "identity" , position = "dodge" ) + labs ( x = "Sample" , y = "Missing values (%)" ) + theme_bw () The proportion of missing values is sufficiently low that none of the samples need be removed. Further, there is no sample- or condition-specific bias in the data. We can get more information about the PSMs with NA values using the code below. ## Find out the range of missing values per PSM nNA (cp_qf[[ "psms_filtered" ]]) $ nNArows $ nNA %>% table () ## . ## 0 1 ## 21627 4 From this output we can see that the maximum number of NA values per PSM is one. This information is useful to know as it may inform the filtering strategy in the next step. ## Get indices of rows which contain NA rows_with_na_indices <- which ( nNA (cp_qf[[ "psms_filtered" ]]) $ nNArows $ nNA != 0 ) ## Subset rows with NA rows_with_na <- cp_qf[[ "psms_filtered" ]][rows_with_na_indices, ] ## Inspect rows with NA assay (rows_with_na) ## S5 S2 S1 S4 S6 S3 ## 12087 NA 17.0 11.0 22.1 30.6 13.3 ## 30824 69.7 NA 45.0 66.7 62.1 43.1 ## 30846 65.5 NA 34.3 56.8 57.2 47.9 ## 44791 3.8 28.7 22.8 NA 12.2 19.6 Filtering out missing values First we apply some standard filtering. Typically, it is desirable to remove features, here PSMs, with greater than 20% missing values. We can do this using the filterNA function in QFeatures , as outlined below. We pass the function the SummarizedExperiment and use the pNA = argument to specify the maximum proportion of NA values to allow. ## Check how many PSMs we will remove nNA (cp_qf[[ "psms_filtered" ]]) $ nNArows %>% as_tibble () %>% dplyr :: count (pNA >= 0.2 ) ## # A tibble: 1 x 2 ## `pNA >= 0.2` n ## ## 1 FALSE 21631 Although the use-case data does not contain any PSMs with a higher proportion of missing values than 0.2, we demonstrate how to apply the desired filter below. ## Remove PSMs with more than 20 % (0.2) NA values cp_qf % filterNA ( pNA = 0.2 , i = "psms_filtered" ) Since previous exploration of missing data did not reveal any sample with an excessive number of NA values, we do not need to remove any samples from the analysis. Although not covered here, users may wish to carry out condition-specific filtering in cases where the exploration of missing values revealed a condition-specific bias, or where the experimental question requires. This would be the case, for example, if one condition was transfected to express proteins of interest whilst the control condition lacked these proteins. Filtering of both conditions together could, therefore, lead to the removal of proteins of interest. Imputation (optional) The final step is to consider whether to impute the remaining missing values within the data. Imputation refers to the replacement of missing values with probable values. Since imputation requires complex assumptions and can have substantial effects on downstream statistical analysis, we here choose to skip imputation. This is reasonable given that we only have 4 missing values at the PSM-level, and that some of these will likely be removed by aggregation. For users who do wish to impute at this stage, it is important to consider the reason why these missing values exist. The majority of missing values in TMT datasets are due to reporter ion signals below the limit of detection. In other words, most missing values in this dataset are MNAR. Therefore, if exploration of missing values did not indicate an unusually high percentage of missingness, it might be most appropriate to apply left-censored methods (e.g. minimal value approaches, limit of detection). Typically, imputation should be avoided where possible to ensure high confidence in downstream analyses. A more in-depth discussion of imputation will be provided below in the label-free workflow. Summary of PSM data cleaning Thus far we have checked that the experimental data we are using is of high quality by visualizing the raw data and calculating TMT labelling efficiency. We then carried out non-specific data cleaning, data-specific filtering steps and management of missing data. Here, we present a combined summary of these PSM processing steps. ## Determine final number of PSMs, peptides and master proteins psms_final % nrow () %>% as.numeric () psms_removed_total <- original_psms - psms_final psms_removed_total_prop % round ( digits = 2 ) peps_final % rowData () %>% as_tibble () %>% pull (Sequence) %>% unique () %>% length () %>% as.numeric () peps_removed_total <- original_peps - peps_final peps_removed_total_prop % round ( digits = 2 ) prots_final % rowData () %>% as_tibble () %>% pull (Master.Protein.Accessions) %>% unique () %>% length () %>% as.numeric () prots_removed_total <- original_prots - prots_final prots_removed_total_prop % round ( digits = 2 ) ## Print as table data.frame ( "Feature" = c ( "PSMs" , "Peptides (stripped)" , "Protein groups") , "Number lost" = c (psms_removed_total, peps_removed_total, prots_removed_total), "Percentage lost" = c (psms_removed_total_prop, peps_removed_total_prop, prots_removed_total_prop), "Number remaining" = c (psms_final, peps_final, prots_final)) ## Feature Number.lost Percentage.lost Number.remaining ## 1 PSMs 27201 55.70 21631 ## 2 Peptides (stripped) 11786 45.38 14183 ## 3 Protein groups 1810 35.91 3230 Logarithmic transformation of quantitative data Once satisfied that the PSM-level data is clean and of high quality, the PSM-level quantitative data is log transformed. log2 transformation is a standard step when dealing with quantitative proteomics data since protein abundances are dramatically skewed towards zero. Such a skewed distribution is to be expected given that the majority of cellular proteins present at any one time are of relatively low abundance, whilst only a few highly abundant proteins exist. To perform the logarithmic transformation and generate normally distributed data we pass the PSM-level data in the QFeatures object to the logTransform function, as per the below code chunk. ## log2 transform quantitative data cp_qf <- logTransform ( object = cp_qf, base = 2 , i = "psms_filtered" , name = "log_psms" ) ## Verify cp_qf ## An instance of class QFeatures containing 3 assays: ## [1] psms_raw: SummarizedExperiment with 48832 rows and 6 columns ## [2] psms_filtered: SummarizedExperiment with 21631 rows and 6 columns ## [3] log_psms: SummarizedExperiment with 21631 rows and 6 columns Aggregation of PSMs to proteins For the aggregation itself we use the aggregateFeatures function and provide the base level from which we wish to aggregate, the log PSM-level data in this case. We also tell the function which column to aggregate which is specified by the fcol argument. We will first aggregate from PSM to peptide to create explicit QFeatures links. This means grouping PSMs by “Sequence”. As well as grouping PSMs according to their peptide sequence, the quantitative values for each PSM must be aggregated into a single peptide-level value. The default aggregation method within aggregateFeatures is the robustSummary function from the MsCoreUtils package. 19 This method is a form of robust regression and is described in detail elsewhere. 24 Nevertheless, the user must decide which aggregation method is most appropriate for their data and biological question. Further, an understanding of the selected method is critical given that aggregation is a form of implicit imputation and has substantial effects on the downstream data. Indeed, aggregation methods have different ways of dealing with missing data, either by removal or propagation. Options of aggregation methods within the aggregateFeatures function include MsCoreUtils::medianPolish , MsCoreUtils::robustSummary , base::colMeans , base::colSums , and matrixStats::colMedians . Users should also be aware that some methods have specific input requirements. For example, robustSummary assumes that intensities have already been log transformed. Aggregating using robust summarization Here, we use robustSummary to aggregate from PSM to peptide-level. This method is currently considered to be state-of-the-art as it is more robust against outliers than other aggregation methods. 24 , 25 We also include na.rm = TRUE to exclude any NA values prior to completing the summarization. For simplicity, we here aggregate all PSMs corresponding to the same stripped peptide sequence, regardless of whether they contain different modifications. If users are interested in exploring differential expression of protein isoforms or have reason to believe that post-translational modifications may be important in answering their question, PSMs could also be aggregated by "Annotated.Sequence" to preserve this information. ## Aggregate PSM to peptide cp_qf <- aggregateFeatures (cp_qf, i = "log_psms" , fcol = "Sequence" , name = "log_peptides" , fun = MsCoreUtils :: robustSummary, na.rm = TRUE ) ## Your quantitative and row data contain missing values. Please read the ## relevant section(s) in the aggregateFeatures manual page regarding the ## effects of missing values on data aggregation. ## Verify cp_qf ## An instance of class QFeatures containing 4 assays: ## [1] psms_raw: SummarizedExperiment with 48832 rows and 6 columns ## [2] psms_filtered: SummarizedExperiment with 21631 rows and 6 columns ## [3] log_psms: SummarizedExperiment with 21631 rows and 6 columns ## [4] log_peptides: SummarizedExperiment with 14183 rows and 6 columns We are now left with a QFeatures object holding the PSM and peptide-level data in their own SummarizedExperiment s. Importantly, an explicit link has been maintained between the two levels and this makes it possible to gain information about all PSMs that were aggregated into a peptide. Considerations for aggregating non-imputed data If users did not impute prior to aggregation, NA values within the PSM-level data may have propagated into NaN values. This is because peptides only supported by PSMs containing missing values would not have any quantitative value to which a sum or median function, for example, can be applied. Therefore, we check for NaN and convert back to NA values to facilitate compatibility with downstream processing. ## Confirm the presence of NaN assay (cp_qf[[ "log_peptides" ]]) %>% is.nan () %>% table () ## . ## FALSE ## 85098 ## Replace NaN with NA assay (cp_qf[[ "log_peptides" ]])[ is.nan ( assay (cp_qf[[ "log_peptides" ]]))] <- NA Next, using the same approach as above, we use the aggregateFeatures function to assemble the peptides into proteins. As before, we must pass several arguments to the function. Namely, the QFeatures object i.e. cp_qf , the data level we wish to aggregation from i.e. log_peptides , the column of the rowData defining how to aggregate the features i.e. by "Master.Protein.Accessions" and a name for the new data level e.g. "log_proteins" . We again choose to use robustSummary as our aggregation method and we pass na.rm = TRUE to ignore NA values. Users can type ?aggregateFeatures to see more information. Users should be aware that peptides are grouped by their master protein accession and, therefore, downstream differential expression analysis will consider protein groups rather than individual proteins. ## Aggregate peptides to protein cp_qf <- aggregateFeatures (cp_qf, i = "log_peptides" , fcol = "Master.Protein.Accessions" , name = "log_proteins" , fun = MsCoreUtils :: robustSummary, na.rm = TRUE ) ## Your quantitative and row data contain missing values. Please read the ## relevant section(s) in the aggregateFeatures manual page regarding the ## effects of missing values on data aggregation. ## Verify cp_qf ## An instance of class QFeatures containing 5 assays: ## [1] psms_raw: SummarizedExperiment with 48832 rows and 6 columns ## [2] psms_filtered: SummarizedExperiment with 21631 rows and 6 columns ## [3] log_psms: SummarizedExperiment with 21631 rows and 6 columns ## [4] log_peptides: SummarizedExperiment with 14183 rows and 6 columns ## [5] log_proteins: SummarizedExperiment with 3230 rows and 6 columns Following aggregation, we have a total of 3230 proteins remaining within the data. Normalisation of quantitative data After transforming the data, we normalise the protein-level abundances. Normalisation is a process of correction whereby quantitative data is returned to its original, or ‘normal’, state. In expression proteomics, the aim of post-acquisition data normalisation is to minimise the biases that arises due to experimental error and technological variation. Specifically, the removal of random variation and batch effects will allow samples to be aligned prior to downstream analysis. Importantly, however, users must also be aware of any normalisation that has taken place within their sample preparation, as this will ultimately influence the presence of differentially abundant proteins downstream. An extensive review on normalisation strategies, both experimental and computational, is provided in. 26 Unfortunately, there is not currently a single normalisation method which performs best for all quantitative proteomics datasets. That said, the median (or median-based methods) are a good choice for most quantitative proteomics data. By contrast, mean normalisation is a method to be avoided since the mean is very sensitive to outliers and we often have such outliers in proteomics data. Similarly, quantile normalisation is not recommended for quantitative proteomics data due to complications imposed by the presence of missing values. For users wishing to explore and compare normalisation methods, the NormalyzerDE package within Bioconductor can be used. 27 Here, we will demonstrate the use of a center median normalisation approach using the normalize function within QFeatures . To do this, we pass the log transformed protein-level data to the normalize function in QFeatures . We specify the method of normalisation that we wish to apply i.e. method = "center.median" and name the new data level e.g., name = "log_norm_proteins" . Of note, for users who wish to apply VSN normalisation the raw protein data must be passed (prior to any log transformation) as the log transformation is done internally when specify method = "vsn" . All other methods require users to explicitly perform log transformation on their data before use. More details can be found in the QFeatures documentation, please type help("normalize,QFeatures-method") . ## normalise the log transformed peptide data cp_qf <- normalize (cp_qf, i = "log_proteins" , name = "log_norm_proteins" , method = "center.median" ) ## Verify cp_qf ## An instance of class QFeatures containing 6 assays: ## [1] psms_raw: SummarizedExperiment with 48832 rows and 6 columns ## [2] psms_filtered: SummarizedExperiment with 21631 rows and 6 columns ## [3] log_psms: SummarizedExperiment with 21631 rows and 6 columns ## [4] log_peptides: SummarizedExperiment with 14183 rows and 6 columns ## [5] log_proteins: SummarizedExperiment with 3230 rows and 6 columns ## [6] log_norm_proteins: SummarizedExperiment with 3230 rows and 6 columns To evaluate the effect of normalisation we plot a simple boxplot. ## Evaluate the effect of data normalisation pre_norm % assay () %>% longFormat () %>% mutate ( Condition = ifelse (colname %in% c ( "S1" , "S2" , "S3" ), "Treated" , "Control" ), colname = factor (colname, levels = paste0 ( "S" , 1 : 6 ))) %>% ggplot ( aes ( x = colname, y = value, fill = Condition)) + geom_boxplot () + labs ( x = "Sample" , y = "log2(abundance)" , title = "Pre-normalisation" ) + theme_bw () post_norm % assay () %>% longFormat () %>% mutate ( Condition = ifelse (colname %in% c ( "S1" , "S2" , "S3" ), "Treated" , "Control" ), colname = factor (colname, levels = paste0 ( "S" , 1 : 6 ))) %>% ggplot ( aes ( x = colname, y = value, fill = Condition)) + geom_boxplot () + labs ( x = "Sample" , y = "log2(abundance)" , title = "Post-normalisation" ) + theme_bw () pre_norm + theme ( legend.position = "none" ) + post_norm We can now generate a density plot to help us visualise what the process of log transformation and normalisation has done to the data. This is done using the plotDensities function from the limma package. ## visualise the process of log transformation and normalisation par ( mfrow = c ( 1 , 3 )) cp_qf[[ "psms_filtered" ]] %>% assay () %>% plotDensities ( legend = "topright" , main = "Raw PSMs" ) cp_qf[[ "log_psms" ]] %>% assay () %>% plotDensities ( legend = FALSE , main = "log2(PSMs)" ) cp_qf[[ "log_norm_proteins" ]] %>% assay () %>% plotDensities ( legend = FALSE , main = "log2(norm proteins)" ) Density plots are a useful visualization tool as we are able to quickly compare the data across samples by plotting the distribution of each sample together. When doing this we get an idea of where the majority of the intensities lie. If, for example, all samples come from the same cells and our treatment/conditions don’t cause massive changes to the proteome, we expect the distributions of the intensitie s to be roughly the same. Above, we see that the raw data before normalisation (left), log2 transformed (middle) and post-normalisation (right). In the first two plots the curves/peaks are at different locations but after normalisation (right) we see that we have shifted the curves according to their median and all peaks of samples are now overlapping. Exploration of data using QFeatures links Creating assay links After completing all data pre-processing, we now add explicit links between our final protein-level data and the raw PSM-level data which we created as an untouched copy. This allows us to investigate all data corresponding to the final proteins, including the data that has since been removed. To do this, we use the addAssayLinks function, demonstrated below. We can check that the assay links have been generated correctly by passing our QFeatures object to the AssayLink function along with the assay of interest (i =) . ## Add assay links from log_norm_proteins to psms_raw cp_qf <- addAssayLink ( object = cp_qf, from = "psms_raw" , to = "log_norm_proteins" , varFrom = "Master.Protein.Accessions" , varTo = "Master.Protein.Accessions" ) ## Verify assayLink (cp_qf, i = "log_norm_proteins" ) ## AssayLink for assay ## [from:psms_raw|fcol:Master.Protein.Accessions|hits:42604] Visualising aggregation One of the characteristic attributes of the QFeatures infrastructure is that explicit links have been maintained throughout the aggregation process. This means that we can now access all data corresponding to a protein, its component peptides and PSMs. One way to do this is through the use of the subsetByFeature function which will return a new QFeatures object containing data for the desired feature across all levels. For example, if we wish to subset information about the protein “Q01581”, that is hydroxymethylglutaryl-CoA synthase, we could use the following code: ## Subset all data linked to the protein with accession Q01581 Q01581 <- subsetByFeature (cp_qf, "Q01581" ) ## Verify Q01581 ## An instance of class QFeatures containing 6 assays: ## [1] psms_raw: SummarizedExperiment with 42 rows and 6 columns ## [2] psms_filtered: SummarizedExperiment with 27 rows and 6 columns ## [3] log_psms: SummarizedExperiment with 27 rows and 6 columns ## [4] log_peptides: SummarizedExperiment with 15 rows and 6 columns ## [5] log_proteins: SummarizedExperiment with 1 rows and 6 columns ## [6] log_norm_proteins: SummarizedExperiment with 1 rows and 6 columns We find that in this data the protein Q01581 has 15 peptides and 27 PSMs supporting its identification and quantitation. We also see that the original data prior to processing contained 42 PSMs in support of this protein. Further, we can visualise the process of aggregation that has led to the protein-level abundance data for Q01581, as demonstrated below. Of note, this plot shows the protein data prior to normalisation. ## Define conditions treament <- c ( "S1" , "S2" , "S3" ) control % longFormat () %>% as_tibble () %>% mutate ( assay_order = factor ( assay, levels = c ( "log_psms" , "log_peptides" , "log_proteins" ), labels = c ( "PSMs" , "Peptides" , "Protein" )), condition = ifelse (colname %in% control, "control" , "treatment" )) %>% ggplot ( aes ( x = colname, y = value, colour = assay)) + geom_point ( size = 3 ) + geom_line ( aes ( group = rowname)) + scale_x_discrete ( limits = paste0 ( "S" , 1 : 6 )) + facet_wrap ( ~ assay_order) + labs ( x = "Sample" , y = "Abundance" ) + ggtitle ( "log2 Q01581 abundance profiles" ) + theme_bw () Determining PSM and peptide support Another benefit of the explicit links maintained within a QFeatures object is the ease at which we can determine PSM and peptide support per protein. When applying the aggregateFeatures function a column, termed ".n" , is created within the rowData of the new SummarizedExperiment . This column indicates how many lower-level features were aggregated into each new higher-level feature. Hence, ".n" in the peptide-level data represents how many PSMs were aggregated into a peptide, whilst in the protein-level data it tells us how many peptides were grouped into a master protein. As an example, we plot the a histogram of ".n" from the protein-level to explore peptide support per protein. ## Plot peptide support per protein - .n in the proteins SE cp_qf[[ "log_proteins" ]] %>% rowData () %>% as_tibble () %>% ggplot ( aes ( x = .n)) + geom_histogram ( binwidth = 1 , boundary = 0.5 ) + labs ( x = "Peptide support (shown up to 20)" , y = "Frequency" ) + scale_x_continuous ( expand = c ( 0 , 0 ), limits = c ( 0 , 20.5 ), breaks = seq ( 1 , 20 , 1 )) + scale_y_continuous ( expand = c ( 0 , 0 ), limits = c ( 0 , 1100 ), breaks = seq ( 0 , 1100 , 100 )) + ggtitle ( "Peptide support per protein" ) + theme_bw () At this point, users may wish to include additional quality control filtering based on PSM and/or peptide support per protein. Given the extensive quality control filtering already applied in this workflow, we decide not to remove additional proteins based on PSM or peptide support. Data export Finally, we save the protein-level data and export the QFeatures object into an .rda file so that we can re-load it later at convenience. ## Save protein-level SE cp_proteins <- cp_qf[[ "log_norm_proteins" ]] ## Export the final TMT QFeatures object save (cp_qf, file = "cp_qf.rda" ) Label-free data processing workflow Having discussed the processing of quantitative TMT-labelled data, we now move on to consider that of label-free quantitative (LFQ) data. As described previously, the cell culture supernatant fractions of triplicate control and treated HEK293 cells were kept label-free. As such, each sample was analyzed using an independent mass spectrometry run without pre-fractionation. Again, a two-hour gradient in an Orbitrap Lumos Tribrid mass spectrometer coupled to an UltiMate 3000 HPLC system was applied. Given that much of the TMT pre-processing workflow also applies to label-free data, we only discuss steps which are different to those previously described. Readers are advised to refer to the TMT processing workflow for a more in-depth explanation of any shared steps. Identification search using Proteome Discoverer As was the case for TMT labelled cell pellets, raw LFQ data from supernatant samples was searched using Proteome Discoverer 2.5. The workflows for this identification search are provided in the supplementary materials with an additional explanation of key parameters in the appendix 10 along with details about how to use this workflow with MaxQuant data. To begin processing LFQ data, users should export a peptide-level .txt file from the results of their identification search. Data import, housekeeping and exploration Unlike the TMT-labelled use-case data which was processed from the PSM-level, the label-free use-case data can only be considered from the peptide-level up. This is because a retention time alignment algorithm (equivalent to match between runs) was applied to the ion-level data. This means that peptides can be identified in samples even without a corresponding PSM, simply by sharing feature information across runs. When using Proteome Discoverer, the information gained by retention time alignment is only integrated in the output files for peptide-level and above. That said, other third party software may integrate this data into the lower-level data files, such as the evidence.txt file generated by MaxQuant. Importing data into a QFeatures object We locate the PeptideGroups .txt file and import this into a data.frame container in the same way as before. ## Locate the PeptideGroups .txt file sn_peptide <- "supernatant_lfq_results_peptides.txt" ## Import into a data.frame sn_df % names () ## [1] "Peptide.Groups.Peptide.Group.ID" ## [2] "Checked" ## [3] "Tags" ## [4] "Confidence" ## [5] "PSM.Ambiguity" ## [6] "Sequence" ## [7] "Modifications" ## [8] "Modifications.all.possible.sites" ## [9] "Qvality.PEP" ## [10] "Qvality.q.value" ## [11] "SVM_Score" ## [12] "Number.of.Protein.Groups" ## [13] "Number.of.Proteins" ## [14] "Number.of.PSMs" ## [15] "Master.Protein.Accessions" ## [16] "Master.Protein.Descriptions" ## [17] "Protein.Accessions" ## [18] "Number.of.Missed.Cleavages" ## [19] "Theo.MHplus.in.Da" ## [20] "Sequence.Length" ## [21] "Abundance.F1.Sample" ## [22] "Abundance.F2.Sample" ## [23] "Abundance.F3.Sample" ## [24] "Abundance.F4.Sample" ## [25] "Abundance.F5.Sample" ## [26] "Abundance.F6.Sample" ## [27] "Abundances.Count.F1.Sample" ## [28] "Abundances.Count.F2.Sample" ## [29] "Abundances.Count.F3.Sample" ## [30] "Abundances.Count.F4.Sample" ## [31] "Abundances.Count.F5.Sample" ## [32] "Abundances.Count.F6.Sample" ## [33] "Quan.Info" ## [34] "Found.in.File.in.F1" ## [35] "Found.in.File.in.F2" ## [36] "Found.in.File.in.F3" ## [37] "Found.in.File.in.F4" ## [38] "Found.in.File.in.F5" ## [39] "Found.in.File.in.F6" ## [40] "Found.in.Sample.in.S1.F1.Sample" ## [41] "Found.in.Sample.in.S2.F2.Sample" ## [42] "Found.in.Sample.in.S3.F3.Sample" ## [43] "Found.in.Sample.in.S4.F4.Sample" ## [44] "Found.in.Sample.in.S5.F5.Sample" ## [45] "Found.in.Sample.in.S6.F6.Sample" ## [46] "Found.in.Sample.Group.in.S1.F1.Sample" ## [47] "Found.in.Sample.Group.in.S2.F2.Sample" ## [48] "Found.in.Sample.Group.in.S3.F3.Sample" ## [49] "Found.in.Sample.Group.in.S4.F4.Sample" ## [50] "Found.in.Sample.Group.in.S5.F5.Sample" ## [51] "Found.in.Sample.Group.in.S6.F6.Sample" ## [52] "Confidence.by.Search.Engine.Sequest.HT" ## [53] "Charge.by.Search.Engine.Sequest.HT" ## [54] "Delta.Score.by.Search.Engine.Sequest.HT" ## [55] "Delta.Cn.by.Search.Engine.Sequest.HT" ## [56] "Rank.by.Search.Engine.Sequest.HT" ## [57] "Search.Engine.Rank.by.Search.Engine.Sequest.HT" ## [58] "Concatenated.Rank.by.Search.Engine.Sequest.HT" ## [59] "mz.in.Da.by.Search.Engine.Sequest.HT" ## [60] "Delta.M.in.ppm.by.Search.Engine.Sequest.HT" ## [61] "Delta.mz.in.Da.by.Search.Engine.Sequest.HT" ## [62] "RT.in.min.by.Search.Engine.Sequest.HT" ## [63] "Percolator.q.Value.by.Search.Engine.Sequest.HT" ## [64] "Percolator.PEP.by.Search.Engine.Sequest.HT" ## [65] "Percolator.SVMScore.by.Search.Engine.Sequest.HT" ## [66] "XCorr.by.Search.Engine.Sequest.HT" ## [67] "Top.Apex.RT.in.min" In the code chunk below, we again use the readQFeatures function to create a QFeatures object. We find the abundance data is located in columns 21 to 26 and thus pass this to quantCols . After import we annotate the colData . ## Create QFeatures object sn_qf <- readQFeatures ( assayData = sn_df, quantCols = 21 : 26 , name = "peptides_raw" ) ## Checking arguments. ## Loading data as a 'SummarizedExperiment' object. ## Formatting sample annotations (colData). ## Formatting data as a 'QFeatures' object. ## Clean sample names colnames (sn_qf[[ "peptides_raw" ]]) <- paste0 ( "S" , 1 : 6 ) ## Annotate samples sn_qf $ sample <- paste0 ( "S" , 1 : 6 ) sn_qf $ condition <- rep ( c ( "Treated" , "Control" ), each = 3 ) ## Verify and allocate colData to initial SummarizedExperiment colData (sn_qf) ## DataFrame with 6 rows and 2 columns ## sample condition ## ## S1 S1 Treated ## S2 S2 Treated ## S3 S3 Treated ## S4 S4 Control ## S5 S5 Control ## S6 S6 Control colData (sn_qf[[ "peptides_raw" ]]) <- colData (sn_qf) Preliminary data exploration Next, we check the names of the features within the peptide-level rowData . These features differ from those found at the PSM-level and users should be aware that they have reduced post-search control over the quality of PSMs included in the peptide quantitation, and which method of aggregation is used to define these. Proteome Discoverer uses the sum of PSM quantitative values to calculate peptide-level values. Other third-party software may use different methods. ## Find out what information was imported sn_qf[[ "peptides_raw" ]] %>% rowData () %>% colnames () ## [1] "Peptide.Groups.Peptide.Group.ID" ## [2] "Checked" ## [3] "Tags" ## [4] "Confidence" ## [5] "PSM.Ambiguity" ## [6] "Sequence" ## [7] "Modifications" ## [8] "Modifications.all.possible.sites" ## [9] "Qvality.PEP" ## [10] "Qvality.q.value" ## [11] "SVM_Score" ## [12] "Number.of.Protein.Groups" ## [13] "Number.of.Proteins" ## [14] "Number.of.PSMs" ## [15] "Master.Protein.Accessions" ## [16] "Master.Protein.Descriptions" ## [17] "Protein.Accessions" ## [18] "Number.of.Missed.Cleavages" ## [19] "Theo.MHplus.in.Da" ## [20] "Sequence.Length" ## [21] "Abundances.Count.F1.Sample" ## [22] "Abundances.Count.F2.Sample" ## [23] "Abundances.Count.F3.Sample" ## [24] "Abundances.Count.F4.Sample" ## [25] "Abundances.Count.F5.Sample" ## [26] "Abundances.Count.F6.Sample" ## [27] "Quan.Info" ## [28] "Found.in.File.in.F1" ## [29] "Found.in.File.in.F2" ## [30] "Found.in.File.in.F3" ## [31] "Found.in.File.in.F4" ## [32] "Found.in.File.in.F5" ## [33] "Found.in.File.in.F6" ## [34] "Found.in.Sample.in.S1.F1.Sample" ## [35] "Found.in.Sample.in.S2.F2.Sample" ## [36] "Found.in.Sample.in.S3.F3.Sample" ## [37] "Found.in.Sample.in.S4.F4.Sample" ## [38] "Found.in.Sample.in.S5.F5.Sample" ## [39] "Found.in.Sample.in.S6.F6.Sample" ## [40] "Found.in.Sample.Group.in.S1.F1.Sample" ## [41] "Found.in.Sample.Group.in.S2.F2.Sample" ## [42] "Found.in.Sample.Group.in.S3.F3.Sample" ## [43] "Found.in.Sample.Group.in.S4.F4.Sample" ## [44] "Found.in.Sample.Group.in.S5.F5.Sample" ## [45] "Found.in.Sample.Group.in.S6.F6.Sample" ## [46] "Confidence.by.Search.Engine.Sequest.HT" ## [47] "Charge.by.Search.Engine.Sequest.HT" ## [48] "Delta.Score.by.Search.Engine.Sequest.HT" ## [49] "Delta.Cn.by.Search.Engine.Sequest.HT" ## [50] "Rank.by.Search.Engine.Sequest.HT" ## [51] "Search.Engine.Rank.by.Search.Engine.Sequest.HT" ## [52] "Concatenated.Rank.by.Search.Engine.Sequest.HT" ## [53] "mz.in.Da.by.Search.Engine.Sequest.HT" ## [54] "Delta.M.in.ppm.by.Search.Engine.Sequest.HT" ## [55] "Delta.mz.in.Da.by.Search.Engine.Sequest.HT" ## [56] "RT.in.min.by.Search.Engine.Sequest.HT" ## [57] "Percolator.q.Value.by.Search.Engine.Sequest.HT" ## [58] "Percolator.PEP.by.Search.Engine.Sequest.HT" ## [59] "Percolator.SVMScore.by.Search.Engine.Sequest.HT" ## [60] "XCorr.by.Search.Engine.Sequest.HT" ## [61] "Top.Apex.RT.in.min" We also determine the number of PSMs, peptides and protein groups represented within the initial data. Since identical peptide sequences with different modifications are stored as separate entities, the output of dim will not tell us the number of peptides. Instead, we need to consider only unique peptide sequence entries, as demonstrated in the code chunk below. ## Determine the number of PSMs original_psms % rowData () %>% as_tibble () %>% pull (Number.of.PSMs) %>% sum () ## Determine the number of peptides original_peps % rowData () %>% as_tibble () %>% pull (Sequence) %>% unique () %>% length () %>% as.numeric () ## Determine the number of proteins original_prots % rowData () %>% as_tibble () %>% pull (Master.Protein.Accessions) %>% unique () %>% length () %>% as.numeric () ## View original_psms ## [1] 144302 original_peps ## [1] 20312 original_prots ## [1] 3941 Thus, the search identified 144302 PSMs corresponding to 20312 peptides and 3941 master proteins or protein groups. Finally, we take a look at some of the key parameters applied during the identification search. This is an important verification step, particularly for those using publicly available data with limited access to parameter settings. ## Check missed cleavages sn_qf[[ "peptides_raw" ]] %>% rowData () %>% as_tibble () %>% pull (Number.of.Missed.Cleavages) %>% table () ## . ## 0 1 2 ## 22055 1248 72 ## Check precursor mass tolerance sn_qf[[ "peptides_raw" ]] %>% rowData () %>% as_tibble () %>% pull (Delta.M.in.ppm.by.Search.Engine.Sequest.HT) %>% summary () ## Min. 1st Qu. Median Mean 3rd Qu. Max. ## -9.9600 -0.2500 0.1500 0.6576 0.6900 9.9900 ## Check fragment mass tolerance sn_qf[[ "peptides_raw" ]] %>% rowData () %>% as_tibble () %>% pull (Delta.mz.in.Da.by.Search.Engine.Sequest.HT) %>% summary () ## Min. 1st Qu. Median Mean 3rd Qu. Max. ## -0.0113400 -0.0001400 0.0000900 0.0006618 0.0004800 0.0142300 ## Check peptide confidence allocations sn_qf[[ "peptides_raw" ]] %>% rowData() %>% as_tibble() %>% pull(Confidence) %>% table() ## . ## High ## 23375 The preliminary data is as expected so we continue on to evaluate the quality of the raw data. Experimental quality control checks Quality control of the raw mass spectrometry data To briefly assess the quality of the raw mass spectrometry data from which the search results were derived, we create simple plots. In contrast to the previous PSM processing workflow, we do not have access to information about ion injection times from the peptide-level file. However, we can still look at the peptide delta mass across retention time, as well as the frequency of peptides across the retention time gradient. ## Plot scatter plot of mass accuracy sn_qf[[ "peptides_raw" ]] %>% rowData () %>% as_tibble () %>% ggplot ( aes ( x = RT.in.min.by.Search.Engine.Sequest.HT, y = Delta.M.in.ppm.by.Search.Engine.Sequest.HT)) + geom_point ( size = 0.5 , shape = 4 ) + geom_hline ( yintercept = 5 , linetype = "dashed" , color = "red" ) + geom_hline ( yintercept = - 5 , linetype = "dashed" , color = "red" ) + labs ( x = "RT (min)" , y = "Delta precursor mass (ppm)" ) + scale_x_continuous ( limits = c ( 0 , 120 ), breaks = seq ( 0 , 120 , 20 )) + scale_y_continuous ( limits = c ( - 10 , 10 ), breaks = c ( - 10 , - 5 , 0 , 5 , 10 )) + ggtitle ( "Peptide retention time against delta precursor mass" ) + theme_bw () ## Plot histogram of peptide retention time sn_qf[[ "peptides_raw" ]] %>% rowData () %>% as_tibble () %>% ggplot ( aes ( x = RT.in.min.by.Search.Engine.Sequest.HT)) + geom_histogram ( binwidth = 1 ) + labs ( x = "RT (min)" , y = "Frequency" ) + scale_x_continuous ( breaks = seq ( 0 , 120 , 20 )) + ggtitle ( "Peptide frequency across retention time" ) + theme_bw () For a more in-depth discussion of these plots users should refer back to the TMT processing workflow. Since neither plot indicates any major problems with the MS runs, we continue on to basic data cleaning. Basic data cleaning As discussed in detail above, there are several basic data cleaning steps which are non-specific and should be applied to all quantitative datasets, regardless of the quantitation method or data level (PSM, peptide or protein). These steps are as follows: 1. Removal of features without a master protein accession 2. Removal of features corresponding to protein groups which contain a contaminant 3. Removal of features without quantitative data 4. (Optional) Removal of features which are not unique to a protein group 5. Removal of features not allocated rank 1 during the identification search 6. Removal of features not annotated as unambiguous 7. Control of FDR to 1% protein-level FDR (or 5% for more exploratory analyses) In addition to these standard steps, LFQ data should be filtered to remove peptides that were not quantified based on a monoisotopic peak. The monoisotopic peak is that which comprises the most abundant natural isotope of each constituent element. For bottom-up proteomics, this typically translates to the peptides containing carbon-12 and nitrogen-14. When the different isotopes are well resolved, the monoisotopic peak usually provides the most accurate measurement. Before we remove any data, we first create a second copy of the original SummarizedExperiment , as to retain a copy of the raw data for reference. As before we use the addAssay function. ## Add second copy of data to be filtered data_copy <- sn_qf[[ "peptides_raw" ]] sn_qf <- addAssay ( x = sn_qf, y = data_copy, name = "peptides_filtered" ) ## Verify sn_qf ## An instance of class QFeatures containing 2 assays: ## [1] peptides_raw: SummarizedExperiment with 23375 rows and 6 columns ## [2] peptides_filtered: SummarizedExperiment with 23375 rows and 6 columns Here, cleaning is done in two steps. The first is the removal of contaminant proteins using the self-defined find_cont function. Refer back to the TMT processing workflow for more details. ## Store row indices of peptides matched to a contaminant-containing protein group cont_peptides 0 ) sn_qf[[ "peptides_filtered" ]] <- sn_qf[[ "peptides_filtered" ]][ - cont_peptides, ] Second, we carry out all remaining cleaning using the filterFeatures function as before. sn_qf % filterFeatures ( ~ ! Master.Protein.Accessions == "" , i = "peptides_filtered" ) %>% filterFeatures ( ~ ! Quan.Info == "NoQuanValues" , i = "peptides_filtered" ) %>% filterFeatures ( ~ ! Quan.Info == "NoneMonoisotopic" , i = "peptides_filtered" ) %>% filterFeatures ( ~ Number.of.Protein.Groups == 1 , i = "peptides_filtered" ) %>% filterFeatures ( ~ Rank.by.Search.Engine.Sequest.HT == 1 , i = "peptides_filtered" ) %>% filterFeatures ( ~ PSM.Ambiguity == "Unambiguous" , i = "peptides_filtered" ) As before, we check to see whether additional annotations remain within the “Quan.Info” column. ## Check for remaining annotations sn_qf[[ "peptides_filtered" ]] %>% rowData %>% as_tibble () %>% pull (Quan.Info) %>% table () ## . ## ## 17999 Again, we need to import the protein-level data in order to complete FDR filtering at the highest possible level. See above for more details. protein_sn <- read.delim ( file = "supernatant_lfq_results_proteins.txt" ) ## Extract master protein accessions from our PSM-level data proteins_in_data % rowData () %>% as_tibble () %>% select (Master.Protein.Accessions) ## Extract protein accessions and corresponding confidence from search output file protein_search_output % select (Accession, Protein.FDR.Confidence.Combined) ## Combine data protein_fdr <- left_join ( x = proteins_in_data, y = protein_search_output, by = c ( "Master.Protein.Accessions" = "Accession" )) rowData (sn_qf[[ "peptides_filtered" ]]) $ Protein.Confidence <- protein_fdr $ Protein.FDR.Confidence.Combined We can now use filterFeatures to remove peptides corresponding to low or medium confidence master proteins. sn_qf % filterFeatures( ~ Protein.Confidence == "High" , i = "peptides_filtered" ) Assessing the impact of non-specific data cleaning As in the previous example, we assess the impact that cleaning has had on the data. Specifically, we determine the number and proportion of PSMs, peptides and protein groups lost. Again, when we refer to the number of peptides we only consider unique peptide sequences, not those that differ in their modifications. ## Determine number of PSMs, peptides and proteins remaining psms_remaining % rowData () %>% as_tibble () %>% pull (Number.of.PSMs) %>% sum () peps_remaining % rowData () %>% as_tibble () %>% pull (Sequence) %>% unique () %>% length () %>% as.numeric () prots_remaining % rowData () %>% as_tibble () %>% pull (Master.Protein.Accessions) %>% unique () %>% length() %>% as.numeric() ## Determine the number of proportion of PSMs, peptides and proteins removed psms_removed <- original_psms - psms_remaining psms_removed_prop % round ( digits = 2 ) peps_removed <- original_peps - peps_remaining peps_removed_prop % round ( digits = 2 ) prots_removed <- original_prots - prots_remaining prots_removed_prop % round ( digits = 2 ) ## Present in a table data.frame ( "Feature" = c ( "PSMs" , "Peptides (stripped)" , "Protein groups" ), "Number lost" = c (psms_removed, peps_removed, prots_removed), "Percentage lost" = c(psms_removed_prop, peps_removed_prop, prots_removed_prop), "Number remaining" = c (psms_remaining, peps_remaining, prots_remaining)) ## Feature Number.lost Percentage.lost Number.remaining ## 1 PSMs 28367 19.66 115935 ## 2 Peptides (stripped) 3876 19.08 16436 ## 3 Protein groups 799 20.27 3142 Peptide quality control filtering When extracting data from the peptide-level .txt file rather than aggregating up from a PSM file, additional parameters exist within the peptide rowData . Such parameters include Quality PEP, Quality q-value, and SVM score, as well as similar scoring parameters provided by the search engine. Although we will not complete additional filtering based on these parameters in this workflow, users may wish to explore this option. Managing missing data Having cleaned the peptide-level data we now move onto the management of missing data. This is of particular importance for LFQ workflows where the missing value challenge is amplified by intrinsic variability between independent MS runs. As before, the management of missing data can be divided into three steps: 1) exploring the presence and distribution of missing values, (2) filtering out missing values, and (3) optional imputation. Exploring the presence of missing values The aim of the first step is to determine how many missing values are present within the data, and how they are distributed between samples and/or conditions. ## Are there any NA values within the peptide data? sn_qf[[ "peptides_filtered" ]] %>% assay () %>% anyNA () ## [1] TRUE ## How many NA values are there within the peptide data? sn_qf[[ "peptides_filtered" ]] %>% nNA () ## $nNA ## DataFrame with 1 row and 2 columns ## nNA pNA ## ## 1 15742 0.146655 ## ## $nNArows ## DataFrame with 17890 rows and 3 columns ## name nNA pNA ## ## 1 1 4 0.666667 ## 2 2 1 0.166667 ## 3 3 0 0.000000 ## 4 4 1 0.166667 ## 5 5 0 0.000000 ## … … … … ## 17886 23371 0 0 ## 17887 23372 0 0 ## 17888 23373 0 0 ## 17889 23374 0 0 ## 17890 23375 0 0 ## ## $nNAcols ## DataFrame with 6 rows and 3 columns ## name nNA pNA ## ## 1 S1 3674 0.205366 ## 2 S2 1936 0.108217 ## 3 S3 2030 0.113471 ## 4 S4 3648 0.203913 ## 5 S5 2650 0.148127 ## 6 S6 1804 0.100838 As expected, the LFQ data contains a higher proportion of missing values as compared to the TMT-labelled data. There are 15742 missing (NA) values within the data, which corresponds to 0.15 of the data. We check for sample- and condition-specific biases in the distribution of these NA values, again plotting percentage (proportion multiplied by 100). ## Plot histogram to visualise sample-specific distribution of NAs nNA (sn_qf[[ "peptides_filtered" ]]) $ nNAcols %>% as_tibble () %>% mutate ( Condition = rep ( c ( "Treated" , "Control" ), each = 3 )) %>% ggplot ( aes ( x = name, y = (pNA * 100 ), group = Condition, fill = Condition)) + geom_bar ( stat = "identity" ) + labs ( x = "Sample" , y = "Missing values (%)" ) + theme_bw () Whilst S1 and S4 have a slightly higher proportion of missing values, all of the samples are within an acceptable range to continue. Again, there is no evidence of a condition-specific bias in the data. Expectations of missing values All quantitative proteomics datasets will have some missing values. However, the extent and pattern of missing values will depend upon the experimental design. As mentioned above, we expect label-free datasets to have a greater number of missing values relative to label-based quantitation. This is because label-free samples are each analysed by independent MS runs. Since the selection of precursor ions for fragmentation is somewhat stochastic in DDA experiments, different peptides may be identified and quantified across samples, thus leading to a high proportion of missing values. By contrast, one of the advantages of using a TMT labelling strategy is the ability to multiplex samples into a single MS run. As a result, the same peptides are identified and quantified across samples and the number of missing values is decreased. Being aware of what we expect from our experimental design not only allows us to identify where things may have gone wrong (e.g., abnormally high missing values), it also gives us some indication of why our missing values are there. For example, TMT datasets typically contain a low proportion of missing values and most of these are due to reporter ion signals being below the limit of detection. This means that most TMT missing values are MNAR. LFQ datasets, on the other hand, contain a larger proportion of missing values which typically represent a mixture of MNAR and MCAR values. These differences can be used to identify the most appropriate imputation method, should imputation be necessary (see below). Filtering out missing values We next filter out features, here peptides, which comprise 20% or more missing values. ## Check how many peptides we will remove which ( nNA (sn_qf[[ "peptides_filtered" ]]) $ nNArows $ pNA >= 0.2 ) %>% length () ## [1] 4332 ## Remove peptides with 2 or more NA values sn_qf % filterNA ( pNA = 0.2 , i = "peptides_filtered" ) Imputation (optional) Finally, we check how many missing values remain in the data before making a decision as to whether imputation is required. nNA (sn_qf[[ "peptides_filtered" ]]) $ nNA ## DataFrame with 1 row and 2 columns ## nNA pNA ## ## 1 2430 0.0298717 There are 2430 missing values remaining. The presence of proteins with single or low peptide support means that some of these NA values will likely be propagated upward during aggregation. Whilst NA values were traditionally problematic during the application of downstream statistical methods, there are now a number of algorithms that allow statistics to be completed on data containing missing values. For example, the MSqRob2 24 , 25 , 28 package facilitates statistical differential expression analysis on datasets without the need for imputation and functions within the QFeatures infrastructure. Nevertheless, for the purpose of demonstration, we here impute the raw intensity data. As eluded to above, the most appropriate method to determine such probable values is dependent upon why the value is missing, that is whether it is MCAR or MNAR. Although the optimal imputation method is specific to each dataset, left-censored methods (e.g. minimal value approaches, limit of detection) have proven favorable for data with a high proportion of MNAR values whilst hot deck methods (e.g. k-nearest neighbours, random forest, maximum likelihood methods) are more appropriate when the majority of missing data is MCAR (e.g., Refs. 23 , 29 ). Within the QFeatures infrastructure imputation is carried out by passing the data to the impute function, please see ?impute for more information. To see which imputation methods are supported by this function we use the following code: ## Find out available imputation methods MsCoreUtils :: imputeMethods () ## [1]"bpca" "knn" "QRILC" "MLE" "MLE2" "MinDet" "MinProb" ## [8]"min" "zero" "mixed" "nbavg" "with" "RF" "none" Unfortunately, it is very challenging to determine the reason(s) behind missing data, and in most cases experiments contain a mixture of MCAR and MNAR. For LFQ data where little is know about the cause of missing values it is advisable to use methods optimised for MCAR. Here we will use the baseline k-nearest neighbours (k-NN) imputation on the raw peptide intensities. Of note, users who wish to utilise an alternative imputation method should check whether their selected method has a requirement for normality. If the method requires data to display a normal distribution, users must log2 transform the data prior to imputation. ## Impute missing values using kNN sn_qf <- impute (sn_qf, method = "knn" , i = "peptides_filtered" , name = "peptides_imputed" ) Following imputation we check to ensure that the distribution of the data has not dramatically changed. To do so we create a density plot of the data pre- and post-imputation. ## visualise the impact of imputation par ( mfrow = c ( 1 , 2 )) sn_qf[[ "peptides_filtered" ]] %>% assay () %>% log2 () %>% plotDensities ( main = "Pre-imputation" , legend = FALSE ) sn_qf[[ "peptides_imputed" ]] %>% assay () %>% log2 () %>% plotDensities ( main = "Post-imputation" , legend = "topright" ) From this plot the change in the data appears to be minimal. We can further validate this by comparing the summary statistics of the data pre- and post-imputation. ## Determine the impact of imputation on summary statistics pre_imputation_summary % assay () %>% longFormat () %>% group_by (colname) %>% summarise ( sum_intensity = sum (value, na.rm = TRUE ), max_intensity = max (value, na.rm = TRUE ), median_intensity = median (value, na.rm = TRUE )) post_imputation_summary % assay () %>% longFormat () %>% group_by (colname) %>% summarise ( sum_intensity = sum (value, na.rm = TRUE ), max_intensity = max (value, na.rm = TRUE ), median_intensity = median (value, na.rm = TRUE )) print (pre_imputation_summary) ## # A tibble: 6 x 4 ## colname sum_intensity max_intensity median_intensity ## ## 1 S1 98618011197. 1477162278. 1950392. ## 2 S2 155288272302. 1678988256. 3567233. ## 3 S3 145083815203. 1804842981. 3255696. ## 4 S4 94532147208. 1087946291. 1880489. ## 5 S5 121223290798. 1307181986 2511748. ## 6 S6 143149276808. 1608003894. 3288965. print (post_imputation_summary) ## # A tibble: 6 x 4 ## colname sum_intensity max_intensity median_intensity ## ## 1 S1 99501169413. 1477162278. 1814576. ## 2 S2 155691649219. 1678988256. 3493145. ## 3 S3 145325835653. 1804842981. 3210018. ## 4 S4 95867237989. 1087946291. 1726081. ## 5 S5 121738595609. 1307181986 2446493. ## 6 S6 143619358837. 1608003894. 3216396. Comparison of the two tables reveals minimal change within the data. However, we find that S1 and S4 display greater differences between pre- and post-imputation statistics because of the higher number of missing values which required imputation. Logarithmic transformation of quantitative data In the following code chunk we log2 transform the peptide-level data to generate a near-normal distribution within the quantitative data. This is necessary prior to the use of robustSummary aggregation. ## log2 transform the quantitative data sn_qf <- logTransform ( object = sn_qf, base = 2 , i = "peptides_imputed" , name = "log_peptides" ) ## Verify sn_qf ## An instance of class QFeatures containing 4 assays: ## [1] peptides_raw: SummarizedExperiment with 23375 rows and 6 columns ## [2] peptides_filtered: SummarizedExperiment with 13558 rows and 6 columns ## [3] peptides_imputed: SummarizedExperiment with 13558 rows and 6 columns ## [4] log_peptides: SummarizedExperiment with 13558 rows and 6 columns Aggregation of peptide to protein Now that we are happy with the peptide-level data, we aggregate upward to proteins using the aggregateFeatures function. ## Aggregate peptide to protein sn_qf <- aggregateFeatures(sn_qf, i = "log_peptides" , fcol = "Master.Protein.Accessions" , name = "log_proteins" , fun = MsCoreUtils :: robustSummary, na.rm = TRUE ) ## Your row data contain missing values. Please read the relevant ## section(s) in the aggregateFeatures manual page regarding the effects ## of missing values on data aggregation. ## Verify sn_qf ## An instance of class QFeatures containing 5 assays: ## [1] peptides_raw: SummarizedExperiment with 23375 rows and 6 columns ## [2] peptides_filtered: SummarizedExperiment with 13558 rows and 6 columns ## [3] peptides_imputed: SummarizedExperiment with 13558 rows and 6 columns ## [4] log_peptides: SummarizedExperiment with 13558 rows and 6 columns ## [5] log_proteins: SummarizedExperiment with 2760 rows and 6 columns Normalisation of quantitative data Finally, we complete the data processing by normalising quantitation between samples. This is done using the "center.median" method via the normalize function. ## normalize protein-level quantitation data sn_qf <- normalize(sn_qf, i = "log_proteins" , name = "log_norm_proteins" , method = "center.median" ) ## Verify sn_qf ## An instance of class QFeatures containing 6 assays: ## [1] peptides_raw: SummarizedExperiment with 23375 rows and 6 columns ## [2] peptides_filtered: SummarizedExperiment with 13558 rows and 6 columns ## [3] peptides_imputed: SummarizedExperiment with 13558 rows and 6 columns ## [4] log_peptides: SummarizedExperiment with 13558 rows and 6 columns ## [5] log_proteins: SummarizedExperiment with 2760 rows and 6 columns ## [6] log_norm_proteins: SummarizedExperiment with 2760 rows and 6 columns The final dataset is comprised of 2760 protein groups. We will save the protein-level SummarizedExperiment file as well as exporting the final QFeatures object. ## Save protein-level SE sn_proteins <- sn_qf[[ "log_norm_proteins" ]] ## Export TMT final QFeatures object save (sn_qf, file = "sn_qf.rda" ) Exploration of protein data Having described the processing steps for quantitative proteomics data, we next demonstrate how to explore the protein-level data prior to statistical analysis. For this we will utilise the TMT-labelled cell pellet dataset since it contains a greater number of proteins. Correlation plots We will first generate correlation plots between pairs of samples. To do this we use the corrplot package to calculate and plot the Pearson’s correlation coefficient between each sample pair. The cor function within the corrplot package will create a correlation matrix but requires a data.frame , matrix or a vector of class numeric as input. To convert the QFeatures assay data into a data.frame we use the as.data.frame function. ## Convert TMT CP protein assay into a dataframe prot_df % assay () %>% as.data.frame () ## Calculate a correlation matrix between samples corr_matrix <- cor(prot_df, method = "pearson" , use = "pairwise.complete.obs" ) print (corr_matrix) ## S5 S2 S1 S4 S6 S3 ## S5 1.0000000 0.9540226 0.9634202 0.9821489 0.9927946 0.9558386 ## S2 0.9540226 1.0000000 0.9862036 0.9207314 0.9508941 0.9886243 ## S1 0.9634202 0.9862036 1.0000000 0.9451292 0.9637123 0.9926604 ## S4 0.9821489 0.9207314 0.9451292 1.0000000 0.9864988 0.9348920 ## S6 0.9927946 0.9508941 0.9637123 0.9864988 1.0000000 0.9557268 ## S3 0.9558386 0.9886243 0.9926604 0.9348920 0.9557268 1.0000000 Now we can visualise the correlation data using pairwise scatter plots and a correlation heat map. ## Plot correlation between two samples - S1 and S2 used as example prot_df %>% ggplot ( aes ( x = S1 , y = S2 )) + geom_point ( colour = "grey45" , size = 0.5 ) + geom_abline ( intercept = 0 , slope = 1 ) + theme ( panel.grid.major = element_blank (), panel.grid.minor = element_blank (), plot.background = element_rect ( fill = "white" ), panel.background = element_rect ( fill = "white" ), axis.title.x = element_text ( size = 15 , vjust = - 2 ), axis.title.y = element_text ( size = 15 , vjust = 3 ), axis.text.x = element_text ( size = 12 , vjust = - 1 ), axis.text.y = element_text ( size = 12 ), axis.line = element_line ( linewidth = 0.5 , colour = "black" ), plot.margin = margin ( 10 , 10 , 10 , 10 )) + xlim ( - 7.5 , 5 ) + ylim ( - 7.5 , 5 ) + labs ( x = "log2(abundance S1)" , y = "log2(abundance S2)" ) + coord_fixed ( ratio = 1 ) ## Create colour palette for continuum col % cor ( method = "pearson" , use = "pairwise.complete.obs" ) %>% corrplot ( method = "color" , col = col ( 200 ), type = "upper" , addCoef.col = "white" , diag = FALSE , tl.col = "black" , tl.srt = 45 , outline = TRUE ) From these plots we can see that all replicate pairs have a Pearson’s correlation coefficient >0.98 whilst the correlation between pairs of control and treated samples is somewhat lower. Users may interpret this information as an early indication that some proteins may be differentially abundant between the two groups. Of note, whilst correlation is widely applied as a measure of reproducibility, users are reminded that correlation coefficients alone are not informative of reproducibility. 30 , 31 This is especially true for expression proteomics data in which high correlation values are likely due to the majority of proteins remaining at similar levels regardless of cellular perturbation. Users are directed to Ref. 32 for additional information regarding how to determine the calculation of experimental reproducibility. Principal Component Analysis Principal Component Analysis (PCA) is a dimensionality reduction method which aims to simplify complex datasets and facilitate the visualisation of multi-dimensional data. Here we use the prcomp function from the stats package to perform the PCA. Since PCA does not accept missing values and we did not impute the TMT data, the filterNA function can be used to remove any missing values that may be present in the protein-level data. We then extract and transpose the assay data before passing it to the prcomp function to carry out PCA. ## Carry out principal component analysis prot_pca % filterNA () %>% assay () %>% t () %>% prcomp ( scale = TRUE , center = TRUE ) We can get an idea of the outcome of the PCA by running the summary function on the results of the PCA. ## Get a summary of the PCA summary (prot_pca) ## Importance of components: ## PC1 PC2 PC3 PC4 PC5 PC6 ## Standard deviation 42.035 26.5522 18.1232 14.97317 14.3323 4.334e-14 ## Proportion of Variance 0.547 0.2183 0.1017 0.06941 0.0636 0.000e+00 ## Cumulative Proportion 0.547 0.7653 0.8670 0.93640 1.0000 1.000e+00 Finally, we create a PCA plot. For additional PCA exploration and visualisation tools users are directed to the factoextra package . ## Generate dataframe of each sample's PCA results pca_df <- as.data.frame (prot_pca $ x) ## Annotate samples with their corresponding condition pca_df$condition % ggplot ( aes ( x = PC1, y = PC2, colour = condition)) + geom_point ( size = 4 ) + scale_color_brewer ( palette = "Set2" ) + labs ( colour = "Condition" ) + geom_hline ( yintercept = 0 , linetype = "dashed" ) + geom_vline ( xintercept = 0 , linetype = "dashed" ) + guides ( colour = guide_legend ( override.aes = list ( size = 3 ))) + labs ( x = "PC1" , y = "PC2" ) + ggtitle ( "Protein-level PCA plot" ) + xlim ( - 100 , 100 ) + ylim ( - 100 , 100 ) + coord_fixed ( ratio = 1 ) + theme_bw () Exploring potential batch effects Before carrying out differential expression analysis, it is first necessary to explore the presence of batch effects within the data. Batch effects are derived from non-biological factors which impact the experimental data. These include reagents, instrumentation, personnel and laboratory conditions. In most cases the increased variation caused by batch effects will lead to reduced downstream statistical power. On the other hand, if correlated with the experimental sub-groups, batch effects can also lead to confounded results and the incorrect biological interpretation of differential expression. 33 Given that the use-case data was derived from a small experiment with only six samples and a single TMTplex, there are minimal batch effects to explore here. For users analyzing larger experiments completed over long period of time, across several laboratories/individuals, or using multiple TMTplex reagents, it is advisable to annotate the PCA plot with all potential batch factors. If data is found to cluster based on any of these factors, batch effects should be incorporated into downstream analyses. For example, users can apply the removeBatchEffect function from the limma package. Discovery and biological interpretation of differentially abundant proteins The last section of this workflow demonstrates how to gain biological insights from the resulting list of proteins. Again we will utilise the TMT-labelled cell pellet data, although the process would be exactly the same for the LFQ supernatant protein list. Users are reminded that although referred to as differential ‘expression’ analysis, abundance is determined by both protein synthesis and degradation. Extracting and organising protein-level data We first extract the protein-level SummarizedExperiment from the cell pellet TMT QFeatures object and specify the study factors. Here we are interested in discovering differences between conditions, control and treated. As well as assigning these conditions to each sample, we can define the control group as the reference level such that differential abundance is reported relative to the control. This means that when we get the results of the statistical analysis, ‘upregulated’ will refer to increased abundance in treated cells relative to controls. ## Extract protein-level data and associated colData cp_proteins <- cp_qf[[ "log_norm_proteins" ]] colData (cp_proteins) <- colData (cp_qf[[ "log_norm_proteins" ]]) ## Create factor of interest cp_proteins$condition <- factor (cp_proteins $ condition) ## Check which level of the factor is the reference level and correct cp_proteins $ condition ## [1] Control Treated Treated Control Control Treated ## Levels: Control Treated cp_proteins $ condition <- relevel (cp_proteins $ condition, ref = "Control" ) Differential expression analysis using limma Bioconductor contains several packages dedicated to the statistical analysis of proteomics data. For example, MSstats and MSstatsTMT can be used to determine differential protein expression within both DDA and DIA datasets for LFQ and TMT, respectively. 34 , 35 Of note, MSstatsTMT includes additional functionality for dealing with larger, multi-plexed TMT experiments. Similarly, DEqMS provides statistical analysis pipelines both label-based and LFQ experiments. 36 For LFQ experiments, proDA , prolfqua and MSqRob2 can be utilised, among others. 28 , 37 Here, we will use the limma package. 38 limma is widely used for the analysis of large omics datasets and has several models that allow differential abundance to be assessed in multifactorial experiments. This is useful because it allows multiple factors, including TMTplex, to be integrated into the model itself, thus minimising the effects of confounding factors. In this example we will apply limma ’s empirical Bayes moderated t-test, a method that is appropriate for small sample sizes. 39 We first use the model.matrix function to create a matrix in which each of the samples are annotated based on the factors we wish to model, here the condition group. This ultimately defines the ‘design’ of the model, that is how the samples are distributed between the groups of interest. We then fit a linear model to the abundance data of each protein by passing the data and model design matrix to the lmFit function. Finally, we update the estimated standard error for each model coefficient using the eBayes function. This function borrows information across features, here proteins, to shift the per-protein variance estimates towards an expected value based on the variance estimates of other proteins with similar mean intensity. This empirical Bayes technique has been shown to reduce the number of false positives for proteins with small variances as well as increase the power of detection for differentially abundant proteins with larger variances. 40 Further, we use the trend = TRUE argument when passing the eBayes function so that an intensity-dependent trend can be fitted to the prior variances. For more information about the limma trend method users are directed to Ref. 41 . ## Design a matrix containing all of the factors we wish to model the effects of model_design <- model.matrix( ~ cp_proteins $ condition) ## Verify print (model_design) ## (Intercept) cp_proteins$conditionTreated ## 1 1 0 ## 2 1 1 ## 3 1 1 ## 4 1 0 ## 5 1 0 ## 6 1 1 ## attr(,"assign") ## [1] 0 1 ## attr(,"contrasts") ## attr(,"contrasts")$'cp_proteins$condition' ## [1] "contr.treatment" ## Create a linear model using this design fitted_lm % assay () %>% lmFit ( design = model_design) ## Update the model based on Limma eBayes algorithm fitted_lm <- eBayes ( fit = fitted_lm, trend = TRUE ) ## Save results of the test limma_results % rownames_to_column ( "Protein" ) %>% as_tibble () %>% mutate ( TP = grepl ( "ups" , Protein)) Having applied the model to the data, we need to verify that this model was appropriate and that the statistical assumptions were met. To do this we first generate an SA plot using the plotSA function within limma . An SA plot shows the log2 residual standard deviation (sigma) against log average abundance and is a simple way to visualise the trend that has been fitted to the data. ## Plot residual SD against average log abundance plotSA (fitted_lm, xlab = "Average log2(abundance)" , ylab = "log2(sigma)" , cex = 0.5 ) The residual standard deviation is a measure of model accuracy and is most easily conceptualised as a measurement of how far from the model prediction each data point lies. The smaller the residual standard deviation, the closer the fit between the model and observed data. Next we will plot a p-value histogram. Importantly, this histogram shows the distribution of p-values prior to any multiple hypothesis test correction or false discovery rate control. This means plotting the P.value variable, not the adj.P.Val . ## Plot histogram of raw p-values limma_results %>% ggplot ( aes ( x = P.Value)) + geom_histogram ( binwidth = 0.025 ) + labs ( x = "P-value" , y = "Frequency" ) + ggtitle ( "P-value distribution following Limma eBayes trend model" ) + theme_bw () The figure displayed shows an anti-conservative p-value distribution. The flat distribution across the base of the graph represents the non-significant p-values spread uniformly between 0 and 1, whilst the peak close to 0 contains significant p-values, along with some false positives. For a more thorough explanation of interpreting p-value distributions, including why your data may not produce an anti-conservative distribution if your statistical model is inappropriate, please see Ref. 42 . Now, having applied the statistical model and verified it’s suitability, we take an initial look at the outputs. ## Look at limma results table head (limma_results) ## # A tibble: 6 x 8 ## Protein logFC AveExpr t P.Value adj.P.Val B TP ## ## 1 Q01581 1.50 0.592 28.4 6.35e-10 0.00000205 13.1 FALSE ## 2 P15104 1.32 1.36 23.2 3.63e- 9 0.00000558 11.7 FALSE ## 3 Q9UK41 1.46 -1.49 21.7 6.36e- 9 0.00000558 11.2 FALSE ## 4 P37268 1.32 -0.674 21.0 8.58e- 9 0.00000558 10.9 FALSE ## 5 P04183 1.29 0.943 21.0 8.64e- 9 0.00000558 10.9 FALSE ## 6 Q9UHI8 2.45 0.368 18.8 2.21e- 8 0.0000119 10.0 FALSE The results table contains several important pieces of information. Each master protein is represented by its accession number and has an associated log2 fold change, that is the log2 difference in mean abundance between conditions, as well as a log2 mean expression across all six samples, termed AveExpr . Since we carried out an empirical Bayes moderated t-test, each protein also has a moderated t-statistic and associated p-value. The moderated t-statistic can be interpreted in the same way as a standard t-statistic. Each protein also has an adjusted p-value which accounts for multiple hypothesis testing to control the overall FDR. The default method for multiple hypothesis corrections within the topTable function that we applied is the Benjamini and Hochberg (BH) adjustment, 43 although we could have specified an alternative. Finally, the B-statistic represents the log-odds that a protein is differentially abundant between the two conditions, and the data is presented in descending order with those with the highest log-odds of differential abundance at the top. We can add annotations to this results table based on the user-defined significance thresholds. In the literature, for stringent analyses a FDR-adjusted p-value threshold of 0.01 is most frequently used, or 0.05 for exploratory analyses. Ultimately these thresholds are arbitrary and set by the user. The addition of a log-fold change (logFC) threshold is at the users discretion and can be useful to determine significant results of biological relevance. When using a TMT labelling strategy the co-isolation interference can lead to substantial and uneven ratio compression, thus it is not recommended to apply a fold change threshold here. ## Add direction of log fold change relative to control limma_results $ direction 0 , "up" , "down" ) %>% as.factor () ## Add significance thresholds limma_results$significance <- ifelse(limma_results $ adj.P.Val % as.factor () ## Verify str (limma_results) ## tibble [3,230 x 10] (S3: tbl_df/tbl/data.frame) ## $ Protein : chr [1:3230] "Q01581" "P15104" "Q9UK41" "P37268" … ## $ logFC : num [1:3230] 1.5 1.32 1.46 1.32 1.29 … ## $ AveExpr : num [1:3230] 0.592 1.363 -1.485 -0.674 0.943 … ## $ t : num [1:3230] 28.4 23.2 21.7 21 21 … ## $ P.Value : num [1:3230] 6.35e-10 3.63e-09 6.36e-09 8.58e-09 8.64e-09 … ## $ adj.P.Val : num [1:3230] 2.05e-06 5.58e-06 5.58e-06 5.58e-06 5.58e-06 … ## $ B : num [1:3230] 13.1 11.7 11.2 10.9 10.9 … ## $ TP : logi [1:3230] FALSE FALSE FALSE FALSE FALSE FALSE … ## $ direction : Factor w/ 2 levels "down","up": 2 2 2 2 2 2 1 2 1 2 … ## $ significance : Factor w/ 2 levels "not.sig","sig": 2 2 2 2 2 2 2 2 2 2 … In the next code chunk, we use the decideTests function to determine how many proteins are significantly up- and down-regulated in the treated compared to control HEK293 cells. We tell this function to classify the significance of each t-statistic based on a BH-adjusted p-value of 0.01. If we had not used TMT labels and wished to include a logFC threshold, we could have included the lfc argument and passed our desired logFC threshold. The function will then output a numerical matrix containing either -1, 0, or 1 for each protein in each condition, where a value of -1 indicates significant downregulation, 0 not significant and 1 significant upregulation. To simplify interpretation, we print a summary of this matrix. ## Get a summary of statistically significant results fitted_lm %>% decideTests ( adjust.method = "BH" , p.value = 0.01 ) %>% summary () ## (Intercept) cp_proteins$conditionTreated ## Down 1423 381 ## NotSig 404 2536 ## Up 1403 313 From this table we can see that 381 proteins were downregulated in treated HEK293 cells compared to the control group whilst 313 were upregulated. Given that no logFC threshold was applied some of the significant differences in abundance may be small. Further, these results mean little without any information about which proteins these were and what roles they play within the cell. We subset the significant proteins so that we can investigate them further. ## Subset proteins that show significantly different abundance sig_proteins <- subset (limma_results, adj.P.Val <= 0.01 ) length (sig_proteins $ Protein) ## [1] 694 Visualizing differentially abundant proteins Before looking deeper into which proteins have differential abundance, we first create some simple plots to visualise the results. Volcano plots and MA plots are two of the common visualisations used in this instance. When plotting the former, users are advised to plot raw p-values rather than their derivative BH-adjusted p-values. Point colours can be used to indicate significance based on BH- adjusted p-values, as is shown in the code chunk below. ## Generate a volcano plot limma_results %>% ggplot ( aes ( x = logFC, y = - log10 (P.Value))) + geom_point ( aes ( colour = significance : direction), size = 0.5 ) + scale_color_manual ( values = c ( "black" , "black" , "deepskyblue" , "red" ), name = "" , labels = c ( "Downregulated insignificant" , "Upregulated insignificant" , "Downregulated significant" , "Upregulated significant" )) + theme ( axis.title.x = element_text ( size = 15 , vjust = - 2 ), axis.title.y = element_text ( size = 15 , vjust = 2 ), axis.text.x = element_text ( size = 12 , vjust = - 1 ), axis.text.y = element_text ( size = 12 ), plot.background = element_rect ( fill = "white" ), panel.background = element_rect ( fill = "white" ), axis.line = element_line ( linewidth = 0.5 , colour = "black" ), plot.margin = margin ( 10 , 10 , 10 , 10 ), legend.position.inside = c ( 0.25 , 0.9 )) + labs ( x = "log2(FC)" , y = "-log10(p-value)" ) + xlim ( - 3.1 , 3.1 ) ## Generate MA plot limma_results %>% ggplot ( aes ( x = AveExpr, y = logFC)) + geom_point ( aes ( colour = significance : direction), size = 0.5 ) + scale_color_manual ( values = c ( "black" , "black" , "deepskyblue" , "red" ), name = "" , labels = c ( "Downregulated insignificant" , "Upregulated insignificant" , "Downregulated significant" , "Upregulated significant" )) + theme ( axis.title.x = element_text ( size = 15 , vjust = - 2 ), axis.title.y = element_text ( size = 15 , vjust = 2 ), axis.text.x = element_text ( size = 12 , vjust = - 1 ), axis.text.y = element_text ( size = 12 ), plot.background = element_rect ( fill = "white" ), panel.background = element_rect ( fill = "white" ), axis.line = element_line ( linewidth = 0.5 , colour = "black" ), plot.margin = margin ( 10 , 10 , 10 , 10 ), legend.position.inside = c ( 0.25 , 0.9 )) + xlab ( "log2(mean abundance)" ) + ylab ( "log2(FC)" ) + xlim ( - 5 , 3.5 ) Gene Ontology enrichment analysis The final step in the processing workflow is to apply Gene Ontology (GO) enrichment analyses to gain a biological understanding of the proteins which were either up or downregulated in HEK293 cells upon treatment. GO terms provide descriptions for genes and their corresponding proteins in the form of Molecular Functions (MF), Biological Processes (BP) and Cellular Components (CC). By carrying out GO enrichment analysis we can determine whether the frequency of any of these terms is higher than expected in the proteins of interest compared to all of the proteins which were detected. Such results can indicate whether proteins that were increased or decreased in abundance in treated HEK293 cells represent particular cellular locations, biological pathways or cellular functions. Although GO enrichment analysis can be carried out online using websites such as GOrilla 44 or PantherDB , 45 , 46 we advise against this due to a lack of traceability and reproducibility. Instead, readers are advised to make use of GO enrichment packages within the Bioconductor infrastructure. Many such packages exist, including topGO , 47 GOfuncR , 48 and clusterProfiler . 49 Here we will use enrichGO function in the clusterProfiler package. First, we subset the accessions of proteins that we consider to be significantly up or downregulated. These will be our proteins of interest. ## Subset significantly upregulated and downregulated proteins sig_up % filter (direction == "up" ) %>% filter (significance == "sig" ) %>% pull (Protein) sig_down % filter (direction == "down" ) %>% filter (significance == "sig" ) %>% pull (Protein) Next, we input the UniProt IDs of up and downregulated proteins into the GO enrichment analyses, as demonstrated below. Importantly, we provide the protein list of interest as the foreground and a list of all proteins identified within the study as the background, or ‘universe’. The keyType argument is used to tell the function that our protein accessions are in UniProt format. This allows mapping from UniProt ID back to a database containing the entire human genome ( org.Hs.eg.db ). We also inform the function which GO categories we wish to consider, here “ALL”, meaning BP, MF and CC. As well as the information outlined above, there is the opportunity for users to specify various thresholds for statistical significance. These include thresholds on original and adjusted p-values (using the pvalueCutoff argument) as well as q-values (via the qvalueCutoff argument). Although many papers often use ‘q- value’ to mean ‘BH-adjusted p-value’, the two are not always the same and users should be explicit about the statistical thresholds that they have applied. For exploratory purposes we will use the standard BH method for FDR control and set p-value, BH-adjusted p-value, and q-value thresholds of 0.05. ## Search for enriched GO terms within upregulated proteins ego_up <- enrichGO ( gene = sig_up, universe = limma_results $ Protein, OrgDb = org.Hs.eg.db, keyType = "UNIPROT" , ont = "ALL" , pAdjustMethod = "BH" , pvalueCutoff = 0.05 , qvalueCutoff = 0.05 , readable = TRUE ) ## Check results ego_up ## # ## # over-representation test ## # ## #...@organism Homo sapiens ## #...@ontology GOALL ## #...@keytype UNIPROT ## #...@gene chr [1:313] "Q01581" "P15104" "Q9UK41" "P37268" "P04183" "Q9UHI8" "Q13907" … ## #…pvalues adjusted by 'BH' with cutoff <0.05 ## #…2 enriched terms found ## 'data.frame' : 2 obs. of 10 variables: ## $ ONTOLOGY : chr "CC" "CC" ## $ ID : chr "GO:0005758" "GO:0031970" ## $ Description : chr "mitochondrial intermembrane space" "organelle envelope lumen" ## $ GeneRatio : chr "13/308" "13/308" ## $ BgRatio : chr "40/3176" "44/3176" ## $ pvalue : num 5.59e-05 1.68e-04 ## $ p.adjust : num 0.0208 0.0313 ## $ qvalue : num 0.0207 0.0312 ## $ geneID: chr "CHCHD2/TIMM9/AK2/TIMM8B/COA4/COA6/MIX23/TIMM8A/DIABLO/TIMM13/TIMM10/TRIAP1/CYCS" "CHCHD2/TIMM9/AK2/TIMM8B/COA4/COA6/MIX23/TIMM8A/DIABLO/TIMM13/TIMM10/TRIAP1/CYCS" ## $ Count : int 13 13 ## #...Citation ## T Wu, E Hu, S Xu, M Chen, P Guo, Z Dai, T Feng, L Zhou, W Tang, L Zhan, X Fu, S Liu, X Bo, and G Yu. ## clusterProfiler 4.0: A universal enrichment tool for interpreting omics data. ## The Innovation. 2021, 2(3):100141 We can see from the results that there are 2 significantly enriched terms associated with the upregulated proteins. Next, we take a look at the downregulated proteins. ## Search for enriched GO terms within downregulated proteins ego_down <- enrichGO ( gene = sig_down, universe = limma_results $ Protein, OrgDb = org.Hs.eg.db, keyType = "UNIPROT" , ont = "ALL" , pAdjustMethod = "BH" , pvalueCutoff = 0.05 , qvalueCutoff = 0.05 , readable = TRUE ) ## Check results ego_down ## # ## # over-representation test ## # ## #...@organism Homo sapiens ## #...@ontology GOALL ## #...@keytype UNIPROT ## #...@gene chr [1:381] "Q53EL6" "P08243" "P35716" "Q92878" "P26583" "Q92522" "O43657" … ## #…pvalues adjusted by 'BH' with cutoff <0.05 ## #…61 enriched terms found ## 'data.frame' : 61 obs. of 10 variables: ## $ ONTOLOGY : chr "BP" "BP" "BP" "BP" … ## $ ID : chr "GO:0006310" "GO:0000725" "GO:0006302" "GO:0006520" … ## $ Description : chr "DNA recombination" "recombinational repair" "double-strand break repair" "amino acid metabolic process" … ## $ GeneRatio : chr "37/366" "23/366" "32/366" "33/366" … ## $ BgRatio : chr "95/3121" "58/3121" "101/3121" "113/3121" … ## $ pvalue : num 3.61e-12 3.61e-08 4.54e-08 2.48e-07 4.46e-07 … ## $ p.adjust : num 8.65e-09 3.62e-05 3.62e-05 1.48e-04 2.14e-04 … ## $ qvalue : num 8.33e-09 3.48e-05 3.48e-05 1.43e-04 2.06e-04 … ## $ geneID : chr "RAD50/HMGB2/H1-10/RADX/MRE11/H1-0/H1-2/ZMYND8/MCM5/HMGB3/NUCKS1/RAD21/PRKDC/SFPQ/MCM4/XRCC6/HTATSF1/H1-3/MCM7/T"| __truncated__ "RADX/MRE11/ZMYND8/MCM5/NUCKS1/RAD21/SFPQ/MCM4/XRCC6/HTATSF1/MCM7/XRCC5/PPP4R2/POGZ/YY1/MCM3/MCM2/VPS72/PARP1/BR"| __truncated__ "RAD50/HMGB2/RADX/MRE11/DEK/ZMYND8/MCM5/NUCKS1/RAD21/PRKDC/TP53/SMARCC2/SFPQ/MCM4/XRCC6/HPF1/HTATSF1/MCM7/XRCC5/"| __truncated__ "ASNS/PHGDH/SDSL/SARS1/YARS1/AARS2/HMGCL/GARS1/IARS2/AARS1/HIBADH/PYCR1/ACADSB/DHFR/MCCC2/SLC25A12/MARS1/PSAT1/S"| __truncated__ … ## $ Count : int 37 23 32 33 21 14 55 14 14 44 … ## #…Citation ## T Wu, E Hu, S Xu, M Chen, P Guo, Z Dai, T Feng, L Zhou, W Tang, L Zhan, X Fu, S Liu, X Bo, and G Yu. ## clusterProfiler 4.0: A universal enrichment tool for interpreting omics data. ## The Innovation. 2021, 2(3):100141 The downregulated proteins contain 61 significantly enriched GO terms. There are many ways in which users can represent these results visually. Here, we create a barplot using the barplot function from the enrichplot package. 50 Users are directed to the vignette of the enrichplot package for additional visualisation options and guidance. We plot the first 10 GO terms i.e. the 10 GO terms with the greatest enrichment. ## Plot the results barplot (ego_down, x = "Count" , showCategory = 10 , font.size = 12 , label_format = 28 , colorBy = "p.adjust" ) Writing and exporting data Finally, we export the results of our statistical analyses as .csv files. ## Save results of Limma statistics write.csv (limma_results, file = "all_limma_results.csv" ) ## Save subsets of upregulated and downregulated proteins write.csv (sig_up, file = "upregulated_results.csv" ) write.csv (sig_down, file = "downregulated_results.csv" ) ## Save results of GO enrichment write.csv (ego_up, file = "upregulated_go_enrichment.csv" ) write.csv (ego_down, file = "downregulated_go_enrichment.csv" ) Users can also use the ggsave function to export any of the figures generated. Discussion and conclusion Expression proteomics is becoming an increasingly important tool in modern molecular biology. As more researchers participate in expression proteomics, either by collecting data or accessing data collected by others, there is a need for clear illustration(s) of how to deal with such complex data. Existing bottom-up proteomics workflows for differential expression analysis either provide pipelines with limited user control and flexibility (e.g., MSstats and MSstatsTMT 34 , 35 ), can only be applied to specific data formats (e.g., Proteus which is limited to input from MaxQuant 51 ), or provide very limited commentary. The latter directly contributes to a problematic disconnect between researchers and their data whereby the users do not understand if or why each step is necessary for their given dataset and biological question. This can prevent researchers from refining a workflow to fit their specific needs. Finally, the majority of proteomics workflows utilise data.frame or tibble structures which limits their traceability, as is the case for protti , promor and prolfqua. 52 – 54 The workflow presented here outlines in completion how to process, analyze and interpret LFQ and TMT expression proteomics data derived from a bottom-up DDA experiment. Critically, we emphasise quality control and data-guided decisions with an extensive explanation of all key steps and how they may differ in various scenarios (e.g., the quantitation method, instrumentation and biological question). Our workflow takes advantage of the relatively recent QFeatures infrastructure to ensure explicit and transparent data pre-processing as well as to provide an easy way for users to trace back through their analyses. These features are particularly important for beginners who wish to gain a better understanding of their data and how it changes throughout this workflow. No single workflow can demonstrate the processing, analysis and interpretation of all proteomics data. Our workflow is currently suitable for DDA datasets with label-free or TMT-based quantitation. We do not include examples of experiments that combine data from multiple TMTplexes, although the code provided could easily be expanded to include such a scenario. This workflow provides an in-depth user-friendly pipeline for both new and experienced proteomics data analysts. Session information and getting help The workflows provided involve use of functions from many different R/Bioconductor packages. The sessionInfo function provides an easy way to summarise all packages and the corresponding versions used to generate this document. Should software updates lead to the generation of errors or different results to those demonstrated here, such changes should be easily traced. ## Print session information sessionInfo () ## R version 4.4.0 (2024-04-24) ## Platform: aarch64-apple-darwin20 ## Running under: macOS Ventura 13.2 ## ## Matrix products: default ## BLAS: /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRblas.0.dylib ## LAPACK: /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRlapack.dylib; LAPACK version 3.12.0 ## ## locale: ## [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8 ## ## time zone: Europe/London ## tzcode source: internal ## ## attached base packages: ## [1] stats4 stats graphics grDevices utils datasets methods ## [8] base ## ## other attached packages: ## [1] patchwork_1.2.0 enrichplot_1.24.0 ## [3] clusterProfiler_4.12.0 org.Hs.eg.db_3.19.1 ## [5] AnnotationDbi_1.66.0 limma_3.60.0 ## [7] Biostrings_2.72.0 XVector_0.44.0 ## [9] corrplot_0.92 tibble_3.2.1 ## [11] dplyr_1.1.4 stringr_1.5.1 ## [13] ggplot2_3.5.1 QFeatures_1.14.0 ## [15] MultiAssayExperiment_1.30.1 SummarizedExperiment_1.34.0 ## [17] Biobase_2.64.0 GenomicRanges_1.56.0 ## [19] GenomeInfoDb_1.40.0 IRanges_2.38.0 ## [21] S4Vectors_0.42.0 BiocGenerics_0.50.0 ## [23] MatrixGenerics_1.16.0 matrixStats_1.3.0 ## ## loaded via a namespace (and not attached): ## [1] RColorBrewer_1.1-3 rstudioapi_0.16.0 jsonlite_1.8.8 ## [4] magrittr_2.0.3 farver_2.1.1 rmarkdown_2.26 ## [7] fs_1.6.4 zlibbioc_1.50.0 vctrs_0.6.5 ## [10] memoise_2.0.1 ggtree_3.12.0 tinytex_0.51 ## [13] BiocBaseUtils_1.6.0 htmltools_0.5.8.1 S4Arrays_1.4.0 ## [16] usethis_2.2.3 gridGraphics_0.5-1 SparseArray_1.4.3 ## [19] plyr_1.8.9 impute_1.78.0 cachem_1.0.8 ## [22] igraph_2.0.3 lifecycle_1.0.4 pkgconfig_2.0.3 ## [25] gson_0.1.0 Matrix_1.7-0 R6_2.5.1 ## [28] fastmap_1.1.1 GenomeInfoDbData_1.2.12 clue_0.3-65 ## [31] digest_0.6.35 aplot_0.2.2 colorspace_2.1-0 ## [34] RSQLite_2.3.6 labeling_0.4.3 fansi_1.0.6 ## [37] httr_1.4.7 polyclip_1.10-6 abind_1.4-5 ## [40] compiler_4.4.0 bit64_4.0.5 withr_3.0.0 ## [43] BiocParallel_1.38.0 viridis_0.6.5 DBI_1.2.2 ## [46] ggforce_0.4.2 MASS_7.3-60.2 DelayedArray_0.30.1 ## [49] HDO.db_0.99.1 tools_4.4.0 scatterpie_0.2.2 ## [52] ape_5.8 glue_1.7.0 nlme_3.1-164 ## [55] GOSemSim_2.30.0 shadowtext_0.1.3 grid_4.4.0 ## [58] cluster_2.1.6 reshape2_1.4.4 fgsea_1.30.0 ## [61] generics_0.1.3 gtable_0.3.5 tidyr_1.3.1 ## [64] data.table_1.15.4 tidygraph_1.3.1 utf8_1.2.4 ## [67] ggrepel_0.9.5 pillar_1.9.0 yulab.utils_0.1.4 ## [70] BiocWorkflowTools_1.30.0 splines_4.4.0 tweenr_2.0.3 ## [73] treeio_1.28.0 lattice_0.22-6 bit_4.0.5 ## [76] tidyselect_1.2.1 GO.db_3.19.1 knitr_1.46 ## [79] git2r_0.33.0 gridExtra_2.3 bookdown_0.39 ## [82] ProtGenerics_1.36.0 xfun_0.43 graphlayouts_1.1.1 ## [85] statmod_1.5.0 stringi_1.8.4 UCSC.utils_1.0.0 ## [88] lazyeval_0.2.2 ggfun_0.1.4 yaml_2.3.8 ## [91] evaluate_0.23 codetools_0.2-20 ggraph_2.2.1 ## [94] MsCoreUtils_1.16.0 qvalue_2.36.0 BiocManager_1.30.23 ## [97] ggplotify_0.1.2 cli_3.6.2 munsell_0.5.1 ## [100] Rcpp_1.0.12 png_0.1-8 parallel_4.4.0 ## [103] blob_1.2.4 DOSE_3.30.0 AnnotationFilter_1.28.0 ## [106] tidytree_0.4.6 viridisLite_0.4.2 scales_1.3.0 ## [109] purrr_1.0.2 crayon_1.5.2 rlang_1.1.3 ## [112] cowplot_1.1.3 fastmatch_1.1-4 KEGGREST_1.44.0 Users are advised to update R itself as well as packages as required. Bioconductor packages can be updated using the BiocManager::install() function, as shown below. if ( ! require ( "BiocManager" , quietly = TRUE )) { install.packages ( "BiocManager" ) } BiocManager :: install () Author contributions C. H. conceptualization, investigation, methodology, project administration, software, validation, writing – original draft preparation, review and editing; C. S. D. software and writing - review and editing; T. K. methodology, supervision, software, writing - review and editing; K. S. L. funding acquisition, supervision, writing - review and editing; L. M. B. conceptualization, methodology, supervision, writing - review and editing. Data availability This workflow is written in the R statistical programming language and uses freely available open-source software packages from CRAN and Bioconductor. Version numbers for all packages are shown in the Session information section. Raw mass spectrometry data is freely available online through the ProteomeXchange Consortium via the PRIDE repository with identifier PXD041794. All processed data is available at https://zenodo.org/records/13753944 , 10 and at GitHub repository https://github.com/CambridgeCentreForProteomics/f1000_expression_proteomics . Acknowledgements The authors would like to thank Savvas Kourtis from the Centre for Genomic Regulation, Barcelona, and Oliver M. Crook, from the Department of Statistics, Oxford University, UK, for trialing this workflow. References 1. Pina-Jiménez E, Calzada F, Bautista E, et al. : Incomptine a induces apoptosis, ROS production and a differential protein expression on non-hodgkin’s lymphoma cells. Int. J. Mol. Sci. September 2021; 22 (19): 10516. PubMed Abstract | Publisher Full Text | Free Full Text 2. Amiri-Dashatan N, Ahmadi N, Rezaei-Tavirani M, et al. : Identification of differential protein expression and putative drug target in metacyclic stage of leishmania major and leishmania tropica: A quantitative proteomics and computational view. Comp. Immunol. Microbiol. Infect. Dis. April 2021; 75 : 101617. PubMed Abstract | Publisher Full Text 3. Anitua E, de la Fuente M , Muruzabal F, et al. : Differential profile of protein expression on human keratocytes treated with autologous serum and plasma rich in growth factors (PRGF). PLoS One. October 2018; 13 (10): e0205073. PubMed Abstract | Publisher Full Text | Free Full Text 4. Dupree EJ, Jayathirtha M, Yorkey H, et al. : A critical review of bottom-up proteomics: The good, the bad, and the future of this field. Proteomes. July 2020; 8 (3): 14. PubMed Abstract | Publisher Full Text | Free Full Text 5. Obermaier C, Griebel A, Westermeier R: Principles of protein labeling techniques. Methods in Molecular Biology. New York: Springer; 2015; pp. 153–165. Publisher Full Text 6. Fernández-Costa C, Martnez-Bartolomé S, McClatchy DB, et al. : Impact of the identification strategy on the reproducibility of the DDA and DIA results. J. Proteome Res. June 2020; 19 (8): 3153–3161. PubMed Abstract | Publisher Full Text | Free Full Text 7. Alex H, Noble WS, Wolf-Yadlin A: Technical advances in proteomics: new developments in data-independent acquisition. F1000Res. March 2016; 5 : 419. PubMed Abstract | Publisher Full Text | Free Full Text 8. R Development Core Team: R: A Language and Environment for Statistical Computing. Vienna, Austria: R Foundation for Statistical Computing; 2011. 3-900051-07-0. Reference Source 9. Huber W, Carey VJ, Gentleman R, et al. : Orchestrating high-throughput genomic analysis with bioconductor. Nat. Methods. January 2015; 12 (2): 115–121. PubMed Abstract | Publisher Full Text | Free Full Text 10. Hutchings C, Dawson C, Krueger T, et al. : A Bioconductor workflow for processing, evaluating and interpreting expression proteomics data. In F1000 Research. Zenodo. [Dataset]. 2023. Publisher Full Text 11. McAlister GC, Nusinow DP, Jedrychowski MP, et al. : MultiNotch MS3 enables accurate, sensitive, and multiplexed detection of differential expression across cancer cell line proteomes. Anal. Chem. July 2014; 86 (14): 7150–7158. PubMed Abstract | Publisher Full Text | Free Full Text 12. Ting L, Rad R, Gygi SP, et al. : MS3 eliminates ratio distortion in isobaric multiplexed quantitative proteomics. Nat. Methods. October 2011; 8 (11): 937–940. PubMed Abstract | Publisher Full Text | Free Full Text 13. Plubell DL, Wilmarth PA, Zhao Y, et al. : Extended multiplexing of tandem mass tags (TMT) labeling reveals age and high fat diet specific proteome changes in mouse epididymal adipose tissue. Mol. Cell. Proteomics. May 2017; 16 (5): 873–890. PubMed Abstract | Publisher Full Text | Free Full Text 14. Brenes A, Hukelmann J, Bensaddek D, et al. : Multibatch TMT reveals false positives, batch effects and missing values. Mol. Cell. Proteomics. October 2019; 18 (10): 1967–1980. PubMed Abstract | Publisher Full Text | Free Full Text 15. Perez-Riverol Y, Bai J, Bandla C, et al. : The PRIDE database resources in 2022: a hub for mass spectrometry-based proteomics evidences. Nucleic Acids Res. November 2021; 50 (D1): D543–D552. PubMed Abstract | Publisher Full Text | Free Full Text 16. Deutsch EW, Bandeira N, Perez-Riverol Y, et al. : The ProteomeXchange consortium at 10 years: 2023 update. Nucleic Acids Res. November 2022; 51 (D1): D1539–D1548. PubMed Abstract | Publisher Full Text | Free Full Text 17. Gatto L, Vanderaa C: QFeatures: Quantitative features for mass spectrometry data.2023. R package version 1.9.2. Reference Source 18. Morgan M, Obenchain V, Hester J, et al. : SummarizedExperiment: SummarizedExperiment container.2022. R package version 1.29.1. Reference Source 19. Rainer J, Vicini A, Salzer L, et al. : A modular and expandable ecosystem for metabolomics data annotation in r. Metabolites. February 2022; 12 (2): 173. PubMed Abstract | Publisher Full Text | Free Full Text 20. Frankenfield AM, Ni J, Ahmed M, et al. : Protein contaminants matter: Building universal protein contaminant libraries for DDA and DIA proteomics. J. Proteome Res. July 2022; 21 (9): 2104–2113. PubMed Abstract | Publisher Full Text | Free Full Text 21. Pages H, Aboyoun P, Gentleman R, et al. : Biostrings: Efficient Manipulation of Biological Strings.2022. R package version 2.66.0. 22. Karpievitch Y, Stanley J, Taverner T, et al. : A statistical framework for protein quantitation in bottom-up MS-based proteomics. Bioinformatics. June 2009; 25 (16): 2028–2034. PubMed Abstract | Publisher Full Text | Free Full Text 23. Lazar C, Gatto L, Ferro M, et al. : Accounting for the multiple natures of missing salues in label-free quantitative proteomics data sets to compare imputation strategies. J. Proteome Res. March 2016; 15 (4): 1116–1125. PubMed Abstract | Publisher Full Text 24. Sticker A, Goeminne L, Martens L, et al. : Robust summarization and inference in proteome-wide label-free quantification. Mol. Cell. Proteomics. July 2020; 19 (7): 1209–1219. PubMed Abstract | Publisher Full Text | Free Full Text 25. Goeminne LJE, Gevaert K, Clement L: Peptide-level robust ridge regression improves estimation, sensitivity, and specificity in data-dependent quantitative label-free shotgun proteomics. Mol. Cell. Proteomics. February 2016; 15 (2): 657–668. PubMed Abstract | Publisher Full Text | Free Full Text 26. O’Rourke MB, Town SEL, Dalla PV, et al. : What is normalization? the strategies employed in top-down and bottom-up proteome analysis workflows. Proteomes. August 2019; 7 (3): 29. PubMed Abstract | Publisher Full Text | Free Full Text 27. Willforss J, Chawade A, Levander F: NormalyzerDE: Online tool for improved normalization of omics expression data and high-sensitivity differential expression analysis. J. Proteome Res. October 2018; 18 (2): 732–740. PubMed Abstract | Publisher Full Text 28. Goeminne LJE, Sticker A, Martens L, et al. : MSqRob takes the missing hurdle: Uniting intensity- and count-based proteomics. Anal. Chem. March 2020; 92 (9): 6278–6287. PubMed Abstract | Publisher Full Text 29. Liu M, Dongre A: Proper imputation of missing values in proteomics datasets for differential expression analysis. Brief. Bioinform. June 2021; 22 (3). PubMed Abstract | Publisher Full Text 30. Irizarry R: Correlation is not a measure of reproducibility.2015. Reference Source 31. Bunting KV, Steeds RP, Slater LT, et al. : A practical guide to assess the reproducibility of echocardiographic measurements. J. Am. Soc. Echocardiogr. December 2019; 32 (12): 1505–1515. PubMed Abstract | Publisher Full Text 32. Darbani B, Stewart CN: Reproducibility and reliability assays of the gene expression-measurements. J. Biol. Res.-Thessalon. May 2014; 21 (1). PubMed Abstract | Publisher Full Text | Free Full Text 33. Leek JT, Scharpf RB, Bravo HC, et al. : Tackling the widespread and critical impact of batch effects in high-throughput data. Nat. Rev. Genet. September 2010; 11 (10): 733–739. PubMed Abstract | Publisher Full Text | Free Full Text 34. Choi M, Chang C-Y, Clough T, et al. : MSstats: an r package for statistical analysis of quantitative mass spectrometry-based proteomic experiments. Bioinformatics. May 2014; 30 (17): 2524–2526. PubMed Abstract | Publisher Full Text 35. Huang T, Choi M, Tzouros M, et al. : MSstatsTMT: Statistical detection of differentially abundant proteins in experiments with isobaric labeling and multiple mixtures. Mol. Cell. Proteomics. October 2020; 19 (10): 1706–1723. PubMed Abstract | Publisher Full Text | Free Full Text 36. Zhu Y, Orre LM, Tran YZ, et al. : Deqms: A method for accurate variance estimation in differential protein expression analysis. Mol. Cell. Proteomics. June 2020; 19 (6): 1047–1057. 1535-9476. PubMed Abstract | Publisher Full Text | Free Full Text 37. Wolski WE, Nanni P, Grossmann J, et al. : prolfqua: A comprehensive R-package for proteomics differential expression analysis. J. Proteome Res. March 2023; 22 (4): 1092–1104. PubMed Abstract | Publisher Full Text | Free Full Text 38. Ritchie ME, Phipson B, Di W, et al. : limma powers differential expression analyses for RNA-sequencing and microarray studies. Nucleic Acids Res. January 2015; 43 (7): e47–e47. PubMed Abstract | Publisher Full Text | Free Full Text 39. Smyth GK: Linear models and empirical bayes methods for assessing differential expression in microarray experiments. Stat. Appl. Genet. Mol. Biol. January 2004; 3 (1): 1–25. PubMed Abstract | Publisher Full Text 40. Phipson B, Lee S, Majewski IJ, et al. : Robust hyperparameter estimation protects against hypervariable genes and improves power to detect differential expression. Ann. Appl. Stat. June 2016; 10 (2): 946–963. PubMed Abstract | Publisher Full Text | Free Full Text 41. Law CW, Chen Y, Shi W, et al. : voom: precision weights unlock linear model analysis tools for RNA-seq read counts. Genome Biol. 2014; 15 (2): R29. PubMed Abstract | Publisher Full Text | Free Full Text 42. Robinson D: How to interpret a p-value histogram.2014. Reference Source 43. Benjamini Y, Hochberg Y: Controlling the false discovery rate: a practical and powerful approach to multiple testing. J. R. Stat. Soc. 1995; 57 (1): 289–300. Publisher Full Text 44. Eden E, Navon R, Steinfeld I, et al. : GOrilla: a tool for discovery and visualization of enriched GO terms in ranked gene lists. BMC Bioinformatics. February 2009; 10 (1). PubMed Abstract | Publisher Full Text | Free Full Text 45. Mi H, Muruganujan A, Thomas PD: PANTHER in 2013: modeling the evolution of gene function, and other gene attributes, in the context of phylogenetic trees. Nucleic Acids Res. November 2012; 41 (D1): D377–D386. PubMed Abstract | Publisher Full Text | Free Full Text 46. Thomas PD, Ebert D, Muruganujan A, et al. : PANTHER: Making genome-scale phylogenetics accessible to all. Protein Sci. November 2021; 31 (1): 8–22. PubMed Abstract | Publisher Full Text | Free Full Text 47. Alexa A: topGO: Enrichment Analysis for Gene Ontology.2022. R package version 2.50.0. 48. Grote S: GOfuncR: Gene ontology enrichment using FUNC.2022. R package version 1.18.0. 49. Tianzhi W, Erqiang H, Shuangbin X, et al. : clusterProfiler 4.0: A universal enrichment tool for interpreting omics data. Innovation. August 2021; 2 (3): 100141. PubMed Abstract | Publisher Full Text | Free Full Text 50. Yu G: enrichplot: Visualization of Functional Enrichment Result.2022. R package version 1.18.3. 51. Gierlinski M, Gastaldello F, Cole C, et al. : Proteus: an r package for downstream analysis of MaxQuant output.September 2018. Publisher Full Text 52. Ranathunge C, Patel SS, Pinky L, et al. : promor: a comprehensive r package for label-free proteomics data analysis and predictive modeling.August 2022. Publisher Full Text 53. Quast J-P, Schuster D, Picotti P: protti: an r package for comprehensive data analysis of peptide- and protein-centric bottom-up proteomics data. Bioinform. Adv. December 2021; 2 (1). PubMed Abstract | Publisher Full Text | Free Full Text 54. Wolski WE, Nanni P, Grossmann J, et al. : prolfqua: A comprehensive r-package for proteomics differential expression analysis.June 2022. Publisher Full Text 55. Käll L, Canterbury JD, Weston J, et al. : Semi-supervised learning for peptide identification from shotgun proteomics datasets. Nat. Methods. October 2007; 4 (11): 923–925. PubMed Abstract | Publisher Full Text Comments on this article Comments (0) Version 2 VERSION 2 PUBLISHED 24 Oct 2023 ADD YOUR COMMENT Comment Author details Author details 1 Cambridge Centre for Proteomics, University of Cambridge, Cambridge, CB2 1QR, UK 2 Department of Biochemistry, University of Cambridge, Cambridge, CB2 1QR, UK Charlotte Hutchings Roles: Conceptualization, Data Curation, Formal Analysis, Investigation, Methodology, Project Administration, Software, Visualization, Writing – Original Draft Preparation, Writing – Review & Editing Charlotte S. Dawson Roles: Software, Writing – Review & Editing Thomas Krueger Roles: Methodology, Supervision, Writing – Review & Editing Kathryn S. Lilley Roles: Funding Acquisition, Supervision, Writing – Review & Editing Lisa M. Breckels Roles: Conceptualization, Methodology, Supervision, Writing – Review & Editing Competing interests No competing interests were disclosed. Grant information C. H. is funded through a BBSRC CASE award with AstraZeneca (BB/W509929/1). C. S. D. is funded by a Herchel Smith Research Studentship at the University of Cambridge, United Kingdom. T. K. is funded by a Gordon and Betty Moore Foundation Grant (#7872). K. S. L. is funded by Wellcome Trust (110071/Z/15/Z) and European Union Horizon 2020 program INFRAIA project EPIC-XS (project no.: 823839). L. M. B. is funded by European Union Horizon 2020 program INFRAIA project EPIC-XS (project no.: 823839). The funders had no role in study design, data collection and analysis, decision to publish, or preparation of the manuscript. The funders had no role in study design, data collection and analysis, decision to publish, or preparation of the manuscript. Article Versions (2) version 2 Revised Published: 25 Sep 2024, 12:1402 https://doi.org/10.12688/f1000research.139116.2 version 1 Published: 24 Oct 2023, 12:1402 https://doi.org/10.12688/f1000research.139116.1 Copyright © 2024 Hutchings C et al . This is an open access article distributed under the terms of the Creative Commons Attribution License , which permits unrestricted use, distribution, and reproduction in any medium, provided the original work is properly cited. Download Export To Sciwheel Bibtex EndNote ProCite Ref. Manager (RIS) Sente metrics Views Downloads F1000Research - - PubMed Central info_outline Data from PMC are received and updated monthly. - - Citations open_in_new 0 open_in_new 0 open_in_new SEE MORE DETAILS CITE how to cite this article Hutchings C, Dawson CS, Krueger T et al. A Bioconductor workflow for processing, evaluating, and interpreting expression proteomics data [version 2; peer review: 4 approved, 1 approved with reservations] . F1000Research 2024, 12 :1402 ( https://doi.org/10.12688/f1000research.139116.2 ) NOTE: If applicable, it is important to ensure the information in square brackets after the title is included in all citations of this article. COPY CITATION DETAILS track receive updates on this article Track an article to receive email alerts on any updates to this article. TRACK THIS ARTICLE Share Open Peer Review Current Reviewer Status: ? Key to Reviewer Statuses VIEW HIDE Approved The paper is scientifically sound in its current form and only minor, if any, improvements are suggested Approved with reservations A number of small changes, sometimes more significant revisions are required to address specific details and improve the papers academic merit. Not approved Fundamental flaws in the paper seriously undermine the findings and conclusions Version 2 VERSION 2 PUBLISHED 25 Sep 2024 Revised Views 0 Cite How to cite this report: Bender J. Reviewer Report For: A Bioconductor workflow for processing, evaluating, and interpreting expression proteomics data [version 2; peer review: 4 approved, 1 approved with reservations] . F1000Research 2024, 12 :1402 ( https://doi.org/10.5256/f1000research.168933.r357398 ) The direct URL for this report is: https://f1000research.com/articles/12-1402/v2#referee-response-357398 NOTE: it is important to ensure the information in square brackets after the title is included in this citation. Close Copy Citation Details Reviewer Report 06 Feb 2025 Julian Bender , Wuerzburg University, Würzburg, Germany Approved VIEWS 0 https://doi.org/10.5256/f1000research.168933.r357398 The present article describes an R-based workflow for processing database search results from data-dependent analyses of label-free and TMT-labelled experiments generated with the ProteomeDiscoverer software (including a note describing how to transfer to results produced with the MaxQuant software) . The ... Continue reading READ ALL The present article describes an R-based workflow for processing database search results from data-dependent analyses of label-free and TMT-labelled experiments generated with the ProteomeDiscoverer software (including a note describing how to transfer to results produced with the MaxQuant software) . The workflow employs readily available and well-documented R packages from the Bioconductor repository, facilitating both reproduction and adaptation. Moreover, the manuscript emphasises the use of the relatively recent QFeatures package to ensure result consistency across aggregation levels. The manuscript is well written, and the figures are concise, informative, and aligned with the text's argument. The authors not only present a robust approach for generating figures relevant to the biological interpretation of MS results (e.g., volcano and MA plots) but also include quality control metrics and data inspection guidelines. This enables users to tailor the workflow to their dataset, improving the generated results while also promoting critical evaluation. The code, search results, and raw files are available through Zenodo and PRIDE , respectively. I am fully confident that the manuscript is scientifically sound as it stands. Please consider the following comments as suggestions for further improvement. Major comments p. 6, Description of QFeatures and SummarizedExperiment: Since the SummarizedExperiment object is crucial for understanding the workflow, I suggest a more detailed explanation of its function. In particular, emphasis should be placed on describing colData and rowData as DataTables with row indices matching the assay’s row or column names, respectively. Additionally, the SummarizedExperiment container is described as having three components ( rowData , colData , assays ), yet Figure 2 also includes the metadata object as a fourth component. I recommend mentioning this in the text. p. 15: “Here, it is desirable to achieve an average MS2 injection time of 50 ms or less, although the exact target threshold will depend upon the sample load.” It should be noted that the maximum IT time is set in the instrument parameters for each MS run and should be optimised in relation to a specific AGC target (for Orbitrap instruments) by the instrument operator. Therefore, in the QC plot on p. 16, it is impossible to reach an average IT time exceeding 50 ms, as the maximum IT time is set to 50 ms. Instead, I suggest warning users that frequently reaching the maximum IT time during an MS run may indicate either an excessively high AGC target or insufficient ion current. p. 20, Calculation of TMT labelling efficiency: From an experimental perspective, I suggest calculating labelling efficiency per label (i.e., separately for TMT-126, TMT-127, etc.). This would help identify poor performance of individual labels (e.g., due to reagent hydrolysis). Furthermore, if the labelling test was performed after pooling only a subset of the available peptides, and sufficient peptide material remains, this approach would allow relabelling the underperforming sample before continuing with the analysis. p. 28, Assignment of FDR based on existing search results: The workflow suggests filtering PSMs by propagating peptide- or protein group-level FDR values to the underlying PSMs. However, PSMs may be aggregated differently in downstream analyses compared to the initial ProteomeDiscoverer search (e.g., based on gene names rather than master proteins), leading to uncontrolled FDR. Wouldn't it be more precise to retain decoys in the initial PSM table and perform FDR control separately at each aggregation level? Minor comments p. 4: “the exact details of which are anonymised for the purpose of this workflow” – Is there a specific reason not to disclose the exact perturbation analysed in this workflow? While this is not crucial for the analysis pipeline, it would be useful to verify known targets of the perturbation in the resulting volcano plot as an additional validation step. p. 11 and p. 50: “## Assign the colData to the first assay as well” – From this, I understand that both the QFeatures object and the nested SummarizedExperiment objects contain a colData attribute, and both need to be populated. This could be clarified in the introduction of QFeatures on p. 7. p. 12, Calculation of peptide and protein group numbers: The introduction highlights QFeatures ' ability to easily aggregate from the PSM to peptide and protein group levels. However, the number of peptides and protein groups is instead calculated from unique entries in the PSM table. A brief explanation that this avoids repeated QFeatures aggregation after each filtering step (which would clutter the QFeatures object) would aid the reader to understand the workflow at this position of the manuscript. p. 16: “Increasing the time allowed for ions to accumulate in the ion trap could also increase the number of PSMs.” – This is not necessarily the case, as a longer MS2 IT accumulation time reduces the number of ions targeted for MS2, which could ultimately decrease the number of PSMs. To facilitate interpretation, plotting the percentage of identified MS2 spectra against retention time might be helpful. p. 17, “PSM frequency across retention time”: It could be noted that a roughly uniform PSM distribution generally indicates a well defined LC gradient. Conversely, an increased PSM count at a particular gradient point suggests many peptides eluting simultaneously, which could be mitigated by flattening the gradient at this position. p. 17: “To demonstrate how to check for TMT labelling efficiency, only two of the eight fractions were utilised for this search.” – Based on the column names on p. 18, there seems to be no reference to individual fractions or raw files in the search results. Would the results and hence the analysis have differed if all eight fractions had been included? p. 74: “When plotting the former, users are advised to plot raw p-values rather than their derivative BH-adjusted p-values.” – What is the rationale for this recommendation? A brief explanation in the manuscript would be helpful. Is the rationale for developing the new software tool clearly explained? Yes Is the description of the software tool technically sound? Yes Are sufficient details of the code, methods and analysis (if applicable) provided to allow replication of the software development and its use by others? Yes Is sufficient information provided to allow interpretation of the expected output datasets and any results generated using the tool? Yes Are the conclusions about the tool and its performance adequately supported by the findings presented in the article? Yes Competing Interests: No competing interests were disclosed. Reviewer Expertise: I work on MS-based functional and structural (XL-MS, native MS) proteomics with a focus on data processing and computational analysis. I am developing software for data analysis downstream of database searches using Python and R as framework. I confirm that I have read this submission and believe that I have an appropriate level of expertise to confirm that it is of an acceptable scientific standard. Close READ LESS CITE CITE HOW TO CITE THIS REPORT Bender J. Reviewer Report For: A Bioconductor workflow for processing, evaluating, and interpreting expression proteomics data [version 2; peer review: 4 approved, 1 approved with reservations] . F1000Research 2024, 12 :1402 ( https://doi.org/10.5256/f1000research.168933.r357398 ) The direct URL for this report is: https://f1000research.com/articles/12-1402/v2#referee-response-357398 NOTE: it is important to ensure the information in square brackets after the title is included in all citations of this article. COPY CITATION DETAILS Report a concern Respond or Comment COMMENT ON THIS REPORT Views 0 Cite How to cite this report: Quentin GG. Reviewer Report For: A Bioconductor workflow for processing, evaluating, and interpreting expression proteomics data [version 2; peer review: 4 approved, 1 approved with reservations] . F1000Research 2024, 12 :1402 ( https://doi.org/10.5256/f1000research.168933.r357415 ) The direct URL for this report is: https://f1000research.com/articles/12-1402/v2#referee-response-357415 NOTE: it is important to ensure the information in square brackets after the title is included in this citation. Close Copy Citation Details Reviewer Report 22 Jan 2025 Giai Gianetto Quentin , University Paris Cité, Paris, Île-de-France, France Approved with Reservations VIEWS 0 https://doi.org/10.5256/f1000research.168933.r357415 The article titled " A Bioconductor Workflow for Processing, Evaluating, and Interpreting Expression Proteomics Data " provides a detailed workflow for quantitative proteomics data analysis using R. The analysis of proteomics data is composed of many steps, and this paper presents a ... Continue reading READ ALL The article titled " A Bioconductor Workflow for Processing, Evaluating, and Interpreting Expression Proteomics Data " provides a detailed workflow for quantitative proteomics data analysis using R. The analysis of proteomics data is composed of many steps, and this paper presents a detailed application for quality control of acquired data, data filtering, and differential analysis using already published R packages from Proteome Discoverer outputs. Readers interested in conducting an in-depth analysis of their data can use the provided example as a foundation and adapt it to their own datasets. Comments : 1) I understand the value of presenting a complete workflow where each step is discussed in detail. However, the paper is not associated with a new R package and does not introduce novel methods for handling mass spectrometry-based proteomics data. As a result, it is unclear what is new or original about the proposed workflow. It would be helpful to provide clarification in the introduction to clearly highlight the workflow's originality. 2) To improve readability, the structure of the paper should be explained in the introduction. Since the paper exceeds 80 pages, outlining its structure is essential. The authors should include numbered sections and subsections to make it easier for readers to navigate and follow the content. 3) Figures do not have legends. They should be associated to a legend and references to them should be made in the text. 4) In several cases, the authors have included the output of R code as comments. This significantly increases the length of the paper without necessarily adding value. The paper would be more concise and readable if these outputs were included only when they are relevant and accompanied by explanatory commentary from the authors. For instance, on page 9 of the PDF, the output following the use of readQFeatures is useless, or the calls to cp_qf[[...]] seem redundant as they provide identical results. Similarly, pages 49 and 51 are filled with column names that do not appear to offer any meaningful insight. This issue occurs throughout the paper and does not benefit the reader. The authors should work to be more concise. 5) The section "Quality control of the raw mass spectrometry data" presents plots designed to assess data quality. At the end of the section, it is stated: "The four plots that we have generated look relatively standard with no obvious problems indicated.". Could the authors clarify how potential issues can be identified using these plots? For instance, the MS2 ion injection times fixed at 50 ms appear insufficient based on the plots in this section, which seems to contradict the authors' sentence. Also, R packages, such as PTXQC or proteoQC, can be used to investigate quality control of MS-based proteomics data using many metrics with R. The paper should mention some of them. 6) A number of arbitrary thresholds are used along the workflow for data filtering and statistical analysis. To ensure transparency and emphasize the parameters employed in the workflow, all these thresholds should be compiled into a readable table. This is particularly important, as such thresholds can significantly impact the final interpretation of the data. Being arbitrary, they are open to debate and warrant clear documentation. 7) On page 42 of the PDF, the authors apply a normalization method using median-centering. Based on the graph provided, it appears that the method reduces the differences in abundance between the « treated » and « control » samples, while « treated » ones generally seem to have lower overall abundances compared to the « control » samples before normalisation. Thus, this type of normalization risks missing proteins that are more abundant in the « control » samples. Would it not be better to preserve the observed gap between conditions and apply normalization within each condition while maintaining the observed overall difference between conditions? A discussion on this point needs to be provided. 8) In the part « Visualising aggregation », the paper lacks an explanation of the importance and relevance of visualizing this process. Including such an explanation would help readers understand why this visualization is essential and how it contributes to the overall analysis. For example, it could clarify how visualizing aggregation helps identify potential issues during data processing. 9) The conclusion states: « Existing bottom-up proteomics workflows for differential expression analysis either provide pipelines with limited user control and flexibility (e.g., MSstats and MSstatsTMT 34 , 35 ), can only be applied to specific data formats (e.g., Proteus which is limited to input from MaxQuant 51 ), or provide very limited commentary. ». However, this assertion appears arbitrary and is not supported by clear arguments. The authors should clarify what they mean by “limited.” For instance, MSstats and MSstatsTMT offer accessible tutorials and vignettes, which seem to provide sufficient explanations and flexibility for users. Regarding data formats, the authors wrote: « Finally, the majority of proteomics workflows utilise data.frame or tibble structures which limits their traceability, as is the case for protti, promor, and prolfqua. ». This statement is unclear. What exactly is the issue with using these structures? The authors themselves use tibble datasets all along their workflow, similar to the other packages (and not workflows) mentioned. This point needs further explanation to clarify what specific limitations the authors are referring to. In the conclusion, the authors state: “No single workflow can demonstrate the processing, analysis, and interpretation of all proteomics data.” However, it is unclear whether they are claiming to provide the first workflow capable of achieving this or not. From my perspective, their workflow relies heavily on several existing R packages that address specific key aspects, and the authors have leveraged these to construct their workflow. Furthermore, the workflow seems specifically tailored to their dataset, making it less of a universal approach and not something that can be directly applied to other datasets without modification. The authors should consider revising their wording to clarify what aspects of their workflow are intended to be universal, as this is currently unclear. Is the rationale for developing the new software tool clearly explained? Yes Is the description of the software tool technically sound? Yes Are sufficient details of the code, methods and analysis (if applicable) provided to allow replication of the software development and its use by others? Yes Is sufficient information provided to allow interpretation of the expected output datasets and any results generated using the tool? Yes Are the conclusions about the tool and its performance adequately supported by the findings presented in the article? Partly Competing Interests: No competing interests were disclosed. Reviewer Expertise: Biostatistics, bioinformatics I confirm that I have read this submission and believe that I have an appropriate level of expertise to confirm that it is of an acceptable scientific standard, however I have significant reservations, as outlined above. Close READ LESS CITE CITE HOW TO CITE THIS REPORT Quentin GG. Reviewer Report For: A Bioconductor workflow for processing, evaluating, and interpreting expression proteomics data [version 2; peer review: 4 approved, 1 approved with reservations] . F1000Research 2024, 12 :1402 ( https://doi.org/10.5256/f1000research.168933.r357415 ) The direct URL for this report is: https://f1000research.com/articles/12-1402/v2#referee-response-357415 NOTE: it is important to ensure the information in square brackets after the title is included in all citations of this article. COPY CITATION DETAILS Report a concern Respond or Comment COMMENT ON THIS REPORT Version 1 VERSION 1 PUBLISHED 24 Oct 2023 Views 0 Cite How to cite this report: Yadav AK. Reviewer Report For: A Bioconductor workflow for processing, evaluating, and interpreting expression proteomics data [version 2; peer review: 4 approved, 1 approved with reservations] . F1000Research 2024, 12 :1402 ( https://doi.org/10.5256/f1000research.152361.r221408 ) The direct URL for this report is: https://f1000research.com/articles/12-1402/v1#referee-response-221408 NOTE: it is important to ensure the information in square brackets after the title is included in this citation. Close Copy Citation Details Reviewer Report 18 Dec 2023 Amit Kumar Yadav , Translational Health Science and Technology Institute (THSTI), Faridabad, Haryana, India Approved VIEWS 0 https://doi.org/10.5256/f1000research.152361.r221408 The article by Hutchings et al titled "A Bioconductor Workflow for Processing, Evaluating, and Interpreting Expression Proteomics Data" provides a detailed overview tutorial of the interpretation of quantitative proteomics data through R environment using TMT and LFQ workflows as examples. ... Continue reading READ ALL The article by Hutchings et al titled "A Bioconductor Workflow for Processing, Evaluating, and Interpreting Expression Proteomics Data" provides a detailed overview tutorial of the interpretation of quantitative proteomics data through R environment using TMT and LFQ workflows as examples. Major comments: The use of open-source tools ensures transparency and reproducibility. The open-source R software packages from the Bioconductor project also add credibility to the workflow. The workflow described is comprehensive and is a good tutorial for analysis. The article describes the comprehensive workflow with R commands, covering data import, quality control, differential expression analysis, and gene ontology enrichment analysis. This approach ensures a holistic understanding of expression proteomics. The described use-case examples from TMT and LFQ provides practical relevance and enhances the applicability of the workflow. The target audience is for beginners who are also familiar with R. It may also be helpful to optionally provide shiny app (for GUI based application) that biologists who are unfamiliar with CLI, can also use. Minor Comments: This article deals with Proteome Discoverer output. Maybe inclusion of MaxQuant or other workflows may add to it reach. The difference between razor and shared peptides is not clear. Perhaps rephrasing would help a newcomer to proteomics. Page 40, (Under section Visualising Aggregation) “…15 peptides and 27 supporting…”. Did the author mean 27 PSMs? It is missing in the sentence. Please clarify if these were peptides or PSMs? PCA is not considered fit when there are lot of missing values as in LFQ analysis. Should these be removed before PCA? Authors have conflated modified and non-modified forms of the same peptides during analysis. This may not be able to detect modified changes if differential in nature. Perhaps “quantitative proteomics” is a more appropriate term than “Expression proteomics”. The article appears to be a valuable contribution to the field of quantitative proteomics, especially for R users, providing a comprehensive and user-friendly workflow. Is the rationale for developing the new software tool clearly explained? Yes Is the description of the software tool technically sound? Yes Are sufficient details of the code, methods and analysis (if applicable) provided to allow replication of the software development and its use by others? Yes Is sufficient information provided to allow interpretation of the expected output datasets and any results generated using the tool? Yes Are the conclusions about the tool and its performance adequately supported by the findings presented in the article? Yes Competing Interests: No competing interests were disclosed. Reviewer Expertise: quantitative proteomics, bioinformatics, computational biology, proteome informatics I confirm that I have read this submission and believe that I have an appropriate level of expertise to confirm that it is of an acceptable scientific standard. Close READ LESS CITE CITE HOW TO CITE THIS REPORT Yadav AK. Reviewer Report For: A Bioconductor workflow for processing, evaluating, and interpreting expression proteomics data [version 2; peer review: 4 approved, 1 approved with reservations] . F1000Research 2024, 12 :1402 ( https://doi.org/10.5256/f1000research.152361.r221408 ) The direct URL for this report is: https://f1000research.com/articles/12-1402/v1#referee-response-221408 NOTE: it is important to ensure the information in square brackets after the title is included in all citations of this article. COPY CITATION DETAILS Report a concern Author Response 25 Sep 2024 Lisa Breckels , Cambridge Centre for Proteomics, University of Cambridge, Cambridge, CB2 1QR, UK 25 Sep 2024 Author Response We would like to thank Dr. Yadav for reviewing our workflow paper and providing positive feedback. In response to Dr. Yadav’s minor comments, we have provided additional information on how ... Continue reading We would like to thank Dr. Yadav for reviewing our workflow paper and providing positive feedback. In response to Dr. Yadav’s minor comments, we have provided additional information on how to use this workflow with output from MaxQuant. This information can be found in a new section in the Appendix of our Github repository and is mentioned explicitly in the workflow. The sentence regarding shared and unique peptides has been changed slightly and additional discussion added to emphasise how protein inference and presence of isoforms can alter the definition of ‘unique’ peptides. We agree that missing values need to be addressed before performing PCA and as such in the workflow we use the function filterNA in QFeatures to remove missing data prior to any PCA performed. We have also explicitly stated that we conflate modified and non-modified forms of each peptides, and that users could aggregate by “Annotated. Sequence” if they wish to retain this information. However, the discovery of differences in the behaviour of these peptides would require peptide-level statistical analyses, which is outside of the scope of this workflow. We would like to thank Dr. Yadav for reviewing our workflow paper and providing positive feedback. In response to Dr. Yadav’s minor comments, we have provided additional information on how to use this workflow with output from MaxQuant. This information can be found in a new section in the Appendix of our Github repository and is mentioned explicitly in the workflow. The sentence regarding shared and unique peptides has been changed slightly and additional discussion added to emphasise how protein inference and presence of isoforms can alter the definition of ‘unique’ peptides. We agree that missing values need to be addressed before performing PCA and as such in the workflow we use the function filterNA in QFeatures to remove missing data prior to any PCA performed. We have also explicitly stated that we conflate modified and non-modified forms of each peptides, and that users could aggregate by “Annotated. Sequence” if they wish to retain this information. However, the discovery of differences in the behaviour of these peptides would require peptide-level statistical analyses, which is outside of the scope of this workflow. Competing Interests: No competing interests were disclosed. Close Report a concern Respond or Comment COMMENTS ON THIS REPORT Author Response 25 Sep 2024 Lisa Breckels , Cambridge Centre for Proteomics, University of Cambridge, Cambridge, CB2 1QR, UK 25 Sep 2024 Author Response We would like to thank Dr. Yadav for reviewing our workflow paper and providing positive feedback. In response to Dr. Yadav’s minor comments, we have provided additional information on how ... Continue reading We would like to thank Dr. Yadav for reviewing our workflow paper and providing positive feedback. In response to Dr. Yadav’s minor comments, we have provided additional information on how to use this workflow with output from MaxQuant. This information can be found in a new section in the Appendix of our Github repository and is mentioned explicitly in the workflow. The sentence regarding shared and unique peptides has been changed slightly and additional discussion added to emphasise how protein inference and presence of isoforms can alter the definition of ‘unique’ peptides. We agree that missing values need to be addressed before performing PCA and as such in the workflow we use the function filterNA in QFeatures to remove missing data prior to any PCA performed. We have also explicitly stated that we conflate modified and non-modified forms of each peptides, and that users could aggregate by “Annotated. Sequence” if they wish to retain this information. However, the discovery of differences in the behaviour of these peptides would require peptide-level statistical analyses, which is outside of the scope of this workflow. We would like to thank Dr. Yadav for reviewing our workflow paper and providing positive feedback. In response to Dr. Yadav’s minor comments, we have provided additional information on how to use this workflow with output from MaxQuant. This information can be found in a new section in the Appendix of our Github repository and is mentioned explicitly in the workflow. The sentence regarding shared and unique peptides has been changed slightly and additional discussion added to emphasise how protein inference and presence of isoforms can alter the definition of ‘unique’ peptides. We agree that missing values need to be addressed before performing PCA and as such in the workflow we use the function filterNA in QFeatures to remove missing data prior to any PCA performed. We have also explicitly stated that we conflate modified and non-modified forms of each peptides, and that users could aggregate by “Annotated. Sequence” if they wish to retain this information. However, the discovery of differences in the behaviour of these peptides would require peptide-level statistical analyses, which is outside of the scope of this workflow. Competing Interests: No competing interests were disclosed. Close Report a concern COMMENT ON THIS REPORT Views 0 Cite How to cite this report: Locard-Paulet M. Reviewer Report For: A Bioconductor workflow for processing, evaluating, and interpreting expression proteomics data [version 2; peer review: 4 approved, 1 approved with reservations] . F1000Research 2024, 12 :1402 ( https://doi.org/10.5256/f1000research.152361.r221410 ) The direct URL for this report is: https://f1000research.com/articles/12-1402/v1#referee-response-221410 NOTE: it is important to ensure the information in square brackets after the title is included in this citation. Close Copy Citation Details Reviewer Report 27 Nov 2023 Marie Locard-Paulet , Institut de Pharmacologie et de Biologie Structurale (IPBS), Toulouse, France; Université Toulouse III - Paul Sabatier (UT3), Toulouse, France Approved VIEWS 0 https://doi.org/10.5256/f1000research.152361.r221410 The authors provide the full description of a R-based workflow applied to quantitative proteomics data analysis (TMT and label-free data). It makes use of QFeature objects, a structure that is very well suited for bottom-up proteomics data analysis. I think ... Continue reading READ ALL The authors provide the full description of a R-based workflow applied to quantitative proteomics data analysis (TMT and label-free data). It makes use of QFeature objects, a structure that is very well suited for bottom-up proteomics data analysis. I think that this is a very nice step-by-step tutorial for MS-based proteomics data analysis with R for people who start in the field and have limited coding skills. Beyond its educational aspect, it provides the backbones of a data analysis pipeline that can be modified and published alongside any manuscript that includes MS-based proteomics data analysis. The manuscript is very well written, and the authors provide very clear and detailed instructions on how to use the workflow. The figures are also very clear and informative. They present the data, detail what quality control to perform to assess if the data are suitable for statistical analysis. This workflow contains a lot of useful QC plots and checks that are often overlooked, including TMT labelling efficiency calculation. It makes it a good step-by-step guide on how to analyze TMT-labelled bottom-up data. I really like the description on how to double check quality metrics such as S/N and isolation interference to adapt them to the data. The raw data is available in PRIDE and all the fasta files and the Proteome Discoverer output files are in Zenodo. The code is in a github repository. I easily found all the data associated with this manuscript. Major comments: It should be made clear that this script is tailored for Proteome Discoverer outputs (and maybe even for a given version of Proteome Discoverer). For most of the plotting/filtering/analysis steps, changing input would only require adapting the column names/headers, and most of the time it is very well discussed by the authors. Nevertheless, right now this script is only adapted to Proteome Discoverer outputs and this should be made clear in the abstract and the introduction, as well as the discussion. Aggregation of PSM quantification values to peptides and proteins: Here, the authors choose to aggregate all PSM intensities corresponding to the same sequence (stripped of its modifications). I would aggregate the PSM quantities per peptidoform (sequence + localized modifications) since two ions can have the same sequence but with modifications that are differentially regulated between the conditions compared. This should be mentioned. For the GO-term enrichment: only the majority protein accessions are reported in the output of the limma analysis. So there is only one gene per feature. How do you make sure that it is the most representative annotation for a given protein group? I am fully aware that this issue is ignored by the community (for lack of alternative strategy), and that most of the time people just pick one accession per group for GO-term enrichment analysis. So, I am not asking the authors to find a solution. Nevertheless, it would be nice to mention that the output of the enrichment will depend on what accession is picked per group. Minor comments: I would remove contaminants before estimation of TMT labelling efficiency. I find the paragraph “Additional considerations regarding protein isoforms” unclear. The authors should rephrase sentences such as this one: “PSMs or peptides that were previously mapped to one protein and one protein group could instead be mapped to multiple proteins and one protein group.” Maybe they should use the term “canonical protein” to be more precise? In any cases, the issue of peptide uniqueness does not depend only on the presence of isoforms in the fasta file but also on the strategy that was chosen for protein inference. I agree with the authors that people should precisely describe what peptides/PSMs were used for quantification, and it is good to mention it. Nevertheless, this level of detail on general MS-based proteomics concept may not be necessary here. (So the entire paragraph on isoforms could maybe be removed, especially since isoforms are not mentioned later). In the paragraph “Removing PSMs that are not rank 1”: I think that the “PSM category” that is discussed a bit later is specific of Proteome Discoverer. Some search engines report PSMs of equal score (this would correspond to the “pretty rank” in Mascot). I don’t think that all this should necessarily be discussed in this manuscript, but I insist on the fact that the workflow is tuned for Proteome Discoverer output and this should be made clear in the introduction/abstract. In the paragraph “Managing missing data” for the TMT: the authors mention MCAR, MAR, and MNAR, but do they all apply here? I would expect TMT-labelled data to mostly have missing values due to ions being under the limit of detection because when an ion is fragmented, the reporter ions used for relative quantification are often all detected. Isn’t it the case? Knowing this should restrict the choice for a more suited strategy of replacement of missing values. Still on missing values: page 33, it is stated that “Typically, it is desirable to remove features, here PSMs, with greater than 20% missing values”. Why this number? Is this accepted by the entire community? (this comment also applies to the same step in the LFQ analysis. Regarding missing value replacement (discussion on LFQ, page 55): it is really nice to provide references of strategies applied to replacement of missing values. It is indeed a tricky decision to make (how to replace? Should we replace?) and there is no one-size-fits-them-all method. Why do you choose to replace at peptide level and not protein level? Page 38: what do the authors mean by “report did not indicate any superior normalization method”? How would we know what normalization method works best? This point is because I am curious, not to correct any obvious mistake. It is great to try out different normalization strategies, but I don’t really see how to pick one based on the boxplots of normalized intensities (Figure 4). The authors normalize the data after protein aggregation and not at the PSM level. Is this general practice? Wouldn’t it make sense to normalize before aggregation? Page 44; “Data import, housekeeping and exploration”: the authors mention that LFQ analysis cannot be performed at PSM level but has to be done at peptide level. I think that this is dependent on the software tool that is used, and this may be specific of Proteome Discoverer. Match between run is performed at the ion level, but the intensity retrieved at this step can be reported at PSM level. I think that this is the case in MaxQuant “evidence.txt” tables, if I am not mistaken. Page 63: DEqMS could be mentioned since it is specifically developed for proteomics statistical analysis. (DOI: 10.1074/mcp.TIR119.001646) This is more of a naïve question regarding using Limma in this context: does it make sense to model the variance depending on intensity after missing value replacement? I know that this manuscript may not be the place to discuss this, but I would be interested to know what the authors’ opinion is on this question. Additional suggestions (only suggestions that may totally be ignored/dismissed by the authors if they don’t think that they’ll improve their manuscript): The data is available in PRIDE (PXD041794), but the information necessary to match TMT channel/sample to conditions/replicates is only available in the associated paper. It would be great to add the Table 1 of the manuscript and a link to the zenodo repository in PRIDE alongside the data. An even better solution would be to provide the metadata in the SDRF-Proteomics format ( https://www.nature.com/articles/s41467-021-26111-3 ; there is a GUI to generate these files now: https://lessdrf.streamlit.app/). This would facilitate data reuse and transparency. Small comments / typos: Page 3, in the code at the bottom of the page: the “,” is missing after “stringr”. Paragraph "Assessing the impact of non-specific data cleaning”, in the table (and other similar tables or mentions of number of protein groups and peptide stripped sequences): “proteins” should be replaced by “protein groups” since this is what is actually counted. If the authors wanted to be more precise, they could also specify that the “peptides” correspond to peptide sequences stripped of all modifications. Bar plot of missing value proportion page 32: what does the red dashed line correspond to? Page 37, when running the function `normalizer`, I got an error “No RT column specified (column named 'RT') or option not specified Skipping RT normalization.” And could not get the expected report. I am not familiar with the tool and did not investigate further. I don’t think that “softwares” can be used. There is no “s” at the end. Page 51: “cleaning is done is two steps” should be “cleaning is done in two steps” Page 54: in the bar plot of missing value count, what is the dashed red line? Page 55: “If the method requires data to display a normal distribution, users must log2 transform the data prior to imputation.” -> is there a reason to perform missing values replacement before log transformation? If not, this step could be moved to after log transform? Page 66: “If we had not used TMT labels and wished to include a logFC threshold, we could have included lfc = as an argument”. The characters of “ lfc = as ” are in a different police, I think that this is a bit unclear since the “as” should be regular text. Also, maybe you could explain “have included lfc = followed by the minimum absolute log2-transformed fold change”. Page 72: “summarize all packages and corresponding their versions used to generate” -> the sentence does not seem correct to me. Is the rationale for developing the new software tool clearly explained? Yes Is the description of the software tool technically sound? Yes Are sufficient details of the code, methods and analysis (if applicable) provided to allow replication of the software development and its use by others? Yes Is sufficient information provided to allow interpretation of the expected output datasets and any results generated using the tool? Yes Are the conclusions about the tool and its performance adequately supported by the findings presented in the article? Yes Competing Interests: No competing interests were disclosed. Reviewer Expertise: I work on MS-based proteomics data analysis and computational mass spectrometry. I confirm that I have read this submission and believe that I have an appropriate level of expertise to confirm that it is of an acceptable scientific standard. Close READ LESS CITE CITE HOW TO CITE THIS REPORT Locard-Paulet M. Reviewer Report For: A Bioconductor workflow for processing, evaluating, and interpreting expression proteomics data [version 2; peer review: 4 approved, 1 approved with reservations] . F1000Research 2024, 12 :1402 ( https://doi.org/10.5256/f1000research.152361.r221410 ) The direct URL for this report is: https://f1000research.com/articles/12-1402/v1#referee-response-221410 NOTE: it is important to ensure the information in square brackets after the title is included in all citations of this article. COPY CITATION DETAILS Report a concern Author Response 25 Sep 2024 Lisa Breckels , Cambridge Centre for Proteomics, University of Cambridge, Cambridge, CB2 1QR, UK 25 Sep 2024 Author Response We thank Dr Locard-Paulet for her positive comments and have answered her additional comments below. Reviewer Comments: Major comments: It should be made clear that this ... Continue reading We thank Dr Locard-Paulet for her positive comments and have answered her additional comments below. Reviewer Comments: Major comments: It should be made clear that this script is tailored for Proteome Discoverer outputs (and maybe even for a given version of Proteome Discoverer). For most of the plotting/filtering/analysis steps, changing input would only require adapting the column names/headers, and most of the time it is very well discussed by the authors. Nevertheless, right now this script is only adapted to Proteome Discoverer outputs and this should be made clear in the abstract and the introduction, as well as the discussion. Author Response: We appreciate that both use-case datasets in this workflow were processed using Proteome Discoverer and have added text to emphasise this further in the abstract and introduction. Nevertheless, we feel that the workflow is still useful to users of alternative third-party software as the general data processing steps, and extensive discussion of these, remains relevant. To help users make the most out of this workflow, we have provided information on how to adapt the workflow from Proteome Discoverer files to those generated by MaxQuant, a free and accessible search software. This information is provided in a new section in the Appendix of our Github repository. Reviewer Comments: Aggregation of PSM quantification values to peptides and proteins: Here, the authors choose to aggregate all PSM intensities corresponding to the same sequence (stripped of its modifications). I would aggregate the PSM quantities per peptidoform (sequence + localized modifications) since two ions can have the same sequence but with modifications that are differentially regulated between the conditions compared. This should be mentioned. Author Response: As Dr Locard-Paulet mentions, it is possible for the same peptide sequence with and without modifications to behave differently. We have added the following to the workflow to acknowledge this: “For simplicity, we here aggregate all PSMs corresponding to the same stripped peptide sequence, regardless of whether they contain different modifications. If users are interested in exploring differential expression of protein isoforms or have reason to believe that post-translational modifications may be important in answering their question, PSMs could also be aggregated by "Annotated.Sequence" to preserve this information.” We agree that this point is worth drawing attention to. In order to observe any differential abundance of peptides when modified, statistical analysis would need to be carried out at the peptide-level. Since this is outside of the scope of this workflow, we continue to aggregate using the stripped sequence column to facilitate statistical analysis at the protein level. Reviewer Comments: For the GO-term enrichment: only the majority protein accessions are reported in the output of the limma analysis. So there is only one gene per feature. How do you make sure that it is the most representative annotation for a given protein group? I am fully aware that this issue is ignored by the community (for lack of alternative strategy), and that most of the time people just pick one accession per group for GO-term enrichment analysis. So, I am not asking the authors to find a solution. Nevertheless, it would be nice to mention that the output of the enrichment will depend on what accession is picked per group. Author Response: We agree with and acknowledge this point. Indeed, it is a limitation of protein inference that results in statistics and interpretation being done at the level of protein groups rather than individual proteins. As a result, we would always encourage users to explore their statistical hits, particularly those of interest for follow up. This would include tracing the protein group back down all data levels and potentially plotting an aggregation graph, as demonstrated in “Exploration of data using QFeatures links”. With regard to the output of GO enrichment, we do not expect the overall biological interpretation to be dramatically skewed as only protein lists with multiple proteins with the same GO annotation will be considered enriched. Therefore, even if a few of the master proteins are not representative of the protein which is actually changing in abundance, these few cases are unlikely to cause an incorrect enrichment. Nevertheless, it is always worthwhile for the user to examine the results to verify correct interpretation. Reviewer Comments: Minor comments: I would remove contaminants before estimation of TMT labelling efficiency. I find the paragraph “Additional considerations regarding protein isoforms” unclear. The authors should rephrase sentences such as this one: “PSMs or peptides that were previously mapped to one protein and one protein group could instead be mapped to multiple proteins and one protein group.” Maybe they should use the term “canonical protein” to be more precise? In any cases, the issue of peptide uniqueness does not depend only on the presence of isoforms in the fasta file but also on the strategy that was chosen for protein inference. I agree with the authors that people should precisely describe what peptides/PSMs were used for quantification, and it is good to mention it. Nevertheless, this level of detail on general MS-based proteomics concept may not be necessary here. (So the entire paragraph on isoforms could maybe be removed, especially since isoforms are not mentioned later). Author Response: We thank Dr Locard-Paulet for her input on this complex issue. We agree that for a beginner-level workflow, the discussion of isoforms may be confusing. We have removed the paragraph about isoforms, whilst adding some further comment on the importance of defining uniqueness above. Reviewer Comments: In the paragraph “Removing PSMs that are not rank 1”: I think that the “PSM category” that is discussed a bit later is specific of Proteome Discoverer. Some search engines report PSMs of equal score (this would correspond to the “pretty rank” in Mascot). I don’t think that all this should necessarily be discussed in this manuscript, but I insist on the fact that the workflow is tuned for Proteome Discoverer output and this should be made clear in the introduction/abstract. Author Response: We have included additional emphasis on Proteome Discoverer in the introduction to this workflow. That said, users of alternative software will still benefit from being aware of the concept of ‘PSM rank’. Reviewer Comments: In the paragraph “Managing missing data” for the TMT: the authors mention MCAR, MAR, and MNAR, but do they all apply here? I would expect TMT-labelled data to mostly have missing values due to ions being under the limit of detection because when an ion is fragmented, the reporter ions used for relative quantification are often all detected. Isn’t it the case? Knowing this should restrict the choice for a more suited strategy of replacement of missing values. Author Response: Indeed, knowing the reason behind missing values is important in deciding upon an imputation method. We have added an additional few sentences to outline this in the “Imputation” section of the TMT workflow. Nonetheless, we still wish to emphasise that in the use-case, and most datasets with such little missingness, it is not necessary to impute. Additional discussion has also been added under “The importance of knowing what you expect in missing values” to ensure that users consider their experimental design and quantitation strategy when assessing and dealing with missing values. Reviewer Comments: Still on missing values: page 33, it is stated that “Typically, it is desirable to remove features, here PSMs, with greater than 20% missing values”. Why this number? Is this accepted by the entire community? (this comment also applies to the same step in the LFQ analysis. Author Response: The percentage of missing data to allow per dataset will depend on the experimental design and number of samples. There are no strict rules on what one should allow and if imputation is required several groups report that up to 20% missing values in quantitative proteomics is acceptable (please see, for example, https://doi.org/10.1038/s41597-024-02922-z and https://doi.org/10.1186/s12864-022-08723-1 ) to maintain data structure as close to reality as possible. Reviewer Comments: Regarding missing value replacement (discussion on LFQ, page 55): it is really nice to provide references of strategies applied to replacement of missing values. It is indeed a tricky decision to make (how to replace? Should we replace?) and there is no one-size-fits-them-all method. Why do you choose to replace at peptide level and not protein level? Author Response: The reason that we typically choose to impute at the lowest possible data level is to avoid the implicit imputation that occurs during aggregation. For example, if a protein is supported by two peptides, and one peptide contains missing values whilst the other does not, aggregation would result in a protein level quantitation value without the user explicitly stating how to deal with the missing value. Reviewer Comments: Page 38: what do the authors mean by “report did not indicate any superior normalization method”? How would we know what normalization method works best? This point is because I am curious, not to correct any obvious mistake. It is great to try out different normalization strategies, but I don’t really see how to pick one based on the boxplots of normalized intensities (Figure 4). Author Response: In our experience of sharing and teaching this workflow, we have found that one of the most common questions is in regard to selecting an appropriate normalisation method. Therefore, we decided to include NormalyzerDE as one approach for users to make this decision. However, we appreciate that the results of this comparison are not particularly informative for either of the use-case datasets. As a result, we have decided to remove the NormalyzerDE example from the workflow and instead include further discussion. Reviewer Comments: The authors normalize the data after protein aggregation and not at the PSM level. Is this general practice? Wouldn’t it make sense to normalize before aggregation? Author Response: We acknowledge that this decision is not a simple one, and not one which has a consensus in the literature. For example, some workflows choose to normalise at lower data levels so that normalisation can occur prior to imputation. We typically choose to normalise data at the protein level because this is the level at which statistical analyses are carried out. As the goal of normalisation is to remove non-biological variation to increase statistical power and lead to the discovery of meaningful, biological variation, we feel it makes the most sense to do this step immediately before statistics. Normalising the data at PSM or peptide level would not account for any small variation re-introduced during aggregation (depending upon the selected aggregation method). Reviewer Comments: Page 44; “Data import, housekeeping and exploration”: the authors mention that LFQ analysis cannot be performed at PSM level but has to be done at peptide level. I think that this is dependent on the software tool that is used, and this may be specific of Proteome Discoverer. Match between run is performed at the ion level, but the intensity retrieved at this step can be reported at PSM level. I think that this is the case in MaxQuant “evidence.txt” tables, if I am not mistaken. Author Response: We thank Dr Locard-Paulet for pointing this out and have adjusted the text in the LFQ data import section accordingly. Reviewer Comments: Page 63: DEqMS could be mentioned since it is specifically developed for proteomics statistical analysis. (http://doi.org/10.1074/mcp.TIR119.001646) Author Response: Thank you for this suggestion. We have now mentioned and referenced this package in the appropriate place. Reviewer Comments: This is more of a naïve question regarding using Limma in this context: does it make sense to model the variance depending on intensity after missing value replacement? I know that this manuscript may not be the place to discuss this, but I would be interested to know what the authors’ opinion is on this question. Author Response: We agree with the reviewer that one does need to be cautious, and in the text, we advise users to check their data following imputation and that the distribution has not dramatically changed. As we mention in the manuscript it is now possible to use packages such as msqRob2 to facilitates statistical differential expression analysis on datasets without the need for imputation. With the limma package, for a given protein, the cases with missing values are removed both from the data and design matrix. That is, the linear model is fitted to the non-missing values. If a particular regression co-efficient cannot be estimated from the observed data for a protein of interest, then a NA value will be returned for that coefficient. Reviewer Comments: Additional suggestions (only suggestions that may totally be ignored/dismissed by the authors if they don’t think that they’ll improve their manuscript): The data is available in PRIDE (PXD041794), but the information necessary to match TMT channel/sample to conditions/replicates is only available in the associated paper. It would be great to add the Table 1 of the manuscript and a link to the zenodo repository in PRIDE alongside the data. An even better solution would be to provide the metadata in the SDRF-Proteomics format ( https://www.nature.com/articles/s41467-021-26111-3 ; there is a GUI to generate these files now: https://lessdrf.streamlit.app/). This would facilitate data reuse and transparency. Small comments / typos: Page 3, in the code at the bottom of the page: the “,” is missing after “stringr”. Paragraph "Assessing the impact of non-specific data cleaning”, in the table (and other similar tables or mentions of number of protein groups and peptide stripped sequences): “proteins” should be replaced by “protein groups” since this is what is actually counted. If the authors wanted to be more precise, they could also specify that the “peptides” correspond to peptide sequences stripped of all modifications. Bar plot of missing value proportion page 32: what does the red dashed line correspond to? Page 37, when running the function `normalizer`, I got an error “No RT column specified (column named 'RT') or option not specified Skipping RT normalization.” And could not get the expected report. I am not familiar with the tool and did not investigate further. I don’t think that “softwares” can be used. There is no “s” at the end. Page 51: “cleaning is done is two steps” should be “cleaning is done in two steps” Page 54: in the bar plot of missing value count, what is the dashed red line? Page 55: “If the method requires data to display a normal distribution, users must log2 transform the data prior to imputation.” -> is there a reason to perform missing values replacement before log transformation? If not, this step could be moved to after log transform? Page 66: “If we had not used TMT labels and wished to include a logFC threshold, we could have included lfc = as an argument”. The characters of “ lfc = as ” are in a different police, I think that this is a bit unclear since the “as” should be regular text. Also, maybe you could explain “have included lfc = followed by the minimum absolute log2-transformed fold change”. Page 72: “summarize all packages and corresponding their versions used to generate” -> the sentence does not seem correct to me. Author Response: We would like to thank Dr. Locard-Paulet for being so thorough in reviewing the manuscript. We have corrected the highlighted typos. We thank Dr Locard-Paulet for her positive comments and have answered her additional comments below. Reviewer Comments: Major comments: It should be made clear that this script is tailored for Proteome Discoverer outputs (and maybe even for a given version of Proteome Discoverer). For most of the plotting/filtering/analysis steps, changing input would only require adapting the column names/headers, and most of the time it is very well discussed by the authors. Nevertheless, right now this script is only adapted to Proteome Discoverer outputs and this should be made clear in the abstract and the introduction, as well as the discussion. Author Response: We appreciate that both use-case datasets in this workflow were processed using Proteome Discoverer and have added text to emphasise this further in the abstract and introduction. Nevertheless, we feel that the workflow is still useful to users of alternative third-party software as the general data processing steps, and extensive discussion of these, remains relevant. To help users make the most out of this workflow, we have provided information on how to adapt the workflow from Proteome Discoverer files to those generated by MaxQuant, a free and accessible search software. This information is provided in a new section in the Appendix of our Github repository. Reviewer Comments: Aggregation of PSM quantification values to peptides and proteins: Here, the authors choose to aggregate all PSM intensities corresponding to the same sequence (stripped of its modifications). I would aggregate the PSM quantities per peptidoform (sequence + localized modifications) since two ions can have the same sequence but with modifications that are differentially regulated between the conditions compared. This should be mentioned. Author Response: As Dr Locard-Paulet mentions, it is possible for the same peptide sequence with and without modifications to behave differently. We have added the following to the workflow to acknowledge this: “For simplicity, we here aggregate all PSMs corresponding to the same stripped peptide sequence, regardless of whether they contain different modifications. If users are interested in exploring differential expression of protein isoforms or have reason to believe that post-translational modifications may be important in answering their question, PSMs could also be aggregated by "Annotated.Sequence" to preserve this information.” We agree that this point is worth drawing attention to. In order to observe any differential abundance of peptides when modified, statistical analysis would need to be carried out at the peptide-level. Since this is outside of the scope of this workflow, we continue to aggregate using the stripped sequence column to facilitate statistical analysis at the protein level. Reviewer Comments: For the GO-term enrichment: only the majority protein accessions are reported in the output of the limma analysis. So there is only one gene per feature. How do you make sure that it is the most representative annotation for a given protein group? I am fully aware that this issue is ignored by the community (for lack of alternative strategy), and that most of the time people just pick one accession per group for GO-term enrichment analysis. So, I am not asking the authors to find a solution. Nevertheless, it would be nice to mention that the output of the enrichment will depend on what accession is picked per group. Author Response: We agree with and acknowledge this point. Indeed, it is a limitation of protein inference that results in statistics and interpretation being done at the level of protein groups rather than individual proteins. As a result, we would always encourage users to explore their statistical hits, particularly those of interest for follow up. This would include tracing the protein group back down all data levels and potentially plotting an aggregation graph, as demonstrated in “Exploration of data using QFeatures links”. With regard to the output of GO enrichment, we do not expect the overall biological interpretation to be dramatically skewed as only protein lists with multiple proteins with the same GO annotation will be considered enriched. Therefore, even if a few of the master proteins are not representative of the protein which is actually changing in abundance, these few cases are unlikely to cause an incorrect enrichment. Nevertheless, it is always worthwhile for the user to examine the results to verify correct interpretation. Reviewer Comments: Minor comments: I would remove contaminants before estimation of TMT labelling efficiency. I find the paragraph “Additional considerations regarding protein isoforms” unclear. The authors should rephrase sentences such as this one: “PSMs or peptides that were previously mapped to one protein and one protein group could instead be mapped to multiple proteins and one protein group.” Maybe they should use the term “canonical protein” to be more precise? In any cases, the issue of peptide uniqueness does not depend only on the presence of isoforms in the fasta file but also on the strategy that was chosen for protein inference. I agree with the authors that people should precisely describe what peptides/PSMs were used for quantification, and it is good to mention it. Nevertheless, this level of detail on general MS-based proteomics concept may not be necessary here. (So the entire paragraph on isoforms could maybe be removed, especially since isoforms are not mentioned later). Author Response: We thank Dr Locard-Paulet for her input on this complex issue. We agree that for a beginner-level workflow, the discussion of isoforms may be confusing. We have removed the paragraph about isoforms, whilst adding some further comment on the importance of defining uniqueness above. Reviewer Comments: In the paragraph “Removing PSMs that are not rank 1”: I think that the “PSM category” that is discussed a bit later is specific of Proteome Discoverer. Some search engines report PSMs of equal score (this would correspond to the “pretty rank” in Mascot). I don’t think that all this should necessarily be discussed in this manuscript, but I insist on the fact that the workflow is tuned for Proteome Discoverer output and this should be made clear in the introduction/abstract. Author Response: We have included additional emphasis on Proteome Discoverer in the introduction to this workflow. That said, users of alternative software will still benefit from being aware of the concept of ‘PSM rank’. Reviewer Comments: In the paragraph “Managing missing data” for the TMT: the authors mention MCAR, MAR, and MNAR, but do they all apply here? I would expect TMT-labelled data to mostly have missing values due to ions being under the limit of detection because when an ion is fragmented, the reporter ions used for relative quantification are often all detected. Isn’t it the case? Knowing this should restrict the choice for a more suited strategy of replacement of missing values. Author Response: Indeed, knowing the reason behind missing values is important in deciding upon an imputation method. We have added an additional few sentences to outline this in the “Imputation” section of the TMT workflow. Nonetheless, we still wish to emphasise that in the use-case, and most datasets with such little missingness, it is not necessary to impute. Additional discussion has also been added under “The importance of knowing what you expect in missing values” to ensure that users consider their experimental design and quantitation strategy when assessing and dealing with missing values. Reviewer Comments: Still on missing values: page 33, it is stated that “Typically, it is desirable to remove features, here PSMs, with greater than 20% missing values”. Why this number? Is this accepted by the entire community? (this comment also applies to the same step in the LFQ analysis. Author Response: The percentage of missing data to allow per dataset will depend on the experimental design and number of samples. There are no strict rules on what one should allow and if imputation is required several groups report that up to 20% missing values in quantitative proteomics is acceptable (please see, for example, https://doi.org/10.1038/s41597-024-02922-z and https://doi.org/10.1186/s12864-022-08723-1 ) to maintain data structure as close to reality as possible. Reviewer Comments: Regarding missing value replacement (discussion on LFQ, page 55): it is really nice to provide references of strategies applied to replacement of missing values. It is indeed a tricky decision to make (how to replace? Should we replace?) and there is no one-size-fits-them-all method. Why do you choose to replace at peptide level and not protein level? Author Response: The reason that we typically choose to impute at the lowest possible data level is to avoid the implicit imputation that occurs during aggregation. For example, if a protein is supported by two peptides, and one peptide contains missing values whilst the other does not, aggregation would result in a protein level quantitation value without the user explicitly stating how to deal with the missing value. Reviewer Comments: Page 38: what do the authors mean by “report did not indicate any superior normalization method”? How would we know what normalization method works best? This point is because I am curious, not to correct any obvious mistake. It is great to try out different normalization strategies, but I don’t really see how to pick one based on the boxplots of normalized intensities (Figure 4). Author Response: In our experience of sharing and teaching this workflow, we have found that one of the most common questions is in regard to selecting an appropriate normalisation method. Therefore, we decided to include NormalyzerDE as one approach for users to make this decision. However, we appreciate that the results of this comparison are not particularly informative for either of the use-case datasets. As a result, we have decided to remove the NormalyzerDE example from the workflow and instead include further discussion. Reviewer Comments: The authors normalize the data after protein aggregation and not at the PSM level. Is this general practice? Wouldn’t it make sense to normalize before aggregation? Author Response: We acknowledge that this decision is not a simple one, and not one which has a consensus in the literature. For example, some workflows choose to normalise at lower data levels so that normalisation can occur prior to imputation. We typically choose to normalise data at the protein level because this is the level at which statistical analyses are carried out. As the goal of normalisation is to remove non-biological variation to increase statistical power and lead to the discovery of meaningful, biological variation, we feel it makes the most sense to do this step immediately before statistics. Normalising the data at PSM or peptide level would not account for any small variation re-introduced during aggregation (depending upon the selected aggregation method). Reviewer Comments: Page 44; “Data import, housekeeping and exploration”: the authors mention that LFQ analysis cannot be performed at PSM level but has to be done at peptide level. I think that this is dependent on the software tool that is used, and this may be specific of Proteome Discoverer. Match between run is performed at the ion level, but the intensity retrieved at this step can be reported at PSM level. I think that this is the case in MaxQuant “evidence.txt” tables, if I am not mistaken. Author Response: We thank Dr Locard-Paulet for pointing this out and have adjusted the text in the LFQ data import section accordingly. Reviewer Comments: Page 63: DEqMS could be mentioned since it is specifically developed for proteomics statistical analysis. (http://doi.org/10.1074/mcp.TIR119.001646) Author Response: Thank you for this suggestion. We have now mentioned and referenced this package in the appropriate place. Reviewer Comments: This is more of a naïve question regarding using Limma in this context: does it make sense to model the variance depending on intensity after missing value replacement? I know that this manuscript may not be the place to discuss this, but I would be interested to know what the authors’ opinion is on this question. Author Response: We agree with the reviewer that one does need to be cautious, and in the text, we advise users to check their data following imputation and that the distribution has not dramatically changed. As we mention in the manuscript it is now possible to use packages such as msqRob2 to facilitates statistical differential expression analysis on datasets without the need for imputation. With the limma package, for a given protein, the cases with missing values are removed both from the data and design matrix. That is, the linear model is fitted to the non-missing values. If a particular regression co-efficient cannot be estimated from the observed data for a protein of interest, then a NA value will be returned for that coefficient. Reviewer Comments: Additional suggestions (only suggestions that may totally be ignored/dismissed by the authors if they don’t think that they’ll improve their manuscript): The data is available in PRIDE (PXD041794), but the information necessary to match TMT channel/sample to conditions/replicates is only available in the associated paper. It would be great to add the Table 1 of the manuscript and a link to the zenodo repository in PRIDE alongside the data. An even better solution would be to provide the metadata in the SDRF-Proteomics format ( https://www.nature.com/articles/s41467-021-26111-3 ; there is a GUI to generate these files now: https://lessdrf.streamlit.app/). This would facilitate data reuse and transparency. Small comments / typos: Page 3, in the code at the bottom of the page: the “,” is missing after “stringr”. Paragraph "Assessing the impact of non-specific data cleaning”, in the table (and other similar tables or mentions of number of protein groups and peptide stripped sequences): “proteins” should be replaced by “protein groups” since this is what is actually counted. If the authors wanted to be more precise, they could also specify that the “peptides” correspond to peptide sequences stripped of all modifications. Bar plot of missing value proportion page 32: what does the red dashed line correspond to? Page 37, when running the function `normalizer`, I got an error “No RT column specified (column named 'RT') or option not specified Skipping RT normalization.” And could not get the expected report. I am not familiar with the tool and did not investigate further. I don’t think that “softwares” can be used. There is no “s” at the end. Page 51: “cleaning is done is two steps” should be “cleaning is done in two steps” Page 54: in the bar plot of missing value count, what is the dashed red line? Page 55: “If the method requires data to display a normal distribution, users must log2 transform the data prior to imputation.” -> is there a reason to perform missing values replacement before log transformation? If not, this step could be moved to after log transform? Page 66: “If we had not used TMT labels and wished to include a logFC threshold, we could have included lfc = as an argument”. The characters of “ lfc = as ” are in a different police, I think that this is a bit unclear since the “as” should be regular text. Also, maybe you could explain “have included lfc = followed by the minimum absolute log2-transformed fold change”. Page 72: “summarize all packages and corresponding their versions used to generate” -> the sentence does not seem correct to me. Author Response: We would like to thank Dr. Locard-Paulet for being so thorough in reviewing the manuscript. We have corrected the highlighted typos. Competing Interests: No competing interests were disclosed. Close Report a concern Respond or Comment COMMENTS ON THIS REPORT Author Response 25 Sep 2024 Lisa Breckels , Cambridge Centre for Proteomics, University of Cambridge, Cambridge, CB2 1QR, UK 25 Sep 2024 Author Response We thank Dr Locard-Paulet for her positive comments and have answered her additional comments below. Reviewer Comments: Major comments: It should be made clear that this ... Continue reading We thank Dr Locard-Paulet for her positive comments and have answered her additional comments below. Reviewer Comments: Major comments: It should be made clear that this script is tailored for Proteome Discoverer outputs (and maybe even for a given version of Proteome Discoverer). For most of the plotting/filtering/analysis steps, changing input would only require adapting the column names/headers, and most of the time it is very well discussed by the authors. Nevertheless, right now this script is only adapted to Proteome Discoverer outputs and this should be made clear in the abstract and the introduction, as well as the discussion. Author Response: We appreciate that both use-case datasets in this workflow were processed using Proteome Discoverer and have added text to emphasise this further in the abstract and introduction. Nevertheless, we feel that the workflow is still useful to users of alternative third-party software as the general data processing steps, and extensive discussion of these, remains relevant. To help users make the most out of this workflow, we have provided information on how to adapt the workflow from Proteome Discoverer files to those generated by MaxQuant, a free and accessible search software. This information is provided in a new section in the Appendix of our Github repository. Reviewer Comments: Aggregation of PSM quantification values to peptides and proteins: Here, the authors choose to aggregate all PSM intensities corresponding to the same sequence (stripped of its modifications). I would aggregate the PSM quantities per peptidoform (sequence + localized modifications) since two ions can have the same sequence but with modifications that are differentially regulated between the conditions compared. This should be mentioned. Author Response: As Dr Locard-Paulet mentions, it is possible for the same peptide sequence with and without modifications to behave differently. We have added the following to the workflow to acknowledge this: “For simplicity, we here aggregate all PSMs corresponding to the same stripped peptide sequence, regardless of whether they contain different modifications. If users are interested in exploring differential expression of protein isoforms or have reason to believe that post-translational modifications may be important in answering their question, PSMs could also be aggregated by "Annotated.Sequence" to preserve this information.” We agree that this point is worth drawing attention to. In order to observe any differential abundance of peptides when modified, statistical analysis would need to be carried out at the peptide-level. Since this is outside of the scope of this workflow, we continue to aggregate using the stripped sequence column to facilitate statistical analysis at the protein level. Reviewer Comments: For the GO-term enrichment: only the majority protein accessions are reported in the output of the limma analysis. So there is only one gene per feature. How do you make sure that it is the most representative annotation for a given protein group? I am fully aware that this issue is ignored by the community (for lack of alternative strategy), and that most of the time people just pick one accession per group for GO-term enrichment analysis. So, I am not asking the authors to find a solution. Nevertheless, it would be nice to mention that the output of the enrichment will depend on what accession is picked per group. Author Response: We agree with and acknowledge this point. Indeed, it is a limitation of protein inference that results in statistics and interpretation being done at the level of protein groups rather than individual proteins. As a result, we would always encourage users to explore their statistical hits, particularly those of interest for follow up. This would include tracing the protein group back down all data levels and potentially plotting an aggregation graph, as demonstrated in “Exploration of data using QFeatures links”. With regard to the output of GO enrichment, we do not expect the overall biological interpretation to be dramatically skewed as only protein lists with multiple proteins with the same GO annotation will be considered enriched. Therefore, even if a few of the master proteins are not representative of the protein which is actually changing in abundance, these few cases are unlikely to cause an incorrect enrichment. Nevertheless, it is always worthwhile for the user to examine the results to verify correct interpretation. Reviewer Comments: Minor comments: I would remove contaminants before estimation of TMT labelling efficiency. I find the paragraph “Additional considerations regarding protein isoforms” unclear. The authors should rephrase sentences such as this one: “PSMs or peptides that were previously mapped to one protein and one protein group could instead be mapped to multiple proteins and one protein group.” Maybe they should use the term “canonical protein” to be more precise? In any cases, the issue of peptide uniqueness does not depend only on the presence of isoforms in the fasta file but also on the strategy that was chosen for protein inference. I agree with the authors that people should precisely describe what peptides/PSMs were used for quantification, and it is good to mention it. Nevertheless, this level of detail on general MS-based proteomics concept may not be necessary here. (So the entire paragraph on isoforms could maybe be removed, especially since isoforms are not mentioned later). Author Response: We thank Dr Locard-Paulet for her input on this complex issue. We agree that for a beginner-level workflow, the discussion of isoforms may be confusing. We have removed the paragraph about isoforms, whilst adding some further comment on the importance of defining uniqueness above. Reviewer Comments: In the paragraph “Removing PSMs that are not rank 1”: I think that the “PSM category” that is discussed a bit later is specific of Proteome Discoverer. Some search engines report PSMs of equal score (this would correspond to the “pretty rank” in Mascot). I don’t think that all this should necessarily be discussed in this manuscript, but I insist on the fact that the workflow is tuned for Proteome Discoverer output and this should be made clear in the introduction/abstract. Author Response: We have included additional emphasis on Proteome Discoverer in the introduction to this workflow. That said, users of alternative software will still benefit from being aware of the concept of ‘PSM rank’. Reviewer Comments: In the paragraph “Managing missing data” for the TMT: the authors mention MCAR, MAR, and MNAR, but do they all apply here? I would expect TMT-labelled data to mostly have missing values due to ions being under the limit of detection because when an ion is fragmented, the reporter ions used for relative quantification are often all detected. Isn’t it the case? Knowing this should restrict the choice for a more suited strategy of replacement of missing values. Author Response: Indeed, knowing the reason behind missing values is important in deciding upon an imputation method. We have added an additional few sentences to outline this in the “Imputation” section of the TMT workflow. Nonetheless, we still wish to emphasise that in the use-case, and most datasets with such little missingness, it is not necessary to impute. Additional discussion has also been added under “The importance of knowing what you expect in missing values” to ensure that users consider their experimental design and quantitation strategy when assessing and dealing with missing values. Reviewer Comments: Still on missing values: page 33, it is stated that “Typically, it is desirable to remove features, here PSMs, with greater than 20% missing values”. Why this number? Is this accepted by the entire community? (this comment also applies to the same step in the LFQ analysis. Author Response: The percentage of missing data to allow per dataset will depend on the experimental design and number of samples. There are no strict rules on what one should allow and if imputation is required several groups report that up to 20% missing values in quantitative proteomics is acceptable (please see, for example, https://doi.org/10.1038/s41597-024-02922-z and https://doi.org/10.1186/s12864-022-08723-1 ) to maintain data structure as close to reality as possible. Reviewer Comments: Regarding missing value replacement (discussion on LFQ, page 55): it is really nice to provide references of strategies applied to replacement of missing values. It is indeed a tricky decision to make (how to replace? Should we replace?) and there is no one-size-fits-them-all method. Why do you choose to replace at peptide level and not protein level? Author Response: The reason that we typically choose to impute at the lowest possible data level is to avoid the implicit imputation that occurs during aggregation. For example, if a protein is supported by two peptides, and one peptide contains missing values whilst the other does not, aggregation would result in a protein level quantitation value without the user explicitly stating how to deal with the missing value. Reviewer Comments: Page 38: what do the authors mean by “report did not indicate any superior normalization method”? How would we know what normalization method works best? This point is because I am curious, not to correct any obvious mistake. It is great to try out different normalization strategies, but I don’t really see how to pick one based on the boxplots of normalized intensities (Figure 4). Author Response: In our experience of sharing and teaching this workflow, we have found that one of the most common questions is in regard to selecting an appropriate normalisation method. Therefore, we decided to include NormalyzerDE as one approach for users to make this decision. However, we appreciate that the results of this comparison are not particularly informative for either of the use-case datasets. As a result, we have decided to remove the NormalyzerDE example from the workflow and instead include further discussion. Reviewer Comments: The authors normalize the data after protein aggregation and not at the PSM level. Is this general practice? Wouldn’t it make sense to normalize before aggregation? Author Response: We acknowledge that this decision is not a simple one, and not one which has a consensus in the literature. For example, some workflows choose to normalise at lower data levels so that normalisation can occur prior to imputation. We typically choose to normalise data at the protein level because this is the level at which statistical analyses are carried out. As the goal of normalisation is to remove non-biological variation to increase statistical power and lead to the discovery of meaningful, biological variation, we feel it makes the most sense to do this step immediately before statistics. Normalising the data at PSM or peptide level would not account for any small variation re-introduced during aggregation (depending upon the selected aggregation method). Reviewer Comments: Page 44; “Data import, housekeeping and exploration”: the authors mention that LFQ analysis cannot be performed at PSM level but has to be done at peptide level. I think that this is dependent on the software tool that is used, and this may be specific of Proteome Discoverer. Match between run is performed at the ion level, but the intensity retrieved at this step can be reported at PSM level. I think that this is the case in MaxQuant “evidence.txt” tables, if I am not mistaken. Author Response: We thank Dr Locard-Paulet for pointing this out and have adjusted the text in the LFQ data import section accordingly. Reviewer Comments: Page 63: DEqMS could be mentioned since it is specifically developed for proteomics statistical analysis. (http://doi.org/10.1074/mcp.TIR119.001646) Author Response: Thank you for this suggestion. We have now mentioned and referenced this package in the appropriate place. Reviewer Comments: This is more of a naïve question regarding using Limma in this context: does it make sense to model the variance depending on intensity after missing value replacement? I know that this manuscript may not be the place to discuss this, but I would be interested to know what the authors’ opinion is on this question. Author Response: We agree with the reviewer that one does need to be cautious, and in the text, we advise users to check their data following imputation and that the distribution has not dramatically changed. As we mention in the manuscript it is now possible to use packages such as msqRob2 to facilitates statistical differential expression analysis on datasets without the need for imputation. With the limma package, for a given protein, the cases with missing values are removed both from the data and design matrix. That is, the linear model is fitted to the non-missing values. If a particular regression co-efficient cannot be estimated from the observed data for a protein of interest, then a NA value will be returned for that coefficient. Reviewer Comments: Additional suggestions (only suggestions that may totally be ignored/dismissed by the authors if they don’t think that they’ll improve their manuscript): The data is available in PRIDE (PXD041794), but the information necessary to match TMT channel/sample to conditions/replicates is only available in the associated paper. It would be great to add the Table 1 of the manuscript and a link to the zenodo repository in PRIDE alongside the data. An even better solution would be to provide the metadata in the SDRF-Proteomics format ( https://www.nature.com/articles/s41467-021-26111-3 ; there is a GUI to generate these files now: https://lessdrf.streamlit.app/). This would facilitate data reuse and transparency. Small comments / typos: Page 3, in the code at the bottom of the page: the “,” is missing after “stringr”. Paragraph "Assessing the impact of non-specific data cleaning”, in the table (and other similar tables or mentions of number of protein groups and peptide stripped sequences): “proteins” should be replaced by “protein groups” since this is what is actually counted. If the authors wanted to be more precise, they could also specify that the “peptides” correspond to peptide sequences stripped of all modifications. Bar plot of missing value proportion page 32: what does the red dashed line correspond to? Page 37, when running the function `normalizer`, I got an error “No RT column specified (column named 'RT') or option not specified Skipping RT normalization.” And could not get the expected report. I am not familiar with the tool and did not investigate further. I don’t think that “softwares” can be used. There is no “s” at the end. Page 51: “cleaning is done is two steps” should be “cleaning is done in two steps” Page 54: in the bar plot of missing value count, what is the dashed red line? Page 55: “If the method requires data to display a normal distribution, users must log2 transform the data prior to imputation.” -> is there a reason to perform missing values replacement before log transformation? If not, this step could be moved to after log transform? Page 66: “If we had not used TMT labels and wished to include a logFC threshold, we could have included lfc = as an argument”. The characters of “ lfc = as ” are in a different police, I think that this is a bit unclear since the “as” should be regular text. Also, maybe you could explain “have included lfc = followed by the minimum absolute log2-transformed fold change”. Page 72: “summarize all packages and corresponding their versions used to generate” -> the sentence does not seem correct to me. Author Response: We would like to thank Dr. Locard-Paulet for being so thorough in reviewing the manuscript. We have corrected the highlighted typos. We thank Dr Locard-Paulet for her positive comments and have answered her additional comments below. Reviewer Comments: Major comments: It should be made clear that this script is tailored for Proteome Discoverer outputs (and maybe even for a given version of Proteome Discoverer). For most of the plotting/filtering/analysis steps, changing input would only require adapting the column names/headers, and most of the time it is very well discussed by the authors. Nevertheless, right now this script is only adapted to Proteome Discoverer outputs and this should be made clear in the abstract and the introduction, as well as the discussion. Author Response: We appreciate that both use-case datasets in this workflow were processed using Proteome Discoverer and have added text to emphasise this further in the abstract and introduction. Nevertheless, we feel that the workflow is still useful to users of alternative third-party software as the general data processing steps, and extensive discussion of these, remains relevant. To help users make the most out of this workflow, we have provided information on how to adapt the workflow from Proteome Discoverer files to those generated by MaxQuant, a free and accessible search software. This information is provided in a new section in the Appendix of our Github repository. Reviewer Comments: Aggregation of PSM quantification values to peptides and proteins: Here, the authors choose to aggregate all PSM intensities corresponding to the same sequence (stripped of its modifications). I would aggregate the PSM quantities per peptidoform (sequence + localized modifications) since two ions can have the same sequence but with modifications that are differentially regulated between the conditions compared. This should be mentioned. Author Response: As Dr Locard-Paulet mentions, it is possible for the same peptide sequence with and without modifications to behave differently. We have added the following to the workflow to acknowledge this: “For simplicity, we here aggregate all PSMs corresponding to the same stripped peptide sequence, regardless of whether they contain different modifications. If users are interested in exploring differential expression of protein isoforms or have reason to believe that post-translational modifications may be important in answering their question, PSMs could also be aggregated by "Annotated.Sequence" to preserve this information.” We agree that this point is worth drawing attention to. In order to observe any differential abundance of peptides when modified, statistical analysis would need to be carried out at the peptide-level. Since this is outside of the scope of this workflow, we continue to aggregate using the stripped sequence column to facilitate statistical analysis at the protein level. Reviewer Comments: For the GO-term enrichment: only the majority protein accessions are reported in the output of the limma analysis. So there is only one gene per feature. How do you make sure that it is the most representative annotation for a given protein group? I am fully aware that this issue is ignored by the community (for lack of alternative strategy), and that most of the time people just pick one accession per group for GO-term enrichment analysis. So, I am not asking the authors to find a solution. Nevertheless, it would be nice to mention that the output of the enrichment will depend on what accession is picked per group. Author Response: We agree with and acknowledge this point. Indeed, it is a limitation of protein inference that results in statistics and interpretation being done at the level of protein groups rather than individual proteins. As a result, we would always encourage users to explore their statistical hits, particularly those of interest for follow up. This would include tracing the protein group back down all data levels and potentially plotting an aggregation graph, as demonstrated in “Exploration of data using QFeatures links”. With regard to the output of GO enrichment, we do not expect the overall biological interpretation to be dramatically skewed as only protein lists with multiple proteins with the same GO annotation will be considered enriched. Therefore, even if a few of the master proteins are not representative of the protein which is actually changing in abundance, these few cases are unlikely to cause an incorrect enrichment. Nevertheless, it is always worthwhile for the user to examine the results to verify correct interpretation. Reviewer Comments: Minor comments: I would remove contaminants before estimation of TMT labelling efficiency. I find the paragraph “Additional considerations regarding protein isoforms” unclear. The authors should rephrase sentences such as this one: “PSMs or peptides that were previously mapped to one protein and one protein group could instead be mapped to multiple proteins and one protein group.” Maybe they should use the term “canonical protein” to be more precise? In any cases, the issue of peptide uniqueness does not depend only on the presence of isoforms in the fasta file but also on the strategy that was chosen for protein inference. I agree with the authors that people should precisely describe what peptides/PSMs were used for quantification, and it is good to mention it. Nevertheless, this level of detail on general MS-based proteomics concept may not be necessary here. (So the entire paragraph on isoforms could maybe be removed, especially since isoforms are not mentioned later). Author Response: We thank Dr Locard-Paulet for her input on this complex issue. We agree that for a beginner-level workflow, the discussion of isoforms may be confusing. We have removed the paragraph about isoforms, whilst adding some further comment on the importance of defining uniqueness above. Reviewer Comments: In the paragraph “Removing PSMs that are not rank 1”: I think that the “PSM category” that is discussed a bit later is specific of Proteome Discoverer. Some search engines report PSMs of equal score (this would correspond to the “pretty rank” in Mascot). I don’t think that all this should necessarily be discussed in this manuscript, but I insist on the fact that the workflow is tuned for Proteome Discoverer output and this should be made clear in the introduction/abstract. Author Response: We have included additional emphasis on Proteome Discoverer in the introduction to this workflow. That said, users of alternative software will still benefit from being aware of the concept of ‘PSM rank’. Reviewer Comments: In the paragraph “Managing missing data” for the TMT: the authors mention MCAR, MAR, and MNAR, but do they all apply here? I would expect TMT-labelled data to mostly have missing values due to ions being under the limit of detection because when an ion is fragmented, the reporter ions used for relative quantification are often all detected. Isn’t it the case? Knowing this should restrict the choice for a more suited strategy of replacement of missing values. Author Response: Indeed, knowing the reason behind missing values is important in deciding upon an imputation method. We have added an additional few sentences to outline this in the “Imputation” section of the TMT workflow. Nonetheless, we still wish to emphasise that in the use-case, and most datasets with such little missingness, it is not necessary to impute. Additional discussion has also been added under “The importance of knowing what you expect in missing values” to ensure that users consider their experimental design and quantitation strategy when assessing and dealing with missing values. Reviewer Comments: Still on missing values: page 33, it is stated that “Typically, it is desirable to remove features, here PSMs, with greater than 20% missing values”. Why this number? Is this accepted by the entire community? (this comment also applies to the same step in the LFQ analysis. Author Response: The percentage of missing data to allow per dataset will depend on the experimental design and number of samples. There are no strict rules on what one should allow and if imputation is required several groups report that up to 20% missing values in quantitative proteomics is acceptable (please see, for example, https://doi.org/10.1038/s41597-024-02922-z and https://doi.org/10.1186/s12864-022-08723-1 ) to maintain data structure as close to reality as possible. Reviewer Comments: Regarding missing value replacement (discussion on LFQ, page 55): it is really nice to provide references of strategies applied to replacement of missing values. It is indeed a tricky decision to make (how to replace? Should we replace?) and there is no one-size-fits-them-all method. Why do you choose to replace at peptide level and not protein level? Author Response: The reason that we typically choose to impute at the lowest possible data level is to avoid the implicit imputation that occurs during aggregation. For example, if a protein is supported by two peptides, and one peptide contains missing values whilst the other does not, aggregation would result in a protein level quantitation value without the user explicitly stating how to deal with the missing value. Reviewer Comments: Page 38: what do the authors mean by “report did not indicate any superior normalization method”? How would we know what normalization method works best? This point is because I am curious, not to correct any obvious mistake. It is great to try out different normalization strategies, but I don’t really see how to pick one based on the boxplots of normalized intensities (Figure 4). Author Response: In our experience of sharing and teaching this workflow, we have found that one of the most common questions is in regard to selecting an appropriate normalisation method. Therefore, we decided to include NormalyzerDE as one approach for users to make this decision. However, we appreciate that the results of this comparison are not particularly informative for either of the use-case datasets. As a result, we have decided to remove the NormalyzerDE example from the workflow and instead include further discussion. Reviewer Comments: The authors normalize the data after protein aggregation and not at the PSM level. Is this general practice? Wouldn’t it make sense to normalize before aggregation? Author Response: We acknowledge that this decision is not a simple one, and not one which has a consensus in the literature. For example, some workflows choose to normalise at lower data levels so that normalisation can occur prior to imputation. We typically choose to normalise data at the protein level because this is the level at which statistical analyses are carried out. As the goal of normalisation is to remove non-biological variation to increase statistical power and lead to the discovery of meaningful, biological variation, we feel it makes the most sense to do this step immediately before statistics. Normalising the data at PSM or peptide level would not account for any small variation re-introduced during aggregation (depending upon the selected aggregation method). Reviewer Comments: Page 44; “Data import, housekeeping and exploration”: the authors mention that LFQ analysis cannot be performed at PSM level but has to be done at peptide level. I think that this is dependent on the software tool that is used, and this may be specific of Proteome Discoverer. Match between run is performed at the ion level, but the intensity retrieved at this step can be reported at PSM level. I think that this is the case in MaxQuant “evidence.txt” tables, if I am not mistaken. Author Response: We thank Dr Locard-Paulet for pointing this out and have adjusted the text in the LFQ data import section accordingly. Reviewer Comments: Page 63: DEqMS could be mentioned since it is specifically developed for proteomics statistical analysis. (http://doi.org/10.1074/mcp.TIR119.001646) Author Response: Thank you for this suggestion. We have now mentioned and referenced this package in the appropriate place. Reviewer Comments: This is more of a naïve question regarding using Limma in this context: does it make sense to model the variance depending on intensity after missing value replacement? I know that this manuscript may not be the place to discuss this, but I would be interested to know what the authors’ opinion is on this question. Author Response: We agree with the reviewer that one does need to be cautious, and in the text, we advise users to check their data following imputation and that the distribution has not dramatically changed. As we mention in the manuscript it is now possible to use packages such as msqRob2 to facilitates statistical differential expression analysis on datasets without the need for imputation. With the limma package, for a given protein, the cases with missing values are removed both from the data and design matrix. That is, the linear model is fitted to the non-missing values. If a particular regression co-efficient cannot be estimated from the observed data for a protein of interest, then a NA value will be returned for that coefficient. Reviewer Comments: Additional suggestions (only suggestions that may totally be ignored/dismissed by the authors if they don’t think that they’ll improve their manuscript): The data is available in PRIDE (PXD041794), but the information necessary to match TMT channel/sample to conditions/replicates is only available in the associated paper. It would be great to add the Table 1 of the manuscript and a link to the zenodo repository in PRIDE alongside the data. An even better solution would be to provide the metadata in the SDRF-Proteomics format ( https://www.nature.com/articles/s41467-021-26111-3 ; there is a GUI to generate these files now: https://lessdrf.streamlit.app/). This would facilitate data reuse and transparency. Small comments / typos: Page 3, in the code at the bottom of the page: the “,” is missing after “stringr”. Paragraph "Assessing the impact of non-specific data cleaning”, in the table (and other similar tables or mentions of number of protein groups and peptide stripped sequences): “proteins” should be replaced by “protein groups” since this is what is actually counted. If the authors wanted to be more precise, they could also specify that the “peptides” correspond to peptide sequences stripped of all modifications. Bar plot of missing value proportion page 32: what does the red dashed line correspond to? Page 37, when running the function `normalizer`, I got an error “No RT column specified (column named 'RT') or option not specified Skipping RT normalization.” And could not get the expected report. I am not familiar with the tool and did not investigate further. I don’t think that “softwares” can be used. There is no “s” at the end. Page 51: “cleaning is done is two steps” should be “cleaning is done in two steps” Page 54: in the bar plot of missing value count, what is the dashed red line? Page 55: “If the method requires data to display a normal distribution, users must log2 transform the data prior to imputation.” -> is there a reason to perform missing values replacement before log transformation? If not, this step could be moved to after log transform? Page 66: “If we had not used TMT labels and wished to include a logFC threshold, we could have included lfc = as an argument”. The characters of “ lfc = as ” are in a different police, I think that this is a bit unclear since the “as” should be regular text. Also, maybe you could explain “have included lfc = followed by the minimum absolute log2-transformed fold change”. Page 72: “summarize all packages and corresponding their versions used to generate” -> the sentence does not seem correct to me. Author Response: We would like to thank Dr. Locard-Paulet for being so thorough in reviewing the manuscript. We have corrected the highlighted typos. Competing Interests: No competing interests were disclosed. Close Report a concern COMMENT ON THIS REPORT Views 0 Cite How to cite this report: Borges Lima D. Reviewer Report For: A Bioconductor workflow for processing, evaluating, and interpreting expression proteomics data [version 2; peer review: 4 approved, 1 approved with reservations] . F1000Research 2024, 12 :1402 ( https://doi.org/10.5256/f1000research.152361.r221416 ) The direct URL for this report is: https://f1000research.com/articles/12-1402/v1#referee-response-221416 NOTE: it is important to ensure the information in square brackets after the title is included in this citation. Close Copy Citation Details Reviewer Report 27 Nov 2023 Diogo Borges Lima , Leibniz - Forschungsinstitut für Molekulare Pharmakologie, Berlin, Germany Approved VIEWS 0 https://doi.org/10.5256/f1000research.152361.r221416 The article entitled "A Bioconductor workflow for processing, evaluating, and interpreting expression proteomics data" regards a full and comprehensive workflow for performing not only qualitative but also quantitative proteomics analysis. The manuscript is very well written and ... Continue reading READ ALL The article entitled "A Bioconductor workflow for processing, evaluating, and interpreting expression proteomics data" regards a full and comprehensive workflow for performing not only qualitative but also quantitative proteomics analysis. The manuscript is very well written and describes in detail the whole workflow for quantifying proteomics data. The authors focused on the LFQ analysis and TMT (for labeled datasets). However, this workflow relies on the results from a search engine that will provide the identified peptides. On this manuscript the authors used results from Proteome Discoverer. I recommended the publication, but I would like to pinpoint some minor comments: a) Although the authors mentioned the quantitation analyses by using TMT for labeled datasets, why they didn't show the analysis by using SILAC, once it uses XIC (the same strategy used by LFQ)? b) The authors used Proteome Discoverer as search engine, and the provided a template to import the results into the workflow. They could also provide other templates to turn this workflow more versatile, such as FragPipe, Patternlab for Proteomics, etc. Is the rationale for developing the new software tool clearly explained? Yes Is the description of the software tool technically sound? Yes Are sufficient details of the code, methods and analysis (if applicable) provided to allow replication of the software development and its use by others? Yes Is sufficient information provided to allow interpretation of the expected output datasets and any results generated using the tool? Yes Are the conclusions about the tool and its performance adequately supported by the findings presented in the article? Yes Competing Interests: No competing interests were disclosed. Reviewer Expertise: I have experience in proteomics analyses (qualitative and quantitative); XL-MS analysis. I also develop software for identifying and quantifying proteomics datasets. I confirm that I have read this submission and believe that I have an appropriate level of expertise to confirm that it is of an acceptable scientific standard. Close READ LESS CITE CITE HOW TO CITE THIS REPORT Borges Lima D. Reviewer Report For: A Bioconductor workflow for processing, evaluating, and interpreting expression proteomics data [version 2; peer review: 4 approved, 1 approved with reservations] . F1000Research 2024, 12 :1402 ( https://doi.org/10.5256/f1000research.152361.r221416 ) The direct URL for this report is: https://f1000research.com/articles/12-1402/v1#referee-response-221416 NOTE: it is important to ensure the information in square brackets after the title is included in all citations of this article. COPY CITATION DETAILS Report a concern Author Response 25 Sep 2024 Lisa Breckels , Cambridge Centre for Proteomics, University of Cambridge, Cambridge, CB2 1QR, UK 25 Sep 2024 Author Response We thank Dr. Lima for taking the time to review our workflow paper. The main aim of this workflow was to provide an overview of the essential steps required for ... Continue reading We thank Dr. Lima for taking the time to review our workflow paper. The main aim of this workflow was to provide an overview of the essential steps required for the processing, analysis and interpretation of quantitative mass spectrometry-based expression proteomics data. We show two use case examples, one labelled TMT experiment and one label-free experimental design. It would have been nice to also include a SILAC use-case example, among other designs, but in the interest of length of the workflow we chose these two designs as they are typically the most popular in the field. Further, statistical analysis of SILAC experiments often applies a ratiometric approach, which differs from the statistics discussed here. As Dr. Lima states we indeed use Proteome Discoverer to process the data and show how to import a PSM, peptide or protein .txt data table into R and into a QFeatures object. All third-party MS search engines typically output a data table of quantitation data and for flexibility this is where we start our analysis. Header names in the output data will differ between softwares but should be transferable. Another popular third-party software used for quantitation and identification is MaxQuant and we have added a new section in the Appendix of our Github repository to show users how one might use data from MaxQuant in the context of this workflow. We thank Dr. Lima for taking the time to review our workflow paper. The main aim of this workflow was to provide an overview of the essential steps required for the processing, analysis and interpretation of quantitative mass spectrometry-based expression proteomics data. We show two use case examples, one labelled TMT experiment and one label-free experimental design. It would have been nice to also include a SILAC use-case example, among other designs, but in the interest of length of the workflow we chose these two designs as they are typically the most popular in the field. Further, statistical analysis of SILAC experiments often applies a ratiometric approach, which differs from the statistics discussed here. As Dr. Lima states we indeed use Proteome Discoverer to process the data and show how to import a PSM, peptide or protein .txt data table into R and into a QFeatures object. All third-party MS search engines typically output a data table of quantitation data and for flexibility this is where we start our analysis. Header names in the output data will differ between softwares but should be transferable. Another popular third-party software used for quantitation and identification is MaxQuant and we have added a new section in the Appendix of our Github repository to show users how one might use data from MaxQuant in the context of this workflow. Competing Interests: No competing interests were disclosed. Close Report a concern Respond or Comment COMMENTS ON THIS REPORT Author Response 25 Sep 2024 Lisa Breckels , Cambridge Centre for Proteomics, University of Cambridge, Cambridge, CB2 1QR, UK 25 Sep 2024 Author Response We thank Dr. Lima for taking the time to review our workflow paper. The main aim of this workflow was to provide an overview of the essential steps required for ... Continue reading We thank Dr. Lima for taking the time to review our workflow paper. The main aim of this workflow was to provide an overview of the essential steps required for the processing, analysis and interpretation of quantitative mass spectrometry-based expression proteomics data. We show two use case examples, one labelled TMT experiment and one label-free experimental design. It would have been nice to also include a SILAC use-case example, among other designs, but in the interest of length of the workflow we chose these two designs as they are typically the most popular in the field. Further, statistical analysis of SILAC experiments often applies a ratiometric approach, which differs from the statistics discussed here. As Dr. Lima states we indeed use Proteome Discoverer to process the data and show how to import a PSM, peptide or protein .txt data table into R and into a QFeatures object. All third-party MS search engines typically output a data table of quantitation data and for flexibility this is where we start our analysis. Header names in the output data will differ between softwares but should be transferable. Another popular third-party software used for quantitation and identification is MaxQuant and we have added a new section in the Appendix of our Github repository to show users how one might use data from MaxQuant in the context of this workflow. We thank Dr. Lima for taking the time to review our workflow paper. The main aim of this workflow was to provide an overview of the essential steps required for the processing, analysis and interpretation of quantitative mass spectrometry-based expression proteomics data. We show two use case examples, one labelled TMT experiment and one label-free experimental design. It would have been nice to also include a SILAC use-case example, among other designs, but in the interest of length of the workflow we chose these two designs as they are typically the most popular in the field. Further, statistical analysis of SILAC experiments often applies a ratiometric approach, which differs from the statistics discussed here. As Dr. Lima states we indeed use Proteome Discoverer to process the data and show how to import a PSM, peptide or protein .txt data table into R and into a QFeatures object. All third-party MS search engines typically output a data table of quantitation data and for flexibility this is where we start our analysis. Header names in the output data will differ between softwares but should be transferable. Another popular third-party software used for quantitation and identification is MaxQuant and we have added a new section in the Appendix of our Github repository to show users how one might use data from MaxQuant in the context of this workflow. Competing Interests: No competing interests were disclosed. Close Report a concern COMMENT ON THIS REPORT Comments on this article Comments (0) Version 2 VERSION 2 PUBLISHED 24 Oct 2023 ADD YOUR COMMENT Comment keyboard_arrow_left keyboard_arrow_right Open Peer Review Reviewer Status info_outline Alongside their report, reviewers assign a status to the article: Approved The paper is scientifically sound in its current form and only minor, if any, improvements are suggested Approved with reservations A number of small changes, sometimes more significant revisions are required to address specific details and improve the papers academic merit. Not approved Fundamental flaws in the paper seriously undermine the findings and conclusions Reviewer Reports Invited Reviewers 1 2 3 4 5 Version 2 (revision) 25 Sep 24 read read Version 1 24 Oct 23 read read read Diogo Borges Lima , Leibniz - Forschungsinstitut für Molekulare Pharmakologie, Berlin, Germany Marie Locard-Paulet , Institut de Pharmacologie et de Biologie Structurale (IPBS), Toulouse, France; Université Toulouse III - Paul Sabatier (UT3), Toulouse, France Amit Kumar Yadav , Translational Health Science and Technology Institute (THSTI), Faridabad, India Giai Gianetto Quentin , University Paris Cité, Paris, France Julian Bender , Wuerzburg University, Würzburg, Germany Comments on this article All Comments (0) Add a comment Sign up for content alerts Sign Up You are now signed up to receive this alert Browse by related subjects keyboard_arrow_left Back to all reports Reviewer Report 0 Views copyright © 2025 Bender J. This is an open access peer review report distributed under the terms of the Creative Commons Attribution License , which permits unrestricted use, distribution, and reproduction in any medium, provided the original work is properly cited. 06 Feb 2025 | for Version 2 Julian Bender , Wuerzburg University, Würzburg, Germany 0 Views copyright © 2025 Bender J. This is an open access peer review report distributed under the terms of the Creative Commons Attribution License , which permits unrestricted use, distribution, and reproduction in any medium, provided the original work is properly cited. format_quote Cite this report speaker_notes Responses (0) Approved info_outline Alongside their report, reviewers assign a status to the article: Approved The paper is scientifically sound in its current form and only minor, if any, improvements are suggested Approved with reservations A number of small changes, sometimes more significant revisions are required to address specific details and improve the papers academic merit. Not approved Fundamental flaws in the paper seriously undermine the findings and conclusions The present article describes an R-based workflow for processing database search results from data-dependent analyses of label-free and TMT-labelled experiments generated with the ProteomeDiscoverer software (including a note describing how to transfer to results produced with the MaxQuant software) . The workflow employs readily available and well-documented R packages from the Bioconductor repository, facilitating both reproduction and adaptation. Moreover, the manuscript emphasises the use of the relatively recent QFeatures package to ensure result consistency across aggregation levels. The manuscript is well written, and the figures are concise, informative, and aligned with the text's argument. The authors not only present a robust approach for generating figures relevant to the biological interpretation of MS results (e.g., volcano and MA plots) but also include quality control metrics and data inspection guidelines. This enables users to tailor the workflow to their dataset, improving the generated results while also promoting critical evaluation. The code, search results, and raw files are available through Zenodo and PRIDE , respectively. I am fully confident that the manuscript is scientifically sound as it stands. Please consider the following comments as suggestions for further improvement. Major comments p. 6, Description of QFeatures and SummarizedExperiment: Since the SummarizedExperiment object is crucial for understanding the workflow, I suggest a more detailed explanation of its function. In particular, emphasis should be placed on describing colData and rowData as DataTables with row indices matching the assay’s row or column names, respectively. Additionally, the SummarizedExperiment container is described as having three components ( rowData , colData , assays ), yet Figure 2 also includes the metadata object as a fourth component. I recommend mentioning this in the text. p. 15: “Here, it is desirable to achieve an average MS2 injection time of 50 ms or less, although the exact target threshold will depend upon the sample load.” It should be noted that the maximum IT time is set in the instrument parameters for each MS run and should be optimised in relation to a specific AGC target (for Orbitrap instruments) by the instrument operator. Therefore, in the QC plot on p. 16, it is impossible to reach an average IT time exceeding 50 ms, as the maximum IT time is set to 50 ms. Instead, I suggest warning users that frequently reaching the maximum IT time during an MS run may indicate either an excessively high AGC target or insufficient ion current. p. 20, Calculation of TMT labelling efficiency: From an experimental perspective, I suggest calculating labelling efficiency per label (i.e., separately for TMT-126, TMT-127, etc.). This would help identify poor performance of individual labels (e.g., due to reagent hydrolysis). Furthermore, if the labelling test was performed after pooling only a subset of the available peptides, and sufficient peptide material remains, this approach would allow relabelling the underperforming sample before continuing with the analysis. p. 28, Assignment of FDR based on existing search results: The workflow suggests filtering PSMs by propagating peptide- or protein group-level FDR values to the underlying PSMs. However, PSMs may be aggregated differently in downstream analyses compared to the initial ProteomeDiscoverer search (e.g., based on gene names rather than master proteins), leading to uncontrolled FDR. Wouldn't it be more precise to retain decoys in the initial PSM table and perform FDR control separately at each aggregation level? Minor comments p. 4: “the exact details of which are anonymised for the purpose of this workflow” – Is there a specific reason not to disclose the exact perturbation analysed in this workflow? While this is not crucial for the analysis pipeline, it would be useful to verify known targets of the perturbation in the resulting volcano plot as an additional validation step. p. 11 and p. 50: “## Assign the colData to the first assay as well” – From this, I understand that both the QFeatures object and the nested SummarizedExperiment objects contain a colData attribute, and both need to be populated. This could be clarified in the introduction of QFeatures on p. 7. p. 12, Calculation of peptide and protein group numbers: The introduction highlights QFeatures ' ability to easily aggregate from the PSM to peptide and protein group levels. However, the number of peptides and protein groups is instead calculated from unique entries in the PSM table. A brief explanation that this avoids repeated QFeatures aggregation after each filtering step (which would clutter the QFeatures object) would aid the reader to understand the workflow at this position of the manuscript. p. 16: “Increasing the time allowed for ions to accumulate in the ion trap could also increase the number of PSMs.” – This is not necessarily the case, as a longer MS2 IT accumulation time reduces the number of ions targeted for MS2, which could ultimately decrease the number of PSMs. To facilitate interpretation, plotting the percentage of identified MS2 spectra against retention time might be helpful. p. 17, “PSM frequency across retention time”: It could be noted that a roughly uniform PSM distribution generally indicates a well defined LC gradient. Conversely, an increased PSM count at a particular gradient point suggests many peptides eluting simultaneously, which could be mitigated by flattening the gradient at this position. p. 17: “To demonstrate how to check for TMT labelling efficiency, only two of the eight fractions were utilised for this search.” – Based on the column names on p. 18, there seems to be no reference to individual fractions or raw files in the search results. Would the results and hence the analysis have differed if all eight fractions had been included? p. 74: “When plotting the former, users are advised to plot raw p-values rather than their derivative BH-adjusted p-values.” – What is the rationale for this recommendation? A brief explanation in the manuscript would be helpful. Is the rationale for developing the new software tool clearly explained? Yes Is the description of the software tool technically sound? Yes Are sufficient details of the code, methods and analysis (if applicable) provided to allow replication of the software development and its use by others? Yes Is sufficient information provided to allow interpretation of the expected output datasets and any results generated using the tool? Yes Are the conclusions about the tool and its performance adequately supported by the findings presented in the article? Yes Competing Interests No competing interests were disclosed. Reviewer Expertise I work on MS-based functional and structural (XL-MS, native MS) proteomics with a focus on data processing and computational analysis. I am developing software for data analysis downstream of database searches using Python and R as framework. I confirm that I have read this submission and believe that I have an appropriate level of expertise to confirm that it is of an acceptable scientific standard. reply Respond to this report Responses (0) Bender J. Peer Review Report For: A Bioconductor workflow for processing, evaluating, and interpreting expression proteomics data [version 2; peer review: 4 approved, 1 approved with reservations] . F1000Research 2024, 12 :1402 ( https://doi.org/10.5256/f1000research.168933.r357398) NOTE: it is important to ensure the information in square brackets after the title is included in this citation. The direct URL for this report is: https://f1000research.com/articles/12-1402/v2#referee-response-357398 keyboard_arrow_left Back to all reports Reviewer Report 0 Views copyright © 2025 Quentin G. This is an open access peer review report distributed under the terms of the Creative Commons Attribution License , which permits unrestricted use, distribution, and reproduction in any medium, provided the original work is properly cited. 22 Jan 2025 | for Version 2 Giai Gianetto Quentin , University Paris Cité, Paris, Île-de-France, France 0 Views copyright © 2025 Quentin G. This is an open access peer review report distributed under the terms of the Creative Commons Attribution License , which permits unrestricted use, distribution, and reproduction in any medium, provided the original work is properly cited. format_quote Cite this report speaker_notes Responses (0) Approved With Reservations info_outline Alongside their report, reviewers assign a status to the article: Approved The paper is scientifically sound in its current form and only minor, if any, improvements are suggested Approved with reservations A number of small changes, sometimes more significant revisions are required to address specific details and improve the papers academic merit. Not approved Fundamental flaws in the paper seriously undermine the findings and conclusions The article titled " A Bioconductor Workflow for Processing, Evaluating, and Interpreting Expression Proteomics Data " provides a detailed workflow for quantitative proteomics data analysis using R. The analysis of proteomics data is composed of many steps, and this paper presents a detailed application for quality control of acquired data, data filtering, and differential analysis using already published R packages from Proteome Discoverer outputs. Readers interested in conducting an in-depth analysis of their data can use the provided example as a foundation and adapt it to their own datasets. Comments : 1) I understand the value of presenting a complete workflow where each step is discussed in detail. However, the paper is not associated with a new R package and does not introduce novel methods for handling mass spectrometry-based proteomics data. As a result, it is unclear what is new or original about the proposed workflow. It would be helpful to provide clarification in the introduction to clearly highlight the workflow's originality. 2) To improve readability, the structure of the paper should be explained in the introduction. Since the paper exceeds 80 pages, outlining its structure is essential. The authors should include numbered sections and subsections to make it easier for readers to navigate and follow the content. 3) Figures do not have legends. They should be associated to a legend and references to them should be made in the text. 4) In several cases, the authors have included the output of R code as comments. This significantly increases the length of the paper without necessarily adding value. The paper would be more concise and readable if these outputs were included only when they are relevant and accompanied by explanatory commentary from the authors. For instance, on page 9 of the PDF, the output following the use of readQFeatures is useless, or the calls to cp_qf[[...]] seem redundant as they provide identical results. Similarly, pages 49 and 51 are filled with column names that do not appear to offer any meaningful insight. This issue occurs throughout the paper and does not benefit the reader. The authors should work to be more concise. 5) The section "Quality control of the raw mass spectrometry data" presents plots designed to assess data quality. At the end of the section, it is stated: "The four plots that we have generated look relatively standard with no obvious problems indicated.". Could the authors clarify how potential issues can be identified using these plots? For instance, the MS2 ion injection times fixed at 50 ms appear insufficient based on the plots in this section, which seems to contradict the authors' sentence. Also, R packages, such as PTXQC or proteoQC, can be used to investigate quality control of MS-based proteomics data using many metrics with R. The paper should mention some of them. 6) A number of arbitrary thresholds are used along the workflow for data filtering and statistical analysis. To ensure transparency and emphasize the parameters employed in the workflow, all these thresholds should be compiled into a readable table. This is particularly important, as such thresholds can significantly impact the final interpretation of the data. Being arbitrary, they are open to debate and warrant clear documentation. 7) On page 42 of the PDF, the authors apply a normalization method using median-centering. Based on the graph provided, it appears that the method reduces the differences in abundance between the « treated » and « control » samples, while « treated » ones generally seem to have lower overall abundances compared to the « control » samples before normalisation. Thus, this type of normalization risks missing proteins that are more abundant in the « control » samples. Would it not be better to preserve the observed gap between conditions and apply normalization within each condition while maintaining the observed overall difference between conditions? A discussion on this point needs to be provided. 8) In the part « Visualising aggregation », the paper lacks an explanation of the importance and relevance of visualizing this process. Including such an explanation would help readers understand why this visualization is essential and how it contributes to the overall analysis. For example, it could clarify how visualizing aggregation helps identify potential issues during data processing. 9) The conclusion states: « Existing bottom-up proteomics workflows for differential expression analysis either provide pipelines with limited user control and flexibility (e.g., MSstats and MSstatsTMT 34 , 35 ), can only be applied to specific data formats (e.g., Proteus which is limited to input from MaxQuant 51 ), or provide very limited commentary. ». However, this assertion appears arbitrary and is not supported by clear arguments. The authors should clarify what they mean by “limited.” For instance, MSstats and MSstatsTMT offer accessible tutorials and vignettes, which seem to provide sufficient explanations and flexibility for users. Regarding data formats, the authors wrote: « Finally, the majority of proteomics workflows utilise data.frame or tibble structures which limits their traceability, as is the case for protti, promor, and prolfqua. ». This statement is unclear. What exactly is the issue with using these structures? The authors themselves use tibble datasets all along their workflow, similar to the other packages (and not workflows) mentioned. This point needs further explanation to clarify what specific limitations the authors are referring to. In the conclusion, the authors state: “No single workflow can demonstrate the processing, analysis, and interpretation of all proteomics data.” However, it is unclear whether they are claiming to provide the first workflow capable of achieving this or not. From my perspective, their workflow relies heavily on several existing R packages that address specific key aspects, and the authors have leveraged these to construct their workflow. Furthermore, the workflow seems specifically tailored to their dataset, making it less of a universal approach and not something that can be directly applied to other datasets without modification. The authors should consider revising their wording to clarify what aspects of their workflow are intended to be universal, as this is currently unclear. Is the rationale for developing the new software tool clearly explained? Yes Is the description of the software tool technically sound? Yes Are sufficient details of the code, methods and analysis (if applicable) provided to allow replication of the software development and its use by others? Yes Is sufficient information provided to allow interpretation of the expected output datasets and any results generated using the tool? Yes Are the conclusions about the tool and its performance adequately supported by the findings presented in the article? Partly Competing Interests No competing interests were disclosed. Reviewer Expertise Biostatistics, bioinformatics I confirm that I have read this submission and believe that I have an appropriate level of expertise to confirm that it is of an acceptable scientific standard, however I have significant reservations, as outlined above. reply Respond to this report Responses (0) Quentin GG. Peer Review Report For: A Bioconductor workflow for processing, evaluating, and interpreting expression proteomics data [version 2; peer review: 4 approved, 1 approved with reservations] . F1000Research 2024, 12 :1402 ( https://doi.org/10.5256/f1000research.168933.r357415) NOTE: it is important to ensure the information in square brackets after the title is included in this citation. The direct URL for this report is: https://f1000research.com/articles/12-1402/v2#referee-response-357415 keyboard_arrow_left Back to all reports Reviewer Report 0 Views copyright © 2023 Yadav A. This is an open access peer review report distributed under the terms of the Creative Commons Attribution License , which permits unrestricted use, distribution, and reproduction in any medium, provided the original work is properly cited. 18 Dec 2023 | for Version 1 Amit Kumar Yadav , Translational Health Science and Technology Institute (THSTI), Faridabad, Haryana, India 0 Views copyright © 2023 Yadav A. This is an open access peer review report distributed under the terms of the Creative Commons Attribution License , which permits unrestricted use, distribution, and reproduction in any medium, provided the original work is properly cited. format_quote Cite this report speaker_notes Responses (1) Approved info_outline Alongside their report, reviewers assign a status to the article: Approved The paper is scientifically sound in its current form and only minor, if any, improvements are suggested Approved with reservations A number of small changes, sometimes more significant revisions are required to address specific details and improve the papers academic merit. Not approved Fundamental flaws in the paper seriously undermine the findings and conclusions The article by Hutchings et al titled "A Bioconductor Workflow for Processing, Evaluating, and Interpreting Expression Proteomics Data" provides a detailed overview tutorial of the interpretation of quantitative proteomics data through R environment using TMT and LFQ workflows as examples. Major comments: The use of open-source tools ensures transparency and reproducibility. The open-source R software packages from the Bioconductor project also add credibility to the workflow. The workflow described is comprehensive and is a good tutorial for analysis. The article describes the comprehensive workflow with R commands, covering data import, quality control, differential expression analysis, and gene ontology enrichment analysis. This approach ensures a holistic understanding of expression proteomics. The described use-case examples from TMT and LFQ provides practical relevance and enhances the applicability of the workflow. The target audience is for beginners who are also familiar with R. It may also be helpful to optionally provide shiny app (for GUI based application) that biologists who are unfamiliar with CLI, can also use. Minor Comments: This article deals with Proteome Discoverer output. Maybe inclusion of MaxQuant or other workflows may add to it reach. The difference between razor and shared peptides is not clear. Perhaps rephrasing would help a newcomer to proteomics. Page 40, (Under section Visualising Aggregation) “…15 peptides and 27 supporting…”. Did the author mean 27 PSMs? It is missing in the sentence. Please clarify if these were peptides or PSMs? PCA is not considered fit when there are lot of missing values as in LFQ analysis. Should these be removed before PCA? Authors have conflated modified and non-modified forms of the same peptides during analysis. This may not be able to detect modified changes if differential in nature. Perhaps “quantitative proteomics” is a more appropriate term than “Expression proteomics”. The article appears to be a valuable contribution to the field of quantitative proteomics, especially for R users, providing a comprehensive and user-friendly workflow. Is the rationale for developing the new software tool clearly explained? Yes Is the description of the software tool technically sound? Yes Are sufficient details of the code, methods and analysis (if applicable) provided to allow replication of the software development and its use by others? Yes Is sufficient information provided to allow interpretation of the expected output datasets and any results generated using the tool? Yes Are the conclusions about the tool and its performance adequately supported by the findings presented in the article? Yes Competing Interests No competing interests were disclosed. Reviewer Expertise quantitative proteomics, bioinformatics, computational biology, proteome informatics I confirm that I have read this submission and believe that I have an appropriate level of expertise to confirm that it is of an acceptable scientific standard. reply Respond to this report Responses (1) Author Response 25 Sep 2024 Lisa Breckels, Cambridge Centre for Proteomics, University of Cambridge, Cambridge, CB2 1QR, UK We would like to thank Dr. Yadav for reviewing our workflow paper and providing positive feedback. In response to Dr. Yadav’s minor comments, we have provided additional information on how to use this workflow with output from MaxQuant. This information can be found in a new section in the Appendix of our Github repository and is mentioned explicitly in the workflow. The sentence regarding shared and unique peptides has been changed slightly and additional discussion added to emphasise how protein inference and presence of isoforms can alter the definition of ‘unique’ peptides. We agree that missing values need to be addressed before performing PCA and as such in the workflow we use the function filterNA in QFeatures to remove missing data prior to any PCA performed. We have also explicitly stated that we conflate modified and non-modified forms of each peptides, and that users could aggregate by “Annotated. Sequence” if they wish to retain this information. However, the discovery of differences in the behaviour of these peptides would require peptide-level statistical analyses, which is outside of the scope of this workflow. View more View less Competing Interests No competing interests were disclosed. reply Respond Report a concern Yadav AK. Peer Review Report For: A Bioconductor workflow for processing, evaluating, and interpreting expression proteomics data [version 2; peer review: 4 approved, 1 approved with reservations] . F1000Research 2024, 12 :1402 ( https://doi.org/10.5256/f1000research.152361.r221408) NOTE: it is important to ensure the information in square brackets after the title is included in this citation. The direct URL for this report is: https://f1000research.com/articles/12-1402/v1#referee-response-221408 keyboard_arrow_left Back to all reports Reviewer Report 0 Views copyright © 2023 Locard-Paulet M. This is an open access peer review report distributed under the terms of the Creative Commons Attribution License , which permits unrestricted use, distribution, and reproduction in any medium, provided the original work is properly cited. 27 Nov 2023 | for Version 1 Marie Locard-Paulet , Institut de Pharmacologie et de Biologie Structurale (IPBS), Toulouse, France; Université Toulouse III - Paul Sabatier (UT3), Toulouse, France 0 Views copyright © 2023 Locard-Paulet M. This is an open access peer review report distributed under the terms of the Creative Commons Attribution License , which permits unrestricted use, distribution, and reproduction in any medium, provided the original work is properly cited. format_quote Cite this report speaker_notes Responses (1) Approved info_outline Alongside their report, reviewers assign a status to the article: Approved The paper is scientifically sound in its current form and only minor, if any, improvements are suggested Approved with reservations A number of small changes, sometimes more significant revisions are required to address specific details and improve the papers academic merit. Not approved Fundamental flaws in the paper seriously undermine the findings and conclusions The authors provide the full description of a R-based workflow applied to quantitative proteomics data analysis (TMT and label-free data). It makes use of QFeature objects, a structure that is very well suited for bottom-up proteomics data analysis. I think that this is a very nice step-by-step tutorial for MS-based proteomics data analysis with R for people who start in the field and have limited coding skills. Beyond its educational aspect, it provides the backbones of a data analysis pipeline that can be modified and published alongside any manuscript that includes MS-based proteomics data analysis. The manuscript is very well written, and the authors provide very clear and detailed instructions on how to use the workflow. The figures are also very clear and informative. They present the data, detail what quality control to perform to assess if the data are suitable for statistical analysis. This workflow contains a lot of useful QC plots and checks that are often overlooked, including TMT labelling efficiency calculation. It makes it a good step-by-step guide on how to analyze TMT-labelled bottom-up data. I really like the description on how to double check quality metrics such as S/N and isolation interference to adapt them to the data. The raw data is available in PRIDE and all the fasta files and the Proteome Discoverer output files are in Zenodo. The code is in a github repository. I easily found all the data associated with this manuscript. Major comments: It should be made clear that this script is tailored for Proteome Discoverer outputs (and maybe even for a given version of Proteome Discoverer). For most of the plotting/filtering/analysis steps, changing input would only require adapting the column names/headers, and most of the time it is very well discussed by the authors. Nevertheless, right now this script is only adapted to Proteome Discoverer outputs and this should be made clear in the abstract and the introduction, as well as the discussion. Aggregation of PSM quantification values to peptides and proteins: Here, the authors choose to aggregate all PSM intensities corresponding to the same sequence (stripped of its modifications). I would aggregate the PSM quantities per peptidoform (sequence + localized modifications) since two ions can have the same sequence but with modifications that are differentially regulated between the conditions compared. This should be mentioned. For the GO-term enrichment: only the majority protein accessions are reported in the output of the limma analysis. So there is only one gene per feature. How do you make sure that it is the most representative annotation for a given protein group? I am fully aware that this issue is ignored by the community (for lack of alternative strategy), and that most of the time people just pick one accession per group for GO-term enrichment analysis. So, I am not asking the authors to find a solution. Nevertheless, it would be nice to mention that the output of the enrichment will depend on what accession is picked per group. Minor comments: I would remove contaminants before estimation of TMT labelling efficiency. I find the paragraph “Additional considerations regarding protein isoforms” unclear. The authors should rephrase sentences such as this one: “PSMs or peptides that were previously mapped to one protein and one protein group could instead be mapped to multiple proteins and one protein group.” Maybe they should use the term “canonical protein” to be more precise? In any cases, the issue of peptide uniqueness does not depend only on the presence of isoforms in the fasta file but also on the strategy that was chosen for protein inference. I agree with the authors that people should precisely describe what peptides/PSMs were used for quantification, and it is good to mention it. Nevertheless, this level of detail on general MS-based proteomics concept may not be necessary here. (So the entire paragraph on isoforms could maybe be removed, especially since isoforms are not mentioned later). In the paragraph “Removing PSMs that are not rank 1”: I think that the “PSM category” that is discussed a bit later is specific of Proteome Discoverer. Some search engines report PSMs of equal score (this would correspond to the “pretty rank” in Mascot). I don’t think that all this should necessarily be discussed in this manuscript, but I insist on the fact that the workflow is tuned for Proteome Discoverer output and this should be made clear in the introduction/abstract. In the paragraph “Managing missing data” for the TMT: the authors mention MCAR, MAR, and MNAR, but do they all apply here? I would expect TMT-labelled data to mostly have missing values due to ions being under the limit of detection because when an ion is fragmented, the reporter ions used for relative quantification are often all detected. Isn’t it the case? Knowing this should restrict the choice for a more suited strategy of replacement of missing values. Still on missing values: page 33, it is stated that “Typically, it is desirable to remove features, here PSMs, with greater than 20% missing values”. Why this number? Is this accepted by the entire community? (this comment also applies to the same step in the LFQ analysis. Regarding missing value replacement (discussion on LFQ, page 55): it is really nice to provide references of strategies applied to replacement of missing values. It is indeed a tricky decision to make (how to replace? Should we replace?) and there is no one-size-fits-them-all method. Why do you choose to replace at peptide level and not protein level? Page 38: what do the authors mean by “report did not indicate any superior normalization method”? How would we know what normalization method works best? This point is because I am curious, not to correct any obvious mistake. It is great to try out different normalization strategies, but I don’t really see how to pick one based on the boxplots of normalized intensities (Figure 4). The authors normalize the data after protein aggregation and not at the PSM level. Is this general practice? Wouldn’t it make sense to normalize before aggregation? Page 44; “Data import, housekeeping and exploration”: the authors mention that LFQ analysis cannot be performed at PSM level but has to be done at peptide level. I think that this is dependent on the software tool that is used, and this may be specific of Proteome Discoverer. Match between run is performed at the ion level, but the intensity retrieved at this step can be reported at PSM level. I think that this is the case in MaxQuant “evidence.txt” tables, if I am not mistaken. Page 63: DEqMS could be mentioned since it is specifically developed for proteomics statistical analysis. (DOI: 10.1074/mcp.TIR119.001646) This is more of a naïve question regarding using Limma in this context: does it make sense to model the variance depending on intensity after missing value replacement? I know that this manuscript may not be the place to discuss this, but I would be interested to know what the authors’ opinion is on this question. Additional suggestions (only suggestions that may totally be ignored/dismissed by the authors if they don’t think that they’ll improve their manuscript): The data is available in PRIDE (PXD041794), but the information necessary to match TMT channel/sample to conditions/replicates is only available in the associated paper. It would be great to add the Table 1 of the manuscript and a link to the zenodo repository in PRIDE alongside the data. An even better solution would be to provide the metadata in the SDRF-Proteomics format ( https://www.nature.com/articles/s41467-021-26111-3 ; there is a GUI to generate these files now: https://lessdrf.streamlit.app/). This would facilitate data reuse and transparency. Small comments / typos: Page 3, in the code at the bottom of the page: the “,” is missing after “stringr”. Paragraph "Assessing the impact of non-specific data cleaning”, in the table (and other similar tables or mentions of number of protein groups and peptide stripped sequences): “proteins” should be replaced by “protein groups” since this is what is actually counted. If the authors wanted to be more precise, they could also specify that the “peptides” correspond to peptide sequences stripped of all modifications. Bar plot of missing value proportion page 32: what does the red dashed line correspond to? Page 37, when running the function `normalizer`, I got an error “No RT column specified (column named 'RT') or option not specified Skipping RT normalization.” And could not get the expected report. I am not familiar with the tool and did not investigate further. I don’t think that “softwares” can be used. There is no “s” at the end. Page 51: “cleaning is done is two steps” should be “cleaning is done in two steps” Page 54: in the bar plot of missing value count, what is the dashed red line? Page 55: “If the method requires data to display a normal distribution, users must log2 transform the data prior to imputation.” -> is there a reason to perform missing values replacement before log transformation? If not, this step could be moved to after log transform? Page 66: “If we had not used TMT labels and wished to include a logFC threshold, we could have included lfc = as an argument”. The characters of “ lfc = as ” are in a different police, I think that this is a bit unclear since the “as” should be regular text. Also, maybe you could explain “have included lfc = followed by the minimum absolute log2-transformed fold change”. Page 72: “summarize all packages and corresponding their versions used to generate” -> the sentence does not seem correct to me. Is the rationale for developing the new software tool clearly explained? Yes Is the description of the software tool technically sound? Yes Are sufficient details of the code, methods and analysis (if applicable) provided to allow replication of the software development and its use by others? Yes Is sufficient information provided to allow interpretation of the expected output datasets and any results generated using the tool? Yes Are the conclusions about the tool and its performance adequately supported by the findings presented in the article? Yes Competing Interests No competing interests were disclosed. Reviewer Expertise I work on MS-based proteomics data analysis and computational mass spectrometry. I confirm that I have read this submission and believe that I have an appropriate level of expertise to confirm that it is of an acceptable scientific standard. reply Respond to this report Responses (1) Author Response 25 Sep 2024 Lisa Breckels, Cambridge Centre for Proteomics, University of Cambridge, Cambridge, CB2 1QR, UK We thank Dr Locard-Paulet for her positive comments and have answered her additional comments below. Reviewer Comments: Major comments: It should be made clear that this script is tailored for Proteome Discoverer outputs (and maybe even for a given version of Proteome Discoverer). For most of the plotting/filtering/analysis steps, changing input would only require adapting the column names/headers, and most of the time it is very well discussed by the authors. Nevertheless, right now this script is only adapted to Proteome Discoverer outputs and this should be made clear in the abstract and the introduction, as well as the discussion. Author Response: We appreciate that both use-case datasets in this workflow were processed using Proteome Discoverer and have added text to emphasise this further in the abstract and introduction. Nevertheless, we feel that the workflow is still useful to users of alternative third-party software as the general data processing steps, and extensive discussion of these, remains relevant. To help users make the most out of this workflow, we have provided information on how to adapt the workflow from Proteome Discoverer files to those generated by MaxQuant, a free and accessible search software. This information is provided in a new section in the Appendix of our Github repository. Reviewer Comments: Aggregation of PSM quantification values to peptides and proteins: Here, the authors choose to aggregate all PSM intensities corresponding to the same sequence (stripped of its modifications). I would aggregate the PSM quantities per peptidoform (sequence + localized modifications) since two ions can have the same sequence but with modifications that are differentially regulated between the conditions compared. This should be mentioned. Author Response: As Dr Locard-Paulet mentions, it is possible for the same peptide sequence with and without modifications to behave differently. We have added the following to the workflow to acknowledge this: “For simplicity, we here aggregate all PSMs corresponding to the same stripped peptide sequence, regardless of whether they contain different modifications. If users are interested in exploring differential expression of protein isoforms or have reason to believe that post-translational modifications may be important in answering their question, PSMs could also be aggregated by "Annotated.Sequence" to preserve this information.” We agree that this point is worth drawing attention to. In order to observe any differential abundance of peptides when modified, statistical analysis would need to be carried out at the peptide-level. Since this is outside of the scope of this workflow, we continue to aggregate using the stripped sequence column to facilitate statistical analysis at the protein level. Reviewer Comments: For the GO-term enrichment: only the majority protein accessions are reported in the output of the limma analysis. So there is only one gene per feature. How do you make sure that it is the most representative annotation for a given protein group? I am fully aware that this issue is ignored by the community (for lack of alternative strategy), and that most of the time people just pick one accession per group for GO-term enrichment analysis. So, I am not asking the authors to find a solution. Nevertheless, it would be nice to mention that the output of the enrichment will depend on what accession is picked per group. Author Response: We agree with and acknowledge this point. Indeed, it is a limitation of protein inference that results in statistics and interpretation being done at the level of protein groups rather than individual proteins. As a result, we would always encourage users to explore their statistical hits, particularly those of interest for follow up. This would include tracing the protein group back down all data levels and potentially plotting an aggregation graph, as demonstrated in “Exploration of data using QFeatures links”. With regard to the output of GO enrichment, we do not expect the overall biological interpretation to be dramatically skewed as only protein lists with multiple proteins with the same GO annotation will be considered enriched. Therefore, even if a few of the master proteins are not representative of the protein which is actually changing in abundance, these few cases are unlikely to cause an incorrect enrichment. Nevertheless, it is always worthwhile for the user to examine the results to verify correct interpretation. Reviewer Comments: Minor comments: I would remove contaminants before estimation of TMT labelling efficiency. I find the paragraph “Additional considerations regarding protein isoforms” unclear. The authors should rephrase sentences such as this one: “PSMs or peptides that were previously mapped to one protein and one protein group could instead be mapped to multiple proteins and one protein group.” Maybe they should use the term “canonical protein” to be more precise? In any cases, the issue of peptide uniqueness does not depend only on the presence of isoforms in the fasta file but also on the strategy that was chosen for protein inference. I agree with the authors that people should precisely describe what peptides/PSMs were used for quantification, and it is good to mention it. Nevertheless, this level of detail on general MS-based proteomics concept may not be necessary here. (So the entire paragraph on isoforms could maybe be removed, especially since isoforms are not mentioned later). Author Response: We thank Dr Locard-Paulet for her input on this complex issue. We agree that for a beginner-level workflow, the discussion of isoforms may be confusing. We have removed the paragraph about isoforms, whilst adding some further comment on the importance of defining uniqueness above. Reviewer Comments: In the paragraph “Removing PSMs that are not rank 1”: I think that the “PSM category” that is discussed a bit later is specific of Proteome Discoverer. Some search engines report PSMs of equal score (this would correspond to the “pretty rank” in Mascot). I don’t think that all this should necessarily be discussed in this manuscript, but I insist on the fact that the workflow is tuned for Proteome Discoverer output and this should be made clear in the introduction/abstract. Author Response: We have included additional emphasis on Proteome Discoverer in the introduction to this workflow. That said, users of alternative software will still benefit from being aware of the concept of ‘PSM rank’. Reviewer Comments: In the paragraph “Managing missing data” for the TMT: the authors mention MCAR, MAR, and MNAR, but do they all apply here? I would expect TMT-labelled data to mostly have missing values due to ions being under the limit of detection because when an ion is fragmented, the reporter ions used for relative quantification are often all detected. Isn’t it the case? Knowing this should restrict the choice for a more suited strategy of replacement of missing values. Author Response: Indeed, knowing the reason behind missing values is important in deciding upon an imputation method. We have added an additional few sentences to outline this in the “Imputation” section of the TMT workflow. Nonetheless, we still wish to emphasise that in the use-case, and most datasets with such little missingness, it is not necessary to impute. Additional discussion has also been added under “The importance of knowing what you expect in missing values” to ensure that users consider their experimental design and quantitation strategy when assessing and dealing with missing values. Reviewer Comments: Still on missing values: page 33, it is stated that “Typically, it is desirable to remove features, here PSMs, with greater than 20% missing values”. Why this number? Is this accepted by the entire community? (this comment also applies to the same step in the LFQ analysis. Author Response: The percentage of missing data to allow per dataset will depend on the experimental design and number of samples. There are no strict rules on what one should allow and if imputation is required several groups report that up to 20% missing values in quantitative proteomics is acceptable (please see, for example, https://doi.org/10.1038/s41597-024-02922-z and https://doi.org/10.1186/s12864-022-08723-1 ) to maintain data structure as close to reality as possible. Reviewer Comments: Regarding missing value replacement (discussion on LFQ, page 55): it is really nice to provide references of strategies applied to replacement of missing values. It is indeed a tricky decision to make (how to replace? Should we replace?) and there is no one-size-fits-them-all method. Why do you choose to replace at peptide level and not protein level? Author Response: The reason that we typically choose to impute at the lowest possible data level is to avoid the implicit imputation that occurs during aggregation. For example, if a protein is supported by two peptides, and one peptide contains missing values whilst the other does not, aggregation would result in a protein level quantitation value without the user explicitly stating how to deal with the missing value. Reviewer Comments: Page 38: what do the authors mean by “report did not indicate any superior normalization method”? How would we know what normalization method works best? This point is because I am curious, not to correct any obvious mistake. It is great to try out different normalization strategies, but I don’t really see how to pick one based on the boxplots of normalized intensities (Figure 4). Author Response: In our experience of sharing and teaching this workflow, we have found that one of the most common questions is in regard to selecting an appropriate normalisation method. Therefore, we decided to include NormalyzerDE as one approach for users to make this decision. However, we appreciate that the results of this comparison are not particularly informative for either of the use-case datasets. As a result, we have decided to remove the NormalyzerDE example from the workflow and instead include further discussion. Reviewer Comments: The authors normalize the data after protein aggregation and not at the PSM level. Is this general practice? Wouldn’t it make sense to normalize before aggregation? Author Response: We acknowledge that this decision is not a simple one, and not one which has a consensus in the literature. For example, some workflows choose to normalise at lower data levels so that normalisation can occur prior to imputation. We typically choose to normalise data at the protein level because this is the level at which statistical analyses are carried out. As the goal of normalisation is to remove non-biological variation to increase statistical power and lead to the discovery of meaningful, biological variation, we feel it makes the most sense to do this step immediately before statistics. Normalising the data at PSM or peptide level would not account for any small variation re-introduced during aggregation (depending upon the selected aggregation method). Reviewer Comments: Page 44; “Data import, housekeeping and exploration”: the authors mention that LFQ analysis cannot be performed at PSM level but has to be done at peptide level. I think that this is dependent on the software tool that is used, and this may be specific of Proteome Discoverer. Match between run is performed at the ion level, but the intensity retrieved at this step can be reported at PSM level. I think that this is the case in MaxQuant “evidence.txt” tables, if I am not mistaken. Author Response: We thank Dr Locard-Paulet for pointing this out and have adjusted the text in the LFQ data import section accordingly. Reviewer Comments: Page 63: DEqMS could be mentioned since it is specifically developed for proteomics statistical analysis. (http://doi.org/10.1074/mcp.TIR119.001646) Author Response: Thank you for this suggestion. We have now mentioned and referenced this package in the appropriate place. Reviewer Comments: This is more of a naïve question regarding using Limma in this context: does it make sense to model the variance depending on intensity after missing value replacement? I know that this manuscript may not be the place to discuss this, but I would be interested to know what the authors’ opinion is on this question. Author Response: We agree with the reviewer that one does need to be cautious, and in the text, we advise users to check their data following imputation and that the distribution has not dramatically changed. As we mention in the manuscript it is now possible to use packages such as msqRob2 to facilitates statistical differential expression analysis on datasets without the need for imputation. With the limma package, for a given protein, the cases with missing values are removed both from the data and design matrix. That is, the linear model is fitted to the non-missing values. If a particular regression co-efficient cannot be estimated from the observed data for a protein of interest, then a NA value will be returned for that coefficient. Reviewer Comments: Additional suggestions (only suggestions that may totally be ignored/dismissed by the authors if they don’t think that they’ll improve their manuscript): The data is available in PRIDE (PXD041794), but the information necessary to match TMT channel/sample to conditions/replicates is only available in the associated paper. It would be great to add the Table 1 of the manuscript and a link to the zenodo repository in PRIDE alongside the data. An even better solution would be to provide the metadata in the SDRF-Proteomics format ( https://www.nature.com/articles/s41467-021-26111-3 ; there is a GUI to generate these files now: https://lessdrf.streamlit.app/). This would facilitate data reuse and transparency. Small comments / typos: Page 3, in the code at the bottom of the page: the “,” is missing after “stringr”. Paragraph "Assessing the impact of non-specific data cleaning”, in the table (and other similar tables or mentions of number of protein groups and peptide stripped sequences): “proteins” should be replaced by “protein groups” since this is what is actually counted. If the authors wanted to be more precise, they could also specify that the “peptides” correspond to peptide sequences stripped of all modifications. Bar plot of missing value proportion page 32: what does the red dashed line correspond to? Page 37, when running the function `normalizer`, I got an error “No RT column specified (column named 'RT') or option not specified Skipping RT normalization.” And could not get the expected report. I am not familiar with the tool and did not investigate further. I don’t think that “softwares” can be used. There is no “s” at the end. Page 51: “cleaning is done is two steps” should be “cleaning is done in two steps” Page 54: in the bar plot of missing value count, what is the dashed red line? Page 55: “If the method requires data to display a normal distribution, users must log2 transform the data prior to imputation.” -> is there a reason to perform missing values replacement before log transformation? If not, this step could be moved to after log transform? Page 66: “If we had not used TMT labels and wished to include a logFC threshold, we could have included lfc = as an argument”. The characters of “ lfc = as ” are in a different police, I think that this is a bit unclear since the “as” should be regular text. Also, maybe you could explain “have included lfc = followed by the minimum absolute log2-transformed fold change”. Page 72: “summarize all packages and corresponding their versions used to generate” -> the sentence does not seem correct to me. Author Response: We would like to thank Dr. Locard-Paulet for being so thorough in reviewing the manuscript. We have corrected the highlighted typos. View more View less Competing Interests No competing interests were disclosed. reply Respond Report a concern Locard-Paulet M. Peer Review Report For: A Bioconductor workflow for processing, evaluating, and interpreting expression proteomics data [version 2; peer review: 4 approved, 1 approved with reservations] . F1000Research 2024, 12 :1402 ( https://doi.org/10.5256/f1000research.152361.r221410) NOTE: it is important to ensure the information in square brackets after the title is included in this citation. The direct URL for this report is: https://f1000research.com/articles/12-1402/v1#referee-response-221410 keyboard_arrow_left Back to all reports Reviewer Report 0 Views copyright © 2023 Borges Lima D. This is an open access peer review report distributed under the terms of the Creative Commons Attribution License , which permits unrestricted use, distribution, and reproduction in any medium, provided the original work is properly cited. The author(s) is/are employees of the US Government and therefore domestic copyright protection in USA does not apply to this work. The work may be protected under the copyright laws of other jurisdictions when used in those jurisdictions. 27 Nov 2023 | for Version 1 Diogo Borges Lima , Leibniz - Forschungsinstitut für Molekulare Pharmakologie, Berlin, Germany 0 Views copyright © 2023 Borges Lima D. This is an open access peer review report distributed under the terms of the Creative Commons Attribution License , which permits unrestricted use, distribution, and reproduction in any medium, provided the original work is properly cited. The author(s) is/are employees of the US Government and therefore domestic copyright protection in USA does not apply to this work. The work may be protected under the copyright laws of other jurisdictions when used in those jurisdictions. format_quote Cite this report speaker_notes Responses (1) Approved info_outline Alongside their report, reviewers assign a status to the article: Approved The paper is scientifically sound in its current form and only minor, if any, improvements are suggested Approved with reservations A number of small changes, sometimes more significant revisions are required to address specific details and improve the papers academic merit. Not approved Fundamental flaws in the paper seriously undermine the findings and conclusions The article entitled "A Bioconductor workflow for processing, evaluating, and interpreting expression proteomics data" regards a full and comprehensive workflow for performing not only qualitative but also quantitative proteomics analysis. The manuscript is very well written and describes in detail the whole workflow for quantifying proteomics data. The authors focused on the LFQ analysis and TMT (for labeled datasets). However, this workflow relies on the results from a search engine that will provide the identified peptides. On this manuscript the authors used results from Proteome Discoverer. I recommended the publication, but I would like to pinpoint some minor comments: a) Although the authors mentioned the quantitation analyses by using TMT for labeled datasets, why they didn't show the analysis by using SILAC, once it uses XIC (the same strategy used by LFQ)? b) The authors used Proteome Discoverer as search engine, and the provided a template to import the results into the workflow. They could also provide other templates to turn this workflow more versatile, such as FragPipe, Patternlab for Proteomics, etc. Is the rationale for developing the new software tool clearly explained? Yes Is the description of the software tool technically sound? Yes Are sufficient details of the code, methods and analysis (if applicable) provided to allow replication of the software development and its use by others? Yes Is sufficient information provided to allow interpretation of the expected output datasets and any results generated using the tool? Yes Are the conclusions about the tool and its performance adequately supported by the findings presented in the article? Yes Competing Interests No competing interests were disclosed. Reviewer Expertise I have experience in proteomics analyses (qualitative and quantitative); XL-MS analysis. I also develop software for identifying and quantifying proteomics datasets. I confirm that I have read this submission and believe that I have an appropriate level of expertise to confirm that it is of an acceptable scientific standard. reply Respond to this report Responses (1) Author Response 25 Sep 2024 Lisa Breckels, Cambridge Centre for Proteomics, University of Cambridge, Cambridge, CB2 1QR, UK We thank Dr. Lima for taking the time to review our workflow paper. The main aim of this workflow was to provide an overview of the essential steps required for the processing, analysis and interpretation of quantitative mass spectrometry-based expression proteomics data. We show two use case examples, one labelled TMT experiment and one label-free experimental design. It would have been nice to also include a SILAC use-case example, among other designs, but in the interest of length of the workflow we chose these two designs as they are typically the most popular in the field. Further, statistical analysis of SILAC experiments often applies a ratiometric approach, which differs from the statistics discussed here. As Dr. Lima states we indeed use Proteome Discoverer to process the data and show how to import a PSM, peptide or protein .txt data table into R and into a QFeatures object. All third-party MS search engines typically output a data table of quantitation data and for flexibility this is where we start our analysis. Header names in the output data will differ between softwares but should be transferable. Another popular third-party software used for quantitation and identification is MaxQuant and we have added a new section in the Appendix of our Github repository to show users how one might use data from MaxQuant in the context of this workflow. View more View less Competing Interests No competing interests were disclosed. reply Respond Report a concern Borges Lima D. Peer Review Report For: A Bioconductor workflow for processing, evaluating, and interpreting expression proteomics data [version 2; peer review: 4 approved, 1 approved with reservations] . F1000Research 2024, 12 :1402 ( https://doi.org/10.5256/f1000research.152361.r221416) NOTE: it is important to ensure the information in square brackets after the title is included in this citation. The direct URL for this report is: https://f1000research.com/articles/12-1402/v1#referee-response-221416 Alongside their report, reviewers assign a status to the article: Approved - the paper is scientifically sound in its current form and only minor, if any, improvements are suggested Approved with reservations - A number of small changes, sometimes more significant revisions are required to address specific details and improve the papers academic merit. Not approved - fundamental flaws in the paper seriously undermine the findings and conclusions Adjust parameters to alter display View on desktop for interactive features Includes Interactive Elements View on desktop for interactive features Competing Interests Policy Provide sufficient details of any financial or non-financial competing interests to enable users to assess whether your comments might lead a reasonable person to question your impartiality. Consider the following examples, but note that this is not an exhaustive list: Examples of 'Non-Financial Competing Interests' Within the past 4 years, you have held joint grants, published or collaborated with any of the authors of the selected paper. You have a close personal relationship (e.g. parent, spouse, sibling, or domestic partner) with any of the authors. You are a close professional associate of any of the authors (e.g. scientific mentor, recent student). You work at the same institute as any of the authors. You hope/expect to benefit (e.g. favour or employment) as a result of your submission. You are an Editor for the journal in which the article is published. Examples of 'Financial Competing Interests' You expect to receive, or in the past 4 years have received, any of the following from any commercial organisation that may gain financially from your submission: a salary, fees, funding, reimbursements. You expect to receive, or in the past 4 years have received, shared grant support or other funding with any of the authors. You hold, or are currently applying for, any patents or significant stocks/shares relating to the subject matter of the paper you are commenting on. Stay Updated Sign up for content alerts and receive a weekly or monthly email with all newly published articles Register with F1000Research Already registered? Sign in Not now, thanks close PLEASE NOTE If you are an AUTHOR of this article, please check that you signed in with the account associated with this article otherwise we cannot automatically identify your role as an author and your comment will be labelled as a “User Comment”. If you are a REVIEWER of this article, please check that you have signed in with the account associated with this article and then go to your account to submit your report, please do not post your review here. If you do not have access to your original account, please contact us . All commenters must hold a formal affiliation as per our Policies . The information that you give us will be displayed next to your comment. User comments must be in English, comprehensible and relevant to the article under discussion. We reserve the right to remove any comments that we consider to be inappropriate, offensive or otherwise in breach of the User Comment Terms and Conditions . Commenters must not use a comment for personal attacks. When criticisms of the article are based on unpublished data, the data should be made available. I accept the User Comment Terms and Conditions Please confirm that you accept the User Comment Terms and Conditions. Affiliation ✕ refresh Please enter your institution. Note: To add your institution or organisation, start typing the name and then select the correct name from the list. Where applicable, the name will appear in both the original language and in English. Do not paste in the name. If the name does not appear in the drop-down list, we will display the information you have entered. ✕ refresh Country/Region * USA UK Canada China France Germany Afghanistan Aland Islands Albania Algeria American Samoa Andorra Angola Anguilla Antarctica Antigua and Barbuda Argentina Armenia Aruba Australia Austria Azerbaijan Bahamas Bahrain Bangladesh Barbados Belarus Belgium Belize Benin Bermuda Bhutan Bolivia Bosnia and Herzegovina Botswana Bouvet Island Brazil British Indian Ocean Territory British Virgin Islands Brunei Bulgaria Burkina Faso Burundi Cambodia Cameroon Canada Cape Verde Cayman Islands Central African Republic Chad Chile China Christmas Island Cocos (Keeling) Islands Colombia Comoros Congo Cook Islands Costa Rica Cote d'Ivoire Croatia Cuba Cyprus Czech Republic Democratic Republic of the Congo Denmark Djibouti Dominica Dominican Republic Ecuador Egypt El Salvador Equatorial Guinea Eritrea Estonia Ethiopia Falkland Islands Faroe Islands Federated States of Micronesia Fiji Finland France French Guiana French Polynesia French Southern Territories Gabon Georgia Germany Ghana Gibraltar Greece Greenland Grenada Guadeloupe Guam Guatemala Guernsey Guinea Guinea-Bissau Guyana Haiti Heard Island and Mcdonald Islands Holy See (Vatican City State) Honduras Hong Kong Hungary Iceland India Indonesia Iran Iraq Ireland Israel Italy Jamaica Japan Jersey Jordan Kazakhstan Kenya Kiribati Kosovo (Serbia and Montenegro) Kuwait Kyrgyzstan Lao People's Democratic Republic Latvia Lebanon Lesotho Liberia Libya Liechtenstein Lithuania Luxembourg Macao Madagascar Malawi Malaysia Maldives Mali Malta Marshall Islands Martinique Mauritania Mauritius Mayotte Mexico Minor Outlying Islands of the United States Moldova Monaco Mongolia Montenegro Montserrat Morocco Mozambique Myanmar Namibia Nauru Nepal Netherlands Antilles New Caledonia New Zealand Nicaragua Niger Nigeria Niue Norfolk Island North Korea North Macedonia Northern Mariana Islands Norway Oman Pakistan Palau Palestinian Territory Panama Papua New Guinea Paraguay Peru Philippines Pitcairn Poland Portugal Puerto Rico Qatar Reunion Romania Russian Federation Rwanda Saint Helena Saint Kitts and Nevis Saint Lucia Saint Pierre and Miquelon Saint Vincent and the Grenadines Samoa San Marino Sao Tome and Principe Saudi Arabia Senegal Serbia Seychelles Sierra Leone Singapore Slovakia Slovenia Solomon Islands Somalia South Africa South Georgia and the South Sandwich Is South Korea South Sudan Spain Sri Lanka Sudan Suriname Svalbard and Jan Mayen Swaziland Sweden Switzerland Syria Taiwan Tajikistan Tanzania Thailand The Gambia The Netherlands Timor-Leste Togo Tokelau Tonga Trinidad and Tobago Tunisia Turkey Turkmenistan Turks and Caicos Islands Tuvalu UK USA Uganda Ukraine United Arab Emirates United States Virgin Islands Uruguay Uzbekistan Vanuatu Venezuela Vietnam Wallis and Futuna West Bank and Gaza Strip Western Sahara Yemen Zambia Zimbabwe Please select your country/region. You must enter a comment. Competing Interests Please disclose any competing interests that might be construed to influence your judgment of the article's or peer review report's validity or importance. Competing Interests Policy Provide sufficient details of any financial or non-financial competing interests to enable users to assess whether your comments might lead a reasonable person to question your impartiality. Consider the following examples, but note that this is not an exhaustive list: Examples of 'Non-Financial Competing Interests' Within the past 4 years, you have held joint grants, published or collaborated with any of the authors of the selected paper. You have a close personal relationship (e.g. parent, spouse, sibling, or domestic partner) with any of the authors. You are a close professional associate of any of the authors (e.g. scientific mentor, recent student). You work at the same institute as any of the authors. You hope/expect to benefit (e.g. favour or employment) as a result of your submission. You are an Editor for the journal in which the article is published. Examples of 'Financial Competing Interests' You expect to receive, or in the past 4 years have received, any of the following from any commercial organisation that may gain financially from your submission: a salary, fees, funding, reimbursements. You expect to receive, or in the past 4 years have received, shared grant support or other funding with any of the authors. You hold, or are currently applying for, any patents or significant stocks/shares relating to the subject matter of the paper you are commenting on. Please state your competing interests The comment has been saved. An error has occurred. Please try again. Cancel Post var lTitle = "A Bioconductor workflow for processing, evaluating,...".replace("'", ''); var linkedInUrl = "http://www.linkedin.com/shareArticle?url=https://f1000research.com/articles/12-1402/v2" + "&title=" + encodeURIComponent(lTitle) + "&summary=" + encodeURIComponent('Read the article by '); var deliciousUrl = "https://del.icio.us/post?url=https://f1000research.com/articles/12-1402/v2&title=" + encodeURIComponent(lTitle); var redditUrl = "http://reddit.com/submit?url=https://f1000research.com/articles/12-1402/v2" + "&title=" + encodeURIComponent(lTitle); linkedInUrl += encodeURIComponent('Hutchings C et al.'); var offsetTop = /chrome/i.test( navigator.userAgent ) ? 4 : -10; var addthis_config = { ui_offset_top: offsetTop, services_compact : "facebook,twitter,www.linkedin.com,www.mendeley.com,reddit.com", services_expanded : "facebook,twitter,www.linkedin.com,www.mendeley.com,reddit.com", services_custom : [ { name: "LinkedIn", url: linkedInUrl, icon:"/img/icon/at_linkedin.svg" }, { name: "Mendeley", url: "http://www.mendeley.com/import/?url=https://f1000research.com/articles/12-1402/v2/mendeley", icon:"/img/icon/at_mendeley.svg" }, { name: "Reddit", url: redditUrl, icon:"/img/icon/at_reddit.svg" }, ] }; var addthis_share = { url: "https://f1000research.com/articles/12-1402", templates : { twitter : "A Bioconductor workflow for processing, evaluating, and interpreting.... Hutchings C et al., published by " + "@F1000Research" + ", https://f1000research.com/articles/12-1402/v2" } }; if (typeof(addthis) != "undefined"){ addthis.addEventListener('addthis.ready', checkCount); addthis.addEventListener('addthis.menu.share', checkCount); } $(".f1r-shares-twitter").attr("href", "https://twitter.com/intent/tweet?text=" + addthis_share.templates.twitter); $(".f1r-shares-facebook").attr("href", "https://www.facebook.com/sharer/sharer.php?u=" + addthis_share.url); $(".f1r-shares-linkedin").attr("href", addthis_config.services_custom[0].url); $(".f1r-shares-reddit").attr("href", addthis_config.services_custom[2].url); $(".f1r-shares-mendelay").attr("href", addthis_config.services_custom[1].url); function checkCount(){ setTimeout(function(){ $(".addthis_button_expanded").each(function(){ var count = $(this).text(); if (count !== "" && count != "0") $(this).removeClass("is-hidden"); else $(this).addClass("is-hidden"); }); }, 1000); } close How to cite this report {{reportCitation}} Cancel Copy Citation Details $(function(){R.ui.buttonDropdowns('.dropdown-for-downloads');}); $(function(){R.ui.toolbarDropdowns('.toolbar-dropdown-for-downloads');}); $.get("/articles/acj/139116/168933") new F1000.Clipboard(); new F1000.ThesaurusTermsDisplay("articles", "article", "168933"); $(document).ready(function() { $( "#frame1" ).on('load', function() { var mydiv = $(this).contents().find("div"); var h = mydiv.height(); console.log(h) }); var tooltipLivingFigure = jQuery(".interactive-living-figure-label .icon-more-info"), titleLivingFigure = tooltipLivingFigure.attr("title"); tooltipLivingFigure.simpletip({ fixed: true, position: ["-115", "30"], baseClass: 'small-tooltip', content:titleLivingFigure + " " }); tooltipLivingFigure.removeAttr("title"); $("body").on("click", ".cite-living-figure", function(e) { e.preventDefault(); var ref = $(this).attr("data-ref"); $(this).closest(".living-figure-list-container").find("#" + ref).fadeIn(200); }); $("body").on("click", ".close-cite-living-figure", function(e) { e.preventDefault(); $(this).closest(".popup-window-wrapper").fadeOut(200); }); $(document).on("mouseup", function(e) { var metricsContainer = $(".article-metrics-popover-wrapper"); if (!metricsContainer.is(e.target) && metricsContainer.has(e.target).length === 0) { $(".article-metrics-close-button").click(); } }); var articleId = $('#articleId').val(); if($("#main-article-count-box").attachArticleMetrics) { $("#main-article-count-box").attachArticleMetrics(articleId, { articleMetricsView: true }); } }); var figshareWidget = $(".new_figshare_widget"); if (figshareWidget.length > 0) { window.figshare.load("f1000", function(Widget) { // Select a tag/tags defined in your page. In this tag we will place the widget. _.map(figshareWidget, function(el){ var widget = new Widget({ articleId: $(el).attr("figshare_articleId") //height:300 // this is the height of the viewer part. [Default: 550] }); widget.initialize(); // initialize the widget widget.mount(el); // mount it in a tag that's on your page // this will save the widget on the global scope for later use from // your JS scripts. This line is optional. //window.widget = widget; }); }); } close Error Close Add Reset F1000.MICROSERVICES.AFFILIATION = ''; $(document).ready(function () { $('.js-affiliations-form').each((index, form) => { new AffiliationForm({ formId: form.id, institutionErrorSelector: '.comment-enter-institution', departmentErrorSelector: '.comment-enter-department', placeSelector: '.js-add-comment-place', stateSelector: '.js-add-comment-state', zipCodeSelector: '.js-add-comment-zipcode', countrySelector: '.js-add-comment-country', countryErrorSelector: '.comment-enter-country', }); }); }); $(document).ready(function () { var reportIds = { "357398": 23, "357407": 0, "221406": 0, "221404": 0, "357413": 0, "221410": 48, "357412": 0, "357415": 41, "221408": 38, "357414": 0, "357409": 0, "221414": 0, "357408": 0, "357411": 0, "221412": 0, "357410": 0, "221419": 0, "326828": 0, "221417": 0, "221416": 53, "221423": 0, "221421": 0, "326826": 0, "326827": 0, "218167": 0, "218171": 0, "218170": 0, "218169": 0, "218168": 0, }; $(".referee-response-container,.js-referee-report").each(function(index, el) { var reportId = $(el).attr("data-reportid"), reportCount = reportIds[reportId] || 0; $(el).find(".comments-count-container,.js-referee-report-views").html(reportCount); }); var uuidInput = $("#article_uuid"), oldUUId = uuidInput.val(), newUUId = "90a7bc5f-c743-4160-9d4a-a76b228daffd"; uuidInput.val(newUUId); $("a[href*='article_uuid=']").each(function(index, el) { var newHref = $(el).attr("href").replace(oldUUId, newUUId); $(el).attr("href", newHref); }); }); An innovative open access publishing platform offering rapid publication and open peer review, whilst supporting data deposition and sharing. Browse Gateways Collections How it Works Contact For Developers Cookie Notice Privacy Notice RSS Submit Your Research Follow us © 2012-2026 F1000 Research Ltd. ISSN 2046-1402 | Legal | Partner of Research4Life • CrossRef • ORCID • FAIRSharing R.templateTests.simpleTemplate = R.template(' $text $text $text $text $text '); R.templateTests.runTests(); var F1000platform = new F1000.Platform({ name: "f1000research", displayName: "F1000Research", hostName: "f1000research.com", id: "1", editorialEmail: "[email protected]", infoEmail: "[email protected]", usePmcStats: true }); $(function(){R.ui.dropdowns('.dropdown-for-authors, .dropdown-for-about, .dropdown-for-myresearch');}); // $(function(){R.ui.dropdowns('.dropdown-for-referees');}); $(document).ready(function () { if ($(".cookie-warning").is(":visible")) { $(".sticky").css("margin-bottom", "35px"); $(".devices").addClass("devices-and-cookie-warning"); } $(".cookie-warning .close-button").click(function (e) { $(".devices").removeClass("devices-and-cookie-warning"); $(".sticky").css("margin-bottom", "0"); }); $("#tweeter-feed .tweet-message").each(function (i, message) { var self = $(message); self.html(linkify(self.html())); }); $(".partner").on("mouseenter mouseleave", function() { $(this).find(".gray-scale, .colour").toggleClass("is-hidden"); }); }); Sign In Remember me Forgotten your password? Sign In Cancel Email or password not correct. Please try again Please wait... $(function(){ // Note: All the setup needs to run against a name attribute and *not* the id due the clonish // nature of facebox... $("a[id=googleSignInButton]").click(function(event){ event.preventDefault(); $("input[id=oAuthSystem]").val("GOOGLE"); $("form[id=oAuthForm]").submit(); }); $("a[id=facebookSignInButton]").click(function(event){ event.preventDefault(); $("input[id=oAuthSystem]").val("FACEBOOK"); $("form[id=oAuthForm]").submit(); }); $("a[id=orcidSignInButton]").click(function(event){ event.preventDefault(); $("input[id=oAuthSystem]").val("ORCID"); $("form[id=oAuthForm]").submit(); }); }); If you've forgotten your password, please enter your email address below and we'll send you instructions on how to reset your password. The email address should be the one you originally registered with F1000. Email address not valid, please try again You registered with F1000 via Google, so we cannot reset your password. To sign in, please click here . If you still need help with your Google account password, please click here . You registered with F1000 via Facebook, so we cannot reset your password. To sign in, please click here . If you still need help with your Facebook account password, please click here . Code not correct, please try again Reset password Cancel Email us for further assistance. Server error, please try again. If your email address is registered with us, we will email you instructions to reset your password. If you think you should have received this email but it has not arrived, please check your spam filters and/or contact for further assistance. Please wait... Register $(document).ready(function () { signIn.createSignInAsRow($("#sign-in-form-gfb-popup")); $(".target-field").each(function () { var uris = $(this).val().split("/"); if (uris.pop() === "login") { $(this).val(uris.toString().replace(",","/")); } }); });

Text is read by the "Ask this paper" AI Q&A widget below. Extraction quality varies by source — PMC NXML preserves structure cleanly, OA-HTML may include some navigation residue, and OA-PDF can have broken hyphenation. The publisher copy (via DOI) is the canonical version.

My notes (saved in your browser only)

Ask this paper AI returns verbatim quotes from the full text · source: preprint-html

Answers must be backed by verbatim quotes from this paper's full text. Hallucinated quotes are dropped automatically; if no verbatim passage answers the question, we say so. How this works

Citation neighborhood (no data yet)

We don't have any in-corpus citations linked to this paper yet. This is a recent paper (2024) — citers typically take a year or two to land, and the OpenAlex reference graph may still be filling in.

Source provenance

europepmc
last seen: 2026-05-20T01:45:00.602351+00:00