scripts/p8/prepare.py lays out the 360 GEO IDATs under their header barcode/position; scripts/p8/validate_p8.py computes concordance, NRD, no-call rate, per-class and per-MAF sensitivity/specificity/precision/F1 vs NYGC 30x and GIAB HG001, replicate concordance, systematic/allele-swap site errors, per-chip batch table and duplicate detection. Cloud userdata can skip the Omni2.5 archive (OMNI=0). Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01814GKVzZVL3FuF3DeiZXhv
66 lines
2.9 KiB
Bash
Executable File
66 lines
2.9 KiB
Bash
Executable File
#!/bin/bash
|
|
# EC2 user-data for a self-destructing SimurgArray validation run (Ubuntu 24.04, arm64).
|
|
# Placeholders (__X__) are filled in by scripts/cloud/trial.sh.
|
|
#
|
|
# Safety layers inside the instance:
|
|
# 1. `shutdown -h +MAX_MINUTES` is scheduled first -> hard time cap
|
|
# 2. an EXIT trap uploads the log and shuts down -> ends as soon as the job ends, success or failure
|
|
# Shutdown = TERMINATE (instance-initiated-shutdown-behavior) and the only disk has DeleteOnTermination=true,
|
|
# so nothing keeps costing money afterwards. A CloudWatch alarm (layer 3) terminates an idle instance from
|
|
# outside, in case the OS hangs.
|
|
set -uo pipefail
|
|
export HOME=/root # cloud-init runs user-data without HOME
|
|
export PATH="/root/.local/bin:/snap/bin:$PATH"
|
|
BUCKET="__BUCKET__"
|
|
RUN="__RUN__"
|
|
MAX_MINUTES="__MAX_MINUTES__"
|
|
shutdown -h +"$MAX_MINUTES" "SimurgArray trial hard time limit"
|
|
|
|
LOG=/var/log/simurg-trial.log
|
|
exec > >(tee -a "$LOG") 2>&1
|
|
S3=""
|
|
upload_log() { [[ -n "$S3" ]] && $S3 cp "$LOG" "s3://$BUCKET/$RUN/log.txt" --only-show-errors || true; }
|
|
finish() {
|
|
rc=$?
|
|
echo "=== finished rc=$rc at $(date -u +%FT%TZ) ==="
|
|
echo "$rc" > /tmp/rc && [[ -n "$S3" ]] && $S3 cp /tmp/rc "s3://$BUCKET/$RUN/exit_code.txt" --only-show-errors
|
|
upload_log
|
|
shutdown -h now
|
|
}
|
|
trap finish EXIT
|
|
set -e
|
|
echo "=== start $(date -u +%FT%TZ) on $(uname -m), $(nproc) cpus ==="
|
|
|
|
export DEBIAN_FRONTEND=noninteractive
|
|
apt-get update -q
|
|
apt-get install -y -q pigz git python3-venv curl unzip time
|
|
snap install aws-cli --classic
|
|
S3="/snap/bin/aws s3"
|
|
( while sleep 300; do upload_log; done ) &
|
|
|
|
mkdir -p /work && cd /work
|
|
$S3 cp "s3://$BUCKET/$RUN/repo.tar.gz" . --only-show-errors
|
|
mkdir repo && tar -xzf repo.tar.gz -C repo && cd repo
|
|
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
uv venv -q --python 3.12 .venv && uv pip install -q -e ".[dev]"
|
|
mkdir -p refs && git clone -q --depth 1 https://github.com/Illumina/BeadArrayFiles.git refs/BeadArrayFiles
|
|
|
|
SRC=s3://1000genomes/release/20130502/supporting/hd_genotype_chip/broad_intensities
|
|
D=/work/omni && mkdir -p $D/data
|
|
if [[ "__OMNI__" == "1" ]]; then
|
|
for f in HumanOmni2.5-4v1-Multi_B.bpm HumanOmni2.5-4v1-Multi_B.egt HumanOmni2.5-4v1_B.csv; do
|
|
$S3 cp --no-sign-request "$SRC/$f" $D/ --only-show-errors
|
|
done
|
|
echo "=== streaming 107 GB IDAT+GTC archive (no copy of the .tgz is kept) $(date -u +%T) ==="
|
|
$S3 cp --no-sign-request "$SRC/Omni25_idats_gtcs_2141_samples.tgz" - | pigz -dc | tar -x -C $D/data
|
|
echo "=== extracted $(du -sh $D/data | cut -f1) at $(date -u +%T) ==="
|
|
fi
|
|
|
|
echo "=== unit tests $(date -u +%T) ==="
|
|
.venv/bin/python -m pytest tests/unit -q -p no:cacheprovider || echo "unit tests reported failures (continuing)"
|
|
echo "=== task __TASK__ $(date -u +%T) ==="
|
|
mkdir -p /work/results
|
|
bash scripts/cloud/tasks/__TASK__.sh $D /work/results || echo "task exit code $?"
|
|
$S3 cp /work/results "s3://$BUCKET/$RUN/" --recursive --only-show-errors || true
|
|
echo "=== done $(date -u +%T) ==="
|