原始出处: http://www.tpj.com/
本文作者: Lincoln Steinx
本文译者: tcwu
Reprinted courtesy of the Perl Journal, http://www.tpj.com/
Lincoln Stein's website is http://stein.cshl.org/
位置:英国剑桥,欧洲最大的 DNA 定序研究中心的会议室
场合:本中心与美国最大的 DNA 定序研究中心的电脑科学家的高阶层会议
问题:虽然这两个中心使用几乎相同的实验技术,几乎相同的数据库,还有几乎相同的资料分析工具,却仍然无法交换或者比较出有意义的结果。
解决方案:Perl
人类基因计划在大约 1990 开始雄心勃勃的开始发展,期望能以国际合作的力量找出人类以及部分实验动物的完整 DNA 序列。这项工作的性质兼具科学与医药。藉由了解生物起源的构造,以及种种令人苦恼的细节,我们希望能够了解有机体如何由一颗卵发展到复杂的多细胞生物,食物如何代谢以及被转换成身体的一部分,以及神经系统如何流畅的工作。从医学的角度来看,从全盘了解完整的 DNA 序列得来的知道,能够有效的加速找出人类疾病(以及可能的疾病)的原因。
经过六年的努力,基因计划已经超越原先的计划日程了。人类以及实验动物的详细基因地图已经完成了(用一连串的标记来安排 DNA 是决定完整序列的第一步)。最小的有机体,酵母,已经近乎完成,接著下一个,细小的蠕虫也不远了。几个月以前大规模的人类 DAN 定序工作已经在各中心展开,并且在整年中都会全力进行。
从资讯处理的角度来看,DNA 是一个非常长的字串且由四个字母构成,分别是 A,T,G,C(这四个字母分别为四种化学物质的缩写,是构成双股螺旋的基础。字串的长度令人印象深刻但也不是让人特别惊讶: 3 x 10^9 的字母长,或者如果你用一个位元来储存每个字母的话,需要 3GB 的储存空间。
3GB 不小但是以今天的标准无疑的可以被管理。不幸的是,这只是储存结果所需要的空间。要得到这些结果所需要的储存空间远远大的多。根本的问题在於,目前的 DNA 定序技术一次最多只能读到 500 个连续的字母。为了决定更长的序列,必须将 DNA 定序为一小块一小块部分重叠的片段,称为”reads”,这些拼图般的区域用演算法来检查并找出相配的地方。因为 DNA 序列并非随机的(相似但并非完全一样的基本图案在基因中出现很多次),而且因为 DNA 定序技术有杂讯且倾向於错误,必须针对某个区域作 5 到 10 次,才能可靠的把”reads”片段重组成真正的序列,这增加了要管理的资料的数量。在这之上的是与实验室工作相关的资讯: 谁进行了实验,什麽时候完成的,被定序的基因区段,用哪个软件以及哪个版本重组序列,对实验加上的注解,等等。除此之外,一般人通常想要将定序用的机器产生的原始资料储存下来,每 500 个字母会产生 20-30kilobytes 长度的资料档案!
这还并非全部。只决定 DNA 序列是不够的。在这些序列里面,有功能的区域散布在很长的没有功\能的区域中。人类 DNA 中有基因,控制区域,结构区域,甚至有些病毒卷入人体中并且变成了化石遗迹。因为基因跟控制区域负责健康与疾病,研究者会想要标示以其注解它们当它们被重组的时候。这类的注解产生了更多的资料需要被追踪与储存。
某些人评估居会有 1 至 10TB 的资讯需要被储存才能看出人类基因计划的结论。
所以 Perl 能做什麽呢?从一开始研究者就了解到资讯学将会在基因计划中扮演很重要的角色。一个整合每个基因中心的资讯学核心被建立了。这些核心的任务有两个: 提供电脑支援和数据库福对给他们相关的实验室,还有发展资料分析和管理软件给整个基因研究社群。
公平的来说,资讯科学小组一开始的结果是好坏参杂的。有些小组试图在复杂的关联数据库上面建立大型的系统,它们一次又一次的受到生物研究的高度动态的阻挠。当一套系统里里外外运作都与复杂的实验室协定正常配合,被实作出来且经过除错,新的科技已经取代了旧的协定,於是软件工程师又得回到设计版前。
然而,大多数的小组学会了建构模组化的,松散结合的系统,这些系统的部分可以被拿出来或放进去而不需要重新更换整套系统。举例来说,在我的小组里面,我们发现许多资料分析工作牵涉到一连串的半独立的步骤,假想某人想要操作一个刚刚被定只好的位元(图一)。首先需要一个基本的品质测试:序列够不够长 ? 含糊不清的字元是不是在最大限制以下? 接著有”向量检查”。为了技术上的理由,人类 DNA 在被定序前必须经过细菌处理(这就是”复制”的程序)。并不常发生,但是人类 DNA 有时候会在处理的过程中遗失,而且整个序列包含了细菌的向量。向量检查确保只有人类的基因被记载到数据库里面。接下来是反覆序列的检查。人类 DNA 充满了重复的元素,使得将拼图安装在一起变的富有挑战性。重复序列测试试图由一个已知重复序列的数据库找出新序列,倒数第二个测试则是试图找出新的序列靠著对照於一个很大的社群的 DNA 序列数据库。在这时候一个比对成功通常能提供线索找到新序列的功\能。完成这些测试之後,序列以及它的资讯已经被收集且载入了实验室的区域性数据库。
将 DNA 序列通过这些独立分析步骤的过程看起来很像一根水管,因此不用多久我们就了解 Unix 系统上面的”pipe”可以操作项工作。我们发展了一个简单的以 Perl 为基础的资料交换格式,叫做”boulderio”,这格式允许松散连结的程序加入资讯到以导管(pipe)为基础的输入/输入字串流。 Boulderio 的基础是一对一对标签/值。Perl 模组让获得输入很容易,取出他们有兴趣的标签,在上面作一些事情,然後丢回输出字串流。所有该程序不感兴趣的标签被传到标准输出,所以其他的程序可以使用它们。
在这种形式的设计下,分析一个新 DNA 序列看起来像是这样(这并非我们真正在用的程序源代码,但已经很接近了)
name_sequence.pl < new.dna |
quality_check.pl |
vector_check.pl |
find_repeats.pl |
search_big_database.pl |
load_lab_database.pl
1 一个包含新的 DNA 序列的档案会一个叫做 "name_sequence.pl" 的 perl script 处理,该程序的任务只是给予这个序列一个新的且唯一的名字并且将他输出成 boulder 格式,它的输出看起来像:
NAME=L26P93.2
SEQUENCE=GATTTCAGAGTCCCAGATTTCCCCCAGGGGGTTTCCAGAGAGCCC......
来自 name_sequence.pl 的输入接著被传入品质检查程序,它会找寻 SEQUENCE 标签,跑品质检查演算法,然後把它的结论写到资料字串流里面。资料字串流现在看起来像:
NAME=L26P93.2
SEQUENCE=GATTTCAGAGTCCCAGATTTCCCCCAGGGGGTTTCCAGAGAGCCC......
QUALITY_CHECK=OK
现在资料字串流进入了向量检查。它会从字串流中取出 SEQUENCE 标签并且执行向量检查演算法。资料字串流现在看起来:
NAME=L26P93.2
SEQUENCE=GATTTCAGAGTCCCAGATTTCCCCCAGGGGGTTTCCAGAGAGCCC......
QUALITY_CHECK=OK
VECTOR_CHECK=OK
VECTOR_START=10
VECTOR_LENGTH=300
这些东西继续通过导管(pipeline),直到最後 "load_lab_database.pl" 程序核对所有收集的资料,将一些最後的结论是否适合未来适合标记起来,以及把所有的结果送入实验室的数据库。Boulderio 格式的一个很好的特性就是许多个序列的纪录可以被连续的在 Unix 导管里面被处理。用一个”=”表示表示一笔记录的结尾,以及下笔资料的开始:
NAME=L26P93.2
SEQUENCE=GATTTCAGAGTCCCAGATTTCCCCCAGGGGGTTTCCAGAGAGCCC......
=
NAME=L26P93.3
SEQUENCE=CCCCTAGAGAGAGAGAGCCGAGTTCAAAGTCAAAACCCATTCTCTCTCCTC...
=
也可以在纪录中再建立子纪录,这使得我们可以使用结构化的资料型态。
以下为范例源代码,这个源代码处理 boulderio 格式。它有物件导向的风格,纪录被从输入字串流中拉出来,修改,然後丢回字串流中。
use Boulder::Stream;
$stream = new Boulder::Stream;
while ($record = $stream->read_record('NAME','SEQUENCE')) {
$name = $record->get('NAME');
$sequence = $record->get('SEQUENCE');
...[continue processing]...
$record->add(QUALITY_CHECK=>"OK");
$stream->write_record($record);
}
(如果你对 boulderio 格式有兴趣,可以在 http://stein.cshl.org/software/boulder/找到更多资讯以及操作它所需要的 Perl 函式库)
有趣的是,好几个资讯小组不约而同的发展出类似 boulderio 的主意。举例来说,好几个参予的小组蠕虫定序计划使用了一个资料交换格式叫做”.ace”。虽然这个格式一开始被设计用来作 ACE(一种生物资料用的数据库)数据库的资料倾印以及重复载入格式,可是它用了一个标签/值格式与 boulderio 很像。很快的,.ace档案被用 Perl 程序导管所处理,并且在最後一个步骤载入数据库。
Perlll 实验室管理的其他部分也找到用途。举个例子,许多中心,包括我的,使用以网页为基础的介面来显示专案状态,并且让研究者采取行动。Perl 文稿语言是写作网页 CGI 引擎的完美语言。同样的,Perl 执行邮件数据库查询服务器,管理定期的工作,准备每天晚上的实验室活动总结报告,建立控制机器人的指令档案,以其操作几乎每个忙碌的基因实验室都会需要的资讯管理工作。
就实验室管理来看,资讯核心小组合理的成功了。就发展与散布性的一般用途,事情就没有这麽乐观了。
这些问题与那些参与一个大型,松散的组织软件专案的人的问题将会很相似。尽管尽了最大的力,专案仍开始飘移。程序员进行那些令他们感兴趣的想法,需要互相沟通介面的模组被独立的设计,而且同样的问题被以不同的,不能相同的方法解决了好几次。当需要将所有部分放在一起的时刻来临,没有一个能够正常运作。这些情形也发生在基因计划上面。尽管事实是所有人都在同一个专案中工作,没有两个小组采用同样的解法。用来解决已知问题的程序被写了又写好几次。当不能保证一段程序片段工作的比其他地方发展出来的类似程序好的时候,你只能指望夸耀它特殊的使用者介面以及资料格式。一个典型的例子是重组数以千计的短 DNA reads 成为一个排序过的重叠片段的集合用的核心演算法,至少有六种不同版本在各地被使用,而且没有任何两个有相同的资料输入或输出格式。
这种缺乏交换性表现出基因中心的严重的困境。没有可交换性,一个资讯小组被锁住只能用他们自家发展的软件。如果其他基因中心做出更好的工具软件来解决同样的问题,前者必须重新更患他们的系统来使用这个新工具。
这个问题长远的解法是提出每个基因软件都该遵循的制式化的资料交换标准。这也让公用的模组可以轻易的被装入或卸下。然而,这样的标准需要时间使大家都认可,而当不同的小组间参与讨论与协商的时候,仍然有紧急的需求要用既有的工具来完成当下的任务。
这时候再度用到了 Perl 并且达成了紧急救援。剑桥高级会议引述这篇文章并且请求商业资料交换的问题。尽管事实上这两个小组的关系是亲密的合作者,而且粗浅的来看,似乎用同样的工具来解决同样的问题,但是再接近一点观察後可以发现他们做的事情没有一件是一样的。
在 DNA 定序专案中主要的软件元件有:
一个追踪编辑器,用来分析,显示小片段的来自DNA定序机器的 DNA reads 色层。
一个 read 组译器,找出 reads 之间重复的部分并且重组他们成为连续的区间。
一个组译器编辑器,观看组译器的结果并且在发现组译错误的时候能改变内容。
一个能够追踪以上一切的数据库。
经过数年时间,这两个小组已经分别开发出在他们手上可以顺利工作的套件。照著类似的基因中心模式,有些元件是自己发展而有些是从外面引进的。如图二所示, Perl 用来当作胶水,把这些软件片段组合在一起。在每对交互作用的模组之间,是一个或多个 Perl 文稿负责将某个元件的输出调整成另一个模组预期的样子。然而,当需要交换资料的时候来临,这两个小组遇到了困难。在他们两组之间,有两种追踪编程器,三种组译器,两种组译器编辑器以及(感谢上帝)一种数据库。如果两个元件之间需要两个 Perl 文稿的话(一个方向一个),会需要 62 个不同的文稿来满足所有可能的互相交换的工作。每次当其中一个模组的输出或输入格式改变,将要更动检查和修正 14 个文稿。
在这个会议中得的结论在图三。这两个小组决定采用一个共图的资料交换格式,叫做 CAF。CAF 将会包含双方的分析与编辑工具的的交集。对每个模组,有两个模组分别将 CAF 转换成该模组的资料格式,以及将其格式转换成 CAF。这简化了写程序以及维护的工作。现在只需要写 16 个文稿了;当其中一个模组改变了,只有两个模组需要跟著被检查。
这个事件并非独一无二的。Perl 已经变成基因中心的解决方案,当他们需要资料交换的时候,或是翻新某中心的模组来跟其他中心的一起工作的时候。
因此 Perl 已然成为基因中心之间计算的主要软件,就好像胶水将它们连结在一起。虽然基因资讯小组总是在思考有没有其他高阶语言,例如 Python,Tcl 还有最近的 Java,却没有能像 Perl 这样普及的。Perl 如何达成了这样的非凡成就?
我想有以下几个因素:
Perl 非常擅长於切割,扭转,绞,弄平,总结,以及其他的操作文字文件。虽然生物科学开始采用数用分析,然而大部分的资料仍然是文字文件:繁殖名称,注解,评住,目录查阅。甚至DNA序列也是类文字的。互相交换不相容的资料格式是在文字文件上用创造性的猜测来处理的议题。Perl强大的正规表示式(regular expression)比对以及字串操作使这个工作变得简单而没有其他语言能相比。
Perl 能容错。生物资料通常是不完全的,栏位可以被忽略,或是某个栏位被预期要出现好几次(举例来说,一个实验可能被重复的操作),或是资料以手动输入所以有错误。 Perl并不介意某个值是空的或是有奇怪的字元。正规表示式能够被写成取出并且更正错误的一般错误。当然这种弹性也可能是各坏处。我将会在之後提後。
Perl 是元件导向的。Perl 鼓励人们将他们的软件写成小模组,不问适用 Perl 函式库模组或是正统的 Unix 工具导向的方式。外部程序能够轻易的被整合进 Perl 程序,靠著管道(pipe),系统呼叫,或是插座(socket)。Perl5 引进的动态载入器允许人们使用 C 的函式,或者让整个编程过的函式库,被使用在 Perl 直译器中。最近的成果是世界各地的智慧结晶都会收录在一组模组里面,称为”bioPerl”(请参考 Perl Journal)
Perl 很容易去写并且能很快开发完。直译器让你不需要宣告你所有的函数型式以及资料型态,当未定义的函式被呼叫时只会引起一个错误,除错器也能与Emacs很好的合作并且让你能用令人舒服的交谈式的开发模式。
Perl 是良好的原型语言。因为它快而且脏(quick and dirty),用 Perl 建构新演算的原型比直接写成一个快的需要编程过的语言来的有意义。有时候发现结果是Perl已经够快了,所以程序变不需要移植;更多情形是某人可以用C写一个小的核心程序,编程成动态载入的模组或是外部的可执行程序,然後其他的部分用Perl来完成。这部分的例子可以参考 http://waldo.wi.mit.edu/ftp/distribution/software/rhmapper/)。
Perl 在写作网页 CGI 方面非常优秀,而且重要性随著各实验将资料发表在网络上之後更是增加。我在基因中心环境下使用 Perl 的经验从头到尾都是值得称赞的。然而我发现 Perl 也有它的问题。它的松散的程序风格导致许多错误,这些在其他严格的语言都会被抓到。举例来说,Perl 让你在一个变数在被指定值之前就能使用,这是个很有用的特性当你需要的时候,但是却是一个灾难当你单纯的打错了辨识名称。同样的,很容易忘记要宣告一个函式里面的区域变数,导致不小心地改到了全域变数。
最後,Perl 的不足之处在於建立图形化的使用者介面。虽然 Unix 忠实信徒所有事情都能在命令模式下完成,大多数的终端使用者却不同意。视窗,选单,弹跳的图案已经变成了必要的时尚。
直到最近,Perl 的使用者界面(GUI)发展仍是不成熟的。然而 Nick Ing-Simmons 的努力使得 perlTK(pTK) 的整合使得以 Perl 驱动的使用者介面在 X-window 上面成为可能。我的夥伴和我曾经在 MIT 基因中心写过几个 pTK 为基础的应用程序供互连网使用者,而且从头到尾都是一个令人满意的经验。其他的基因中心则更大规模的使用 pTK,在某些地方已经成为主要的生产力。
不幸的,我很难过的坦承,几个月以前当我需要将一个我写的 C++ 的图形分析系统放上去,我使用了标准的 Tcl/Tk 函式库而不是 pTK。我做了这个决定因为我希望这个应用程序能广泛流传。我发现 pTK 在输入方面仍然太不稳定:一个 pTK 的新发行版本发现 lurking 的问题。更进一步,我发现即使是经验丰富的系统管理者编程及安装 Perl 模组的时候也会遇到问题,而我担心在安装 pTK 或是我的应用程序所需要的 Perl 模组的时候遇到大问题,而就此放弃。相反的,许多系统拥有 Tcl/TK 函式库;即使没有,安装也是快又无痛的。
总之,当基因计划奠基在一片不相容的资料格式的海洋,快速变化的科技,以及庞大的,在发布当天就已时的资料分析程序上时。Perl 拯救了这一切。虽然它并不完美。 Perl 似乎明显的满足了许多基因中心需要,而且经常是当我们遇到问题时第一个想到的工具。