require(tidyverse)
require(cowplot)
old = theme_set(theme_cowplot())

Goal

The goal of this analysis is to use qPCR to measure the gene induction time course after phosphate starvation in Saccharomyces cerevisiae in comparison with Candida glabrata. In particular, we would like to resolve a previous contradiction where oxidative stress response genes were found to be induced upon phosphate starvation in S. cerevisiae in one experiment but not in another. Here we repeat the time course experiment in S. cerevisiae and C. glabrata side by side to see if the induction of OSR genes upon phosphate starvation is species-specific.

Experimental Design

experimental design Preparation: Cells were grown to log phase in synthetic complete (SC) medium with replete phosphate; Sample C1 was collected from this pre-stress condition; Switch media: Log phase cultures were then subjected to parallel media exchange via spin/filter procedure: experimental cultures were transferred to phosphate-depleted SC medium (-Pi), while control cultures were transferred to fresh phosphate-replete SC medium to control for media switch effects. The parallel phosphate-replete culture (+Pi) was then sampled and used as a secondary control (C2). Following media exchange, a time course was performed with samples collected at 30 minutes (E1 for -Pi condition) and 60 minutes (E2 for -Pi condition); for the parallel +Pi culture, an experimental sample was only taken at 30 minutes post-stress induction. In a separate experiment for oxidative stress analysis, log phase cells grown in SC medium were transferred via spin/filter to H2O2-treated medium (1 mM for S. cerevisiae, and 10 mM for C. glabrata). A positive control sample was collected immediately post-transfer (C1 control), followed by experimental samples at 30 minutes (E1) and 60 minutes (E2) of H2O2 exposure. All samples underwent total RNA isolation, cDNA synthesis, and RT-qPCR analysis. Representative amplification curves show threshold determination for calculating Ct values, with reactions performed in duplicate (2x).

Data

The qPCR data file is a tab-delimited text file with the following columns: Well, Row, Col, Sample, Species, Task, Treatment, Timepoint, Replicate, Target, Cq, Amp Status

  1. Sample (e.g. A1, B1, etc.,no RT,NTC)
  2. Species (Sc or Cg)
  3. Task (e.g. unknown, NTC, NoRT)
  4. Treatment (e.g. Pi, H2O2)
  5. Timepoint (e.g. 0,30,60)
  6. Replicate (e.g. 1,2)
  7. Target (e.g. ACT1, CTA1, TRX2, PHO84)
  8. Cq (Ct value)
  9. Amp Status (e.g. OK, No Amp, etc.)

Read & Format data

dat <- read_csv("../input/20251010-OSR-qPCR-Ct-raw-formatted.csv",
                col_types = cols()) |>
  mutate(Ct = na_if(Cq, "Undetermined") |> as.numeric())

Check to make sure the NTC are negative

dat %>% filter(Task %in% c("NTC", "NoRT")) |> 
                 select(Well, Sample, Task, Target, Ct, `Amp Status`)

There was one NTC reaction for PHO84 that had extremely low Ct. Double check

EDA and QC

Overview of Ct values

dat %>%
  filter(Task  == "Unknown") %>%
  mutate(label = paste(Species, Treatment, Timepoint, sep = "_")) %>% 
  ggplot(aes(x = label, Ct)) + geom_point(aes(color = Replicate), shape=5) + 
  facet_wrap( ~Target ) +
  theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5, size = 10))

Looking at ACT1, we see that one sample, Cg_Pi_60m_b1, appears to have a problem (Ct value much higher than expected). We will examine this sample further

dat %>% filter(Sample == "Cg-Pi-60m-b1") %>% 
  select(Well, Sample, Task, Target, Ct, `Amp Status`)

This sample clearly failed. Will remove from further analyses

Also, we notice that ‘Cg-H2O2-30m-b2’ appears to be missing.

dat %>% filter(Sample == "Cg-H2O2-30m-b2") %>% 
  select(Well, Sample, Task, Target, Ct, `Amp Status`)

This sample failed as well. We will remove both failed samples from further analyses

filtered_dat <- dat %>% filter(!Sample %in% c("Cg-Pi-60m-b1", "Cg-H2O2-30m-b2"),
                               Task == "Unknown")

Check the experimental design and number of replicates per group after filtering

with(filtered_dat %>% mutate(Target = fct_recode(Target, CTT1 = "CTA1")),
     table(Species, paste(Treatment, Timepoint, sep = "_"), Target))
, , Target = ACT1

       
Species CTRL_0m H2O2_30m H2O2_60m Pi_30m Pi_60m
     Cg       3        3        6      6      3
     Sc       3        6        6      6      6

, , Target = CTT1

       
Species CTRL_0m H2O2_30m H2O2_60m Pi_30m Pi_60m
     Cg       3        3        6      6      3
     Sc       3        6        6      6      6

, , Target = PHO84

       
Species CTRL_0m H2O2_30m H2O2_60m Pi_30m Pi_60m
     Cg       3        3        6      6      3
     Sc       3        6        6      6      6

, , Target = TRX2-p1

       
Species CTRL_0m H2O2_30m H2O2_60m Pi_30m Pi_60m
     Cg       3        3        6      6      3
     Sc       3        6        6      6      6

, , Target = TRX2-p2

       
Species CTRL_0m H2O2_30m H2O2_60m Pi_30m Pi_60m
     Cg       0        3        6      6      3
     Sc       0        6        6      6      6
  1. TRX2-p2 was not run on the reference sample.
  2. Cg_H2O2_30m only has one replicate after filtering.
  3. Cg_Pi_60m only has one replicate after filtering.

ddCt analysis

Standard curve and efficiency calculation

To calculate efficiency, use linear regression \[ n_t = D_i n_0 E^{C_{T,i}} \]

We don’t have standard curves in this experiment. Skip

ddCt calculation

Set the reference gene and reference condition

ref.target <- "ACT1"
ref.treat <- "CTRL"
dilute <- 100 # all samples diluted to 100 fold in this experiment
# Mean and sd
# ---
# all samples are diluted to the same 100 fold, hence no need to back calculate here
# data1$Ct1 <- data1$Ct - log2(data1$Dilution/dilute)
# ---
average_Ct <- filtered_dat %>% 
  group_by(Species, Treatment, Timepoint, Replicate, Target) %>%
  summarize(Ct = Ct(Ct, na.rm=TRUE), sd = sd(Ct, na.rm=TRUE), .groups="drop")
Error in `summarize()`:
ℹ In argument: `Ct = Ct(Ct, na.rm = TRUE)`.
ℹ In group 1: `Species = "Cg"`, `Treatment = "CTRL"`, `Timepoint = "0m"`, `Replicate = "b1"`, `Target =
  "ACT1"`.
Caused by error in `Ct()`:
! could not find function "Ct"
Backtrace:
  1. ... %>% ...
  3. dplyr:::summarise.grouped_df(., Ct = Ct(Ct, na.rm = TRUE), sd = sd(Ct, na.rm = TRUE), .groups = "drop")
  4. dplyr:::summarise_cols(.data, dplyr_quosures(...), by, "summarise")
  6. dplyr:::map(quosures, summarise_eval_one, mask = mask)
  7. base::lapply(.x, .f, ...)
  8. dplyr (local) FUN(X[[i]], ...)
  9. mask$eval_all_summarise(quo)
 10. dplyr (local) eval()

Next, we group the data by {Species, Treatment, Timepoint, and Replicate}, and calculate ddCt relative to the reference target and then the reference sample.

dCt calculation

ddCt calculation.

Note that only one control sample was run and will be used as the reference sample for both biological replicates; also, while two sets of primers were used for TRX2, only one of them, p1, was tested on the reference sample. p2 will be dropped as a result.

Plot results

LS0tCnRpdGxlOiAicVBDUiBhbmFseXNpcyBvZiBQaSBzdGFydmF0aW9uIHRpbWUgY291cnNlIHRvIGRldGVybWluZSBPU1IgZ2VuZSBpbmR1Y3Rpb24iCmRhdGU6IDIwMjUtMTAtMjEsIHVwZGF0ZWQgb24gYHIgU3lzLkRhdGUoKWAKYXV0aG9yOiBCaW4gSGUKb3V0cHV0OiAKICBodG1sX25vdGVib29rOgogICAgdG9jOiB0cnVlCiAgICB0b2NfZGVwdGg6IDMKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgdGhlbWU6IHJlYWRhYmxlCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKLS0tCgpgYGB7cn0KcmVxdWlyZSh0aWR5dmVyc2UpCnJlcXVpcmUoY293cGxvdCkKYGBgCgpgYGB7cn0Kb2xkID0gdGhlbWVfc2V0KHRoZW1lX2Nvd3Bsb3QoKSkKYGBgCgojIyBHb2FsClRoZSBnb2FsIG9mIHRoaXMgYW5hbHlzaXMgaXMgdG8gdXNlIHFQQ1IgdG8gbWVhc3VyZSB0aGUgZ2VuZSBpbmR1Y3Rpb24gdGltZSBjb3Vyc2UgYWZ0ZXIgcGhvc3BoYXRlIHN0YXJ2YXRpb24gaW4gX1NhY2NoYXJvbXljZXMgY2VyZXZpc2lhZV8gaW4gY29tcGFyaXNvbiB3aXRoIF9DYW5kaWRhIGdsYWJyYXRhXy4gSW4gcGFydGljdWxhciwgd2Ugd291bGQgbGlrZSB0byByZXNvbHZlIGEgcHJldmlvdXMgY29udHJhZGljdGlvbiB3aGVyZSBveGlkYXRpdmUgc3RyZXNzIHJlc3BvbnNlIGdlbmVzIHdlcmUgZm91bmQgdG8gYmUgaW5kdWNlZCB1cG9uIHBob3NwaGF0ZSBzdGFydmF0aW9uIGluIF9TLiBjZXJldmlzaWFlXyBpbiBvbmUgZXhwZXJpbWVudCBidXQgbm90IGluIGFub3RoZXIuIEhlcmUgd2UgcmVwZWF0IHRoZSB0aW1lIGNvdXJzZSBleHBlcmltZW50IGluIF9TLiBjZXJldmlzaWFlXyBhbmQgX0MuIGdsYWJyYXRhXyBzaWRlIGJ5IHNpZGUgdG8gc2VlIGlmIHRoZSBpbmR1Y3Rpb24gb2YgT1NSIGdlbmVzIHVwb24gcGhvc3BoYXRlIHN0YXJ2YXRpb24gaXMgc3BlY2llcy1zcGVjaWZpYy4gCgojIyBFeHBlcmltZW50YWwgRGVzaWduCiFbZXhwZXJpbWVudGFsIGRlc2lnbl0oLi4vYXNzZXQvMjAyNTEwMTAtT1NSLXFSVC1QQ1ItZGVzaWduLnBuZykKKipQcmVwYXJhdGlvbioqOiBDZWxscyB3ZXJlIGdyb3duIHRvIGxvZyBwaGFzZSBpbiBzeW50aGV0aWMgY29tcGxldGUgKFNDKSBtZWRpdW0gd2l0aCByZXBsZXRlIHBob3NwaGF0ZTsgKipTYW1wbGUgQzEqKiB3YXMgY29sbGVjdGVkIGZyb20gdGhpcyBwcmUtc3RyZXNzIGNvbmRpdGlvbjsgKipTd2l0Y2ggbWVkaWEqKjogTG9nIHBoYXNlIGN1bHR1cmVzIHdlcmUgdGhlbiBzdWJqZWN0ZWQgdG8gcGFyYWxsZWwgbWVkaWEgZXhjaGFuZ2UgdmlhIHNwaW4vZmlsdGVyIHByb2NlZHVyZTogZXhwZXJpbWVudGFsIGN1bHR1cmVzIHdlcmUgdHJhbnNmZXJyZWQgdG8gcGhvc3BoYXRlLWRlcGxldGVkIFNDIG1lZGl1bSAoLVBpKSwgd2hpbGUgY29udHJvbCBjdWx0dXJlcyB3ZXJlIHRyYW5zZmVycmVkIHRvIGZyZXNoIHBob3NwaGF0ZS1yZXBsZXRlIFNDIG1lZGl1bSB0byBjb250cm9sIGZvciBtZWRpYSBzd2l0Y2ggZWZmZWN0cy4gVGhlIHBhcmFsbGVsIHBob3NwaGF0ZS1yZXBsZXRlIGN1bHR1cmUgKCtQaSkgd2FzIHRoZW4gc2FtcGxlZCBhbmQgdXNlZCBhcyBhIHNlY29uZGFyeSBjb250cm9sIChDMikuIEZvbGxvd2luZyBtZWRpYSBleGNoYW5nZSwgYSB0aW1lIGNvdXJzZSB3YXMgcGVyZm9ybWVkIHdpdGggc2FtcGxlcyBjb2xsZWN0ZWQgYXQgMzAgbWludXRlcyAoRTEgZm9yIC1QaSBjb25kaXRpb24pIGFuZCA2MCBtaW51dGVzIChFMiBmb3IgLVBpIGNvbmRpdGlvbik7IGZvciB0aGUgcGFyYWxsZWwgK1BpIGN1bHR1cmUsIGFuIGV4cGVyaW1lbnRhbCBzYW1wbGUgd2FzIG9ubHkgdGFrZW4gYXQgMzAgbWludXRlcyBwb3N0LXN0cmVzcyBpbmR1Y3Rpb24uIEluIGEgc2VwYXJhdGUgZXhwZXJpbWVudCBmb3Igb3hpZGF0aXZlIHN0cmVzcyBhbmFseXNpcywgbG9nIHBoYXNlIGNlbGxzIGdyb3duIGluIFNDIG1lZGl1bSB3ZXJlIHRyYW5zZmVycmVkIHZpYSBzcGluL2ZpbHRlciB0byBIMk8yLXRyZWF0ZWQgbWVkaXVtICgxIG1NIGZvciBfUy4gY2VyZXZpc2lhZV8sIGFuZCAxMCBtTSBmb3IgX0MuIGdsYWJyYXRhXykuIEEgcG9zaXRpdmUgY29udHJvbCBzYW1wbGUgd2FzIGNvbGxlY3RlZCBpbW1lZGlhdGVseSBwb3N0LXRyYW5zZmVyIChDMSBjb250cm9sKSwgZm9sbG93ZWQgYnkgZXhwZXJpbWVudGFsIHNhbXBsZXMgYXQgMzAgbWludXRlcyAoRTEpIGFuZCA2MCBtaW51dGVzIChFMikgb2YgSDJPMiBleHBvc3VyZS4gQWxsIHNhbXBsZXMgdW5kZXJ3ZW50IHRvdGFsIFJOQSBpc29sYXRpb24sIGNETkEgc3ludGhlc2lzLCBhbmQgUlQtcVBDUiBhbmFseXNpcy4gUmVwcmVzZW50YXRpdmUgYW1wbGlmaWNhdGlvbiBjdXJ2ZXMgc2hvdyB0aHJlc2hvbGQgZGV0ZXJtaW5hdGlvbiBmb3IgY2FsY3VsYXRpbmcgQ3QgdmFsdWVzLCB3aXRoIHJlYWN0aW9ucyBwZXJmb3JtZWQgaW4gZHVwbGljYXRlICgyeCkuCgojIyBEYXRhClRoZSBxUENSIGRhdGEgZmlsZSBpcyBhIHRhYi1kZWxpbWl0ZWQgdGV4dCBmaWxlIHdpdGggdGhlIGZvbGxvd2luZyBjb2x1bW5zOgpXZWxsLCBSb3csIENvbCwgU2FtcGxlLCBTcGVjaWVzLCBUYXNrLCBUcmVhdG1lbnQsIFRpbWVwb2ludCwgUmVwbGljYXRlLCBUYXJnZXQsIENxLCBBbXAgU3RhdHVzCgozLiBTYW1wbGUgICAgICAgKGUuZy4gQTEsIEIxLCBldGMuLG5vIFJULE5UQykKNC4gU3BlY2llcyAgICAgIChTYyBvciBDZykKNS4gVGFzayAgICAgICAgIChlLmcuIHVua25vd24sIE5UQywgTm9SVCkKNi4gVHJlYXRtZW50ICAgIChlLmcuIFBpLCBIMk8yKQo3LiBUaW1lcG9pbnQgICAgKGUuZy4gMCwzMCw2MCkKOC4gUmVwbGljYXRlICAgIChlLmcuIDEsMikKOS4gVGFyZ2V0ICAgICAgIChlLmcuIEFDVDEsIENUQTEsIFRSWDIsIFBITzg0KQoxMC4gQ3EgICAgICAgICAgKEN0IHZhbHVlKQoxMS4gQW1wIFN0YXR1cyAgKGUuZy4gT0ssIE5vIEFtcCwgZXRjLikKCiMjIFJlYWQgJiBGb3JtYXQgZGF0YQpgYGB7cn0KZGF0IDwtIHJlYWRfY3N2KCIuLi9pbnB1dC8yMDI1MTAxMC1PU1ItcVBDUi1DdC1yYXctZm9ybWF0dGVkLmNzdiIsCiAgICAgICAgICAgICAgICBjb2xfdHlwZXMgPSBjb2xzKCkpIHw+CiAgbXV0YXRlKEN0ID0gbmFfaWYoQ3EsICJVbmRldGVybWluZWQiKSB8PiBhcy5udW1lcmljKCkpCmBgYAoKQ2hlY2sgdG8gbWFrZSBzdXJlIHRoZSBOVEMgYXJlIG5lZ2F0aXZlCmBgYHtyfQpkYXQgJT4lIGZpbHRlcihUYXNrICVpbiUgYygiTlRDIiwgIk5vUlQiKSkgfD4gCiAgICAgICAgICAgICAgICAgc2VsZWN0KFdlbGwsIFNhbXBsZSwgVGFzaywgVGFyZ2V0LCBDdCwgYEFtcCBTdGF0dXNgKQpgYGAKPiBUaGVyZSB3YXMgb25lIE5UQyByZWFjdGlvbiBmb3IgUEhPODQgdGhhdCBoYWQgZXh0cmVtZWx5IGxvdyBDdC4gRG91YmxlIGNoZWNrCgojIyBFREEgYW5kIFFDCgojIyMgT3ZlcnZpZXcgb2YgQ3QgdmFsdWVzCmBgYHtyfQpkYXQgJT4lCiAgZmlsdGVyKFRhc2sgID09ICJVbmtub3duIikgJT4lCiAgbXV0YXRlKGxhYmVsID0gcGFzdGUoU3BlY2llcywgVHJlYXRtZW50LCBUaW1lcG9pbnQsIHNlcCA9ICJfIikpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBsYWJlbCwgQ3QpKSArIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gUmVwbGljYXRlKSwgc2hhcGU9NSkgKyAKICBmYWNldF93cmFwKCB+VGFyZ2V0ICkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIGhqdXN0ID0gMSwgdmp1c3QgPSAwLjUsIHNpemUgPSAxMCkpCmBgYAoKPiBMb29raW5nIGF0IEFDVDEsIHdlIHNlZSB0aGF0IG9uZSBzYW1wbGUsIENnX1BpXzYwbV9iMSwgYXBwZWFycyB0byBoYXZlIGEgcHJvYmxlbSAoQ3QgdmFsdWUgbXVjaCBoaWdoZXIgdGhhbiBleHBlY3RlZCkuIFdlIHdpbGwgZXhhbWluZSB0aGlzIHNhbXBsZSBmdXJ0aGVyCgpgYGB7cn0KZGF0ICU+JSBmaWx0ZXIoU2FtcGxlID09ICJDZy1QaS02MG0tYjEiKSAlPiUgCiAgc2VsZWN0KFdlbGwsIFNhbXBsZSwgVGFzaywgVGFyZ2V0LCBDdCwgYEFtcCBTdGF0dXNgKQpgYGAKPiBUaGlzIHNhbXBsZSBjbGVhcmx5IGZhaWxlZC4gV2lsbCByZW1vdmUgZnJvbSBmdXJ0aGVyIGFuYWx5c2VzCgpBbHNvLCB3ZSBub3RpY2UgdGhhdCAnQ2ctSDJPMi0zMG0tYjInIGFwcGVhcnMgdG8gYmUgbWlzc2luZy4KYGBge3J9CmRhdCAlPiUgZmlsdGVyKFNhbXBsZSA9PSAiQ2ctSDJPMi0zMG0tYjIiKSAlPiUgCiAgc2VsZWN0KFdlbGwsIFNhbXBsZSwgVGFzaywgVGFyZ2V0LCBDdCwgYEFtcCBTdGF0dXNgKQpgYGAKPiBUaGlzIHNhbXBsZSBmYWlsZWQgYXMgd2VsbC4gV2Ugd2lsbCByZW1vdmUgYm90aCBmYWlsZWQgc2FtcGxlcyBmcm9tIGZ1cnRoZXIgYW5hbHlzZXMKCmBgYHtyfQpmaWx0ZXJlZF9kYXQgPC0gZGF0ICU+JSBmaWx0ZXIoIVNhbXBsZSAlaW4lIGMoIkNnLVBpLTYwbS1iMSIsICJDZy1IMk8yLTMwbS1iMiIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVGFzayA9PSAiVW5rbm93biIpCmBgYAoKQ2hlY2sgdGhlIGV4cGVyaW1lbnRhbCBkZXNpZ24gYW5kIG51bWJlciBvZiByZXBsaWNhdGVzIHBlciBncm91cCBhZnRlciBmaWx0ZXJpbmcKYGBge3J9CndpdGgoZmlsdGVyZWRfZGF0ICU+JSBtdXRhdGUoVGFyZ2V0ID0gZmN0X3JlY29kZShUYXJnZXQsIENUVDEgPSAiQ1RBMSIpKSwKICAgICB0YWJsZShTcGVjaWVzLCBwYXN0ZShUcmVhdG1lbnQsIFRpbWVwb2ludCwgc2VwID0gIl8iKSwgVGFyZ2V0KSkKYGBgCgo+IDEuIFRSWDItcDIgd2FzIG5vdCBydW4gb24gdGhlIHJlZmVyZW5jZSBzYW1wbGUuCj4gMi4gQ2dfSDJPMl8zMG0gb25seSBoYXMgb25lIHJlcGxpY2F0ZSBhZnRlciBmaWx0ZXJpbmcuCj4gMy4gQ2dfUGlfNjBtIG9ubHkgaGFzIG9uZSByZXBsaWNhdGUgYWZ0ZXIgZmlsdGVyaW5nLgoKIyMgZGRDdCBhbmFseXNpcwojIyMgU3RhbmRhcmQgY3VydmUgYW5kIGVmZmljaWVuY3kgY2FsY3VsYXRpb24KVG8gY2FsY3VsYXRlIGVmZmljaWVuY3ksIHVzZSBsaW5lYXIgcmVncmVzc2lvbgokJCBuX3QgPSBEX2kgbl8wIEVee0Nfe1QsaX19ICQkIAoKV2UgZG9uJ3QgaGF2ZSBzdGFuZGFyZCBjdXJ2ZXMgaW4gdGhpcyBleHBlcmltZW50LiBTa2lwCmBgYHtyIGVjaG89RkFMU0UsIGluY2x1ZGU9RkFMU0V9CiMgU3RhbmRhcmQgY3VydmUKcCA8LSBnZ3Bsb3QoIHN1YnNldChkYXRhMSwgV2VsbC5UeXBlID09ICJzdGQiKSwgYWVzKGxvZzIoRGlsdXRpb24vZGlsdXRlKSwgQ3QpICkgCnAgKyBnZW9tX3BvaW50KCkgKyBnZW9tX3Ntb290aChhZXMoZ3JvdXA9MSksbWV0aG9kPSJsbSIpICsgZmFjZXRfZ3JpZCggUGxhdGUgfiBBc3NheSwgbGFiZWxsZXIgPSBsYWJlbF9ib3RoICkKCiMgQ2FsYyBwcmltZXIgYW1wbGlmaWNhdGlvbiBlZmZpY2llbmN5Cmxpbm1vZCA8LSBmdW5jdGlvbihkZikgewogIGlmKCBzdW0oIWlzLm5hKGRmJEN0KSkgPT0gMCApIHsgIyBpZiBubyBub24tTkEgZGF0YQogICAgcmV0dXJuKCBjKCJpbnRlcmNlcHQiPU5BLCAic2xvcGUiPU5BLCAicC52YWx1ZSI9TkEsICJyLnNxdWFyZWQiPU5BKSApCiAgfQogIGxtIDwtIGxtKCBsb2cyKERpbHV0aW9uL2RpbHV0ZSkgfiBDdCwgZGF0YT1kZiwgbmEuYWN0aW9uID0gIm5hLm9taXQiKQogIGludGVyY2VwdCA8LSBhcy5udW1lcmljKGNvZWYobG0pWzFdKQogIHNsb3BlIDwtIGFzLm51bWVyaWMoY29lZihsbSlbMl0pCiAgZWZmaWNpZW5jeSA8LSAyXihzbG9wZSkKICBzdW0gPC0gc3VtbWFyeShsbSkKICBwIDwtIGNvZWYoc3VtKVsyLDRdCiAgUjIgPC0gc3VtJHIuc3F1YXJlZAogIHJldHVybiggYygiZWZmaWNpZW5jeSI9ZWZmaWNpZW5jeSwgInNsb3BlIj1zbG9wZSwgInAudmFsdWUiPXAsICJyLnNxdWFyZWQiPVIyKSApCn0KZWZmIDwtIGRkcGx5KCBzdWJzZXQoZGF0YTEsV2VsbC5UeXBlID09ICJzdGQiKSwgLihQbGF0ZSwgQXNzYXkpLCBsaW5tb2QpCnByaW50KGVmZiwgZGlnaXRzPTMpCiNjYXQoIlRoZXJlIGFyZSBzb21lIHByb2JsZW1zIHdpdGggdGhlIDggZm9sZCBkaWx1dGlvbiBpbiBwbGF0ZSBDLiIpCmBgYAoKIyMjIGRkQ3QgY2FsY3VsYXRpb24KU2V0IHRoZSByZWZlcmVuY2UgZ2VuZSBhbmQgcmVmZXJlbmNlIGNvbmRpdGlvbgpgYGB7cn0KcmVmLnRhcmdldCA8LSAiQUNUMSIKcmVmLnRyZWF0IDwtICJDVFJMIgpkaWx1dGUgPC0gMTAwICMgYWxsIHNhbXBsZXMgZGlsdXRlZCB0byAxMDAgZm9sZCBpbiB0aGlzIGV4cGVyaW1lbnQKYGBgCgpgYGB7ciBmaWcud2lkdGg9OSwgZmlnLmhlaWdodD01LCB3YXJuaW5nPUZBTFNFfQojIE1lYW4gYW5kIHNkCiMgLS0tCiMgYWxsIHNhbXBsZXMgYXJlIGRpbHV0ZWQgdG8gdGhlIHNhbWUgMTAwIGZvbGQsIGhlbmNlIG5vIG5lZWQgdG8gYmFjayBjYWxjdWxhdGUgaGVyZQojIGRhdGExJEN0MSA8LSBkYXRhMSRDdCAtIGxvZzIoZGF0YTEkRGlsdXRpb24vZGlsdXRlKQojIC0tLQphdmVyYWdlX0N0IDwtIGZpbHRlcmVkX2RhdCAlPiUgCiAgZ3JvdXBfYnkoU3BlY2llcywgVHJlYXRtZW50LCBUaW1lcG9pbnQsIFJlcGxpY2F0ZSwgVGFyZ2V0KSAlPiUKICBzdW1tYXJpemUoQ3QgPSBtZWFuKEN0LCBuYS5ybT1UUlVFKSwgc2QgPSBzZChDdCwgbmEucm09VFJVRSksIC5ncm91cHM9ImRyb3AiKQpgYGAKCk5leHQsIHdlIGdyb3VwIHRoZSBkYXRhIGJ5IHtTcGVjaWVzLCBUcmVhdG1lbnQsIFRpbWVwb2ludCwgYW5kIFJlcGxpY2F0ZX0sIGFuZCBjYWxjdWxhdGUgZGRDdCByZWxhdGl2ZSB0byB0aGUgcmVmZXJlbmNlIHRhcmdldCBhbmQgdGhlbiB0aGUgcmVmZXJlbmNlIHNhbXBsZS4KCmRDdCBjYWxjdWxhdGlvbgpgYGB7cn0KZEN0IDwtIGF2ZXJhZ2VfQ3QgJT4lCiAgc2VsZWN0KC1zZCkgJT4lIAogIGdyb3VwX2J5KFNwZWNpZXMsIFRyZWF0bWVudCwgVGltZXBvaW50LCBSZXBsaWNhdGUpICU+JQogIG11dGF0ZShkQ3QgPSBDdCAtIEN0W1RhcmdldCA9PSByZWYudGFyZ2V0XSkgJT4lCiAgZmlsdGVyKFRhcmdldCAhPSByZWYudGFyZ2V0KSAlPiUKICB1bmdyb3VwKCkKYGBgCgpkZEN0IGNhbGN1bGF0aW9uLgoKPiBOb3RlIHRoYXQgb25seSBvbmUgY29udHJvbCBzYW1wbGUgd2FzIHJ1biBhbmQgd2lsbCBiZSB1c2VkIGFzIHRoZSByZWZlcmVuY2Ugc2FtcGxlCj4gZm9yIGJvdGggYmlvbG9naWNhbCByZXBsaWNhdGVzOyBhbHNvLCB3aGlsZSB0d28gc2V0cyBvZiBwcmltZXJzIHdlcmUgdXNlZCBmb3IgVFJYMiwKPiBvbmx5IG9uZSBvZiB0aGVtLCBwMSwgd2FzIHRlc3RlZCBvbiB0aGUgcmVmZXJlbmNlIHNhbXBsZS4gcDIgd2lsbCBiZSBkcm9wcGVkIGFzIGEgCj4gcmVzdWx0LgoKYGBge3J9CmRkQ3QgPC0gZEN0ICU+JQogIGZpbHRlcihUYXJnZXQgIT0gIlRSWDItcDIiKSAlPiUKICBncm91cF9ieShTcGVjaWVzLCBUYXJnZXQpICU+JQogIGFycmFuZ2UoU3BlY2llcywgVGFyZ2V0KSAlPiUKICBtdXRhdGUoZGRDdCA9IGRDdCAtIGRDdFtUcmVhdG1lbnQgPT0gcmVmLnRyZWF0XSkgJT4lCiAgZmlsdGVyKFRyZWF0bWVudCAhPSByZWYudHJlYXQpICU+JQogIHVuZ3JvdXAoKQpgYGAKCiMjIFBsb3QgcmVzdWx0cwpgYGB7cn0Kc3BlY2llcyA9IGMoIlNjIiA9ICJfUy4gY2VyZXZpc2lhZV8iLCAiQ2ciID0gIl9DLiBnbGFicmF0YV8iKQp0cmVhdCA9IGMoIlBpIiA9ICItUGkiLCAiSDJPMiIgPSAiSDxzdWI+Mjwvc3ViPk88c3ViPjI8L3N1Yj4iKQpkZEN0ICU+JSAKICBtdXRhdGUoVGFyZ2V0ID0gZmN0X3JlY29kZShUYXJnZXQsIFRSWDIgPSAiVFJYMi1wMSIpLAogICAgICAgICBUYXJnZXQgPSBmY3RfcmVsZXZlbChUYXJnZXQsICJDVEExIiwgIkNUVDEiLCAiVFJYMiIsICJQSE84NCIpLAogICAgICAgICBTcGVjaWVzID0gZmFjdG9yKFNwZWNpZXMsIGxldmVscyA9IG5hbWVzKHNwZWNpZXMpLCBsYWJlbHMgPSBzcGVjaWVzKSwKICAgICAgICAgVHJlYXRtZW50ID0gZmFjdG9yKFRyZWF0bWVudCwgbGV2ZWxzID0gbmFtZXModHJlYXQpLCBsYWJlbHMgPSB0cmVhdCkKICAgICAgICAgKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBUYXJnZXQsIHkgPSAtZGRDdCwgZ3JvdXAgPSBSZXBsaWNhdGUpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJzdW1tYXJ5IiwgZnVuID0gIm1lYW4iLCB3aWR0aCA9IDAuNDUsIAogICAgICAgICAgIGZpbGwgPSAiZ3JleTUwIiwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSguNSkpICsKICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IFJlcGxpY2F0ZSksIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoLjUpKSArIAogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJvcmFuZ2UiLCAic3RlZWxibHVlMyIpKSArCiAgZmFjZXRfZ3JpZChUcmVhdG1lbnQgfiBTcGVjaWVzLCBzY2FsZXMgPSAiZnJlZV94IikgKwogIHRoZW1lX2J3KGJhc2Vfc2l6ZT0xNCkgKwogIHRoZW1lKAogICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X21hcmtkb3duKHNpemUgPSByZWwoMC45KSkKICApCnAgKyB4bGFiKCJUaW1lIGFmdGVyIHN0YXJ2YXRpb24gKG1pbikiKSArIHlsYWIoICJmb2xkIGluZHVjdGlvbiIgKSArIGxhYnMoIHRpdGxlPSJGb2xkIGluZHVjdGlvbiByZWxhdGl2ZSB0byBBTEc5IGFuZCBwcmUtc3RyZXNzIikKCmBgYAo=