السلام عليكم,
عند تحليل البيانات في العادة نستعمل اكثر من أدات واحدة للحصول على النتيجة او النتائج النهائية . مثلا عند حساب التعبير الجيني يجب اولا ان نقوم بحساب جودة السلاسل باستعمال fastqc، بعدها نقوم بنزع المناطق ذات النوعية الرديئة (مثلا باستعمال Trimmomatic) ، ثم مطابقتها للجينوم المرجعي ثم حساب التعبير الجيني و القيام بتحاليل اخرى.
بطيعة الحال سوف نقوم بهذه الخطوات مرات عديدة على عينات مختلفة, وفي بعض الأحيان نحتاج الى تحسين الخطوات او استبدال الأدوات (مثلا استبدال Tophat بـ STAR).اذا كنت تكتب سكربتات باستعمال Bash فسوف تحتاج في كل مرة الى تغير اسم الملفات والمسارات مما يزيد نسبة الخطأ كلما زاد السكريبت تعقيدا. كما انك ستواجه عدة اشكاليات عند حدوث مشكلة في وسط خط التحليل, فلا تدري اين وقعت وهل الملفات الموجوة كاملة ام كتب بعضها فقط. مما يجبرك في بعض الاحيان الى اعادة القيام بالتحليل للتخلص من كل الشكوك.
لتسهيل عملية تصميم خطوات تحليل البيانات Data processing pipeline تم تطوير مجموعة من الأدوات. بعض هذه الأدوات لديه واجهة سهلة التحكم لكن لا تعطيك الحرية الكاملة في التصميم (مثلا Galaxy و Taverna) او لا تسمح لك بالقيام بعمليات متوازية ( Parallel Processing) . في المقابل, هناك ادوات تعطيك الحرية الكافية لكن تستلزم منك إلماما بلغة البرمجة المستعملة.
في هذا المقال سوف نقوم بالتعريف بالأدات Bpipe التي تتمركز في الوسط بين السهولة والحرية. يمكن تعريف Bpipe
على انها لغة برمجة لكتابة خطوط بيانات المعلوماتية الحيوية تتميز بسهولتها وليونتها نسبيا مقارنة بالأدوات المتوفورة. صممت Bpipe
باستعمال لغة الـ Groovy وهي لغة كائنية التوجه يمكن استعمالها كلغة سكربت لمنصة جافا وهي مشابهة لـ Perl او Python من حيث المبدأ.
التعريف بـ Bpipe
شخصيا من بين الخصائص التي تعجبني فيBpipe
هو سهولة تحويل سكريبتات Shell الى خطوات واضحة دون القيام بالكثير من التعديلات. يمكننا تلخيص خصائصBpipe
في النقاط التالية:
سهولة تعريف الخطوات | يمكن تحويل سكريبتات Shell بسهولة الى Bipipe |
الادارة المٌعاملاتية للخطوات | حيت يتم اعبار كل خطوة على انها مٌعاملة (Transaction). في حالة فشل الخطوة, يتم حذف الملفات التي تم انشاؤها و حفظ ملفات الـ log ويتم انهاء خط تحليل البيانات. |
الربط الاوتوماتيكي بين الخطوات | يقوم Bpipe بالربط الاوتوماتيكي بين مداخل ومخارج الخطوات المتتابعة, كما يسمح بالتسمية الاوتوماتيكية للمفات المنشأة في كل خطوة. |
سهولة اعادة تشغيل الخطوات | في حالة حدوث مشكلة في خطوة من الخطوات يمكن اعادة تشغيل خط تحليل البيانات من نقطة حدوث المشكل وليس اعادة التحليل من البداية. |
سهولة القيام بعمليات الحوسبة المتوازية | يسمح Bpipe بالتشغيل المتوازي للخطوات بحيث يمكن تحويل سكريبت Shellالى سكريبت متوازي دون القيام بأيت تغييرات جذرية. |
ارشفت الاوامر | يسمح Bpipe بارشفت الاوامر التي تم استعمالها خلال تنفيذ خط التشغيل مما يسهل عملية اكتشاف الاخطاء. |
دعمه للحوسبة الشبكية | يدعم Bpipe مجموعة من انظمة الحوسبة الشبكية (Grid computing) كـ Torque PBS, Oracle Grid Engine و LSF |
تنصيب Bpipe
لا يحتاج Bpipe
الى خطوات معقدة لتنصيبه, فقط يجب تحميله من github بعدها فك الضغط و اضافة مساره الى الـ PATH
. بالطبع ننوه هنا ان Bpipe
يعمل فقط على انظمة Linux و MacOS, اما في حالة الـ Windows يجب تنصيب مكتبة الـ Cygwin لكن ربما لن تستفيد من كل الخصائص. اذا كنت تعمل في مجال المعلوماتية الحيوية او المجالات المشابهة فهناك احتمال كبير لاستعمالك للنيكس نظرا لتوفر العديد من الادوات في تلك البيئة.
لغة Bpipe
لا يهدف Bpipe
الى تعريف لغة جديدة تحل محل سكربيتات Shell لكنها توفر مجموعة من الاوامر تسهل لك استعمال اوامر Shell استعمالا افضل. كما نوهنا سابقا, يعتمد Bpipe
على لغة Groovy و التي هي لغة سكريبت مشتقة من جافا. يهدف Bpipe
الى تعريف مجموعة من الاوامر البسيطة عن طريق تعريف الخطوات (stages) و الربط بينها من اجل تصميم خطوط تحليل البيانات (pipeline).
تُعَرف كل خطوة في Bpipe
بالشكل المبين في المثال التالي:
stage_name = { exec "shell command to execute your pipeline stage" }
حيث يمثل stage_name
اسم الخطوة و يتم وضع امر الـ Shell في الجملة التي تلي امر exec
. اذا كان امر الـ Shell طويلا او يحتوي على مجموعة من الاوامر فيتحسن كتابة ثلاث علامات اقتباس """
بعد امر exec
.
بعد تعريف الخطوات, يمكن تحديد ترتيب تنفذيد الخطوات بالستعمال امر run
كما هو موضح في المثال التالي:
hello = { // An exec with single quotes exec "echo 'Hello'" } world = { // An exec with triple quotes exec """ echo 'World' """ } run { hello + world }
من اجل تنفيذ هذا المثال, يمكنك حفظه في ملف مثلا mypipeline.groovy
ثم تقوم بتشغيله كالتالي:
bpipe run mypipeline.groovy
سوف تتحصل على النتيجة التالية:
==================================================================================================== | Starting Pipeline at 2016-05-14 19:00 | ==================================================================================================== =========================================== Stage hello ============================================ Hello =========================================== Stage world ============================================ World ======================================= Pipeline Succeeded ======================================== 19:00:27 MSG: Finished at Sat May 14 19:00:27 CST 2016
التعامل مع مداخل ومخارج الخطوات
بطبيعة الحال عند كتابة انابيب تحليل البيانات الحقيقية نحتاج الى تحديد الملفات المستعملة كمَدخل ومَخرج لكل خطوة. يقوم Bpipe
اتوماتيكيا بتعريف المتغيريين input
و output
عند بداية كل خطوة, بحيث تحتوي input
على مسار الملفات المستعملة في الخطوة الحالية و output
تحتوي على اسماء الملفات المنتجة في الخطوة التي هي في طور التنفيذ.
عند ربط الخطوات مع بعضها البعض يقوم Bpipe
بتحويل output
الخطوة السابقة الى input
الخطوة الحالية. بطبيعة الحال يمكن تحديد الملفات التي نريد استقبالها و الملفات التي نريد ارسالها للخطوات التي تاتي من بعد, كما يمكن الاستغناء عن المتغيرين input
و output
و كتابة اسماء الملفات كاملة, لكن هذه الطريقة غير محبذة لانها تعيدنا الى نقطة الصفر.
لنأخذ مثلا المثال التالي:
hello = { exec "echo Hello | cat - $input > $output" } world = { exec "echo World | cat $input - > $output" } run { hello + world }
الذي يهدف الى اضافة كلمة Hello الى محتوى ملف وكتابته في ملف جديد, بعدها نضيف كلمة World و نحفظها في ملف جديد و الذي يمثل النتيجة النهائية. من اجل تنفيذ هذا الانبوب, نقوم بانشاء الملف input1.txt و نمرره لسكربنتا.
touch input1.txt bpipe run mypipeline.goovy input1.txt
في هذا المثال بما اننا لم نحدد اسم الملفات في الـ output
في كلا المرحلتين , سيقوم Bpipe
بتسميتهما اوتوماتيكيا حيث يسمي الملف الناتج عن المرحلة الاولى بـ : input1.txt.hello
والثاني بـ: input1.txt.hello.world
.
من اجل التسمية الاوتوماتيكية للملفات المنتجة في كل مرحلة يمكن استعمال عدة اوامر:
1. امر Filter
يسمح لك هذا الامر باظافة كلمة (او جمل) لاسم الملف لكن مع الحفاظ على نفس نوع الـ extension لملف الـ input
. مثلا اذا كتبت:
remove_comments = { filter("nocomments") { exec """ grep -v '^#' $input > $output """ } } run { remove_comments }
في هذا المثال مثلا اذا كانت الـ input
مثلا myinput.txt
سوف يقوم Bpipe
بحدف كل الاسطر التي تبدأ بـ #
ثم انشاء ملف جديد اسمه myinput.nocomments.txt
.
2.امر transform
يقوم هذا الامر بالمحافظة على اسم ملف الدخول لكن يغير الـ extension. مثلا اذا كانت الـ input
مثلا myinput.txt
وكان لديك مرحلة (او stage) يقوم بإنتاج ملف من نوع csv سوف يكون اسم الـ output
هو myinput.csv
.
في هذا المثال سوف نستعمل امري filter
و transform
من اجل حذف التعليقات ثم تحويلها الى csv.
remove_comments = { filter("nocomments") { exec """ grep -v '^#' $input > $output """ } } convert_to_csv = { transform("csv") { // bash command is: tr "\\t" "," exec """ cat $input | tr "\\\\t" "," > $output """ } } run { remove_comments + convert_to_csv }
3.امر produce
في بعض الاحيان, خاصة اذا كانت اسماء الملفات الناتجة ليس لها علاقة كبيرة باسم الملف في الـ input
او كانت تسمية لها علاقة معقدة اكثر من فقط اظافة كلمة (كامر filter) او تغير extension الملف نقوم باستعمال الامر produce. مثلا في هذا المثال نقوم بانتاج ملفي و bar.txt.
basic_produce = { produce ("foo.txt","bar.txt") { exec """ echo Hello > $output1; echo World > $output2; """ } } run { basic_produce }
4. امر forward
يستعمل امر forward لتحديد الملف الذي نريد تمريره الى الخطوات القادمة . مثلا اذا كنت لدينا خطوة نقوم فيها باستعمال برنامج FastQC
لحساب بعض معايير الجودة في ملف fastq ثم بعدها نريد استعمال برنامج Trimmomatic
لنزع الجزيئات القاعدية ذات النوعية الرديئة او التي تم سلسلتها من الـ Adapters و ليس من الجينوم.
في هذه الحالة الـ output
التي نريد تمريها بعد نهاية برنامج FastQC
ملف الـ fastqc الذي مرر كـ input
و ليس الملفات الناتجة عن برنامج FastQC
. يمكننا تلخيض ذلك في السكريبت.
fastqc = { exec "fastqc $input" forward $input } trim = { filter("trim") { exec """ trimmomatic SE -phred33 $input $output.gz \ ILLUMINACLIP:TruSeq2-SE.fa:2:30:10 \ TRAILING:20 LEADING:20 MINLEN:35; """ } } run { fastqc + trim }
4. تحديد extension الملفات
في بعض الاحيان نريد ان تستقبل خطوة من الخطوات نوعية محددة من الملفات (مثلا, فقط ملفات bam). يمكننا تحديد ذلك بكتابة الـ extension مع الـ input
كما هو موضع في المثال التالي الذي نريد فيه صناعة index لملف من نوع bam.
index_bam = { transform("bam") to ("bam.bai") { exec "samtools index $input.bam" } forward input } run { index_bam }
فهنا كتبنا $input.bam
من اجل اخبار bpipe
باننا نريد استقبال ملف من نوع bam.
هناك العديد من الخصائص الاخرى يمكن للقارىء المهتم ان يتعلمها من موقع bpipe لكن اظن ان هذه الاوامر تكفي للقيام بالعديد من الاشياء.
القيام بعمليات الحوسبة المتوازية
من بين الخصائص التي تستهوي مستعملي bpipe هو سهولة القيام بعمليات متوازية بدون الحاجة الى تغيير السكربت مما يسمح لنا بمعالجة العديد من الملفات بنفس السكربت. يمكن تحديد الخطوات المتوازية بوضعها بين علامتي []
يتم تقسم العمليات المتوازية الى نوعين:
- عمليات منفصلة: وهي العمليات المستقلة عن بعضها البعض والترتيب غير مهم عند ادائها, يمكن الفصل بينها باستعمال الفاصلة للفصل بين العمليات المستقلة.
مثلا في مثال FastQC و Trimmomatic لا توجد علاقة بين نتائج البرنامجين لكنها يستعملان نفس الملفات يمكننا اذن كتابة
run { [ fastqc , trim ] }
مثلا اذا كان لدينا الملفات: expr1.fastq.gz و expr2.fastq.gz سوف يقوم Bpipe بانشاء اربعة عمليات متوازية, اثنان fastqc و اثنان trim.
- عمليات متصلة: وهي العمليات التي المرتبطة ببعضها البعض و لايمكن الشروع في الخطوة التالية قبل نهاية الخطوة الحالية ويمكن استعمال رمز + لتحديدالترابط.
مثلا في هذا المثال نريد ان نرتب الـ reads في مجموعة ملفات bam وذلك لانشاء index لكل ملف و القيام ببعض الاخصائيات. لكن بما ان عملية الـ indexing تتطلب ملفا مرتبا على حسب الاحداثيات الجينومية, هناك ترابط بين هذين الخطوتين كما ان عملية حساب الاحصائيات تتطلب ملف bam مرتب ولديه index . لهذا, اذا كان لدينا مجموعة من ملفات bam, سوف نعالج كل ملفعلى حدى, لكن كل عملية متوازية تقوم بثلاث خطوات. المثال التالي يوضح ذلك.
sort_bam = { filter("sorted") { exec "samtools sort $input.bam $output.prefix" } } index_bam = { transform("bam") to ("bam.bai") { exec "samtools index $input.bam" } forward input } mapping_stats { transform("bam") to ("index_stats.txt"){ exec "samtools idxstats $input.bam > $output" } } run { [ sort_bam + index_bam + mapping_stats ] }
تحديد طريقة تقسيم الملفات بين المهام المتوازية
مثلا لو كان لدينا الملفات التالية:
. ├── expriment_1_R1.fastq.gz ├── expriment_1_R2.fastq.gz ├── expriment_2_R1.fastq.gz └── expriment_2_R2.fastq.gz
نلاحظ انه لدينا ملفان R1 و R2 لكل تجربة يمثلان نتائج السلسلة باستعمال Pair-end Sequencing. بما اننا نريد ان نقوم بتحليل هذه البيانات بطريقة متوازية نريد ان يعالج الملفان expriment_1_R1.fastq.gz
و expriment_1_R2.fastq.gz
معا و الملفات expriment_2_R1.fastq.gz
و expriment_2_R2.fastq.gz
معا.
لتحديد طريقة التقسيم يمكننا استعمال التعابير القياسية التالية :
- الرمز %: لاخبار
Bpipe
باننا نريد استعمال المنطقة التي تَحل مَحل الرمز % من اجل التقسيم الى مجموعات. - الرمز *: اخبار
Bpipe
بان هذه المنطقة متغيرة لكن لا تحدد طريقة التقسيم.
مثلا من اجل معالجة ملفات كل تجربة على حدى يمكننا كتابة expriment_%_R*.fastq.gz
كما هو موضح في المثال التالي:
trim_PE = { filter("trim","trim") { exec """ trimmomatic PE -phred33 $input1.gz $input2.gz $output1.gz ${output1.prefix}.unpaired.gz $output2.gz ${output2.prefix}.unpaired.gz LEADING:15 TRAILING:15 SLIDINGWINDOW:5:15 MINLEN:30 """ } } run { "expriment_%_R*.fastq.gz" * [ trim_PE ] }
دعم الحوسبة الشبكية (Gird computing)
في العادة البيانات التي نتعامل معها تكون ملفات كبيرة و لمعالجتها نحتاج مساحة ذاكرة كبيرة و عدد كبير من المعالجات, لهذا تستعمل الكثير من مخابر المعلوماتية الحيوية نظم الحوسبة الشبكية. يدعم Bpipe الثلاثة انواع الاكثر تداولا من الشبكات: Torque PBS, Oracle Grid Engine و LSF.
من اجل تفعيل الدعم, يجب انشاء ملف بإسم bpipe.config
في نفس المجلد الذي نريد منه تشغيل Bpipe
ثم تحديد نوع الشبكة وكمية المساحة المراد استعمالها وعدد المعالجات المطلوبة. مثلا في هذا المثال نستعمل Oracle Grid Engine.
executor="sge" sge_request_options="-l h_vmem=30G -l p=32 -N myBigAnalysis"
تعريف المتغيرات
بما ان Bpipe
مبني باستعمال لغة الـ Groovy يمكن كتابة سكربيتات معقدة تحتوي على المتغيرات و العبارات الشرطية و كل مايستطيع Groovy القيام به. هناك نوعين من المتغيرات:
- المتغيرات المحلية (local variables): وهي متغيرات خاصة بكل خطوة يتم تعريفها باستعمال امر def او امر var اذا كنا نريد استعمالها كـ command line parameter variable.
- المتغيرات العامة (global variables): وهي متغيرات مشترك بين كل الخطوات ويتم تعريفها بدون اسعمال كلمة def. مثلا مسار الجينوم المستعمل, ربما سوف نحتاجه في العديدمن الخطوات, لهذا يمكنا تعريفه كمتغير عام.
ليكن لدينا المثال التالي:
global="man" hello = { var greetings : "Hello" exec "echo $greetings , $global" } world = { var name : "Earth" exec "echo welcom to $name , $global" } run{ hello + world }
اذا شغلنا هذا السكربت بدون تحديد قيم المتغيرات سوف نتحصل على :
$bpipe run mypipeline.groovy Hello , man welcom to Earth , man
اذا اردنا تغيير قيمة المتغيرين greetings
و name
يمكننا استعمال -p
كما هو موضح في المثال التالي:
$bpipe run -p greetings="Good morning" -p name="Mars" mypipeline.groovy Good morning , man welcom to Mars , man
انشاء التقارير
يمكننا Bpipe من انشاء تقارير تلخص طريقة خط تحليل البيانات و الوقت المستغرق في كل خطوة. يمكن تفعيل خاصية التقارير باستدعاء Bpipe باستعمال -r
. يمكن ايضا اضافة معلومات في كل خطوة تشرح دور الخطوة و المتغيرات المستعملة و اسم الشخص الذي كتبها ... الخ من العلومات. هنا مثال يوصح هذا الامر.
about title: "A simple pipeline to align paired reads" REFERENCE_GENOME = "hg19.fa" align_bwa = { doc title: "Align DNA reads with bwa mem", desc: "Use bwa mem to align reads on the reference genome.", constraints: "Input must be compressed (fastq.gz)", author: "me@gmail.com" transform("bam") { exec """ bwa mem $REFERENCE_GENOME $input1.fgz $input2.fgz | samtools view -bSu - | samtools sort - $output.bam.prefix; """ } }
يمكن تشغيل هذا الملف باستعمال:
bpipe run -r mypipeline.groovy
اعادة التشغيل من نقطة الخطأ
من بين اهم خصائص Bpipe
هي القدرة على اتمام العمل من نقطة الخطأ. مثلا اذا كان لديك 5 خطوات وحدث مشكل في الخطوة الثالثة, يمكن اصلاع الخطأ في الخطوة الثالثة ثم استعمال امر retry
بدلا من run
من اجل الاستكمال من الخطوة الثالثة.
bpipe retry
خلاصة
في هذا المقال عرفنا ببعض خصائص Bpipe وبينا طرق استعماله و بعض المزايا التي تجعل من ادات مفيدة للتعريف خطوط البيانات. تعلمنا كيفية انشاء خطوط بيانات متوازية وكيفية استعمال الحوسبة الشبكية وغيره من المهارات التي تمكننا من استعمال Bipe. لكن هذا المقال يعتبر فقط مقدمة في التعريف بـ Bpipe, يمكن التعرف اكثر على خصائصه Bpipe عند طريق استعماله والاطلاع الى المصادر اسفله.
في الأخير اتمنى ان يكون هناك من استفاد من هذا المقال.
مصادر
- Sadedin SP, Pope B, Oshlack A: Bpipe : a tool for running and managing Bioinformatics pipelines. Bioinformatics. 2012.
- Bpipe documentation (http://bpipe-test-documentation.readthedocs.io/en/latest/)
- Bpipe workshop (https://github.com/tucano/bpipe_workshop)
رابط المقالة : المعلوماتية الحيوية بالعربية » انشاء خطوط تحليل البيانات باستعمال bpipe