Creative Commons License

This is part of the online course Proteomics Data Analysis (PDA)

Outline

  1. Introduction

  2. Preprocessing

    • Log-transformation
    • Filtering
    • Normalization
    • Summarization

Note, that the R-code is included for learners who are aiming to develop R/markdown scripts to automate their quantitative proteomics data analyses. According to the target audience of the course we either work with a graphical user interface (GUI) in a R/shiny App msqrob2gui (e.g. Proteomics Bioinformatics course of the EBI and the Proteomics Data Analysis course at the Gulbenkian institute) or with R/markdowns scripts (e.g. Bioinformatics Summer School at UCLouvain or the Statistical Genomics Course at Ghent University).


1 Intro: Challenges in Label-Free Quantitative Proteomics

1.1 MS-based workflow

  • Peptide Characteristics

    • Modifications
    • Ionisation Efficiency: huge variability
    • Identification
      • Misidentification \(\rightarrow\) outliers
      • MS\(^2\) selection on peptide abundance
      • Context depending missingness
      • Non-random missingness

\(\rightarrow\) Unbalanced pepide identifications across samples and messy data


1.2 Level of quantification

  • MS-based proteomics returns peptides: pieces of proteins

  • Quantification commonly required on the protein level


1.3 Label-free Quantitative Proteomics Data Analysis Workflows


1.4 CPTAC Spike-in Study

  • Same trypsin-digested yeast proteome background in each sample

  • Trypsin-digested Sigma UPS1 standard: 48 different human proteins spiked in at 5 different concentrations (treatment A-E)

  • Samples repeatedly run on different instruments in different labs

  • After MaxQuant search with match between runs option

    • 41% of all proteins are quantified in all samples
    • 6.6% of all peptides are quantified in all samples

\(\rightarrow\) vast amount of missingness

1.5 Maxquant output


2 Import the data in R

2.1 Data infrastructure

Click to see background on data infrastructure used in R to store proteomics data

  • We use the QFeatures package that provides the infrastructure to
    • store,
    • process,
    • manipulate and
    • analyse quantitative data/features from mass spectrometry experiments.
  • It is based on the SummarizedExperiment and MultiAssayExperiment classes.
Conceptual representation of a `SummarizedExperiment` object.  Assays contain information on the measured omics features (rows) for different samples (columns). The `rowData` contains information on the omics features, the `colData` contains information on the samples, i.e. experimental design etc.

Conceptual representation of a SummarizedExperiment object. Assays contain information on the measured omics features (rows) for different samples (columns). The rowData contains information on the omics features, the colData contains information on the samples, i.e. experimental design etc.

  • Assays in a QFeatures object have a hierarchical relation:

    • proteins are composed of peptides,
    • themselves produced by spectra
    • relations between assays are tracked and recorded throughout data processing
Conceptual representation of a `QFeatures` object and the aggregative relation between different assays.

Conceptual representation of a QFeatures object and the aggregative relation between different assays.

2.2 Import data in R

2.2.1 Load libraries

Click to see code

library(tidyverse)
library(limma)
library(QFeatures)
library(msqrob2)
library(plotly)
library(ggplot2)

2.2.2 Read data

Click to see background and code

  1. We use a peptides.txt file from MS-data quantified with maxquant that contains MS1 intensities summarized at the peptide level.
peptidesFile <- "https://raw.githubusercontent.com/statOmics/PDA22GTPB/data/quantification/fullCptacDatasSetNotForTutorial/peptides.txt"
  1. Maxquant stores the intensity data for the different samples in columnns that start with Intensity. We can retreive the column names with the intensity data with the code below:
ecols <- grep("Intensity\\.", names(read.delim(peptidesFile)))
  1. Read the data and store it in QFeatures object
pe <- readQFeatures(
  assayData = read.delim(peptidesFile),
  fnames = 1,
  quantCols = ecols,
  name = "peptideRaw")
## Checking arguments.
## Loading data as a 'SummarizedExperiment' object.
## Formatting sample annotations (colData).
## Formatting data as a 'QFeatures' object.

2.2.3 Explore object

Click to see background and code

  • The rowData contains information on the features (peptides) in the assay. E.g. Sequence, protein, …
rowData(pe[["peptideRaw"]])
## DataFrame with 11466 rows and 143 columns
##                          Sequence N.term.cleavage.window C.term.cleavage.window
##                       <character>            <character>            <character>
## AAAAGAGGAGDSGDAVTK  AAAAGAGGAG...          EHQHDEQKAA...          DSGDAVTKIG...
## AAAALAGGK               AAAALAGGK          QQLSKAAKAA...          AAALAGGKKS...
## AAAALAGGKK             AAAALAGGKK          QQLSKAAKAA...          AALAGGKKSK...
## AAADALSDLEIK        AAADALSDLE...          MPKETPSKAA...          ALSDLEIKDS...
## AAADALSDLEIKDSK     AAADALSDLE...          MPKETPSKAA...          DLEIKDSKSN...
## ...                           ...                    ...                    ...
## YYSIYDLGNNAVGLAK    YYSIYDLGNN...          VGDAFLRKYY...          NNAVGLAKAI...
## YYTFNGPNYNENETIR    YYTFNGPNYN...          FKDGSYPKYY...          YNENETIRHI...
## YYTITEVATR             YYTITEVATR          QEWDINERYY...          TITEVATRAK...
## YYTVFDRDNNR         YYTVFDRDNN...          LGDVFIGRYY...          VFDRDNNRVG...
## YYTVFDRDNNRVGFAEAAR YYTVFDRDNN...          LGDVFIGRYY...          VGFAEAARL_...
##                     Amino.acid.before First.amino.acid Second.amino.acid
##                           <character>      <character>       <character>
## AAAAGAGGAGDSGDAVTK                  K                A                 A
## AAAALAGGK                           K                A                 A
## AAAALAGGKK                          K                A                 A
## AAADALSDLEIK                        K                A                 A
## AAADALSDLEIKDSK                     K                A                 A
## ...                               ...              ...               ...
## YYSIYDLGNNAVGLAK                    K                Y                 Y
## YYTFNGPNYNENETIR                    K                Y                 Y
## YYTITEVATR                          R                Y                 Y
## YYTVFDRDNNR                         R                Y                 Y
## YYTVFDRDNNRVGFAEAAR                 R                Y                 Y
##                     Second.last.amino.acid Last.amino.acid Amino.acid.after
##                                <character>     <character>      <character>
## AAAAGAGGAGDSGDAVTK                       T               K                I
## AAAALAGGK                                G               K                K
## AAAALAGGKK                               K               K                S
## AAADALSDLEIK                             I               K                D
## AAADALSDLEIKDSK                          S               K                S
## ...                                    ...             ...              ...
## YYSIYDLGNNAVGLAK                         A               K                A
## YYTFNGPNYNENETIR                         I               R                H
## YYTITEVATR                               T               R                A
## YYTVFDRDNNR                              N               R                V
## YYTVFDRDNNRVGFAEAAR                      A               R                L
##                       A.Count   R.Count   N.Count   D.Count   C.Count   Q.Count
##                     <integer> <integer> <integer> <integer> <integer> <integer>
## AAAAGAGGAGDSGDAVTK          7         0         0         2         0         0
## AAAALAGGK                   5         0         0         0         0         0
## AAAALAGGKK                  5         0         0         0         0         0
## AAADALSDLEIK                4         0         0         2         0         0
## AAADALSDLEIKDSK             4         0         0         3         0         0
## ...                       ...       ...       ...       ...       ...       ...
## YYSIYDLGNNAVGLAK            2         0         2         1         0         0
## YYTFNGPNYNENETIR            0         1         4         0         0         0
## YYTITEVATR                  1         1         0         0         0         0
## YYTVFDRDNNR                 0         2         2         2         0         0
## YYTVFDRDNNRVGFAEAAR         3         3         2         2         0         0
##                       E.Count   G.Count   H.Count   I.Count   L.Count   K.Count
##                     <integer> <integer> <integer> <integer> <integer> <integer>
## AAAAGAGGAGDSGDAVTK          0         5         0         0         0         1
## AAAALAGGK                   0         2         0         0         1         1
## AAAALAGGKK                  0         2         0         0         1         2
## AAADALSDLEIK                1         0         0         1         2         1
## AAADALSDLEIKDSK             1         0         0         1         2         2
## ...                       ...       ...       ...       ...       ...       ...
## YYSIYDLGNNAVGLAK            0         2         0         1         2         1
## YYTFNGPNYNENETIR            2         1         0         1         0         0
## YYTITEVATR                  1         0         0         1         0         0
## YYTVFDRDNNR                 0         0         0         0         0         0
## YYTVFDRDNNRVGFAEAAR         1         1         0         0         0         0
##                       M.Count   F.Count   P.Count   S.Count   T.Count   W.Count
##                     <integer> <integer> <integer> <integer> <integer> <integer>
## AAAAGAGGAGDSGDAVTK          0         0         0         1         1         0
## AAAALAGGK                   0         0         0         0         0         0
## AAAALAGGKK                  0         0         0         0         0         0
## AAADALSDLEIK                0         0         0         1         0         0
## AAADALSDLEIKDSK             0         0         0         2         0         0
## ...                       ...       ...       ...       ...       ...       ...
## YYSIYDLGNNAVGLAK            0         0         0         1         0         0
## YYTFNGPNYNENETIR            0         1         1         0         2         0
## YYTITEVATR                  0         0         0         0         3         0
## YYTVFDRDNNR                 0         1         0         0         1         0
## YYTVFDRDNNRVGFAEAAR         0         2         0         0         1         0
##                       Y.Count   V.Count   U.Count    Length Missed.cleavages
##                     <integer> <integer> <integer> <integer>        <integer>
## AAAAGAGGAGDSGDAVTK          0         1         0        18                0
## AAAALAGGK                   0         0         0         9                0
## AAAALAGGKK                  0         0         0        10                1
## AAADALSDLEIK                0         0         0        12                0
## AAADALSDLEIKDSK             0         0         0        15                1
## ...                       ...       ...       ...       ...              ...
## YYSIYDLGNNAVGLAK            3         1         0        16                0
## YYTFNGPNYNENETIR            3         0         0        16                0
## YYTITEVATR                  2         1         0        10                0
## YYTVFDRDNNR                 2         1         0        11                1
## YYTVFDRDNNRVGFAEAAR         2         2         0        19                2
##                          Mass      Proteins Leading.razor.protein
##                     <numeric>   <character>           <character>
## AAAAGAGGAGDSGDAVTK   1445.675 sp|P38915|...         sp|P38915|...
## AAAALAGGK             728.418 sp|Q3E792|...         sp|Q3E792|...
## AAAALAGGKK            856.513 sp|Q3E792|...         sp|Q3E792|...
## AAADALSDLEIK         1215.635 sp|P09938|...         sp|P09938|...
## AAADALSDLEIKDSK      1545.789 sp|P09938|...         sp|P09938|...
## ...                       ...           ...                   ...
## YYSIYDLGNNAVGLAK      1759.88 sp|P07267|...         sp|P07267|...
## YYTFNGPNYNENETIR      1993.88 sp|Q00955|...         sp|Q00955|...
## YYTITEVATR            1215.61 sp|P38891|...         sp|P38891|...
## YYTVFDRDNNR           1461.66 P07339ups|...         P07339ups|...
## YYTVFDRDNNRVGFAEAAR   2263.08 P07339ups|...         P07339ups|...
##                     Start.position End.position Unique..Groups.
##                          <integer>    <integer>     <character>
## AAAAGAGGAGDSGDAVTK              97          114             yes
## AAAALAGGK                       13           21             yes
## AAAALAGGKK                      13           22             yes
## AAADALSDLEIK                     9           20             yes
## AAADALSDLEIKDSK                  9           23             yes
## ...                            ...          ...             ...
## YYSIYDLGNNAVGLAK               388          403             yes
## YYTFNGPNYNENETIR              1275         1290             yes
## YYTITEVATR                     311          320             yes
## YYTVFDRDNNR                    225          235             yes
## YYTVFDRDNNRVGFAEAAR            225          243             yes
##                     Unique..Proteins.     Charges        PEP     Score
##                           <character> <character>  <numeric> <numeric>
## AAAAGAGGAGDSGDAVTK                yes           2 1.1843e-05    82.942
## AAAALAGGK                          no           2 7.4562e-06   134.810
## AAAALAGGKK                         no           2 3.3094e-09   143.730
## AAADALSDLEIK                      yes           2 9.1593e-23   182.230
## AAADALSDLEIKDSK                   yes           3 1.5319e-04    73.927
## ...                               ...         ...        ...       ...
## YYSIYDLGNNAVGLAK                  yes           2 7.7415e-37   174.240
## YYTFNGPNYNENETIR                  yes           2 4.2208e-21   147.750
## YYTITEVATR                        yes           2 1.3566e-04   109.160
## YYTVFDRDNNR                       yes           2 6.1425e-04   110.930
## YYTVFDRDNNRVGFAEAAR               yes           3 8.9859e-04    59.728
##                     Identification.type.6A_1 Identification.type.6A_2
##                                  <character>              <character>
## AAAAGAGGAGDSGDAVTK             By matchin...                 By MS/MS
## AAAALAGGK                      By matchin...            By matchin...
## AAAALAGGKK                     By matchin...            By matchin...
## AAADALSDLEIK                        By MS/MS                 By MS/MS
## AAADALSDLEIKDSK                By matchin...            By matchin...
## ...                                      ...                      ...
## YYSIYDLGNNAVGLAK               By matchin...            By matchin...
## YYTFNGPNYNENETIR               By matchin...            By matchin...
## YYTITEVATR                          By MS/MS            By matchin...
## YYTVFDRDNNR                    By matchin...            By matchin...
## YYTVFDRDNNRVGFAEAAR            By matchin...            By matchin...
##                     Identification.type.6A_3 Identification.type.6A_4
##                                  <character>              <character>
## AAAAGAGGAGDSGDAVTK             By matchin...                 By MS/MS
## AAAALAGGK                      By matchin...                 By MS/MS
## AAAALAGGKK                     By matchin...                 By MS/MS
## AAADALSDLEIK                   By matchin...                 By MS/MS
## AAADALSDLEIKDSK                By matchin...                 By MS/MS
## ...                                      ...                      ...
## YYSIYDLGNNAVGLAK               By matchin...                 By MS/MS
## YYTFNGPNYNENETIR               By matchin...                 By MS/MS
## YYTITEVATR                     By matchin...            By matchin...
## YYTVFDRDNNR                    By matchin...            By matchin...
## YYTVFDRDNNRVGFAEAAR            By matchin...            By matchin...
##                     Identification.type.6A_5 Identification.type.6A_6
##                                  <character>              <character>
## AAAAGAGGAGDSGDAVTK             By matchin...            By matchin...
## AAAALAGGK                      By matchin...            By matchin...
## AAAALAGGKK                     By matchin...            By matchin...
## AAADALSDLEIK                        By MS/MS                 By MS/MS
## AAADALSDLEIKDSK                     By MS/MS                 By MS/MS
## ...                                      ...                      ...
## YYSIYDLGNNAVGLAK                    By MS/MS                 By MS/MS
## YYTFNGPNYNENETIR                    By MS/MS                 By MS/MS
## YYTITEVATR                     By matchin...            By matchin...
## YYTVFDRDNNR                    By matchin...            By matchin...
## YYTVFDRDNNRVGFAEAAR            By matchin...            By matchin...
##                     Identification.type.6A_7 Identification.type.6A_8
##                                  <character>              <character>
## AAAAGAGGAGDSGDAVTK                  By MS/MS                 By MS/MS
## AAAALAGGK                           By MS/MS                 By MS/MS
## AAAALAGGKK                          By MS/MS                 By MS/MS
## AAADALSDLEIK                        By MS/MS            By matchin...
## AAADALSDLEIKDSK                     By MS/MS                 By MS/MS
## ...                                      ...                      ...
## YYSIYDLGNNAVGLAK               By matchin...            By matchin...
## YYTFNGPNYNENETIR               By matchin...            By matchin...
## YYTITEVATR                          By MS/MS            By matchin...
## YYTVFDRDNNR                    By matchin...            By matchin...
## YYTVFDRDNNRVGFAEAAR            By matchin...            By matchin...
##                     Identification.type.6A_9 Identification.type.6B_1
##                                  <character>              <character>
## AAAAGAGGAGDSGDAVTK                  By MS/MS            By matchin...
## AAAALAGGK                           By MS/MS                 By MS/MS
## AAAALAGGKK                          By MS/MS            By matchin...
## AAADALSDLEIK                        By MS/MS                 By MS/MS
## AAADALSDLEIKDSK                     By MS/MS            By matchin...
## ...                                      ...                      ...
## YYSIYDLGNNAVGLAK               By matchin...            By matchin...
## YYTFNGPNYNENETIR               By matchin...            By matchin...
## YYTITEVATR                     By matchin...                 By MS/MS
## YYTVFDRDNNR                    By matchin...            By matchin...
## YYTVFDRDNNRVGFAEAAR            By matchin...            By matchin...
##                     Identification.type.6B_2 Identification.type.6B_3
##                                  <character>              <character>
## AAAAGAGGAGDSGDAVTK             By matchin...            By matchin...
## AAAALAGGK                      By matchin...            By matchin...
## AAAALAGGKK                          By MS/MS                 By MS/MS
## AAADALSDLEIK                        By MS/MS            By matchin...
## AAADALSDLEIKDSK                By matchin...            By matchin...
## ...                                      ...                      ...
## YYSIYDLGNNAVGLAK               By matchin...            By matchin...
## YYTFNGPNYNENETIR               By matchin...            By matchin...
## YYTITEVATR                     By matchin...            By matchin...
## YYTVFDRDNNR                    By matchin...            By matchin...
## YYTVFDRDNNRVGFAEAAR            By matchin...            By matchin...
##                     Identification.type.6B_4 Identification.type.6B_5
##                                  <character>              <character>
## AAAAGAGGAGDSGDAVTK             By matchin...            By matchin...
## AAAALAGGK                      By matchin...            By matchin...
## AAAALAGGKK                     By matchin...            By matchin...
## AAADALSDLEIK                        By MS/MS                 By MS/MS
## AAADALSDLEIKDSK                     By MS/MS                 By MS/MS
## ...                                      ...                      ...
## YYSIYDLGNNAVGLAK                    By MS/MS            By matchin...
## YYTFNGPNYNENETIR                    By MS/MS                 By MS/MS
## YYTITEVATR                          By MS/MS                 By MS/MS
## YYTVFDRDNNR                    By matchin...            By matchin...
## YYTVFDRDNNRVGFAEAAR            By matchin...            By matchin...
##                     Identification.type.6B_6 Identification.type.6B_7
##                                  <character>              <character>
## AAAAGAGGAGDSGDAVTK             By matchin...            By matchin...
## AAAALAGGK                      By matchin...                 By MS/MS
## AAAALAGGKK                     By matchin...                 By MS/MS
## AAADALSDLEIK                        By MS/MS                 By MS/MS
## AAADALSDLEIKDSK                     By MS/MS                 By MS/MS
## ...                                      ...                      ...
## YYSIYDLGNNAVGLAK               By matchin...            By matchin...
## YYTFNGPNYNENETIR                    By MS/MS            By matchin...
## YYTITEVATR                     By matchin...            By matchin...
## YYTVFDRDNNR                    By matchin...            By matchin...
## YYTVFDRDNNRVGFAEAAR            By matchin...            By matchin...
##                     Identification.type.6B_8 Identification.type.6B_9
##                                  <character>              <character>
## AAAAGAGGAGDSGDAVTK                  By MS/MS                 By MS/MS
## AAAALAGGK                           By MS/MS                 By MS/MS
## AAAALAGGKK                          By MS/MS                 By MS/MS
## AAADALSDLEIK                   By matchin...            By matchin...
## AAADALSDLEIKDSK                     By MS/MS                 By MS/MS
## ...                                      ...                      ...
## YYSIYDLGNNAVGLAK               By matchin...            By matchin...
## YYTFNGPNYNENETIR               By matchin...            By matchin...
## YYTITEVATR                          By MS/MS            By matchin...
## YYTVFDRDNNR                    By matchin...            By matchin...
## YYTVFDRDNNRVGFAEAAR            By matchin...            By matchin...
##                     Identification.type.6C_1 Identification.type.6C_2
##                                  <character>              <character>
## AAAAGAGGAGDSGDAVTK             By matchin...            By matchin...
## AAAALAGGK                      By matchin...                 By MS/MS
## AAAALAGGKK                     By matchin...                 By MS/MS
## AAADALSDLEIK                        By MS/MS            By matchin...
## AAADALSDLEIKDSK                By matchin...            By matchin...
## ...                                      ...                      ...
## YYSIYDLGNNAVGLAK               By matchin...            By matchin...
## YYTFNGPNYNENETIR               By matchin...            By matchin...
## YYTITEVATR                     By matchin...            By matchin...
## YYTVFDRDNNR                    By matchin...            By matchin...
## YYTVFDRDNNRVGFAEAAR            By matchin...            By matchin...
##                     Identification.type.6C_3 Identification.type.6C_4
##                                  <character>              <character>
## AAAAGAGGAGDSGDAVTK             By matchin...            By matchin...
## AAAALAGGK                      By matchin...                 By MS/MS
## AAAALAGGKK                     By matchin...                 By MS/MS
## AAADALSDLEIK                        By MS/MS                 By MS/MS
## AAADALSDLEIKDSK                By matchin...                 By MS/MS
## ...                                      ...                      ...
## YYSIYDLGNNAVGLAK               By matchin...                 By MS/MS
## YYTFNGPNYNENETIR               By matchin...                 By MS/MS
## YYTITEVATR                          By MS/MS            By matchin...
## YYTVFDRDNNR                    By matchin...            By matchin...
## YYTVFDRDNNRVGFAEAAR            By matchin...            By matchin...
##                     Identification.type.6C_5 Identification.type.6C_6
##                                  <character>              <character>
## AAAAGAGGAGDSGDAVTK                  By MS/MS            By matchin...
## AAAALAGGK                      By matchin...            By matchin...
## AAAALAGGKK                     By matchin...            By matchin...
## AAADALSDLEIK                        By MS/MS                 By MS/MS
## AAADALSDLEIKDSK                     By MS/MS                 By MS/MS
## ...                                      ...                      ...
## YYSIYDLGNNAVGLAK                    By MS/MS                 By MS/MS
## YYTFNGPNYNENETIR               By matchin...            By matchin...
## YYTITEVATR                     By matchin...            By matchin...
## YYTVFDRDNNR                    By matchin...            By matchin...
## YYTVFDRDNNRVGFAEAAR            By matchin...            By matchin...
##                     Identification.type.6C_7 Identification.type.6C_8
##                                  <character>              <character>
## AAAAGAGGAGDSGDAVTK                  By MS/MS            By matchin...
## AAAALAGGK                           By MS/MS                 By MS/MS
## AAAALAGGKK                          By MS/MS                 By MS/MS
## AAADALSDLEIK                   By matchin...                 By MS/MS
## AAADALSDLEIKDSK                     By MS/MS                 By MS/MS
## ...                                      ...                      ...
## YYSIYDLGNNAVGLAK               By matchin...            By matchin...
## YYTFNGPNYNENETIR               By matchin...            By matchin...
## YYTITEVATR                     By matchin...                 By MS/MS
## YYTVFDRDNNR                    By matchin...            By matchin...
## YYTVFDRDNNRVGFAEAAR            By matchin...            By matchin...
##                     Identification.type.6C_9 Identification.type.6D_1
##                                  <character>              <character>
## AAAAGAGGAGDSGDAVTK             By matchin...            By matchin...
## AAAALAGGK                           By MS/MS            By matchin...
## AAAALAGGKK                          By MS/MS            By matchin...
## AAADALSDLEIK                        By MS/MS                 By MS/MS
## AAADALSDLEIKDSK                     By MS/MS                 By MS/MS
## ...                                      ...                      ...
## YYSIYDLGNNAVGLAK               By matchin...            By matchin...
## YYTFNGPNYNENETIR               By matchin...            By matchin...
## YYTITEVATR                          By MS/MS            By matchin...
## YYTVFDRDNNR                    By matchin...            By matchin...
## YYTVFDRDNNRVGFAEAAR            By matchin...            By matchin...
##                     Identification.type.6D_2 Identification.type.6D_3
##                                  <character>              <character>
## AAAAGAGGAGDSGDAVTK             By matchin...            By matchin...
## AAAALAGGK                      By matchin...            By matchin...
## AAAALAGGKK                     By matchin...            By matchin...
## AAADALSDLEIK                   By matchin...            By matchin...
## AAADALSDLEIKDSK                     By MS/MS            By matchin...
## ...                                      ...                      ...
## YYSIYDLGNNAVGLAK               By matchin...            By matchin...
## YYTFNGPNYNENETIR               By matchin...            By matchin...
## YYTITEVATR                          By MS/MS                 By MS/MS
## YYTVFDRDNNR                    By matchin...            By matchin...
## YYTVFDRDNNRVGFAEAAR            By matchin...            By matchin...
##                     Identification.type.6D_4 Identification.type.6D_5
##                                  <character>              <character>
## AAAAGAGGAGDSGDAVTK             By matchin...            By matchin...
## AAAALAGGK                      By matchin...            By matchin...
## AAAALAGGKK                          By MS/MS            By matchin...
## AAADALSDLEIK                        By MS/MS                 By MS/MS
## AAADALSDLEIKDSK                     By MS/MS                 By MS/MS
## ...                                      ...                      ...
## YYSIYDLGNNAVGLAK                    By MS/MS                 By MS/MS
## YYTFNGPNYNENETIR                    By MS/MS                 By MS/MS
## YYTITEVATR                     By matchin...            By matchin...
## YYTVFDRDNNR                    By matchin...            By matchin...
## YYTVFDRDNNRVGFAEAAR            By matchin...            By matchin...
##                     Identification.type.6D_6 Identification.type.6D_7
##                                  <character>              <character>
## AAAAGAGGAGDSGDAVTK                  By MS/MS            By matchin...
## AAAALAGGK                      By matchin...                 By MS/MS
## AAAALAGGKK                     By matchin...                 By MS/MS
## AAADALSDLEIK                        By MS/MS            By matchin...
## AAADALSDLEIKDSK                By matchin...                 By MS/MS
## ...                                      ...                      ...
## YYSIYDLGNNAVGLAK                    By MS/MS            By matchin...
## YYTFNGPNYNENETIR                    By MS/MS            By matchin...
## YYTITEVATR                     By matchin...            By matchin...
## YYTVFDRDNNR                    By matchin...                 By MS/MS
## YYTVFDRDNNRVGFAEAAR            By matchin...            By matchin...
##                     Identification.type.6D_8 Identification.type.6D_9
##                                  <character>              <character>
## AAAAGAGGAGDSGDAVTK             By matchin...            By matchin...
## AAAALAGGK                           By MS/MS                 By MS/MS
## AAAALAGGKK                          By MS/MS                 By MS/MS
## AAADALSDLEIK                        By MS/MS                 By MS/MS
## AAADALSDLEIKDSK                     By MS/MS                 By MS/MS
## ...                                      ...                      ...
## YYSIYDLGNNAVGLAK               By matchin...            By matchin...
## YYTFNGPNYNENETIR               By matchin...            By matchin...
## YYTITEVATR                          By MS/MS            By matchin...
## YYTVFDRDNNR                         By MS/MS            By matchin...
## YYTVFDRDNNRVGFAEAAR            By matchin...            By matchin...
##                     Identification.type.6E_1 Identification.type.6E_2
##                                  <character>              <character>
## AAAAGAGGAGDSGDAVTK             By matchin...            By matchin...
## AAAALAGGK                      By matchin...            By matchin...
## AAAALAGGKK                     By matchin...            By matchin...
## AAADALSDLEIK                        By MS/MS                 By MS/MS
## AAADALSDLEIKDSK                     By MS/MS                 By MS/MS
## ...                                      ...                      ...
## YYSIYDLGNNAVGLAK               By matchin...            By matchin...
## YYTFNGPNYNENETIR               By matchin...            By matchin...
## YYTITEVATR                     By matchin...            By matchin...
## YYTVFDRDNNR                    By matchin...            By matchin...
## YYTVFDRDNNRVGFAEAAR            By matchin...            By matchin...
##                     Identification.type.6E_3 Identification.type.6E_4
##                                  <character>              <character>
## AAAAGAGGAGDSGDAVTK             By matchin...            By matchin...
## AAAALAGGK                      By matchin...                 By MS/MS
## AAAALAGGKK                     By matchin...            By matchin...
## AAADALSDLEIK                   By matchin...                 By MS/MS
## AAADALSDLEIKDSK                     By MS/MS            By matchin...
## ...                                      ...                      ...
## YYSIYDLGNNAVGLAK               By matchin...                 By MS/MS
## YYTFNGPNYNENETIR               By matchin...                 By MS/MS
## YYTITEVATR                     By matchin...            By matchin...
## YYTVFDRDNNR                    By matchin...                 By MS/MS
## YYTVFDRDNNRVGFAEAAR            By matchin...            By matchin...
##                     Identification.type.6E_5 Identification.type.6E_6
##                                  <character>              <character>
## AAAAGAGGAGDSGDAVTK             By matchin...            By matchin...
## AAAALAGGK                      By matchin...            By matchin...
## AAAALAGGKK                     By matchin...            By matchin...
## AAADALSDLEIK                        By MS/MS            By matchin...
## AAADALSDLEIKDSK                     By MS/MS                 By MS/MS
## ...                                      ...                      ...
## YYSIYDLGNNAVGLAK                    By MS/MS                 By MS/MS
## YYTFNGPNYNENETIR                    By MS/MS                 By MS/MS
## YYTITEVATR                     By matchin...            By matchin...
## YYTVFDRDNNR                         By MS/MS            By matchin...
## YYTVFDRDNNRVGFAEAAR            By matchin...                 By MS/MS
##                     Identification.type.6E_7 Identification.type.6E_8
##                                  <character>              <character>
## AAAAGAGGAGDSGDAVTK             By matchin...            By matchin...
## AAAALAGGK                           By MS/MS                 By MS/MS
## AAAALAGGKK                          By MS/MS                 By MS/MS
## AAADALSDLEIK                        By MS/MS                 By MS/MS
## AAADALSDLEIKDSK                By matchin...                 By MS/MS
## ...                                      ...                      ...
## YYSIYDLGNNAVGLAK               By matchin...            By matchin...
## YYTFNGPNYNENETIR               By matchin...            By matchin...
## YYTITEVATR                     By matchin...            By matchin...
## YYTVFDRDNNR                         By MS/MS                 By MS/MS
## YYTVFDRDNNRVGFAEAAR            By matchin...            By matchin...
##                     Identification.type.6E_9 Experiment.6A_1 Experiment.6A_2
##                                  <character>       <integer>       <integer>
## AAAAGAGGAGDSGDAVTK             By matchin...              NA               1
## AAAALAGGK                           By MS/MS              NA               1
## AAAALAGGKK                          By MS/MS              NA               1
## AAADALSDLEIK                        By MS/MS               1               1
## AAADALSDLEIKDSK                     By MS/MS               1               1
## ...                                      ...             ...             ...
## YYSIYDLGNNAVGLAK               By matchin...              NA              NA
## YYTFNGPNYNENETIR                    By MS/MS              NA              NA
## YYTITEVATR                     By matchin...               1              NA
## YYTVFDRDNNR                         By MS/MS              NA              NA
## YYTVFDRDNNRVGFAEAAR            By matchin...              NA              NA
##                     Experiment.6A_3 Experiment.6A_4 Experiment.6A_5
##                           <integer>       <integer>       <integer>
## AAAAGAGGAGDSGDAVTK               NA               1               1
## AAAALAGGK                         2               1               1
## AAAALAGGKK                       NA               1              NA
## AAADALSDLEIK                      1               1               1
## AAADALSDLEIKDSK                  NA               1               1
## ...                             ...             ...             ...
## YYSIYDLGNNAVGLAK                 NA               1               1
## YYTFNGPNYNENETIR                 NA               1               1
## YYTITEVATR                        1              NA              NA
## YYTVFDRDNNR                      NA              NA              NA
## YYTVFDRDNNRVGFAEAAR              NA              NA              NA
##                     Experiment.6A_6 Experiment.6A_7 Experiment.6A_8
##                           <integer>       <integer>       <integer>
## AAAAGAGGAGDSGDAVTK                1               1               1
## AAAALAGGK                         1               2               1
## AAAALAGGKK                        1               1               1
## AAADALSDLEIK                      1               1               1
## AAADALSDLEIKDSK                   1               1               1
## ...                             ...             ...             ...
## YYSIYDLGNNAVGLAK                  1              NA              NA
## YYTFNGPNYNENETIR                  1               1              NA
## YYTITEVATR                        1               1              NA
## YYTVFDRDNNR                      NA              NA              NA
## YYTVFDRDNNRVGFAEAAR              NA              NA              NA
##                     Experiment.6A_9 Experiment.6B_1 Experiment.6B_2
##                           <integer>       <integer>       <integer>
## AAAAGAGGAGDSGDAVTK                1              NA              NA
## AAAALAGGK                         1               1               1
## AAAALAGGKK                        1              NA               1
## AAADALSDLEIK                      1               1               1
## AAADALSDLEIKDSK                   1              NA               1
## ...                             ...             ...             ...
## YYSIYDLGNNAVGLAK                 NA              NA              NA
## YYTFNGPNYNENETIR                  1              NA              NA
## YYTITEVATR                       NA               1               1
## YYTVFDRDNNR                      NA              NA              NA
## YYTVFDRDNNRVGFAEAAR              NA              NA              NA
##                     Experiment.6B_3 Experiment.6B_4 Experiment.6B_5
##                           <integer>       <integer>       <integer>
## AAAAGAGGAGDSGDAVTK               NA              NA               1
## AAAALAGGK                         1               2               1
## AAAALAGGKK                        1               1              NA
## AAADALSDLEIK                      1               1               1
## AAADALSDLEIKDSK                  NA               1               1
## ...                             ...             ...             ...
## YYSIYDLGNNAVGLAK                 NA               1               1
## YYTFNGPNYNENETIR                 NA               1               1
## YYTITEVATR                        1               1               1
## YYTVFDRDNNR                      NA              NA              NA
## YYTVFDRDNNRVGFAEAAR              NA              NA              NA
##                     Experiment.6B_6 Experiment.6B_7 Experiment.6B_8
##                           <integer>       <integer>       <integer>
## AAAAGAGGAGDSGDAVTK                1              NA               1
## AAAALAGGK                        NA               2               1
## AAAALAGGKK                       NA               1               1
## AAADALSDLEIK                      1               1               1
## AAADALSDLEIKDSK                   1               1               1
## ...                             ...             ...             ...
## YYSIYDLGNNAVGLAK                  1              NA              NA
## YYTFNGPNYNENETIR                  1               1              NA
## YYTITEVATR                        1              NA               1
## YYTVFDRDNNR                      NA              NA              NA
## YYTVFDRDNNRVGFAEAAR              NA              NA              NA
##                     Experiment.6B_9 Experiment.6C_1 Experiment.6C_2
##                           <integer>       <integer>       <integer>
## AAAAGAGGAGDSGDAVTK                1              NA              NA
## AAAALAGGK                         2              NA               1
## AAAALAGGKK                        1              NA               1
## AAADALSDLEIK                      1               1               1
## AAADALSDLEIKDSK                   1               1               1
## ...                             ...             ...             ...
## YYSIYDLGNNAVGLAK                 NA              NA              NA
## YYTFNGPNYNENETIR                 NA              NA              NA
## YYTITEVATR                       NA               1               1
## YYTVFDRDNNR                      NA              NA              NA
## YYTVFDRDNNRVGFAEAAR              NA              NA              NA
##                     Experiment.6C_3 Experiment.6C_4 Experiment.6C_5
##                           <integer>       <integer>       <integer>
## AAAAGAGGAGDSGDAVTK               NA               1               1
## AAAALAGGK                         2               2              NA
## AAAALAGGKK                       NA               1              NA
## AAADALSDLEIK                      1               1               1
## AAADALSDLEIKDSK                   1               1               1
## ...                             ...             ...             ...
## YYSIYDLGNNAVGLAK                 NA               1               1
## YYTFNGPNYNENETIR                 NA               1               1
## YYTITEVATR                        1               1              NA
## YYTVFDRDNNR                      NA              NA              NA
## YYTVFDRDNNRVGFAEAAR              NA              NA              NA
##                     Experiment.6C_6 Experiment.6C_7 Experiment.6C_8
##                           <integer>       <integer>       <integer>
## AAAAGAGGAGDSGDAVTK                1               1               1
## AAAALAGGK                        NA               2               1
## AAAALAGGKK                       NA               1               1
## AAADALSDLEIK                      1               1               1
## AAADALSDLEIKDSK                   1               1               1
## ...                             ...             ...             ...
## YYSIYDLGNNAVGLAK                  1              NA              NA
## YYTFNGPNYNENETIR                  1               1               1
## YYTITEVATR                        1              NA               1
## YYTVFDRDNNR                       1              NA               1
## YYTVFDRDNNRVGFAEAAR              NA              NA              NA
##                     Experiment.6C_9 Experiment.6D_1 Experiment.6D_2
##                           <integer>       <integer>       <integer>
## AAAAGAGGAGDSGDAVTK                1              NA              NA
## AAAALAGGK                         1              NA               1
## AAAALAGGKK                        1              NA              NA
## AAADALSDLEIK                      1               1               1
## AAADALSDLEIKDSK                   1               1               1
## ...                             ...             ...             ...
## YYSIYDLGNNAVGLAK                 NA              NA              NA
## YYTFNGPNYNENETIR                  1              NA              NA
## YYTITEVATR                        1              NA               1
## YYTVFDRDNNR                      NA              NA              NA
## YYTVFDRDNNRVGFAEAAR              NA              NA              NA
##                     Experiment.6D_3 Experiment.6D_4 Experiment.6D_5
##                           <integer>       <integer>       <integer>
## AAAAGAGGAGDSGDAVTK               NA               1               1
## AAAALAGGK                         1               1               1
## AAAALAGGKK                       NA               1              NA
## AAADALSDLEIK                      1               1               1
## AAADALSDLEIKDSK                   1               1               1
## ...                             ...             ...             ...
## YYSIYDLGNNAVGLAK                 NA               1               1
## YYTFNGPNYNENETIR                 NA               1               1
## YYTITEVATR                        1               1               1
## YYTVFDRDNNR                      NA               1               1
## YYTVFDRDNNRVGFAEAAR              NA               1              NA
##                     Experiment.6D_6 Experiment.6D_7 Experiment.6D_8
##                           <integer>       <integer>       <integer>
## AAAAGAGGAGDSGDAVTK                1               1              NA
## AAAALAGGK                        NA               2               1
## AAAALAGGKK                       NA               1               1
## AAADALSDLEIK                      1               1               1
## AAADALSDLEIKDSK                   1               1               1
## ...                             ...             ...             ...
## YYSIYDLGNNAVGLAK                  1               1              NA
## YYTFNGPNYNENETIR                  1               1               1
## YYTITEVATR                        1              NA               1
## YYTVFDRDNNR                       1               1               1
## YYTVFDRDNNRVGFAEAAR              NA              NA              NA
##                     Experiment.6D_9 Experiment.6E_1 Experiment.6E_2
##                           <integer>       <integer>       <integer>
## AAAAGAGGAGDSGDAVTK               NA              NA               1
## AAAALAGGK                         2              NA               1
## AAAALAGGKK                        1              NA              NA
## AAADALSDLEIK                      1               1               1
## AAADALSDLEIKDSK                   1               1               1
## ...                             ...             ...             ...
## YYSIYDLGNNAVGLAK                 NA              NA              NA
## YYTFNGPNYNENETIR                  1              NA              NA
## YYTITEVATR                       NA              NA               1
## YYTVFDRDNNR                       1               1              NA
## YYTVFDRDNNRVGFAEAAR              NA              NA              NA
##                     Experiment.6E_3 Experiment.6E_4 Experiment.6E_5
##                           <integer>       <integer>       <integer>
## AAAAGAGGAGDSGDAVTK               NA              NA               1
## AAAALAGGK                         2               2               1
## AAAALAGGKK                       NA               1              NA
## AAADALSDLEIK                      1               1               1
## AAADALSDLEIKDSK                   1               1               1
## ...                             ...             ...             ...
## YYSIYDLGNNAVGLAK                  1               1               1
## YYTFNGPNYNENETIR                 NA               1               1
## YYTITEVATR                        1               1               1
## YYTVFDRDNNR                       1               1               1
## YYTVFDRDNNRVGFAEAAR              NA               1               1
##                     Experiment.6E_6 Experiment.6E_7 Experiment.6E_8
##                           <integer>       <integer>       <integer>
## AAAAGAGGAGDSGDAVTK                1              NA              NA
## AAAALAGGK                        NA               2               2
## AAAALAGGKK                       NA               1               1
## AAADALSDLEIK                      1               1               1
## AAADALSDLEIKDSK                   1              NA               1
## ...                             ...             ...             ...
## YYSIYDLGNNAVGLAK                  1              NA              NA
## YYTFNGPNYNENETIR                  1               1               1
## YYTITEVATR                       NA              NA              NA
## YYTVFDRDNNR                       1               1               1
## YYTVFDRDNNRVGFAEAAR               1               1               1
##                     Experiment.6E_9 Intensity     Reverse Potential.contaminant
##                           <integer> <numeric> <character>           <character>
## AAAAGAGGAGDSGDAVTK               NA   1190800                                  
## AAAALAGGK                         1 280990000                                  
## AAAALAGGKK                        1  33360000                                  
## AAADALSDLEIK                      1  54622000                                  
## AAADALSDLEIKDSK                   1  18910000                                  
## ...                             ...       ...         ...                   ...
## YYSIYDLGNNAVGLAK                 NA   2145900                                  
## YYTFNGPNYNENETIR                  1   5608800                                  
## YYTITEVATR                       NA  13034000                                  
## YYTVFDRDNNR                       1   8702500                                  
## YYTVFDRDNNRVGFAEAAR               1   2391100                                  
##                            id Protein.group.IDs Mod..peptide.IDs  Evidence.IDs
##                     <integer>       <character>      <character>   <character>
## AAAAGAGGAGDSGDAVTK          0               859                0 0;1;2;3;4;...
## AAAALAGGK                   1               230                1 24;25;26;2...
## AAAALAGGKK                  2               230                2 74;75;76;7...
## AAADALSDLEIK                3               229                3 99;100;101...
## AAADALSDLEIKDSK             4               229                4 144;145;14...
## ...                       ...               ...              ...           ...
## YYSIYDLGNNAVGLAK        11461               196            12240 331367;331...
## YYTFNGPNYNENETIR        11462              1254            12241 331384;331...
## YYTITEVATR              11463               854            12242 331411;331...
## YYTVFDRDNNR             11464                34            12243 331439;331...
## YYTVFDRDNNRVGFAEAAR     11465                34            12244 331455;331...
##                         MS.MS.IDs Best.MS.MS Oxidation..M..site.IDs MS.MS.Count
##                       <character>  <integer>            <character>   <integer>
## AAAAGAGGAGDSGDAVTK  0;1;2;3;4;...          0                                 10
## AAAALAGGK           10;11;12;1...         21                                 18
## AAAALAGGKK          30;31;32;3...         31                                 21
## AAADALSDLEIK        51;52;53;5...         72                                 29
## AAADALSDLEIKDSK     85;86;87;8...         94                                 32
## ...                           ...        ...                    ...         ...
## YYSIYDLGNNAVGLAK    169138;169...     169147                                 13
## YYTFNGPNYNENETIR    169151;169...     169159                                 14
## YYTITEVATR          169165;169...     169173                                 12
## YYTVFDRDNNR         169177;169...     169180                                  7
## YYTVFDRDNNRVGFAEAAR        169184     169184                                  1
  • The colData contains information on the samples
colData(pe)
## DataFrame with 45 rows and 0 columns
  • No information is stored yet on the design.
pe %>% colnames
## CharacterList of length 1
## [["peptideRaw"]] Intensity.6A_1 Intensity.6A_2 ... Intensity.6E_9
  • Note, that the sample names include the spike-in condition.

  • They also end on a number.

    • 1-3 is from lab 1,
    • 4-6 from lab 2 and
    • 7-9 from lab 3.
  • We update the colData with information on the design

colData(pe)$lab <- rep(rep(paste0("lab",1:3),each=3),5) %>% as.factor
colData(pe)$condition <- pe[["peptideRaw"]] %>% colnames %>% substr(12,12) %>% as.factor
colData(pe)$spikeConcentration <- rep(c(A = 0.25, B = 0.74, C = 2.22, D = 6.67, E = 20),each = 9)
  • We explore the colData again
colData(pe)
## DataFrame with 45 rows and 3 columns
##                     lab condition spikeConcentration
##                <factor>  <factor>          <numeric>
## Intensity.6A_1     lab1         A               0.25
## Intensity.6A_2     lab1         A               0.25
## Intensity.6A_3     lab1         A               0.25
## Intensity.6A_4     lab2         A               0.25
## Intensity.6A_5     lab2         A               0.25
## ...                 ...       ...                ...
## Intensity.6E_5     lab2         E                 20
## Intensity.6E_6     lab2         E                 20
## Intensity.6E_7     lab3         E                 20
## Intensity.6E_8     lab3         E                 20
## Intensity.6E_9     lab3         E                 20


3 Preprocessing

3.1 Log-transformation

3.1.1 Explore the data with plots

Peptide AALEELVK from spiked-in UPS protein P12081. We only show data from lab1.

Click to see code to make plot

subset <- pe["AALEELVK",colData(pe)$lab=="lab1"]
plotWhyLog <- data.frame(concentration = colData(subset)$spikeConcentration,
           y = assay(subset[["peptideRaw"]]) %>% c
           ) %>% 
  ggplot(aes(concentration, y)) +
  geom_point() +
  xlab("concentration (fmol/l)") +
  ggtitle("peptide AALEELVK in lab1")

plotWhyLog

  • Variance increases with the mean \(\rightarrow\) Multiplicative error structure
Click to see code to make plot

plotLog <- data.frame(concentration = colData(subset)$spikeConcentration,
           y = assay(subset[["peptideRaw"]]) %>% c
           ) %>% 
  ggplot(aes(concentration, y)) +
  geom_point() + 
  scale_x_continuous(trans='log2') + 
  scale_y_continuous(trans='log2') +
  xlab("concentration (fmol/l)") +
  ggtitle("peptide AALEELVK in lab1 with axes on log scale")

plotLog

  • Data seems to be homoscedastic on log-scale \(\rightarrow\) log transformation of the intensity data
  • In quantitative proteomics analysis on \(\log_2\)

\(\rightarrow\) Differences on a \(\log_2\) scale: \(\log_2\) fold changes

\[ \log_2 B - \log_2 A = \log_2 \frac{B}{A} = \log FC_\text{B - A} \] \[ \begin{array} {l} log_2 FC = 1 \rightarrow FC = 2^1 =2\\ log_2 FC = 2 \rightarrow FC = 2^2 = 4\\ \end{array} \]

3.1.2 log-transformation of the data

Click to see code to log-transfrom the data

  • We calculate how many non zero intensities we have for each peptide and this can be useful for filtering.
rowData(pe[["peptideRaw"]])$nNonZero <- rowSums(assay(pe[["peptideRaw"]]) > 0)
  • Peptides with zero intensities are missing peptides and should be represent with a NA value rather than 0.
pe <- zeroIsNA(pe, "peptideRaw") # convert 0 to NA
  • Logtransform data with base 2
pe <- logTransform(pe, base = 2, i = "peptideRaw", name = "peptideLog")


3.2 Filtering

  • Reverse sequences
  • Only identified by modification site (only modified peptides detected)
  • Razor peptides: non-unique peptides assigned to the protein group with the most other peptides
  • Contaminants
  • Peptides few identifications
  • Proteins that are only identified with one or a few peptides

Filtering does not induce bias if the criterion is independent from the downstream data analysis!

Click to see code to filter the data

  1. Handling overlapping protein groups

In our approach a peptide can map to multiple proteins, as long as there is none of these proteins present in a smaller subgroup.

pe <- filterFeatures(pe, ~ Proteins %in% smallestUniqueGroups(rowData(pe[["peptideLog"]])$Proteins))
## 'Proteins' found in 2 out of 2 assay(s)
  1. Remove reverse sequences (decoys) and contaminants

We now remove the contaminants, peptides that map to decoy sequences, and proteins which were only identified by peptides with modifications.

pe <- filterFeatures(pe,~Reverse != "+")
## 'Reverse' found in 2 out of 2 assay(s)
pe <- filterFeatures(pe,~ Potential.contaminant != "+")
## 'Potential.contaminant' found in 2 out of 2 assay(s)
  1. Drop peptides that were only identified in one sample

We keep peptides that were observed at last twice.

pe <- filterFeatures(pe,~ nNonZero >=2)
## 'nNonZero' found in 2 out of 2 assay(s)
nrow(pe[["peptideLog"]])
## [1] 10478
We keep 10478 peptides upon filtering.


3.3 Normalization

Click to see code to make plot

densityConditionD <- pe[["peptideLog"]][,colData(pe)$condition=="D"] %>% 
  assay %>%
  as.data.frame() %>%
  gather(sample, intensity) %>% 
  mutate(lab = colData(pe)[sample,"lab"]) %>%
  ggplot(aes(x=intensity,group=sample,color=lab)) + 
    geom_density() +
    ggtitle("condition D")

densityLab2 <- pe[["peptideLog"]][,colData(pe)$lab=="lab2"] %>% 
  assay %>%
  as.data.frame() %>%
  gather(sample, intensity) %>% 
  mutate(condition = colData(pe)[sample,"condition"]) %>%
  ggplot(aes(x=intensity,group=sample,color=condition)) + 
    geom_density() +
    ggtitle("lab2")

densityConditionD
## Warning: Removed 39179 rows containing non-finite outside the scale range
## (`stat_density()`).

densityLab2
## Warning: Removed 44480 rows containing non-finite outside the scale range
## (`stat_density()`).

- Even in very clean synthetic dataset (same background, only 48 UPS proteins can be different) the marginal peptide intensity distribution across samples can be quite distinct

  • Considerable effects between and within labs for replicate samples
  • Considerable effects between samples with different spike-in concentration

\(\rightarrow\) Normalization is needed


3.3.1 Mean or median?

  • Miller and Fishkin (1997) reported that over a period of 30 years males would like to have on average 64.3 partners and females 2.8.

  • Miller and Fishkin (1997) reported that the median number of partners someone would like to have over a period of 30 years males is 1 for both males and females.

Mean is very sensitive to outliers!


3.3.2 Normalization of the data by median centering

\[y_{ip}^\text{norm} = y_{ip} - \hat\mu_i\] with \(\hat\mu_i\) the median intensity over all observed peptides in sample \(i\).

Click to see R-code to normalize the data

pe <- normalize(pe, 
                i = "peptideLog", 
                name = "peptideNorm", 
                method = "center.median")

3.3.3 Plots of normalized data

Click to see code to make plot

densityConditionDNorm <- pe[["peptideNorm"]][,colData(pe)$condition=="D"] %>% 
  assay %>%
  as.data.frame() %>%
  gather(sample, intensity) %>% 
  mutate(lab = colData(pe)[sample,"lab"]) %>%
  ggplot(aes(x=intensity,group=sample,color=lab)) + 
    geom_density() +
    ggtitle("condition D")

densityLab2Norm <- pe[["peptideNorm"]][,colData(pe)$lab=="lab2"] %>% 
  assay %>%
  as.data.frame() %>%
  gather(sample, intensity) %>% 
  mutate(condition = colData(pe)[sample,"condition"]) %>%
  ggplot(aes(x=intensity,group=sample,color=condition)) + 
    geom_density() +
    ggtitle("lab2")

densityConditionDNorm
## Warning: Removed 39179 rows containing non-finite outside the scale range
## (`stat_density()`).

densityLab2Norm
## Warning: Removed 44480 rows containing non-finite outside the scale range
## (`stat_density()`).

  • Upon normalization the marginal distributions of the peptide intensities across samples are much more comparable
  • We still see deviations
  • This can be due to technical variability
  • In micro-array literature, quantile normalisation is used to force the median and all other quantiles to be equal across samples
  • In proteomics quantile normalisation often introduces artifacts due to a difference in missing peptides across samples
  • More advanced methods should be developed for normalizing proteomics data
  • If there are differences in the width of the marginal distributions of the data across samples. They can also be standardized by using a robust estimator for location and scale, i.e.  \[y_{ip}^\text{norm} = \frac{y_{ip} - \mu_i}{s_i}\]

3.4 Summarization

  • We illustrate summarization issues using a subset of the cptac study (Lab 2, condition A and E) for a spiked protein (UPS P12081).
Click to see code to make plot

summaryPlot <- pe[["peptideNorm"]][
    rowData(pe[["peptideNorm"]])$Proteins == "P12081ups|SYHC_HUMAN_UPS",
    colData(pe)$lab=="lab2"&colData(pe)$condition %in% c("A","E")] %>%
  assay %>%
  as.data.frame %>%
  rownames_to_column(var = "peptide") %>%
  gather(sample, intensity, -peptide) %>% 
  mutate(condition = colData(pe)[sample,"condition"]) %>%
  ggplot(aes(x = peptide, y = intensity, color = sample, group = sample, label = condition), show.legend = FALSE) +
  geom_line(show.legend = FALSE) +
  geom_text(show.legend = FALSE) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1)) +
  xlab("Peptide") + 
  ylab("Intensity (log2)")

summaryPlot
## Warning: Removed 10 rows containing missing values or values outside the scale range
## (`geom_line()`).
## Warning: Removed 90 rows containing missing values or values outside the scale range
## (`geom_text()`).

We observe:

  • intensities from multiple peptides for each protein in a sample
  • Strong peptide effect -Unbalanced peptide identification
  • Pseudo-replication: peptide intensities from a particular protein in the same sample are correlated, i.e. they more alike than peptide intensities from a particular protein between samples.

\(\rightarrow\) Summarize all peptide intensities from the same protein in a sample into a single protein expression value

Commonly used methods are

  • Mean summarization \[ y_{ip}=\beta_i^\text{samp} + \epsilon_{ip} \]

  • Median summarization

  • Maxquant’s maxLFQ summarization (in protein groups file)

  • Model based summarization: \[ y_{ip}=\beta_i^\text{samp} + \beta_p^\text{pep} + \epsilon_{ip} \]

Click to see R-code to aggregate the data

We use the standard sumarization in aggregateFeatures, which is robust model based summarization.

pe <- aggregateFeatures(pe,
    i = "peptideNorm", 
    fcol = "Proteins", 
    na.rm = TRUE,
    name = "protein")
## 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.

Other summarization methods can be implemented by using the fun argument in the aggregateFeatures function.

  • fun = MsCoreUtils::medianPolish() to fits an additive model (two way decomposition) using Tukey’s median polish_ procedure using stats::medpolish()

  • fun = MsCoreUtils::robustSummary() to calculate a robust aggregation using MASS::rlm() (default)

  • fun = base::colMeans() to use the mean of each column

  • fun = matrixStats::colMedians() to use the median of each column

  • fun = base::colSums() to use the sum of each column


4 Exercise

  1. We will evaluate different summarization methods (Maxquant maxLFQ, median and robust model based) in the tutorial session before discussing on their advantages/disadvantages.
  2. Can you anticipate on potential problems related to the summarization?

5 Software & code

  • Our R/Bioconductor package msqrob2 can be used in R markdown scripts or with a GUI/shinyApp in the msqrob2gui package.

  • The GUI is intended as a introduction to the key concepts of proteomics data analysis for users who have no experience in R.

  • However, learning how to code data analyses in R markdown scripts is key for open en reproducible science and for reporting your proteomics data analyses and interpretation in a reproducible way.

  • More information on our tools can be found in our papers (L. J. Goeminne, Gevaert, and Clement 2016), (L. J. E. Goeminne et al. 2020) and (Sticker et al. 2020). Please refer to our work when using our tools.

5.1 Code

  1. Data infrastructure

  2. Import proteomics data

  1. Preprocessing

    • Log-transformation

    • Filtering

    • Normalisation

    • Summarization

5.2 Data analysis with the GUI/shinyApp msqrob2gui

References

Goeminne, L. J. E., A. Sticker, L. Martens, K. Gevaert, and L. Clement. 2020. MSqRob Takes the Missing Hurdle: Uniting Intensity- and Count-Based Proteomics.” Anal Chem 92 (9): 6278–87.
Goeminne, L. J., K. Gevaert, and L. Clement. 2016. Peptide-level Robust Ridge Regression Improves Estimation, Sensitivity, and Specificity in Data-dependent Quantitative Label-free Shotgun Proteomics.” Mol Cell Proteomics 15 (2): 657–68.
Sticker, A., L. Goeminne, L. Martens, and L. Clement. 2020. Robust Summarization and Inference in Proteome-wide Label-free Quantification.” Mol Cell Proteomics 19 (7): 1209–19.
LS0tCnRpdGxlOiAiU3RhdGlzdGljYWwgTWV0aG9kcyBmb3IgUXVhbnRpdGF0aXZlIE1TLWJhc2VkIFByb3Rlb21pY3M6IFBhcnQgSS4gUHJlcHJvY2Vzc2luZyIKYXV0aG9yOiAiTGlldmVuIENsZW1lbnQiCmRhdGU6ICJbc3RhdE9taWNzXShodHRwczovL3N0YXRvbWljcy5naXRodWIuaW8pLCBHaGVudCBVbml2ZXJzaXR5IgpvdXRwdXQ6CiAgICBodG1sX2RvY3VtZW50OgogICAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICAgIHRoZW1lOiBmbGF0bHkKICAgICAgdG9jOiB0cnVlCiAgICAgIHRvY19mbG9hdDogdHJ1ZQogICAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogICAgcGRmX2RvY3VtZW50OgogICAgICB0b2M6IHRydWUKICAgICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCmxpbmtjb2xvcjogYmx1ZQp1cmxjb2xvcjogYmx1ZQpjaXRlY29sb3I6IGJsdWUKCmJpYmxpb2dyYXBoeTogbXNxcm9iMi5iaWIKICAgICAgCi0tLQoKPGEgcmVsPSJsaWNlbnNlIiBocmVmPSJodHRwczovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktbmMtc2EvNC4wIj48aW1nIGFsdD0iQ3JlYXRpdmUgQ29tbW9ucyBMaWNlbnNlIiBzdHlsZT0iYm9yZGVyLXdpZHRoOjAiIHNyYz0iaHR0cHM6Ly9pLmNyZWF0aXZlY29tbW9ucy5vcmcvbC9ieS1uYy1zYS80LjAvODh4MzEucG5nIiAvPjwvYT4KClRoaXMgaXMgcGFydCBvZiB0aGUgb25saW5lIGNvdXJzZSBbUHJvdGVvbWljcyBEYXRhIEFuYWx5c2lzIChQREEpXShodHRwczovL3N0YXRvbWljcy5naXRodWIuaW8vUERBMjJHVFBCLykKCjxpZnJhbWUgd2lkdGg9IjU2MCIgaGVpZ2h0PSIzMTUiCnNyYz0iaHR0cHM6Ly93d3cueW91dHViZS5jb20vZW1iZWQvVjZJay1TT1JvS28iCmZyYW1lYm9yZGVyPSIwIgpzdHlsZT0iZGlzcGxheTogYmxvY2s7IG1hcmdpbjogYXV0bzsiCmFsbG93PSJhdXRvcGxheTsgZW5jcnlwdGVkLW1lZGlhIiBhbGxvd2Z1bGxzY3JlZW4+PC9pZnJhbWU+CgotIFtQbGF5bGlzdCBQREEgUHJlcHJvY2Vzc2luZ10oaHR0cHM6Ly93d3cueW91dHViZS5jb20vcGxheWxpc3Q/bGlzdD1QTFpIMWhQOF9MYkpKWFFlUV9LWUROb3EtQVh5RkJHNm5YKQoKIyBPdXRsaW5lIHstfQoKMS4gSW50cm9kdWN0aW9uCgoyLiBQcmVwcm9jZXNzaW5nCgogICAgLSBMb2ctdHJhbnNmb3JtYXRpb24KICAgIC0gRmlsdGVyaW5nCiAgICAtIE5vcm1hbGl6YXRpb24KICAgIC0gU3VtbWFyaXphdGlvbgoKTm90ZSwgdGhhdCB0aGUgUi1jb2RlIGlzIGluY2x1ZGVkIGZvciBsZWFybmVycyB3aG8gYXJlIGFpbWluZyB0byBkZXZlbG9wIFIvbWFya2Rvd24gc2NyaXB0cyB0byBhdXRvbWF0ZSB0aGVpciBxdWFudGl0YXRpdmUgcHJvdGVvbWljcyBkYXRhIGFuYWx5c2VzLgpBY2NvcmRpbmcgdG8gdGhlIHRhcmdldCBhdWRpZW5jZSBvZiB0aGUgY291cnNlIHdlIGVpdGhlciB3b3JrIHdpdGggYSBncmFwaGljYWwgdXNlciBpbnRlcmZhY2UgKEdVSSkgaW4gYSBSL3NoaW55IEFwcCBtc3Fyb2IyZ3VpIChlLmcuIFByb3Rlb21pY3MgQmlvaW5mb3JtYXRpY3MgY291cnNlIG9mIHRoZSBFQkkgYW5kIHRoZSBQcm90ZW9taWNzIERhdGEgQW5hbHlzaXMgY291cnNlIGF0IHRoZSBHdWxiZW5raWFuIGluc3RpdHV0ZSkgb3Igd2l0aCBSL21hcmtkb3ducyBzY3JpcHRzIChlLmcuIEJpb2luZm9ybWF0aWNzIFN1bW1lciBTY2hvb2wgYXQgVUNMb3V2YWluIG9yIHRoZSBTdGF0aXN0aWNhbCBHZW5vbWljcyBDb3Vyc2UgYXQgR2hlbnQgVW5pdmVyc2l0eSkuIAoKLS0tCgojIEludHJvOiBDaGFsbGVuZ2VzIGluIExhYmVsLUZyZWUgUXVhbnRpdGF0aXZlIFByb3Rlb21pY3MKCgo8aWZyYW1lIHdpZHRoPSI1NjAiIGhlaWdodD0iMzE1IgpzcmM9Imh0dHBzOi8vd3d3LnlvdXR1YmUuY29tL2VtYmVkLzN3X0s0U19HVXpFIgpmcmFtZWJvcmRlcj0iMCIKc3R5bGU9ImRpc3BsYXk6IGJsb2NrOyBtYXJnaW46IGF1dG87IgphbGxvdz0iYXV0b3BsYXk7IGVuY3J5cHRlZC1tZWRpYSIgYWxsb3dmdWxsc2NyZWVuPjwvaWZyYW1lPgoKCiMjIE1TLWJhc2VkIHdvcmtmbG93CgpgYGB7ciBlY2hvPUZBTFNFfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiLi9maWd1cmVzL1Byb3Rlb21pY3NXb3JrZmxvdy5wbmciKQpgYGAKICAKLSBQZXB0aWRlIENoYXJhY3RlcmlzdGljcwogIAogIC0gTW9kaWZpY2F0aW9ucwogIC0gSW9uaXNhdGlvbiBFZmZpY2llbmN5OiBodWdlIHZhcmlhYmlsaXR5CiAgLSBJZGVudGlmaWNhdGlvbgogICAgLSBNaXNpZGVudGlmaWNhdGlvbiAkXHJpZ2h0YXJyb3ckIG91dGxpZXJzCiAgICAtIE1TJF4yJCBzZWxlY3Rpb24gb24gcGVwdGlkZSBhYnVuZGFuY2UKICAgIC0gQ29udGV4dCBkZXBlbmRpbmcgbWlzc2luZ25lc3MKICAgIC0gTm9uLXJhbmRvbSBtaXNzaW5nbmVzcwoKJFxyaWdodGFycm93JCBVbmJhbGFuY2VkIHBlcGlkZSBpZGVudGlmaWNhdGlvbnMgYWNyb3NzIHNhbXBsZXMgYW5kIG1lc3N5IGRhdGEKCi0tLQoKIyMgTGV2ZWwgb2YgcXVhbnRpZmljYXRpb24KCi0gTVMtYmFzZWQgcHJvdGVvbWljcyByZXR1cm5zIHBlcHRpZGVzOiBwaWVjZXMgb2YgcHJvdGVpbnMKCmBgYHtyIGVjaG89RkFMU0V9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIuL2ZpZ3VyZXMvY2hhbGxlbmdlc19wZXB0aWRlcy5wbmciKQpgYGAKCi0gUXVhbnRpZmljYXRpb24gY29tbW9ubHkgcmVxdWlyZWQgb24gdGhlIHByb3RlaW4gbGV2ZWwKCmBgYHtyIGVjaG89RkFMU0V9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIuL2ZpZ3VyZXMvY2hhbGxlbmdlc19wcm90ZWlucy5wbmciKQpgYGAKCi0tLQoKIyMgTGFiZWwtZnJlZSBRdWFudGl0YXRpdmUgUHJvdGVvbWljcyBEYXRhIEFuYWx5c2lzIFdvcmtmbG93cwoKYGBge3IgZWNobz1GQUxTRX0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi4vZmlndXJlcy9wcm90ZW9taWNzRGF0YUFuYWx5c2lzLnBuZyIpCmBgYAoKLS0tCgojIyBDUFRBQyBTcGlrZS1pbiBTdHVkeQoKPGlmcmFtZSB3aWR0aD0iNTYwIiBoZWlnaHQ9IjMxNSIKc3JjPSJodHRwczovL3d3dy55b3V0dWJlLmNvbS9lbWJlZC82VjVHaUE0Q2cyVSIKZnJhbWVib3JkZXI9IjAiCnN0eWxlPSJkaXNwbGF5OiBibG9jazsgbWFyZ2luOiBhdXRvOyIKYWxsb3c9ImF1dG9wbGF5OyBlbmNyeXB0ZWQtbWVkaWEiIGFsbG93ZnVsbHNjcmVlbj48L2lmcmFtZT4KCmBgYHtyIGVjaG89RkFMU0UsIG91dC53aWR0aD0iNTAlIn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi4vZmlndXJlcy9jcHRhY0xheW91dEx1ZGdlci5wbmciKQpgYGAKCi0gU2FtZSB0cnlwc2luLWRpZ2VzdGVkIHllYXN0IHByb3Rlb21lIGJhY2tncm91bmQgaW4gZWFjaCBzYW1wbGUKLSBUcnlwc2luLWRpZ2VzdGVkIFNpZ21hIFVQUzEgc3RhbmRhcmQ6IDQ4IGRpZmZlcmVudCBodW1hbiBwcm90ZWlucyBzcGlrZWQgaW4gYXQgNSBkaWZmZXJlbnQgY29uY2VudHJhdGlvbnMgKHRyZWF0bWVudCBBLUUpIAotIFNhbXBsZXMgcmVwZWF0ZWRseSBydW4gb24gZGlmZmVyZW50IGluc3RydW1lbnRzIGluIGRpZmZlcmVudCBsYWJzCi0gQWZ0ZXIgTWF4UXVhbnQgc2VhcmNoIHdpdGggbWF0Y2ggYmV0d2VlbiBydW5zIG9wdGlvbgoKICAtIDQxXCUgb2YgYWxsIHByb3RlaW5zIGFyZSBxdWFudGlmaWVkIGluIGFsbCBzYW1wbGVzCiAgLSA2LjZcJSBvZiBhbGwgcGVwdGlkZXMgYXJlIHF1YW50aWZpZWQgaW4gYWxsIHNhbXBsZXMKCiRccmlnaHRhcnJvdyQgdmFzdCBhbW91bnQgb2YgbWlzc2luZ25lc3MKCgojIyBNYXhxdWFudCBvdXRwdXQKCmBgYHtyIGVjaG89RkFMU0V9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIuL2ZpZ3VyZXMvbWF4cXVhbnRPdXRwdXREaXIucG5nIikKYGBgCgotLS0KCgojIEltcG9ydCB0aGUgZGF0YSBpbiBSIAoKIyMgRGF0YSBpbmZyYXN0cnVjdHVyZQoKPGRldGFpbHM+PHN1bW1hcnk+IENsaWNrIHRvIHNlZSBiYWNrZ3JvdW5kIG9uIGRhdGEgaW5mcmFzdHJ1Y3R1cmUgdXNlZCBpbiBSIHRvIHN0b3JlIHByb3Rlb21pY3MgZGF0YSA8L3N1bW1hcnk+PHA+Ci0gV2UgdXNlIHRoZSBgUUZlYXR1cmVzYCBwYWNrYWdlIHRoYXQgcHJvdmlkZXMgdGhlIGluZnJhc3RydWN0dXJlIHRvCiAgLSBzdG9yZSwgIAogIC0gcHJvY2VzcywgCiAgLSBtYW5pcHVsYXRlIGFuZCAKICAtIGFuYWx5c2UgcXVhbnRpdGF0aXZlIGRhdGEvZmVhdHVyZXMgZnJvbSBtYXNzIHNwZWN0cm9tZXRyeQpleHBlcmltZW50cy4gCgotIEl0IGlzIGJhc2VkIG9uIHRoZSBgU3VtbWFyaXplZEV4cGVyaW1lbnRgIGFuZApgTXVsdGlBc3NheUV4cGVyaW1lbnRgIGNsYXNzZXMuIAoKCgpgYGB7ciBmaWcuY2FwID0gIkNvbmNlcHR1YWwgcmVwcmVzZW50YXRpb24gb2YgYSBgU3VtbWFyaXplZEV4cGVyaW1lbnRgIG9iamVjdC4gIEFzc2F5cyBjb250YWluIGluZm9ybWF0aW9uIG9uIHRoZSBtZWFzdXJlZCBvbWljcyBmZWF0dXJlcyAocm93cykgZm9yIGRpZmZlcmVudCBzYW1wbGVzIChjb2x1bW5zKS4gVGhlIGByb3dEYXRhYCBjb250YWlucyBpbmZvcm1hdGlvbiBvbiB0aGUgb21pY3MgZmVhdHVyZXMsIHRoZSBgY29sRGF0YWAgY29udGFpbnMgaW5mb3JtYXRpb24gb24gdGhlIHNhbXBsZXMsIGkuZS4gZXhwZXJpbWVudGFsIGRlc2lnbiBldGMuIiwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI4MCUifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiLi9maWd1cmVzL1NFLnBuZyIpCmBgYAoKLSBBc3NheXMgaW4gYSBRRmVhdHVyZXMgb2JqZWN0IGhhdmUgYQpoaWVyYXJjaGljYWwgcmVsYXRpb246IAogIAogIC0gcHJvdGVpbnMgYXJlIGNvbXBvc2VkIG9mIHBlcHRpZGVzLCAKICAtIHRoZW1zZWx2ZXMgcHJvZHVjZWQgYnkgc3BlY3RyYQogIC0gcmVsYXRpb25zIGJldHdlZW4gYXNzYXlzIGFyZSB0cmFja2VkIGFuZCByZWNvcmRlZCB0aHJvdWdob3V0IGRhdGEgcHJvY2Vzc2luZwoKYGBge3IgZmVhdHVyZXNwbG90LCBmaWcuY2FwID0gIkNvbmNlcHR1YWwgcmVwcmVzZW50YXRpb24gb2YgYSBgUUZlYXR1cmVzYCBvYmplY3QgYW5kIHRoZSBhZ2dyZWdhdGl2ZSByZWxhdGlvbiBiZXR3ZWVuIGRpZmZlcmVudCBhc3NheXMuIiwgZWNobyA9IEZBTFNFfQpwYXIobWFyID0gYygwLCAwLCAwLCAwKSkKcGxvdChOQSwgeGxpbSA9IGMoMCwgMTIpLCB5bGltID0gYygwLCAyMCksCiAgICAgeGF4dCA9ICJuIiwgeWF4dCA9ICJuIiwKICAgICB4bGFiID0gIiIsIHlsYWIgPSAiIiwgYnR5ID0gIm4iKQpmb3IgKGkgaW4gMDo3KQogICAgcmVjdCgwLCBpLCAzLCBpKzEsIGNvbCA9ICJsaWdodGdyZXkiLCBib3JkZXIgPSAid2hpdGUiKQpmb3IgKGkgaW4gODoxMikKICAgIHJlY3QoMCwgaSwgMywgaSsxLCBjb2wgPSAic3RlZWxibHVlIiwgYm9yZGVyID0gIndoaXRlIikKZm9yIChpIGluIDEzOjE4KQogICAgcmVjdCgwLCBpLCAzLCBpKzEsIGNvbCA9ICJvcmFuZ2UiLCBib3JkZXIgPSAid2hpdGUiKQpmb3IgKGkgaW4gMTkpCiAgICByZWN0KDAsIGksIDMsIGkrMSwgY29sID0gImRhcmtncmV5IiwgYm9yZGVyID0gIndoaXRlIikKZm9yIChpIGluIDU6NykKICAgIHJlY3QoNSwgaSwgOCwgaSsxLCBjb2wgPSAibGlnaHRncmV5IiwgYm9yZGVyID0gIndoaXRlIikKZm9yIChpIGluIDg6MTApCiAgICByZWN0KDUsIGksIDgsIGkrMSwgY29sID0gInN0ZWVsYmx1ZSIsIGJvcmRlciA9ICJ3aGl0ZSIpCmZvciAoaSBpbiAxMToxMykKICAgIHJlY3QoNSwgaSwgOCwgaSsxLCBjb2wgPSAib3JhbmdlIiwgYm9yZGVyID0gIndoaXRlIikKZm9yIChpIGluIDE0KQogICAgcmVjdCg1LCBpLCA4LCBpKzEsIGNvbCA9ICJkYXJrZ3JleSIsIGJvcmRlciA9ICJ3aGl0ZSIpCnJlY3QoOSwgOCwgMTIsIDgrMSwgY29sID0gImxpZ2h0Z3JleSIsIGJvcmRlciA9ICJ3aGl0ZSIpCnJlY3QoOSwgOSwgMTIsIDkrMSwgY29sID0gInN0ZWVsYmx1ZSIsIGJvcmRlciA9ICJ3aGl0ZSIpCnJlY3QoOSwgMTAsIDEyLCAxMCsxLCBjb2wgPSAib3JhbmdlIiwgYm9yZGVyID0gIndoaXRlIikKcmVjdCg5LCAxMSwgMTIsIDExKzEsIGNvbCA9ICJkYXJrZ3JleSIsIGJvcmRlciA9ICJ3aGl0ZSIpCnNlZ21lbnRzKDMsIDgsIDUsIDgsIGx0eSA9ICJkYXNoZWQiKQpzZWdtZW50cygzLCA2LCA1LCA3LCBsdHkgPSAiZGFzaGVkIikKc2VnbWVudHMoMywgNCwgNSwgNiwgbHR5ID0gImRhc2hlZCIpCnNlZ21lbnRzKDMsIDAsIDUsIDUsIGx0eSA9ICJkYXNoZWQiKQpzZWdtZW50cygzLCAxMCwgNSwgOSwgbHR5ID0gImRhc2hlZCIpCnNlZ21lbnRzKDMsIDExLCA1LCAxMCwgbHR5ID0gImRhc2hlZCIpCnNlZ21lbnRzKDMsIDEzLCA1LCAxMSwgbHR5ID0gImRhc2hlZCIpCnNlZ21lbnRzKDMsIDE0LCA1LCAxMiwgbHR5ID0gImRhc2hlZCIpCnNlZ21lbnRzKDMsIDE2LCA1LCAxMywgbHR5ID0gImRhc2hlZCIpCnNlZ21lbnRzKDMsIDE5LCA1LCAxNCwgbHR5ID0gImRhc2hlZCIpCnNlZ21lbnRzKDMsIDIwLCA1LCAxNSwgbHR5ID0gImRhc2hlZCIpCnNlZ21lbnRzKDgsIDUsIDksIDgsIGx0eSA9ICJkYXNoZWQiKQpzZWdtZW50cyg4LCA4LCA5LCA5LCBsdHkgPSAiZGFzaGVkIikKc2VnbWVudHMoOCwgMTEsIDksIDEwLCBsdHkgPSAiZGFzaGVkIikKc2VnbWVudHMoOCwgMTQsIDksIDExLCBsdHkgPSAiZGFzaGVkIikKc2VnbWVudHMoOCwgMTUsIDksIDEyLCBsdHkgPSAiZGFzaGVkIikKYGBgCgo8L3A+PC9kZXRhaWxzPgoKIyMgSW1wb3J0IGRhdGEgaW4gUgoKCiMjIyBMb2FkIGxpYnJhcmllcyAKCjxkZXRhaWxzPjxzdW1tYXJ5PiBDbGljayB0byBzZWUgY29kZSA8L3N1bW1hcnk+PHA+CmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShsaW1tYSkKbGlicmFyeShRRmVhdHVyZXMpCmxpYnJhcnkobXNxcm9iMikKbGlicmFyeShwbG90bHkpCmxpYnJhcnkoZ2dwbG90MikKYGBgCjwvcD48L2RldGFpbHM+CgojIyMgUmVhZCBkYXRhIAoKPGRldGFpbHM+PHN1bW1hcnk+IENsaWNrIHRvIHNlZSBiYWNrZ3JvdW5kIGFuZCBjb2RlIDwvc3VtbWFyeT48cD4KMS4gV2UgdXNlIGEgcGVwdGlkZXMudHh0IGZpbGUgZnJvbSBNUy1kYXRhIHF1YW50aWZpZWQgd2l0aCBtYXhxdWFudCB0aGF0IApjb250YWlucyBNUzEgaW50ZW5zaXRpZXMgc3VtbWFyaXplZCBhdCB0aGUgcGVwdGlkZSBsZXZlbC4gCmBgYHtyfQpwZXB0aWRlc0ZpbGUgPC0gImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9zdGF0T21pY3MvUERBMjJHVFBCL2RhdGEvcXVhbnRpZmljYXRpb24vZnVsbENwdGFjRGF0YXNTZXROb3RGb3JUdXRvcmlhbC9wZXB0aWRlcy50eHQiCmBgYAoKMi4gTWF4cXVhbnQgc3RvcmVzIHRoZSBpbnRlbnNpdHkgZGF0YSBmb3IgdGhlIGRpZmZlcmVudCBzYW1wbGVzIGluIGNvbHVtbm5zIHRoYXQgc3RhcnQgd2l0aCBJbnRlbnNpdHkuIFdlIGNhbiByZXRyZWl2ZSB0aGUgY29sdW1uIG5hbWVzIHdpdGggdGhlIGludGVuc2l0eSBkYXRhIHdpdGggdGhlIGNvZGUgYmVsb3c6IAoKYGBge3J9CmVjb2xzIDwtIGdyZXAoIkludGVuc2l0eVxcLiIsIG5hbWVzKHJlYWQuZGVsaW0ocGVwdGlkZXNGaWxlKSkpCmBgYAoKMy4gUmVhZCB0aGUgZGF0YSBhbmQgc3RvcmUgaXQgaW4gIFFGZWF0dXJlcyBvYmplY3QgCgpgYGB7cn0KcGUgPC0gcmVhZFFGZWF0dXJlcygKICBhc3NheURhdGEgPSByZWFkLmRlbGltKHBlcHRpZGVzRmlsZSksCiAgZm5hbWVzID0gMSwKICBxdWFudENvbHMgPSBlY29scywKICBuYW1lID0gInBlcHRpZGVSYXciKQpgYGAKPC9wPjwvZGV0YWlscz4KCiMjIyBFeHBsb3JlIG9iamVjdAoKPGRldGFpbHM+PHN1bW1hcnk+IENsaWNrIHRvIHNlZSBiYWNrZ3JvdW5kIGFuZCBjb2RlIDwvc3VtbWFyeT48cD4KLSBUaGUgcm93RGF0YSBjb250YWlucyBpbmZvcm1hdGlvbiBvbiB0aGUgZmVhdHVyZXMgKHBlcHRpZGVzKSBpbiB0aGUgYXNzYXkuIEUuZy4gU2VxdWVuY2UsIHByb3RlaW4sIC4uLgoKYGBge3J9CnJvd0RhdGEocGVbWyJwZXB0aWRlUmF3Il1dKQpgYGAKCi0gVGhlIGNvbERhdGEgY29udGFpbnMgaW5mb3JtYXRpb24gb24gdGhlIHNhbXBsZXMKCmBgYHtyfSAKY29sRGF0YShwZSkKYGBgCgotIE5vIGluZm9ybWF0aW9uIGlzIHN0b3JlZCB5ZXQgb24gdGhlIGRlc2lnbi4gCgoKYGBge3J9IApwZSAlPiUgY29sbmFtZXMKYGBgCgotIE5vdGUsIHRoYXQgdGhlIHNhbXBsZSBuYW1lcyBpbmNsdWRlIHRoZSBzcGlrZS1pbiBjb25kaXRpb24uIAotIFRoZXkgYWxzbyBlbmQgb24gYSBudW1iZXIuIAogIAogIC0gMS0zIGlzIGZyb20gbGFiIDEsIAogIC0gNC02IGZyb20gbGFiIDIgYW5kIAogIC0gNy05IGZyb20gbGFiIDMuIAoKLSBXZSB1cGRhdGUgdGhlIGNvbERhdGEgd2l0aCBpbmZvcm1hdGlvbiBvbiB0aGUgZGVzaWduCgpgYGB7cn0KY29sRGF0YShwZSkkbGFiIDwtIHJlcChyZXAocGFzdGUwKCJsYWIiLDE6MyksZWFjaD0zKSw1KSAlPiUgYXMuZmFjdG9yCmNvbERhdGEocGUpJGNvbmRpdGlvbiA8LSBwZVtbInBlcHRpZGVSYXciXV0gJT4lIGNvbG5hbWVzICU+JSBzdWJzdHIoMTIsMTIpICU+JSBhcy5mYWN0b3IKY29sRGF0YShwZSkkc3Bpa2VDb25jZW50cmF0aW9uIDwtIHJlcChjKEEgPSAwLjI1LCBCID0gMC43NCwgQyA9IDIuMjIsIEQgPSA2LjY3LCBFID0gMjApLGVhY2ggPSA5KQpgYGAKCi0gV2UgZXhwbG9yZSB0aGUgY29sRGF0YSBhZ2FpbgoKYGBge3J9CmNvbERhdGEocGUpCmBgYAoKPC9wPjwvZGV0YWlscz4KCi0tLQoKIyBQcmVwcm9jZXNzaW5nCgojIyBMb2ctdHJhbnNmb3JtYXRpb24KCjxpZnJhbWUgd2lkdGg9IjU2MCIgaGVpZ2h0PSIzMTUiCnNyYz0iaHR0cHM6Ly93d3cueW91dHViZS5jb20vZW1iZWQvQVBzZFNidTFSQk0iCmZyYW1lYm9yZGVyPSIwIgpzdHlsZT0iZGlzcGxheTogYmxvY2s7IG1hcmdpbjogYXV0bzsiCmFsbG93PSJhdXRvcGxheTsgZW5jcnlwdGVkLW1lZGlhIiBhbGxvd2Z1bGxzY3JlZW4+PC9pZnJhbWU+CgojIyMgRXhwbG9yZSB0aGUgZGF0YSB3aXRoIHBsb3RzCgpQZXB0aWRlIEFBTEVFTFZLIGZyb20gc3Bpa2VkLWluIFVQUyBwcm90ZWluIFAxMjA4MS4gCldlIG9ubHkgc2hvdyBkYXRhIGZyb20gbGFiMS4KCjxkZXRhaWxzPjxzdW1tYXJ5PiBDbGljayB0byBzZWUgY29kZSB0byBtYWtlIHBsb3QgPC9zdW1tYXJ5PjxwPgpgYGB7cn0Kc3Vic2V0IDwtIHBlWyJBQUxFRUxWSyIsY29sRGF0YShwZSkkbGFiPT0ibGFiMSJdCnBsb3RXaHlMb2cgPC0gZGF0YS5mcmFtZShjb25jZW50cmF0aW9uID0gY29sRGF0YShzdWJzZXQpJHNwaWtlQ29uY2VudHJhdGlvbiwKICAgICAgICAgICB5ID0gYXNzYXkoc3Vic2V0W1sicGVwdGlkZVJhdyJdXSkgJT4lIGMKICAgICAgICAgICApICU+JSAKICBnZ3Bsb3QoYWVzKGNvbmNlbnRyYXRpb24sIHkpKSArCiAgZ2VvbV9wb2ludCgpICsKICB4bGFiKCJjb25jZW50cmF0aW9uIChmbW9sL2wpIikgKwogIGdndGl0bGUoInBlcHRpZGUgQUFMRUVMVksgaW4gbGFiMSIpCmBgYAo8L3A+PC9kZXRhaWxzPgoKYGBge3J9CnBsb3RXaHlMb2cKYGBgCgotIFZhcmlhbmNlIGluY3JlYXNlcyB3aXRoIHRoZSBtZWFuCiRccmlnaHRhcnJvdyQgTXVsdGlwbGljYXRpdmUgZXJyb3Igc3RydWN0dXJlIAoKPGRldGFpbHM+PHN1bW1hcnk+IENsaWNrIHRvIHNlZSBjb2RlIHRvIG1ha2UgcGxvdCA8L3N1bW1hcnk+PHA+CmBgYHtyfQpwbG90TG9nIDwtIGRhdGEuZnJhbWUoY29uY2VudHJhdGlvbiA9IGNvbERhdGEoc3Vic2V0KSRzcGlrZUNvbmNlbnRyYXRpb24sCiAgICAgICAgICAgeSA9IGFzc2F5KHN1YnNldFtbInBlcHRpZGVSYXciXV0pICU+JSBjCiAgICAgICAgICAgKSAlPiUgCiAgZ2dwbG90KGFlcyhjb25jZW50cmF0aW9uLCB5KSkgKwogIGdlb21fcG9pbnQoKSArIAogIHNjYWxlX3hfY29udGludW91cyh0cmFucz0nbG9nMicpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKHRyYW5zPSdsb2cyJykgKwogIHhsYWIoImNvbmNlbnRyYXRpb24gKGZtb2wvbCkiKSArCiAgZ2d0aXRsZSgicGVwdGlkZSBBQUxFRUxWSyBpbiBsYWIxIHdpdGggYXhlcyBvbiBsb2cgc2NhbGUiKQpgYGAKPC9wPjwvZGV0YWlscz4KCmBgYHtyfQpwbG90TG9nCmBgYAoKLSBEYXRhIHNlZW1zIHRvIGJlIGhvbW9zY2VkYXN0aWMgb24gbG9nLXNjYWxlICRccmlnaHRhcnJvdyQgbG9nIHRyYW5zZm9ybWF0aW9uIG9mIHRoZSBpbnRlbnNpdHkgZGF0YQotIEluIHF1YW50aXRhdGl2ZSBwcm90ZW9taWNzIGFuYWx5c2lzIG9uICRcbG9nXzIkIAoKJFxyaWdodGFycm93JCBEaWZmZXJlbmNlcyBvbiBhICRcbG9nXzIkIHNjYWxlOiAkXGxvZ18yJCBmb2xkIGNoYW5nZXMKCiQkClxsb2dfMiBCIC0gXGxvZ18yIEEgPSBcbG9nXzIgXGZyYWN7Qn17QX0gPSBcbG9nIEZDX1x0ZXh0e0IgLSBBfQokJAokJCAKXGJlZ2lue2FycmF5fSB7bH0KbG9nXzIgRkMgPSAxIFxyaWdodGFycm93IEZDID0gMl4xID0yXFwKbG9nXzIgRkMgPSAyIFxyaWdodGFycm93IEZDID0gMl4yID0gNFxcClxlbmR7YXJyYXl9CiQkCgoKIyMjIGxvZy10cmFuc2Zvcm1hdGlvbiBvZiB0aGUgZGF0YSAKCjxkZXRhaWxzPjxzdW1tYXJ5PiBDbGljayB0byBzZWUgY29kZSB0byBsb2ctdHJhbnNmcm9tIHRoZSBkYXRhIDwvc3VtbWFyeT48cD4KLSBXZSBjYWxjdWxhdGUgaG93IG1hbnkgbm9uIHplcm8gaW50ZW5zaXRpZXMgd2UgaGF2ZSBmb3IgZWFjaCBwZXB0aWRlIGFuZCB0aGlzIGNhbiBiZSB1c2VmdWwgZm9yIGZpbHRlcmluZy4KCmBgYHtyfQpyb3dEYXRhKHBlW1sicGVwdGlkZVJhdyJdXSkkbk5vblplcm8gPC0gcm93U3Vtcyhhc3NheShwZVtbInBlcHRpZGVSYXciXV0pID4gMCkKYGBgCgoKLSBQZXB0aWRlcyB3aXRoIHplcm8gaW50ZW5zaXRpZXMgYXJlIG1pc3NpbmcgcGVwdGlkZXMgYW5kIHNob3VsZCBiZSByZXByZXNlbnQKd2l0aCBhIGBOQWAgdmFsdWUgcmF0aGVyIHRoYW4gYDBgLgoKYGBge3J9CnBlIDwtIHplcm9Jc05BKHBlLCAicGVwdGlkZVJhdyIpICMgY29udmVydCAwIHRvIE5BCmBgYAoKLSBMb2d0cmFuc2Zvcm0gZGF0YSB3aXRoIGJhc2UgMgoKYGBge3J9CnBlIDwtIGxvZ1RyYW5zZm9ybShwZSwgYmFzZSA9IDIsIGkgPSAicGVwdGlkZVJhdyIsIG5hbWUgPSAicGVwdGlkZUxvZyIpCmBgYAo8L3A+PC9kZXRhaWxzPgoKLS0tCgojIyBGaWx0ZXJpbmcKCjxpZnJhbWUgd2lkdGg9IjU2MCIgaGVpZ2h0PSIzMTUiCnNyYz0iaHR0cHM6Ly93d3cueW91dHViZS5jb20vZW1iZWQvM3pWRnFkVGxCX2MiCmZyYW1lYm9yZGVyPSIwIgpzdHlsZT0iZGlzcGxheTogYmxvY2s7IG1hcmdpbjogYXV0bzsiCmFsbG93PSJhdXRvcGxheTsgZW5jcnlwdGVkLW1lZGlhIiBhbGxvd2Z1bGxzY3JlZW4+PC9pZnJhbWU+CgotIFJldmVyc2Ugc2VxdWVuY2VzCi0gT25seSBpZGVudGlmaWVkIGJ5IG1vZGlmaWNhdGlvbiBzaXRlIChvbmx5IG1vZGlmaWVkIHBlcHRpZGVzIGRldGVjdGVkKQotIFJhem9yIHBlcHRpZGVzOiBub24tdW5pcXVlIHBlcHRpZGVzIGFzc2lnbmVkIHRvIHRoZSBwcm90ZWluIGdyb3VwIHdpdGggdGhlIG1vc3Qgb3RoZXIgcGVwdGlkZXMgCi0gQ29udGFtaW5hbnRzCi0gUGVwdGlkZXMgZmV3IGlkZW50aWZpY2F0aW9ucwotIFByb3RlaW5zIHRoYXQgYXJlIG9ubHkgaWRlbnRpZmllZCB3aXRoIG9uZSBvciBhIGZldyBwZXB0aWRlcwoKRmlsdGVyaW5nIGRvZXMgbm90IGluZHVjZSBiaWFzIGlmIHRoZSBjcml0ZXJpb24gaXMgaW5kZXBlbmRlbnQgZnJvbSB0aGUgZG93bnN0cmVhbSBkYXRhIGFuYWx5c2lzIQoKPGRldGFpbHM+PHN1bW1hcnk+IENsaWNrIHRvIHNlZSBjb2RlIHRvIGZpbHRlciB0aGUgZGF0YSA8L3N1bW1hcnk+PHA+CgoxLiBIYW5kbGluZyBvdmVybGFwcGluZyBwcm90ZWluIGdyb3VwcwoKSW4gb3VyIGFwcHJvYWNoIGEgcGVwdGlkZSBjYW4gbWFwIHRvIG11bHRpcGxlIHByb3RlaW5zLCBhcyBsb25nIGFzIHRoZXJlIGlzCm5vbmUgb2YgdGhlc2UgcHJvdGVpbnMgcHJlc2VudCBpbiBhIHNtYWxsZXIgc3ViZ3JvdXAuCgpgYGB7cn0KcGUgPC0gZmlsdGVyRmVhdHVyZXMocGUsIH4gUHJvdGVpbnMgJWluJSBzbWFsbGVzdFVuaXF1ZUdyb3Vwcyhyb3dEYXRhKHBlW1sicGVwdGlkZUxvZyJdXSkkUHJvdGVpbnMpKQpgYGAKCjIuIFJlbW92ZSByZXZlcnNlIHNlcXVlbmNlcyAoZGVjb3lzKSBhbmQgY29udGFtaW5hbnRzCgpXZSBub3cgcmVtb3ZlIHRoZSBjb250YW1pbmFudHMsIHBlcHRpZGVzIHRoYXQgbWFwIHRvIGRlY295IHNlcXVlbmNlcywgYW5kIHByb3RlaW5zCndoaWNoIHdlcmUgb25seSBpZGVudGlmaWVkIGJ5IHBlcHRpZGVzIHdpdGggbW9kaWZpY2F0aW9ucy4KCmBgYHtyfQpwZSA8LSBmaWx0ZXJGZWF0dXJlcyhwZSx+UmV2ZXJzZSAhPSAiKyIpCnBlIDwtIGZpbHRlckZlYXR1cmVzKHBlLH4gUG90ZW50aWFsLmNvbnRhbWluYW50ICE9ICIrIikKYGBgCgozLiBEcm9wIHBlcHRpZGVzIHRoYXQgd2VyZSBvbmx5IGlkZW50aWZpZWQgaW4gb25lIHNhbXBsZQoKV2Uga2VlcCBwZXB0aWRlcyB0aGF0IHdlcmUgb2JzZXJ2ZWQgYXQgbGFzdCB0d2ljZS4KCmBgYHtyfQpwZSA8LSBmaWx0ZXJGZWF0dXJlcyhwZSx+IG5Ob25aZXJvID49MikKbnJvdyhwZVtbInBlcHRpZGVMb2ciXV0pCmBgYAoKV2Uga2VlcCBgciBucm93KHBlW1sicGVwdGlkZUxvZyJdXSlgIHBlcHRpZGVzIHVwb24gZmlsdGVyaW5nLgo8L3A+PC9kZXRhaWxzPgoKLS0tCgojIyBOb3JtYWxpemF0aW9uIAoKPGlmcmFtZSB3aWR0aD0iNTYwIiBoZWlnaHQ9IjMxNSIKc3JjPSJodHRwczovL3d3dy55b3V0dWJlLmNvbS9lbWJlZC85cUNKRWtkU1NoSSIKZnJhbWVib3JkZXI9IjAiCnN0eWxlPSJkaXNwbGF5OiBibG9jazsgbWFyZ2luOiBhdXRvOyIKYWxsb3c9ImF1dG9wbGF5OyBlbmNyeXB0ZWQtbWVkaWEiIGFsbG93ZnVsbHNjcmVlbj48L2lmcmFtZT4KCjxkZXRhaWxzPjxzdW1tYXJ5PiBDbGljayB0byBzZWUgY29kZSB0byBtYWtlIHBsb3QgPC9zdW1tYXJ5PjxwPgoKYGBge3J9CmRlbnNpdHlDb25kaXRpb25EIDwtIHBlW1sicGVwdGlkZUxvZyJdXVssY29sRGF0YShwZSkkY29uZGl0aW9uPT0iRCJdICU+JSAKICBhc3NheSAlPiUKICBhcy5kYXRhLmZyYW1lKCkgJT4lCiAgZ2F0aGVyKHNhbXBsZSwgaW50ZW5zaXR5KSAlPiUgCiAgbXV0YXRlKGxhYiA9IGNvbERhdGEocGUpW3NhbXBsZSwibGFiIl0pICU+JQogIGdncGxvdChhZXMoeD1pbnRlbnNpdHksZ3JvdXA9c2FtcGxlLGNvbG9yPWxhYikpICsgCiAgICBnZW9tX2RlbnNpdHkoKSArCiAgICBnZ3RpdGxlKCJjb25kaXRpb24gRCIpCgpkZW5zaXR5TGFiMiA8LSBwZVtbInBlcHRpZGVMb2ciXV1bLGNvbERhdGEocGUpJGxhYj09ImxhYjIiXSAlPiUgCiAgYXNzYXkgJT4lCiAgYXMuZGF0YS5mcmFtZSgpICU+JQogIGdhdGhlcihzYW1wbGUsIGludGVuc2l0eSkgJT4lIAogIG11dGF0ZShjb25kaXRpb24gPSBjb2xEYXRhKHBlKVtzYW1wbGUsImNvbmRpdGlvbiJdKSAlPiUKICBnZ3Bsb3QoYWVzKHg9aW50ZW5zaXR5LGdyb3VwPXNhbXBsZSxjb2xvcj1jb25kaXRpb24pKSArIAogICAgZ2VvbV9kZW5zaXR5KCkgKwogICAgZ2d0aXRsZSgibGFiMiIpCmBgYAo8L3A+PC9kZXRhaWxzPgoKYGBge3J9CmRlbnNpdHlDb25kaXRpb25ECmBgYAoKYGBge3J9CmRlbnNpdHlMYWIyCmBgYAotIEV2ZW4gaW4gdmVyeSBjbGVhbiBzeW50aGV0aWMgZGF0YXNldCAoc2FtZSBiYWNrZ3JvdW5kLCBvbmx5IDQ4IFVQUwpwcm90ZWlucyBjYW4gYmUgZGlmZmVyZW50KSB0aGUgbWFyZ2luYWwgcGVwdGlkZSBpbnRlbnNpdHkgZGlzdHJpYnV0aW9uCmFjcm9zcyBzYW1wbGVzIGNhbiBiZSBxdWl0ZSBkaXN0aW5jdAoKLSBDb25zaWRlcmFibGUgZWZmZWN0cyBiZXR3ZWVuIGFuZCB3aXRoaW4gbGFicyBmb3IgcmVwbGljYXRlIHNhbXBsZXMKLSBDb25zaWRlcmFibGUgZWZmZWN0cyBiZXR3ZWVuIHNhbXBsZXMgd2l0aCBkaWZmZXJlbnQgc3Bpa2UtaW4KY29uY2VudHJhdGlvbgoKJFxyaWdodGFycm93JCBOb3JtYWxpemF0aW9uIGlzIG5lZWRlZAoKLS0tCgoKIyMjIE1lYW4gb3IgbWVkaWFuPwoKLSBNaWxsZXIgYW5kIEZpc2hraW4gKDE5OTcpIHJlcG9ydGVkIHRoYXQgb3ZlciBhIHBlcmlvZCBvZiAzMCB5ZWFycyBtYWxlcyB3b3VsZCBsaWtlIHRvIGhhdmUgb24gYXZlcmFnZSA2NC4zIHBhcnRuZXJzIGFuZCBmZW1hbGVzIDIuOC4gCgoKPGRldGFpbHM+PHN1bW1hcnk+IDwvc3VtbWFyeT48cD4KLSBNaWxsZXIgYW5kIEZpc2hraW4gKDE5OTcpIHJlcG9ydGVkIHRoYXQgdGhlIG1lZGlhbiBudW1iZXIgb2YgcGFydG5lcnMgc29tZW9uZSB3b3VsZCBsaWtlIHRvIGhhdmUgb3ZlciBhIHBlcmlvZCBvZiAzMCB5ZWFycyBtYWxlcyBpcyAxIGZvciBib3RoIG1hbGVzIGFuZCBmZW1hbGVzLiAKPC9wPjwvZGV0YWlscz4KCjxkZXRhaWxzPjxzdW1tYXJ5PiA8L3N1bW1hcnk+PHA+Ck1lYW4gaXMgdmVyeSBzZW5zaXRpdmUgdG8gb3V0bGllcnMhCgpgYGB7ciBlY2hvPUZBTFNFfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiLi9maWd1cmVzL3BhcnRuZXJzLnBuZyIpCmBgYAo8L3A+PC9kZXRhaWxzPgoKCi0tLQoKIyMjIE5vcm1hbGl6YXRpb24gb2YgdGhlIGRhdGEgYnkgbWVkaWFuIGNlbnRlcmluZwoKJCR5X3tpcH1eXHRleHR7bm9ybX0gPSB5X3tpcH0gLSBcaGF0XG11X2kkJCAKd2l0aCAkXGhhdFxtdV9pJCB0aGUgbWVkaWFuIGludGVuc2l0eSBvdmVyIGFsbCBvYnNlcnZlZCBwZXB0aWRlcyBpbiBzYW1wbGUgJGkkLgoKPGRldGFpbHM+PHN1bW1hcnk+IENsaWNrIHRvIHNlZSBSLWNvZGUgdG8gbm9ybWFsaXplIHRoZSBkYXRhIDwvc3VtbWFyeT48cD4KYGBge3J9CnBlIDwtIG5vcm1hbGl6ZShwZSwgCiAgICAgICAgICAgICAgICBpID0gInBlcHRpZGVMb2ciLCAKICAgICAgICAgICAgICAgIG5hbWUgPSAicGVwdGlkZU5vcm0iLCAKICAgICAgICAgICAgICAgIG1ldGhvZCA9ICJjZW50ZXIubWVkaWFuIikKYGBgCjwvcD48L2RldGFpbHM+CgojIyMgUGxvdHMgb2Ygbm9ybWFsaXplZCBkYXRhCgoKPGRldGFpbHM+PHN1bW1hcnk+IENsaWNrIHRvIHNlZSBjb2RlIHRvIG1ha2UgcGxvdCA8L3N1bW1hcnk+PHA+CmBgYHtyfQpkZW5zaXR5Q29uZGl0aW9uRE5vcm0gPC0gcGVbWyJwZXB0aWRlTm9ybSJdXVssY29sRGF0YShwZSkkY29uZGl0aW9uPT0iRCJdICU+JSAKICBhc3NheSAlPiUKICBhcy5kYXRhLmZyYW1lKCkgJT4lCiAgZ2F0aGVyKHNhbXBsZSwgaW50ZW5zaXR5KSAlPiUgCiAgbXV0YXRlKGxhYiA9IGNvbERhdGEocGUpW3NhbXBsZSwibGFiIl0pICU+JQogIGdncGxvdChhZXMoeD1pbnRlbnNpdHksZ3JvdXA9c2FtcGxlLGNvbG9yPWxhYikpICsgCiAgICBnZW9tX2RlbnNpdHkoKSArCiAgICBnZ3RpdGxlKCJjb25kaXRpb24gRCIpCgpkZW5zaXR5TGFiMk5vcm0gPC0gcGVbWyJwZXB0aWRlTm9ybSJdXVssY29sRGF0YShwZSkkbGFiPT0ibGFiMiJdICU+JSAKICBhc3NheSAlPiUKICBhcy5kYXRhLmZyYW1lKCkgJT4lCiAgZ2F0aGVyKHNhbXBsZSwgaW50ZW5zaXR5KSAlPiUgCiAgbXV0YXRlKGNvbmRpdGlvbiA9IGNvbERhdGEocGUpW3NhbXBsZSwiY29uZGl0aW9uIl0pICU+JQogIGdncGxvdChhZXMoeD1pbnRlbnNpdHksZ3JvdXA9c2FtcGxlLGNvbG9yPWNvbmRpdGlvbikpICsgCiAgICBnZW9tX2RlbnNpdHkoKSArCiAgICBnZ3RpdGxlKCJsYWIyIikKYGBgCjwvcD48L2RldGFpbHM+CgpgYGB7cn0KZGVuc2l0eUNvbmRpdGlvbkROb3JtCmBgYAoKYGBge3J9CmRlbnNpdHlMYWIyTm9ybQpgYGAKCi0gVXBvbiBub3JtYWxpemF0aW9uIHRoZSBtYXJnaW5hbCBkaXN0cmlidXRpb25zIG9mIHRoZSBwZXB0aWRlIGludGVuc2l0aWVzIGFjcm9zcyBzYW1wbGVzIGFyZSBtdWNoIG1vcmUgY29tcGFyYWJsZQotIFdlIHN0aWxsIHNlZSBkZXZpYXRpb25zCi0gVGhpcyBjYW4gYmUgZHVlIHRvIHRlY2huaWNhbCB2YXJpYWJpbGl0eQotIEluIG1pY3JvLWFycmF5IGxpdGVyYXR1cmUsIHF1YW50aWxlIG5vcm1hbGlzYXRpb24gaXMgdXNlZCB0byBmb3JjZSB0aGUgbWVkaWFuIGFuZCBhbGwgb3RoZXIgcXVhbnRpbGVzIHRvIGJlIGVxdWFsIGFjcm9zcyBzYW1wbGVzCi0gSW4gcHJvdGVvbWljcyBxdWFudGlsZSBub3JtYWxpc2F0aW9uIG9mdGVuIGludHJvZHVjZXMgYXJ0aWZhY3RzIGR1ZSB0byBhIGRpZmZlcmVuY2UgaW4gbWlzc2luZyBwZXB0aWRlcyBhY3Jvc3Mgc2FtcGxlcyAKLSBNb3JlIGFkdmFuY2VkIG1ldGhvZHMgc2hvdWxkIGJlIGRldmVsb3BlZCBmb3Igbm9ybWFsaXppbmcgcHJvdGVvbWljcyBkYXRhCi0gSWYgdGhlcmUgYXJlIGRpZmZlcmVuY2VzIGluIHRoZSB3aWR0aCBvZiB0aGUgbWFyZ2luYWwgZGlzdHJpYnV0aW9ucyBvZiB0aGUgZGF0YSBhY3Jvc3Mgc2FtcGxlcy4gVGhleSBjYW4gYWxzbyBiZSBzdGFuZGFyZGl6ZWQgYnkgdXNpbmcgYSByb2J1c3QgZXN0aW1hdG9yIGZvciBsb2NhdGlvbiBhbmQgc2NhbGUsIGkuZS4gCiQkeV97aXB9Xlx0ZXh0e25vcm19ID0gXGZyYWN7eV97aXB9IC0gXG11X2l9e3NfaX0kJCAKCi0tLQoKIyMgU3VtbWFyaXphdGlvbiAKCjxpZnJhbWUgd2lkdGg9IjU2MCIgaGVpZ2h0PSIzMTUiCnNyYz0iaHR0cHM6Ly93d3cueW91dHViZS5jb20vZW1iZWQvTlVQSldQSmdRVWMiCmZyYW1lYm9yZGVyPSIwIgpzdHlsZT0iZGlzcGxheTogYmxvY2s7IG1hcmdpbjogYXV0bzsiCmFsbG93PSJhdXRvcGxheTsgZW5jcnlwdGVkLW1lZGlhIiBhbGxvd2Z1bGxzY3JlZW4+PC9pZnJhbWU+CgotIFdlIGlsbHVzdHJhdGUgc3VtbWFyaXphdGlvbiBpc3N1ZXMgdXNpbmcgYSBzdWJzZXQgb2YgdGhlIGNwdGFjIHN0dWR5IChMYWIgMiwgY29uZGl0aW9uIEEgYW5kIEUpIGZvciBhIHNwaWtlZCBwcm90ZWluIChVUFMgUDEyMDgxKS4KCjxkZXRhaWxzPjxzdW1tYXJ5PiBDbGljayB0byBzZWUgY29kZSB0byBtYWtlIHBsb3QgPC9zdW1tYXJ5PjxwPgpgYGB7ciBwbG90ID0gRkFMU0V9CnN1bW1hcnlQbG90IDwtIHBlW1sicGVwdGlkZU5vcm0iXV1bCiAgICByb3dEYXRhKHBlW1sicGVwdGlkZU5vcm0iXV0pJFByb3RlaW5zID09ICJQMTIwODF1cHN8U1lIQ19IVU1BTl9VUFMiLAogICAgY29sRGF0YShwZSkkbGFiPT0ibGFiMiImY29sRGF0YShwZSkkY29uZGl0aW9uICVpbiUgYygiQSIsIkUiKV0gJT4lCiAgYXNzYXkgJT4lCiAgYXMuZGF0YS5mcmFtZSAlPiUKICByb3duYW1lc190b19jb2x1bW4odmFyID0gInBlcHRpZGUiKSAlPiUKICBnYXRoZXIoc2FtcGxlLCBpbnRlbnNpdHksIC1wZXB0aWRlKSAlPiUgCiAgbXV0YXRlKGNvbmRpdGlvbiA9IGNvbERhdGEocGUpW3NhbXBsZSwiY29uZGl0aW9uIl0pICU+JQogIGdncGxvdChhZXMoeCA9IHBlcHRpZGUsIHkgPSBpbnRlbnNpdHksIGNvbG9yID0gc2FtcGxlLCBncm91cCA9IHNhbXBsZSwgbGFiZWwgPSBjb25kaXRpb24pLCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgZ2VvbV9saW5lKHNob3cubGVnZW5kID0gRkFMU0UpICsKICBnZW9tX3RleHQoc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgdmp1c3QgPSAwLjUsIGhqdXN0ID0gMSkpICsKICB4bGFiKCJQZXB0aWRlIikgKyAKICB5bGFiKCJJbnRlbnNpdHkgKGxvZzIpIikKYGBgCjwvcD48L2RldGFpbHM+CgpgYGB7cn0Kc3VtbWFyeVBsb3QKYGBgCgpXZSBvYnNlcnZlOiAgCgotIGludGVuc2l0aWVzIGZyb20gbXVsdGlwbGUgcGVwdGlkZXMgZm9yIGVhY2ggcHJvdGVpbiBpbiBhIHNhbXBsZQotIFN0cm9uZyBwZXB0aWRlIGVmZmVjdCAKLVVuYmFsYW5jZWQgcGVwdGlkZSBpZGVudGlmaWNhdGlvbgotIFBzZXVkby1yZXBsaWNhdGlvbjogcGVwdGlkZSBpbnRlbnNpdGllcyBmcm9tIGEgcGFydGljdWxhciBwcm90ZWluIGluIHRoZSBzYW1lIHNhbXBsZSBhcmUgY29ycmVsYXRlZCwgaS5lLiB0aGV5IG1vcmUgYWxpa2UgdGhhbiBwZXB0aWRlIGludGVuc2l0aWVzIGZyb20gYSBwYXJ0aWN1bGFyIHByb3RlaW4gYmV0d2VlbiBzYW1wbGVzLiAKCgokXHJpZ2h0YXJyb3ckIFN1bW1hcml6ZSBhbGwgcGVwdGlkZSBpbnRlbnNpdGllcyBmcm9tIHRoZSBzYW1lIHByb3RlaW4gaW4gYSBzYW1wbGUgaW50byBhIHNpbmdsZSBwcm90ZWluIGV4cHJlc3Npb24gdmFsdWUKCkNvbW1vbmx5IHVzZWQgbWV0aG9kcyBhcmUgCgotIE1lYW4gc3VtbWFyaXphdGlvbgokJAp5X3tpcH09XGJldGFfaV5cdGV4dHtzYW1wfSArIFxlcHNpbG9uX3tpcH0KJCQKCi0gTWVkaWFuIHN1bW1hcml6YXRpb24KLSBNYXhxdWFudCdzIG1heExGUSBzdW1tYXJpemF0aW9uIChpbiBwcm90ZWluIGdyb3VwcyBmaWxlKQotIE1vZGVsIGJhc2VkIHN1bW1hcml6YXRpb246IAokJAp5X3tpcH09XGJldGFfaV5cdGV4dHtzYW1wfSArIFxiZXRhX3BeXHRleHR7cGVwfSArIFxlcHNpbG9uX3tpcH0KJCQKCgo8ZGV0YWlscz48c3VtbWFyeT4gQ2xpY2sgdG8gc2VlIFItY29kZSB0byBhZ2dyZWdhdGUgdGhlIGRhdGEgPC9zdW1tYXJ5PjxwPgpXZSB1c2UgdGhlIHN0YW5kYXJkIHN1bWFyaXphdGlvbiBpbiBhZ2dyZWdhdGVGZWF0dXJlcywgd2hpY2ggaXMKcm9idXN0IG1vZGVsIGJhc2VkIHN1bW1hcml6YXRpb24uIAoKYGBge3Isd2FybmluZz1GQUxTRX0KcGUgPC0gYWdncmVnYXRlRmVhdHVyZXMocGUsCiAgICBpID0gInBlcHRpZGVOb3JtIiwgCiAgICBmY29sID0gIlByb3RlaW5zIiwgCiAgICBuYS5ybSA9IFRSVUUsCiAgICBuYW1lID0gInByb3RlaW4iKQpgYGAKCk90aGVyIHN1bW1hcml6YXRpb24gbWV0aG9kcyBjYW4gYmUgaW1wbGVtZW50ZWQgYnkgdXNpbmcgdGhlIGBmdW5gIGFyZ3VtZW50IGluIHRoZSBgYWdncmVnYXRlRmVhdHVyZXNgIGZ1bmN0aW9uLiAKCi0gYGZ1biA9IE1zQ29yZVV0aWxzOjptZWRpYW5Qb2xpc2goKWAgdG8gZml0cyBhbiBhZGRpdGl2ZSBtb2RlbCAodHdvIHdheSBkZWNvbXBvc2l0aW9uKSB1c2luZyBUdWtleSdzIG1lZGlhbiBwb2xpc2hfIHByb2NlZHVyZSB1c2luZyBzdGF0czo6bWVkcG9saXNoKCkKCi0gYGZ1biA9IE1zQ29yZVV0aWxzOjpyb2J1c3RTdW1tYXJ5KClgIHRvIGNhbGN1bGF0ZSBhIHJvYnVzdCBhZ2dyZWdhdGlvbiB1c2luZyBNQVNTOjpybG0oKSAoZGVmYXVsdCkKCi0gYGZ1biA9IGJhc2U6OmNvbE1lYW5zKClgIHRvIHVzZSB0aGUgbWVhbiBvZiBlYWNoIGNvbHVtbgoKLSBgZnVuID0gbWF0cml4U3RhdHM6OmNvbE1lZGlhbnMoKWAgdG8gdXNlIHRoZSBtZWRpYW4gb2YgZWFjaCBjb2x1bW4KCi0gYGZ1biA9IGJhc2U6OmNvbFN1bXMoKWAgdG8gdXNlIHRoZSBzdW0gb2YgZWFjaCBjb2x1bW4KCjwvcD48L2RldGFpbHM+CgotLS0KCiMgRXhlcmNpc2UKCjEuIFdlIHdpbGwgZXZhbHVhdGUgZGlmZmVyZW50IHN1bW1hcml6YXRpb24gbWV0aG9kcyAoTWF4cXVhbnQgbWF4TEZRLCBtZWRpYW4gYW5kIHJvYnVzdCBtb2RlbCBiYXNlZCkgaW4gdGhlIHR1dG9yaWFsIHNlc3Npb24gYmVmb3JlIGRpc2N1c3Npbmcgb24gdGhlaXIgYWR2YW50YWdlcy9kaXNhZHZhbnRhZ2VzLgoyLiBDYW4geW91IGFudGljaXBhdGUgb24gcG90ZW50aWFsIHByb2JsZW1zIHJlbGF0ZWQgdG8gdGhlIHN1bW1hcml6YXRpb24/CgotLS0KCiMgU29mdHdhcmUgJiBjb2RlCgotIE91ciBSL0Jpb2NvbmR1Y3RvciBwYWNrYWdlIFttc3Fyb2IyXShodHRwczovL3d3dy5iaW9jb25kdWN0b3Iub3JnL3BhY2thZ2VzL3JlbGVhc2UvYmlvYy9odG1sL21zcXJvYjIuaHRtbCkgY2FuIGJlIHVzZWQgaW4gUiBtYXJrZG93biBzY3JpcHRzIG9yIHdpdGggYSBHVUkvc2hpbnlBcHAgaW4gdGhlIFttc3Fyb2IyZ3VpXShodHRwczovL2dpdGh1Yi5jb20vc3RhdE9taWNzL21zcXJvYjJndWkpIHBhY2thZ2UuCgotIFRoZSBHVUkgaXMgaW50ZW5kZWQgYXMgYSBpbnRyb2R1Y3Rpb24gdG8gdGhlIGtleSBjb25jZXB0cyBvZiBwcm90ZW9taWNzIGRhdGEgYW5hbHlzaXMgZm9yIHVzZXJzIHdobyBoYXZlIG5vIGV4cGVyaWVuY2UgaW4gUi4gCgotIEhvd2V2ZXIsIGxlYXJuaW5nIGhvdyB0byBjb2RlIGRhdGEgYW5hbHlzZXMgaW4gUiBtYXJrZG93biBzY3JpcHRzIGlzIGtleSBmb3Igb3BlbiBlbiByZXByb2R1Y2libGUgc2NpZW5jZSBhbmQgZm9yIHJlcG9ydGluZyB5b3VyIHByb3Rlb21pY3MgZGF0YSBhbmFseXNlcyBhbmQgaW50ZXJwcmV0YXRpb24gaW4gYSByZXByb2R1Y2libGUgd2F5LiAKCgotIE1vcmUgaW5mb3JtYXRpb24gb24gb3VyIHRvb2xzIGNhbiBiZSBmb3VuZCBpbiBvdXIgcGFwZXJzIFtAZ29lbWlubmUyMDE2XSwgW0Bnb2VtaW5uZTIwMjBdIGFuZCBbQHN0aWNrZXIyMDIwXS4gUGxlYXNlIHJlZmVyIHRvIG91ciB3b3JrIHdoZW4gdXNpbmcgb3VyIHRvb2xzLiAKCgoKIyMgQ29kZSAKCjEuIERhdGEgaW5mcmFzdHJ1Y3R1cmUKPGlmcmFtZSB3aWR0aD0iNTYwIiBoZWlnaHQ9IjMxNSIKc3JjPSJodHRwczovL3d3dy55b3V0dWJlLmNvbS9lbWJlZC9OMHlJWjFZQjJhUSIKZnJhbWVib3JkZXI9IjAiCnN0eWxlPSJkaXNwbGF5OiBibG9jazsgbWFyZ2luOiBhdXRvOyIKYWxsb3c9ImF1dG9wbGF5OyBlbmNyeXB0ZWQtbWVkaWEiIGFsbG93ZnVsbHNjcmVlbj48L2lmcmFtZT4KCjIuIEltcG9ydCBwcm90ZW9taWNzIGRhdGEKCjxpZnJhbWUgd2lkdGg9IjU2MCIgaGVpZ2h0PSIzMTUiCnNyYz0iaHR0cHM6Ly93d3cueW91dHViZS5jb20vZW1iZWQvRFBIdHJHajhza2siCmZyYW1lYm9yZGVyPSIwIgpzdHlsZT0iZGlzcGxheTogYmxvY2s7IG1hcmdpbjogYXV0bzsiCmFsbG93PSJhdXRvcGxheTsgZW5jcnlwdGVkLW1lZGlhIiBhbGxvd2Z1bGxzY3JlZW4+PC9pZnJhbWU+CgozLiBQcmVwcm9jZXNzaW5nCgogICAgLSAgIExvZy10cmFuc2Zvcm1hdGlvbgo8aWZyYW1lIHdpZHRoPSI1NjAiIGhlaWdodD0iMzE1IgpzcmM9Imh0dHBzOi8vd3d3LnlvdXR1YmUuY29tL2VtYmVkL2F4RFQydEpOTHdNIgpmcmFtZWJvcmRlcj0iMCIKc3R5bGU9ImRpc3BsYXk6IGJsb2NrOyBtYXJnaW46IGF1dG87IgphbGxvdz0iYXV0b3BsYXk7IGVuY3J5cHRlZC1tZWRpYSIgYWxsb3dmdWxsc2NyZWVuPjwvaWZyYW1lPgoKICAgIC0gRmlsdGVyaW5nCjxpZnJhbWUgd2lkdGg9IjU2MCIgaGVpZ2h0PSIzMTUiCnNyYz0iaHR0cHM6Ly93d3cueW91dHViZS5jb20vZW1iZWQvY0l3QXhmSjVDR28iCmZyYW1lYm9yZGVyPSIwIgpzdHlsZT0iZGlzcGxheTogYmxvY2s7IG1hcmdpbjogYXV0bzsiCmFsbG93PSJhdXRvcGxheTsgZW5jcnlwdGVkLW1lZGlhIiBhbGxvd2Z1bGxzY3JlZW4+PC9pZnJhbWU+CgogICAgLSBOb3JtYWxpc2F0aW9uCjxpZnJhbWUgd2lkdGg9IjU2MCIgaGVpZ2h0PSIzMTUiCnNyYz0iaHR0cHM6Ly93d3cueW91dHViZS5jb20vZW1iZWQvOXFDSkVrZFNTaEkiCmZyYW1lYm9yZGVyPSIwIgpzdHlsZT0iZGlzcGxheTogYmxvY2s7IG1hcmdpbjogYXV0bzsiCmFsbG93PSJhdXRvcGxheTsgZW5jcnlwdGVkLW1lZGlhIiBhbGxvd2Z1bGxzY3JlZW4+PC9pZnJhbWU+CgogICAgLSBTdW1tYXJpemF0aW9uCjxpZnJhbWUgd2lkdGg9IjU2MCIgaGVpZ2h0PSIzMTUiCnNyYz0iaHR0cHM6Ly93d3cueW91dHViZS5jb20vZW1iZWQvZldxNHJNeG1KVFUiCmZyYW1lYm9yZGVyPSIwIgpzdHlsZT0iZGlzcGxheTogYmxvY2s7IG1hcmdpbjogYXV0bzsiCmFsbG93PSJhdXRvcGxheTsgZW5jcnlwdGVkLW1lZGlhIiBhbGxvd2Z1bGxzY3JlZW4+PC9pZnJhbWU+ICAgIAoKIyMgRGF0YSBhbmFseXNpcyB3aXRoIHRoZSBHVUkvc2hpbnlBcHAgbXNxcm9iMmd1aQoKPGlmcmFtZSB3aWR0aD0iNTYwIiBoZWlnaHQ9IjMxNSIKc3JjPSJodHRwczovL3d3dy55b3V0dWJlLmNvbS9lbWJlZC9GNWQwRS1VNHJPTSIKZnJhbWVib3JkZXI9IjAiCnN0eWxlPSJkaXNwbGF5OiBibG9jazsgbWFyZ2luOiBhdXRvOyIKYWxsb3c9ImF1dG9wbGF5OyBlbmNyeXB0ZWQtbWVkaWEiIGFsbG93ZnVsbHNjcmVlbj48L2lmcmFtZT4gICAKCiMgUmVmZXJlbmNlcwo=