我正在尝试使用vcftools包来计算weir和cockerham的fst。我想在第一个例子中循环两对种群,然后在1000基因组项目的所有变体上循环这些种群:每个染色体包含一个单独的vcf文件。例如,对于pop1和pop2,对于pop3和pop4,计算染色体1-10的fst。每个人口文件(例如,LWKfile )都包含属于此人口的个人的列表。
我尝试过:
for population in LWK_GBR YRI_FIN; do
firstpop=$(echo $population | cut -d '_' -f1)
secondpop=$(echo $population | cut -d '_' -f2)
for filename in *.vcf.gz; do
vcftools --gzvcf ${filename} \
--weir-fst-pop /outdir/${firstpop}file \
--weir-fst-pop /outdir/${secondpop}file \
--out /out/${population}_${filename}
done
done 然而,这并不是循环遍历所有的文件,并且似乎卡在10号染色体上。有没有更有效的方法在bash中执行这一点,因为我担心循环中的循环会太慢。
发布于 2020-12-31 21:26:28
然而,这并没有循环遍历所有的文件,并且似乎卡在了10号染色体上。我担心循环中的循环会太慢。
你确定是for filename in *.vcf.gz太慢而无法遍历所有文件吗?
尝试将echo放在vcftools之前,看看它是否仍然卡住。
为了能够做出正确的选择,你需要确定什么需要花费太多的时间。
例如,如果它是vcftools,那么您可能不需要等待此命令结束,并考虑进行一些异步处理。
如果一个循环的文件太多,您还应该考虑进行一些并行处理。
此外,您似乎对所有.vcf.gz文件重复了两次循环。它可能会更快地逆转你的两个循环。
以下是使用bash进行并行和异步处理的示例
#!/bin/bash
MAX_PARALLEL_PIDS=4 # adjust regarding your own machin capacity (cpu available, etc... it could be dynamically calculated)
declare -a POPS
declare -a PIDS
POPS=("LWK_GBR" "YRI_FIN")
# your heavy treatment in a function
process() {
pop="${1}"
filename="${2}"
firstpop="${pop%%_*}" # no need to call an external program here
secondpop="${pop#*_}" # same here
vcftools --gzvcf "${filename}" \
--weir-fst-pop "/outdir/${firstpop}file" \
--weir-fst-pop "/outdir/${secondpop}file" \
--out "/out/${pop}_${filename}"
}
# a function which is usefull to wait all process when your "thread pool" reached its limits
wait_for_pids() {
for pid in "${PIDS[@]}"; do
[[ $pid =~ ^[0-9]+ ]] && wait $pid
done
unset PIDS
}
i=0
for filename in *.vcf.gz; do
if [[ $i -ge $MAX_PARALLEL_PIDS ]]; then
i=0
wait_for_pids
fi
for population in "${POPS[@]}"; do
process "${population}" "${filename}" & # You won't wait for the end here
PIDS[$i]=$!
(( i++ ))
done
done
# at the end wait for the remaining processes
wait_for_pids注意:把[[条件中的变量放在一边,你应该注意引用可以包含一些空格的变量,特别是文件名。否则它会坏掉的。
https://stackoverflow.com/questions/65521198
复制相似问题