2023年12月24日日曜日
つれづれ思うこと 外国語編 その2
2023年12月9日土曜日
魔法の粉 ATP
2023年12月8日金曜日
大腸菌培養の最少培地 M9 その6
その後に、次のような論文が出ていたらしい。
M. Cai, Y. Huang, J. Lloyd, R. Craigie, G.M. Clore (2021) A simple and cost-effective protocol for high-yield expression of deuterated and selectively isoleucine/leucine/valine methyl protonated proteins in Escherichia coli grown in shaker flasks. J. Biomol. NMR 75, 83-87. doi: 10.1007/s10858-021-00357-x
同じ著者で過去にも数報が出ており、いずれも M9 培地での培養の効率を上げる内容となっている。
この論文には、D2O を 1/10 量の 100 mL に減らしながら、これまでの 1 L 培養と同じ量のタンパク質を調製するための方法が書かれている。私も「重水 100 mL 培養は良いよ」とどこかに書いたような気もする。蛋白質を重水素化して methyl-TROSY を測ると、数 μM のような濃度でも観える。したがって、15N, 13C 安定同位体の培地を 1 L 作るのと、2H, methyl 1H/13C の培地を 0.1 L 作るのとでは、コストの面でそれほど大差はなくなってくるのである(とは言え、怖くて厳密に価格を計算していない)。それでいて、分解能は 2H 化の方が圧倒的によい。
重水 M9 培地に LB (D2O) が少しコンタミするそうであるが、3% までは 1H のコンタミの点で大したことはないそうである(本当か?)。著者らは 0.1% でも、むしろ大腸菌の成長にとって十分に効果ありと言っている(ただし、transfer cross saturation 実験に使う場合には、極力 1H の混入を避けた方がよいだろう)。
以下は論文から抜粋しているが、"100 mL" 培地に対してであることに注意
α -ketoisovaleric 32 mg
α -ketobutyric acid 16 mg
[2H]-glucose 1.8 g
[15N]-NH4Cl 0.5 g
LB (D2O) 1/1,000
グルコースの量が非常に多い。我々は 2 g/L ほど入れているが、彼らはそれの 9 倍量を入れていることになる。また、15NH4Cl も、我々は 2 g/L ほど入れるが、彼らはそれの 2.5 倍量を入れていることになる。
さらに硫黄源も多い。我々は MgSO4 の形で 2 mM ほど入れている。しかし、この論文では K2SO4 の形で 7 倍量の 14 mM も入れている。では、MgSO4 を 14 mM も入れても大丈夫なのだろうか?Mg2+ が多過ぎてダメだろうか?しかし、著者らは何故 Mg2+ の量を前回の論文での 10 mM から今回の 1 mM に減らしてしまったのだろう?我々は 2 mM 入れているが、Mg が多いと何かまずいことが起こるのだろうか?来週、学生に試してもらおう(どこかで後述)
これら、グルコース、塩化アンモニウム、硫黄源は、我々の現在の仕様より何倍も多く、これらが大腸菌の増殖に効くのだろう。さらに、微量金属やビタミンミックスもちゃんと?入れている。1/1,000 の LB 混入も効くのだろう(我々は遠心して大腸菌だけを植菌しているが)。
著者らの方法により、IPTG での誘導時の OD600 は 10 に達し、100 mL の重水培地から最終的に 11 mg の精製蛋白質がとれたそうである。確かにグルコースが通常の 10 倍近く入っている。もし、とれる蛋白質量がグルコースの絶対量に比例するならば(きっとそうだろう)、納得のいく数値である。ただし、いくつかの注意点も書かれている。
ひとつは、植え継ぎをこまめにすることである。Pre-culture を main-culture に入れて終わりというのではなく、次に植えた時に 10 倍以上は薄まらないように気をつけている(図2が分かりやすい)。こちらでも、100 mL を 1L に植えると成功するのに、20 mL を 1L に植えてしまい何度も失敗したことがある。なんと何億匹もいるはずの大腸菌が一匹残らず全滅するのである。二個目の注意点はバッフル付きの大きなフラスコを使うことである。培地の量はフラスコ容量の 1/10 以下に抑えている。これはエアレーションをよくするためであろう。ただし、上にも書いたが、実験目的が transfer cross saturation の場合には、培地の攪拌によってあまり多量の 1H 水蒸気を入れたくないので、ここが難しいところである。
著者らの方法により、たったの 100 mL で 1 L 培養と同じ量の蛋白質がとれた。もちろん、グルコースの絶対量は同じであるが、2-ケト酸や重水そのものは少なくてすむ。今、日本で重水を買うと 30 万円/L(= 2,100 USドル)であるので、かなりの節約になるだろう。
2023年11月23日木曜日
つれづれ思うこと 外国語編 その1
2023年10月15日日曜日
つれづれ思うこと Perl 編 その9
x = 3;
y = 4;
ab = {x, y};
ab
と書くと、ab には {3, 4} という具体的な数値が代入されます。後から x や y の値を変えても ab は変わりません。これは、一般的なプログラムと同じです。ところが、
ab = {x, y};
x = 3;
ab
というように、今度は行の順番を変えてみると、一行目で ab には {x, y} という文字式が代入されます。そして、面白いことに、二行目で x や y の文字変数の値を変えると、ab も {3, y} に変わるのです。続けて、
x = 8;
ab
と打つと、なんと ab は {8, y} に変わります。ab の中の x という文字はまだ生きているのです。これは Perl などの一般的なプログラムとは異なる点です。
詳細は Mathematica の「遅延割当」という項目をご覧ください。
これは Mathematica が数値計算だけでなく数式処理もできるためですが、いま大変重宝しています。例えば、ある時は数値計算を、またある時には数式処理をしたいとします。いずれにしても、ab = {x, y} のような公式にあたる箇所を先にプログラミングで組み立てておきます。もし、数式処理をしたければ、これでそのまま数式での答を得ることができます。
上記のような書き方は数値計算に特化されていないので、実は余計に計算時間がかかってしまうのですが、いろいろな数値を入れて答を比べてみたい時には助かります。
よって、次のような計算もできます。
d = e;
e = f;
f = 8;
d
d を表示させると、8 になっています。
これは、普通のプログラミング言語とは行の順番が真逆です。
blist = alist; (* 先に変数を結び付けておく *)
alist = {2, 4, 6, 8, 10}; (* そして alist に偶数の配列を代入する *)
alist (* 試しに alist を表示 *)
{2, 4, 6, 8, 10} (* もちろん alist は偶数の配列 *)
blist (* そして blist も表示 *)
{2, 4, 6, 8, 10} (* blist も同じ偶数の配列 *)
alist[[3]] = 100; (* それでは alist の3番目の要素に 100 を代入 *)
alist (* を表示させてみる *)
{2, 4, 100, 8, 10} (* ちゃんと3番目の要素は 100 に変わっている OK *)
blist (* それでは blist は? *)
{2, 4, 100, 8, 10}
先に blist = alist のように公式を組み立てておくと、このような結果になります。
Perl ではこのような行の順番で書くことはできませんので、下記のように上の行から下の行へと水が流れ落ちるように書くことになります。
#!/usr/bin/perl
@alist = (2, 4, 6, 8, 10);
@blist = (1, 3, 5, 7, 9, 11);
@blist = @alist;
$alist[2] = 100;
print "alist = @alist\n"; # 2 4 100 8 10 と表示
print "blist = @blist\n"; # 2, 4, 6, 8, 10 と表示
以上より @blist = @alist という表現では、alist のコピーが blist に複写されているようです。つまり、alist の先頭アドレスが blist に代入されたわけではありません。
しかし、次のように書くと、
#!/usr/bin/perl
@alist = (2, 4, 6, 8, 10);
@blist = (1, 3, 5, 7, 9, 11);
$blist = \@alist;
$alist[2] = 100;
print "alist = @alist\n"; # 2 4 100 8 10 と表示
print "blist = @$blist\n"; # 2 4 100 8 10 と表示
print "blist = @blist\n"; # 1 3 5 7 9 11 と表示
$blist には @alist の先頭アドレス(レファレンス)が入り、それとは別に @blist の配列そのものはちゃんと維持されるようです。
話が急に配列そのもののコピーか、それともアドレス(参照)のコピーかに飛んでしまいましたが、Perl, Python, JavaScript とごちゃまぜに書いていると、いつも分からなくなって困ってしまう点です。どこかに比較対照表のようなものをまとめたブログはないでしょうか?
おそらく Python では次のようになります。
a = [1, 1]
b = a
a[1] = 2
print(b) #[1,2]が表示される
多くの HP には「数値はイミュータブル(変更不可)、一方、リストはミュータブル(変更可能)」などといった説明が載っており、それはそれなりに説得力があるのであるが、Perl と比較しながら理解しようとすると混乱してしまいます。上記の Python は、いわば C 言語でいうところの、配列名はその先頭アドレスを表すという概念と似ています。
Python でリスト(配列)そのものをコピーするには、
b = copy.copy(a) # 浅いコピー
としないといけないようです。二次元以上の配列になってくると、またちょっと複雑。
b = copy.deepcopy(a) # 深いコピー
を使わないといけない。
一方、Perl では
@blist = @alist;
と書くと、配列そのもののコピー(複写)になることに注意しないといけません。
Mathematica でも同じ複写ですが、blist = alist を先に書いてから、後で具体的な数値の配列を alist に入れるという方式をとると、これはアドレス渡しのように振る舞うことになります。
いや~もう疲れた。もう JavaScript まで行きたくない。が、ついでだ!思い切ってやってみよう。もう混乱してきたので、詳細は他の情報源に譲ることにして要点だけ。
JavaScript の配列では参照渡しとなるようです。配列を値渡しに(複写)するには、slice や concat の引数なしを使うようです。
var arr1 = [0, 1, 2, 3, 4];
var arr3 = arr1.slice();
ということは C 言語と似ているということ?
C 言語では、配列名は先頭アドレスを指しますよね。
なので、b = a の後で、a の中身を変えると、b も変わって見える。
C 参照渡し
a[3] = {1, 2, 3};
b = a;
Python 参照渡し
a = [1, 2, 3]
b = a
JavaScript 参照渡し
a = [1, 2, 3];
b = a;
Perl 値渡し
@a = (1, 2, 3);
@b = @a;
ただし、$b = \@a; のように、b をポインタ変数のように使うことも可能。この場合は、それ以降 @$b の形で配列 b を使う。「\」は、C 言語のアドレス演算子「&」と似ている。
Mathematica 1 値渡し
a = {1, 2, 3}
b = a
Mathematica 2 参照渡し
b = a
a = {1, 2, 3}
こうして見てみると、Python は、まあ C と似ているのかも。
Perl や Mathematica がむしろ異端児なのか?
2023年9月26日火曜日
つれづれ思うこと Perl 編 その8
{
$y = -$x;
else
{
$y = $x;
となります(むりやり Perl にしてしまった)。。。
(* if *) x < 0,
y = -x,
(* else *)
z = x*3;
y = Sqrt[z]
]
2023年9月16日土曜日
つれづれ思うこと Perl 編 その7
2023年9月14日木曜日
つれづれ思うこと Perl 編 その6
Tcl 言語はひとことで言うと、たいへん可愛いに尽きます。Perl や Python がそれぞれ立派なリャマと大蛇だとすると、Tcl はコアラのような感じ。例のシリーズ本では、お猿さんの図が表紙になっていますが、猿のイメージとは大違い。ぱっと見た感じではシェルに見えます。ですので、ちょっとした計算(x = 5+3)でも、set x [expr 5+3] のような面倒な書き方になります。しかし、逆に c-shell も知らない筆者にとっては、これが新鮮で可愛く映ったのでした。
しかし、これだけなら Tcl/Tk を使おうとは思わなったのですが、Tcl にはそれ以上に面白い点がありました。Tcl は C 言語のコードをコンパイルする時に、そこにライブラリーとして含めることができるのです。つまり、以下のようになります。複雑な計算の箇所は高速化が必要ですので C 言語で書いておきます。そして、そのコードの入力と出力のパラメータを Tcl 言語と紐づけします。そして、Tcl ライブラリーを含めてコンパイルします。できあがった実行可能バイナリーファイルですが、入出力を Tcl 言語にすることができるのです。これはたいへん便利。いろいろなパラメータで同じような計算をし、結果をグラフに表して比べたい時、そのパラメータの入出力部分は Tcl でいかようにも変えることができるのです。ですので、二度目、三度目のコンパイルは不要。もし、C 言語だけでそれをしようとすると、「パラメータ a を入力してください」などと画面で促し、それを scanf で取り込むという面倒なことになります。もし、数百種類のパラメータでそれをしないといけないとすると、それでもう終わりです。
2023年9月13日水曜日
つれづれ思うこと Perl 編 その5
Perl で exp(i H t) などの計算を試してはみたものの、やはり 1995 年頃は遅くて使い物にはならなかった。そこで科学計算にはやはり C 言語を使っていた。その時に役立った本が「Mumerical Recipes in C」(の翻訳版)。ここにはいろいろな計算のためのコードが載っていて、それをそのまま使ってかなりの数値計算をすることができる。特に重宝したのが最適化(フィッティング)の処理である。データに非線形的にフィッティングするための方法では Levenberg–Marquardt 法が有名であるが、コードを打ち込むのが大変そうだったので、何かもっと簡単な方法はないかな?とこの本で探してみると「アメーバ法」という方法が紹介されていた。正式には Nelder–Mead 法と呼ぶらしい。コードも数百行ぐらいで閉じているので、頑張って間違わずに打ち込めば、すぐに動く。この方法のよい点はモデル式の微分が要らない、不連続な箇所があってもよいなどで、まあとにかく制限がほとんど無いので、どんな状況にも適用できる。欠点は時間がかかる、間違えた解にトラップされやすいなど。よって、予想できる解がすでにある時には、できるだけそこからスタートするとよいです。
こんな(失礼ながら)子供遊びのような方法で数学的な最適化ができるのか?と思われ勝ちだが、試してみるとたいへん強力であった。例えば、NMR の残余双極子相互作用値を蛋白質の構造に当てはめる場合、400 残基分のデータをフィットするのに今の PC であれば 0.1 秒とかからない。当時でも 3 秒あれば十分であった。そこで、いろいろな初期値を 10 個ぐらい適当に準備して、それらを全部試してみる。 30 秒ぐらいで 10 個のフィッティングがすべて終わるので、その中から最小の二乗偏差を示す結果だけを選ぶ。エラーバーはどうするのかということになるが、これはモンテカルロ・シミュレーションがよい。100 個ほど模擬データを作っておき、全てにアメーバを振りかける。バナナを食べ終わる 10 分後にはすでに終わっており、その結果をエクセルで統計処理すればエラーバー(標準偏差)が出てくる。
結局つい数年前まで、NMR の緩和、残余双極子相互作用、回転拡散の異方性、拡散係数など、ほとんど全ての処理にアメーバを這わせたが、まったく問題なかった。緩和分散曲線もかなりは問題なし。もちろん Levenberg–Marquardt 法を使えば 0.1 秒ほどで終わってしまうが、今の PC をもってすると、それが延びたところで 1 秒ぐらいなので、もはや大した問題ではなくなっている。今は Perl に書き直したコードも使っている。C の 3-5 倍ぐらいかかるが、上記の NMR データの最適化で 1 分以上かかるような処理はあまりない。
2023年9月10日日曜日
つれづれ思うこと Perl 編 その4
2023年9月9日土曜日
つれづれ思うこと Perl 編 その3
(その2)の続きとして、次は NumPy について。
例えば、筆者の NMR データの解析のためのプログラムには、exp(i H t) という計算が一杯入ってくる。ここで i は虚数、t は時間であるが、H はハミルトニアンと呼ばれる演算子であり、中身は行列である。つまり、e の何とか乗での冪数(べきすう)にあたる箇所に行列が来る。その行列も1万行 x 1万列などという大きさの場合がある(NOESY, saturation transfer のシミュレーションなど)。3 の 2 乗は 9 とすぐに計算できるが、3 の行列乗(しかも内部には虚数)なんて、どのようにして計算するのだろう?と思われるかもしれないが、実はこの行列 (i H t) を対角化さえできれば簡単に計算できる。この exp(i H t) は物理では至るところに出てくるので、物理の計算では行列の対角化(つまり、固有値と固有関数の導出)ができるかどうかが重要な鍵であると言える。
これを Python で計算させると、リターンキーを押し込む前に速攻で答が返ってくる。NumPy と SciPy ライブラリーのおかげである。ここが Python の強いところ。このライブラリー部分は C 言語か Fortran かで書かれているらしいが、表面的にはまるで Python そのものが計算しているように見える。
一方、Perl でこれができるだろうか?一応 PDL(Perl Data Language)と呼ばれるライブラリーがあり、最近ではいろいろな計算ができるらしい。しかし、25 年ほど前は exp(i H t) が Perl で簡単に、しかもバナナジュースを飲み終える短時間内に計算できるかどうかはよく分からなかった。ここが個人的には勝敗を分けたような気がする。1996 年頃、何とかこの計算を Perl で行いたく、力づくでテーラー展開を使った。そうです、対角化という高等な操作を使わなくても、ひたすらテーラー展開をして汗水流せば、exp(i H t) を求めることができるのです。高校でよく x が小さい時 (1+x)^n = 1+nx ですよと習う、あの近似式もテーラー展開から来ている。これを1次でストップせずに、2次、3次と続けていくとますます真の値に近づいていくはずであるが、いったいどこまで続ければよいのだろう?
普通はまあ 10 次ぐらいまで計算して足し込めば十分だろうと思いがちである。ところが、どんどん次数を上げていくと、収束したり発散したりを繰り返したのである(行列の中に虚数が含まれているためだろうか?)。よって、変な次数のところでうっかり止めてしまうと、真値からかなり外れた値に落ちてしまう。というわけで、200 次ぐらいまで計算することにした。この 200 がよいのかどうかは今だに分からない。
ややこしそうに見えるが、要は行列の内積(行と列の要素を一つずつ掛け合わせてから足す)をどんどん繰り返していくだけである。これを計算するには、for 文による繰り返しをひたすら書いていけばよい。そして、NMR のシミュレーションでは FID 部分は 1,000 ポイントぐらいあるので、またこれを 1,000 回ぐらい計算するのである。いずれも for 文を使って。ちょっとややこしいのは、実数と虚数を分けたり混ぜたりしながら計算しないといけない点である(虚数 x 虚数 = 実数, 虚数 x 実数 = 虚数となる具合に)。
このようなプログラムを書いていると何故か汗が出てくる。計算するのはあくまで PC であって、自分が計算するわけではないのであるが、for 文をひとつ追加するごとに、まるで自分が激しく運動しているかのような錯覚に陥り、大変だなあと困って汗ばんでしまうのである。そして何とか書き上げ、いざ実行!だが、答が返ってこない。。。。バグっているのか、それとも PC がまだひたすら計算しているのかは?である。試しに1ポイントだけ計算させてみると、10 分ほど経って一応は正しい答が返ってきた。やった~と叫んだが、たった1ポイントだけではスペクトルをシミュレートするには程遠く、ほとんど役立たずである。それでそのまま放り出してやめてしまった。
月日は流れ 22 年ほど経ったある日、そのプログラムをふと思い出し、こわごわ動かしてみた。普通はそんな昔のプログラムが素直に動くことはない。しかし、この Perl はなにやら計算をし始めた。この Perl の後方互換性は大変すばらしい!私がこれまでに作った Perl の中でうまく動かなったのは一度だけで、それも 30 年以上前に作った初期版だけである。たしか、先頭にスペースのある行を split した時に、配列インデックスが 1 から始まったような気がする(今は0)。それで iMac-27 (core-i5, 32 GB memory)のマシンで 30 分後にプロンプトが返ってきた!恐る恐る gnuplot でグラフを表示させてみると、事前に Mathematica で計算したのと全く同じグラフが出てきたのである。これには大変驚きで、プログラムを前に「なんて可愛いヤツなんだ」と感動してしまった。
あまりもの嬉しさに論文に「Mathematica と Perl で図8をシミュレートした」などと書いたら、ある審査員 reviewer が「こいつはバカか?」と思ったのか、論文を reject すると同時に、NumPy と SciPy のプログラムを送ってきた。それでこれを実行してみると、3 秒ぐらいで同じグラフが画面に出てきたので(gnuplot もなしに)、共著者とともにまたまた驚き、なんて速いプログラムなんだ、大蛇、恐るべし!と、これまた感動してしまった。
それからは、もう勝てないものには勝てないと諦め、素直に Python で、しかし泣く泣く計算プログラムを作るようになった次第である。とは言え、もし Perl にもそのような高速の数学ライブラリが揃っていれば、さらにグラフも簡単に作れれば、間違いなく、蛇ではなくリャマをお友達にしている。
2023年9月8日金曜日
つれづれ思うこと Perl 編 その2
2023年9月7日木曜日
つれづれ思うこと Perl 編 その1
{
$def = 3;
}
のように { } を使うが、Python では使わずに行を右へずらす(インデント)。ちなみに、私は癖で
if ($abc == 3) {
}
のようには書かない。その理由は、{ と } がエディター上で縦に揃っていると、if 文の及ぶ範囲が一目で分かるためである。しかし、Python では括弧がないので、vi で Python プログラムを編集した時、if 文の階段が5段ぐらい入れ子になり、そこでインデントを間違えた瞬間に崩壊してしまった。間違えた!と気づいても、どこをどう修正してよいのか分からなくなるのである。他人の Python プログラムを破壊するのは簡単である。エディター上でスペースキーをちょこっと押してやると、もう動かなくなり、修正にたいへん時間がかかる。
2023年6月23日金曜日
NMR 誘導型指向性進化
2023年2月26日日曜日
防腐剤
Alphafold の不得意なところこそ NMR にとって得意
https://www.frontiersin.org/articles/10.3389/fmolb.2022.906437/full
published: 17 May 2022 doi: 10.3389/fmolb.2022.906437