Configuration

Volume

{
    "AvailabilityZone": "us-east-1a", 
    "Attachments": [
        {
            "AttachTime": "2018-02-07T15:13:07.000Z", 
            "InstanceId": "i-09a31c8d356966248", 
            "VolumeId": "vol-0d8d10c68176aa97b", 
            "State": "attached", 
            "DeleteOnTermination": false, 
            "Device": "/dev/sdf"
        }
    ], 
    "Encrypted": false, 
    "VolumeType": "gp2", 
    "VolumeId": "vol-0d8d10c68176aa97b", 
    "State": "in-use", 
    "Iops": 900, 
    "SnapshotId": "", 
    "CreateTime": "2018-01-19T20:14:49.325Z", 
    "Size": 300
}

ec2 instance

{
  "IamFleetRole": "arn:aws:iam::385009899373:role/aws-ec2-spot-fleet-tagging-role",
  "AllocationStrategy": "lowestPrice",
  "TargetCapacity": 1,
  "SpotPrice": "0.6",
  "ValidFrom": "2018-01-15T18:27:00Z",
  "ValidUntil": "2019-01-15T18:27:00Z",
  "TerminateInstancesWithExpiration": true,
  "LaunchSpecifications": [
    {
      "ImageId": "ami-3480df4e",
      "InstanceType": "c4.4xlarge",
      "SubnetId": "subnet-d2d5c7a4",
      "KeyName": "CellProfiler",
      "SpotPrice": "0.5",
      "IamInstanceProfile": {
        "Arn": "arn:aws:iam::385009899373:instance-profile/s3-imaging-platform-role"
      },
      "BlockDeviceMappings": [
        {
          "DeviceName": "/dev/sda1",
          "Ebs": {
            "DeleteOnTermination": true,
            "VolumeType": "gp2",
            "VolumeSize": 60,
            "SnapshotId": "snap-0d61c49c2c8ecee7a"
          }
        }
      ],
      "SecurityGroups": [
        {
          "GroupId": "sg-2a88ab51"
        },
        {
          "GroupId": "sg-74b99a0f"
        }
      ],
      "TagSpecifications": [
        {
          "ResourceType": "instance",
          "Tags": [
            {
              "Key": "Name",
              "Value": "Shantanu-cytotools"
            }
          ]
        }
      ]
    }
  ],
  "Type": "request"
}

Pipeline

https://github.com/broadinstitute/imaging-platform-pipelines/blob/master/bbbc021_mcf7_20x_imagexpress/analysis.cppipe Processing was grouped by Metadata_Plate, Metadata_Well. 632 groups in total

Software

Setup

  • All images were copied to the 300 Gb EBS volume and processes, per well, using GNU parallel, across 16 cores.

Timing

time   parallel   --no-run-if-empty   --eta   --results ../../log/${BATCH_ID}/analysis/{/.}   --joblog ../../log/${BATCH_ID}/analysis.log   --keep-order   -a ../../scratch/${BATCH_ID}/cp_docker_commands_analysis.txt
real    317m42.417s
user    0m42.691s
sys     1m21.371s

See data/cp-221-analysis.log for details


parallel mkdir basename {1} ::: find . -name "Image.csv"

parallel dirname {} ::: `find . -name "Image.csv"` > /tmp/dirs

cd /tmp/

parallel mkdir -p {} :::: dirs

parallel "csvcut -c Metadata_Plate,Metadata_Well,Metadata_Site,Count_Cells,ExecutionTime_01LoadData,ExecutionTime_02CorrectIlluminationApply,ExecutionTime_03IdentifyPrimaryObjects,ExecutionTime_04IdentifySecondaryObjects,ExecutionTime_05IdentifyTertiaryObjects,ExecutionTime_06MeasureObjectSizeShape,ExecutionTime_07MeasureObjectIntensity,ExecutionTime_08MeasureObjectIntensity,ExecutionTime_09MeasureObjectIntensity,ExecutionTime_10MeasureObjectNeighbors,ExecutionTime_11MeasureObjectNeighbors,ExecutionTime_12MeasureObjectNeighbors,ExecutionTime_13MeasureObjectNeighbors,ExecutionTime_14MeasureTexture {} > /tmp/{}" ::: `find . -name "Image.csv"`

csvstack `find /tmp/ljosa_2013/ -name "Image.csv"` > time.csv
library(magrittr)
library(stringr)
library(tidyverse)
library(corrplot)
df <- read_csv("data/cp-221-time.csv") %>% 
  select(-matches("Metadata_"))
names(df) <- str_replace_all(names(df), "ExecutionTime_", "")
for (i in 1:5) {
  nonmax <- 
    setdiff(seq(nrow(df)), 
            df %>% 
              summarize_all(funs(which.max)) %>% 
              select(-Count_Cells) %>% 
              gather(k, v) %>% 
              extract2("v"))
  
  df <- df[nonmax, ]
}
long_module <- 
  tribble(~module, ~is_long,
          "13MeasureObjectNeighbors", TRUE,
          "06MeasureObjectSizeShape", TRUE)
df2 <- 
  df %>% 
  gather(module, time, -Count_Cells)  
  
df2 %<>% left_join(long_module)
Joining, by = "module"
df2 %<>% mutate(is_long = ifelse(is.na(is_long), FALSE, TRUE))
p <- 
df2 %>%  
  ggplot(aes(module, time)) + geom_boxplot() + facet_wrap(~is_long, scale = "free_x", nrow = 2) + 
  coord_flip()
p 
ggsave("timepermodule.pdf", width = 6, height = 6)

p <- 
df2 %>% 
  ggplot(aes(Count_Cells, time)) + geom_hex() + facet_wrap(~module, scales = "free") 
p
ggsave("scatter.pdf", width = 9, height = 8)

pdf("cordf.pdf", width = 10, height = 10)
corrplot(cor(df), method = "number", order = "hclust")
dev.off()
null device 
          1 
pdf("cordf-ellipse.pdf", width = 10, height = 10)
corrplot(cor(df), method = "ellipse", order = "hclust")
dev.off()
null device 
          1 
corrplot(cor(df), method = "ellipse", order = "hclust")

df1 <- read_csv("data/cp-221-time.csv") 
df1 %<>% mutate(ExecutionTime = ExecutionTime_01LoadData+ExecutionTime_02CorrectIlluminationApply+ExecutionTime_03IdentifyPrimaryObjects+ExecutionTime_04IdentifySecondaryObjects+ExecutionTime_05IdentifyTertiaryObjects+ExecutionTime_06MeasureObjectSizeShape+ExecutionTime_07MeasureObjectIntensity+ExecutionTime_08MeasureObjectIntensity+ExecutionTime_09MeasureObjectIntensity+ExecutionTime_10MeasureObjectNeighbors+ExecutionTime_11MeasureObjectNeighbors+ExecutionTime_12MeasureObjectNeighbors+ExecutionTime_13MeasureObjectNeighbors+ExecutionTime_14MeasureTexture) %>%
  group_by(Metadata_Plate, Metadata_Well) %>%
  summarise(ExecutionTime = sum(ExecutionTime)) %>% ungroup()
df2 <- read_tsv("data/cp-221-analysis.log") 
df2 %<>% rowwise() %>% mutate(pws = Command %>% str_split("/status_dir/") %>% extract2(1) %>% extract2(2) %>% str_split("\\.") %>% extract2(1) %>% extract2(1)) %>% ungroup() %>% separate(pws, into = c("Metadata_Plate", "Metadata_Well"), sep = "-") %>% select(Metadata_Plate, Metadata_Well, JobRuntime)
df <- inner_join(df1, df2)
corval <- with(df, cor(ExecutionTime, JobRuntime))
ggplot(df, aes(ExecutionTime, JobRuntime)) + 
  geom_point() + 
  geom_abline(slope = 1, intercept = 0) + 
  xlim(0, 900) + 
  ylim(0, 900) +
  coord_equal() +
  ggtitle(paste0("cor = ", corval))

m <- lm(data = df, formula = JobRuntime ~ ExecutionTime)
summary(m)

Call:
lm(formula = JobRuntime ~ ExecutionTime, data = df)

Residuals:
    Min      1Q  Median      3Q     Max 
-59.597  -5.055   0.372   6.346  36.146 

Coefficients:
               Estimate Std. Error t value Pr(>|t|)    
(Intercept)   1.889e+02  1.606e+00   117.6   <2e-16 ***
ExecutionTime 1.163e+00  6.199e-03   187.6   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 10.8 on 630 degrees of freedom
Multiple R-squared:  0.9824,    Adjusted R-squared:  0.9824 
F-statistic: 3.521e+04 on 1 and 630 DF,  p-value: < 2.2e-16
plot(m)

LS0tCnRpdGxlOiAiQ2VsbFByb2ZpbGVyIHRpbWluZ3Mgb24gQkJCQzAyMSIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyBDb25maWd1cmF0aW9uCgojIyBWb2x1bWUKCmBgYAp7CiAgICAiQXZhaWxhYmlsaXR5Wm9uZSI6ICJ1cy1lYXN0LTFhIiwgCiAgICAiQXR0YWNobWVudHMiOiBbCiAgICAgICAgewogICAgICAgICAgICAiQXR0YWNoVGltZSI6ICIyMDE4LTAyLTA3VDE1OjEzOjA3LjAwMFoiLCAKICAgICAgICAgICAgIkluc3RhbmNlSWQiOiAiaS0wOWEzMWM4ZDM1Njk2NjI0OCIsIAogICAgICAgICAgICAiVm9sdW1lSWQiOiAidm9sLTBkOGQxMGM2ODE3NmFhOTdiIiwgCiAgICAgICAgICAgICJTdGF0ZSI6ICJhdHRhY2hlZCIsIAogICAgICAgICAgICAiRGVsZXRlT25UZXJtaW5hdGlvbiI6IGZhbHNlLCAKICAgICAgICAgICAgIkRldmljZSI6ICIvZGV2L3NkZiIKICAgICAgICB9CiAgICBdLCAKICAgICJFbmNyeXB0ZWQiOiBmYWxzZSwgCiAgICAiVm9sdW1lVHlwZSI6ICJncDIiLCAKICAgICJWb2x1bWVJZCI6ICJ2b2wtMGQ4ZDEwYzY4MTc2YWE5N2IiLCAKICAgICJTdGF0ZSI6ICJpbi11c2UiLCAKICAgICJJb3BzIjogOTAwLCAKICAgICJTbmFwc2hvdElkIjogIiIsIAogICAgIkNyZWF0ZVRpbWUiOiAiMjAxOC0wMS0xOVQyMDoxNDo0OS4zMjVaIiwgCiAgICAiU2l6ZSI6IDMwMAp9CmBgYAoKIyMgZWMyIGluc3RhbmNlCmBgYAp7CiAgIklhbUZsZWV0Um9sZSI6ICJhcm46YXdzOmlhbTo6Mzg1MDA5ODk5MzczOnJvbGUvYXdzLWVjMi1zcG90LWZsZWV0LXRhZ2dpbmctcm9sZSIsCiAgIkFsbG9jYXRpb25TdHJhdGVneSI6ICJsb3dlc3RQcmljZSIsCiAgIlRhcmdldENhcGFjaXR5IjogMSwKICAiU3BvdFByaWNlIjogIjAuNiIsCiAgIlZhbGlkRnJvbSI6ICIyMDE4LTAxLTE1VDE4OjI3OjAwWiIsCiAgIlZhbGlkVW50aWwiOiAiMjAxOS0wMS0xNVQxODoyNzowMFoiLAogICJUZXJtaW5hdGVJbnN0YW5jZXNXaXRoRXhwaXJhdGlvbiI6IHRydWUsCiAgIkxhdW5jaFNwZWNpZmljYXRpb25zIjogWwogICAgewogICAgICAiSW1hZ2VJZCI6ICJhbWktMzQ4MGRmNGUiLAogICAgICAiSW5zdGFuY2VUeXBlIjogImM0LjR4bGFyZ2UiLAogICAgICAiU3VibmV0SWQiOiAic3VibmV0LWQyZDVjN2E0IiwKICAgICAgIktleU5hbWUiOiAiQ2VsbFByb2ZpbGVyIiwKICAgICAgIlNwb3RQcmljZSI6ICIwLjUiLAogICAgICAiSWFtSW5zdGFuY2VQcm9maWxlIjogewogICAgICAgICJBcm4iOiAiYXJuOmF3czppYW06OjM4NTAwOTg5OTM3MzppbnN0YW5jZS1wcm9maWxlL3MzLWltYWdpbmctcGxhdGZvcm0tcm9sZSIKICAgICAgfSwKICAgICAgIkJsb2NrRGV2aWNlTWFwcGluZ3MiOiBbCiAgICAgICAgewogICAgICAgICAgIkRldmljZU5hbWUiOiAiL2Rldi9zZGExIiwKICAgICAgICAgICJFYnMiOiB7CiAgICAgICAgICAgICJEZWxldGVPblRlcm1pbmF0aW9uIjogdHJ1ZSwKICAgICAgICAgICAgIlZvbHVtZVR5cGUiOiAiZ3AyIiwKICAgICAgICAgICAgIlZvbHVtZVNpemUiOiA2MCwKICAgICAgICAgICAgIlNuYXBzaG90SWQiOiAic25hcC0wZDYxYzQ5YzJjOGVjZWU3YSIKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIF0sCiAgICAgICJTZWN1cml0eUdyb3VwcyI6IFsKICAgICAgICB7CiAgICAgICAgICAiR3JvdXBJZCI6ICJzZy0yYTg4YWI1MSIKICAgICAgICB9LAogICAgICAgIHsKICAgICAgICAgICJHcm91cElkIjogInNnLTc0Yjk5YTBmIgogICAgICAgIH0KICAgICAgXSwKICAgICAgIlRhZ1NwZWNpZmljYXRpb25zIjogWwogICAgICAgIHsKICAgICAgICAgICJSZXNvdXJjZVR5cGUiOiAiaW5zdGFuY2UiLAogICAgICAgICAgIlRhZ3MiOiBbCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAiS2V5IjogIk5hbWUiLAogICAgICAgICAgICAgICJWYWx1ZSI6ICJTaGFudGFudS1jeXRvdG9vbHMiCiAgICAgICAgICAgIH0KICAgICAgICAgIF0KICAgICAgICB9CiAgICAgIF0KICAgIH0KICBdLAogICJUeXBlIjogInJlcXVlc3QiCn0KYGBgCgojIyBQaXBlbGluZQpodHRwczovL2dpdGh1Yi5jb20vYnJvYWRpbnN0aXR1dGUvaW1hZ2luZy1wbGF0Zm9ybS1waXBlbGluZXMvYmxvYi9tYXN0ZXIvYmJiYzAyMV9tY2Y3XzIweF9pbWFnZXhwcmVzcy9hbmFseXNpcy5jcHBpcGUKUHJvY2Vzc2luZyB3YXMgZ3JvdXBlZCBieSBNZXRhZGF0YV9QbGF0ZSwgTWV0YWRhdGFfV2VsbC4gNjMyIGdyb3VwcyBpbiB0b3RhbAoKIyMgU29mdHdhcmUKLSBkb2NrZXIgaW1hZ2Ugb2YgQ2VsbFByb2ZpbGVyIDIuMi4xIHNobnRudS9jZWxscHJvZmlsZXI6Mi4yLjEgaHR0cHM6Ly9odWIuZG9ja2VyLmNvbS9yL3NobnRudS9jZWxscHJvZmlsZXIvdGFncy8KLSBHTlUgcGFyYWxsZWwgdjIwMTgwMTIyCgojIyBTZXR1cAotIEFsbCBpbWFnZXMgd2VyZSBjb3BpZWQgdG8gdGhlIDMwMCBHYiBFQlMgdm9sdW1lIGFuZCBwcm9jZXNzZXMsIHBlciB3ZWxsLCB1c2luZyBHTlUgcGFyYWxsZWwsIGFjcm9zcyAxNiBjb3Jlcy4KCiMjIFRpbWluZwpgYGAKdGltZSAgIHBhcmFsbGVsICAgLS1uby1ydW4taWYtZW1wdHkgICAtLWV0YSAgIC0tcmVzdWx0cyAuLi8uLi9sb2cvJHtCQVRDSF9JRH0vYW5hbHlzaXMvey8ufSAgIC0tam9ibG9nIC4uLy4uL2xvZy8ke0JBVENIX0lEfS9hbmFseXNpcy5sb2cgICAtLWtlZXAtb3JkZXIgICAtYSAuLi8uLi9zY3JhdGNoLyR7QkFUQ0hfSUR9L2NwX2RvY2tlcl9jb21tYW5kc19hbmFseXNpcy50eHQKCmBgYAoKYGBgCnJlYWwgICAgMzE3bTQyLjQxN3MKdXNlciAgICAwbTQyLjY5MXMKc3lzICAgICAxbTIxLjM3MXMKYGBgCgpTZWUgYGRhdGEvY3AtMjIxLWFuYWx5c2lzLmxvZ2AgZm9yIGRldGFpbHMKCgpgYGAKCnBhcmFsbGVsIG1rZGlyIGJhc2VuYW1lIHsxfSA6OjogZmluZCAuIC1uYW1lICJJbWFnZS5jc3YiCgpwYXJhbGxlbCBkaXJuYW1lIHt9IDo6OiBgZmluZCAuIC1uYW1lICJJbWFnZS5jc3YiYCA+IC90bXAvZGlycwoKY2QgL3RtcC8KCnBhcmFsbGVsIG1rZGlyIC1wIHt9IDo6OjogZGlycwoKcGFyYWxsZWwgImNzdmN1dCAtYyBNZXRhZGF0YV9QbGF0ZSxNZXRhZGF0YV9XZWxsLE1ldGFkYXRhX1NpdGUsQ291bnRfQ2VsbHMsRXhlY3V0aW9uVGltZV8wMUxvYWREYXRhLEV4ZWN1dGlvblRpbWVfMDJDb3JyZWN0SWxsdW1pbmF0aW9uQXBwbHksRXhlY3V0aW9uVGltZV8wM0lkZW50aWZ5UHJpbWFyeU9iamVjdHMsRXhlY3V0aW9uVGltZV8wNElkZW50aWZ5U2Vjb25kYXJ5T2JqZWN0cyxFeGVjdXRpb25UaW1lXzA1SWRlbnRpZnlUZXJ0aWFyeU9iamVjdHMsRXhlY3V0aW9uVGltZV8wNk1lYXN1cmVPYmplY3RTaXplU2hhcGUsRXhlY3V0aW9uVGltZV8wN01lYXN1cmVPYmplY3RJbnRlbnNpdHksRXhlY3V0aW9uVGltZV8wOE1lYXN1cmVPYmplY3RJbnRlbnNpdHksRXhlY3V0aW9uVGltZV8wOU1lYXN1cmVPYmplY3RJbnRlbnNpdHksRXhlY3V0aW9uVGltZV8xME1lYXN1cmVPYmplY3ROZWlnaGJvcnMsRXhlY3V0aW9uVGltZV8xMU1lYXN1cmVPYmplY3ROZWlnaGJvcnMsRXhlY3V0aW9uVGltZV8xMk1lYXN1cmVPYmplY3ROZWlnaGJvcnMsRXhlY3V0aW9uVGltZV8xM01lYXN1cmVPYmplY3ROZWlnaGJvcnMsRXhlY3V0aW9uVGltZV8xNE1lYXN1cmVUZXh0dXJlIHt9ID4gL3RtcC97fSIgOjo6IGBmaW5kIC4gLW5hbWUgIkltYWdlLmNzdiJgCgpjc3ZzdGFjayBgZmluZCAvdG1wL2xqb3NhXzIwMTMvIC1uYW1lICJJbWFnZS5jc3YiYCA+IHRpbWUuY3N2CgpgYGAKCmBgYHtyIG1lc3NhZ2U9RkFMU0V9CmxpYnJhcnkobWFncml0dHIpCmxpYnJhcnkoc3RyaW5ncikKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoY29ycnBsb3QpCmBgYAoKCmBgYHtyIG1lc3NhZ2U9RkFMU0V9CmRmIDwtIHJlYWRfY3N2KCJkYXRhL2NwLTIyMS10aW1lLmNzdiIpICU+JSAKICBzZWxlY3QoLW1hdGNoZXMoIk1ldGFkYXRhXyIpKQoKbmFtZXMoZGYpIDwtIHN0cl9yZXBsYWNlX2FsbChuYW1lcyhkZiksICJFeGVjdXRpb25UaW1lXyIsICIiKQoKZm9yIChpIGluIDE6NSkgewogIG5vbm1heCA8LSAKICAgIHNldGRpZmYoc2VxKG5yb3coZGYpKSwgCiAgICAgICAgICAgIGRmICU+JSAKICAgICAgICAgICAgICBzdW1tYXJpemVfYWxsKGZ1bnMod2hpY2gubWF4KSkgJT4lIAogICAgICAgICAgICAgIHNlbGVjdCgtQ291bnRfQ2VsbHMpICU+JSAKICAgICAgICAgICAgICBnYXRoZXIoaywgdikgJT4lIAogICAgICAgICAgICAgIGV4dHJhY3QyKCJ2IikpCiAgCiAgZGYgPC0gZGZbbm9ubWF4LCBdCn0KCmBgYAoKCmBgYHtyfQoKbG9uZ19tb2R1bGUgPC0gCiAgdHJpYmJsZSh+bW9kdWxlLCB+aXNfbG9uZywKICAgICAgICAgICIxM01lYXN1cmVPYmplY3ROZWlnaGJvcnMiLCBUUlVFLAogICAgICAgICAgIjA2TWVhc3VyZU9iamVjdFNpemVTaGFwZSIsIFRSVUUpCgpkZjIgPC0gCiAgZGYgJT4lIAogIGdhdGhlcihtb2R1bGUsIHRpbWUsIC1Db3VudF9DZWxscykgIAogIApkZjIgJTw+JSBsZWZ0X2pvaW4obG9uZ19tb2R1bGUpCgpkZjIgJTw+JSBtdXRhdGUoaXNfbG9uZyA9IGlmZWxzZShpcy5uYShpc19sb25nKSwgRkFMU0UsIFRSVUUpKQoKcCA8LSAKZGYyICU+JSAgCiAgZ2dwbG90KGFlcyhtb2R1bGUsIHRpbWUpKSArIGdlb21fYm94cGxvdCgpICsgZmFjZXRfd3JhcCh+aXNfbG9uZywgc2NhbGUgPSAiZnJlZV94IiwgbnJvdyA9IDIpICsgCiAgY29vcmRfZmxpcCgpCgpwIAoKZ2dzYXZlKCJ0aW1lcGVybW9kdWxlLnBkZiIsIHdpZHRoID0gNiwgaGVpZ2h0ID0gNikKCmBgYAoKYGBge3J9CnAgPC0gCmRmMiAlPiUgCiAgZ2dwbG90KGFlcyhDb3VudF9DZWxscywgdGltZSkpICsgZ2VvbV9oZXgoKSArIGZhY2V0X3dyYXAofm1vZHVsZSwgc2NhbGVzID0gImZyZWUiKSAKcApnZ3NhdmUoInNjYXR0ZXIucGRmIiwgd2lkdGggPSA5LCBoZWlnaHQgPSA4KQpgYGAKCgpgYGB7cn0KcGRmKCJjb3JkZi5wZGYiLCB3aWR0aCA9IDEwLCBoZWlnaHQgPSAxMCkKY29ycnBsb3QoY29yKGRmKSwgbWV0aG9kID0gIm51bWJlciIsIG9yZGVyID0gImhjbHVzdCIpCmRldi5vZmYoKQpwZGYoImNvcmRmLWVsbGlwc2UucGRmIiwgd2lkdGggPSAxMCwgaGVpZ2h0ID0gMTApCmNvcnJwbG90KGNvcihkZiksIG1ldGhvZCA9ICJlbGxpcHNlIiwgb3JkZXIgPSAiaGNsdXN0IikKZGV2Lm9mZigpCmNvcnJwbG90KGNvcihkZiksIG1ldGhvZCA9ICJlbGxpcHNlIiwgb3JkZXIgPSAiaGNsdXN0IikKCgpgYGAKCmBgYHtyIG1lc3NhZ2U9RkFMU0V9CmRmMSA8LSByZWFkX2NzdigiZGF0YS9jcC0yMjEtdGltZS5jc3YiKSAKCmRmMSAlPD4lIG11dGF0ZShFeGVjdXRpb25UaW1lID0gRXhlY3V0aW9uVGltZV8wMUxvYWREYXRhK0V4ZWN1dGlvblRpbWVfMDJDb3JyZWN0SWxsdW1pbmF0aW9uQXBwbHkrRXhlY3V0aW9uVGltZV8wM0lkZW50aWZ5UHJpbWFyeU9iamVjdHMrRXhlY3V0aW9uVGltZV8wNElkZW50aWZ5U2Vjb25kYXJ5T2JqZWN0cytFeGVjdXRpb25UaW1lXzA1SWRlbnRpZnlUZXJ0aWFyeU9iamVjdHMrRXhlY3V0aW9uVGltZV8wNk1lYXN1cmVPYmplY3RTaXplU2hhcGUrRXhlY3V0aW9uVGltZV8wN01lYXN1cmVPYmplY3RJbnRlbnNpdHkrRXhlY3V0aW9uVGltZV8wOE1lYXN1cmVPYmplY3RJbnRlbnNpdHkrRXhlY3V0aW9uVGltZV8wOU1lYXN1cmVPYmplY3RJbnRlbnNpdHkrRXhlY3V0aW9uVGltZV8xME1lYXN1cmVPYmplY3ROZWlnaGJvcnMrRXhlY3V0aW9uVGltZV8xMU1lYXN1cmVPYmplY3ROZWlnaGJvcnMrRXhlY3V0aW9uVGltZV8xMk1lYXN1cmVPYmplY3ROZWlnaGJvcnMrRXhlY3V0aW9uVGltZV8xM01lYXN1cmVPYmplY3ROZWlnaGJvcnMrRXhlY3V0aW9uVGltZV8xNE1lYXN1cmVUZXh0dXJlKSAlPiUKICBncm91cF9ieShNZXRhZGF0YV9QbGF0ZSwgTWV0YWRhdGFfV2VsbCkgJT4lCiAgc3VtbWFyaXNlKEV4ZWN1dGlvblRpbWUgPSBzdW0oRXhlY3V0aW9uVGltZSkpICU+JSB1bmdyb3VwKCkKCmRmMiA8LSByZWFkX3RzdigiZGF0YS9jcC0yMjEtYW5hbHlzaXMubG9nIikgCgpkZjIgJTw+JSByb3d3aXNlKCkgJT4lIG11dGF0ZShwd3MgPSBDb21tYW5kICU+JSBzdHJfc3BsaXQoIi9zdGF0dXNfZGlyLyIpICU+JSBleHRyYWN0MigxKSAlPiUgZXh0cmFjdDIoMikgJT4lIHN0cl9zcGxpdCgiXFwuIikgJT4lIGV4dHJhY3QyKDEpICU+JSBleHRyYWN0MigxKSkgJT4lIHVuZ3JvdXAoKSAlPiUgc2VwYXJhdGUocHdzLCBpbnRvID0gYygiTWV0YWRhdGFfUGxhdGUiLCAiTWV0YWRhdGFfV2VsbCIpLCBzZXAgPSAiLSIpICU+JSBzZWxlY3QoTWV0YWRhdGFfUGxhdGUsIE1ldGFkYXRhX1dlbGwsIEpvYlJ1bnRpbWUpCgpkZiA8LSBpbm5lcl9qb2luKGRmMSwgZGYyKQoKY29ydmFsIDwtIHdpdGgoZGYsIGNvcihFeGVjdXRpb25UaW1lLCBKb2JSdW50aW1lKSkKCmdncGxvdChkZiwgYWVzKEV4ZWN1dGlvblRpbWUsIEpvYlJ1bnRpbWUpKSArIAogIGdlb21fcG9pbnQoKSArIAogIGdlb21fYWJsaW5lKHNsb3BlID0gMSwgaW50ZXJjZXB0ID0gMCkgKyAKICB4bGltKDAsIDkwMCkgKyAKICB5bGltKDAsIDkwMCkgKwogIGNvb3JkX2VxdWFsKCkgKwogIGdndGl0bGUocGFzdGUwKCJjb3IgPSAiLCBjb3J2YWwpKQoKbSA8LSBsbShkYXRhID0gZGYsIGZvcm11bGEgPSBKb2JSdW50aW1lIH4gRXhlY3V0aW9uVGltZSkKCnN1bW1hcnkobSkKCnBsb3QobSkKYGBgCgo=