Bölüm 2: Gerçek pipeline'ları çalıştırma¶
Yapay Zeka Destekli Çeviri - daha fazla bilgi ve iyileştirme önerileri
Bu kursun 1. Bölümünde (Temel İşlemleri Çalıştırma), kod karmaşıklığını düşük tutmak için yalnızca minimal özelliklere sahip örnek bir workflow ile başladık.
Örneğin, 1-hello.nf bir seferde tek bir değer sağlamak için komut satırı parametresi (--input) kullandı.
Ancak, gerçek dünya pipeline'larının çoğu, büyük miktarda veriyi ölçekte verimli bir şekilde işlemek ve bazen karmaşık mantıkla birbirine zincirlenen birden fazla işleme adımı uygulamak için daha sofistike özellikler kullanır.
Eğitimin bu bölümünde, orijinal Hello World pipeline'ının genişletilmiş versiyonlarını deneyerek gerçek dünya pipeline'larının temel özelliklerini gösteriyoruz.
1. Bir dosyadan girdi verilerini işleme¶
Gerçek dünya pipeline'larında, tipik olarak bir veya daha fazla girdi dosyasında bulunan birden fazla veri noktasını (veya veri serisini) işlemek istiyoruz. Ve mümkün olduğunda, analiz için harcanan süreyi kısaltmak için bağımsız verilerin işlenmesini paralel olarak çalıştırmak istiyoruz.
Nextflow'un bunu nasıl yaptığını göstermek için, gerçek bir veri analizinde işlemek isteyebileceğiniz türden sütunlu verileri taklit eden birkaç girdi selamlama içeren greetings.csv adlı bir CSV dosyası hazırladık.
Sayıların anlamlı olmadığını, sadece açıklama amaçlı olduğunu unutmayın.
Ayrıca, CSV dosyasını okuyacak, selamlamaları çıkaracak ve her birini ayrı bir dosyaya yazacak olan 2a-inputs.nf adlı orijinal workflow'un geliştirilmiş bir versiyonunu yazdık.
Önce workflow'u çalıştıralım ve ardından ilgili Nextflow koduna bakacağız.
1.1. Workflow'u çalıştırın¶
Terminalinizde aşağıdaki komutu çalıştırın.
Komut çıktısı
Heyecan verici bir şekilde, bu process için '3 of 3' çağrının yapıldığını gösteriyor gibi görünüyor, bu cesaret verici, çünkü girdi olarak sağladığımız CSV'de üç veri satırı vardı.
Bu, sayHello() process'inin her girdi satırında bir kez olmak üzere üç kez çağrıldığını gösteriyor.
1.2. Yayınlanan çıktıları results dizininde bulun¶
Workflow'umuzun hala çıktılarımızın bir kopyasını oraya yazıp yazmadığını görmek için 'results' dizinine bakalım.
Dizin içeriği
Evet! Yeterince uygun bir şekilde farklı adlara sahip üç çıktı dosyası içeren 2a-inputs adlı yeni bir dizin görüyoruz.
Uygun selamlama dizesini içerdiklerinden emin olmak için her birini açabilirsiniz.
Dosya içeriği
Bu, girdi dosyasındaki her selamlamanın uygun şekilde işlendiğini doğrular.
1.3. Orijinal çıktıları ve logları bulun¶
Yukarıdaki konsol çıktısının yalnızca bir görev dizinine atıfta bulunduğunu fark etmiş olabilirsiniz.
Bu, sayHello() çağrısının üçünün de bu tek görev dizininde yürütüldüğü anlamına mı geliyor?
1.3.1. Terminalde verilen görev dizinini inceleyin¶
8e/0eb066 görev dizininin içine bakalım.
Yalnızca selamlamalardan birine karşılık gelen çıktıyı buluyoruz (gizli dosyaların görüntülenmesini etkinleştirirsek yardımcı dosyaları da).
Peki ne oluyor?
Varsayılan olarak, ANSI loglama sistemi aynı process'e yapılan tüm çağrılar için durum bilgisini aynı satıra yazar.
Sonuç olarak, konsol çıktısında bize üç görev dizini yolundan yalnızca birini (8e/0eb066) gösterdi.
Orada listelenmeyen iki tane daha var.
1.3.2. Terminalin daha fazla ayrıntı göstermesini sağlayın¶
Process çağrılarının tam listesini görmek için loglama davranışını aşağıdaki gibi komuta -ansi-log false ekleyerek değiştirebiliriz:
Komut çıktısı
Bu sefer çıktıda üç process çalıştırmasını ve ilişkili çalışma alt dizinlerini görüyoruz. ANSI loglamasını devre dışı bırakmak, Nextflow'un terminal çıktısında renk kullanmasını da engelledi.
Durumun iki loglama modu arasında biraz farklı raporlandığına dikkat edin. Yoğunlaştırılmış modda, Nextflow çağrıların başarıyla tamamlanıp tamamlanmadığını raporlar. Bu genişletilmiş modda, yalnızca gönderildiklerini raporlar.
Bu, sayHello() process'inin üç kez çağrıldığını ve her biri için ayrı bir görev dizini oluşturulduğunu doğrular.
Orada listelenen her görev dizininin içine bakarsak, her birinin selamlamalardan birine karşılık geldiğini doğrulayabiliriz.
Dizin içeriği
Bu, her process çağrısının diğerlerinden izole olarak yürütüldüğünü doğrular. Bunun, process'in benzersiz olmayan adlara sahip ara dosyalar üretmesi durumunda çakışmaları önlemek de dahil olmak üzere birçok avantajı vardır.
İpucu
Karmaşık bir workflow veya çok sayıda girdi için, tam listenin terminale çıktı verilmesi biraz bunaltıcı olabilir, bu nedenle insanlar normalde rutin kullanımda -ansi-log false kullanmazlar.
1.4. Workflow kodunu inceleyin¶
Bu workflow versiyonu bir CSV girdi dosyasını okuyabilir, girdileri ayrı ayrı işleyebilir ve çıktıları benzersiz şekilde adlandırabilir.
Workflow kodunda bunu mümkün kılan şeylere bir göz atalım.
Tam kod dosyası
Yine, kod sözdizimini ezberlememeniz gerekmez, ancak önemli işlevsellik sağlayan workflow'un temel bileşenlerini tanımayı öğrenmek iyidir.
1.4.1. CSV'den girdi verilerini yükleme¶
En ilginç kısım şudur: komut satırından tek bir değer almaktan, bir CSV dosyası almaya, ayrıştırmaya ve içerdiği bireysel selamlamaları işlemeye nasıl geçtik?
Nextflow'da bunu bir channel ile yapıyoruz: girdileri verimli bir şekilde işlemek ve çok adımlı workflow'larda bir adımdan diğerine taşımak için tasarlanmış, yerleşik paralellik ve birçok ek avantaj sağlayan bir yapı.
Parçalayalım.
| 2a-inputs.nf | |
|---|---|
Bu kod, CSV dosyasını okuyan, ayrıştıran ve her satırdan ilk sütunu çıkaran greeting_ch adlı bir channel oluşturur.
Sonuç, Hello, Bonjour ve Holà içeren bir channel'dır.
Bu nasıl çalışır?
Bu satırın düz İngilizce'de anlamı şudur:
channel.fromPath, dosya yollarından bir channel oluşturan bir channel factory'dir(params.input), dosya yolunun komut satırında--inputile sağlandığını belirtir
Başka bir deyişle, bu satır Nextflow'a şunu söyler: --input ile verilen dosya yolunu al ve içeriğini girdi verisi olarak işlemeye hazırlan.
Sonra, sonraki iki satır dosyanın gerçek ayrıştırmasını yapan ve verileri uygun veri yapısına yükleyen operatörleri uygular:
.splitCsv()Nextflow'a CSV dosyasını satırları ve sütunları temsil eden bir diziye ayrıştırmasını söyler.map { line -> line[0] }Nextflow'a her satırdan yalnızca ilk sütundaki elemanı almasını söyler
Yani pratikte, aşağıdaki CSV dosyasından başlayarak:
Bunu şuna benzer bir diziye dönüştürdük:
Ve sonra üç satırın her birinden ilk elemanı aldık ve artık Hello, Bonjour ve Holà içeren bir Nextflow channel'ına yükledik.
Channel'ları ve operatörleri derinlemesine anlamak istiyorsanız, bunları kendiniz nasıl yazacağınız da dahil, Hello Nextflow Bölüm 2: Hello Channels bölümüne bakın.
1.4.2. Her selamlamada process'i çağırma¶
Sonra, workflow'un main: bloğunun son satırında, yüklenen greeting_ch channel'ını sayHello() process'ine girdi olarak sağlıyoruz.
| 2a-inputs.nf | |
|---|---|
Bu, Nextflow'a process'i channel'daki her eleman üzerinde, yani her selamlamada bireysel olarak çalıştırmasını söyler. Ve Nextflow bu kadar akıllı olduğundan, mevcut hesaplama altyapısına bağlı olarak bu process çağrılarını mümkünse paralel olarak çalıştıracaktır.
Çok sayıda veriyi (birçok örnek veya veri noktası, araştırma biriminiz ne olursa olsun) karşılaştırmalı olarak çok az kodla verimli ve ölçeklenebilir bir şekilde bu şekilde işleyebilirsiniz.
1.4.3. Çıktılar nasıl adlandırılır¶
Son olarak, çıktı dosyalarının benzersiz şekilde adlandırılmasını nasıl sağladığımızı görmek için process koduna hızlıca bakmaya değer.
| 2a-inputs.nf | |
|---|---|
Gördüğünüz gibi, 1-hello.nf'deki bu process versiyonuna kıyasla, çıktı bildirimi ve komutun ilgili kısmı, selamlama değerini çıktı dosya adına dahil edecek şekilde değişti.
Bu, ortak results dizinine yayınlandıklarında çıktı dosya adlarının çakışmamasını sağlamanın bir yoludur.
Ve process bildiriminde yapmak zorunda olduğumuz tek değişiklik bu!
Özet¶
Channel'ların ve operatörlerin birden fazla girdiyi verimli bir şekilde işlememizi nasıl sağladığını temel düzeyde anlıyorsunuz.
Sırada ne var?¶
Çok adımlı workflow'ların nasıl oluşturulduğunu ve nasıl çalıştığını keşfedin.
2. Çok adımlı workflow'ları çalıştırma¶
Gerçek dünya workflow'larının çoğu birden fazla adım içerir. Channel'lar hakkında öğrendiklerimizi temel alarak, Nextflow'un çok adımlı bir workflow'da process'leri birbirine bağlamak için channel'ları ve operatörleri nasıl kullandığına bakalım.
Bu amaçla, aşağıdakileri gösteren, üç ayrı adımı birbirine zincirleyen örnek bir workflow sağlıyoruz:
- Bir process'ten diğerine veri akışı sağlama
- Birden fazla process çağrısından gelen çıktıları tek bir process çağrısında toplama
Özellikle, her girdi selamlamasını alan, büyük harfe dönüştüren ve ardından tüm büyük harfli selamlamaları tek bir çıktı dosyasında toplayan 2b-multistep.nf adlı genişletilmiş bir workflow versiyonu yaptık.
Daha önce olduğu gibi, önce workflow'u çalıştıracağız, ardından yeni olan şeyi görmek için koda bakacağız.
2.1. Workflow'u çalıştırın¶
Terminalinizde aşağıdaki komutu çalıştırın:
Komut çıktısı
Gördüğünüz gibi, vaat edildiği gibi, workflow'un bir parçası olarak birden fazla adım çalıştırıldı; ilk ikisi (sayHello ve convertToUpper) muhtemelen her bir selamlamada çalıştırıldı ve üçüncüsü (collectGreetings) yalnızca bir kez, üç convertToUpper çağrısının çıktılarında çalıştırıldı.
2.2. Çıktıları bulun¶
Gerçekten olan şeyin bu olduğunu results dizinine bakarak doğrulayalım.
Dizin içeriği
Gördüğünüz gibi, 2b-multistep adında yeni bir dizinimiz var ve öncekinden çok daha fazla dosya içeriyor.
Dosyaların bazıları intermediates adlı bir alt dizinde gruplandırılmış, iki dosya ise üst düzeyde bulunuyor.
Bu ikisi, çok adımlı workflow'un nihai sonuçlarıdır. Dosya adlarına bakıp beklediğiniz gibi olduklarını doğrulamak için içeriklerini kontrol etmek üzere bir dakikanızı ayırın.
Dosya içeriği
İlki, vaat edildiği gibi büyük harfe dönüştürülmüş ve tek bir dosyada toplanmış üç selamlamamızı içeriyor. İkincisi, çalıştırma hakkında bazı bilgileri özetleyen bir rapor dosyasıdır.
2.3. Kodu inceleyin¶
Koda bakalım ve çok adımlı workflow'lar için temel kalıpları tanımlayalım.
Tam kod dosyası
| 2b-multistep.nf | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | |
Orada çok şey oluyor, ancak önceki workflow versiyonuna kıyasla en belirgin fark, şimdi birden fazla process tanımının olması ve buna bağlı olarak workflow bloğunda birkaç process çağrısının olmasıdır.
Daha yakından bakalım ve en ilginç parçaları tanımlayabilecek miyiz görelim.
2.3.1. Workflow yapısını görselleştirme¶
Nextflow uzantısıyla VSCode kullanıyorsanız, herhangi bir Nextflow betiğinde workflow bloğunun hemen üzerinde görüntülenen küçük DAG preview bağlantısına tıklayarak process'lerin nasıl bağlandığına dair yararlı bir diyagram alabilirsiniz.
Bu size process'lerin nasıl bağlandığına ve ne ürettiklerine dair güzel bir genel bakış sunar.
Orijinal sayHello process'ine ek olarak, şimdi konsol çıktısında gördüğümüz process'lerin adlarıyla eşleşen convertToUpper ve collectGreetings'in de olduğunu görüyorsunuz.
İki yeni process tanımı, sayHello process'i ile aynı şekilde yapılandırılmıştır, ancak collectGreetings batch adlı ek bir girdi parametresi alır ve iki çıktı üretir.
Her birinin koduna ayrıntılı olarak girmeyeceğiz, ancak merak ediyorsanız, ayrıntıları Hello Nextflow Bölüm 2'de bulabilirsiniz.
Şimdilik, process'lerin birbirine nasıl bağlandığını inceleyelim.
2.3.2. Process'ler nasıl bağlanır¶
Burada bakılması gereken gerçekten ilginç şey, process çağrılarının workflow'un main: bloğunda nasıl birbirine zincirlendiğidir.
İlk process çağrısı olan sayHello(greeting_ch)'nin değişmediğini görebilirsiniz.
Sonra, convertToUpper'a yapılan sonraki process çağrısı, sayHello'nun çıktısına sayHello.out olarak atıfta bulunur.
Kalıp basit: processName.out bir process'in çıktı channel'ına atıfta bulunur ve bu doğrudan sonraki process'e geçirilebilir.
Nextflow'da verileri bir adımdan diğerine bu şekilde taşıyoruz.
2.3.3. Bir process birden fazla girdi alabilir¶
Üçüncü process çağrısı olan collectGreetings biraz farklıdır.
| 2b-multistep.nf | |
|---|---|
Bu çağrıya convertToUpper.out.collect() ve params.batch olmak üzere iki girdi verildiğini görüyorsunuz.
Şimdilik .collect() kısmını göz ardı edersek, bunu collectGreetings(input1, input2) olarak genelleyebiliriz.
Bu, process modülündeki iki girdi bildirimiyle eşleşir:
Nextflow bunu ayrıştırdığında, çağrıdaki ilk girdiyi path input_files'a, ikinciyi val batch_name'e atayacaktır.
Böylece artık bir process'in birden fazla girdi alabileceğini ve workflow bloğundaki çağrının nasıl göründüğünü biliyorsunuz.
Şimdi ilk girdiye daha yakından bakalım, convertToUpper.out.collect().
2.3.4. collectGreetings çağrısında collect() ne yapar¶
sayHello'nun çıktısını convertToUpper'a geçirmek için, sayHello'nun çıktı channel'ına sayHello.out olarak atıfta bulunduk. Ancak bir sonraki adım için convertToUpper.out.collect() referansı görüyoruz.
Bu collect() kısmı nedir ve ne yapar?
Bu elbette bir operatördür. Daha önce karşılaştığımız splitCsv ve map operatörleri gibi.
Bu sefer operatör collect olarak adlandırılır ve convertToUpper tarafından üretilen çıktı channel'ına uygulanır.
collect operatörü, aynı process'e yapılan birden fazla çağrıdan gelen çıktıları toplamak ve tek bir channel elemanına paketlemek için kullanılır.
Bu workflow bağlamında, convertToUpper.out channel'ındaki üç büyük harfli selamlamayı --bunlar üç ayrı channel öğesidir ve normalde sonraki process tarafından ayrı çağrılarda işlenirler-- alıp tek bir öğeye paketliyor.
Daha pratik terimlerle: collectGreetings()'e beslemeden önce convertToUpper()'ın çıktısına collect() uygulamasaydık, Nextflow basitçe collectGreetings()'i her selamlamada bağımsız olarak çalıştırırdı, bu da amacımıza ulaşmazdı.
Buna karşılık, collect() kullanmak, workflow'un ikinci adımı tarafından üretilen tüm ayrı büyük harfli selamlamaları almamıza ve pipeline'ın üçüncü adımında tek bir çağrıya hepsini birlikte beslememize olanak tanır.
Tüm selamlamaları aynı dosyaya bu şekilde geri alıyoruz.
Process çağrıları arasında channel içeriklerine dönüşümler uygulamak için birçok başka operatör mevcuttur.
Bu, pipeline geliştiricilerine pipeline'larının akış mantığını özelleştirmek için çok fazla esneklik sağlar. Dezavantajı, bazen pipeline'ın ne yaptığını çözmeyi zorlaştırabilmesidir.
2.3.5. Bir girdi parametresinin varsayılan değeri olabilir¶
collectGreetings'in ikinci bir girdi aldığını, params.batch'i fark etmiş olabilirsiniz:
| 2b-multistep.nf | |
|---|---|
Bu, workflow'a --batch adlı bir CLI parametresi geçirir.
Ancak, workflow'u daha önce başlattığımızda bir --batch parametresi belirtmedik.
Burada ne oluyor?
params bloğuna bir göz atın:
Workflow'da yapılandırılmış bir varsayılan değer var, bu yüzden sağlamamız gerekmiyor. Ancak komut satırında bir tane sağlarsak, belirttiğimiz değer varsayılan yerine kullanılacaktır.
Deneyin:
Komut çıktısı
Özel batch adınızla adlandırılmış yeni nihai çıktılar görmelisiniz.
Dizin içeriği
Bu, Bölüm 3'te daha ayrıntılı olarak ele alacağımız girdi yapılandırmasının bir yönüdür, ancak şimdilik önemli olan girdi parametrelerine varsayılan değerler verilebileceğini bilmektir.
2.3.6. Bir process birden fazla çıktı üretebilir¶
collectGreetings process tanımında aşağıdaki çıktı bildirimlerini görüyoruz:
| 2b-multistep.nf | |
|---|---|
Bunlara daha sonra publish: bloğunda emit: ile verilen adla atıfta bulunulur:
| 2b-multistep.nf | |
|---|---|
Bu, belirli çıktıları çeşitli operatörlerle birlikte workflow'daki diğer process'lere bireysel olarak geçirmeyi kolaylaştırır.
2.3.7. Yayınlanan çıktılar organize edilebilir¶
output bloğunda, workflow'un yalnızca nihai çıktılarını seçmeyi kolaylaştırmak için ara sonuçları gruplamak üzere özel yollar kullandık.
| 2b-multistep.nf | |
|---|---|
Yayınlanan çıktıları organize etmenin daha sofistike yolları var; yapılandırma bölümünde birkaçına değineceğiz.
Workflow oluşturma hakkında daha fazla bilgi edinmek ister misiniz?
Çok adımlı workflow'lar oluşturmanın ayrıntılı ele alınması için Hello Nextflow Bölüm 3: Hello Workflow bölümüne bakın.
Özet¶
Çok adımlı workflow'ların channel'lar ve operatörler kullanılarak nasıl oluşturulduğunu ve nasıl çalıştığını temel düzeyde anlıyorsunuz. Ayrıca process'lerin birden fazla girdi alabileceğini ve birden fazla çıktı üretebileceğini ve bunların yapılandırılmış bir şekilde yayınlanabileceğini gördünüz.
Sırada ne var?¶
Nextflow pipeline'larının kod yeniden kullanımını ve sürdürülebilirliği teşvik etmek için nasıl modülerleştirilebileceğini öğrenin.
3. Modülerleştirilmiş pipeline'ları çalıştırma¶
Şu ana kadar baktığımız tüm workflow'lar, tüm ilgili kodu içeren tek bir workflow dosyasından oluşuyordu.
Ancak, gerçek dünya pipeline'ları tipik olarak modülerleştirilmiş olmaktan fayda görür, yani kod farklı dosyalara bölünür. Bu, geliştirmelerini ve bakımlarını daha verimli ve sürdürülebilir hale getirebilir.
Burada Nextflow'da en yaygın kod modülerlik biçimini göstereceğiz, bu da modül kullanımıdır.
Nextflow'da bir modül, bağımsız bir kod dosyasında kendi başına kapsüllenmiş tek bir process tanımıdır. Bir workflow'da modül kullanmak için, workflow kod dosyanıza tek satırlık bir import ifadesi eklemeniz yeterlidir; ardından process'i normalde yapacağınız şekilde workflow'a entegre edebilirsiniz. Bu, kodun birden fazla kopyasını üretmeden birden fazla workflow'da process tanımlarını yeniden kullanmayı mümkün kılar.
Şu ana kadar tüm process'leri monolitik bir kod dosyasına dahil edilmiş workflow'ları çalıştırıyorduk. Şimdi process'ler ayrı modüllerde saklandığında nasıl göründüğünü göreceğiz.
Elbette yine gösterim amacıyla uygun bir workflow, 2c-modules.nf adlı, modules/ dizininde bulunan bir modül setiyle birlikte hazırladık.
Her biri process'lerden birinin adını taşıyan dört Nextflow dosyası olduğunu görüyorsunuz.
Şimdilik cowpy.nf dosyasını görmezden gelebilirsiniz; ona daha sonra geleceğiz.
3.1. Kodu inceleyin¶
Bu sefer önce koda bakacağız.
2c-modules.nf workflow dosyasını açarak başlayın.
Tam kod dosyası
Workflow mantığının önceki workflow versiyonuyla tamamen aynı olduğunu görüyorsunuz.
Ancak, process kodu workflow dosyasından gitmiş ve yerine modules altındaki ayrı dosyalara işaret eden include ifadeleri var.
| hello-modules.nf | |
|---|---|
Bu dosyalardan birini açın ve ilgili process'in kodunu bulacaksınız.
Tam kod dosyası
| modules/sayHello.nf | |
|---|---|
Gördüğünüz gibi, process kodu değişmedi; sadece ana workflow dosyasında olmak yerine bireysel bir modül dosyasına kopyalandı. Aynısı diğer iki process için de geçerlidir.
Şimdi bu yeni versiyonu çalıştırmanın nasıl göründüğüne bakalım.
3.2. Workflow'u çalıştırın¶
Bu komutu -resume bayrağıyla terminalinizde çalıştırın:
Komut çıktısı
Process çalıştırmalarının hepsinin başarıyla önbelleğe alındığını fark edeceksiniz, yani Nextflow istenen işi zaten yaptığını tanıdı, kod bölünmüş ve ana workflow dosyası yeniden adlandırılmış olsa bile.
Bunların hiçbiri Nextflow için önemli değil; önemli olan tüm kod bir araya getirilip değerlendirildikten sonra oluşturulan iş betiğidir.
İpucu
Bir workflow'un bir bölümünü daha büyük bir pipeline'a aktarılabilecek bir 'alt workflow' olarak kapsüllemek de mümkündür, ancak bu kursun kapsamı dışındadır.
Workflows of Workflows Yan Görevinde birleştirilebilir workflow'lar geliştirme hakkında daha fazla bilgi edinebilirsiniz.
Özet¶
Process'lerin kod yeniden kullanımını teşvik etmek ve sürdürülebilirliği artırmak için bağımsız modüllerde nasıl saklanabileceğini biliyorsunuz.
Sırada ne var?¶
Yazılım bağımlılıklarını yönetmek için konteynerleri kullanmayı öğrenin.
4. Konteynerleştirilmiş yazılım kullanma¶
Şu ana kadar örnek olarak kullandığımız workflow'lar, ortamımızda bulunan UNIX araçlarını kullanarak çok temel metin işleme işlemlerini çalıştırmak zorunda kaldı.
Ancak, gerçek dünya pipeline'ları tipik olarak çoğu ortamda varsayılan olarak dahil edilmeyen özel araçlar ve paketler gerektirir. Genellikle bu araçları yüklemeniz, bağımlılıklarını yönetmeniz ve herhangi bir çakışmayı çözmeniz gerekirdi.
Bunların hepsi çok sıkıcı ve can sıkıcıdır. Bu sorunu ele almanın çok daha iyi bir yolu konteyner kullanmaktır.
Bir konteyner, kod, sistem kütüphaneleri ve ayarlar dahil bir uygulamayı çalıştırmak için gereken her şeyi içeren bir konteyner imajından oluşturulan hafif, bağımsız, çalıştırılabilir bir yazılım birimidir.
İpucu
Bunu Docker teknolojisini kullanarak öğretiyoruz, ancak Nextflow birkaç başka konteyner teknolojisini de destekler.
4.1. Bir konteyneri doğrudan kullanın¶
Önce bir konteynerle doğrudan etkileşime geçelim. Bu, Nextflow'da kullanmaya başlamadan önce konteynerlerin ne olduğunu anlamanıza yardımcı olacaktır.
4.1.1. Konteyner imajını çekin¶
Bir konteyneri kullanmak için, genellikle bir konteyner kaydından bir konteyner imajı indirirsiniz veya "çekersiniz" ve ardından bir konteyner örneği oluşturmak için konteyner imajını çalıştırırsınız.
Genel sözdizimi şöyledir:
docker pull, konteyner sistemine bir havuzdan konteyner imajı çekmesi için talimat verir.'<container>', konteyner imajının URI adresidir.
Örnek olarak, rastgele metin girdilerini eğlenceli bir şekilde görüntülemek için ASCII art üreten cowsay adlı bir aracın python uygulaması olan cowpy içeren bir konteyner imajı çekelim.
Yayınlanmış konteynerleri bulabileceğiniz çeşitli havuzlar vardır.
Bu Docker konteyner imajını cowpy Conda paketinden oluşturmak için Seqera Containers hizmetini kullandık: 'community.wave.seqera.io/library/cowpy:1.1.5--3db457ae1977a273'.
Tam çekme komutunu çalıştırın:
Komut çıktısı
Unable to find image 'community.wave.seqera.io/library/cowpy:1.1.5--3db457ae1977a273' locally
131d6a1b707a8e65: Pulling from library/cowpy
dafa2b0c44d2: Pull complete
dec6b097362e: Pull complete
f88da01cff0b: Pull complete
4f4fb700ef54: Pull complete
92dc97a3ef36: Pull complete
403f74b0f85e: Pull complete
10b8c00c10a5: Pull complete
17dc7ea432cc: Pull complete
bb36d6c3110d: Pull complete
0ea1a16bbe82: Pull complete
030a47592a0a: Pull complete
622dd7f15040: Pull complete
895fb5d0f4df: Pull complete
Digest: sha256:fa50498b32534d83e0a89bb21fec0c47cc03933ac95c6b6587df82aaa9d68db3
Status: Downloaded newer image for community.wave.seqera.io/library/cowpy:1.1.5--3db457ae1977a273
community.wave.seqera.io/library/cowpy:1.1.5--3db457ae1977a273
Bu, sisteme belirtilen imajı indirmesini söyler. İndirme tamamlandığında, konteyner imajının yerel bir kopyasına sahip olursunuz.
4.1.2. Konteyneri başlatın¶
Konteynerler tek seferlik bir komut olarak çalıştırılabilir, ancak bunları etkileşimli olarak da kullanabilirsiniz, bu size konteynerin içinde bir shell promptu verir ve komutla oynamanıza olanak tanır.
Genel sözdizimi şöyledir:
docker run --rm '<container>', konteyner sistemine bir konteyner imajından bir konteyner örneği başlatması ve içinde bir komut yürütmesi için talimat verir.--rm, sisteme komut tamamlandıktan sonra konteyner örneğini kapatmasını söyler.
Tam olarak birleştirilmiş konteyner yürütme komutu şöyle görünür:
Bu komutu çalıştırın ve promptunuzun (base) root@b645838b3314:/tmp# gibi bir şeye dönüştüğünü görmelisiniz, bu artık konteynerin içinde olduğunuzu gösterir.
Bunu, dizin içeriğini listelemek için ls çalıştırarak doğrulayabilirsiniz:
Konteynerin içindeki dosya sisteminin ana sisteminizden farklı olduğunu görüyorsunuz.
İpucu
Bir konteyneri çalıştırdığınızda, varsayılan olarak ana sistemden izole edilir.
Bu, konteynerin ana sistemdeki hiçbir dosyaya erişemeyeceği anlamına gelir, bunu aşağıdaki sözdizimini kullanarak docker run komutunun bir parçası olarak bir birim bağlamak istediğinizi belirterek açıkça izin vermediğiniz sürece:
Bu, dosya sisteminizin o bölümüne erişmek için kullanabileceğiniz, konteyner duvarından bir tünel oluşturur.
Bu, Hello Nextflow Bölüm 5'te daha ayrıntılı olarak ele alınmaktadır.
4.1.3. cowpy aracını çalıştırın¶
Konteynerin içinden cowpy komutunu doğrudan çalıştırabilirsiniz.
Komut çıktısı
Bu, belirttiğimiz metni içeren bir konuşma balonuyla varsayılan inek karakterinin (veya 'cowacter') ASCII art'ını üretir.
Temel kullanımı test ettiğinize göre, ona bazı parametreler vermeyi deneyebilirsiniz.
Örneğin, araç belgeleri karakteri -c ile ayarlayabileceğimizi söylüyor.
Komut çıktısı
Bu sefer ASCII art çıktısı Linux pengueni Tux'u gösteriyor, çünkü -c tux parametresini belirttik.
Konteynerin içinde olduğunuz için, sisteminize herhangi bir kütüphane yüklemek zorunda kalmadan girdi parametrelerini değiştirerek cowpy komutunu istediğiniz kadar çalıştırabilirsiniz.
Diğer mevcut karakterler
Farklı bir karakter seçmek için '-c' bayrağını kullanın, bunlar dahil:
beavis, cheese, daemon, dragonandcow, ghostbusters, kitty, moose, milk, stegosaurus, turkey, turtle, tux
Bununla oynamaktan çekinmeyin.
İşiniz bittiğinde, exit komutunu kullanarak konteynerden çıkın:
Normal shell'inize geri döneceksiniz.
4.2. Bir workflow'da konteyner kullanın¶
Bir pipeline çalıştırdığımızda, Nextflow'a her adımda hangi konteynerin kullanılacağını söyleyebilmek istiyoruz ve önemlisi, az önce yaptığımız tüm işi onun halletmesini istiyoruz: konteyneri çekmek, başlatmak, komutu çalıştırmak ve bittiğinde konteyneri kapatmak.
İyi haber: tam olarak Nextflow'un bizim için yapacağı şey bu. Sadece her process için bir konteyner belirtmemiz gerekiyor.
Bunun nasıl çalıştığını göstermek için, üçüncü adımda üretilen toplanan selamlamalar dosyasında cowpy çalıştıran workflow'umuzun başka bir versiyonunu yaptık.
Bu, konuşma balonunda üç selamlama içeren ASCII art içeren bir dosya çıktısı vermelidir.
4.2.1. Kodu inceleyin¶
Workflow, öncekine çok benzer, artı cowpy çalıştırmak için ekstra adım.
Tam kod dosyası
Bu workflow'un bir modül dosyasından bir cowpy process'i içe aktardığını ve bunu collectGreetings() çağrısının çıktısında, artı params.character adlı bir girdi parametresinde çağırdığını görüyorsunuz.
ASCII art oluşturmak için cowpy komutunu saran cowpy process'i, cowpy.nf modülünde tanımlanmıştır.
Tam kod dosyası
cowpy process'i iki girdi gerektirir: konuşma balonuna konulacak metni içeren bir girdi dosyasının yolu (input_file) ve karakter değişkeni için bir değer.
Önemlisi, daha önce kullandığımız konteyner URI'sine işaret eden container 'community.wave.seqera.io/library/cowpy:1.1.5--3db457ae1977a273' satırını da içerir.
4.2.2. Yapılandırmada Docker'ın etkinleştirildiğini kontrol edin¶
Bu eğitim kursunun 3. Bölümünü biraz öne çekerek, Nextflow'un workflow çalıştırmasını yapılandırmanın ana yollarından biri olan nextflow.config yapılandırma dosyasını tanıtacağız.
Geçerli dizinde nextflow.config adlı bir dosya bulunduğunda, Nextflow otomatik olarak yükleyecek ve içerdiği yapılandırmayı uygulayacaktır.
Bu amaçla, Docker'ı etkinleştiren tek satırlık kod içeren bir nextflow.config dosyası ekledik.
| nextflow.config | |
|---|---|
Bu yapılandırma, Nextflow'a uyumlu bir konteyner belirten herhangi bir process için Docker kullanmasını söyler.
İpucu
Docker çalıştırmasını komut satırından, çalıştırma başına bazında -with-docker <container> parametresini kullanarak etkinleştirmek teknik olarak mümkündür.
Ancak, bu yalnızca tüm workflow için bir konteyner belirtmemize izin verirken, az önce gösterdiğimiz yaklaşım process başına farklı bir konteyner belirtmemize olanak tanır.
İkincisi modülerlik, kod bakımı ve tekrar üretilebilirlik için çok daha iyidir.
4.2.3. Workflow'u çalıştırın¶
Özetlemek gerekirse, çalıştırmak üzere olduğumuz şey:
Çalışacak mı sizce?
Workflow'u -resume bayrağıyla çalıştıralım ve karakterin hindi olmasını istediğimizi belirtelim.
Komut çıktısı
N E X T F L O W ~ version 25.10.2
Launching `2d-container.nf` [elegant_brattain] DSL2 - revision: 028a841db1
executor > local (1)
[95/fa0bac] sayHello (3) | 3 of 3, cached: 3 ✔
[92/32533f] convertToUpper (3) | 3 of 3, cached: 3 ✔
[aa/e697a2] collectGreetings | 1 of 1, cached: 1 ✔
[7f/caf718] cowpy | 1 of 1 ✔
İlk üç adım daha önce çalıştırdığımız için önbelleğe alındı, ancak cowpy process'i yeni olduğu için gerçekten çalıştırılıyor.
cowpy adımının çıktısını results dizininde bulabilirsiniz.
Dosya içeriği
_________
/ HOLà \
| HELLO |
\ BONJOUR /
---------
\ ,+*^^*+___+++_
\ ,*^^^^ )
\ _+* ^**+_
\ +^ _ _++*+_+++_, )
_+^^*+_ ( ,+*^ ^ \+_ )
{ ) ( ,( ,_+--+--, ^) ^\
{ (\@) } f ,( ,+-^ __*_*_ ^^\_ ^\ )
{:;-/ (_+*-+^^^^^+*+*<_ _++_)_ ) ) /
( / ( ( ,___ ^*+_+* ) < < \
U _/ ) *--< ) ^\-----++__) ) ) )
( ) _(^)^^)) ) )\^^^^^))^*+/ / /
( / (_))_^)) ) ) ))^^^^^))^^^)__/ +^^
( ,/ (^))^)) ) ) ))^^^^^^^))^^) _)
*+__+* (_))^) ) ) ))^^^^^^))^^^^^)____*^
\ \_)^)_)) ))^^^^^^^^^^))^^^^)
(_ ^\__^^^^^^^^^^^^))^^^^^^^)
^\___ ^\__^^^^^^))^^^^^^^^)\\
^^^^^\uuu/^^\uuu/^^^^\^\^\^\^\^\^\^\
___) >____) >___ ^\_\_\_\_\_\_\)
^^^//\\_^^//\\_^ ^(\_\_\_\)
^^^ ^^ ^^^ ^
Karakterin tüm selamlamaları söylediğini görüyorsunuz, çünkü toplanan büyük harfli selamlamalar dosyasında çalıştı.
Daha da önemlisi, cowpy ve tüm bağımlılıklarının düzgün bir kurulumunu yapmak zorunda kalmadan bunu pipeline'ımızın bir parçası olarak çalıştırabildik. Ve şimdi pipeline'ı iş arkadaşlarımızla paylaşabilir ve Docker veya yukarıda belirtildiği gibi alternatiflerinden biri (Singularity/Apptainer gibi) dışında hiçbir şey yüklemelerine gerek kalmadan kendi altyapılarında çalıştırmalarını sağlayabiliriz.
4.2.4. Nextflow'un konteynerleştirilmiş görevi nasıl başlattığını inceleyin¶
Bu bölüme son bir koda olarak, Nextflow'un kaputun altında konteynerlerle nasıl çalıştığı hakkında biraz daha fazla bilgi edinmek için cowpy process çağrılarından birinin çalışma alt dizinine bir göz atalım.
cowpy process'inin çalışma alt dizininin yolunu bulmak için nextflow run komutunuzun çıktısını kontrol edin.
Yukarıda gösterilen çalıştırma için aldığımıza bakarsak, cowpy process'i için konsol log satırı [7f/caf718] ile başlıyor.
Bu, şu kısaltılmış dizin yoluna karşılık gelir: work/7f/caf718.
Bu dizinde, Nextflow'un pipeline'ı yürütme sürecinde sizin adınıza çalıştırdığı tüm komutları içeren .command.run dosyasını bulacaksınız.
Dosya içeriği
#!/bin/bash
### ---
### name: 'cowpy'
### container: 'community.wave.seqera.io/library/cowpy:1.1.5--3db457ae1977a273'
### outputs:
### - 'cowpy-COLLECTED-batch-output.txt'
### ...
set -e
set -u
NXF_DEBUG=${NXF_DEBUG:=0}; [[ $NXF_DEBUG > 1 ]] && set -x
NXF_ENTRY=${1:-nxf_main}
nxf_sleep() {
sleep $1 2>/dev/null || sleep 1;
}
nxf_date() {
local ts=$(date +%s%3N);
if [[ ${#ts} == 10 ]]; then echo ${ts}000
elif [[ $ts == *%3N ]]; then echo ${ts/\%3N/000}
elif [[ $ts == *3N ]]; then echo ${ts/3N/000}
elif [[ ${#ts} == 13 ]]; then echo $ts
else echo "Unexpected timestamp value: $ts"; exit 1
fi
}
...
Bu dosyada ilerlerseniz, her şeyin nasıl kurulduğunu ve konteynerin nasıl başlatıldığını görebilirsiniz; bu epey bir iş ki biz hiç yapmak zorunda kalmadık!
Özet¶
Bir workflow'da konteynerleştirilmiş araçların nasıl kullanılacağını ve bir process modülünde konteyner direktifinin nasıl belirtileceğini biliyorsunuz.
Sırada ne var?¶
Çalıştırma yapılandırmasıyla pipeline'ı nasıl özelleştireceğinizi öğrenin.