私はシミュレーションで評価ファイルを処理するために使用する見苦しいスクリプトを持っています。それはひどいようです。いいえ、私はコーダーではなく、通常は動作しますが、現在は動作しません。
明らかに、スクリプトは通常複数の入力ファイルを繰り返し、私のMacとシミュレーションを実行しているクラスタで動作します。 Ubuntuサーバーを実行しているVPSで実行しようとすると、奇妙な出力が生成されます。この問題を解決する方法がわかりません。
完全なスクリプトは次のとおりです。
#!/usr/bin/awk -f
FNR==1 && NR!=1 { endfile(); avgLT=totFrames=avgLTsq=avgFramessq=denom=0 }
FNR==1 { out1="analLT_"FILENAME; out2="sumLT_"FILENAME; out3="reportLT.txt"; print "-> Input file is: "FILENAME >> out3; next
}
FNR==1 { next }
{
avgLT+=$4; totFrames+=$5; ++denom;
printf "%10.4f %10.1f\n",$4,$5 > out1
}
END { endfile() }
function endfile()
{
x="\nNO DATA POINTS IN INPUT => NO HYDROGEN BONDS DETECTED!"
if (avgLT==0 && denom==0) {
print x > out1; print x > out2; print x"\n\n----------------------------------------\n" >> out3;
close(out1); close(out2); close(out3); return
}
if (avgLT>0) {
avgAvgLT=avgLT/denom
avgFrames=totFrames/denom
while ((getline<out1)>0) {
avgLTsq+=(($1-avgAvgLT)^2)
avgFramessq+=(($2-avgFrames)^2)
}
close(out1)
printf "\n Summary data for hbond lifetime analysis:\n\n" > out2
printf " Summed Avg Lifetime: %10.4f\n",avgLT > out2
printf " Average Lifetime: %10.4f\n",avgAvgLT > out2
printf " Summed Frames: %10.0f\n",totFrames > out2
printf " Average Frames: %10.4f\n",avgFrames > out2
printf "\n Summary data for hbond lifetime analysis:\n\n" >> out3
printf " Summed Avg Lifetime: %10.4f\n",avgLT >> out3
printf " Average Lifetime: %10.4f\n",avgAvgLT >> out3
printf " Summed Frames: %10.0f\n",totFrames >> out3
printf " Average Frames: %10.4f\n",avgFrames >> out3
if (denom>1) {
sd_avgLT=sqrt(avgLTsq/(denom-1)); semAvgLT=(sd_avgLT/(sqrt(denom))); sd_totFrames=sqrt(avgFramessq/(denom-1)); semTotFrames=(sd_totFrames/(sqrt(denom)))
printf "\n SD lifetime: %10.4f\n",sd_avgLT > out2
printf " SEM lifetime: %10.4f\n",semAvgLT > out2
printf " SD Frames: %10.4f\n",sd_totFrames > out2
printf " SEM Frames: %10.4f\n\n",semTotFrames > out2
printf "\n SD lifetime: %10.4f\n",sd_avgLT >> out3
printf " SEM lifetime: %10.4f\n",semAvgLT >> out3
printf " SD Frames: %10.4f\n",sd_totFrames > out3
printf " SEM Frames: %10.4f\n\n",semTotFrames > out3
} if (denom>1 && denom!=2) {print "----------------------------------------\n" >> out3 }
if (denom==1) { print " Single HBOND event, no SD or SEM calculation possible!" > out2;
print "\n Single HBOND event, no SD or SEM calculation possible!\n\n----------------------------------------\n" >> out3
}
if (denom==2) { print "\n 2 Hydrogen bond events found! No proper SD or SEM!" > out2;
print " 2 Hydrogen bond events found! No proper SD or SEM!\n\n----------------------------------------\n" >> out3
}
}
close(out3)
close(out2)
}
5列入力ファイルをインポートして2列を処理し、後で処理するために同じ列を別のファイルに入れます(out1)。その後、いくつかの統計を計算するためにファイルを処理する必要があります。しかし、これはVPSでは発生せず、私が得た値はすべて0.0000です。
問題はwhile関数にあるようです。
while ((getline<out1)>0) {
avgLTsq+=(($1-avgAvgLT)^2)
avgFramessq+=(($2-avgFrames)^2)
}
スクリプトの最後に内容がファイルに出力されると、計算された合計と平均(、、、avgLT
平均avgAvgLT
)の合理的な値が得られるようです。統計セクション(、および)に達すると、すべての値は元の値ではなく0.0000ですが、両方の項目に印刷されます。totFrames
avgFrames
sd_avgLT
semAvgLT
sd_totFrames
semTotFrames
out2
out3
out1
「math」は、ファイルに対して個別にコマンドを実行できるようです。
awk ' BEGIN { avgAvgLT=1.4264 } { avgLTsq+=(($1-avgAvgLT)^2) } END { print avgLTsq }' analLT_multiple.out
awk ' BEGIN { avgFrames=4.4831 } { avgFramessq+=(($2-avgFrames)^2) } END { print avgFramessq }' analLT_multiple.out
awk ' BEGIN { avgLTsq=30.3478; denom=89 } { sd_avgLT=sqrt(avgLTsq/(denom-1)) } END { print sd_avgLT }' analLT_multiple.out
awk ' BEGIN { sd_avgLT=0.587249; denom=89 } {semAvgLT=(sd_avgLT/(sqrt(denom))) } END { print semAvgLT }' analLT_multiple.out
awk ' BEGIN { avgFramessq=2040.22; denom=89 } { sd_totFrames=sqrt(avgFramessq/(denom-1)) } END { print sd_totFrames }' analLT_multiple.out
awk ' BEGIN { sd_totFrames=4.81501; denom=89 } { semTotFrames=(sd_totFrames/(sqrt(denom))) } END { print semTotFrames }' analLT_multiple.out
ゼロ以外の値を提供することで合理的に見えますが、スクリプトはすべての値を0.0000として提供します。また、複数のファイルを実行したときにスクリプトの変数値を印刷してみましたが、、、、およびすべて0または空の値を返しましdenom
たが、変数はまだ機能していました。sd_avgLT
semAvgLT
sd_totFrames
semTotFrames
私の「結論」(ここで推測だと言いたい)は、前に述べたように、while関数に問題があるということです。何かはわかりませんが。
Pastebinにサンプル入力ファイルを入れました。https://pastebin.com/JsuTz0mD スクリプトを直接実行してみたい場合。
私のVPSシステムでこのスクリプトを動作させるための入力/フィードバックまたはソリューションを提供していただきありがとうございます。
答え1
ファイルに書き込むときにファイルに書き込まれるデータをフラッシュしない(GNUまたは)、書き込み用に開いたままにしておくawk
ファイルハンドルから何かを読み取っています。これは、このファイルのデータをチャンクで読み取ったときにデータが読み込まれないことを意味します。 BSDの実装にはこの問題はないようで、コードはOpenBSDやmacOSなどで期待どおりに動作します。awk
mawk
out1
awk
END
awk
回避策は簡単です。無条件ブロックでclose(out1)
使用してください。END
今後現在はそれをgetline
閉じます。後ろにそれを読んでください。
>
また、との一貫性を維持することをお勧めします>>
。私はあなたが>
このコードを完全に使用できると信じています。
答え2
@Kusalanandaはすでに何が間違っているかを言っているので、これは答えではありません。しかし、スクリプトを少し整理して読みやすくし、コードの重複を減らしましょう。
FNR == 1 {
if ( NR != 1 ) {
endfile()
}
avgLT = totFrames = denom = 0
out1 = "analLT_" FILENAME
out2 = "sumLT_" FILENAME
out3 = "reportLT.txt"
print "-> Input file is: " FILENAME > out3
next
}
{
avgLT += $4
totFrames += $5
++denom
printf "%10.4f %10.1f\n", $4, $5 > out1
}
END {
endfile()
}
function endfile( x, avgAvgLT, avgFrames, sd_avgLT,
semAvgLT, sd_totFrames, semTotFrames )
{
if (avgLT == 0 && denom == 0 ) {
x = "\nNO DATA POINTS IN INPUT => NO HYDROGEN BONDS DETECTED!"
print x > out1
print x > out2
print x > out3
}
else if (avgLT > 0) {
avgAvgLT = avgLT / denom
avgFrames = totFrames / denom
close(out1)
while ((getline < out1) > 0) {
avgLTsq += (($1 - avgAvgLT) ^ 2)
avgFramessq += (($2 - avgFrames) ^ 2)
}
close(out1)
printf "\n Summary data for hbond lifetime analysis:\n\n" > out2
printf " Summed Avg Lifetime: %10.4f\n", avgLT > out2
printf " Average Lifetime: %10.4f\n", avgAvgLT > out2
printf " Summed Frames: %10.0f\n", totFrames > out2
printf " Average Frames: %10.4f\n", avgFrames > out2
printf "\n Summary data for hbond lifetime analysis:\n\n" > out3
printf " Summed Avg Lifetime: %10.4f\n", avgLT > out3
printf " Average Lifetime: %10.4f\n", avgAvgLT > out3
printf " Summed Frames: %10.0f\n", totFrames > out3
printf " Average Frames: %10.4f\n", avgFrames > out3
if (denom == 1) {
x = " Single HBOND event, no SD or SEM calculation possible!"
print x > out2
print "" > out3
print x > out3
}
else if (denom > 1) {
sd_avgLT = sqrt(avgLTsq / (denom - 1))
semAvgLT = (sd_avgLT / (sqrt(denom)))
sd_totFrames = sqrt(avgFramessq / (denom - 1))
semTotFrames = (sd_totFrames / (sqrt(denom)))
printf "\n SD lifetime: %10.4f\n", sd_avgLT > out2
printf " SEM lifetime: %10.4f\n", semAvgLT > out2
printf " SD Frames: %10.4f\n", sd_totFrames > out2
printf " SEM Frames: %10.4f\n\n", semTotFrames > out2
printf "\n SD lifetime: %10.4f\n", sd_avgLT > out3
printf " SEM lifetime: %10.4f\n", semAvgLT > out3
printf " SD Frames: %10.4f\n", sd_totFrames > out3
printf " SEM Frames: %10.4f\n\n", semTotFrames > out3
if (denom == 2) {
x = " 2 Hydrogen bond events found! No proper SD or SEM!"
print "" > out2
print x > out2
print x > out3
}
}
print "\n\n----------------------------------------\n" > out3
close(out1)
close(out2)
close(out3)
}
out1のwhile getlineループは、スクリプト本体にout1を書くのではなく、配列にデータを格納できるので、実際には必要ありません。たとえば、次のようになります。
FNR == 1 {
if ( NR != 1 ) {
endfile()
}
avgLT = totFrames = denom = 0
out1 = "analLT_" FILENAME
out2 = "sumLT_" FILENAME
out3 = "reportLT.txt"
print "-> Input file is: " FILENAME > out3
next
}
{
avgLT += $4
totFrames += $5
++denom
fnr2avgLT[FNR] = avgLT
fnr2totFrames[FNR] = totFrames
}
END {
endfile()
}
function endfile( i, x, avgAvgLT, avgFrames, sd_avgLT,
semAvgLT, sd_totFrames, semTotFrames )
{
if (avgLT == 0 && denom == 0 ) {
x = "\nNO DATA POINTS IN INPUT => NO HYDROGEN BONDS DETECTED!"
print x > out1
print x > out2
print x > out3
}
else if (avgLT > 0) {
avgAvgLT = avgLT / denom
avgFrames = totFrames / denom
for (i=1; i<=FNR; i++) {
avgLT = fnr2avgLT[i]
totFrames = fnr2totFrames[i]
printf "%10.4f %10.1f\n", avgLT, totFrames > out1
avgLTsq += ((avgLT - avgAvgLT) ^ 2)
avgFramessq += ((totFrames - avgFrames) ^ 2)
}
printf "\n Summary data for hbond lifetime analysis:\n\n" > out2
printf " Summed Avg Lifetime: %10.4f\n", avgLT > out2
printf " Average Lifetime: %10.4f\n", avgAvgLT > out2
printf " Summed Frames: %10.0f\n", totFrames > out2
printf " Average Frames: %10.4f\n", avgFrames > out2
printf "\n Summary data for hbond lifetime analysis:\n\n" > out3
printf " Summed Avg Lifetime: %10.4f\n", avgLT > out3
printf " Average Lifetime: %10.4f\n", avgAvgLT > out3
printf " Summed Frames: %10.0f\n", totFrames > out3
printf " Average Frames: %10.4f\n", avgFrames > out3
if (denom == 1) {
x = " Single HBOND event, no SD or SEM calculation possible!"
print x > out2
print "" > out3
print x > out3
}
else if (denom > 1) {
sd_avgLT = sqrt(avgLTsq / (denom - 1))
semAvgLT = (sd_avgLT / (sqrt(denom)))
sd_totFrames = sqrt(avgFramessq / (denom - 1))
semTotFrames = (sd_totFrames / (sqrt(denom)))
printf "\n SD lifetime: %10.4f\n", sd_avgLT > out2
printf " SEM lifetime: %10.4f\n", semAvgLT > out2
printf " SD Frames: %10.4f\n", sd_totFrames > out2
printf " SEM Frames: %10.4f\n\n", semTotFrames > out2
printf "\n SD lifetime: %10.4f\n", sd_avgLT > out3
printf " SEM lifetime: %10.4f\n", semAvgLT > out3
printf " SD Frames: %10.4f\n", sd_totFrames > out3
printf " SEM Frames: %10.4f\n\n", semTotFrames > out3
if (denom == 2) {
x = " 2 Hydrogen bond events found! No proper SD or SEM!"
print "" > out2
print x > out2
print x > out3
}
}
print "\n\n----------------------------------------\n" > out3
close(out1)
close(out2)
close(out3)
}
もちろん、テストするサンプル入力/出力を提供していないので、上記の項目はすべてテストされていませんが、すべてのバグを簡単に見つけて修正できることを願っています。