From 5b174ea47ab3cbc338ce515a4f6c668c0e67e425 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20=C5=9Acise=C5=82?= Date: Tue, 20 May 2025 19:22:11 +0200 Subject: [PATCH 01/13] Initial version of base sequence quality --- Cargo.lock | 5 +- Cargo.toml | 1 + docs/notebooks/example.fastq | 800 +++++++++++++++++++++++++++++++++ docs/notebooks/example.parquet | Bin 0 -> 20352 bytes docs/notebooks/tutorial.ipynb | 211 ++++++--- polars_bio/__init__.py | 2 + polars_bio/quality_stats.py | 25 ++ src/lib.rs | 36 ++ src/operation.rs | 133 ++++++ 9 files changed, 1145 insertions(+), 68 deletions(-) create mode 100644 docs/notebooks/example.fastq create mode 100644 docs/notebooks/example.parquet create mode 100644 polars_bio/quality_stats.py diff --git a/Cargo.lock b/Cargo.lock index d84574f0..2527967b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5424,6 +5424,7 @@ dependencies = [ "pyo3-log", "rand", "sequila-core", + "serde_json", "tokio", "tracing", ] @@ -6346,9 +6347,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.138" +version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ "indexmap", "itoa", diff --git a/Cargo.toml b/Cargo.toml index 47d326b7..919b38d5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,3 +43,4 @@ coitrees = "0.4.0" fnv = "1.0.7" async-stream = "0.3.6" rand = "0.8.5" +serde_json = "1.0.140" diff --git a/docs/notebooks/example.fastq b/docs/notebooks/example.fastq new file mode 100644 index 00000000..4b357e52 --- /dev/null +++ b/docs/notebooks/example.fastq @@ -0,0 +1,800 @@ +@SRR9130495.1 D00236:723:HG32CBCX2:1:1108:1330:1935/1 +NCAATACAAAAGCAATATGGGAGAAGCTACCTACCATGCTTAAAAACGCCAATGAGCAGNGATTTGTCANCNNNNNNNNCNNNNNNNNTNNTANNANNCTC ++ +#4BDFDFFHGHGGJJJHIIIIGGIIJGJJGIIIIBHIJJJIIJIJJIJDHIGGGIJJJI#-@AEHGEFF#,########,########+##++##+##+2< +@SRR9130495.2 D00236:723:HG32CBCX2:1:1108:1472:1938/1 +NGTCAAAGATAAGATCAAAAGGCACTGGCTTACCTGATTAAGAAATTGTGTAGTCCAACATCAAAATACNTNTNNNNNAGAGNCANGNCAAGCNNANNAAT ++ +#1=DDDDD>DHFH@EFHHGHGGFGIIIGIGGGGIIGIIDDCHIIIIIID@FEGGGIIIIICHIIIIIIG#-#-#####,,;;#,5#,#,,85@A:AB@8>@:@A@9(:((+(834 +@SRR9130495.6 D00236:723:HG32CBCX2:1:1108:2392:1965/1 +CGATAAAGGACTTTCAGTCAACCAACTAGATAATGACCACTGGGCACCCATTCATTATGCATGCTGGTAAATAAATTATTCTGTTCAGGAACATTGAACTC ++ +CC@DDDBDFFHHHJJIJJIIJIJJJIIIHGIGGHCGGIGHHAACC??A< +@SRR9130495.11 D00236:723:HG32CBCX2:1:1108:4089:1977/1 +CATTCCAACCAGCCGCTTAAAGTTTCTAAAAGAAGCTGGTCATGGAACCCAGAAGGAGGAGATACCTGAGGAGGAATTAGCAGAGGATGTTGAAGAGATTG ++ +CCCFFFDFHHHHHJIJJJJIIJJJJJJJJJJJIIGJJJIGHGIJJIJJIJJIIFHGHIJJGHEHHFCEFFDEDDBDDDDDDDDDDDBACDDDDDDDDDDDD +@SRR9130495.12 D00236:723:HG32CBCX2:1:1108:6197:1936/1 +NCTTAAAGGCAAGGTGCTCGGCTTCCGCTATCAAGACCTCCGACAGAAAATCCGGCCTGNGGCTAAAGANCNNNNNNNNANNNNNNNNCNNGGNNCNNGGC ++ +#1BDFDEFGHHHHIJJJJJJIJJJJJJJJJJIJJIGIJJIJJJIJJJJHIJJHHHFFDC#,;?BBDDDD#,########+########+##++##+##++8 +@SRR9130495.13 D00236:723:HG32CBCX2:1:1108:6415:1939/1 +NTGTGTATGGGGATGAGGAAGGATATTAATATGTTCTATTTGAGATTTAGGGATTACATTTGTTTTTGCNCNCNNNNNTTTTNTCNTCATTTGNNGTNAAT ++ +#1:ADDDFHGGHFGGBHIGGIIJJEIIIJJIJIJJJFGJIIHGHGDGHJGHIHIIIIJJIIHFHIIJJJ#-#-#####,,;?#,;#,8?DDEE##,+#+2< +@SRR9130495.14 D00236:723:HG32CBCX2:1:1108:6361:1952/1 +TCAGATCTTATTTTAATAGTTGACTTTACCTCTTCTTTGACTTCCTCTTCCTCGGTCTCAGTAGATATAGATGGTACCTTGGGCTTATGCCATGAGATCTG ++ +CCCFFFFFHHHHDHIIIIJJJJJJJJJJHIIIJJJJJJJIHJHJII>GHIEGHIIIIJJJIJJIHHIJJJIJIGHIJJGJJHFHHFFDCFFEDCEDCCDEC +@SRR9130495.15 D00236:723:HG32CBCX2:1:1108:6263:1960/1 +CAATATCTGACTGAATGGGCCCATTTTCATAATATTCTGAAACTGTTCATACATGTCTCGCAATGTAAACTGACCTGAAATGCAATACAAAAAAATTCAGA ++ +CCCFFFFFHHGHGGGIIIIJJIJIJJIIIIIIIIEIHGGIEGGHGIJJIJJJCECGHIIIJJJJJIFGHIIHGIIJJHHGEFHDFFFFFCCCDDBBCCDCA +@SRR9130495.16 D00236:723:HG32CBCX2:1:1108:6338:1988/1 +AGACACTAAAATGCCATGTATGAGACTACATAGACATACCAATTTACAACACAAACACATGAAATATACATGAGAAAACATTAACTTACTTCCAGTTGGGA ++ +C@CFFDDDHGHHHIIIIHJJIIHIHGIJJJJJIJJJIJIIHEHIIJJJJJJIJJIIIIIJJDHIJIJGIJIJJIJJHHGGHFFFFFFFEEEDCCC@ACCBA +@SRR9130495.17 D00236:723:HG32CBCX2:1:1108:6742:1944/1 +NGAAACACTCTTTTTCTGGAATTTGCAAGTGGAGATTTCAGCCGCTTTGTGGTCAATGGTAGAAAAGGAAATATNTNCATATAAAAACTAGACAGAATGAT ++ +#1BDFDFFHGHGHJJJJJJJJHIJHHIJIIJJIJJGIJJIJIIJJGIJIHIJJJIIJJJHIEIIJJJJIHDEFH#,#,5=ADEEEDCDDDDDDDCDD5@CD +@SRR9130495.18 D00236:723:HG32CBCX2:1:1108:7076:1942/1 +NGTCTAAGAATGAAGTGCTTATGGTCAACATAGGCTCCCTGTCGACAGGAGGAAGAGTTAGTGCAGTCAAGGCTNANTTGGGCAAAATTGTTTNNACCAAT ++ +#1:B:BDDHHFFHIEGGIGIDEHGEEGIGHIIIFACHIGIGCFGEHIGGHHGHGH@DCGGIDEIIIIFFHHAEE#,#,5=@BBC@BCCCCCCC##,+8?BC +@SRR9130495.19 D00236:723:HG32CBCX2:1:1108:7440:1957/1 +CACCTGATGTCCCACAGTCCTCATAGACACTAGCACTGACTGCTGGCCATCGTCTCAGCCAGATGATGTTGACCTGCTAGCTTTTCAATTAAATTATTAAA ++ ++=144=DD>D4CCD?E@AECFFIIIIEI?E+??;3EBDECEIBEECDIEIIADDDDEIDCDCA;=A@CECE7ACD=(;;A@DA@A@A:ADAAAD>AADBB> +@SRR9130495.20 D00236:723:HG32CBCX2:1:1108:7363:1977/1 +ACTCATAGAGTTGAAGATTCCCTTTCATAGAGCAGGTTTGAAACACTCTTTCTGGAGTATCTGGATGTGGACATTTGGAGCGCTTTGATGCCTACGGTGGA ++ +CCCFFDDDFHHHHJJJIJJJJHHIIHGIJIJJJIGGHGIJIJJIIIJJJJJIJIGBFDHIIJIJGIJIGGCHGGIJHIIHHHFECDECEEDCDDCBD9?B? +@SRR9130495.21 D00236:723:HG32CBCX2:1:1108:7298:1979/1 +AACCGTCGCCAGGTACCATCCCAGAGAACTCTGTCTTCCTTACTTATAGCCAAGTTGCCGGCAGATCACAGCTGCATGCTTATCGGTCCATCCGTCATCGC ++ +BCCDDDFFGGFGFJIBBHHIJJIIHHIIIGJIIHIIJJJIIEIGHJIIJJJJIIHHGIJFGHGFDDCEECDDDDDDDDDDEDDDDDDDBDEDDDCCC +@SRR9130495.23 D00236:723:HG32CBCX2:1:1108:7307:1995/1 +TAATTTGGTATATGTCTTTTTAAAGGCATTTTTATTAGATATTTCCTTAATTTACATTTCAAATGTTATCCCCAAAGCCCCCTATAATCTACCCCTGCCTT ++ +;?7DD?;DBFHHFIA;A@AABBB@B?2<58+:?<<9<@: +@SRR9130495.25 D00236:723:HG32CBCX2:1:1108:7870:1955/1 +CTATCCCGTCGGGTGACTGTTTCCTGCTTTGCAGTTATTCAGTGGCAGAGCGTGGCGCTCTAATTTCTGCTTTCCTCTTTCCTGCAGATTGTGTGCTACAT ++ +CCCFFFDFFHHFHBHGJIIIHGIIIJJIJIIIIJHIIIIEIJJIIJJJJIJIJIJDFEDDDCEEEEEEDDDDDDDDCDDDCDDDDDDDCDDDCDDDDDDDD +@SRR9130495.26 D00236:723:HG32CBCX2:1:1108:8157:1994/1 +GAAGTGCTCTTCGTTACTACTTAAATCCCCCTGGGCATGTTTCATTATTTTACAATTTGTGCAGAACCCTATCCAAACACACATGGAGTACAAATGACTTC ++ +CCCFFDDDDHHDHHIGIIBIHHHJJJ@FGGA?@CCCCCC@CCCDD +@SRR9130495.27 D00236:723:HG32CBCX2:1:1108:8703:1937/1 +NATAAAAAAATAACATCCTTTCCTCCTAATAGCTTAATTATTTGAAAAAAAATATTTTCNAATCACATGNANNNNNNNNTNNNNNNNNTCTTTNNTNNCCT ++ +#1=DFDDDHHHHHIIJJJJJFIJJJIGIEGIIJJJHHIJJJJJIIJIIIIIJEHEHHHA#,;??AEDDC#,########,########++8??##+##(+2 +@SRR9130495.28 D00236:723:HG32CBCX2:1:1108:8702:1991/1 +CTCAGAGATTAAAAATGAATAACGCCTGCCGGCCAATGAGCGGACTCACAGTCCCTGTTTGTTTGTAAGCTAGGTGATTTTCAATCCACAGGGCAGGCTGA ++ +@@@DFDFFGGDHFGIIBGEHJIIIBGIIIJJIIJIJIIFGGEGIJJJHGGHHHDCFFDDDEDEDDDDDCDDDCBDDACDEDEDDDDCCCCDGII@GIFGFE???BFBBEHIGGIEEHIHIGGHHGIHA3?CH;?@CB@DCCEDEDD3 +@SRR9130495.34 D00236:723:HG32CBCX2:1:1108:10535:1962/1 +AATACAGAAAAGTTAAGAGCCAGCCCCAGGCGGATTGGATGAATAGGTTGCATCTCTTTCTTGCTTATATCAAATGCCTCTTGGCAGGCTCCTTGGGAATT ++ +???BD:A:3=?B:;?;;CA;;;A3-5>5-5:(::@8/2?8?9>>3(83(+ +@SRR9130495.35 D00236:723:HG32CBCX2:1:1108:11147:1968/1 +GCTGCCTTCTCCCCTCAAGGATGCAGTGGAAGTGTCAACCTGGAGAAGATGCTACACGATGCAGGAGGTGAACTCGGCCCTCAGTAAAATCCAGCTGGTGG ++ +CCCFFFDFHHHGHJFEGIHEGHIGIIGCCGGGIIJJIJJGGGGHCGIF>DGHIIIEHHGIIJJDBGHFHFCCFFFDDCDDDDBDDDCCDEDA:CACD@CDD +@SRR9130495.36 D00236:723:HG32CBCX2:1:1108:11124:1986/1 +GACAGGGTTTCACCATGTTAGCCAGGACGGTCTTGATCTCCTGACCTCGTGATCCGCCTGTCTCGGCCTCCCAAAGTCCTGGGATTACAGGCGTGAGCCAC ++ +CCCFFFFBFFFHGGHGHIHIIGIJFJJJIJHIIIFGHGGIIGEGHIH@@FGGIJIIGGIHIEEHEEFFDDCCCCBDDACCDCDBAACCDDDBDDDDBDDCC +@SRR9130495.37 D00236:723:HG32CBCX2:1:1108:11773:1947/1 +TACCTGCCTCTGCCTCTCGAGTGCTGGGATGAAAGATGTGCACACCCCCACCACCACCACCACCACTGCCTGGCNCNGTTTTTGATTTCTTATTCTCCAGA ++ +CCCFFFFFHGHHHJIJIJIIEHIJJIJJIJJIHIHJJIGFIIIIJBHHGFF>HGIJIEHHHFGDEEEEEECC?B#,#,,5?@HF1CGBGHCDDFF7=DEG.?AAC?3@EED;6@;>(-;@AC?31(,5?(4::A>AC +@SRR9130495.46 D00236:723:HG32CBCX2:1:1108:14226:1948/1 +AACCTGCACCCAGAATGGCAGGAGGTCCTGGTGGCCCAGGGGGTCCTGGTGGTCCAGGAACACCAGGTCTCCCANANCCAGGTGGCCCAGGCAGGCCTGGA ++ +??1D1BDDHFHHBBHGGGAFG)AF1:?CEGD@BGAFDGIGGB'5;CE77?=???>>CC3#+#++228>>28((2(>ACC?CCDDCCD@ +@SRR9130495.48 D00236:723:HG32CBCX2:1:1108:15049:1993/1 +TGACCAAGAACTCACAGAGATCCCCCCCCCCAGGGCTAAGATTAAAGGCATGTGCCACTGCCACTGGATAGATATTATCTTTTATTTTACCTGACTGGTTG ++ +@CCFFDDDHDFHGJJJJIJGIHHHIIJJIJFE=(5;?@>@A@;@C>CAB=@<:@C@CA:>CC3:>CB<@@?344>>@@A>CDC>ACDD:>4>>>ACD?CC( +@SRR9130495.49 D00236:723:HG32CBCX2:1:1108:15487:1951/1 +ACGGAGGGTGGGGCTGGGTGATTGTGGTTGTCTCCTTCTTCACCCAGTTCCTCTCTTACGGATCCCCGTTAGCTNTNGGGGTCTTGTATGTAGAATGGCTG ++ +BCCFD@DFDFHHGDGIIICGHIIJJIJGHIIJIIJJJIJIJIJEHIGHHHHHHHFFFFFFDDCDDCD@DDDDD:#+#+2<@8GHIIIEHGACFHIIGGIBHIIHHC??BDC@BBCECDCE63>@@CACCDD@ +@SRR9130495.51 D00236:723:HG32CBCX2:1:1108:15923:1957/1 +CCGCAACTGCCATGGAGCCACAGCCTGGTCCGTAATAGATGCAAAGCTTCTCAATAGTCAGGGGCGTGGTTTCGCGCAGCTTGGAGGCCAGCAACAGGCAG ++ +CCCFFFFFHFHHHIIFIIIGIIFIIGJIIJJIFHGHIIIIIJIIFIJIIIJJJJJJJGGIGJFFH@?BBBDBCDDDDDDDDDDDDDDDDDDDDDDDDDDD? +@SRR9130495.52 D00236:723:HG32CBCX2:1:1108:15793:1968/1 +GTTTTTCCACAGACCTCTGATCTCTTACATTCGAAAGTTCTACTACTATGATCCTCAGGAAGAGGTGTACCTGTCCCTAAAGGAAGCGCAGCTCATTTCCA ++ +BB@FFFFFFFHGDGFHJJJJIFIIGGG@FIIIGIBGGDHIIIJCHIIJJDHIIJJJIIIGIIJJFHHIJCHGDHIIHHHHHFFFFFDDDDDDCDDDDEDDE +@SRR9130495.53 D00236:723:HG32CBCX2:1:1108:16082:1968/1 +GAAACTTGTTTGTGACGTGTGTATTCAACTAACAGAGTTGAACCTTTCTTTTTACAGAGCAGCTTTGAAACACGCTTTTTGTAGAATCAGATCGGAAGAGC ++ +@<@ADDDECBFFHIFEGDG;EEHHB@FHGHIIGGEHGGHGGEGEGICGCEFFDB@D>AE>ADC@CBBFGIIJJJJIHHIJJGH?DGGHCFHHIJJEEIIJAHIJJFG=FGGGIFHHIIDHGEHIHHHHGHGEB;?CDCECEEDD +@SRR9130495.55 D00236:723:HG32CBCX2:1:1108:16048:2000/1 +AGGACAGGAAGGACGCTTTGAGATATGATTTCACAGGCGACAGTGAGAGAAAACCAATGTCTTTAATGCATTTCTCTGCAGCATGTGACAAACTTTCAACA ++ +CCCFFFFDFHGHHIIJJJJIFGGIJJIIIIJIJIHJIIJIHGIJJIJGGIIJIJJHHHHEDCDFFFEEEDDEDEEDDDDDDDDDDCDEDDCDDDDDDCCD@ +@SRR9130495.56 D00236:723:HG32CBCX2:1:1108:16580:1970/1 +GCCTGTACTCCCAGCTACTTGGGAGGCTGAGACAGGAGAATCACTTGAACCCAGGAGGTGGAGGTTGCAGTGAGCCAAGACCGGGCTATTGCACTAGATCG ++ +@@@FFD?DBFFHHIIEHCIJIFIJHEDCH@GGEBFHHIJJIIIIIJJJJJIFHFHF@G-6@AAEDFFF>AEC@@A?;=?BCD6/<@>BAAC>:@C:CDDA? +@SRR9130495.57 D00236:723:HG32CBCX2:1:1108:16594:1971/1 +TCCTCTGACTTTGACACTAGTGTTGACCTTGCATGAGGAGATGTTCTCCATTTGGACTAACCTGATGTACACAGACGTTACACTTATCACAGAATACCATA ++ +CCCFFDDFFHFHFHIJIJJIHIIIJJJJJIJJJJIIIIHIGIIJJJIGIIJJIIJEHIIJIJJJIGIJJJEIHJJIIHHEFFFFFFCCEEEEDCDDDDDDC +@SRR9130495.58 D00236:723:HG32CBCX2:1:1108:16808:1998/1 +ACCAATTTTCCCCTCCCCTTCCTCCCTCCCTCCCAGCCCCCTTCCTCTCTCTACCTCCTGTTATTGTTTTGTTCCTTGTTCTATGTAGGATTGAAGCATCT ++ +@@@FFDDFHDFHGIJJJJIIGGDFHI>DGC;DHI9??FHIJIIHG>>3>;ACCCC9:@>@:>AA +@SRR9130495.59 D00236:723:HG32CBCX2:1:1108:17428:1967/1 +TGCATGGTGCTGAAAGCTTTGTTGCAGCTTTTCTTGGGATTGCTTAGCTGCTCCGGGTCGATCCACTTGCAGATGAGCTCTTGCTTGATGCACTGCTGCCG ++ +?<A3>A>>AAAA?3 +@SRR9130495.60 D00236:723:HG32CBCX2:1:1108:17508:1988/1 +TTGTTCAGAAAAAAGTATCTTGAAACCAAAAGAACTGGGATCTTGTTAAATGCAGATTCTGTTCATTAGGTATAGGTATGCAGTCTTACAAAATGAGGTAG ++ +CCCFFEFFHHHHHJJJJJJJJJJJJJJJJJGIJJJJJJJIIJJJJJJJJIJJIJJJJJJJJJJJIJJIIIEHHBHGHHEFFFFFEEEEDEEDDCDCDDCDC +@SRR9130495.61 D00236:723:HG32CBCX2:1:1108:18425:1951/1 +CCACTTAATAAATCACCTATCAAGTTGAATTATTTGTGCAAAGGCACTAGGCTGAATAGAGACCACTCAGTAGCNTNTTTTTAATCTTGCTAAGAAAGAAT ++ +CCCFFDDFHFHHGJIIJJJJJJHGHEHHHIIJIJJIJGJIHIJHEFDHGHIFIJJGHIJJJFIGGIHIIIJIII#-#-5@DFFEEEDEEEDEDDACDCCBC +@SRR9130495.62 D00236:723:HG32CBCX2:1:1108:18468:1964/1 +CTATTGACTTTTATTAGAAAGGGTCTTGTTGCATAGGTAGGTCTTTAACAACCATCTCTTAAAGGGCTGGGATTGCCAGAGTAGGCCAACACGCCCAGCTA ++ +CCCFFFFFGGHHGIGIJIJJIIIJJJJIJJIJJJJIIJDGEHGIIJJJIJJJHIJJIGFHGIJGEGIJJJIIHHHHHHFFFFFEDEEDDDDDDDBDDBBD@ +@SRR9130495.63 D00236:723:HG32CBCX2:1:1108:18615:1941/1 +NAGCCGAGAGGCGCCGGCTCACCTGCCTGGGTCCCGGCCTTTCTCCTGCAGTGCCAGGGATTCACCTGANGNCNNNNNNTCTNCTAGGCAAGCNNATNCTT ++ +#1:DDFDDHHHHHIIJIIFGJJIEFHHIHHIIIJJIEHFFEEEEEEE?DFF;5:AAB9>29(#+#++8++4>>:@>AA:@1<@@A(:4? +@SRR9130495.72 D00236:723:HG32CBCX2:1:1108:1440:2047/1 +GCTGGTGCAGGACACCAGAATCCGCTCGATCATGCTCCCTAGAGAGGAGGGGCACAGTGAGTACACATAAGCACATGTACACACACACCCAGGACCCAAAG ++ +CCCFFFDEHHGHHHIIIIIIIIJJIJJJGEGHIJIJJJJIIJGHIIJJJIDFEDFFFFEEEEDEDDDDDDDDDDDDDEEEEDDDDDDDDDDDDDDDDDDDA +@SRR9130495.73 D00236:723:HG32CBCX2:1:1108:1468:2080/1 +ACTGTCTTTTTTTTAAAACAGGTGATTGCCCGTTGATTGTTCAGTTTGCTGCTAATGATGCAAGACTTTTATCTGATGCTGCCCTGCTAGTCTGTCCCTAT ++ +CCCFFDDEHFFDHIEIIJHGCGFHCIIHIIIHH@FGGIHIGHIJJIJGIIIJBHIGEIHGHHGGHFFFFFFEEEEDEDDDDDDDDDDDCDDDEDDDDDDDD +@SRR9130495.74 D00236:723:HG32CBCX2:1:1108:1333:2084/1 +ATGAGCACACAAGGGATGATCAGATTGATGGTGTAGAAGAGTGGCTTGCGCTTGATGATGAAGTCATAGGTCACGTCCACATAGCTGGGGTCCTGTGGGTT ++ +CCCFFFFFHHHHHJIJHDIIHHHIIJIIJJJJJIJJIIJIJJJIBDGIJJJJIJJJJGIIIJIAHEEHEFFFFF>EDCDDDDDCDDCDDDDDDDDDCDDDD +@SRR9130495.75 D00236:723:HG32CBCX2:1:1108:1447:2137/1 +TCCACTTGTACAAAAAATTACAAAAATTAGCTGGGCATGGTGGCACACACCTGTAGTCCCAGCTACTCGGGAGGCTGAAGTGGCAGGATCACTTGAGGCAG ++ +CCCFFEFFHFHGHJJJJIJJJJIIDIEHJIIJJJIGJJJHGJIIDHIDGIJIJJIGHIJJJJJHHHFEEBDCDBBDDDDDDDDDDDDDDDDDDDDDCDDD@ +@SRR9130495.76 D00236:723:HG32CBCX2:1:1108:1499:2151/1 +GAGAAAAAGCATCCCTTTAATAAGGCCGCCCCGGTTCCAAATCAATCCTGGCATTGCAGGAGGCAAGGGGGAAACACAGCCACGAAATTGGATTAGCTCTT ++ +CCCFFFFFGGHHHJIIJHIEIJJIIIIJIIGJJIHJIJJIGIJJJIIJJHHHHHFFFFFFDCDBDDDDDDDDDDDCDDDBDBDDBBDDDDDCDDDDCDDCD +@SRR9130495.77 D00236:723:HG32CBCX2:1:1108:1280:2166/1 +GCCTTCTTCCCAGCAGCAATATGGCTCTTTCTTCAGCTCTTATCAGTCACATCCATCAACGAGTGGCTTTTAAAAGGGTATGTTTAAACCTTTTGACGGGA ++ +CCCFFDEFHHHGGJIJJIJIJEIJJJJJIFGIIIIIIIJIIGIJJGIIBHIJJJJIJIEH>CG;CHCHGHICHFFFFFFDDC;@CCEEDDCDDCCDDDDDB +@SRR9130495.78 D00236:723:HG32CBCX2:1:1108:1458:2216/1 +TTTCTTTCCACACATCCCACCTAACACCCAAACTAAGCACTCAGTGCTTGGAATCTCCCCACCCATTCCCTCACCCCTGCTCTTCCATCATTTCCTCCAGC ++ +CCCFFFFFHHHHHIDHIIJJJJHIIJFHIJIJIGIJHGIIIIGJEHIGIIJCGEEHJJJJJJJDHEHHGFFFFFDCDDDDDDDDDDDECCDDEEEDDDDDD +@SRR9130495.79 D00236:723:HG32CBCX2:1:1108:1634:2001/1 +TGTGCATTTCTCATTTTTCACGATTTTCAGTGATTTCGTCATTTTTCAAGTCGTCAAGTGGATGTTTATGATTTTCCATGATTTTCAGTTTTCTTGCCATA ++ +CCCFFFFFHHHHGJJJJJJJJIJHGIJJJJIIIIJJIGIIJJJIJJJIIFIIJJJJJIJJJIJIIIIIIJIJGJJJJFHHGGHGFFFFCEFFDEEDEEDDD +@SRR9130495.80 D00236:723:HG32CBCX2:1:1108:1566:2120/1 +GGACGAAGTAAGGGAGGAGCAACTGACAACATTCATCTTGTCTGTCTCCTCCACGTCCCGAGGTACAAGGCGGATGTCATTCTTACTAATTTTTTTCTTCT ++ +CCCFFFFFHHHHHIIJJJJIJJJIJJJJJJJIFIJJJIJIJIJIIJJIJIJJJJIJJIIJHHFFEEEEEDDDDDDDCDEDEDEEDDDEDDEECDDDDDDDD +@SRR9130495.81 D00236:723:HG32CBCX2:1:1108:1863:2047/1 +AAATTCGGACCCCTTGGGTGGAATATTCCTTACGAATTCAATGAGACAGATCTAAGAATCAGTGTGCAGCAACTCCACATGTTCCTGGACCAGTATGAGGT ++ +@BCFFFFFHHFHHHIJIJGIIIJIJJJJIIJJIIIIJJJJGIJJJIJJIEGIIGIJIJJJEGHHHGEEHFFFFDEEEDDDDEEEDDDDDDDBBCDDCCCCC +@SRR9130495.82 D00236:723:HG32CBCX2:1:1108:1844:2145/1 +TAACTCTCTGCCTGCGATGTCCCTACCTTCCAGAATGGTGCCATGACAACGGTGTCAACTACAAGATCGGAGAGAAGTGGGATCGGCAGGGAGAAAATGGC ++ +@CCFFFFFHHGHHJJJJJJJIJJJJJIJIIIHIIIJIIJJJJIJIIJIJJJJJJJJJIJJIIJEHHGHHFDFDDDDDCDCDDDDDDDDDDD?>BDDDDDDD +@SRR9130495.83 D00236:723:HG32CBCX2:1:1108:1772:2188/1 +GAGGTAGGGGTGTGTGTGAATGGGTGAGTGTGTGCCTATGCTTGTATGCCATATGAGAGAAAATGCAGCATTTAAAATCAGTGGTTAACGGCCAGCACAGT ++ +B@BFDFDDHHDDHHGIGIJIJGIJ:CFHHIGGIJJIEHGIIIJIIIFHGIJBHIJJJJJJCHHIHHHHHGFDFFFFEEEECEEDDDDDDDDDDBDDDDDCA +@SRR9130495.84 D00236:723:HG32CBCX2:1:1108:2103:2085/1 +TACAAATGTGCCAGGCACTCTTCTAAGTCCTCACATGCATGAAGTTATACAACTCTACAACAAACCTAGGAATATAAACTGAGGGCAGGGACCCCCAGCAA ++ +CCCFFFFFHHHHHJIJIJJJJJJJJJJJJIJJJJJJIJJJIJJJFHIJJJJIIJJJJJIJIIHIICHHIJJJIIIJJHHHFHHFDDDDDBDDDDDBDDDDD +@SRR9130495.85 D00236:723:HG32CBCX2:1:1108:2067:2091/1 +ACCAGCCCTGCTGCCACCCAGCCCACGTCCCGCGCGCCACCCATGCTGCTGCCTCGGAGCTGCAGGGAGCCGGGGAGCCAGGGCCACACGCAGGTGCAGCT ++ +?@@D?A:BF8DDFFFFFFFFAECBF@GFECAEFIIIIIIFBE?DBBD;@CCCCBBBBBB@B::AABBBBBB7>BBB>@BB?B>B>BB?/?A?BCCCBDDDD>@ +@SRR9130495.87 D00236:723:HG32CBCX2:1:1108:2387:2038/1 +GGCTAACCACTGCCTTGTCAAGTTGTGTAGAGTGAGATTCAGGGGTGTTGAAGTAATGTCCTTGTTACTTGCTGTAGGGCATCTGTTTTCTGTGTATCCCA ++ +CCCFFDDDDHGHGJEIGHHIJIHGGIIHGIIIIIEGBEHGGHIGGAFHIJJJJJJJJIDGHIIGIJJJIIHGFHEHFDFEDCEECDCDDACCCAACDFCCC +@SRR9130495.88 D00236:723:HG32CBCX2:1:1108:2285:2075/1 +CTGAAAGCTGAGCGTGAGCGTGGTATCACTATTGACATCTCCCTGTGGAAATTCGAGACCAGCAAATACTATGTGACCATCATTGATGCCCCAGGACACAG ++ +?;@DDBDDDFFD>ACGED@D8@):E*::??FFC@;FEF>E;CC=CC=@DDD>?;>A>A>A;AB3;A(;@:??DFBCB4<CCD@=BB@-(4812>>> +@SRR9130495.93 D00236:723:HG32CBCX2:1:1108:2748:2098/1 +CATCATCTTTTTTTTTTTTTTCTCCTGAAAACTGTCTAGTAGTTTGATATATTTTGTCCGAGGTTATTTCAAGTGTTTTTTTTTTTTTTTTTAAAACGGTG ++ +@@@DDDDDHHHHHIIFEHIIH8))7)7CEF9).)7;;>B@>9BD;;(6(55>DDDCBCC@/8-084@CC>C(((+4>?CBBBBBBBBBBB>&23:A(5?(( +@SRR9130495.94 D00236:723:HG32CBCX2:1:1108:2733:2156/1 +GACTGAGAAGAACAGAAAGGGAGAGAGAGGCCAATGGAAATACATGAGAAGGGAGAGAGGGAGAGAGAGGGAGGGAGGGAGGGAAGGAGGGGGAGAGGGAG ++ +CCCFFFEFGHHHHJJGIIIJJHIIHHIIJJJJJIJIIHGJJJGIJJJJJJJJJHGGHHIHHHFDFCDCDDD>BDDBDDDDDDD>BDD?BDDDDBDBDBD@D?ABD@BD?BBDDDC +@SRR9130495.96 D00236:723:HG32CBCX2:1:1108:2818:2076/1 +ACACTTCATGGCAACCTGGCTTAGATTCTTCAAAATTTCTGATCCTATACCAAAGCCTCTGTAATCACTCATCACGAAGAAGTCTTCAAGATACAGTAACT ++ +CCCFFFDDHGHHHJJJJIIJIIHIJHGCHIFEGGJJJJIJIGIIJJJIIJCEHIIIIJIBGHGGIIJIIBFGGGGHHGHFFFFDEEDECEDDDDCD>CCDE +@SRR9130495.97 D00236:723:HG32CBCX2:1:1108:2848:2112/1 +AACCTCTTCTCTTTGTCTTTCTCTTTATCCTTCTCCCTCTTGCCAGGACTGGACTCGCTGGTGATGGTGACGACGCTGGTGGGTAAGGTCTGCGCCCGACT ++ +@@BFFFFEHGHHGIJDEHIJIIIIIIJIFHIIIJEIDHIIIIJJIIIGIEIIJJIIIJFEHFHIIIGIIJIFBEDDBD>=?BB@CACCCAACDDBDBB5;6@;ACBCCCC?@AA>C>?<<<9)?FHFCAG=GFFG>FGGEGHIEEBEDEFC>C@::=BB@BCACCC@CA3:(8@C<8?CC +@SRR9130495.100 D00236:723:HG32CBCX2:1:1108:3014:2117/1 +CCCTCCTGAAAAGGTCCAGCTCCAAAGCCTGACCCGTAGCTGCAGAGAAGAAAGCTTTTCCTCTAAAGGCTGAGGAAAAGATGAAAAATCACTGCTAGAAC ++ +CCCFFFFFHHHHGIJIJJJJJJJJJJJJJJJIJJJIJJIJJJJIJGIDHHIIIJJIJJJJJIJJJHHHHHFFFFDEEEEDDDDDDDDDDDDDDDDDDDDDD +@SRR9130495.101 D00236:723:HG32CBCX2:1:1108:3316:2011/1 +GCAGAGCTGAATGGGCAAGCCCAGGACCCTTTTCAGACATTCTGCTGGCCTTTGGAAAGTGTACTCCTGTTGTATTTGATTACTTTTAGAGGACAGTACAT ++ +CCCFFDDFHHHGHJJJJIJFGIGHJGIJIIIIIHIIGIIJIIIIJJJIIIIJIIIGIJGIJJJJIIJJJEEEE?ECFFFFFFCCEDEEEDDDDDDDDEDCD +@SRR9130495.102 D00236:723:HG32CBCX2:1:1108:3264:2036/1 +GGGTGCTGGAGATAGCCCACGTACACTCCTTCTTGCTGGGGTACTTGTCAGGCCAGTTGGGGCTGGTGATGGTGCCACTGGTGGATGTCACCTTGTGTTCA ++ +=@<=B+AD>BFDFIIDEDGEIGFIIIIIICDFGFFGIII;D?F>?*/9BF>DAF;CFFGI>/:=?>7@BAA:;@5=A5>@=,98?:>@(;:4>ABAB?ABD +@SRR9130495.103 D00236:723:HG32CBCX2:1:1108:3400:2065/1 +TCTGTCTGTCACCAGGTTGGAGTGCAGTGGTAGGATCATGGCTCACTGCAGCCTCGTCCTCTTGGGTTCAAGCAATCCTCCTGCCTCAGCCTCCCAGGTAG ++ +@@BDFFFFHHHGHIJJFHEG@GHHIIAFD@HGGGEHIJJJGIJJGGGIHFDAHHHHJFCGGGHGJI;CHFCEDDFFFCEDEEDDDDDDDD<C +@SRR9130495.104 D00236:723:HG32CBCX2:1:1108:3468:2219/1 +TGCACTTCGTTCTCTTAATGAAACCCTTTGACTTAACCATGACTCCGCTCTGCTCTTGAGTTTGCAAGTGTGTGCGAGTGCCCGAGAGACAGTTTTTTTTT ++ +CCCFFEFFHHHHHJIJIIJJIIJJJIIJJIHIHJJJJJFHFHIIJIJJJJIJIJJJJJGGIIJJJGDIJJJIHHHGFFDDEEEDDDDDDDCCDCEDDDDDD +@SRR9130495.105 D00236:723:HG32CBCX2:1:1108:3722:2006/1 +TCCATAGTTTCGCAGAAGACTTGGAAGGATGTTGATGTATATGCAGGTCCATTATCAGTTTTTAAATTAGATGGTTTTCCCCAAGCTGCCCATGCGTCTAA ++ +CCCFFFDDHHHHHJJIJJIIHGHIGIIDFHHIIIHHIJJIJJIJIJJJJJJIIJJIJG=DHHJJIJIIIJJJJJIGHGHHFFBFDDEEEDDDDDDBBDDDD +@SRR9130495.106 D00236:723:HG32CBCX2:1:1108:3517:2148/1 +CTCTGTTCTGTTCCATTGATCTATATCTCTGTTTTGGTACCAGTACCATGCTGTTTTGGTTACTGTAGCCTTGTAGTATAGTTTGAAGTCAGGTAACGTGA ++ +CCCFFEBFHHHHFGGGIEEHIIJIJJIJJIIJIJJHIIJIIJJIIFHGIIIIJJJJJJFIJIJJJJGIIJIJCHIJIJHGJIJHHHHHHFFFFFFEEDECA +@SRR9130495.107 D00236:723:HG32CBCX2:1:1108:3927:2234/1 +CTGTGCTCTATGTACACGCCCATCTGTTTGCCTGACTACCACAAGCCGCTACCACCGTGCCGTTCCGTGTGCGAGCGCGCCAAGGCCGGCTGCTCGCCGCT ++ +@C@FFFFFHHHHHJJJJGIIJIJJIJEHIIGHGJJIJJJJJJIIGHHIJIJIGHJIIJIHHGFFDEDE?BBDDBDCDDDBDDDDBDD>BDBDDDDBDDDB< +@SRR9130495.108 D00236:723:HG32CBCX2:1:1108:4124:2011/1 +GACTCAGAGCCAGGGCCCGGGAACAGAGATGACTCGAAGGCTAGGGCTCCAGCCAGACTTACCGGCACACGTACACCTCTAGGGGTGGCAGGGTGCTGGGT ++ +CCCFFDDEGGGHHIJIIIJIIIIJIHHJJIJIIJIJIGGIIGIIHIGGIGHBHGHFEFFEECEDDDDDDDDBDDDDDCBACCDDDDDDBDDDDDDDDCD?9 +@SRR9130495.109 D00236:723:HG32CBCX2:1:1108:4130:2090/1 +TTCTATTTCTATAAACTGGCCTATTTTGGGTATTTCATATATATGGAAATATATAATTTGATTTTTTTGTTCTCTTAGCTGTATGTTTTCAGGATTCTTTC ++ +@BBFDFFFHHGHHIJJJJJJJIIIJJJJIJJJIJJJJIJJIIIJJJIJJJJIJIIJJJJJJJJJIHJIJJHHHHHHFFFFFFEEEDECEEDDDDDCDDEDD +@SRR9130495.110 D00236:723:HG32CBCX2:1:1108:4176:2091/1 +AAATTGAAAGTAAATGTATACTGTAGTCCCACGCACGAGTGAATAAAGGGGTGTCTAAAAGGAGTGTGTTCTCTTCCAGGCTGCATCTCTCGGTACTCAGC ++ +;8;ABD?+AA=ADBHIGBHE?ACCCCC +@SRR9130495.111 D00236:723:HG32CBCX2:1:1108:4108:2121/1 +ATGCGGAAGTAGGCAAAAATGATGTGCTAGACTACAAGAATTCCTTTTACAGAAAGTAACAAATACAGAGCCAAGAAAGTTTTTGTTAATTATCACGGTGT ++ +@@@ADADA@AD>FIIBBBFGIBGHJDCIGEGGGHHHIJIIJJJJGHIIEHHEGHJIHGGGIFAGGGGIIG>=CHHFD?@;CCEDDDDCDD>>ACDCB@8<5 +@SRR9130495.112 D00236:723:HG32CBCX2:1:1108:4384:2110/1 +ACACAGGCAGCAATGATGTCTTTACTTCTTTATTTTTTTCGACTTCATCTACAGAGCTTAGCACAGCCATTGGAACAAAATTGGAGCTCAGTGCACAGTTA ++ +@@@FDEFDDFF3CCF?FHCH@DEEGEFHIIFGBGGGDGIHAFBGDDHHIBAGGDGHE@CHAHBFFFFBDD +@SRR9130495.115 D00236:723:HG32CBCX2:1:1108:4445:2247/1 +TCTGTATTCTGTGTCATCTGCCATTCCTTGACTCCCTGCGCCCTTCAGCCCACAGGAAACGTGTGGATGACACACGAGGAGATGGAGTCTCTGACGGCAGC ++ +CCCFFDDDHHHHGJJJJIJJJJBHHJJIIGIIJJJIIGIFIJJIIIIGIJJIIIJIJCHIIJJJIHHFHEFFFFDDDDDBDDCDDCDCDDDDCCCDBBDDB +@SRR9130495.116 D00236:723:HG32CBCX2:1:1108:4698:2005/1 +GAGGGAAGGAGGGAGGGAAAGAAGAAGGGAGAGAGGGAGGAAGGCAGGACTGTCGATGCAAGTACCTCGCTTCCTTGTTCTTAACTCATTTGATTCTTGCT ++ +C@BFFFFFGHHGHIIIJJIBGGDHC@FEGDHIIIHGEHHEGCGIHHHFFFFDEEDDDEDDDDCDCCCDDDDDDDDDDDDDEDCCCDDDCDDDED:CCDDDD +@SRR9130495.117 D00236:723:HG32CBCX2:1:1108:4588:2182/1 +CTGGGGTGCAGTGGTGCAATCATAGCTCACTGCAGCCTCAATTTCCTAGGCTTAAGCATTTCTTCCACCTCAACTTCCCAAGTAGCCAGGATTACAAGCAC ++ +CCCFFADDFFHHGGHHGIIJIJJJJJJHIIJIJJIFIJJEIIJIJIGIJIJJJJJJIJJJIIHIIJHIIFFHGHHFFFFFEDEECCCCBDBDDDDDDCDBC +@SRR9130495.118 D00236:723:HG32CBCX2:1:1108:4964:2029/1 +CCCCGTCTCTACTGAAACACACACACACACACACACACACACACACACACAATTAGCCAGGCGTGGCAGCGTCTGCCTGTAGTCCCAGCTACTCAGGAGGC ++ +;8=:DDDDFFFAFIIFFBEIIEFIFIFIEFFFIIBEGEF?BF<4;A@EE/?;AB>7;7;>@?>B?''5<@;@?;0((4:@>34@@>:4<@>BAB@(948&+ +@SRR9130495.119 D00236:723:HG32CBCX2:1:1108:4831:2078/1 +GCGAAGAAAACTGAAAAAGGTGGAAAATTTAGAAATGTCCACTGTAGGACGTGGAATATGGCAAGAAAACTGAAAATCATGGAAAATGAGAAACATCCACT ++ +CCCFFFFFGFHHFFHGIHDICFHIGGIDHIIJJJJIIIIIGIGHGIJJJJJJJJJJJIJJJIJJIHHHHHFFFFFEEEEEEEDDDDDDDDDDDDDDDDCDD +@SRR9130495.120 D00236:723:HG32CBCX2:1:1108:4877:2117/1 +GCATAATGTTGCCACTGCACTCCAGCTGGGACGACAAAGACTGTCTCTAAAAAAGTAATAAATAAATAAAAGTTTGAAATGCATTGTCCTAGGTTTTAGTC ++ +CCCFFDEFHHHHHIIJJJJJIJIIIGIJJJJJJIIJIJJJIJJJJJJJJJJJJJIIHHGHHHHHFDFFFFFEEEEEEDDDDDCEEDEEDDDDDCDDDDDDD +@SRR9130495.121 D00236:723:HG32CBCX2:1:1108:4918:2158/1 +AAACATGTCAATGGCCAAAAAAAACAGACAATCAAAAAATGGACAAATATATGAACAGACATTTCTCACAAGAGGACATACAAATGGCCAGCAAATATATA ++ +CCCFFFFDHHGHHIIJIJJJIIIJJJJJJJIJJIJJJIIJJJJIJJIJJIHGFHHHHFFFFFEFEEEEEDDDDDDDDCDDDDDDDCCBCDDDDDDDDEEEE +@SRR9130495.122 D00236:723:HG32CBCX2:1:1108:4939:2211/1 +CCTGGTCTCAGCATTCCTCACACGTCATAGCGAGGCCCATGGCTGTAGAAATCCCACCATTCTCTTCTCCCCAGGCCTGGCATCCGTAGAAGCCTACAGCT ++ +@CCFFFFFHHHHDHIDIHIJIJJJJJIGGEGIJIIGIIIJJJGGIJJJJIGGHGIIIJJGHHHHHFFFFEFDEDDDDDDBDDDDDDDDD?CDDDDDDDDAC +@SRR9130495.123 D00236:723:HG32CBCX2:1:1108:5169:2188/1 +TCTGACCCCATGTCCTCAGGCCAGAACCCGGGAGCCTGTCAGAAAAGGTCTCTCACCTAGAGTCCATGCTCTGGAAGCTCCAGGAGGACCTGCAGAGGGTG ++ +??@DD?DFHDFHFIIIIGFHEGGDFFHIBHGIAFIGGIIIFI@CHE@FGH@CDGGIFHEEFCCED@DEEEECCCCCCCCCCCCCCBB8ABC?ACAAABBBB +@SRR9130495.124 D00236:723:HG32CBCX2:1:1108:5192:2231/1 +ACTCTCCTGGCCCACGAGAGAGTCCACACAGGAGAGAAACCTTACCAGTGTCATGAGTGCGGCAAGAACTTTAGTCAGAAATCCTACCTTCAAAGCCATCA ++ +CCCFFFFFHFHHGJJGEFGHGIIEIIFJJJIHGIJIIJIIIJIIGIEHHIGIHIJIIJIIBDFDDDDDDDDDCDDDCCDDDDDDDCDDCDDDDDCDDDDDA +@SRR9130495.125 D00236:723:HG32CBCX2:1:1108:5408:2041/1 +TGTGTGCATCCTCATGTGTCCTTGATAAGTGGTGTGATAAATGAAGGCTTTGCCACATTCCTTACACATGTAGGGCTTCTCTCCAGTGTGAGTCCTCTCAT ++ +@@@DDDEBFHHHHIIIHIFHIDHIIIJHHJIHEGFIIHIJJIIJJEIJGHHIEIEGIIJIJJJGIGHGJJIIGIGIHJEHHHHHFFEFFFCC@CEEDDDDE +@SRR9130495.126 D00236:723:HG32CBCX2:1:1108:5351:2057/1 +CTCTATATATTTTAACAAATGCATAATGTCATGTGTTTACCATTACAGTAGGATAAAGAACAGTCTCATTGCCTTAAAAAGTTCCCTAACATTTTAATTGT ++ +CCCFFDEDFHHHHJIJIIJJJIJJJHJJJJIJIIIHHIJIJIJJJJIIHIJJIIJJJJJIJJJJJJIJIJIJIIJJJJJJJGGIGHHFHFFFFFFFEEEEE +@SRR9130495.127 D00236:723:HG32CBCX2:1:1108:5475:2108/1 +AGCCCAGAAGGCTGGACACACCTCCCCCTCACCCCATCCCGCTCCCCAATCAACCCAGTCCTCAAGAAGCACACTGTGGCTGCTTGCTCTCTTGCCCCCCT ++ +CCCFFDFFHGHGHJJIJJJIGIIIHIGIIJIIJJJIJJJHGIJIJIIIJHHGHHFFEDEEEECCDDDDDDDDDDDDDDDDDDDDDDDDDDCCDCDDDDDDB +@SRR9130495.128 D00236:723:HG32CBCX2:1:1108:5542:2138/1 +TGGCTAGCTACTGCTGCTGCTGCATCAAAGCCCAAATATTCACTGGCATCAGCTGTTTTGTTCTTTAGCATATTAGTAAAGTGCTCATTTAGAGACATCTT ++ +@CCFFFFFHHHHGJIJJIJJJIJJJJJJJJJJJJJJIGGIJJJJJHJJJJJJJJJHIEIIJJJIIJJJIJIIJJJJHHHHHHHF@DFFFFEDEEEEDDCDD +@SRR9130495.129 D00236:723:HG32CBCX2:1:1108:5707:2147/1 +CCAGCATCACTCATGGAACCGGAGGCACTAAGGCCCCTCGGGAGACGCTGAGCAGGTGGGTAGAGGCATACTTCTGGGAGATGGCATCAAGAGCCAGTCAA ++ +CC@FFDDFFDHG>FFFHGGIJIEIIIHIGIGHBHCEHGGGFH@FHGIHHFBFDEEDDEDDDDBDC?BBDCDDDDDC:?A?BDDDCCDC>ACDDDBDDACCC +@SRR9130495.130 D00236:723:HG32CBCX2:1:1108:5614:2168/1 +AAACCATGTCTCTACTAAAACTACAAAAATTAGCTGGGCAACATGGTGGGTGCCTGTATCCCAGCTACCTGGGAGGGTGAGGCACGAGAATCACTTGAACC ++ +CCCFFFFFHHHHHIJJJJIJGJIJJJIJJJJIJJJJJIJJJJIJJHIIHJIJJJJJJJJJJJJJJJJGHFHHF@DDDDDDDDDDDDDDDBDDDDDDDDDDD +@SRR9130495.131 D00236:723:HG32CBCX2:1:1108:5985:2027/1 +GCGGCAGCGGCCGCGATGGAAGAACTTACGGCGTTCGTCTCCAAGTCTTTTGACCAGAAAGTGAAGGAGAAGAAGGAGGCCATCACGTACCGGGAGGTGCT ++ +CCCFFFDDHHDGHFIJFHFFHHBFGHGEIJJJFFDDDDDDDDDDD@CCDCDDDDDAAACACDC@CCDBBBDBD@ +@SRR9130495.132 D00236:723:HG32CBCX2:1:1108:5816:2071/1 +TTTACATATAAGAACCTGATGACCTTTTGTTTTTGTCCAGGAGAGTCCTTCTTGTCTACGAAATGCAGCTATCACAGCAGCTGGACTTGTTTCCTGAATGC ++ +C@CFFDDAFFFHHHHHHGFIHJIJFHHHCAAEHIGHJGCCGHIHEHJJJEHGIIIFIGBBAEHGIJIGIIHHEHHHFFFFEECCABCDCCCCACDDACDA: +@SRR9130495.133 D00236:723:HG32CBCX2:1:1108:5835:2081/1 +CCAGGGCTCCAAGGGGCTGGTTACGAAGTGTCTCCTGCTGCATGAGGTCCCCACGGGAGAGATTGTGGTCCGCCTTGACCTGCAGTTGTTTGATGAGCCGT ++ +@CCDDDFFHHHGHGJGJFHIEHIGCGHIGJGIIIJJJJJJJJJIIIEIJFGIJJIJGCCDDBDDCDDDBDDDDCDDDDDDDD>BACDDDEDDCBD +@SRR9130495.134 D00236:723:HG32CBCX2:1:1108:5841:2101/1 +GGGCATGGTGGCATGCGCCTGTAGTCCCAGCTATTCGGGAAGCTGAGGCAGGAAAATCTCTTGAACCCAGGAGGCGGAGGTTGCAGTGAGCCAAGCTTGCA ++ +@CCF?BDDHFHGHIIIIIIIIIGHGHHIIIFIIIIIGGFGGIIIIEFGGEGHCD>CGGFHHHGGHFFFCDDADDDDDDDBDBCDCCCCA@CCCCBDDDDDD +@SRR9130495.135 D00236:723:HG32CBCX2:1:1108:6165:2044/1 +TTTATACCATTTTTTTTTTTAGCATATATCCTTGTACTTTATAGGAATTATTTGCTTTATTCTCTTGTGACTTGTAAATTGATGTACTTAATTAAATCTTT ++ +@@CBAB;DHFFHHIGIIGGHGFF@?BGB@8=FHEGHIGD=@CGHIA;@EHFHGHBFFFCBD;>(>@A@C>>;>CA;;35>@3;>5>,;3>:;(:@:>:@@C +@SRR9130495.136 D00236:723:HG32CBCX2:1:1108:6059:2069/1 +CTATGACCGCTATGTTGCCATCTGTAGCCCACTGCTTTATAACACTGTAATGTCCCACAAGGTCTGTTCCATAATGATGGCTGTGGTATACTCACTGGGCT ++ +CCBFFDBEHHHHFEGIIGHGIIIJIIHIJIFIJJJJJJJJJJIIJJIJJJJIIHHIJIIIFIHIJFIGIIIHGGHHHHFFFFDEEEEEDEFEDDDCDDDBC +@SRR9130495.137 D00236:723:HG32CBCX2:1:1108:6161:2181/1 +ATGAAGCAACAACCTTATAGGCATTTTAACTCATAGGTTTTAAAACTTAAGGTTATTTTCATAGGAGTCCCTTTTAGCAGAAATGCTCACCACAGGACCAG ++ +@@CGGDD@4???BDHCH@GH<=FHGEGGGIGCEG@E7ACH@:77?C@A@CBAA???2FFFIGIIGIIIIFDADBDDDDDDDBBBBBBCDD@CDDDD?BDDDDDDCDDBDDDBDDDCCCCCBBCCCDCCCCDDAC>ABDDDCDDDDA@C +@SRR9130495.144 D00236:723:HG32CBCX2:1:1108:6837:2146/1 +CCTGTTATTTTAGTTGTTAAAGGTGGCATTCTGTTCTTGTGGCTGTCTTCTTTTAGGTTTGTTGAGGGATTACCTTCTTGTTTTTTCTAGGGCATTGTTCC ++ +BCCFDDFDHFDHFGIIIIJIGIIJJIDGHIJIIJJJJJJGFIIIHFHHIJJJIGDGIGHGHIJICHGGEHGCHGFEHFHHFDDDDDDDDDDDC?CDDDDCC +@SRR9130495.145 D00236:723:HG32CBCX2:1:1108:6804:2189/1 +TGAATCTCTCTTGGCCTCCTCCCCTCTCATGTCCCCTCCTCCCTCCTCTCCACTTACTCCTCCTCCTCCCCTCCCTCCTCCCAGATGGTTCTGTGTCTTTT ++ +CCCFFEFFHHGHHJJJIJJIJJJJIJJJJJIJIFIJIGIIGGJIJJIIIIIGIIJIJIJGIIIJIJJHHHFDFFDCDCCDDDCDBCCDCDDD@ACCCDDDD +@SRR9130495.146 D00236:723:HG32CBCX2:1:1108:6940:2229/1 +CTTAATGCCACTATCACCACTTCCTTCAAGAGTGAGGGAGAGGAAGAGGAGGAAGAGGAGGAGGAAGAAGAGGAGGAGGAGGAAGAGGAGGGTGAAGGGGA ++ +@@@DBDDEFHHHHGIJIEGGIGECHIFIIJGFHHACCF?D:DFF;?FHH9DFCGGHFG@CA?AB?DD>?A@BDDBB=?B5@BBFCAA@A;;5?BB9;=>;BB?1>A?ABDCC +@SRR9130495.149 D00236:723:HG32CBCX2:1:1108:7167:2101/1 +TTTCATGTTTTAGGTCTTGTAAGCAAGATTTTTCCTGTTGAAAAACTGGTTGAAGAAGCCATCCAATGTGCAGAAAAAATTGCCAGCAATTCTAAAATCGT ++ +?@?DB?DDHHGDHIHHGBIECFDHHE>C7?BB7;@A(5==;88323>CDC9B +@SRR9130495.152 D00236:723:HG32CBCX2:1:1108:7449:2110/1 +GGCTTCAGGAGCTTCAGAAGTTAAGAGCTGCAAAAAAGAAGAAAAAGGATCGGCCAAGTAAAGACTGTTCCAAGTTGGACATGCTTGCTAGAAATTTCCAG ++ +CCCFFDFEHGHHGJIIBEEHHIIIHHIGGJIIJIIGIIGGHIIIJIGGGGGGGIIJJHHFHHGFFFFFEEEEEEEDDDDDDDCDDEDDDDDDDDDDDDEDC +@SRR9130495.153 D00236:723:HG32CBCX2:1:1108:7499:2197/1 +TTCTCATAGTTCAGCTTCCACTTGCGGTAGCTTGTTCCACTTGCGGAACATGTGGTGTTTGGTTTTTTGTACCTGCACTAGTTTGCTGAGAAAGATCGGAA ++ +@@@DDDDEHHFFHABECCAFHHHFDGIHJIIEFGHIIGIGEHEBGG0AEDHGFFFGIDG@EH=ADEBADDE@CCCBCACDDDEEDDCCCBCCC@CC>AB@@ +@SRR9130495.154 D00236:723:HG32CBCX2:1:1108:7309:2205/1 +GGAGGCTGAGGCAGGAGAATCGCTTGGACCCGGGAGGTGTAGGTTGCAGTGAGCCAAGATTGCGCCACTGCACTCCAGCCTGGGTGACAAAGTGAGATATT ++ +BC@FFFDFDHHGFIGIIIJIJJJJJIJJJIIJJJIIIHHIJIJJJIJHHHHGHFFFEBAEECEDDB:@CDDDDCDDDDDDDDDBCBDCDCDDDCDBDCC?ACDD34>C@BD<>>:CB<>@BA8 +@SRR9130495.156 D00236:723:HG32CBCX2:1:1108:7518:2119/1 +TTATCAAAGAGGCCCAAGAGAAACCACTTGTCTGACTTCTACCATATGAGTTTAGAATAAGATGATGGCTGCCTATGAGGAAGCAGGCCCTCAACAGATAC ++ +@@@DDBD4CFFAAHII=G9FDHG;?F@;EEBEFCF>BGBGDBECC@BBBBBBBCCABC@CC +@SRR9130495.157 D00236:723:HG32CBCX2:1:1108:7577:2169/1 +AGTTACTTAATATACCTTAGCCGAAACTTCTGCACTGATTTCCTCCTGTGTTTCAGCCAGCCGCTTTTTGGCAAGTTCGGTTCTCCGATCACACTCTGCAA ++ +@@@DDDFFFFHGHIICGHFH@FGGHGHHJGIHJIJIJGIIIBDHCBGGHEHIJJIGIIIBGIEIGGHHCEBDFEDECD?@DDDDDDDDDDBCCDDDDDDC> +@SRR9130495.158 D00236:723:HG32CBCX2:1:1108:7659:2196/1 +TTCTGATTTTTGCTGCAGCTTCTGCTTATAATCATATGGCCAGTTGTGCTTGTCAGAGTAATGGTGAAGTCCACAAAACAAATTTCCACATCGGCAGTCAA ++ +CCCFDDDDHDFHFGIFCHIII9FHHIGGHHIJJJJIJJEHGEGIIJJJJJJJJDHGI:DFGIIGHGJGCGHGIJJGIIHGHGFFECB@CEC@B@BDD?CCD +@SRR9130495.159 D00236:723:HG32CBCX2:1:1108:7733:2213/1 +GGCCAGATGTTTCTGTAAAGATTGAATTAGATCCCCAGGGAGAGGCAGCACAAAGTGCAAATGAATCAAAAACTGAGTAGAATATTGTAGAGTGCCAATTA ++ +@<@DDA+AFFHHHIIFBHC@@F>@>CC: +@SRR9130495.160 D00236:723:HG32CBCX2:1:1108:7590:2217/1 +GGGGCTGGGCCCACCTGGGACAGAGGGCCACATGTAGAGGCAGCGCTCCCCCGTCTTGAGCTGATCTTTGCAGTCGAATAGCATGAGGTTGGCCCAAGCGA ++ +CC@FFDDDGHHDHIJDGIIACBDDBBBDDD@ +@SRR9130495.161 D00236:723:HG32CBCX2:1:1108:7735:2228/1 +GCAGCACTGTCTGAGTATGGGAGCAAAGCCTAATCTGGCTTGCCCGGCCTCTCACCTCTGTGGCGCTCTGCATCATGGTGCTTCTTGTCATCTTTTATTGC ++ +?@;DDDDDFCFFHIHHGBHIBH?FHIBDEHB@GEIHIEHGHAFFHGEEH<@CC@C@CCA +@SRR9130495.162 D00236:723:HG32CBCX2:1:1108:7898:2065/1 +GTTGGCTTCCCCCTCCCCTCTCCCGTGAGCTGAAAAGCAACAAGGGCTCCACCAGCCTGCAAAATAAGACTTGGGGGGGGGGGGGCAGGGATTGCTTTTTT ++ +@@@FDDDDHHFHFIJIFHIIJJJDHFGIGIGJAFHIDG>@GGFHGGHJIGCHIIGEEHFGF@CFEECC>;>CCABBD<99B@BD99&)&&+9(3(4>(+:0 +@SRR9130495.163 D00236:723:HG32CBCX2:1:1108:7872:2066/1 +CACGCTGGATGAGTTCCTGTTCAGCGACCTGCAGGCGCTGGAAGTGCTGTTGCTCTACAATAACCACATTGTGGTGGTGGACCGGAATGCCTTTGAGGACA ++ +CCCFFFFFGHGGHJJJJJJJJJJIJJJJJJHJJJJJIJJIJJJIGIJJIJJJJIHHHHHHFFDFFEDDEEEEDDDDBDDDDDDDDDDDDDDDDDDDDDDDD +@SRR9130495.164 D00236:723:HG32CBCX2:1:1108:7826:2191/1 +ATCTCTGGACCCAAACTGGAGGGTGACATTAAAGTTCCCAGGGTGGATTTGAAGGGCCCAGAAGTGGACATTTCTGCTCCCAAGGTCAATATTGATGGGAA ++ +CCCFFEFFGHHGHIHHIIJIIIJJIJIGIIJIHIGIJJJJIJJBFGGIJJIJJJJJIJIHFHHFFF@EEDEEFEEDDDDDDDDDBACDDF@CDEDEDDBDD +@SRR9130495.165 D00236:723:HG32CBCX2:1:1108:7791:2195/1 +GGAGAACAGCGTGTAGAGCACTCACAGTCTGCTGCCTTCAGGTGTGGGAGGCACTGCTCACACTGATCTTCTTCCCGGTGTGTGTGGTGTTTGCCTGGATG ++ +CCCFFDEFFGHHHJDIIJJIFJJJJJIJJJGIJJIIJIIIJIJIIGEGHHJJJJJIIFIJJJHHHHFHFFDDFFEDC>9;?BBDDD?CDDDDDDDCC?BDC +@SRR9130495.166 D00236:723:HG32CBCX2:1:1108:7767:2199/1 +GACTAGCCTGGCCAACATGGCAAAACCCAGTCTCTATTAAAAATACAAAAATTAGCTGGGCATGGTGGTGCACGCCTGTAGTCCCAGCTATTCAAGAGGCT ++ +@@@DDDFFFHHFBHBHBDEHHGGGHIIJIIHIHJIEEEIGHEIHIIGHIIHHGJIEHGI?G@CDHI=CA?BDFFACDCCDFCC32??A +@SRR9130495.167 D00236:723:HG32CBCX2:1:1108:7824:2210/1 +GCACCACCGTGCCTGGCTAATTTTTATATATTTAGTAGAGATTGGGTTTCACTGTGTTGGCCAGGCTGATCTTGAACTCTGGACCTCAGGTGATCCTCCCG ++ +@@@FFDDFDFAHHJJIJIIGHHHHHIIJIIDGG>GHHIGGCGHGIEHGGH>FFHJJJHDGBGHJCGGGHFEHHHHFFFFFECDECEDDDCDDDDCCDDCDD +@SRR9130495.168 D00236:723:HG32CBCX2:1:1108:8205:2084/1 +CTTAGCCGCTGGTGATGCTAAGGGCATGGTCAAAGTGTGGCAGCTGAGCACAGCCTTCACAGAACAAGGGCCCCGGGAGGTGGAGGACTTGGATCAGCTAG ++ +CCCFFDEDFFHHHJEGIDHHIIIIJJJIJGIJJJGHJIJIJJJIIIJIGGIIGIJJIGHIIJGEFHGBEFDDDBDDD;>B2<@BBDBBCCCCDDDDDDDDD +@SRR9130495.169 D00236:723:HG32CBCX2:1:1108:8202:2124/1 +GAGACTCTTGCACACATACCGGGGAGCTGGCTCACCCTGGCCCCTCCATCCTGTCAGACTGAAGAGAACAAGTGTCTTAATTTGGGTTTTTCTTATTATTA ++ +CCCFFEFDHFHGHGJIIIJJIJJJIIIGIJJJJFIJJHGIJGHIIJJEEEHFGFFEFECCEEEEDDDDCCAD>CCDDDDCCD?@@A=?8=?=BA93>CA??B@A????8CD(8&8?()(+224@?@>35 +@SRR9130495.179 D00236:723:HG32CBCX2:1:1108:8868:2131/1 +GTACATTGTATCTTTGTTCTCATTAGTTTCAGAGAAATTATTGATTTCTGCCTTTATTTCATTATTTACCCAAGAGTGATTTGGAAGCAGGTTGTTCAGTT ++ +<;;B?D>DFC:DBF@AEDHHAHHGH:A:AC4?BFFEDA?ABD@ACCD:> +@SRR9130495.183 D00236:723:HG32CBCX2:1:1108:9106:2031/1 +CTAGAAATCCTGGATTTTCAGCACAATAACTTAGCCAGGCTCTGGAAACGCGCAAACCCCGGTGGTCCCGTTAATTTCCTGAAGGGGCTGTCTCACCTCCA ++ +C@CFFDFFGGHHFJHIIJGIHCCEHHIGIFIIHIJJFIGJIGIJJIIJHIFGIJIJFFHHFDAD@BCCBDDDDBCC@CDDCCDDAEFC'8;&+)+((&28&&&+((&)&&++((++8((2(((25(&&&(++(0&&&(+((+4(+ +@SRR9130495.186 D00236:723:HG32CBCX2:1:1108:9230:2213/1 +ACTTAGTGCAGTACCCACTATTCCCGCTCAGGCTCCGAATAGTAGATAGAGGGTTCCGATATCTTTGTGATTGGTTGAGAATAATCAACGATTAATGAACA ++ +CCCFFFFEHGFFHFIICIIFIJHHGBHHGIGJJIJGGHIGFHIGIIJJJIIGJCFIJI@EFDFEDFFCCEEEEDDDBDDDDDDDECCDD@BDDDCDDDCDC +@SRR9130495.187 D00236:723:HG32CBCX2:1:1108:9264:2024/1 +AACATAAGGTTTCTCATAAAACAAAGAAAAATGTCAATTCAGTTGTGAATTCATATTGATACCTGGAACTCTCCTGCTAGACCACCTCTAAAGGCCCAGGG ++ +CCCFFFFFHHHGHIJJIDJIJJJDHIIJJJJIJJJJJJJIJJGCHIIJJJJJJJJJJIHJJJJJJGIJJIJIJIIIIJJHHHHGFFFFFECEEDDDDBBBB +@SRR9130495.188 D00236:723:HG32CBCX2:1:1108:9293:2034/1 +GTGGGGAGGTTTGGGAGTGAGCAGCACACCCCAGTTAGACTCCTGTTGGGTTTCATAGGAGCTGGCTGCTGAATGTAAGAGTGCAGGCTACCCCGGGACTT ++ +@@@FDA;1DAFHFIIFBGIGHGADHIGIIIIIIIIHBFEHIIIIIIIIHIACEEEHHBD@CDECECCBBCCACCCCEECCCCCCCCBBBCCCB?9>>>>BC +@SRR9130495.189 D00236:723:HG32CBCX2:1:1108:9484:2048/1 +ATGTAGAGAGAGGGAAAAAAGGAGAGAGAGAAGGATAAAGAGAAGGATGCACAAGAAGACCAAAATACCTGATCATGTAGGGGAGAGCCTCTGGGAGAAGG ++ +@@@DFDDDCDDFHICFHHDGIIHHCHCFFDGHHDCGIJIH@FFHFHGIIGIJIGIGF@CEBDFF@EECDCCCCCCDDEEEDDDDDDDDDDCDDCD<@BDCB +@SRR9130495.190 D00236:723:HG32CBCX2:1:1108:9388:2219/1 +AGCTGCTGCGAGATGGTGGCTTGCATCTCCTTGGACGGCCGCTTGTTCTCCTTGAAGATGGCAATCAGCGTGCGGCGCTGCAGGTCTGTGAACACGAGGCG ++ +B?>3=?>;@DF@>CACC>;>@A>',,88>>-09599(+8>C95>>>00 +@SRR9130495.191 D00236:723:HG32CBCX2:1:1108:9404:2245/1 +TCCGGCTGGTACCTTCATAACTACAGTAATAGAAGACATTGAGTGCCTCCACCGCAGCTGGCCCTCTCTGTTTGTAGCCAAAGATCAGATCTATCCATTCA ++ +CCCFFFFFHHHHHJJIJIIJEIIJJJJJIJJJIJJJIJIIIIIJJJIJJIIJJJJEIJJIHIGHHHFFFFFFDEEEEEDDDDDDDDDDDDDEDCDDDCDCC +@SRR9130495.192 D00236:723:HG32CBCX2:1:1108:9632:2134/1 +ATAGTGGCTGCTGATGGATGTGCTCTATGCAAGGGAGGTGCTCACTATTTCTGTTCGTCAATTTGTAACCCACGGGAGGAAAGGGAACAAAGAGTGAACAA ++ +CCCFFFFFHHHGAEFFHIICHGIJHGFIIIHIJDGIJJIIIEGIJJIIFHEGHGIICHIIFIJJJJIIJJHHHFFDBDD?BDDDDBDBDDBCDD:@CCCCD +@SRR9130495.193 D00236:723:HG32CBCX2:1:1108:9647:2175/1 +AATACCAGCCCAAGACTTTGGGAGAAGGGAAGAAAACAAAGTAAAATAACTTACCACTTTGGCCCAGTCCGAGAACAAGTGAAAATACCCAGGCTGCCCCA ++ +CCCFFFDFGHHFHIIJJGIIIJDIIJIJJJJIIHIIIIJJJHCFHHFHIJJJJJJGIHJJJIJJHGHHHFFFDDDDDCD>CCDDDDDDCDDDBDDDDDDDD +@SRR9130495.194 D00236:723:HG32CBCX2:1:1108:9552:2194/1 +CCATGCCGACACAGGTAGATGGTACGGGGCTGCACGTGGATGTTCATCAGGTAGTATACAATTCGGCTCTGGATGTGGTCCTGCACTCTGTTCACCAAGAA ++ +@@CFFFFFGHGHHJJJIJJJJIJJJIGHFEGGIFIJIJIIIIIJJIIJJIHHHHHHHFFFFFFFDCDDDC@@ACDDCDDDDDDDDDDDDCDDD@CCDDDDD +@SRR9130495.195 D00236:723:HG32CBCX2:1:1108:9620:2235/1 +CCAATGATGGCCAACTAGGCCATCTTCTACTATGTACGCAGCTAGAGGCACGAGCGCTGGGGGTACCGATTAGTTCATATTGGTGTTCCACCTATAGGGTT ++ +===BD?DBAABD8AC3?F?D9C6'5;:>7<<>8:(',&22>(((:>3>+:(+28(43>@B(>:>A((32 +@SRR9130495.196 D00236:723:HG32CBCX2:1:1108:9908:2124/1 +TCTTGTGAAGAAGATGCTGTTGGAAGCCTCTAAGAAGCCCGAACTGAATGCTCTTATAAACAATACCAGAGGAATTATTTTTTACAGTGTCCCTCACCATG ++ +CCCFFFFFHGDFGIIJJIJJIGGJJIIJJIIJHIIIIJJJJI>HHIFIJIJIJJIIHIHIJJJJIHIHHHGFDEFFEEEEEEDDDDDFDEDCCDCDDDDDD +@SRR9130495.197 D00236:723:HG32CBCX2:1:1108:9923:2206/1 +TGGGGCTGTGAACCGAAGTCTGCTCCTTTGCGTGAGCCACCCCTGCAGCCCCTCCCACAGTTCCTGAGGAGCCTTTAGTCCTCGTCCTTTCTCAGCTGTAT ++ +@BCFFDAFHHHHHIIIIHIIJIIJIIJJJIIIJJIGGIIIJJFGGGGGEIIIGFHHEFFFEECCCC@CB@BDDDCDDCCDCCDDABBBCDDCC@CCDCCCD +@SRR9130495.198 D00236:723:HG32CBCX2:1:1108:10131:2036/1 +ATGTGCTCAAAGGCTGGGTGGACCTTACCTCCAGTAAACCCCACGTTGTGAAGAAATCCATCAAGTACCTGGAACAAGGAACTCAAGACACCAAAGATGTG ++ +@CCFFFDDFFBHDHIIIBFEGFGHGHGDFHFGIJJIIHDGEGHIJHFHIIIIJJJJJIIIFHHHFHFFFFFFBAEAACBBCADDDDDDDDADBABCCC>AA +@SRR9130495.199 D00236:723:HG32CBCX2:1:1108:10246:2089/1 +GCCCTGGGATTGTCCCTCTGGGCACAGGGAGTCCTGGGGTTGTCCCTCTGAGTAGTTCTGTTGGGAGAGGAGGCCCTGGGATTGTCCCTCTGGGTACAGGG ++ +CCCFFBDDHHHFHJIIIJJJJIIIIIFIIEHGIGJIJDHJIJIIJJFJIJ@FFCHJJJBEGEHHHDFDCD@DBB;=?A?@BDDDCACDDDDD@?CCCCDCB +@SRR9130495.200 D00236:723:HG32CBCX2:1:1108:10051:2156/1 +ATGGAGGATGGCACCCTGCAGGCTGGCCCAGGAGGTGCCAGTGGGCCTCGTGCCCTGGAAATAAATAAAATGATTTCTTTTTGGAGGAATGCTCATAAACG ++ +@@CDFFDFGFHFFIJGGIICCDDADDB diff --git a/docs/notebooks/example.parquet b/docs/notebooks/example.parquet new file mode 100644 index 0000000000000000000000000000000000000000..017772b75ddd5cc787ad49beb2b077e023a560af GIT binary patch literal 20352 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 Nd1+4Hm4k1k?{$61mUoJMOGi;v{oi7S;D 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\n", + "[String, String, String, String]\n", + "\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "200rows [00:00, 67012.37rows/s]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "200rows [00:00, 138084.08rows/s]\n" + ] + }, + { + "data": { + "text/plain": [ + "'{\"base_quality_warn\":\"pass\",\"base_per_pos_data\":[{\"pos\":72,\"average\":66.265,\"upper\":74.0,\"lower\":35.0,\"q1\":66.0,\"q3\":70.0,\"median\":68.0},{\"pos\":80,\"average\":65.61,\"upper\":74.0,\"lower\":35.0,\"q1\":65.0,\"q3\":69.0,\"median\":68.0},{\"pos\":81,\"average\":65.76,\"upper\":74.0,\"lower\":35.0,\"q1\":66.0,\"q3\":69.0,\"median\":68.0},{\"pos\":83,\"average\":65.03,\"upper\":73.0,\"lower\":35.0,\"q1\":66.0,\"q3\":68.0,\"median\":68.0},{\"pos\":85,\"average\":65.195,\"upper\":73.0,\"lower\":35.0,\"q1\":66.0,\"q3\":68.0,\"median\":68.0},{\"pos\":19,\"average\":71.425,\"upper\":74.0,\"lower\":43.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":86,\"average\":64.815,\"upper\":73.0,\"lower\":35.0,\"q1\":66.0,\"q3\":68.0,\"median\":68.0},{\"pos\":91,\"average\":65.665,\"upper\":73.0,\"lower\":38.0,\"q1\":65.0,\"q3\":68.0,\"median\":68.0},{\"pos\":92,\"average\":64.835,\"upper\":72.0,\"lower\":38.0,\"q1\":65.0,\"q3\":68.0,\"median\":68.0},{\"pos\":94,\"average\":63.775,\"upper\":73.0,\"lower\":35.0,\"q1\":65.0,\"q3\":68.0,\"median\":67.0},{\"pos\":51,\"average\":70.53,\"upper\":74.0,\"lower\":40.0,\"q1\":69.0,\"q3\":74.0,\"median\":72.0},{\"pos\":78,\"average\":64.46,\"upper\":74.0,\"lower\":35.0,\"q1\":64.0,\"q3\":69.0,\"median\":68.0},{\"pos\":61,\"average\":68.99,\"upper\":74.0,\"lower\":40.0,\"q1\":68.0,\"q3\":73.0,\"median\":71.0},{\"pos\":88,\"average\":65.065,\"upper\":72.0,\"lower\":38.0,\"q1\":66.0,\"q3\":68.0,\"median\":68.0},{\"pos\":74,\"average\":63.83,\"upper\":74.0,\"lower\":35.0,\"q1\":65.0,\"q3\":70.0,\"median\":68.0},{\"pos\":1,\"average\":64.21,\"upper\":67.0,\"lower\":43.0,\"q1\":64.0,\"q3\":67.0,\"median\":67.0},{\"pos\":4,\"average\":68.68,\"upper\":70.0,\"lower\":49.0,\"q1\":68.0,\"q3\":70.0,\"median\":70.0},{\"pos\":0,\"average\":63.135,\"upper\":67.0,\"lower\":35.0,\"q1\":64.0,\"q3\":67.0,\"median\":66.0},{\"pos\":68,\"average\":68.91,\"upper\":74.0,\"lower\":40.0,\"q1\":67.0,\"q3\":72.0,\"median\":69.0},{\"pos\":56,\"average\":70.59,\"upper\":74.0,\"lower\":38.0,\"q1\":69.0,\"q3\":73.0,\"median\":72.0},{\"pos\":82,\"average\":64.525,\"upper\":74.0,\"lower\":35.0,\"q1\":66.0,\"q3\":68.0,\"median\":68.0},{\"pos\":97,\"average\":63.67,\"upper\":71.0,\"lower\":35.0,\"q1\":64.0,\"q3\":68.0,\"median\":67.0},{\"pos\":100,\"average\":64.105,\"upper\":70.0,\"lower\":40.0,\"q1\":64.0,\"q3\":68.0,\"median\":67.0},{\"pos\":2,\"average\":65.015,\"upper\":67.0,\"lower\":49.0,\"q1\":64.0,\"q3\":67.0,\"median\":67.0},{\"pos\":33,\"average\":71.245,\"upper\":74.0,\"lower\":40.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":34,\"average\":71.205,\"upper\":74.0,\"lower\":51.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":28,\"average\":71.445,\"upper\":74.0,\"lower\":49.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":65,\"average\":68.995,\"upper\":74.0,\"lower\":38.0,\"q1\":68.0,\"q3\":72.0,\"median\":70.0},{\"pos\":12,\"average\":70.5,\"upper\":72.0,\"lower\":52.0,\"q1\":70.0,\"q3\":72.0,\"median\":72.0},{\"pos\":3,\"average\":68.69,\"upper\":70.0,\"lower\":52.0,\"q1\":68.0,\"q3\":70.0,\"median\":70.0},{\"pos\":9,\"average\":70.36,\"upper\":72.0,\"lower\":52.0,\"q1\":70.0,\"q3\":72.0,\"median\":72.0},{\"pos\":39,\"average\":70.895,\"upper\":74.0,\"lower\":39.0,\"q1\":71.0,\"q3\":73.0,\"median\":73.0},{\"pos\":57,\"average\":70.35,\"upper\":74.0,\"lower\":38.0,\"q1\":69.0,\"q3\":73.0,\"median\":72.0},{\"pos\":70,\"average\":66.565,\"upper\":74.0,\"lower\":40.0,\"q1\":67.0,\"q3\":71.0,\"median\":68.0},{\"pos\":13,\"average\":71.94,\"upper\":74.0,\"lower\":58.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":46,\"average\":70.79,\"upper\":74.0,\"lower\":40.0,\"q1\":70.0,\"q3\":74.0,\"median\":73.0},{\"pos\":76,\"average\":63.265,\"upper\":74.0,\"lower\":35.0,\"q1\":64.0,\"q3\":70.0,\"median\":68.0},{\"pos\":44,\"average\":70.565,\"upper\":74.0,\"lower\":39.0,\"q1\":70.0,\"q3\":74.0,\"median\":73.0},{\"pos\":71,\"average\":66.005,\"upper\":74.0,\"lower\":35.0,\"q1\":66.0,\"q3\":71.0,\"median\":68.0},{\"pos\":54,\"average\":70.59,\"upper\":74.0,\"lower\":38.0,\"q1\":69.0,\"q3\":74.0,\"median\":73.0},{\"pos\":67,\"average\":68.96,\"upper\":74.0,\"lower\":39.0,\"q1\":67.0,\"q3\":72.0,\"median\":70.0},{\"pos\":79,\"average\":65.46,\"upper\":74.0,\"lower\":40.0,\"q1\":65.0,\"q3\":69.0,\"median\":68.0},{\"pos\":90,\"average\":65.275,\"upper\":72.0,\"lower\":35.0,\"q1\":66.0,\"q3\":68.0,\"median\":68.0},{\"pos\":42,\"average\":70.78,\"upper\":74.0,\"lower\":39.0,\"q1\":70.0,\"q3\":73.0,\"median\":73.0},{\"pos\":14,\"average\":71.965,\"upper\":74.0,\"lower\":60.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":10,\"average\":70.675,\"upper\":72.0,\"lower\":52.0,\"q1\":70.0,\"q3\":72.0,\"median\":72.0},{\"pos\":48,\"average\":70.61,\"upper\":74.0,\"lower\":40.0,\"q1\":69.0,\"q3\":74.0,\"median\":73.0},{\"pos\":18,\"average\":71.47,\"upper\":74.0,\"lower\":49.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":8,\"average\":70.625,\"upper\":72.0,\"lower\":60.0,\"q1\":70.0,\"q3\":72.0,\"median\":72.0},{\"pos\":50,\"average\":70.425,\"upper\":74.0,\"lower\":43.0,\"q1\":69.0,\"q3\":74.0,\"median\":72.0},{\"pos\":22,\"average\":71.41,\"upper\":74.0,\"lower\":41.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":60,\"average\":68.985,\"upper\":74.0,\"lower\":40.0,\"q1\":68.0,\"q3\":73.0,\"median\":71.0},{\"pos\":6,\"average\":68.145,\"upper\":70.0,\"lower\":43.0,\"q1\":68.0,\"q3\":70.0,\"median\":68.0},{\"pos\":49,\"average\":70.21,\"upper\":74.0,\"lower\":41.0,\"q1\":69.0,\"q3\":73.0,\"median\":72.0},{\"pos\":73,\"average\":65.68,\"upper\":74.0,\"lower\":35.0,\"q1\":66.0,\"q3\":70.0,\"median\":68.0},{\"pos\":75,\"average\":64.06,\"upper\":74.0,\"lower\":35.0,\"q1\":64.0,\"q3\":70.0,\"median\":68.0},{\"pos\":23,\"average\":71.635,\"upper\":74.0,\"lower\":41.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":26,\"average\":70.855,\"upper\":74.0,\"lower\":43.0,\"q1\":71.0,\"q3\":73.0,\"median\":73.0},{\"pos\":45,\"average\":70.45,\"upper\":74.0,\"lower\":41.0,\"q1\":69.0,\"q3\":74.0,\"median\":73.0},{\"pos\":62,\"average\":69.145,\"upper\":74.0,\"lower\":38.0,\"q1\":68.0,\"q3\":73.0,\"median\":71.0},{\"pos\":55,\"average\":70.55,\"upper\":74.0,\"lower\":39.0,\"q1\":69.0,\"q3\":73.0,\"median\":72.0},{\"pos\":84,\"average\":65.415,\"upper\":74.0,\"lower\":35.0,\"q1\":66.0,\"q3\":68.0,\"median\":68.0},{\"pos\":15,\"average\":71.725,\"upper\":74.0,\"lower\":51.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":87,\"average\":64.915,\"upper\":73.0,\"lower\":35.0,\"q1\":65.0,\"q3\":68.0,\"median\":68.0},{\"pos\":59,\"average\":69.08,\"upper\":74.0,\"lower\":35.0,\"q1\":68.0,\"q3\":73.0,\"median\":71.0},{\"pos\":66,\"average\":68.875,\"upper\":74.0,\"lower\":39.0,\"q1\":68.0,\"q3\":72.0,\"median\":70.0},{\"pos\":96,\"average\":64.315,\"upper\":71.0,\"lower\":35.0,\"q1\":65.0,\"q3\":68.0,\"median\":67.0},{\"pos\":53,\"average\":70.845,\"upper\":74.0,\"lower\":38.0,\"q1\":70.0,\"q3\":73.0,\"median\":72.0},{\"pos\":64,\"average\":69.095,\"upper\":74.0,\"lower\":38.0,\"q1\":68.0,\"q3\":73.0,\"median\":70.0},{\"pos\":17,\"average\":71.505,\"upper\":74.0,\"lower\":60.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":32,\"average\":71.29,\"upper\":74.0,\"lower\":42.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":29,\"average\":71.595,\"upper\":74.0,\"lower\":56.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":25,\"average\":71.2,\"upper\":74.0,\"lower\":41.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":58,\"average\":69.77,\"upper\":74.0,\"lower\":38.0,\"q1\":68.0,\"q3\":73.0,\"median\":71.0},{\"pos\":7,\"average\":68.4,\"upper\":70.0,\"lower\":43.0,\"q1\":68.0,\"q3\":70.0,\"median\":69.0},{\"pos\":47,\"average\":70.665,\"upper\":74.0,\"lower\":38.0,\"q1\":70.0,\"q3\":74.0,\"median\":72.0},{\"pos\":16,\"average\":71.48,\"upper\":74.0,\"lower\":43.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":99,\"average\":64.25,\"upper\":71.0,\"lower\":38.0,\"q1\":65.0,\"q3\":68.0,\"median\":67.0},{\"pos\":40,\"average\":70.95,\"upper\":74.0,\"lower\":47.0,\"q1\":71.0,\"q3\":73.0,\"median\":73.0},{\"pos\":21,\"average\":71.445,\"upper\":74.0,\"lower\":41.0,\"q1\":71.0,\"q3\":73.0,\"median\":73.0},{\"pos\":37,\"average\":71.0,\"upper\":74.0,\"lower\":41.0,\"q1\":71.0,\"q3\":73.0,\"median\":73.0},{\"pos\":95,\"average\":64.425,\"upper\":70.0,\"lower\":40.0,\"q1\":65.0,\"q3\":68.0,\"median\":67.0},{\"pos\":98,\"average\":64.55,\"upper\":73.0,\"lower\":40.0,\"q1\":65.0,\"q3\":68.0,\"median\":67.0},{\"pos\":35,\"average\":71.385,\"upper\":74.0,\"lower\":50.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":69,\"average\":66.7,\"upper\":74.0,\"lower\":35.0,\"q1\":67.0,\"q3\":72.0,\"median\":69.0},{\"pos\":89,\"average\":65.44,\"upper\":72.0,\"lower\":35.0,\"q1\":66.0,\"q3\":68.0,\"median\":68.0},{\"pos\":20,\"average\":71.625,\"upper\":74.0,\"lower\":56.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":36,\"average\":71.11,\"upper\":74.0,\"lower\":40.0,\"q1\":71.0,\"q3\":73.0,\"median\":73.0},{\"pos\":38,\"average\":70.64,\"upper\":74.0,\"lower\":39.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":93,\"average\":64.05,\"upper\":72.0,\"lower\":35.0,\"q1\":65.0,\"q3\":68.0,\"median\":67.0},{\"pos\":63,\"average\":69.25,\"upper\":74.0,\"lower\":40.0,\"q1\":68.0,\"q3\":73.0,\"median\":71.0},{\"pos\":41,\"average\":70.87,\"upper\":74.0,\"lower\":41.0,\"q1\":70.0,\"q3\":74.0,\"median\":73.0},{\"pos\":30,\"average\":71.245,\"upper\":74.0,\"lower\":41.0,\"q1\":71.0,\"q3\":73.0,\"median\":73.0},{\"pos\":43,\"average\":70.775,\"upper\":74.0,\"lower\":41.0,\"q1\":71.0,\"q3\":73.0,\"median\":73.0},{\"pos\":5,\"average\":68.095,\"upper\":70.0,\"lower\":43.0,\"q1\":68.0,\"q3\":70.0,\"median\":68.0},{\"pos\":77,\"average\":63.805,\"upper\":74.0,\"lower\":35.0,\"q1\":63.0,\"q3\":69.0,\"median\":68.0},{\"pos\":24,\"average\":71.265,\"upper\":74.0,\"lower\":43.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":31,\"average\":71.795,\"upper\":74.0,\"lower\":41.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":11,\"average\":70.71,\"upper\":72.0,\"lower\":51.0,\"q1\":70.0,\"q3\":72.0,\"median\":72.0},{\"pos\":27,\"average\":71.44,\"upper\":74.0,\"lower\":43.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":52,\"average\":70.77,\"upper\":74.0,\"lower\":40.0,\"q1\":70.0,\"q3\":73.0,\"median\":72.0}]}'" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" } ], - "execution_count": 1 + "source": [ + "import polars_bio as pb\n", + "import pandas as pd\n", + "\n", + "a_lazyframe = pb.read_fastq(\"./example.fastq\")\n", + "a_dataframe = a_lazyframe.collect()\n", + "print(type(a_lazyframe))\n", + "# display types of columns\n", + "print(a_lazyframe.dtypes)\n", + "print(type(a_dataframe))\n", + "a_pandas_dataframe = a_lazyframe.collect().to_pandas()\n", + "print(type(a_pandas_dataframe))\n", + "pb.base_sequence_quality(a_lazyframe)\n", + "pb.base_sequence_quality(a_dataframe)\n", + "pb.base_sequence_quality(a_pandas_dataframe)\n", + "pb.base_sequence_quality(\"./example.csv\")\n", + "pb.base_sequence_quality(\"./example.parquet\")\n" + ] }, { "cell_type": "markdown", "id": "d2bb8c193890f27f", "metadata": {}, - "source": "### Sample data" + "source": [ + "### Sample data" + ] }, { "cell_type": "code", + "execution_count": null, "id": "86fe039c3780140e", "metadata": { "ExecuteTime": { @@ -46,27 +107,44 @@ "start_time": "2025-02-24T16:59:37.452650Z" } }, + "outputs": [ + { + "ename": "TypeError", + "evalue": "argument 'df_path_or_table': 'DataFrame' object cannot be converted to 'PyString'", + "output_type": "error", + "traceback": [ + "\u001b[31m---------------------------------------------------------------------------\u001b[39m", + "\u001b[31mTypeError\u001b[39m Traceback (most recent call last)", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[3]\u001b[39m\u001b[32m, line 6\u001b[39m\n\u001b[32m 1\u001b[39m df1 = pd.DataFrame(\n\u001b[32m 2\u001b[39m [[\u001b[33m\"\u001b[39m\u001b[33mchr1\u001b[39m\u001b[33m\"\u001b[39m, \u001b[32m1\u001b[39m, \u001b[32m5\u001b[39m], [\u001b[33m\"\u001b[39m\u001b[33mchr1\u001b[39m\u001b[33m\"\u001b[39m, \u001b[32m3\u001b[39m, \u001b[32m8\u001b[39m], [\u001b[33m\"\u001b[39m\u001b[33mchr1\u001b[39m\u001b[33m\"\u001b[39m, \u001b[32m8\u001b[39m, \u001b[32m10\u001b[39m], [\u001b[33m\"\u001b[39m\u001b[33mchr1\u001b[39m\u001b[33m\"\u001b[39m, \u001b[32m12\u001b[39m, \u001b[32m14\u001b[39m]],\n\u001b[32m 3\u001b[39m columns=[\u001b[33m\"\u001b[39m\u001b[33mchrom\u001b[39m\u001b[33m\"\u001b[39m, \u001b[33m\"\u001b[39m\u001b[33mstart\u001b[39m\u001b[33m\"\u001b[39m, \u001b[33m\"\u001b[39m\u001b[33mend\u001b[39m\u001b[33m\"\u001b[39m],\n\u001b[32m 4\u001b[39m )\n\u001b[32m----> \u001b[39m\u001b[32m6\u001b[39m \u001b[43mpb\u001b[49m\u001b[43m.\u001b[49m\u001b[43mbase_sequance_quality\u001b[49m\u001b[43m(\u001b[49m\u001b[43mdf1\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 8\u001b[39m df2 = pd.DataFrame(\n\u001b[32m 9\u001b[39m [[\u001b[33m\"\u001b[39m\u001b[33mchr1\u001b[39m\u001b[33m\"\u001b[39m, \u001b[32m4\u001b[39m, \u001b[32m8\u001b[39m], [\u001b[33m\"\u001b[39m\u001b[33mchr1\u001b[39m\u001b[33m\"\u001b[39m, \u001b[32m10\u001b[39m, \u001b[32m11\u001b[39m]], columns=[\u001b[33m\"\u001b[39m\u001b[33mchrom\u001b[39m\u001b[33m\"\u001b[39m, \u001b[33m\"\u001b[39m\u001b[33mstart\u001b[39m\u001b[33m\"\u001b[39m, \u001b[33m\"\u001b[39m\u001b[33mend\u001b[39m\u001b[33m\"\u001b[39m]\n\u001b[32m 10\u001b[39m )\n", + "\u001b[36mFile \u001b[39m\u001b[32m~/.pyenv/versions/3.12.9/lib/python3.12/site-packages/polars_bio/quality_stats.py:9\u001b[39m, in \u001b[36mbase_sequance_quality\u001b[39m\u001b[34m(df)\u001b[39m\n\u001b[32m 8\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34mbase_sequance_quality\u001b[39m(df: Union[\u001b[38;5;28mstr\u001b[39m, pl.DataFrame, pl.LazyFrame, pd.DataFrame]):\n\u001b[32m----> \u001b[39m\u001b[32m9\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mpy_base_sequence_quality\u001b[49m\u001b[43m(\u001b[49m\u001b[43mctx\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdf\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[31mTypeError\u001b[39m: argument 'df_path_or_table': 'DataFrame' object cannot be converted to 'PyString'" + ] + } + ], "source": [ "df1 = pd.DataFrame(\n", " [[\"chr1\", 1, 5], [\"chr1\", 3, 8], [\"chr1\", 8, 10], [\"chr1\", 12, 14]],\n", " columns=[\"chrom\", \"start\", \"end\"],\n", ")\n", "\n", + "pb.base_sequence_quality(df1)\n", + "\n", "df2 = pd.DataFrame(\n", " [[\"chr1\", 4, 8], [\"chr1\", 10, 11]], columns=[\"chrom\", \"start\", \"end\"]\n", ")" - ], - "outputs": [], - "execution_count": 2 + ] }, { "cell_type": "markdown", "id": "a884cd2960796fdb", "metadata": {}, - "source": "### Overlap" + "source": [ + "### Overlap" + ] }, { "cell_type": "code", + "execution_count": 3, "id": "304f3aa6fcdc9650", "metadata": { "ExecuteTime": { @@ -74,9 +152,6 @@ "start_time": "2025-02-24T16:59:37.538707Z" } }, - "source": [ - "overlapping_intervals = pb.overlap(df1, df2, output_type=\"pandas.DataFrame\")" - ], "outputs": [ { "name": "stderr", @@ -86,10 +161,13 @@ ] } ], - "execution_count": 3 + "source": [ + "overlapping_intervals = pb.overlap(df1, df2, output_type=\"pandas.DataFrame\")" + ] }, { "cell_type": "code", + "execution_count": 4, "id": "61c9254622598622", "metadata": { "ExecuteTime": { @@ -97,17 +175,9 @@ "start_time": "2025-02-24T16:59:37.552440Z" } }, - "source": [ - "display(overlapping_intervals)" - ], "outputs": [ { "data": { - "text/plain": [ - " chrom_1 start_1 end_1 chrom_2 start_2 end_2\n", - "0 chr1 1 5 chr1 4 8\n", - "1 chr1 3 8 chr1 4 8" - ], "text/html": [ "
\n", " + + + + + + + + + + + + +
+ +
+
+ +
+
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ average GC content + + 46.15999984741211 +
+ average read length + + 101 +
+ canonical + + True +
+ file name + + example.fastq +
+ k + + 5 +
+ total reads + + 200 +
+
+
+ + \ No newline at end of file diff --git a/docs/notebooks/tutorial.ipynb b/docs/notebooks/tutorial.ipynb index 42771c6a..5b98a620 100644 --- a/docs/notebooks/tutorial.ipynb +++ b/docs/notebooks/tutorial.ipynb @@ -10,7 +10,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "7b173024d3e8f76", "metadata": { "ExecuteTime": { @@ -18,75 +18,36 @@ "start_time": "2025-02-24T16:59:36.960817Z" } }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "INFO:polars_bio:Table: example registered for path: ./example.fastq\n", - "200rows [00:00, 46795.76rows/s]\n", - "/tmp/ipykernel_220539/1600797315.py:8: PerformanceWarning: Determining the data types of a LazyFrame requires resolving its schema, which is a potentially expensive operation. Use `LazyFrame.collect_schema().dtypes()` to get the data types without this warning.\n", - " print(a_lazyframe.dtypes)\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "[String, String, String, String]\n", - "\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "200rows [00:00, 67012.37rows/s]\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "200rows [00:00, 138084.08rows/s]\n" - ] - }, - { - "data": { - "text/plain": [ - "'{\"base_quality_warn\":\"pass\",\"base_per_pos_data\":[{\"pos\":72,\"average\":66.265,\"upper\":74.0,\"lower\":35.0,\"q1\":66.0,\"q3\":70.0,\"median\":68.0},{\"pos\":80,\"average\":65.61,\"upper\":74.0,\"lower\":35.0,\"q1\":65.0,\"q3\":69.0,\"median\":68.0},{\"pos\":81,\"average\":65.76,\"upper\":74.0,\"lower\":35.0,\"q1\":66.0,\"q3\":69.0,\"median\":68.0},{\"pos\":83,\"average\":65.03,\"upper\":73.0,\"lower\":35.0,\"q1\":66.0,\"q3\":68.0,\"median\":68.0},{\"pos\":85,\"average\":65.195,\"upper\":73.0,\"lower\":35.0,\"q1\":66.0,\"q3\":68.0,\"median\":68.0},{\"pos\":19,\"average\":71.425,\"upper\":74.0,\"lower\":43.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":86,\"average\":64.815,\"upper\":73.0,\"lower\":35.0,\"q1\":66.0,\"q3\":68.0,\"median\":68.0},{\"pos\":91,\"average\":65.665,\"upper\":73.0,\"lower\":38.0,\"q1\":65.0,\"q3\":68.0,\"median\":68.0},{\"pos\":92,\"average\":64.835,\"upper\":72.0,\"lower\":38.0,\"q1\":65.0,\"q3\":68.0,\"median\":68.0},{\"pos\":94,\"average\":63.775,\"upper\":73.0,\"lower\":35.0,\"q1\":65.0,\"q3\":68.0,\"median\":67.0},{\"pos\":51,\"average\":70.53,\"upper\":74.0,\"lower\":40.0,\"q1\":69.0,\"q3\":74.0,\"median\":72.0},{\"pos\":78,\"average\":64.46,\"upper\":74.0,\"lower\":35.0,\"q1\":64.0,\"q3\":69.0,\"median\":68.0},{\"pos\":61,\"average\":68.99,\"upper\":74.0,\"lower\":40.0,\"q1\":68.0,\"q3\":73.0,\"median\":71.0},{\"pos\":88,\"average\":65.065,\"upper\":72.0,\"lower\":38.0,\"q1\":66.0,\"q3\":68.0,\"median\":68.0},{\"pos\":74,\"average\":63.83,\"upper\":74.0,\"lower\":35.0,\"q1\":65.0,\"q3\":70.0,\"median\":68.0},{\"pos\":1,\"average\":64.21,\"upper\":67.0,\"lower\":43.0,\"q1\":64.0,\"q3\":67.0,\"median\":67.0},{\"pos\":4,\"average\":68.68,\"upper\":70.0,\"lower\":49.0,\"q1\":68.0,\"q3\":70.0,\"median\":70.0},{\"pos\":0,\"average\":63.135,\"upper\":67.0,\"lower\":35.0,\"q1\":64.0,\"q3\":67.0,\"median\":66.0},{\"pos\":68,\"average\":68.91,\"upper\":74.0,\"lower\":40.0,\"q1\":67.0,\"q3\":72.0,\"median\":69.0},{\"pos\":56,\"average\":70.59,\"upper\":74.0,\"lower\":38.0,\"q1\":69.0,\"q3\":73.0,\"median\":72.0},{\"pos\":82,\"average\":64.525,\"upper\":74.0,\"lower\":35.0,\"q1\":66.0,\"q3\":68.0,\"median\":68.0},{\"pos\":97,\"average\":63.67,\"upper\":71.0,\"lower\":35.0,\"q1\":64.0,\"q3\":68.0,\"median\":67.0},{\"pos\":100,\"average\":64.105,\"upper\":70.0,\"lower\":40.0,\"q1\":64.0,\"q3\":68.0,\"median\":67.0},{\"pos\":2,\"average\":65.015,\"upper\":67.0,\"lower\":49.0,\"q1\":64.0,\"q3\":67.0,\"median\":67.0},{\"pos\":33,\"average\":71.245,\"upper\":74.0,\"lower\":40.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":34,\"average\":71.205,\"upper\":74.0,\"lower\":51.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":28,\"average\":71.445,\"upper\":74.0,\"lower\":49.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":65,\"average\":68.995,\"upper\":74.0,\"lower\":38.0,\"q1\":68.0,\"q3\":72.0,\"median\":70.0},{\"pos\":12,\"average\":70.5,\"upper\":72.0,\"lower\":52.0,\"q1\":70.0,\"q3\":72.0,\"median\":72.0},{\"pos\":3,\"average\":68.69,\"upper\":70.0,\"lower\":52.0,\"q1\":68.0,\"q3\":70.0,\"median\":70.0},{\"pos\":9,\"average\":70.36,\"upper\":72.0,\"lower\":52.0,\"q1\":70.0,\"q3\":72.0,\"median\":72.0},{\"pos\":39,\"average\":70.895,\"upper\":74.0,\"lower\":39.0,\"q1\":71.0,\"q3\":73.0,\"median\":73.0},{\"pos\":57,\"average\":70.35,\"upper\":74.0,\"lower\":38.0,\"q1\":69.0,\"q3\":73.0,\"median\":72.0},{\"pos\":70,\"average\":66.565,\"upper\":74.0,\"lower\":40.0,\"q1\":67.0,\"q3\":71.0,\"median\":68.0},{\"pos\":13,\"average\":71.94,\"upper\":74.0,\"lower\":58.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":46,\"average\":70.79,\"upper\":74.0,\"lower\":40.0,\"q1\":70.0,\"q3\":74.0,\"median\":73.0},{\"pos\":76,\"average\":63.265,\"upper\":74.0,\"lower\":35.0,\"q1\":64.0,\"q3\":70.0,\"median\":68.0},{\"pos\":44,\"average\":70.565,\"upper\":74.0,\"lower\":39.0,\"q1\":70.0,\"q3\":74.0,\"median\":73.0},{\"pos\":71,\"average\":66.005,\"upper\":74.0,\"lower\":35.0,\"q1\":66.0,\"q3\":71.0,\"median\":68.0},{\"pos\":54,\"average\":70.59,\"upper\":74.0,\"lower\":38.0,\"q1\":69.0,\"q3\":74.0,\"median\":73.0},{\"pos\":67,\"average\":68.96,\"upper\":74.0,\"lower\":39.0,\"q1\":67.0,\"q3\":72.0,\"median\":70.0},{\"pos\":79,\"average\":65.46,\"upper\":74.0,\"lower\":40.0,\"q1\":65.0,\"q3\":69.0,\"median\":68.0},{\"pos\":90,\"average\":65.275,\"upper\":72.0,\"lower\":35.0,\"q1\":66.0,\"q3\":68.0,\"median\":68.0},{\"pos\":42,\"average\":70.78,\"upper\":74.0,\"lower\":39.0,\"q1\":70.0,\"q3\":73.0,\"median\":73.0},{\"pos\":14,\"average\":71.965,\"upper\":74.0,\"lower\":60.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":10,\"average\":70.675,\"upper\":72.0,\"lower\":52.0,\"q1\":70.0,\"q3\":72.0,\"median\":72.0},{\"pos\":48,\"average\":70.61,\"upper\":74.0,\"lower\":40.0,\"q1\":69.0,\"q3\":74.0,\"median\":73.0},{\"pos\":18,\"average\":71.47,\"upper\":74.0,\"lower\":49.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":8,\"average\":70.625,\"upper\":72.0,\"lower\":60.0,\"q1\":70.0,\"q3\":72.0,\"median\":72.0},{\"pos\":50,\"average\":70.425,\"upper\":74.0,\"lower\":43.0,\"q1\":69.0,\"q3\":74.0,\"median\":72.0},{\"pos\":22,\"average\":71.41,\"upper\":74.0,\"lower\":41.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":60,\"average\":68.985,\"upper\":74.0,\"lower\":40.0,\"q1\":68.0,\"q3\":73.0,\"median\":71.0},{\"pos\":6,\"average\":68.145,\"upper\":70.0,\"lower\":43.0,\"q1\":68.0,\"q3\":70.0,\"median\":68.0},{\"pos\":49,\"average\":70.21,\"upper\":74.0,\"lower\":41.0,\"q1\":69.0,\"q3\":73.0,\"median\":72.0},{\"pos\":73,\"average\":65.68,\"upper\":74.0,\"lower\":35.0,\"q1\":66.0,\"q3\":70.0,\"median\":68.0},{\"pos\":75,\"average\":64.06,\"upper\":74.0,\"lower\":35.0,\"q1\":64.0,\"q3\":70.0,\"median\":68.0},{\"pos\":23,\"average\":71.635,\"upper\":74.0,\"lower\":41.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":26,\"average\":70.855,\"upper\":74.0,\"lower\":43.0,\"q1\":71.0,\"q3\":73.0,\"median\":73.0},{\"pos\":45,\"average\":70.45,\"upper\":74.0,\"lower\":41.0,\"q1\":69.0,\"q3\":74.0,\"median\":73.0},{\"pos\":62,\"average\":69.145,\"upper\":74.0,\"lower\":38.0,\"q1\":68.0,\"q3\":73.0,\"median\":71.0},{\"pos\":55,\"average\":70.55,\"upper\":74.0,\"lower\":39.0,\"q1\":69.0,\"q3\":73.0,\"median\":72.0},{\"pos\":84,\"average\":65.415,\"upper\":74.0,\"lower\":35.0,\"q1\":66.0,\"q3\":68.0,\"median\":68.0},{\"pos\":15,\"average\":71.725,\"upper\":74.0,\"lower\":51.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":87,\"average\":64.915,\"upper\":73.0,\"lower\":35.0,\"q1\":65.0,\"q3\":68.0,\"median\":68.0},{\"pos\":59,\"average\":69.08,\"upper\":74.0,\"lower\":35.0,\"q1\":68.0,\"q3\":73.0,\"median\":71.0},{\"pos\":66,\"average\":68.875,\"upper\":74.0,\"lower\":39.0,\"q1\":68.0,\"q3\":72.0,\"median\":70.0},{\"pos\":96,\"average\":64.315,\"upper\":71.0,\"lower\":35.0,\"q1\":65.0,\"q3\":68.0,\"median\":67.0},{\"pos\":53,\"average\":70.845,\"upper\":74.0,\"lower\":38.0,\"q1\":70.0,\"q3\":73.0,\"median\":72.0},{\"pos\":64,\"average\":69.095,\"upper\":74.0,\"lower\":38.0,\"q1\":68.0,\"q3\":73.0,\"median\":70.0},{\"pos\":17,\"average\":71.505,\"upper\":74.0,\"lower\":60.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":32,\"average\":71.29,\"upper\":74.0,\"lower\":42.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":29,\"average\":71.595,\"upper\":74.0,\"lower\":56.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":25,\"average\":71.2,\"upper\":74.0,\"lower\":41.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":58,\"average\":69.77,\"upper\":74.0,\"lower\":38.0,\"q1\":68.0,\"q3\":73.0,\"median\":71.0},{\"pos\":7,\"average\":68.4,\"upper\":70.0,\"lower\":43.0,\"q1\":68.0,\"q3\":70.0,\"median\":69.0},{\"pos\":47,\"average\":70.665,\"upper\":74.0,\"lower\":38.0,\"q1\":70.0,\"q3\":74.0,\"median\":72.0},{\"pos\":16,\"average\":71.48,\"upper\":74.0,\"lower\":43.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":99,\"average\":64.25,\"upper\":71.0,\"lower\":38.0,\"q1\":65.0,\"q3\":68.0,\"median\":67.0},{\"pos\":40,\"average\":70.95,\"upper\":74.0,\"lower\":47.0,\"q1\":71.0,\"q3\":73.0,\"median\":73.0},{\"pos\":21,\"average\":71.445,\"upper\":74.0,\"lower\":41.0,\"q1\":71.0,\"q3\":73.0,\"median\":73.0},{\"pos\":37,\"average\":71.0,\"upper\":74.0,\"lower\":41.0,\"q1\":71.0,\"q3\":73.0,\"median\":73.0},{\"pos\":95,\"average\":64.425,\"upper\":70.0,\"lower\":40.0,\"q1\":65.0,\"q3\":68.0,\"median\":67.0},{\"pos\":98,\"average\":64.55,\"upper\":73.0,\"lower\":40.0,\"q1\":65.0,\"q3\":68.0,\"median\":67.0},{\"pos\":35,\"average\":71.385,\"upper\":74.0,\"lower\":50.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":69,\"average\":66.7,\"upper\":74.0,\"lower\":35.0,\"q1\":67.0,\"q3\":72.0,\"median\":69.0},{\"pos\":89,\"average\":65.44,\"upper\":72.0,\"lower\":35.0,\"q1\":66.0,\"q3\":68.0,\"median\":68.0},{\"pos\":20,\"average\":71.625,\"upper\":74.0,\"lower\":56.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":36,\"average\":71.11,\"upper\":74.0,\"lower\":40.0,\"q1\":71.0,\"q3\":73.0,\"median\":73.0},{\"pos\":38,\"average\":70.64,\"upper\":74.0,\"lower\":39.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":93,\"average\":64.05,\"upper\":72.0,\"lower\":35.0,\"q1\":65.0,\"q3\":68.0,\"median\":67.0},{\"pos\":63,\"average\":69.25,\"upper\":74.0,\"lower\":40.0,\"q1\":68.0,\"q3\":73.0,\"median\":71.0},{\"pos\":41,\"average\":70.87,\"upper\":74.0,\"lower\":41.0,\"q1\":70.0,\"q3\":74.0,\"median\":73.0},{\"pos\":30,\"average\":71.245,\"upper\":74.0,\"lower\":41.0,\"q1\":71.0,\"q3\":73.0,\"median\":73.0},{\"pos\":43,\"average\":70.775,\"upper\":74.0,\"lower\":41.0,\"q1\":71.0,\"q3\":73.0,\"median\":73.0},{\"pos\":5,\"average\":68.095,\"upper\":70.0,\"lower\":43.0,\"q1\":68.0,\"q3\":70.0,\"median\":68.0},{\"pos\":77,\"average\":63.805,\"upper\":74.0,\"lower\":35.0,\"q1\":63.0,\"q3\":69.0,\"median\":68.0},{\"pos\":24,\"average\":71.265,\"upper\":74.0,\"lower\":43.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":31,\"average\":71.795,\"upper\":74.0,\"lower\":41.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":11,\"average\":70.71,\"upper\":72.0,\"lower\":51.0,\"q1\":70.0,\"q3\":72.0,\"median\":72.0},{\"pos\":27,\"average\":71.44,\"upper\":74.0,\"lower\":43.0,\"q1\":71.0,\"q3\":74.0,\"median\":73.0},{\"pos\":52,\"average\":70.77,\"upper\":74.0,\"lower\":40.0,\"q1\":70.0,\"q3\":73.0,\"median\":72.0}]}'" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "import polars_bio as pb\n", "import pandas as pd\n", "\n", - "a_lazyframe = pb.read_fastq(\"./example.fastq\")\n", - "a_dataframe = a_lazyframe.collect()\n", - "print(type(a_lazyframe))\n", - "# display types of columns\n", - "print(a_lazyframe.dtypes)\n", - "print(type(a_dataframe))\n", - "a_pandas_dataframe = a_lazyframe.collect().to_pandas()\n", - "print(type(a_pandas_dataframe))\n", - "pb.base_sequence_quality(a_lazyframe)\n", - "pb.base_sequence_quality(a_dataframe)\n", - "pb.base_sequence_quality(a_pandas_dataframe)\n", - "pb.base_sequence_quality(\"./example.csv\")\n", - "pb.base_sequence_quality(\"./example.parquet\")\n" + "# print(type(a_lazyframe))\n", + "# # display types of columns\n", + "# print(a_lazyframe.dtypes)\n", + "# print(type(a_dataframe))\n", + "# print(type(a_pandas_dataframe))\n", + "# print(pb.sql(\"SHOW TABLES\").collect())\n", + "print(pb.sql(\"SHOW TABLES\").collect())\n", + "\n", + "# a_lazyframe = pb.read_fastq(\"./example.fastq\")\n", + "# a_dataframe = a_lazyframe.collect()\n", + "# a_pandas_dataframe = a_lazyframe.collect().to_pandas()\n", + "# print(pb.base_sequence_quality(a_lazyframe))\n", + "# print(pb.base_sequence_quality(a_dataframe))\n", + "# print(pb.base_sequence_quality(a_pandas_dataframe))\n", + "\n", + "# result = pb.sql(\"SELECT base_sequence_quality(quality_scores) FROM example\").collect()\n", + "# print(result.item())\n", + "# print(pb.base_sequence_quality(\"./example.csv\"))\n", + "print(pb.base_sequence_quality(\"./example.fastq\"))\n", + "# print(pb.base_sequence_quality(\"./example.parquet\"))\n", + "\n", + "# sql display all tables and print it\n", + "print(pb.sql(\"SHOW TABLES\").collect())\n", + "# use sql and display result (it is aggregate function that returns string)\n", + "# print(result.item())\n" ] }, { @@ -107,20 +68,7 @@ "start_time": "2025-02-24T16:59:37.452650Z" } }, - "outputs": [ - { - "ename": "TypeError", - "evalue": "argument 'df_path_or_table': 'DataFrame' object cannot be converted to 'PyString'", - "output_type": "error", - "traceback": [ - "\u001b[31m---------------------------------------------------------------------------\u001b[39m", - "\u001b[31mTypeError\u001b[39m Traceback (most recent call last)", - "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[3]\u001b[39m\u001b[32m, line 6\u001b[39m\n\u001b[32m 1\u001b[39m df1 = pd.DataFrame(\n\u001b[32m 2\u001b[39m [[\u001b[33m\"\u001b[39m\u001b[33mchr1\u001b[39m\u001b[33m\"\u001b[39m, \u001b[32m1\u001b[39m, \u001b[32m5\u001b[39m], [\u001b[33m\"\u001b[39m\u001b[33mchr1\u001b[39m\u001b[33m\"\u001b[39m, \u001b[32m3\u001b[39m, \u001b[32m8\u001b[39m], [\u001b[33m\"\u001b[39m\u001b[33mchr1\u001b[39m\u001b[33m\"\u001b[39m, \u001b[32m8\u001b[39m, \u001b[32m10\u001b[39m], [\u001b[33m\"\u001b[39m\u001b[33mchr1\u001b[39m\u001b[33m\"\u001b[39m, \u001b[32m12\u001b[39m, \u001b[32m14\u001b[39m]],\n\u001b[32m 3\u001b[39m columns=[\u001b[33m\"\u001b[39m\u001b[33mchrom\u001b[39m\u001b[33m\"\u001b[39m, \u001b[33m\"\u001b[39m\u001b[33mstart\u001b[39m\u001b[33m\"\u001b[39m, \u001b[33m\"\u001b[39m\u001b[33mend\u001b[39m\u001b[33m\"\u001b[39m],\n\u001b[32m 4\u001b[39m )\n\u001b[32m----> \u001b[39m\u001b[32m6\u001b[39m \u001b[43mpb\u001b[49m\u001b[43m.\u001b[49m\u001b[43mbase_sequance_quality\u001b[49m\u001b[43m(\u001b[49m\u001b[43mdf1\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 8\u001b[39m df2 = pd.DataFrame(\n\u001b[32m 9\u001b[39m [[\u001b[33m\"\u001b[39m\u001b[33mchr1\u001b[39m\u001b[33m\"\u001b[39m, \u001b[32m4\u001b[39m, \u001b[32m8\u001b[39m], [\u001b[33m\"\u001b[39m\u001b[33mchr1\u001b[39m\u001b[33m\"\u001b[39m, \u001b[32m10\u001b[39m, \u001b[32m11\u001b[39m]], columns=[\u001b[33m\"\u001b[39m\u001b[33mchrom\u001b[39m\u001b[33m\"\u001b[39m, \u001b[33m\"\u001b[39m\u001b[33mstart\u001b[39m\u001b[33m\"\u001b[39m, \u001b[33m\"\u001b[39m\u001b[33mend\u001b[39m\u001b[33m\"\u001b[39m]\n\u001b[32m 10\u001b[39m )\n", - "\u001b[36mFile \u001b[39m\u001b[32m~/.pyenv/versions/3.12.9/lib/python3.12/site-packages/polars_bio/quality_stats.py:9\u001b[39m, in \u001b[36mbase_sequance_quality\u001b[39m\u001b[34m(df)\u001b[39m\n\u001b[32m 8\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34mbase_sequance_quality\u001b[39m(df: Union[\u001b[38;5;28mstr\u001b[39m, pl.DataFrame, pl.LazyFrame, pd.DataFrame]):\n\u001b[32m----> \u001b[39m\u001b[32m9\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mpy_base_sequence_quality\u001b[49m\u001b[43m(\u001b[49m\u001b[43mctx\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdf\u001b[49m\u001b[43m)\u001b[49m\n", - "\u001b[31mTypeError\u001b[39m: argument 'df_path_or_table': 'DataFrame' object cannot be converted to 'PyString'" - ] - } - ], + "outputs": [], "source": [ "df1 = pd.DataFrame(\n", " [[\"chr1\", 1, 5], [\"chr1\", 3, 8], [\"chr1\", 8, 10], [\"chr1\", 12, 14]],\n", @@ -144,7 +92,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "id": "304f3aa6fcdc9650", "metadata": { "ExecuteTime": { @@ -152,22 +100,14 @@ "start_time": "2025-02-24T16:59:37.538707Z" } }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "INFO:polars_bio.operation:Running Overlap operation with algorithm Coitrees and 1 thread(s)...\n" - ] - } - ], + "outputs": [], "source": [ "overlapping_intervals = pb.overlap(df1, df2, output_type=\"pandas.DataFrame\")" ] }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "61c9254622598622", "metadata": { "ExecuteTime": { @@ -175,76 +115,14 @@ "start_time": "2025-02-24T16:59:37.552440Z" } }, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
chrom_1start_1end_1chrom_2start_2end_2
0chr115chr148
1chr138chr148
\n", - "
" - ], - "text/plain": [ - " chrom_1 start_1 end_1 chrom_2 start_2 end_2\n", - "0 chr1 1 5 chr1 4 8\n", - "1 chr1 3 8 chr1 4 8" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "display(overlapping_intervals)" ] }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "e640901ec6e6ce11", "metadata": { "ExecuteTime": { @@ -252,28 +130,7 @@ "start_time": "2025-02-24T16:59:37.581481Z" } }, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAygAAADTCAYAAABqSTe2AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8ekN5oAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAZEUlEQVR4nO3dB5QdVf0H8BtIQgshBCQQJPTeiyBFooAUI1KkChIIRwXpKiIqhB6K1MChKAKKNKWDlCABQQgdpCg1hibtHyAsSBLI+5/f9bx1d7OBbNjNXPZ9Pue8ZN+8dmdm3879zi3To1ar1RIAAEABZqm6AAAAAHUCCgAAUAwBBQAAKIaAAgAAFENAAQAAiiGgAAAAxRBQAACAYggoAABAMQQUAACgGAIKQEHuuOOO1KNHj/x/CY444ohcnu4i1iXWCYByCSgAMIPeeeedNMsss6Rbbrkl37/66qvTbLPNliZOnDjVc2PZIYcckgYOHJjmmGOOtM4666RRo0ZVUGqAsgkoAEzTL3/5y/Sf//wndRexLrFOneX+++/P/0fYCPfee29affXVc0hpa/fdd0+nnHJK2mWXXdLpp5+eZp111vSNb3wj3X333Z1WHoDuoGfVBQAgpQ8//DD17t07laZnz5751l3MPvvsn/qc999/P80111zTHVCWXXbZ1K9fv+aAUg8rbZ932WWXpZNOOin95Cc/yct22223tNJKK6Wf/vSn6Z577unwugB0V1pQgIb2yCOPpC222CL17ds39enTJ2288cZpzJgxzY8/+OCDedzCRRddNNVro1tPPHbDDTc0L3vllVfSsGHD0oABA/JZ9BVXXDH99re/bXecSVRY42z+wgsvnOacc840YcKEdst41113pe233z4NGjQov+ciiyySDjrooKlaNuIMfazDCy+8kDbbbLNcyY7uREcddVSq1WrNz/vXv/6VP/9Xv/pVOvXUU9Oiiy6auxwNHjw4PfHEE586BiXu77vvvumaa67JFez6et58881TlT3Wda211srBYMkll0znnnvudI9r+epXv5rf/6GHHkrrrbdeLuPiiy+ezjnnnFbPmzRpUjr88MPTmmuumeaZZ5683l/5ylfS6NGjP3UMSr0sTz31VPrOd76T5p133rTBBht8Yrnefffd9NZbb+VbBJJVV101//z666/nsi633HL5fjyv7k9/+lNuMfn+97/fvCy2yZ577pnf46WXXvrU7QHQKLrPaTGADnryySdzRTbCSZzF7tWrV65AR8X4zjvvzGfCo3K9xBJLpCuuuCINHTq01esvv/zyXKGNMBCigvrlL3+5uQL/hS98Id100025Ehrh48ADD2z1+qOPPjq3msQZ9RifMK0WlD/+8Y/pgw8+SHvvvXeab7758tn4kSNHppdffjk/1tLHH3+cNt9881yOE088MYeG4cOHp48++igHlZZ+97vfpffeey/ts88+uQUnuh1ttNFG6fHHH88B65NEt6Srrroq/fCHP0xzzz13OuOMM9K3v/3t9OKLL+Yy1sNflGWhhRZKRx55ZC5blCG2y/R6++23czeoHXbYIe288855P8R2iG0VQTDEtv3Nb36TH//e976X1+n888/P+yW21WqrrfapnxMBcOmll07HHXdcqzDXnq222ir/frT9XaiLbRK3CHz1yQ5iWyyzzDL5d62ltddeO///6KOP5uAJQErxhxigIW299da13r17155//vnmZa+++mpt7rnnrm244YbNyw499NBar169auPHj29eNnHixFq/fv1qw4YNa16255571hZaaKHaW2+91epzdtppp9o888xT++CDD/L90aNHRw24tsQSSzQvq6s/Fv/XtX1OGDFiRK1Hjx61cePGNS8bOnRofu1+++3XvGzKlCm1IUOG5PV8880387KxY8fm580xxxy1l19+ufm59913X15+0EEHNS8bPnx4XtZS3I/3e+6555qXPfbYY3n5yJEjm5dtueWWtTnnnLP2yiuvNC979tlnaz179pzqPdszePDg/LyTTz651XZfbbXVagsssEBt0qRJedlHH32Ul7f09ttv1wYMGNBq/9TLHuvUdv123nnn2vR68MEHa6NGjaqdddZZ+bUXX3xxvr/77rvXFllkkfxz3OJ5dSuuuGJto402muq9nnzyyfwe55xzznR/PkB3p4sX0JDibP6tt96att5669xCUhdn+6OrT7QQ1Ltc7bjjjmny5Mm5xaAuXhszOMVjIeq+V155Zdpyyy3zz/UuQHGLM/nR3efhhx9uVYZokYluS5+m5XNifES8Z3R5is+JM/NtRetNXb01J7pB3Xbbba2eF+se3ctans2PVqM///nPn1qmTTbZJHfZqltllVVy60B0L6tv3/i8+IzoZla31FJL5S510yvG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qmcfVM8+qJ590L22/wwNkgcAAOgKungBAADFEFAAAIBiCCgAAEAxBBQAAODzHVDOOuustNhii6XZZ589rbPOOun+++/v/JLRrhEjRqQvfelLae65504LLLBA2nrrrdPTTz9ddbEa1vHHH5969OiRDjzwwKqL0nBeeeWVtOuuu6b55psvzTHHHGnllVdODz74YNXFaggff/xxOuyww9Liiy+et/2SSy6Zjj766GTOla7117/+NW255ZZp4MCB+e/ONddc0+rx2P6HH354WmihhfJ+2WSTTdKzzz5bWXkbaftPnjw5HXLIIfnv0FxzzZWfs9tuu6VXX3210jI32negpb322is/57TTTpupZezu/jod++Af//hH+ta3vpWvLB/fh6i3vvjii10bUC6//PL0ox/9KE8l9vDDD6dVV101bbbZZumNN97o6FsxA+688860zz77pDFjxqRRo0blP4qbbrppev/996suWsN54IEH0rnnnptWWWWVqovScN5+++20/vrrp169eqWbbropPfXUU+nkk09O8847b9VFawgnnHBCOvvss9OZZ56ZD0Rx/8QTT0wjR46sumjdWvydj2NunCRsT+yDM844I51zzjnpvvvuyxWDOD5/+OGHM72sjbb9P/jgg1wniuAe/1911VX55GFU0ph534G6q6++OteTohLNzN0Hzz//fNpggw3Scsstl+64447097//PX8volGjQ2odtPbaa9f22Wef5vsff/xxbeDAgbURI0Z09K3oBG+88UacsqzdeeedVRelobz33nu1pZdeujZq1Kja4MGDawcccEDVRWoohxxySG2DDTaouhgNa8iQIbVhw4a1WrbtttvWdtlll8rK1Gji7/7VV1/dfH/KlCm1BRdcsHbSSSc1L3vnnXdqs802W+3SSy+tqJSNs/3bc//99+fnjRs3bqaVq5FMax+8/PLLtYUXXrj2xBNP1BZddNHaqaeeWkn5GnUf7LjjjrVdd931M793h1pQJk2alB566KHcbFw3yyyz5Pv33ntvx5IRneLdd9/N//fv37/qojSUaMUaMmRIq+8CM891112X1lprrbT99tvnro6rr756+vWvf111sRrGeuutl/7yl7+kZ555Jt9/7LHH0t1335222GKLqovWsMaOHZtee+21Vn+TontFdMN2fK7u+BxdYPr161d1URrGlClT0ne/+9108MEHpxVXXLHq4jTk9r/xxhvTMsssk1tv4/gcf4M+qSvetHQooLz11lu57/GAAQNaLY/78YeRmf+LEGMfoqvLSiutVHVxGsZll12Wm/BjPBDVeOGFF3IXo6WXXjrdcsstae+99077779/uuiii6ouWkP42c9+lnbaaafchB/d7CIgxt+iXXbZpeqiNaz6MdjxuQzRrS7GpOy8886pb9++VRenYUR30549e+bjATNfDPdoamrK43M333zzdOutt6ZtttkmbbvttnmIQkf07LJSMlPO4j/xxBP5zCUzx0svvZQOOOCAPP6nw/0p6dRwHi0oxx13XL4fFeT4LkTf+6FDh1ZdvG7viiuuSH/4wx/SJZdcks9SPvroozmgRH9v259GF2NDd9hhhzxpQZxIYeaIHj6nn356PoEYLVdUc2wOW221VTrooIPyz6uttlq655578vF58ODBXdOCMv/886dZZ501vf76662Wx/0FF1ywI2/FZ7TvvvumG264IY0ePTp98YtfrLo4DfUHMM4QrLHGGvksTdzirEAMTI2fo4WRrhezFK2wwgqtli2//PIdniWEGRPdJ+qtKDFrUXSpiIORVsXq1I/Bjs9lhJNx48blE1laT2aeu+66Kx+fBw0a1Hx8jv3w4x//OM88S9eLnBDbvTOOzx0KKL17905rrrlm7nvcMi3F/XXXXbdDH8yMiTMyEU5ihorbb789T/PJzLPxxhunxx9/PJ8xrt/iTH50bYmfI8DT9aJbY9vptWM8xKKLLlpZmRpJzFgU4w9bit/9+tkzZr44FkQQaXl8njBhQp7Ny/F55oaTmNr5tttuy1OgM/PEiZKYMarl8TladeOESnQFputFTogphTvj+NzhLl4xxXA04UelbO21187zS8eUY3vssUdH34oZ7NYV3SquvfbafC2Uet/iGAwZ897TtWKbtx3vE1N5xoHIOKCZJ87Wx0Dt6OIVFYK4FtN5552Xb3S9mAP/2GOPzWcqo4vXI488kk455ZQ0bNiwqovWrUXf7ueee67VwPiohMUkKbEvopvdMccck8dmRWCJqT2jghbXy6Jrt3+06m633Xa5e1H0bojW9PrxOR6Pihtd/x1oGwpjjFwE92WXXbaC0jbmPjj44IPTjjvumDbccMP0ta99Ld18883p+uuvz1MOd8iMTP01cuTI2qBBg2q9e/fO0w6PGTPmM08nxvSJXdbe7YILLqi6aA3LNMPVuP7662srrbRSnkZ1ueWWq5133nlVF6lhTJgwIf/Ox3Fg9tlnry2xxBK1X/ziF7WJEydWXbRubfTo0e3+/R86dGjzVMOHHXZYbcCAAfl7sfHGG9eefvrpqovdENt/7Nix0zw+x+uYOd+BtkwzXM0+OP/882tLLbVUPj6suuqqtWuuuabDn9Mj/un8fAUAANBxHb6SPAAAQFcRUAAAgGIIKAAAQDEEFAAAoBgCCgAAUAwBBQAAKIaAAgAAFENAAQAAiiGgAAAAxRBQAACAYggoAABAMQQUAAAgleL/ATwTEzjW7N/GAAAAAElFTkSuQmCC", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAygAAADTCAYAAABqSTe2AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8ekN5oAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAY4klEQVR4nO3dCbgd8/0/8G/IhogIlaASu9h3ak01ammqltZWKsSjpbFWVTdiTSxVS3iQUvRRa+3UEhpKiZ1Sak1jq+0XRKgkkvk/n+//Ofe59+aGe5N7MyPn9Xqek3tmzpxzvjOTc2be811Op6IoigQAAFAB85VdAAAAgBoBBQAAqAwBBQAAqAwBBQAAqAwBBQAAqAwBBQAAqAwBBQAAqAwBBQAAqAwBBQAAqAwBBaBC7r333tSpU6f8twqOO+64XJ55RaxLrBMA1SWgAMBs+vDDD9N8882X7rzzzjx9ww03pG7duqUpU6Y0WW7y5Mlp+PDhabvttku9e/fOQenSSy8tqdQA1SagADBLv/3tb9P//ve/NK+IdYl1ai+PPPJI/rvxxhvnvw899FBad911c0hp7P33308nnHBCev7559Paa6/dbu8PMC/qXHYBAEjps88+S127dk1V07lz53ybV3Tv3v1Ll/nkk0/SQgst1OqAssoqq6RevXo1BJRaWGlsySWXTP/9739T375902OPPZY23HDD2Sg9QH1QgwLUtSeffDJtv/32qWfPnqlHjx5p0KBBady4cQ2Px8lkNMe57LLLZnpuNOuJx2699daGeW+++WYaOnRo6tOnT76Kvvrqq6c//vGPLfYzueqqq/LV/KWXXjotuOCCadKkSS2W8f7770+77rpr6tevX37NZZZZJh1xxBEz1Wzsu+++eR1effXVtO222+aT7KWWWipfuS+KomG5//znP/n9f/e736Uzzzwz9e/fPy2wwAJp4MCB6dlnn/3SPigxffDBB6cbb7wxrbHGGg3reccdd8xU9ljXDTbYIAeDFVZYIV144YWt7tfyzW9+M7/+448/njbddNNcxuWWWy5dcMEFTZabOnVqOvbYY9P666+fFllkkbzeW2yxRRo7duyX9kGpleW5555LP/zhD9Oiiy6aNt988y8s10cffZRrROIWgSRqROL+O++8k8s6YMCAPB3L1cQ2inACwJebdy6LAbTRv/71r3wiG+HkF7/4RerSpUs+gY4T4/vuuy9fCY+T6+WXXz5dc801aciQIU2ef/XVV+cT2ggDIU5Qv/GNbzScwH/ta19Lt99+e9p///1z+Dj88MObPP/EE0/MtSY///nPc5+FWdWgXHvttenTTz9NBx10UFpsscXyVftRo0alN954Iz/W2PTp03M/hyjHaaedlkND9H34/PPPc1Bp7E9/+lP6+OOP07Bhw3INztlnn52+9a1vpWeeeSYHrC/ywAMPpOuvvz799Kc/TQsvvHA655xz0ve///302muv5TLWwl+UJWoPjj/++Fy2KENsl9b64IMP0ne+85202267pT333DPvh9gOsa0iCIbYthdddFF+/IADDsjrdPHFF+f9EttqnXXW+dL3iQC40korpREjRjQJcy3Zcccd8/+P5v8XamKbxC0CX1UGOwD4SikA6tROO+1UdO3atXjllVca5r311lvFwgsvXGy55ZYN8371q18VXbp0KSZOnNgwb8qUKUWvXr2KoUOHNszbf//9iyWXXLJ4//33m7zPHnvsUSyyyCLFp59+mqfHjh0bZ8DF8ssv3zCvpvZY/K1pvkwYOXJk0alTp2LChAkN84YMGZKfe8ghhzTMmzFjRjF48OC8nu+9916eN378+LzcAgssULzxxhsNyz788MN5/hFHHNEwb/jw4XleYzEdr/fyyy83zHv66afz/FGjRjXM22GHHYoFF1ywePPNNxvmvfTSS0Xnzp1nes2WDBw4MC93xhlnNNnu66yzTrHEEksUU6dOzfM+//zzPL+xDz74oOjTp0+T/VMre6xT8/Xbc889i9Z67LHHijFjxhTnnXdefu7ll1+ep/fdd99imWWWyffjFsu15NFHH83Pu+SSS1r9ngD1RBMvoC7F1fy77ror7bTTTrmGpCau9kdTn6ghqDW52n333dO0adNyjUFNPDdGcIrHQpz7XnfddWmHHXbI92tNgOIWV/Kjuc8TTzzRpAxRIxPNlr5M42Wif0S8ZjR5iveJWormovamplabE82g7r777ibLxbpH87KajTbaKNca/fWvf/3SMm299da5yVbNWmutlWuionlZbfvG+8V7RDOzmhVXXDE3qWut6P/yk5/8pGE6ak5i+t13383NqcL888/fUPs0Y8aMNHHixFxjFLVfzbf5rBx44IGtLlM0JYv1j/eIddtrr73y9HvvvZebCMb9uMVy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VIaAAgAAfLUDynnnnZeWXXbZ1L1797TxxhunRx55pP1LRotGjhyZNtxww7TwwgunJZZYIu20007phRdeKLtYdeuUU05JnTp1SocffnjZRak7b775Ztp7773TYostlhZYYIG05pprpscee6zsYtWF6dOnp2OOOSYtt9xyeduvsMIK6cQTT0zGXOlYf//739MOO+yQllpqqfy9c+ONNzZ5PLb/sccem5Zccsm8X7beeuv00ksvlVbeetr+06ZNS0cffXT+HlpooYXyMvvss0966623Si1zvX0GGjvwwAPzMmedddZcLeO87u+t2AfPP/98+t73vpd/WT4+D3He+tprr3VsQLn66qvTz372szyU2BNPPJHWXnvttO2226Z33323rS/FbLjvvvvSsGHD0rhx49KYMWPyl+I222yTPvnkk7KLVnceffTRdOGFF6a11lqr7KLUnQ8++CBtttlmqUuXLun2229Pzz33XDrjjDPSoosuWnbR6sKpp56azj///HTuuefmA1FMn3baaWnUqFFlF22eFt/zccyNi4QtiX1wzjnnpAsuuCA9/PDD+cQgjs+fffbZXC9rvW3/Tz/9NJ8TRXCPv9dff32+eBgnacy9z0DNDTfckM+T4iSaubsPXnnllbT55punAQMGpHvvvTf985//zJ+LqNRok6KNNtpoo2LYsGEN09OnTy+WWmqpYuTIkW19KdrBu+++G5csi/vuu6/sotSVjz/+uFhppZWKMWPGFAMHDiwOO+ywsotUV44++uhi8803L7sYdWvw4MHF0KFDm8zbZZddir322qu0MtWb+N6/4YYbGqZnzJhR9O3btzj99NMb5n344YdFt27diiuvvLKkUtbP9m/JI488kpebMGHCXCtXPZnVPnjjjTeKpZdeunj22WeL/v37F2eeeWYp5avXfbD77rsXe++99xy/dptqUKZOnZoef/zxXG1cM9988+Xphx56qG3JiHbx0Ucf5b+9e/cuuyh1JWqxBg8e3OSzwNxz8803pw022CDtuuuuuanjuuuum/7whz+UXay6semmm6Z77rknvfjii3n66aefTg888EDafvvtyy5a3Ro/fnx6++23m3wnRfOKaIbt+Fze8TmawPTq1avsotSNGTNmpB/96EfpqKOOSquvvnrZxanL7X/bbbellVdeOdfexvE5voO+qCnerLQpoLz//vu57XGfPn2azI/p+GJk7v9HiL4P0dRljTXWKLs4deOqq67KVfjRH4hyvPrqq7mJ0UorrZTuvPPOdNBBB6VDDz00XXbZZWUXrS788pe/THvssUeuwo9mdhEQ47tor732Krtodat2DHZ8roZoVhd9Uvbcc8/Us2fPsotTN6K5aefOnfPxgLkvuntMnjw598/dbrvt0l133ZV23nnntMsuu+QuCm3RucNKyVy5iv/ss8/mK5fMHa+//no67LDDcv+fNrenpF3DedSgjBgxIk/HCXJ8FqLt/ZAhQ8ou3jzvmmuuSX/+85/TFVdcka9SPvXUUzmgRHtv2596F31Dd9tttzxoQVxIYe6IFj5nn312voAYNVeUc2wOO+64YzriiCPy/XXWWSc9+OCD+fg8cODAjqlBWXzxxdP888+f3nnnnSbzY7pv375teSnm0MEHH5xuvfXWNHbs2PT1r3+97OLU1RdgXCFYb7318lWauMVVgeiYGvejhpGOF6MUrbbaak3mrbrqqm0eJYTZE80narUoMWpRNKmIg5FaxfLUjsGOz9UIJxMmTMgXstSezD33339/Pj7369ev4fgc++HII4/MI8/S8SInxHZvj+NzmwJK165d0/rrr5/bHjdOSzG9ySabtOmNmT1xRSbCSYxQ8be//S0P88ncM2jQoPTMM8/kK8a1W1zJj6YtcT8CPB0vmjU2H147+kP079+/tDLVkxixKPofNhb/92tXz5j74lgQQaTx8XnSpEl5NC/H57kbTmJo57vvvjsPgc7cExdKYsSoxsfnqNWNCyrRFJiOFzkhhhRuj+Nzm5t4xRDDUYUfJ2UbbbRRHl86hhzbb7/92vpSzGazrmhWcdNNN+XfQqm1LY7OkDHuPR0rtnnz/j4xlGcciPQDmnvian101I4mXnFCEL/FNHr06Hyj48UY+CeffHK+UhlNvJ588sn0+9//Pg0dOrTsos3Tom33yy+/3KRjfJyExSApsS+imd1JJ52U+2ZFYImhPeMELX4vi47d/lGr+4Mf/CA3L4rWDVGbXjs+x+Nx4kbHfwaah8LoIxfBfZVVVimhtPW5D4466qi0++67py233DJttdVW6Y477ki33HJLHnK4TWZn6K9Ro0YV/fr1K7p27ZqHHR43btwcDydG68Qua+l2ySWXlF20umWY4XLccsstxRprrJGHUR0wYEAxevTosotUNyZNmpT/z8dxoHv37sXyyy9f/OY3vymmTJlSdtHmaWPHjm3x+3/IkCENQw0fc8wxRZ8+ffLnYtCgQcULL7xQdrHrYvuPHz9+lsfneB5z5zPQnGGGy9kHF198cbHiiivm48Paa69d3HjjjW1+n07xT/vnKwAAgLZr8y/JAwAAdBQBBQAAqAwBBQAAqAwBBQAAqAwBBQAAqAwBBQAAqAwBBQAAqAwBBQAAqAwBBQAAqAwBBQAAqAwBBQAAqAwBBQAASFXx/wAOW0rnl+0oyQAAAABJRU5ErkJggg==", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "visualize_intervals(overlapping_intervals)" ] @@ -288,7 +145,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "id": "bc0f8689c31221b3", "metadata": { "ExecuteTime": { @@ -296,22 +153,14 @@ "start_time": "2025-02-24T16:59:37.652480Z" } }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "INFO:polars_bio.operation:Running Nearest operation with algorithm Coitrees and 1 thread(s)...\n" - ] - } - ], + "outputs": [], "source": [ "nearest_intervals = pb.nearest(df1, df2, output_type=\"pandas.DataFrame\")" ] }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "id": "aad83ab53e1294fc", "metadata": { "ExecuteTime": { @@ -319,101 +168,14 @@ "start_time": "2025-02-24T16:59:37.665033Z" } }, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
chrom_1start_1end_1chrom_2start_2end_2distance
0chr115chr1480
1chr138chr1480
2chr1810chr1480
3chr11214chr110111
\n", - "
" - ], - "text/plain": [ - " chrom_1 start_1 end_1 chrom_2 start_2 end_2 distance\n", - "0 chr1 1 5 chr1 4 8 0\n", - "1 chr1 3 8 chr1 4 8 0\n", - "2 chr1 8 10 chr1 4 8 0\n", - "3 chr1 12 14 chr1 10 11 1" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "display(nearest_intervals)" ] }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "id": "5f69f700b50f58e2", "metadata": { "ExecuteTime": { @@ -421,48 +183,7 @@ "start_time": "2025-02-24T16:59:37.673937Z" } }, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAygAAADTCAYAAABqSTe2AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8ekN5oAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAXGUlEQVR4nO3dCbRVZf0/4BdlUhEVTBANNHM2UVEyNcmFaWaZmmOaJLVSc0rNpQ2KMymZYznVQlc5VYpTOWDiUEpgakEaDiE4pKioeJ0gPf/1fX//c9e9CMLFy92vnOdZ63DPPnffs9+zN+fs97Pf4XSq1Wq1BAAAUIClqi4AAABAnYACAAAUQ0ABAACKIaAAAADFEFAAAIBiCCgAAEAxBBQAAKAYAgoAAFAMAQUAACiGgAJA8b71rW+lNdZYo+piANABBBQAPtRbb72VTjrppHT33XenJcluu+2W9t1333y/VqullVZaKV1++eXzXPemm25Km222WerevXvq379/GjFiRPrf//7XwSUGaAwCCgALDCgnn3xypQHlsssuS1OmTGnX55wwYULacsst8/3HHnssvfbaa83LLd16661p1113TSuuuGK64IIL8v3TTjstHX744e1aHgD+T+f//xOAJcSbb76ZlltuubQk6dKlywLXiRaN999/P3Xt2nWB6z777LPp+eefbw4kDzzwQFphhRXSuuuu+4F1f/CDH6SNN9443XHHHalz5/87bfbs2TOdccYZ6cgjj0zrrbfeIr0mAOZNCwrARxTdnzp16pSefPLJPFYirrRHZffAAw/MrQ9z++1vf5sGDRqUlllmmdSrV6+0zz77pGeeeabVOvfdd1/ac889c3eibt26pU9+8pPpqKOOSm+//Xar9WJ7PXr0SE899VT68pe/nJZffvm033775d9FZf3cc89NG264Ye6a1KdPn3TQQQelV199tdVzPPjgg2nHHXdMK6+8ci7TmmuumYYPH55/9/TTT6dPfOIT+X60osTrjFu85vmJblKxzr333pu317t371yhP+CAAz6w7RtvvDHtvPPOqV+/fvl1rrXWWunUU09N77333oeOQYlyxTZ+9rOf5dcYfxd//+ijj863XO+++256+eWX823cuHE59MR+jeUoa4SQV155JS/HvgvxfHH77ne/2xxOwve+973cLewPf/jDfLcHwKLRggLQTvbaa69cuR85cmR66KGH0q9+9au0yiqrpDPPPLN5ndNPPz2dcMIJed3vfOc76aWXXsrdhrbddtv08MMP53ATfv/73+dwc8ghh+QKfnRHivXiyn/8bu6WgwgY22yzTa6wL7vssvnxCAcRFiIoHXHEEWnq1KnpwgsvzNv561//mivoM2bMSDvssEMOIccff3zeflT+r7/++vwc8fhFF12UyxFjNnbffff8eFTmF+Swww7LzxdhJrpnxfNMmzYtdxWLcBGifBGwjj766PzzrrvuSieeeGKaNWtWGjVq1AK3MXr06PTOO+/kABEBJQLf/Fx99dV5X7S02mqrtVquh7HYVxGIYl+FzTffvNV6EahWX3315t8D0I5qAHwkI0aMqMXH6fDhw1s9vttuu9V69+7dvPz000/Xll566drpp5/ear1JkybVOnfu3Orxt9566wPbGTlyZK1Tp061adOmNT82bNiwvO3jjz++1br33XdffvzKK69s9fhtt93W6vExY8bk5YkTJ8739b300kt5nXidC2P06NF5/UGDBtVmz57d/PhZZ52VH7/xxhs/9HUedNBBtWWXXbb2zjvvtHqdAwYMaF6eOnVqfq6ePXvWZsyYsVDlev7552tjx47Nt3iuAw44IN+/+uqr83Odf/75zb9/++2389+MGjUq/2769OkfeL4tttiituWWWy7UtgFYeLp4AbSTgw8+uNXy5z//+dxlKFoDQrRKRNehaD2pdzWKW9++fdPaa6+dux3VRVerlmNKYr2tttoqdyua11X7aOFoKVpZopvZF7/4xVbbiq5l0VJR31a9xeaWW25Jc+bMadf9Ea0aLceORBmjm9Sf/vSneb7ON954I5cx9lu0Hv373/9e4Da+/vWvN7d6LMiqq66att9++9waEl3qoitcLEeZogtclDeW4xbLod6lLlpn5hbrzN3lDoCPThcvgHYS40VaimlrQ4y7iDEYTzzxRA4YEUbmpWVlfvr06bmrU0xvO/e4jddff73VclSwo7tRS7GtWC+6mM1LdO0KQ4YMyZX8GF9yzjnnpC984Qt5lqpvfOMb86yUt8XcrzOCUYSE6EJW969//Sv95Cc/yV276kFufq9zXqJL3cKI8FV/vttvvz0ttdRSeXB7BKJY3nTTTXNAilsEu/qxqAeoGL8yt+ha1jJgAdA+BBSAdrL00kvP8/EIJSFaT2Ls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3gN1Y8aMyfWkqETTscfgqaeeSttss01ab7310t13353++c9/5vdFNGq0Sa2NBg8eXDv00EObl997771av379aiNHjmzrU9EOZsyYEZcsa/fcc0/VRWkob7zxRm3ttdeujR07tjZkyJDakUceWXWRGspxxx1X22abbaouRsPaeeeda8OHD2/12O67717bb7/9KitTo4nP/TFjxjQvv//++7W+ffvWRo0a1fzYa6+9VuvWrVvt6quvrqiUjbP/52XChAl5vWnTpnVYuRrJ/I7Bs88+W1tttdVqkydPrg0YMKB2zjnnVFK+Rj0Ge++9d23//ff/yM/dphaU2bNnp7///e+52bhuqaWWyssPPPBA25IR7eL111/PP3v16lV1URpKtGLtvPPOrd4LdJybbropbb755mnPPffMXR033XTTdNlll1VdrIax1VZbpT//+c/p8ccfz8v/+Mc/0l/+8pe00047VV20hjV16tT0wgsvtPpMiu4V0Q3b+bm683N0gVlxxRWrLkrDeP/999M3v/nNdOyxx6YNN9yw6uI05P7/4x//mNZZZ53cehvn5/gM+rCuePPTpoDy8ssv577Hffr0afV4LMcHIx3/HyHGPkRXl4022qjq4jSMa665Jjfhx3ggqvGf//wndzFae+210+23354OOeSQdMQRR6Qrrrii6qI1hOOPPz7ts88+uQk/utlFQIzPov3226/qojWs+jnY+bkM0a0uxqTsu+++qWfPnlUXp2FEd9POnTvn8wEdL4Z7NDU15fG5X/rSl9Idd9yRdtttt7T77rvnIQpt0XmxlZIOuYo/efLkfOWSjvHMM8+kI488Mo//aXN/Sto1nEcLyhlnnJGXo4Ic74Xoez9s2LCqi7fE+93vfpeuvPLKdNVVV+WrlI888kgOKNHf2/6n0cXY0L322itPWhAXUugY0cPnvPPOyxcQo+WKas7N4Wtf+1o66qij8v1NNtkk3X///fn8PGTIkMXTgrLyyiunpZdeOr344outHo/lvn37tuWp+IgOO+ywdMstt6Rx48al1VdfveriNNQHYFwh2GyzzfJVmrjFVYEYmBr3o4WRxS9mKdpggw1aPbb++uu3eZYQFk10n6i3osSsRdGlIk5GWhWrUz8HOz+XEU6mTZuWL2RpPek49913Xz4/9+/fv/n8HMfhmGOOyTPPsvhFToj93h7n5zYFlK5du6ZBgwblvsct01Isf+5zn2vThlk0cUUmwknMUHHXXXflaT7pOEOHDk2TJk3KV4zrt7iSH11b4n4EeBa/6NY49/TaMR5iwIABlZWpkcSMRTH+sKX4v1+/ekbHi3NBBJGW5+dZs2bl2bycnzs2nMTUznfeeWeeAp2OExdKYsaolufnaNWNCyrRFZjFL3JCTCncHufnNnfxiimGowk/KmWDBw/O80vHlGMHHnhgW5+KRezWFd0qbrzxxvxdKPW+xTEYMua9Z/GKfT73eJ+YyjNORMYBdZy4Wh8DtaOLV1QI4ruYLr300nxj8Ys58E8//fR8pTK6eD388MPp5z//eRo+fHjVRVuiRd/uJ598stXA+KiExSQpcSyim91pp52Wx2ZFYImpPaOCFt+XxeLd/9Gqu8cee+TuRdG7IVrT6+fn+H1U3Fj874G5Q2GMkYvgvu6661ZQ2sY8Bscee2zae++907bbbpu22267dNttt6Wbb745TzncJosy9dcFF1xQ69+/f61r16552uHx48d/5OnEWDhxyOZ1Gz16dNVFa1imGa7GzTffXNtoo43yNKrrrbde7dJLL626SA1j1qxZ+f98nAe6d+9e+9SnPlX78Y9/XHv33XerLtoSbdy4cfP8/B82bFjzVMMnnHBCrU+fPvl9MXTo0NqUKVOqLnZD7P+pU6fO9/wcf0fHvAfmZprhao7Br3/969qnP/3pfH4YOHBg7YYbbmjzdjrFP+2frwAAANquzd8kDwAAsLgIKAAAQDEEFAAAoBgCCgAAUAwBBQAAKIaAAgAAFENAAQAAiiGgAAAAxRBQAACAYggoAABAMQQUAACgGAIKAACQSvH/AFFsXXBd2e9cAAAAAElFTkSuQmCC", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAygAAADTCAYAAABqSTe2AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8ekN5oAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAWgUlEQVR4nO3dC7AWZf0H8Ae5iIqoYIpooBlqYqJpVspfcjTNmEzIG0GS1KSOpqk52gXxRqRmXstbDTqFaKWIWGqYeCklMbU0zVuItxQVBY+okL7/+T0z75lzEJQD55x95Hw+My+c3bPsPu8u77v73eeynWq1Wi0BAAAUYLWqCwAAAFAnoAAAAMUQUAAAgGIIKAAAQDEEFAAAoBgCCgAAUAwBBQAAKIaAAgAAFENAAQAAiiGgAFC8b3zjG2nTTTetuhgAtAMBBYD3tXDhwnTyySen2267La1Khg0blkaMGJF/rtVqab311kuXX375e5a7+uqr06hRo9KAAQNSp06d0uc///kKSgvQcQgoAHxgQDnllFMqDSiXXXZZevTRR1t1nffcc0/67Gc/m39+5JFH0muvvdY43dRFF12Upk6dmj760Y/mEANA2+rSxusHoJ298cYbaa211kqrkq5du37gMv/73//Su+++m7p16/aByz777LPp+eefbwwkd999d1pnnXXSlltu+Z5lf/3rX6eNN944rbbaammbbbZZwXcAwPJSgwKwkqL5UzT9eeKJJ3JfiXXXXTdf7B5yyCG59mFJv/nNb9IOO+yQ1lhjjdSrV6900EEHpWeeeabZMnfeeWfaf//9U79+/dLqq6+e794fc8wx6c0332y2XGyvR48e6cknn0xf+tKX0tprr51GjhyZfxcX6+eee24aOHBg6t69e9pwww3ToYceml599dVm67j33nvTXnvtldZff/1cps022yyNGTMm/+6pp55KH/nIR/LPUYsS7zNe8Z6XJZpJxTJ33HFH3l7v3r1Tz54908EHH/yebUfNxNChQ1Pfvn3z+9x8883Taaedlt5555337YMS5Ypt/PSnP83vMf5d/PuHH354meV6++2308svv5xfM2bMyKEn9mtMR1m33Xbb9Morr+Tp2Hd1sUyEEwDahxoUgFZywAEH5Iv7CRMmpPvuuy/98pe/TBtssEE644wzGpcZP358Gjt2bF72W9/6VnrppZfSBRdckHbdddd0//3353ATfve73+Vwc/jhh+cL/GiOFMvFnf/43ZI1BxEwBg8enC/Y11xzzTw/wkGEhQhKRx11VJo9e3a68MIL83b++te/5gv0uXPnpj333DOHkBNPPDFvPy7+r7322ryOmB9NnKIc0Wdj+PDheX5czH+QI488Mq8vwkw0z4r1zJkzJzcVi3ARonwRsI499tj896233ppOOumktGDBgnTWWWd94DYmTpyY3nrrrfTtb387B5QIfMsyefLkvC+aipqRpuphLPaVTvkAFakBsFLGjRtXi6/TMWPGNJs/bNiwWu/evRunn3rqqVrnzp1r48ePb7bcgw8+WOvSpUuz+QsXLnzPdiZMmFDr1KlTbc6cOY3zRo8enbd94oknNlv2zjvvzPMnTZrUbP5NN93UbP6UKVPy9KxZs5b5/l566aW8TLzP5TFx4sS8/A477FBbtGhR4/wzzzwzz586der7vs9DDz20tuaaa9beeuutZu+zf//+jdOzZ8/O6+rZs2dt7ty5y1Wu559/vjZ9+vT8inUdfPDB+efJkyfndZ1//vmNv3/zzTeXuo6BAwfWhgwZslzbA2DFqLMGaCWHHXZYs+n/+7//y02GojYgRK1ENB2K2pN6U6N49enTJ48QFc2O6qKpVdM+JbHczjvvnEebihqQJUUNR1NRyxLNzL7whS8021Y0LYuaivq26jU2N9xwQ1q8eHGr7o+o1WjadyTK2KVLl/THP/5xqe/z9ddfz2WM/Ra1R//+978/cBtf/epXG2s9PshGG22U9thjj7TjjjvmJnXRFC6mo0zRBC7KG9PximkAqqGJF0Arif4iTdVHfIp+F9EH4/HHH88BI8LI0jS9mH/66adzU6frr7/+Pf025s+f32w6LrA32WSTZvNiW7FcNDFbmmjaFYYMGZIv8qN/yTnnnJOH0N13333T1772tdxkamUs+T4jGEVIiCZkdf/617/Sj370o9y0qx7klvU+lyaa1C2PCF/19d188825T8lWW22VA1FMb7/99jkgxSuC3fJ0ygegbQgoAK2kc+fOS50foSRE7Un0vbjxxhuXumxcwIfoIB41H/PmzUsnnHBCvpCOUbmee+653Fm8aQfuEEFiyU7csUyEk0mTJi21TPVahyjP73//+zRz5sw0bdq0fLEeHeTPPvvsPK9eprYQw/pGQIrwduqpp+aO7lFzEf134n0v+T6XpmkNzPuJPje77bZbs3n9+/df6j6J2iXPOgGojoAC0E7iAjzCStz132KLLZa53IMPPpgee+yxdMUVV+SRr+qmT5/eom3dcsstaZdddlmui/gYbjde0Yn/yiuvzM2frrrqqtyRv96hvaWiFqdpKGhoaEj//e9/82hjITrLRxO4aPoWgwTURQf11jZo0KDG/RdNzeK9jh49Oteq7Lfffum8885LW2+9deOyAFRHHxSAdhIjYEXNSTSnqteq1MV0XKyHeu1K02Xi57iIXl7RzyVqYmLI3iXFqF9RexGi+diSZdluu+0ah+UN9VHB6v9meV166aXN+rXEKF6x7b333nuZ73PRokXpF7/4RWpt0dwu+pbESGfRfC6atcV01ExFOb75zW829j/xMEaAaqlBAWgnUatx+umnp+9///u5H0b09YjnlkSNwZQpU3In7e9973u5SVcsGz9Hs65oAnXNNde8py/K+4mmUzHMcAx5/MADD+ShhKNfRdRqRAf6CDtRcxC1NBEIYgjh2Gb0wYintsc26zUdUQMTtQtXX311rvmJoXzjgYUf9NDCCBu77757DksxzHBsJwLCPvvsk38fnf4jDERNRgyDHDU18VDEJQNTa4pnvkS5YtvhrrvuykMmv9+DLeMZKfEKMSx0DFoQxzFEzU/T2h8AVp6AAtCO4lkjcZEfHdKjJqX+IMAIEPUL9wgS0R8kLtojYES/jAgQ8VyRljQ/uvjii/OoXZdcckn6wQ9+kDvTx7M9Ro0alZt+1YNMPGMlmnO9+OKLuYP4TjvtlPuuNO2AHs90+c53vpMfFhkX+OPGjfvAgBLPXIn1RGf/qEkZMWJEOv/88xubjMXzXWL0sOOOOy53lI+wEmWLUBPPdWkL0Rclglh98IB4gnw9rCxLdOCvH6u6eJZNiP0goAC0rk4x1nArrxOADqz+cMhZs2blIX0BoCX0QQEAAIohoAAAAMUQUAAAgGLogwIAABRDDQoAAFAMAQUAACiGgAIAABRDQAEAAIohoAAAAMUQUAAAgGIIKAAAQDEEFAAAoBgCCgAAUAwBBQAAKIaAAgAAFENAAQAAitGl6gLQsc2bNy81NDRUXQxgJfTo0SP16tWr6mIAsIoQUKg0nJxyyqlp8eJFVRcFWAldu3ZL48adJKQA0CoEFCoTNScRTnrv9tXUdd2PVF0cYAUsfu2l9MqMa/LnWUABoDUIKFQuwkm39ftWXQwAAAqgkzwAAFAMAQUAACiGgAIAABRDQAEAAIohoAAAAMUQUAAAgGIIKAAAQDEEFAAAoBgCCgAAUAwBBQAAKIaAAgAAFENAAQAAiiGgAAAAxRBQAACAYggoAABAMQQUAACgGAIKAABQDAEFAAAohoACAAAUQ0ABAACKIaAAAADFEFAAAIBiCCgAAEAxBBQAAKAYAgoAAFCMLlUXABa/9lLVRQBWkM8vAK1NQKEyPXr0SF27dkuvzLim6qIAKyE+x/F5BoDW0KlWq9VaZU2wAubNm5caGhqqLgawEiKc9OrVq+piALCKEFAAAIBi6CQPAAAUQ0ABAACKIaAAAADFEFAAAIBiCCgAAEAxBBQAAKAYAgoAAFAMAQUAACiGgAIAABRDQAEAAIohoAAAAMUQUAAAgGIIKAAAQDEEFAAAoBgCCgAAUIwuVRcAPszmzZuXGhoaqi4GVKpHjx6pV69eVRcDgFWEgAIrEU5OPeWUtGjx4qqLApXq1rVrOmncOCEFgFYhoMAKipqTCCff2P6zqU+PnlUXByrxQsOCdPn9M/PnQUABoDUIKLCSIpz0W9eFGQBAa9BJHgAAKIaAAgAAFENAAQAAiiGgAAAAxRBQAACAYggoAABAMQQUAACgGAIKAABQDAEFAAAohoACAAAUQ0ABAACKIaAAAADFEFAAAIBiCCgAAEAxBBQAAKAYAgoAAFAMAQUAACiGgAIAABRDQAEAAIohoAAAAMUQUAAAgGIIKAAAQDEEFAAAoBgCCgAAUAwBBQAAKEaXqgsAH3YvNCyoughQGf//AWhtAgqsoB49eqRuXbumy++fWXVRoFLxOYjPAwC0hk61Wq3WKmuCDmjevHmpoaGh6mJApSKc9OrVq+piALCKEFAAAIBi6CQPAAAUQ0ABAACKIaAAAADFEFAAAIBiCCgAAEAxBBQAAKAYAgoAAFAMAQUAACiGgAIAABRDQAEAAIohoAAAAMUQUAAAgGIIKAAAQDEEFAAAoBgCCgAAUAwBBQAAKIaAAgAAFENAAQAAiiGgAAAAxRBQAACAYggoAABAMQQUAACgGAIKAABQDAEFAAAohoACAAAUQ0ABAACKIaAAAADFEFAAAIBiCCgAAEAxBBQAAKAYAgoAAFAMAQUAACiGgAIAABRDQAEAAIohoAAAAMUQUAAAgGIIKAAAQDEEFAAAoBgCCgAAUAwBBQAAKIaAAgAAFENAAQAAiiGgAAAAxRBQAACAYggoAABAMQQUAACgGAIKAABQDAEFAAAohoACAAAUQ0ABAACKIaAAAADFEFAAAIBiCCgAAEAxBBQAAKAYAgoAAPDhDihvv/12Ovnkk/PfVMMxqJ5jUD3HoHqOQfUcg+o5BtVzDFat/d+pVqvVWvqPFixYkNZZZ500f/781LNnz1YpCC3jGFTPMaieY1A9x6B6jkH1HIPqOQar1v7XxAsAACiGgAIAABRDQAEAAD7cAWX11VdP48aNy39TDcegeo5B9RyD6jkG1XMMqucYVM8xWLX2/wp1kgcAAGgLmngBAADFEFAAAIBiCCgAAEAxBBQAAODDHVB+/vOfp0033TR17949feYzn0n33HNP65eMpZowYUL69Kc/ndZee+20wQYbpH333Tc9+uijVRerw/rJT36SOnXqlL773e9WXZQO57nnnkujRo1KvXv3TmussUb65Cc/me69996qi9UhvPPOO2ns2LFps802y/t+8803T6eddloy5krbuuOOO9KXv/zl1Ldv3/y9c9111zX7fez/k046KW200Ub5uOyxxx7p8ccfr6y8HWn/L168OJ1wwgn5e2ittdbKyxx88MHp+eefr7TMHe0z0NRhhx2Wlzn33HPbtYyrujuW4xg88sgjaZ999slPlo/PQ1y3Pv30020bUK6++up07LHH5qHE7rvvvjRo0KC01157pblz57Z0VayA22+/PR1xxBFp5syZafr06flLcc8990xvvPFG1UXrcGbNmpUuueSStO2221ZdlA7n1VdfTbvsskvq2rVruvHGG9PDDz+czj777LTeeutVXbQO4YwzzkgXXXRRuvDCC/OJKKbPPPPMdMEFF1RdtFVafM/HOTduEi5NHIPzzz8/XXzxxelvf/tbvjCI8/Nbb73V7mXtaPt/4cKF+Zoognv8fe211+abh3GRRvt9BuqmTJmSr5PiIpr2PQZPPvlkGjx4cNpqq63Sbbfdlv75z3/mz0VUarRIrYV22mmn2hFHHNE4/c4779T69u1bmzBhQktXRSuYO3du3LKs3X777VUXpUN5/fXXawMGDKhNnz69NmTIkNrRRx9ddZE6lBNOOKE2ePDgqovRYQ0dOrQ2ZsyYZvOGDx9eGzlyZGVl6mjie3/KlCmN0++++26tT58+tbPOOqtx3muvvVZbffXVa5MnT66olB1n/y/NPffck5ebM2dOu5WrI1nWMXj22WdrG2+8ce2hhx6q9e/fv3bOOedUUr6OegwOPPDA2qhRo1Z63S2qQVm0aFH6+9//nquN61ZbbbU8fffdd7csGdEq5s+fn//u1atX1UXpUKIWa+jQoc0+C7Sf66+/Pu24445p//33z00dt99++3TZZZdVXawOY+edd05//vOf02OPPZan//GPf6S//OUvae+99666aB3W7Nmz0wsvvNDsOymaV0QzbOfn6s7P0QRm3XXXrbooHca7776bvv71r6fjjz8+DRw4sOridMj9/4c//CFtscUWufY2zs/xHfR+TfGWpUUB5eWXX85tjzfccMNm82M6vhhp//8I0fchmrpss802VRenw7jqqqtyFX70B6Ia//nPf3ITowEDBqSbb745HX744emoo45KV1xxRdVF6xBOPPHEdNBBB+Uq/GhmFwExvotGjhxZddE6rPo52Pm5DNGsLvqkjBgxIvXs2bPq4nQY0dy0S5cu+XxA+4vuHg0NDbl/7he/+MX0pz/9KQ0bNiwNHz48d1FoiS5tVkra5S7+Qw89lO9c0j6eeeaZdPTRR+f+Py1uT0mrhvOoQfnxj3+cp+MCOT4L0fZ+9OjRVRdvlffb3/42TZo0KV155ZX5LuUDDzyQA0q097b/6eiib+gBBxyQBy2IGym0j2jhc9555+UbiFFzRTXn5vCVr3wlHXPMMfnn7bbbLt111135/DxkyJC2qUFZf/31U+fOndOLL77YbH5M9+nTpyWrYiUdeeSR6YYbbkgzZsxIm2yySdXF6VBfgHGH4FOf+lS+SxOvuCsQHVPj56hhpO3FKEVbb711s3mf+MQnWjxKCCsmmk/Ua1Fi1KJoUhEnI7WK1amfg52fywgnc+bMyTey1J60nzvvvDOfn/v169d4fo7jcNxxx+WRZ2l7kRNiv7fG+blFAaVbt25phx12yG2Pm6almP7c5z7Xog2zYuKOTISTGKHi1ltvzcN80n5233339OCDD+Y7xvVX3MmPpi3xcwR42l40a1xyeO3oD9G/f//KytSRxIhF0f+wqfi/X797RvuLc0EEkabn5wULFuTRvJyf2zecxNDOt9xySx4CnfYTN0pixKim5+eo1Y0bKtEUmLYXOSGGFG6N83OLm3jFEMNRhR8XZTvttFMeXzqGHDvkkENauipWsFlXNKuYOnVqfhZKvW1xdIaMce9pW7HPl+zvE0N5xolIP6D2E3fro6N2NPGKC4J4FtOll16aX7S9GAN//Pjx+U5lNPG6//77089+9rM0ZsyYqou2Sou23U888USzjvFxERaDpMSxiGZ2p59+eu6bFYElhvaMC7R4XhZtu/+jVne//fbLzYuidUPUptfPz/H7uHCj7T8DS4bC6CMXwX3LLbesoLQd8xgcf/zx6cADD0y77rpr2m233dJNN92Upk2bloccbpEVGfrrggsuqPXr16/WrVu3POzwzJkzV3o4MZZPHLKlvSZOnFh10ToswwxXY9q0abVtttkmD6O61VZb1S699NKqi9RhLFiwIP+fj/NA9+7dax/72MdqP/zhD2tvv/121UVbpc2YMWOp3/+jR49uHGp47NixtQ033DB/Lnbffffao48+WnWxO8T+nz179jLPz/HvaJ/PwJIMM1zNMfjVr35V+/jHP57PD4MGDapdd911Ld5Op/ij9fMVAABAy7X4SfIAAABtRUABAACKIaAAAADFEFAAAIBiCCgAAEAxBBQAAKAYAgoAAFAMAQUAACiGgAIAABRDQAEAAIohoAAAAMUQUAAAgFSK/wf6+B9vMqhECAAAAABJRU5ErkJggg==", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAygAAADTCAYAAABqSTe2AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8ekN5oAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAXCUlEQVR4nO3dCbRd4/0/4DdkQgSJEqGJoSFFDY1qa0otStWqilkNqbSrKDVWpVViSmOomZraFdoS2hJTi0bF0JKiaKPUGDGVICSuKWmc//q+v//Jyo2E3OTeu1/3PM9ax7373J2z37O3c/b72e+wO9VqtVoCAAAowGJVFwAAAKBOQAEAAIohoAAAAMUQUAAAgGIIKAAAQDEEFAAAoBgCCgAAUAwBBQAAKIaAAgAAFENAAaB43/72t9Oqq65adTEAaAcCCgAf6Z133knHH398uuOOO1JHMmTIkLTnnnvm32u1WlpuueXSZZdd1myd119/PZ1++ulpiy22SJ/61KfSsssum770pS+lq6++uqJSA3R8AgoAHxtQTjjhhEoDyqWXXpoef/zxVn3N++67L4eN8Nhjj6U333xz9nLdvffem4455pjUq1ev9NOf/jSNHDkyLbnkkmmPPfZII0aMaNXyAPB/Ov//nwB0EG+//XZaaqmlUkfSpUuXj13nf//7X/rggw9S165dP3bdF154Ib300kuzA0kEkWWWWSattdZazdZbZ5110pNPPpn69+8/+7nvf//7aeutt06nnnpq+tGPftTh9jVA1bSgACyi6P7UqVOn9NRTT+WxEtENKCq7++23X259mNtvf/vbNGjQoLTEEkvkK/NxNf75559vts7dd9+ddt1119SvX7/UrVu39OlPfzodfvjh6d133222XmyvR48e6emnn05f//rX09JLL5322muv/LeorJ999tm5kt29e/e04oorpv333z+98cYbzV7jgQceSNtuu21afvnlc5lWW221NGzYsPy3Z599NndtCtGKEu8zHvGe5ye6ScU6d911V95e7969U8+ePdO+++77oW1ff/31afvtt099+/bN73ONNdZIJ510Upo1a9ZHjkGJcsU2fv7zn+f3GP8u/v2jjz4633K9//776bXXXsuP8ePH59AT+zWWo6zrrbde7tIVy7HvQuyLOcNJiO3uuOOO+fWeeeaZ+W4PgIWjBQWgley22265Qjtq1Kj04IMPpl/+8pdphRVWyFfa66KL0LHHHpvX/e53v5teffXVdN555+UxDg899FAON+H3v/99DjcHHnhgruBHd6RYL678x9/mbjmIgLHZZpvlCnt0QQoRDiIsRFA65JBD0qRJk9L555+ft/O3v/0tV9CnTJmSttlmmxxChg8fnrcflf9rr702v0Y8f+GFF+ZyxJiNnXbaKT8flfmPc/DBB+fXizAT3bPidSZPnpy7ikUlP0T5ImAdccQR+eftt9+ejjvuuDR9+vQ89uPjjB49Or333nvpe9/7Xg4oEfjmZ8yYMXlfzGnllVdutlwPY7GvPmpQ/ssvv5x/RqgDoJXVAFgkI0aMqMXX6bBhw5o9P2TIkFrv3r1nLz/77LO1xRdfvDZy5Mhm602cOLHWuXPnZs+/8847H9rOqFGjap06dapNnjx59nNDhw7N2x4+fHizde++++78/BVXXNHs+VtuuaXZ82PHjs3L999//3zf36uvvprXife5IEaPHp3XHzRoUG3GjBmznz/ttNPy89dff/1Hvs/999+/tuSSS9bee++9Zu+zf//+s5cnTZqUX6tnz561KVOmLFC5Xnrppdq4cePyI15r3333zb+PGTMmv9a55547++/vvvvufF/n9ddfr62wwgq1zTfffIG2C0DL6OIF0EoOOOCAZsubb7557jIUrQEhWiWi61C0ntS7GsWjT58+acCAAbnbUV10tZpzTEmst8kmm+TZpqIFZG7RwjGnaGWJbmZf/epXm20rupZFS0V9W/UWm5tuuinNnDmzVfdHtGrMOXYkyti5c+f0pz/9aZ7v86233spljP0WrUf/+c9/PnYbO++88+xWj4+z0kor5bEjG220Ue5SF13hYjnKFF3goryxHI9Ynpc4fvHvYkB9tGgB0Pp08QJoJTFeZE4xbW2IcRcxBiMGW0fAiDAyL3NW5p977rnc1emGG2740LiNadOmNVuOCvYqq6zS7LnYVqwXXczmJbp2hcGDB+dKfowvOeuss9JXvvKVPL7iW9/6Vu4ytSjmfp8RjCIkRBeyun//+995dqzo2lUPcvN7n/MSXeoWRISv+uvdeuutabHFFksDBw7MgSiWN9xwwxyQ4hHBbn6D8n/wgx+kW265Jf36179O66+//gJtG4CWEVAAWsniiy8+z+cjlNSvvsfYi5tvvnme60YFPsQA8Wj5mDp1ajr66KNzRTpminrxxRfzYPH6AO66CBJR4Z5TrBPh5IorrphnmeqtDlGeP/zhD2nChAnpxhtvzJX1GCB/xhln5OfqZWoL0QoRASnC24knnpgHukfLRYzfifc99/uclzlbYD5KjLnZcsstmz039+D3+j6J1qUIanOLEPeLX/winXLKKWmfffZZoO0C0HICCkA7iQp4hJW46r/mmmvOd72JEyemJ554Il1++eV55qu6cePGtWhbt912W9p0000XqBIf0+3GIwbxX3nllbkb01VXXZUH8tcHtLdUtOLMGQqamprSf//73zzbWIjB8tEFLrq+xSQBdTFAvbVFa0d9/0VXs3ivQ4cOza0qu+yySzrnnHPS2muvPXvduV1wwQV5sP9hhx2WwxMAbccYFIB2EjNgRctJXImvt6rUxXJU1kO9dWXOdeL3qEQvqBjnEi0xMWXv3GLWr2i9CNF9bO6ybLDBBvlnTKMb6rOC1f/NgrrkkkuajWuJWbxi29ttt9183+eMGTNyK0Vri+52MbYkZjqL7nPRrS2Wo2UqyvGd73xn9viTete8urhrfMyCFqHtzDPPbPWyAdCcFhSAdhKtGieffHL68Y9/nMdhxFiPuG9JtBiMHTs2D9L+4Q9/mLt0xbrxe3Trii5Q11xzzYfGonyU6DoV0wzHlMcPP/xwnko4xlVEq0YMoI+wEy0H0UoTgSCmEI5txhiMuGt7bLPe0hEtMNG6EBX1aPmJqXzXXXfd/PgoETa22mqrHJZimuHYTgSEHXbYIf89Bv1HGIiWjAgA0VLzm9/85kOBqTXFPV+iXLHtcM899+Qpk+d3s8WY3jlasWKq53gvc3eZi9dZffXV26y8AI1IQAFoR3Gvkajkx4D0aEkJcbPACBD1insEiRgPEpX2CBgxLiMCRNxXpCUDsy+66KI8a9fFF1+cfvKTn+TB9HFvj7333jt3/aoHmaiER3euV155JQ8Q33jjjXNFfM4B6HFPlxggHjeLjAr+iBEjPjagxD1X4nVisH+0pOy5557p3HPPnd1lLCr9MXvYkUcemQfKR1iJskUQiPu6tIUYixJBrD55QNxBvh5W5iVu/BjvN+5XU7955dz3YRFQAFpXp5hruJVfE4AGVr855P3335+n9AWAljAGBQAAKIaAAgAAFENAAQAAimEMCgAAUAwtKAAAQDEEFAAAoBgCCgAAUAwBBQAAKIaAAgAAFENAAQAAiiGgAAAAxRBQAACAYggoAABAMQQUAACgGAIKAABQDAEFAAAoRueqCwDAJ9vUqVNTU1NT1cVoaD169Ei9evWquhgArUJAAWCRwskJJ5yYZs6cUXVRGlqXLl3TiBHHCSlAhyCgALDQouUkwknvLXdOXZb9VNXFaUgz33w1vT7+mnwsBBSgIxBQAFhkEU66Lt+36mIA0AEYJA8AABRDQAEAAIohoAAAAMUQUAAAgGIIKAAAQDEEFAAAoBgCCgAAUAwBBQAAKIaAAgAAFENAAQAAiiGgAAAAxRBQAACAYggoAABAMQQUAACgGAIKAABQDAEFAAAohoACAAAUQ0ABAACKIaAAAADFEFAAAIBiCCgAAEAxBBQAAKAYAgoAAFAMAQUAACiGgAIAABSjc9UFAOCTb+abr1ZdhIZl3wMdjYACwELr0aNH6tKla3p9/DVVF6WhxTGIYwHQEXSq1Wq1qgsBwCfX1KlTU1NTU9XFaGgRTnr16lV1MQBahYACAAAUwyB5AACgGAIKAABQDAEFAAAohoACAAAUQ0ABAACKIaAAAADFEFAAAIBiCCgAAEAxBBQAAKAYAgoAAFAMAQUAACiGgAIAABRDQAEAAIohoAAAAMUQUAAAgGJ0rroA8Ek2derU1NTUVHUxoFI9evRIvXr1qroYAHQQAgosQjg58YQT0oyZM6suClSqa5cu6bgRI4QUAFqFgAILKVpOIpx8e8MvpT49elZdHKjEy03T02UPTcifBwEFgNYgoMAiinDSb1kVMwCA1mCQPAAAUAwBBQAAKIaAAgAAFENAAQAAiiGgAAAAxRBQAACAYggoAABAMQQUAACgGAIKAABQDAEFAAAohoACAAAUQ0ABAACKIaAAAADFEFAAAIBiCCgAAEAxBBQAAKAYAgoAAFAMAQUAACiGgAIAABRDQAEAAIohoAAAAMUQUAAAgGIIKAAAQDEEFAAAoBgCCgAAUIzOVRcAPulebppedRGgMv7/B6C1CSiwkHr06JG6dumSLntoQtVFgUrF5yA+DwDQGjrVarVaq7wSNKCpU6empqamqosBlYpw0qtXr6qLAUAHIaAAAADFMEgeAAAohoACAAAUQ0ABAACKIaAAAADFEFAAAIBiCCgAAEAxBBQAAKAYAgoAAFAMAQUAACiGgAIAABRDQAEAAIohoAAAAMUQUAAAgGIIKAAAQDEEFAAAoBgCCgAAUAwBBQAAKIaAAgAAFENAAQAAiiGgAAAAxRBQAACAYggoAABAMQQUAACgGAIKAABQDAEFAAAohoACAAAUQ0ABAACKIaAAAADFEFAAAIBiCCgAAEAxBBQAAKAYAgoAAFAMAQUAACiGgAIAABRDQAEAAIohoAAAAMUQUAAAgGIIKAAAQDEEFAAAoBgCCgAAUAwBBQAAKIaAAgAAFENAAQAAiiGgAAAAxRBQAACAYggoAABAMQQUAACgGAIKAABQDAEFAAAohoACAAAUQ0ABAACKIaAAAADFEFAAAIBiCCgAAEAxBBQAAOCTHVDef//9dPzxx+efVMMxqJ5jUD3HoHqOQfUcg+o5BtVzDDrW/u9Uq9VqLf1H06dPT8sss0yaNm1a6tmzZ6sUhJZxDKrnGFTPMaieY1A9x6B6jkH1HIOOtf918QIAAIohoAAAAMUQUAAAgE92QOnWrVsaMWJE/kk1HIPqOQbVcwyq5xhUzzGonmNQPcegY+3/hRokDwAA0BZ08QIAAIohoAAAAMUQUAAAgGIIKAAAwCc7oFxwwQVp1VVXTd27d09f/OIX03333df6JWOeRo0alb7whS+kpZdeOq2wwgppxx13TI8//njVxWpYp5xySurUqVM67LDDqi5Kw3nxxRfT3nvvnXr37p2WWGKJ9LnPfS498MADVRerIcyaNSsde+yxabXVVsv7fo011kgnnXRSMudK27rrrrvSN77xjdS3b9/8vXPdddc1+3vs/+OOOy6ttNJK+bhsvfXW6cknn6ysvI20/2fOnJmOPvro/D201FJL5XX23Xff9NJLL1Va5kb7DMzpgAMOyOucffbZ7VrGju6uBTgGjz32WNphhx3yneXj8xD11ueee65tA8rVV1+djjjiiDyV2IMPPpjWX3/9tO2226YpU6a09KVYCHfeeWc66KCD0oQJE9K4cePyl+I222yT3n777aqL1nDuv//+dPHFF6f11luv6qI0nDfeeCNtuummqUuXLunmm29Ojz76aDrjjDPScsstV3XRGsKpp56aLrzwwnT++efnE1Esn3baaem8886rumgdWnzPxzk3LhLOSxyDc889N1100UXp73//e64YxPn5vffea/eyNtr+f+edd3KdKIJ7/Lz22mvzxcOopNF+n4G6sWPH5npSVKJp32Pw9NNPp8022ywNHDgw3XHHHelf//pX/lxEo0aL1Fpo4403rh100EGzl2fNmlXr27dvbdSoUS19KVrBlClT4pJl7c4776y6KA3lrbfeqg0YMKA2bty42uDBg2uHHnpo1UVqKEcffXRts802q7oYDWv77bevDRs2rNlzO+20U22vvfaqrEyNJr73x44dO3v5gw8+qPXp06d2+umnz37uzTffrHXr1q02ZsyYikrZOPt/Xu6777683uTJk9utXI1kfsfghRdeqK288sq1Rx55pNa/f//aWWedVUn5GvUY7L777rW99957kV+7RS0oM2bMSP/4xz9ys3HdYostlpfvvffeliUjWsW0adPyz169elVdlIYSrVjbb799s88C7eeGG25IG220Udp1111zV8cNN9wwXXrppVUXq2Fssskm6S9/+Ut64okn8vI///nP9Ne//jVtt912VRetYU2aNCm9/PLLzb6TontFdMN2fq7u/BxdYJZddtmqi9IwPvjgg7TPPvuko446Kq2zzjpVF6ch9/8f//jHtOaaa+bW2zg/x3fQR3XFm58WBZTXXnst9z1eccUVmz0fy/HFSPv/jxBjH6Kry7rrrlt1cRrGVVddlZvwYzwQ1XjmmWdyF6MBAwakW2+9NR144IHpkEMOSZdffnnVRWsIw4cPT3vssUduwo9udhEQ47tor732qrpoDat+DnZ+LkN0q4sxKXvuuWfq2bNn1cVpGNHdtHPnzvl8QPuL4R5NTU15fO7Xvva19Oc//zkNGTIk7bTTTnmIQkt0brNS0i5X8R955JF85ZL28fzzz6dDDz00j/9pcX9KWjWcRwvKz372s7wcFeT4LETf+6FDh1ZdvA7vd7/7XbriiivSlVdema9SPvzwwzmgRH9v+59GF2NDd9tttzxpQVxIoX1ED59zzjknX0CMliuqOTeHb37zm+nwww/Pv2+wwQbpnnvuyefnwYMHt00LyvLLL58WX3zx9MorrzR7Ppb79OnTkpdiER188MHppptuSuPHj0+rrLJK1cVpqC/AuELw+c9/Pl+liUdcFYiBqfF7tDDS9mKWorXXXrvZc5/97GdbPEsICye6T9RbUWLWouhSEScjrYrVqZ+DnZ/LCCeTJ0/OF7K0nrSfu+++O5+f+/XrN/v8HMfhyCOPzDPP0vYiJ8R+b43zc4sCSteuXdOgQYNy3+M501Isf/nLX27Rhlk4cUUmwknMUHH77bfnaT5pP1tttVWaOHFivmJcf8SV/OjaEr9HgKftRbfGuafXjvEQ/fv3r6xMjSRmLIrxh3OK//frV89of3EuiCAy5/l5+vTpeTYv5+f2DScxtfNtt92Wp0Cn/cSFkpgxas7zc7TqxgWV6ApM24ucEFMKt8b5ucVdvGKK4WjCj0rZxhtvnOeXjinH9ttvv5a+FAvZrSu6VVx//fX5Xij1vsUxGDLmvadtxT6fe7xPTOUZJyLjgNpPXK2PgdrRxSsqBHEvpksuuSQ/aHsxB/7IkSPzlcro4vXQQw+lM888Mw0bNqzqonVo0bf7qaeeajYwPiphMUlKHIvoZnfyySfnsVkRWGJqz6igxf2yaNv9H626u+yyS+5eFL0bojW9fn6Ov0fFjbb/DMwdCmOMXAT3tdZaq4LSNuYxOOqoo9Luu++etthii7TlllumW265Jd144415yuEWWZipv84777xav379al27ds3TDk+YMGGRpxNjwcQhm9dj9OjRVRetYZlmuBo33nhjbd11183TqA4cOLB2ySWXVF2khjF9+vT8/3ycB7p3715bffXVa8ccc0zt/fffr7poHdr48ePn+f0/dOjQ2VMNH3vssbUVV1wxfy622mqr2uOPP151sRti/0+aNGm+5+f4d7TPZ2Buphmu5hj86le/qn3mM5/J54f111+/dt1117V4O53iP62frwAAAFquxXeSBwAAaCsCCgAAUAwBBQAAKIaAAgAAFENAAQAAiiGgAAAAxRBQAACAYggoAABAMQQUAACgGAIKAABQDAEFAAAohoACAACkUvw/PStWp8dTGfAAAAAASUVORK5CYII=", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAygAAADTCAYAAABqSTe2AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8ekN5oAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAXCElEQVR4nO3dCbRVVf0H8I0CTogKJogGmqmoOJuV8pdcmGaunHIiEJJaqUvT1EwbECfCIXMsp1rqKqdKwaHUMFExJTG1NM0pxClFRcXnBOn9r99e67J4DMKT997Zj/v5rHV579x33j37nsO7Z3/PHk6nWq1WSwAAAAVYpuoCAAAA1AkoAABAMQQUAACgGAIKAABQDAEFAAAohoACAAAUQ0ABAACKIaAAAADFEFAAAIBiCCgAFO+b3/xmWmeddaouBgDtQEAB4GO9++676cQTT0x33nlnWprstddeaciQIfn7Wq2WVltttXT55ZfPt95RRx2Vttpqq9SjR4+04oorpo022ijvj6ampgpKDbD061x1AQAoP6CcdNJJ+fsvfelLlZTh0ksvTR999FGrvub999+ffvCDH+TvH3/88fTmm2+mL3zhC/OtN2XKlPR///d/6aCDDkrLL798euihh9Jpp52Wbr/99nT33XenZZZxrQ+gNQkoAEuZd955J6200kppadKlS5dFrvO///0vh5iuXbsuct0XXnghvfTSS3MCyX333ZdWWWWVtOGGG8637j333DPfc+utt176/ve/n0POgkINAJ+cyz4ASyi6+3Tq1Ck9/fTTeazEqquumiu7ccU9Wh/m9dvf/jZtvfXWaYUVVsjdhg444ID0/PPPN1tn0qRJad999019+/ZNyy23XPr0pz+duxq99957zdaL7XXr1i0988wz6atf/WpaeeWV09ChQ/PPorJ+zjnnpE022SRf+e/Vq1c6+OCD0xtvvNHsNR544IG0yy67pNVXXz2Xad11100jR47MP3v22WfTpz71qfx9tKLE+4xHvOeFiW5SsU60LsT2evbsmbp3756GDx8+37ZvuOGGtNtuu6U+ffrk9xkV/1NOOSV9+OGHHzsGJcoV2/jZz36W32P8Xvz+Y489ttByffDBB+m1117Lj4kTJ+bQE/s1lqOsm222WXr99dfz8qJaa+pliVYXAFqXFhSAVrLffvvlyv3YsWPTgw8+mH71q1+lNdZYI51++ulz1hkzZkwaNWpUXvfb3/52evXVV9P555+fdthhh9x1KMJN+P3vf5/DzaGHHpor+HGlPtaLK//xs3lbDiJgDBw4MFfYY5xEiHAQYSGC0hFHHJGmTp2aLrjggrydv/71r7mCPn369LTzzjvnEHL88cfn7Ufl//rrr8+vEc9feOGFuRwxZmPvvffOz0dlflEOP/zw/HoRZp544on8OtOmTctjWSJchChfBKyjjz46f73jjjvSCSeckGbOnJnOPPPMRW7jsssuS++//376zne+kwNKBL6Fufrqq/O+mNtaa63VbLkexmJfzR2IYh9HGJk1a1Z69NFH009+8pMcBrfddttFlhGAFqoBsERGjx5di4/TkSNHNnt+r732qvXs2XPO8rPPPltbdtlla2PGjGm23iOPPFLr3Llzs+fffffd+bYzduzYWqdOnWrTpk2b89yIESPyto8//vhm606aNCk/f+WVVzZ7/tZbb232/Lhx4/LylClTFvr+Xn311bxOvM/Fcdlll+X1t95669qsWbPmPH/GGWfk52+44YaPfZ8HH3xwbcUVV6y9//77zd5nv3795ixPnTo1v1b37t1r06dPX6xyvfTSS7UJEybkR7zW8OHD8/dXX311fq3zzjtvzs/fe++9Zr9733335XXqjw033LA2ceLExdouAC2jixdAKznkkEOaLcfA6ugyFK0BIVoloutQtJ7UuxrFo3fv3mn99dfP3Y7qoqvV3GNKYr3tttsuzzYVLSDzihaOuUUrS3Qz+/KXv9xsW9G1LFoq6tuqt9jcfPPNafbs2a26P6JVY+6xI1HGzp07pz/96U8LfJ9vv/12LmPst2g9+ve//73IbXz961+f0+qxKGuuuWbaaaed0jbbbJO71EVXuFiOMkUXuChvLMcjlue28cYbpwkTJqTx48fngfUxxscsXgBtQxcvgFYS40XmFtPWhhh3EWMwnnrqqRwwIowsyNyV+eeeey53dbrxxhvnG7fx1ltvNVuOCvbaa6/d7LnYVqwXXcwWJLp2hUGDBuVKfowvOfvss/MsXXvuuWf6xje+kbtMLYl532cEowgJ0YWs7l//+lfuLhVdu+pBbmHvc0GiS93iiPBVf73bbrstz7zVv3//HIhiecstt8wBKR4R7OYdlB/HL4JL2GOPPdJVV12Vv0ZXvs0333yxygDA4hFQAFrJ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YggoAABAMQQUAACgGAIKAABQDAEFAAAohoACAAAUQ0ABAACKIaAAAADFEFAAAIBiCCgAAEAxBBQAAKAYAgoAAFAMAQUAACiGgAIAABRDQAEAAIohoAAAAMUQUAAAgGIIKAAAQDEEFAAAoBgCCgAAUAwBBQAAKIaAAgAAFENAAQAAiiGgAAAAxRBQAACAYggoAABAMQQUAACgGAIKAABQDAEFAAAohoACAAAUQ0ABAACKIaAAAADFEFAAAIBiCCgAAEAxBBQAAKAYAgoAAFAMAQUAACiGgAIAABRDQAEAAIohoAAAAMUQUAAAgGIIKAAAQDEEFAAAoBgCCgAA0LEDygcffJBOPPHE/JVqOAbVcwyq5xhUzzGonmNQPcegeo7B0rX/O9VqtVpLf2nmzJlplVVWSW+99Vbq3r17qxSElnEMqucYVM8xqJ5jUD3HoHqOQfUcg6Vr/+viBQAAFENAAQAAiiGgAAAAHTugLLfccmn06NH5K9VwDKrnGFTPMaieY1A9x6B6jkH1HIOla/9/okHyAAAAbUEXLwAAoBgCCgAAUAwBBQAAKIaAAgAAdOyA8otf/CKts846afnll0+f//zn0/3339/6JWOBxo4dmz73uc+llVdeOa2xxhppzz33TE888UTVxWpYp512WurUqVP63ve+V3VRGs6LL76Yhg0blnr27JlWWGGFtOmmm6YHHnig6mI1hA8//DCNGjUqrbvuunnfr7feeumUU05J5lxpW3fffXf62te+lvr06ZM/d8aPH9/s57H/TzjhhLTmmmvm47LTTjulp556qrLyNtL+nz17djruuOPy59BKK62U1xk+fHh66aWXKi1zo/0NzO2QQw7J65xzzjntWsal3d2LcQwef/zxtPvuu+c7y8ffQ9Rbn3vuubYNKNdee206+uij81RiDz74YNp8883TLrvskqZPn97Sl+ITuOuuu9Jhhx2WJk+enCZMmJA/FHfeeef0zjvvVF20hjNlypR08cUXp80226zqojScN954I22//fapS5cu6ZZbbkmPPfZYOuuss9Jqq61WddEawumnn54uvPDCdMEFF+QTUSyfccYZ6fzzz6+6aEu1+JyPc25cJFyQOAbnnXdeuuiii9Lf/va3XDGI8/P777/f7mVttP3/7rvv5jpRBPf4ev311+eLh1FJo/3+BurGjRuX60lRiaZ9j8EzzzyTBg4cmPr375/uvPPO9M9//jP/XUSjRovUWmjbbbetHXbYYXOWP/zww1qfPn1qY8eObelL0QqmT58elyxrd911V9VFaShvv/12bf31169NmDChNmjQoNqRRx5ZdZEaynHHHVcbOHBg1cVoWLvttltt5MiRzZ7be++9a0OHDq2sTI0mPvfHjRs3Z/mjjz6q9e7du3bmmWfOee7NN9+sLbfccrWrr766olI2zv5fkPvvvz+vN23atHYrVyNZ2DF44YUXamuttVbt0UcfrfXr16929tlnV1K+Rj0G+++/f23YsGFL/NotakGZNWtW+vvf/56bjeuWWWaZvHzfffe1LBnRKt566638tUePHlUXpaFEK9Zuu+3W7G+B9nPjjTembbbZJu277765q+OWW26ZLr300qqL1TC222679Je//CU9+eSTefkf//hHuueee9Kuu+5addEa1tSpU9PLL7/c7DMpuldEN2zn5+rOz9EFZtVVV626KA3jo48+SgceeGA69thj0yabbFJ1cRpy///xj39MG2ywQW69jfNzfAZ9XFe8hWlRQHnttddy3+NevXo1ez6W44OR9v+PEGMfoqvLgAEDqi5Ow7jmmmtyE36MB6Ia//nPf3IXo/XXXz/ddttt6dBDD01HHHFEuuKKK6ouWkM4/vjj0wEHHJCb8KObXQTE+CwaOnRo1UVrWPVzsPNzGaJbXYxJGTJkSOrevXvVxWkY0d20c+fO+XxA+4vhHk1NTXl87le+8pX05z//Oe21115p7733zkMUWqJzm5WSdrmK/+ijj+Yrl7SP559/Ph155JF5/E+L+1PSquE8WlB++tOf5uWoIMffQvS9HzFiRNXFW+r97ne/S1deeWW66qqr8lXKhx9+OAeU6O9t/9PoYmzofvvtlyctiAsptI/o4XPuuefmC4jRckU15+awxx57pKOOOip/v8UWW6R77703n58HDRrUNi0oq6++elp22WXTK6+80uz5WO7du3dLXooldPjhh6ebb745TZw4Ma299tpVF6ehPgDjCsFWW22Vr9LEI64KxMDU+D5aGGl7MUvRxhtv3Oy5jTbaqMWzhPDJRPeJeitKzFoUXSriZKRVsTr1c7DzcxnhZNq0aflCltaT9jNp0qR8fu7bt++c83Mch2OOOSbPPEvbi5wQ+701zs8tCihdu3ZNW2+9de57PHdaiuUvfvGLLdown0xckYlwEjNU3HHHHXmaT9rP4MGD0yOPPJKvGNcfcSU/urbE9xHgaXvRrXHe6bVjPES/fv0qK1MjiRmLYvzh3OL/fv3qGe0vzgURROY+P8+cOTPP5uX83L7hJKZ2vv322/MU6LSfuFASM0bNfX6OVt24oBJdgWl7kRNiSuHWOD+3uItXTDEcTfhRKdt2223z/NIx5dhBBx3U0pfiE3brim4VN9xwQ74XSr1vcQyGjHnvaVuxz+cd7xNTecaJyDig9hNX62OgdnTxigpB3IvpkksuyQ/aXsyBP2bMmHylMrp4PfTQQ+nnP/95GjlyZNVFW6pF3+6nn3662cD4qITFJClxLKKb3amnnprHZkVgiak9o4IW98uibfd/tOrus88+uXtR9G6I1vT6+Tl+HhU32v5vYN5QGGPkIrhvuOGGFZS2MY/Bsccem/bff/+0ww47pB133DHdeuut6aabbspTDrfIJ5n66/zzz6/17du31rVr1zzt8OTJk5d4OjEWTxyyBT0uu+yyqovWsEwzXI2bbrqpNmDAgDyNav/+/WuXXHJJ1UVqGDNnzsz/5+M8sPzyy9c+85nP1H784x/XPvjgg6qLtlSbOHHiAj//R4wYMWeq4VGjRtV69eqV/y4GDx5ce+KJJ6oudkPs/6lTpy70/By/R/v8DczLNMPVHINf//rXtc9+9rP5/LD55pvXxo8f3+LtdIp/Wj9fAQAAtFyL7yQPAADQVgQUAACgGAIKAABQDAEFAAAohoACAAAUQ0ABAACKIaAAAADFEFAAAIBiCCgAAEAxBBQAAKAYAgoAAFAMAQUAAEil+H91/GLN46PRBQAAAABJRU5ErkJggg==", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "visualize_intervals(nearest_intervals, \"nearest pair\")" ] diff --git a/polars_bio/quality_stats.py b/polars_bio/quality_stats.py index 6cf85c46..c18ec841 100644 --- a/polars_bio/quality_stats.py +++ b/polars_bio/quality_stats.py @@ -4,17 +4,20 @@ import pandas as pd import pyarrow as pa from .context import ctx -from polars_bio.polars_bio import my_scan, my_frame +from polars_bio.polars_bio import ( + base_sequance_quality_scan, + base_sequance_quality_frame, +) def base_sequence_quality(df: Union[str, pl.DataFrame, pl.LazyFrame, pd.DataFrame]): if isinstance(df, str): - supported_exts = set([".parquet", ".csv", ".bed", ".vcf"]) + supported_exts = set([".parquet", ".csv", ".bed", ".vcf", ".fastq"]) ext = set(Path(df).suffixes) assert ( len(supported_exts.intersection(ext)) > 0 or len(ext) == 0 - ), "Dataframe1 must be a Parquet, a BED or CSV or VCF file" - return my_scan(ctx, df) + ), "Dataframe1 must be a Parquet, CSV, BED, VCF, or FASTQ file." + return base_sequance_quality_scan(ctx, df) else: if isinstance(df, pl.DataFrame): df = df.to_arrow().to_reader() @@ -22,4 +25,4 @@ def base_sequence_quality(df: Union[str, pl.DataFrame, pl.LazyFrame, pd.DataFram df = pa.Table.from_pandas(df) elif isinstance(df, pl.LazyFrame): df = df.collect().to_arrow().to_reader() - return my_frame(ctx, df) + return base_sequance_quality_frame(ctx, df) diff --git a/src/context.rs b/src/context.rs index 5f47f30e..afc02d4e 100644 --- a/src/context.rs +++ b/src/context.rs @@ -1,6 +1,9 @@ use std::collections::HashMap; +use std::sync::Arc; +use datafusion::arrow::datatypes::DataType; use datafusion::config::ConfigOptions; +use datafusion::logical_expr::{create_udaf, AggregateUDF, Volatility}; use datafusion::prelude::SessionConfig; use exon::config::ExonConfigExtension; use exon::ExonSession; @@ -8,6 +11,8 @@ use log::debug; use pyo3::{pyclass, pymethods, PyResult}; use sequila_core::session_context::SequilaConfig; +use crate::udaf::{base_quality_result_type, QualityScoresStats}; + #[pyclass(name = "BioSessionContext")] // #[derive(Clone)] pub struct PyBioSessionContext { @@ -25,7 +30,7 @@ impl PyBioSessionContext { pub fn new(seed: String, catalog_dir: String) -> PyResult { let ctx = create_context().unwrap(); let session_config: HashMap = HashMap::new(); - + ctx.session.register_udaf(make_base_sequence_quality_udaf()); Ok(PyBioSessionContext { ctx, session_config, @@ -87,3 +92,14 @@ fn create_context() -> exon::Result { ExonSession::with_config_exon(config) } + +pub fn make_base_sequence_quality_udaf() -> AggregateUDF { + create_udaf( + "base_sequence_quality", // nazwa funkcji w SQL + vec![DataType::Utf8], // typ wejściowy + Arc::new(base_quality_result_type()), + Volatility::Immutable, + Arc::new(|_| Ok(Box::new(QualityScoresStats::new()))), + Arc::new(vec![]), + ) +} diff --git a/src/lib.rs b/src/lib.rs index 629a9205..d92eb0c4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,12 +4,14 @@ mod option; mod query; mod scan; mod streaming; +mod udaf; mod udtf; mod utils; use std::string::ToString; use std::sync::{Arc, Mutex}; +use arrow::array::*; use datafusion::arrow::ffi_stream::ArrowArrayStreamReader; use datafusion::arrow::pyarrow::PyArrowType; use datafusion::datasource::MemTable; @@ -21,6 +23,8 @@ use polars_lazy::prelude::{LazyFrame, ScanArgsAnonymous}; use polars_python::error::PyPolarsErr; use polars_python::lazyframe::PyLazyFrame; use pyo3::prelude::*; +use pyo3::types::{PyDict, PyList}; +use scan::deregister_table; use tokio::runtime::Runtime; use crate::context::PyBioSessionContext; @@ -32,11 +36,9 @@ use crate::scan::{maybe_register_table, register_frame, register_table}; use crate::streaming::RangeOperationScan; use crate::utils::convert_arrow_rb_schema_to_polars_df_schema; -use pyo3::types::PyString; -use serde_json::Value; - const LEFT_TABLE: &str = "s1"; const RIGHT_TABLE: &str = "s2"; +const DEFAULT_TABLE_NAME: &str = "unnamed_table"; const DEFAULT_COLUMN_NAMES: [&str; 3] = ["contig", "start", "end"]; #[pyfunction] @@ -407,34 +409,128 @@ fn py_from_polars( }) } -#[pyfunction] -#[pyo3(signature = (py_ctx, path))] -fn my_scan(py: Python<'_>, py_ctx: &PyBioSessionContext, path: String) -> PyResult { - let rt = Runtime::new()?; +fn struct_array_to_pydict(py: Python<'_>, struct_array: &StructArray) -> PyResult { + let warn_array = struct_array + .column_by_name("base_quality_warn") + .and_then(|a| a.as_any().downcast_ref::()) + .unwrap(); + + let base_per_pos_array = struct_array + .column_by_name("base_per_pos_data") + .and_then(|a| a.as_any().downcast_ref::()) + .unwrap(); + + let struct_array = base_per_pos_array + .values() + .as_any() + .downcast_ref::() + .unwrap(); + + let mut base_per_pos_data = Vec::new(); + for i in 0..base_per_pos_array.value_length(0) { + let mut row = std::collections::HashMap::new(); + + let pos = struct_array + .column_by_name("pos") + .and_then(|a| a.as_any().downcast_ref::()) + .unwrap() + .value(i as usize); + let average = struct_array + .column_by_name("average") + .and_then(|a| a.as_any().downcast_ref::()) + .unwrap() + .value(i as usize); + let median = struct_array + .column_by_name("median") + .and_then(|a| a.as_any().downcast_ref::()) + .unwrap() + .value(i as usize); + let q1 = struct_array + .column_by_name("q1") + .and_then(|a| a.as_any().downcast_ref::()) + .unwrap() + .value(i as usize); + let q3 = struct_array + .column_by_name("q3") + .and_then(|a| a.as_any().downcast_ref::()) + .unwrap() + .value(i as usize); + let lower = struct_array + .column_by_name("lower") + .and_then(|a| a.as_any().downcast_ref::()) + .unwrap() + .value(i as usize); + let upper = struct_array + .column_by_name("upper") + .and_then(|a| a.as_any().downcast_ref::()) + .unwrap() + .value(i as usize); + + row.insert("pos", pos.into_py(py)); + row.insert("average", average.into_py(py)); + row.insert("median", median.into_py(py)); + row.insert("q1", q1.into_py(py)); + row.insert("q3", q3.into_py(py)); + row.insert("lower", lower.into_py(py)); + row.insert("upper", upper.into_py(py)); + + base_per_pos_data.push(row.into_py(py).to_object(py)); + } + + let result_dict = PyDict::new_bound(py); + result_dict.set_item("base_quality_warn", warn_array.value(0))?; + result_dict.set_item( + "base_per_pos_data", + PyList::new_bound(py, base_per_pos_data), + )?; + + Ok(result_dict.to_object(py)) +} + +fn handle_base_sequence_quality<'a, F>( + py: Python<'a>, + py_ctx: &PyBioSessionContext, + table_name: &str, + register_fn: F, +) -> PyResult +where + F: FnOnce(&PyBioSessionContext, &str, &Runtime), +{ let ctx = &py_ctx.ctx; - let _table = maybe_register_table(path, &LEFT_TABLE.to_string(), None, ctx, &rt); - let result: Value = rt.block_on(do_base_sequence_quality(ctx, LEFT_TABLE.to_string())); + let rt = Runtime::new().unwrap(); + register_fn(py_ctx, table_name, &rt); + let result_opt = rt.block_on(do_base_sequence_quality(ctx, &table_name.to_string())); + deregister_table(ctx, table_name); + if let Some(struct_array) = result_opt { + struct_array_to_pydict(py, &struct_array) + } else { + Ok(py.None()) + } +} - let json_str = serde_json::to_string(&result).unwrap(); - let py_str = PyString::new_bound(py, &json_str); - Ok(py_str.into_py(py)) +#[pyfunction] +#[pyo3(signature = (py_ctx, path))] +fn base_sequance_quality_scan( + py: Python<'_>, + py_ctx: &PyBioSessionContext, + path: String, +) -> PyResult { + handle_base_sequence_quality(py, py_ctx, DEFAULT_TABLE_NAME, |py_ctx, table_name, rt| { + let ctx = &py_ctx.ctx; + maybe_register_table(path, &table_name.to_string(), None, ctx, rt); + }) } #[pyfunction] #[pyo3(signature = (py_ctx, df))] -fn my_frame( +fn base_sequance_quality_frame( py: Python<'_>, py_ctx: &PyBioSessionContext, df: PyArrowType, ) -> PyResult { - let rt = Runtime::new().unwrap(); - let ctx = &py_ctx.ctx; - register_frame(py_ctx, df, LEFT_TABLE.to_string()); - let result: Value = rt.block_on(do_base_sequence_quality(ctx, LEFT_TABLE.to_string())); - - let json_str = serde_json::to_string(&result).unwrap(); - let py_str = PyString::new_bound(py, &json_str); - Ok(py_str.into_py(py)) + handle_base_sequence_quality(py, py_ctx, DEFAULT_TABLE_NAME, |py_ctx, table_name, _rt| { + register_frame(py_ctx, df, table_name.to_string()); + }) } #[pymodule] @@ -451,9 +547,8 @@ fn polars_bio(_py: Python, m: &Bound) -> PyResult<()> { m.add_function(wrap_pyfunction!(py_describe_vcf, m)?)?; m.add_function(wrap_pyfunction!(py_register_view, m)?)?; m.add_function(wrap_pyfunction!(py_from_polars, m)?)?; - m.add_function(wrap_pyfunction!(my_frame, m)?)?; - m.add_function(wrap_pyfunction!(my_scan, m)?)?; - // m.add_function(wrap_pyfunction!(unary_operation_scan, m)?)?; + m.add_function(wrap_pyfunction!(base_sequance_quality_frame, m)?)?; + m.add_function(wrap_pyfunction!(base_sequance_quality_scan, m)?)?; m.add_class::()?; m.add_class::()?; m.add_class::()?; diff --git a/src/operation.rs b/src/operation.rs index 9e5c8cdf..808c55a9 100644 --- a/src/operation.rs +++ b/src/operation.rs @@ -1,10 +1,10 @@ use std::sync::Arc; +use arrow_array::{Array, StructArray}; use datafusion::catalog_common::TableReference; use exon::ExonSession; use log::{debug, info}; use sequila_core::session_context::{Algorithm, SequilaConfig}; -use serde_json::json; use tokio::runtime::Runtime; use crate::context::set_option_internal; @@ -194,134 +194,33 @@ async fn do_count_overlaps_coverage_naive( pub(crate) async fn do_base_sequence_quality( ctx: &ExonSession, - table: String, -) -> serde_json::Value { - let query = format!("SELECT quality_scores FROM {}", table); + table: &String, +) -> Option { + let query = format!( + "SELECT base_sequence_quality(quality_scores) as result FROM {}", + table + ); debug!("Query: {}", query); let batches = ctx.sql(&query).await.unwrap().collect().await.unwrap(); - let mut base_quality_count: std::collections::HashMap> = - std::collections::HashMap::new(); - - use std::any::type_name_of_val; - - for batch in batches { + if let Some(batch) = batches.get(0) { let col_idx = batch .schema() .fields() .iter() - .position(|f| f.name() == "quality_scores") - .expect("Column 'quality_scores' not found"); + .position(|f| f.name() == "result") + .expect("Column 'result' not found"); let array = batch.column(col_idx); - for i in 0..array.len() { - if array.is_null(i) { - continue; - } - let quality_str = if let Some(string_array) = - array.as_any().downcast_ref::() - { - string_array.value(i) - } else if let Some(large_string_array) = array - .as_any() - .downcast_ref::() - { - large_string_array.value(i) - } else if let Some(generic_string_array_i64) = array - .as_any() - .downcast_ref::>( - ) { - generic_string_array_i64.value(i) - } else if let Some(generic_string_array_i32) = array - .as_any() - .downcast_ref::>( - ) { - generic_string_array_i32.value(i) - } else if let Some(string_view_array) = array - .as_any() - .downcast_ref::() - { - string_view_array.value(i) - } else { - panic!( - "Column 'quality_scores' has unsupported array type: {:?} (concrete Rust type: {})", - array.data_type(), - type_name_of_val(array) - ); - }; - - for (pos, qchar) in quality_str.chars().enumerate() { - let qscore = qchar as usize - 33; - let rec = base_quality_count - .entry(pos) - .or_insert_with(|| vec![0_usize; 94]); - if qscore < 94 { - rec[qscore] += 1; - } - } - } - } - fn quartiles(counts: &[usize]) -> Vec { - let mut expanded = Vec::new(); - for (q, &c) in counts.iter().enumerate() { - for _ in 0..c { - expanded.push(q as f32 + 33.0); + if array.len() > 0 && !array.is_null(0) { + if let Some(struct_array) = array.as_any().downcast_ref::() { + return Some(struct_array.clone()); + } else { + panic!("Unsupported result type: {:?}", array.data_type()); } } - if expanded.is_empty() { - return vec![0.0; 5]; - } - expanded.sort_by(|a, b| a.partial_cmp(b).unwrap()); - let n = expanded.len(); - let q = |p: f32| { - let idx = (p * (n - 1) as f32).round() as usize; - expanded[idx] - }; - vec![ - q(0.0), // min - q(0.25), // Q1 - q(0.5), // median - q(0.75), // Q3 - q(1.0), // max - ] - } - - let mut base_quality_warn = "pass"; - let mut base_per_pos_data = Vec::new(); - for (position, qualities) in base_quality_count.iter() { - let (sum, len) = qualities - .iter() - .enumerate() - .fold((0_usize, 0_usize), |(s, l), (q, c)| { - (s + (q + 33) * c, l + c) - }); - let avg = if len > 0 { - sum as f64 / len as f64 - } else { - 0.0 - }; - let values = quartiles(qualities); - let median = values[2]; - if median <= 20.0 { - base_quality_warn = "fail"; - } else if median <= 25.0 && base_quality_warn != "fail" { - base_quality_warn = "warn"; - } - base_per_pos_data.push(json!({ - "pos": position, - "average": avg, - "upper": values[4], - "lower": values[0], - "q1": values[1], - "q3": values[3], - "median": values[2], - })); } - - json!({ - "base_quality_warn": base_quality_warn, - "base_per_pos_data": base_per_pos_data - }) + None } async fn get_non_join_columns( diff --git a/src/scan.rs b/src/scan.rs index 4d5b288e..e7795a99 100644 --- a/src/scan.rs +++ b/src/scan.rs @@ -61,6 +61,8 @@ pub(crate) fn get_input_format(path: &str) -> InputFormat { InputFormat::Bed } else if path.ends_with(".vcf") || path.ends_with(".vcf.gz") || path.ends_with(".vcf.bgz") { InputFormat::Vcf + } else if path.ends_with(".fastq") { + InputFormat::Fastq } else { panic!("Unsupported format") } @@ -154,3 +156,7 @@ pub(crate) fn maybe_register_table( } .to_string() } + +pub(crate) fn deregister_table(ctx: &ExonSession, table_name: &str) { + let _ = ctx.session.deregister_table(table_name); +} diff --git a/src/udaf.rs b/src/udaf.rs new file mode 100644 index 00000000..a26ac237 --- /dev/null +++ b/src/udaf.rs @@ -0,0 +1,210 @@ +use std::collections::HashMap; +use std::sync::Arc; + +use arrow::buffer::OffsetBuffer; +use arrow_array::{Array, ArrayRef, Float64Array, Int64Array, ListArray, StringArray, StructArray}; +use arrow_schema::{DataType, Field, Fields}; +use datafusion::error::{DataFusionError, Result}; +use datafusion::physical_plan::Accumulator; +use datafusion::scalar::ScalarValue; + +#[derive(Debug)] +pub(crate) struct QualityScoresStats { + values_per_pos: HashMap>, // key: position, value: decoded quality scores +} + +impl QualityScoresStats { + pub fn new() -> Self { + Self { + values_per_pos: HashMap::new(), + } + } + + fn decode_score(c: char) -> Option { + let ascii = c as u8; + if ascii >= 33 { + Some(ascii - 33) + } else { + None + } + } + + fn calc_stats(values: &mut Vec) -> (f64, f64, f64, f64, f64, f64) { + values.sort_unstable(); + let n = values.len(); + let average = values.iter().map(|&v| v as f64).sum::() / n as f64; + let median = if n % 2 == 0 { + (values[n / 2 - 1] as f64 + values[n / 2] as f64) / 2.0 + } else { + values[n / 2] as f64 + }; + let q1 = values[n / 4] as f64; + let q3 = values[(3 * n) / 4] as f64; + let iqr = q3 - q1; + let lower = q1 - 1.5 * iqr; + let upper = q3 + 1.5 * iqr; + (average, median, q1, q3, lower, upper) + } +} + +impl Accumulator for QualityScoresStats { + fn state(&mut self) -> Result> { + Ok(vec![]) + } + + fn evaluate(&mut self) -> Result { + #[derive(Default)] + struct StatColumns { + pos: Vec, + avg: Vec, + median: Vec, + q1: Vec, + q3: Vec, + lower: Vec, + upper: Vec, + } + + let mut cols = StatColumns::default(); + let mut base_quality_warn = "pass"; + + for (&pos, values) in &mut self.values_per_pos { + if values.is_empty() { + continue; + } + + let (avg, median, q1, q3, lower, upper) = Self::calc_stats(values); + + cols.pos.push(pos as i64); + cols.avg.push(avg); + cols.median.push(median); + cols.q1.push(q1); + cols.q3.push(q3); + cols.lower.push(lower); + cols.upper.push(upper); + + base_quality_warn = match (q1 <= 20.0, q1 <= 25.0, base_quality_warn) { + (true, _, _) => "fail", + (false, true, "pass") => "warn", + _ => base_quality_warn, + }; + } + + let result_type = base_quality_result_type(); + + let fields = match result_type { + DataType::Struct(ref fields) => fields.clone(), + _ => { + return Err(DataFusionError::Execution( + "Unexpected result type".to_string(), + )) + }, + }; + + let base_quality_warn_field = fields[0].clone(); + let base_per_pos_data_field = fields[1].clone(); + + let base_per_pos_data_element_field = match base_per_pos_data_field.data_type() { + DataType::List(inner_field) => inner_field.as_ref().clone(), + _ => return Err(DataFusionError::Execution("Expected List type".to_string())), + }; + + let struct_fields = match base_per_pos_data_element_field.data_type() { + DataType::Struct(inner_fields) => inner_fields.clone(), + _ => { + return Err(DataFusionError::Execution( + "Expected Struct type inside list".to_string(), + )) + }, + }; + + let to_array = |vec: Vec| Arc::new(Float64Array::from(vec)) as ArrayRef; + + let struct_array = Arc::new(StructArray::new( + struct_fields.clone(), + vec![ + Arc::new(Int64Array::from(cols.pos)) as ArrayRef, + to_array(cols.avg), + to_array(cols.median), + to_array(cols.q1), + to_array(cols.q3), + to_array(cols.lower), + to_array(cols.upper), + ], + None, + )) as ArrayRef; + + let list_array = Arc::new(ListArray::new( + Arc::new(base_per_pos_data_element_field), + OffsetBuffer::new(vec![0, struct_array.len() as i32].into()), + struct_array, + None, + )); + + Ok(ScalarValue::Struct(Arc::new(StructArray::from(vec![ + ( + base_quality_warn_field, + Arc::new(StringArray::from(vec![base_quality_warn])) as ArrayRef, + ), + (base_per_pos_data_field, list_array), + ])))) + } + + fn update_batch(&mut self, values: &[ArrayRef]) -> Result<()> { + let arr = values[0] + .as_any() + .downcast_ref::() + .ok_or_else(|| { + datafusion::error::DataFusionError::Internal("Expected StringArray".to_string()) + })?; + + for i in 0..arr.len() { + if arr.is_null(i) { + continue; + } + let val = arr.value(i); + + for (j, c) in val.chars().enumerate() { + if let Some(decoded) = Self::decode_score(c) { + self.values_per_pos.entry(j).or_default().push(decoded); + } + } + } + + Ok(()) + } + + fn merge_batch(&mut self, _states: &[ArrayRef]) -> Result<()> { + Ok(()) + } + + fn size(&self) -> usize { + std::mem::size_of_val(self) + } +} + +pub fn base_quality_result_type() -> DataType { + let per_pos_fields = Fields::from(vec![ + Field::new("pos", DataType::Int64, false), + Field::new("average", DataType::Float64, false), + Field::new("median", DataType::Float64, false), + Field::new("q1", DataType::Float64, false), + Field::new("q3", DataType::Float64, false), + Field::new("lower", DataType::Float64, false), + Field::new("upper", DataType::Float64, false), + ]); + + let base_per_pos_element_field = Field::new( + "base_per_pos_data_element", + DataType::Struct(per_pos_fields), + false, + ); + + DataType::Struct(Fields::from(vec![ + Field::new("base_quality_warn", DataType::Utf8, false), + Field::new( + "base_per_pos_data", + DataType::List(Arc::new(base_per_pos_element_field)), + false, + ), + ])) +} From 5a64fe13c7219ace43e83997e233d5a1f2169ab3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20=C5=9Acise=C5=82?= Date: Fri, 30 May 2025 21:46:33 +0200 Subject: [PATCH 03/13] Remove serde_json dependency from Cargo files --- Cargo.lock | 1 - Cargo.toml | 1 - 2 files changed, 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2527967b..946f46a3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5424,7 +5424,6 @@ dependencies = [ "pyo3-log", "rand", "sequila-core", - "serde_json", "tokio", "tracing", ] diff --git a/Cargo.toml b/Cargo.toml index 919b38d5..47d326b7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,4 +43,3 @@ coitrees = "0.4.0" fnv = "1.0.7" async-stream = "0.3.6" rand = "0.8.5" -serde_json = "1.0.140" From dbc09494a94f0e6c4de961aef0396f65dd0e13b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20=C5=9Acise=C5=82?= Date: Tue, 3 Jun 2025 14:47:09 +0200 Subject: [PATCH 04/13] Added examples of using the base_sequence_quality function --- docs/notebooks/base_sequence_quality.ipynb | 4587 ++++++++++++++++++++ 1 file changed, 4587 insertions(+) create mode 100644 docs/notebooks/base_sequence_quality.ipynb diff --git a/docs/notebooks/base_sequence_quality.ipynb b/docs/notebooks/base_sequence_quality.ipynb new file mode 100644 index 00000000..35d8bed5 --- /dev/null +++ b/docs/notebooks/base_sequence_quality.ipynb @@ -0,0 +1,4587 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "83d7ccd7", + "metadata": {}, + "source": [ + "### Import dependencies" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "58b40aa6", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/user/.pyenv/versions/3.12.9/lib/python3.12/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", + " from .autonotebook import tqdm as notebook_tqdm\n", + "INFO:polars_bio:Creating BioSessionContext\n" + ] + } + ], + "source": [ + "import polars_bio as pb\n", + "import pandas as pd" + ] + }, + { + "cell_type": "markdown", + "id": "2e29cd0a", + "metadata": {}, + "source": [ + "### Usage examples" + ] + }, + { + "cell_type": "markdown", + "id": "f9aedeb9", + "metadata": {}, + "source": [ + "#### Usage example - calling UDAF directly in SQL" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "5f6fccf3", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:polars_bio:Table: example registered for path: ./example.fastq\n", + "1rows [00:00, 327.48rows/s]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'base_quality_warn': 'pass', 'base_per_pos_data': [{'pos': 89, 'average': 32.44, 'median': 35.0, 'q1': 33.0, 'q3': 35.0, 'lower': 30.0, 'upper': 38.0}, {'pos': 84, 'average': 32.415, 'median': 35.0, 'q1': 33.0, 'q3': 35.0, 'lower': 30.0, 'upper': 38.0}, {'pos': 96, 'average': 31.315, 'median': 34.0, 'q1': 32.0, 'q3': 35.0, 'lower': 27.5, 'upper': 39.5}, {'pos': 31, 'average': 38.795, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 49, 'average': 37.21, 'median': 39.0, 'q1': 36.0, 'q3': 40.0, 'lower': 30.0, 'upper': 46.0}, {'pos': 69, 'average': 33.7, 'median': 36.0, 'q1': 34.0, 'q3': 39.0, 'lower': 26.5, 'upper': 46.5}, {'pos': 63, 'average': 36.25, 'median': 38.0, 'q1': 35.0, 'q3': 40.0, 'lower': 27.5, 'upper': 47.5}, {'pos': 65, 'average': 35.995, 'median': 37.0, 'q1': 35.0, 'q3': 39.0, 'lower': 29.0, 'upper': 45.0}, {'pos': 70, 'average': 33.565, 'median': 35.0, 'q1': 34.0, 'q3': 38.0, 'lower': 28.0, 'upper': 44.0}, {'pos': 68, 'average': 35.91, 'median': 36.0, 'q1': 34.0, 'q3': 39.0, 'lower': 26.5, 'upper': 46.5}, {'pos': 55, 'average': 37.55, 'median': 39.0, 'q1': 36.0, 'q3': 40.0, 'lower': 30.0, 'upper': 46.0}, {'pos': 24, 'average': 38.265, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 21, 'average': 38.445, 'median': 40.0, 'q1': 38.0, 'q3': 40.0, 'lower': 35.0, 'upper': 43.0}, {'pos': 60, 'average': 35.985, 'median': 38.0, 'q1': 35.0, 'q3': 40.0, 'lower': 27.5, 'upper': 47.5}, {'pos': 45, 'average': 37.45, 'median': 40.0, 'q1': 36.0, 'q3': 41.0, 'lower': 28.5, 'upper': 48.5}, {'pos': 30, 'average': 38.245, 'median': 40.0, 'q1': 38.0, 'q3': 40.0, 'lower': 35.0, 'upper': 43.0}, {'pos': 20, 'average': 38.625, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 82, 'average': 31.525, 'median': 35.0, 'q1': 33.0, 'q3': 36.0, 'lower': 28.5, 'upper': 40.5}, {'pos': 85, 'average': 32.195, 'median': 35.0, 'q1': 33.0, 'q3': 35.0, 'lower': 30.0, 'upper': 38.0}, {'pos': 35, 'average': 38.385, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 57, 'average': 37.35, 'median': 39.0, 'q1': 36.0, 'q3': 40.0, 'lower': 30.0, 'upper': 46.0}, {'pos': 66, 'average': 35.875, 'median': 37.0, 'q1': 35.0, 'q3': 39.0, 'lower': 29.0, 'upper': 45.0}, {'pos': 74, 'average': 30.83, 'median': 35.0, 'q1': 32.0, 'q3': 37.0, 'lower': 24.5, 'upper': 44.5}, {'pos': 86, 'average': 31.815, 'median': 35.0, 'q1': 33.0, 'q3': 35.0, 'lower': 30.0, 'upper': 38.0}, {'pos': 87, 'average': 31.915, 'median': 35.0, 'q1': 32.0, 'q3': 35.0, 'lower': 27.5, 'upper': 39.5}, {'pos': 88, 'average': 32.065, 'median': 35.0, 'q1': 33.0, 'q3': 35.0, 'lower': 30.0, 'upper': 38.0}, {'pos': 42, 'average': 37.78, 'median': 40.0, 'q1': 37.0, 'q3': 40.0, 'lower': 32.5, 'upper': 44.5}, {'pos': 51, 'average': 37.53, 'median': 39.0, 'q1': 36.0, 'q3': 41.0, 'lower': 28.5, 'upper': 48.5}, {'pos': 71, 'average': 33.005, 'median': 35.0, 'q1': 33.0, 'q3': 38.0, 'lower': 25.5, 'upper': 45.5}, {'pos': 72, 'average': 33.265, 'median': 35.0, 'q1': 33.0, 'q3': 37.0, 'lower': 27.0, 'upper': 43.0}, {'pos': 90, 'average': 32.275, 'median': 34.5, 'q1': 33.0, 'q3': 35.0, 'lower': 30.0, 'upper': 38.0}, {'pos': 23, 'average': 38.635, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 32, 'average': 38.29, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 11, 'average': 37.71, 'median': 39.0, 'q1': 37.0, 'q3': 39.0, 'lower': 34.0, 'upper': 42.0}, {'pos': 43, 'average': 37.775, 'median': 40.0, 'q1': 38.0, 'q3': 40.0, 'lower': 35.0, 'upper': 43.0}, {'pos': 91, 'average': 32.665, 'median': 35.0, 'q1': 32.0, 'q3': 35.0, 'lower': 27.5, 'upper': 39.5}, {'pos': 6, 'average': 35.145, 'median': 35.0, 'q1': 35.0, 'q3': 37.0, 'lower': 32.0, 'upper': 40.0}, {'pos': 67, 'average': 35.96, 'median': 36.5, 'q1': 34.0, 'q3': 39.0, 'lower': 26.5, 'upper': 46.5}, {'pos': 76, 'average': 30.265, 'median': 35.0, 'q1': 31.0, 'q3': 37.0, 'lower': 22.0, 'upper': 46.0}, {'pos': 52, 'average': 37.77, 'median': 39.0, 'q1': 37.0, 'q3': 40.0, 'lower': 32.5, 'upper': 44.5}, {'pos': 73, 'average': 32.68, 'median': 35.0, 'q1': 33.0, 'q3': 37.0, 'lower': 27.0, 'upper': 43.0}, {'pos': 29, 'average': 38.595, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 17, 'average': 38.505, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 53, 'average': 37.845, 'median': 39.0, 'q1': 37.0, 'q3': 41.0, 'lower': 31.0, 'upper': 47.0}, {'pos': 77, 'average': 30.805, 'median': 35.0, 'q1': 30.0, 'q3': 36.0, 'lower': 21.0, 'upper': 45.0}, {'pos': 12, 'average': 37.5, 'median': 39.0, 'q1': 37.0, 'q3': 39.0, 'lower': 34.0, 'upper': 42.0}, {'pos': 37, 'average': 38.0, 'median': 40.0, 'q1': 38.0, 'q3': 40.0, 'lower': 35.0, 'upper': 43.0}, {'pos': 83, 'average': 32.03, 'median': 35.0, 'q1': 33.0, 'q3': 35.0, 'lower': 30.0, 'upper': 38.0}, {'pos': 99, 'average': 31.25, 'median': 34.0, 'q1': 32.0, 'q3': 35.0, 'lower': 27.5, 'upper': 39.5}, {'pos': 48, 'average': 37.61, 'median': 40.0, 'q1': 36.0, 'q3': 41.0, 'lower': 28.5, 'upper': 48.5}, {'pos': 4, 'average': 35.68, 'median': 37.0, 'q1': 35.0, 'q3': 37.0, 'lower': 32.0, 'upper': 40.0}, {'pos': 56, 'average': 37.59, 'median': 39.0, 'q1': 36.0, 'q3': 40.0, 'lower': 30.0, 'upper': 46.0}, {'pos': 8, 'average': 37.625, 'median': 39.0, 'q1': 37.0, 'q3': 39.0, 'lower': 34.0, 'upper': 42.0}, {'pos': 18, 'average': 38.47, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 38, 'average': 37.64, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 39, 'average': 37.895, 'median': 40.0, 'q1': 38.0, 'q3': 40.0, 'lower': 35.0, 'upper': 43.0}, {'pos': 41, 'average': 37.87, 'median': 40.0, 'q1': 37.0, 'q3': 41.0, 'lower': 31.0, 'upper': 47.0}, {'pos': 19, 'average': 38.425, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 15, 'average': 38.725, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 78, 'average': 31.46, 'median': 35.0, 'q1': 31.0, 'q3': 36.0, 'lower': 23.5, 'upper': 43.5}, {'pos': 62, 'average': 36.145, 'median': 38.0, 'q1': 35.0, 'q3': 40.0, 'lower': 27.5, 'upper': 47.5}, {'pos': 13, 'average': 38.94, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 28, 'average': 38.445, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 93, 'average': 31.05, 'median': 34.0, 'q1': 32.0, 'q3': 35.0, 'lower': 27.5, 'upper': 39.5}, {'pos': 94, 'average': 30.775, 'median': 34.0, 'q1': 32.0, 'q3': 35.0, 'lower': 27.5, 'upper': 39.5}, {'pos': 100, 'average': 31.105, 'median': 34.0, 'q1': 31.0, 'q3': 35.0, 'lower': 25.0, 'upper': 41.0}, {'pos': 64, 'average': 36.095, 'median': 37.0, 'q1': 35.0, 'q3': 40.0, 'lower': 27.5, 'upper': 47.5}, {'pos': 61, 'average': 35.99, 'median': 38.0, 'q1': 35.0, 'q3': 40.0, 'lower': 27.5, 'upper': 47.5}, {'pos': 44, 'average': 37.565, 'median': 40.0, 'q1': 37.0, 'q3': 41.0, 'lower': 31.0, 'upper': 47.0}, {'pos': 40, 'average': 37.95, 'median': 40.0, 'q1': 38.0, 'q3': 40.0, 'lower': 35.0, 'upper': 43.0}, {'pos': 92, 'average': 31.835, 'median': 35.0, 'q1': 32.0, 'q3': 35.0, 'lower': 27.5, 'upper': 39.5}, {'pos': 46, 'average': 37.79, 'median': 39.5, 'q1': 37.0, 'q3': 41.0, 'lower': 31.0, 'upper': 47.0}, {'pos': 10, 'average': 37.675, 'median': 39.0, 'q1': 37.0, 'q3': 39.0, 'lower': 34.0, 'upper': 42.0}, {'pos': 36, 'average': 38.11, 'median': 40.0, 'q1': 38.0, 'q3': 40.0, 'lower': 35.0, 'upper': 43.0}, {'pos': 0, 'average': 30.135, 'median': 33.0, 'q1': 31.0, 'q3': 34.0, 'lower': 26.5, 'upper': 38.5}, {'pos': 33, 'average': 38.245, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 26, 'average': 37.855, 'median': 40.0, 'q1': 38.0, 'q3': 40.0, 'lower': 35.0, 'upper': 43.0}, {'pos': 95, 'average': 31.425, 'median': 34.0, 'q1': 32.0, 'q3': 35.0, 'lower': 27.5, 'upper': 39.5}, {'pos': 98, 'average': 31.55, 'median': 34.0, 'q1': 32.0, 'q3': 35.0, 'lower': 27.5, 'upper': 39.5}, {'pos': 81, 'average': 32.76, 'median': 35.0, 'q1': 33.0, 'q3': 36.0, 'lower': 28.5, 'upper': 40.5}, {'pos': 14, 'average': 38.965, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 75, 'average': 31.06, 'median': 35.0, 'q1': 31.0, 'q3': 37.0, 'lower': 22.0, 'upper': 46.0}, {'pos': 5, 'average': 35.095, 'median': 35.0, 'q1': 35.0, 'q3': 37.0, 'lower': 32.0, 'upper': 40.0}, {'pos': 16, 'average': 38.48, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 3, 'average': 35.69, 'median': 37.0, 'q1': 35.0, 'q3': 37.0, 'lower': 32.0, 'upper': 40.0}, {'pos': 27, 'average': 38.44, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 54, 'average': 37.59, 'median': 39.5, 'q1': 36.0, 'q3': 41.0, 'lower': 28.5, 'upper': 48.5}, {'pos': 9, 'average': 37.36, 'median': 39.0, 'q1': 37.0, 'q3': 39.0, 'lower': 34.0, 'upper': 42.0}, {'pos': 97, 'average': 30.67, 'median': 34.0, 'q1': 31.0, 'q3': 35.0, 'lower': 25.0, 'upper': 41.0}, {'pos': 7, 'average': 35.4, 'median': 36.0, 'q1': 35.0, 'q3': 37.0, 'lower': 32.0, 'upper': 40.0}, {'pos': 22, 'average': 38.41, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 47, 'average': 37.665, 'median': 39.0, 'q1': 37.0, 'q3': 41.0, 'lower': 31.0, 'upper': 47.0}, {'pos': 59, 'average': 36.08, 'median': 38.0, 'q1': 35.0, 'q3': 40.0, 'lower': 27.5, 'upper': 47.5}, {'pos': 79, 'average': 32.46, 'median': 35.0, 'q1': 32.0, 'q3': 36.0, 'lower': 26.0, 'upper': 42.0}, {'pos': 50, 'average': 37.425, 'median': 39.0, 'q1': 36.0, 'q3': 41.0, 'lower': 28.5, 'upper': 48.5}, {'pos': 34, 'average': 38.205, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 58, 'average': 36.77, 'median': 38.0, 'q1': 35.0, 'q3': 40.0, 'lower': 27.5, 'upper': 47.5}, {'pos': 25, 'average': 38.2, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 2, 'average': 32.015, 'median': 34.0, 'q1': 31.0, 'q3': 34.0, 'lower': 26.5, 'upper': 38.5}, {'pos': 1, 'average': 31.21, 'median': 34.0, 'q1': 31.0, 'q3': 34.0, 'lower': 26.5, 'upper': 38.5}, {'pos': 80, 'average': 32.61, 'median': 35.0, 'q1': 32.0, 'q3': 36.0, 'lower': 26.0, 'upper': 42.0}]}\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "a_lazyframe = pb.read_fastq(\"./example.fastq\")\n", + "result = pb.sql(\"SELECT base_sequence_quality(quality_scores) FROM example\").collect()\n", + "print(result.item())" + ] + }, + { + "cell_type": "markdown", + "id": "b238193d", + "metadata": {}, + "source": [ + "#### Usage example - .fastq file" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "0420c240", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'base_quality_warn': 'pass',\n", + " 'base_per_pos_data': [{'lower': 33.5,\n", + " 'q3': 41.0,\n", + " 'q1': 38.0,\n", + " 'median': 40.0,\n", + " 'average': 38.205,\n", + " 'upper': 45.5,\n", + " 'pos': 34},\n", + " {'average': 38.47,\n", + " 'q1': 38.0,\n", + " 'lower': 33.5,\n", + " 'median': 40.0,\n", + " 'q3': 41.0,\n", + " 'pos': 18,\n", + " 'upper': 45.5},\n", + " {'q3': 35.0,\n", + " 'average': 31.815,\n", + " 'median': 35.0,\n", + " 'q1': 33.0,\n", + " 'pos': 86,\n", + " 'lower': 30.0,\n", + " 'upper': 38.0},\n", + " {'q3': 40.0,\n", + " 'lower': 35.0,\n", + " 'upper': 43.0,\n", + " 'pos': 21,\n", + " 'average': 38.445,\n", + " 'q1': 38.0,\n", + " 'median': 40.0},\n", + " {'lower': 27.5,\n", + " 'average': 31.835,\n", + " 'q3': 35.0,\n", + " 'median': 35.0,\n", + " 'q1': 32.0,\n", + " 'upper': 39.5,\n", + " 'pos': 92},\n", + " {'q3': 35.0,\n", + " 'lower': 27.5,\n", + " 'pos': 95,\n", + " 'upper': 39.5,\n", + " 'median': 34.0,\n", + " 'q1': 32.0,\n", + " 'average': 31.425},\n", + " {'average': 35.91,\n", + " 'q3': 39.0,\n", + " 'lower': 26.5,\n", + " 'median': 36.0,\n", + " 'pos': 68,\n", + " 'upper': 46.5,\n", + " 'q1': 34.0},\n", + " {'pos': 61,\n", + " 'average': 35.99,\n", + " 'median': 38.0,\n", + " 'q3': 40.0,\n", + " 'q1': 35.0,\n", + " 'lower': 27.5,\n", + " 'upper': 47.5},\n", + " {'median': 39.0,\n", + " 'lower': 30.0,\n", + " 'upper': 46.0,\n", + " 'average': 37.59,\n", + " 'q1': 36.0,\n", + " 'pos': 56,\n", + " 'q3': 40.0},\n", + " {'q3': 35.0,\n", + " 'upper': 38.0,\n", + " 'q1': 33.0,\n", + " 'pos': 89,\n", + " 'average': 32.44,\n", + " 'median': 35.0,\n", + " 'lower': 30.0},\n", + " {'lower': 35.0,\n", + " 'median': 40.0,\n", + " 'upper': 43.0,\n", + " 'pos': 37,\n", + " 'q1': 38.0,\n", + " 'average': 38.0,\n", + " 'q3': 40.0},\n", + " {'average': 37.71,\n", + " 'median': 39.0,\n", + " 'q1': 37.0,\n", + " 'pos': 11,\n", + " 'lower': 34.0,\n", + " 'q3': 39.0,\n", + " 'upper': 42.0},\n", + " {'average': 32.015,\n", + " 'median': 34.0,\n", + " 'lower': 26.5,\n", + " 'pos': 2,\n", + " 'q1': 31.0,\n", + " 'q3': 34.0,\n", + " 'upper': 38.5},\n", + " {'upper': 41.0,\n", + " 'q1': 31.0,\n", + " 'average': 30.67,\n", + " 'lower': 25.0,\n", + " 'pos': 97,\n", + " 'q3': 35.0,\n", + " 'median': 34.0},\n", + " {'lower': 33.5,\n", + " 'q1': 38.0,\n", + " 'median': 40.0,\n", + " 'q3': 41.0,\n", + " 'average': 38.595,\n", + " 'upper': 45.5,\n", + " 'pos': 29},\n", + " {'pos': 39,\n", + " 'lower': 35.0,\n", + " 'upper': 43.0,\n", + " 'q3': 40.0,\n", + " 'q1': 38.0,\n", + " 'median': 40.0,\n", + " 'average': 37.895},\n", + " {'upper': 39.5,\n", + " 'average': 31.25,\n", + " 'median': 34.0,\n", + " 'pos': 99,\n", + " 'q3': 35.0,\n", + " 'q1': 32.0,\n", + " 'lower': 27.5},\n", + " {'average': 37.425,\n", + " 'upper': 48.5,\n", + " 'pos': 50,\n", + " 'q1': 36.0,\n", + " 'lower': 28.5,\n", + " 'q3': 41.0,\n", + " 'median': 39.0},\n", + " {'median': 37.0,\n", + " 'pos': 66,\n", + " 'q3': 39.0,\n", + " 'upper': 45.0,\n", + " 'q1': 35.0,\n", + " 'lower': 29.0,\n", + " 'average': 35.875},\n", + " {'average': 38.94,\n", + " 'pos': 13,\n", + " 'median': 40.0,\n", + " 'q1': 38.0,\n", + " 'q3': 41.0,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5},\n", + " {'q1': 32.0,\n", + " 'average': 32.61,\n", + " 'median': 35.0,\n", + " 'pos': 80,\n", + " 'q3': 36.0,\n", + " 'lower': 26.0,\n", + " 'upper': 42.0},\n", + " {'lower': 27.5,\n", + " 'q1': 35.0,\n", + " 'upper': 47.5,\n", + " 'median': 38.0,\n", + " 'pos': 59,\n", + " 'average': 36.08,\n", + " 'q3': 40.0},\n", + " {'average': 31.55,\n", + " 'q3': 35.0,\n", + " 'pos': 98,\n", + " 'lower': 27.5,\n", + " 'median': 34.0,\n", + " 'upper': 39.5,\n", + " 'q1': 32.0},\n", + " {'average': 38.505,\n", + " 'q1': 38.0,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'pos': 17,\n", + " 'median': 40.0,\n", + " 'q3': 41.0},\n", + " {'q3': 41.0,\n", + " 'upper': 45.5,\n", + " 'median': 40.0,\n", + " 'pos': 20,\n", + " 'lower': 33.5,\n", + " 'average': 38.625,\n", + " 'q1': 38.0},\n", + " {'upper': 47.0,\n", + " 'average': 37.87,\n", + " 'q3': 41.0,\n", + " 'median': 40.0,\n", + " 'q1': 37.0,\n", + " 'lower': 31.0,\n", + " 'pos': 41},\n", + " {'q1': 38.0,\n", + " 'upper': 43.0,\n", + " 'lower': 35.0,\n", + " 'average': 37.775,\n", + " 'median': 40.0,\n", + " 'q3': 40.0,\n", + " 'pos': 43},\n", + " {'q1': 33.0,\n", + " 'average': 33.265,\n", + " 'pos': 72,\n", + " 'median': 35.0,\n", + " 'lower': 27.0,\n", + " 'upper': 43.0,\n", + " 'q3': 37.0},\n", + " {'median': 35.0,\n", + " 'average': 31.525,\n", + " 'q1': 33.0,\n", + " 'q3': 36.0,\n", + " 'pos': 82,\n", + " 'upper': 40.5,\n", + " 'lower': 28.5},\n", + " {'median': 39.0,\n", + " 'q1': 37.0,\n", + " 'pos': 8,\n", + " 'q3': 39.0,\n", + " 'lower': 34.0,\n", + " 'average': 37.625,\n", + " 'upper': 42.0},\n", + " {'median': 39.0,\n", + " 'q3': 39.0,\n", + " 'upper': 42.0,\n", + " 'lower': 34.0,\n", + " 'average': 37.5,\n", + " 'q1': 37.0,\n", + " 'pos': 12},\n", + " {'pos': 40,\n", + " 'lower': 35.0,\n", + " 'median': 40.0,\n", + " 'q1': 38.0,\n", + " 'upper': 43.0,\n", + " 'average': 37.95,\n", + " 'q3': 40.0},\n", + " {'q1': 36.0,\n", + " 'median': 39.0,\n", + " 'lower': 30.0,\n", + " 'q3': 40.0,\n", + " 'average': 37.35,\n", + " 'pos': 57,\n", + " 'upper': 46.0},\n", + " {'lower': 32.0,\n", + " 'upper': 40.0,\n", + " 'pos': 7,\n", + " 'q3': 37.0,\n", + " 'median': 36.0,\n", + " 'q1': 35.0,\n", + " 'average': 35.4},\n", + " {'median': 35.0,\n", + " 'lower': 30.0,\n", + " 'upper': 38.0,\n", + " 'average': 32.03,\n", + " 'pos': 83,\n", + " 'q1': 33.0,\n", + " 'q3': 35.0},\n", + " {'pos': 6,\n", + " 'q3': 37.0,\n", + " 'q1': 35.0,\n", + " 'lower': 32.0,\n", + " 'upper': 40.0,\n", + " 'median': 35.0,\n", + " 'average': 35.145},\n", + " {'q3': 39.0,\n", + " 'lower': 34.0,\n", + " 'median': 39.0,\n", + " 'upper': 42.0,\n", + " 'average': 37.675,\n", + " 'q1': 37.0,\n", + " 'pos': 10},\n", + " {'q1': 31.0,\n", + " 'q3': 34.0,\n", + " 'median': 33.0,\n", + " 'lower': 26.5,\n", + " 'pos': 0,\n", + " 'average': 30.135,\n", + " 'upper': 38.5},\n", + " {'pos': 1,\n", + " 'lower': 26.5,\n", + " 'average': 31.21,\n", + " 'q3': 34.0,\n", + " 'q1': 31.0,\n", + " 'median': 34.0,\n", + " 'upper': 38.5},\n", + " {'upper': 47.5,\n", + " 'average': 36.095,\n", + " 'q1': 35.0,\n", + " 'pos': 64,\n", + " 'median': 37.0,\n", + " 'q3': 40.0,\n", + " 'lower': 27.5},\n", + " {'average': 37.55,\n", + " 'q3': 40.0,\n", + " 'pos': 55,\n", + " 'lower': 30.0,\n", + " 'q1': 36.0,\n", + " 'median': 39.0,\n", + " 'upper': 46.0},\n", + " {'average': 30.83,\n", + " 'q3': 37.0,\n", + " 'lower': 24.5,\n", + " 'upper': 44.5,\n", + " 'q1': 32.0,\n", + " 'median': 35.0,\n", + " 'pos': 74},\n", + " {'lower': 28.5,\n", + " 'upper': 48.5,\n", + " 'average': 37.61,\n", + " 'pos': 48,\n", + " 'q1': 36.0,\n", + " 'median': 40.0,\n", + " 'q3': 41.0},\n", + " {'pos': 23,\n", + " 'q1': 38.0,\n", + " 'average': 38.635,\n", + " 'q3': 41.0,\n", + " 'lower': 33.5,\n", + " 'median': 40.0,\n", + " 'upper': 45.5},\n", + " {'pos': 32,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'average': 38.29,\n", + " 'median': 40.0,\n", + " 'q1': 38.0,\n", + " 'q3': 41.0},\n", + " {'upper': 45.5,\n", + " 'q1': 38.0,\n", + " 'q3': 41.0,\n", + " 'pos': 38,\n", + " 'lower': 33.5,\n", + " 'median': 40.0,\n", + " 'average': 37.64},\n", + " {'pos': 16,\n", + " 'lower': 33.5,\n", + " 'q1': 38.0,\n", + " 'upper': 45.5,\n", + " 'average': 38.48,\n", + " 'q3': 41.0,\n", + " 'median': 40.0},\n", + " {'median': 39.0,\n", + " 'upper': 42.0,\n", + " 'q1': 37.0,\n", + " 'pos': 9,\n", + " 'q3': 39.0,\n", + " 'average': 37.36,\n", + " 'lower': 34.0},\n", + " {'upper': 43.0,\n", + " 'average': 38.11,\n", + " 'q3': 40.0,\n", + " 'pos': 36,\n", + " 'median': 40.0,\n", + " 'q1': 38.0,\n", + " 'lower': 35.0},\n", + " {'lower': 35.0,\n", + " 'upper': 43.0,\n", + " 'median': 40.0,\n", + " 'q1': 38.0,\n", + " 'q3': 40.0,\n", + " 'average': 37.855,\n", + " 'pos': 26},\n", + " {'upper': 46.0,\n", + " 'pos': 75,\n", + " 'q1': 31.0,\n", + " 'average': 31.06,\n", + " 'median': 35.0,\n", + " 'lower': 22.0,\n", + " 'q3': 37.0},\n", + " {'median': 40.0,\n", + " 'q1': 38.0,\n", + " 'q3': 41.0,\n", + " 'upper': 45.5,\n", + " 'lower': 33.5,\n", + " 'pos': 24,\n", + " 'average': 38.265},\n", + " {'pos': 30,\n", + " 'median': 40.0,\n", + " 'q1': 38.0,\n", + " 'q3': 40.0,\n", + " 'upper': 43.0,\n", + " 'lower': 35.0,\n", + " 'average': 38.245},\n", + " {'pos': 69,\n", + " 'q1': 34.0,\n", + " 'q3': 39.0,\n", + " 'lower': 26.5,\n", + " 'upper': 46.5,\n", + " 'average': 33.7,\n", + " 'median': 36.0},\n", + " {'pos': 77,\n", + " 'q1': 30.0,\n", + " 'q3': 36.0,\n", + " 'lower': 21.0,\n", + " 'upper': 45.0,\n", + " 'median': 35.0,\n", + " 'average': 30.805},\n", + " {'upper': 45.5,\n", + " 'q1': 38.0,\n", + " 'pos': 28,\n", + " 'q3': 41.0,\n", + " 'median': 40.0,\n", + " 'lower': 33.5,\n", + " 'average': 38.445},\n", + " {'q1': 38.0,\n", + " 'average': 38.44,\n", + " 'median': 40.0,\n", + " 'q3': 41.0,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'pos': 27},\n", + " {'q3': 37.0,\n", + " 'pos': 3,\n", + " 'average': 35.69,\n", + " 'q1': 35.0,\n", + " 'lower': 32.0,\n", + " 'upper': 40.0,\n", + " 'median': 37.0},\n", + " {'median': 36.5,\n", + " 'lower': 26.5,\n", + " 'upper': 46.5,\n", + " 'average': 35.96,\n", + " 'q3': 39.0,\n", + " 'pos': 67,\n", + " 'q1': 34.0},\n", + " {'q3': 38.0,\n", + " 'lower': 28.0,\n", + " 'upper': 44.0,\n", + " 'average': 33.565,\n", + " 'median': 35.0,\n", + " 'pos': 70,\n", + " 'q1': 34.0},\n", + " {'upper': 39.5,\n", + " 'lower': 27.5,\n", + " 'pos': 87,\n", + " 'median': 35.0,\n", + " 'average': 31.915,\n", + " 'q1': 32.0,\n", + " 'q3': 35.0},\n", + " {'lower': 30.0,\n", + " 'pos': 88,\n", + " 'average': 32.065,\n", + " 'upper': 38.0,\n", + " 'median': 35.0,\n", + " 'q1': 33.0,\n", + " 'q3': 35.0},\n", + " {'q3': 35.0,\n", + " 'lower': 27.5,\n", + " 'upper': 39.5,\n", + " 'median': 34.0,\n", + " 'average': 31.05,\n", + " 'q1': 32.0,\n", + " 'pos': 93},\n", + " {'upper': 47.0,\n", + " 'median': 39.5,\n", + " 'q3': 41.0,\n", + " 'q1': 37.0,\n", + " 'average': 37.79,\n", + " 'lower': 31.0,\n", + " 'pos': 46},\n", + " {'pos': 96,\n", + " 'average': 31.315,\n", + " 'median': 34.0,\n", + " 'q1': 32.0,\n", + " 'upper': 39.5,\n", + " 'lower': 27.5,\n", + " 'q3': 35.0},\n", + " {'average': 31.105,\n", + " 'upper': 41.0,\n", + " 'pos': 100,\n", + " 'median': 34.0,\n", + " 'q1': 31.0,\n", + " 'q3': 35.0,\n", + " 'lower': 25.0},\n", + " {'q3': 37.0,\n", + " 'average': 32.68,\n", + " 'q1': 33.0,\n", + " 'pos': 73,\n", + " 'lower': 27.0,\n", + " 'upper': 43.0,\n", + " 'median': 35.0},\n", + " {'median': 40.0,\n", + " 'lower': 33.5,\n", + " 'average': 38.2,\n", + " 'upper': 45.5,\n", + " 'pos': 25,\n", + " 'q3': 41.0,\n", + " 'q1': 38.0},\n", + " {'upper': 47.0,\n", + " 'q3': 41.0,\n", + " 'q1': 37.0,\n", + " 'average': 37.845,\n", + " 'median': 39.0,\n", + " 'pos': 53,\n", + " 'lower': 31.0},\n", + " {'q3': 39.0,\n", + " 'upper': 45.0,\n", + " 'lower': 29.0,\n", + " 'pos': 65,\n", + " 'median': 37.0,\n", + " 'q1': 35.0,\n", + " 'average': 35.995},\n", + " {'upper': 38.0,\n", + " 'median': 35.0,\n", + " 'q1': 33.0,\n", + " 'lower': 30.0,\n", + " 'q3': 35.0,\n", + " 'pos': 84,\n", + " 'average': 32.415},\n", + " {'median': 39.5,\n", + " 'pos': 54,\n", + " 'q1': 36.0,\n", + " 'upper': 48.5,\n", + " 'average': 37.59,\n", + " 'q3': 41.0,\n", + " 'lower': 28.5},\n", + " {'average': 37.77,\n", + " 'q1': 37.0,\n", + " 'lower': 32.5,\n", + " 'upper': 44.5,\n", + " 'q3': 40.0,\n", + " 'pos': 52,\n", + " 'median': 39.0},\n", + " {'upper': 47.5,\n", + " 'pos': 58,\n", + " 'median': 38.0,\n", + " 'average': 36.77,\n", + " 'q1': 35.0,\n", + " 'q3': 40.0,\n", + " 'lower': 27.5},\n", + " {'average': 36.25,\n", + " 'q3': 40.0,\n", + " 'q1': 35.0,\n", + " 'lower': 27.5,\n", + " 'median': 38.0,\n", + " 'pos': 63,\n", + " 'upper': 47.5},\n", + " {'q1': 38.0,\n", + " 'q3': 41.0,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'pos': 15,\n", + " 'average': 38.725,\n", + " 'median': 40.0},\n", + " {'pos': 94,\n", + " 'q3': 35.0,\n", + " 'q1': 32.0,\n", + " 'upper': 39.5,\n", + " 'average': 30.775,\n", + " 'median': 34.0,\n", + " 'lower': 27.5},\n", + " {'median': 39.0,\n", + " 'q1': 36.0,\n", + " 'q3': 41.0,\n", + " 'pos': 51,\n", + " 'lower': 28.5,\n", + " 'upper': 48.5,\n", + " 'average': 37.53},\n", + " {'q1': 33.0,\n", + " 'upper': 40.5,\n", + " 'median': 35.0,\n", + " 'average': 32.76,\n", + " 'pos': 81,\n", + " 'lower': 28.5,\n", + " 'q3': 36.0},\n", + " {'average': 37.78,\n", + " 'q3': 40.0,\n", + " 'lower': 32.5,\n", + " 'median': 40.0,\n", + " 'upper': 44.5,\n", + " 'pos': 42,\n", + " 'q1': 37.0},\n", + " {'upper': 42.0,\n", + " 'q1': 32.0,\n", + " 'lower': 26.0,\n", + " 'median': 35.0,\n", + " 'pos': 79,\n", + " 'average': 32.46,\n", + " 'q3': 36.0},\n", + " {'q1': 36.0,\n", + " 'pos': 49,\n", + " 'average': 37.21,\n", + " 'lower': 30.0,\n", + " 'upper': 46.0,\n", + " 'median': 39.0,\n", + " 'q3': 40.0},\n", + " {'upper': 47.5,\n", + " 'pos': 62,\n", + " 'q1': 35.0,\n", + " 'q3': 40.0,\n", + " 'median': 38.0,\n", + " 'lower': 27.5,\n", + " 'average': 36.145},\n", + " {'q3': 36.0,\n", + " 'average': 31.46,\n", + " 'pos': 78,\n", + " 'median': 35.0,\n", + " 'lower': 23.5,\n", + " 'upper': 43.5,\n", + " 'q1': 31.0},\n", + " {'median': 40.0,\n", + " 'average': 38.245,\n", + " 'q3': 41.0,\n", + " 'pos': 33,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'q1': 38.0},\n", + " {'q3': 41.0,\n", + " 'lower': 33.5,\n", + " 'q1': 38.0,\n", + " 'upper': 45.5,\n", + " 'pos': 14,\n", + " 'average': 38.965,\n", + " 'median': 40.0},\n", + " {'median': 40.0,\n", + " 'q1': 38.0,\n", + " 'q3': 41.0,\n", + " 'lower': 33.5,\n", + " 'average': 38.41,\n", + " 'upper': 45.5,\n", + " 'pos': 22},\n", + " {'q3': 35.0,\n", + " 'median': 34.5,\n", + " 'upper': 38.0,\n", + " 'pos': 90,\n", + " 'q1': 33.0,\n", + " 'lower': 30.0,\n", + " 'average': 32.275},\n", + " {'lower': 33.5,\n", + " 'median': 40.0,\n", + " 'pos': 19,\n", + " 'average': 38.425,\n", + " 'q1': 38.0,\n", + " 'q3': 41.0,\n", + " 'upper': 45.5},\n", + " {'average': 38.385,\n", + " 'median': 40.0,\n", + " 'lower': 33.5,\n", + " 'q1': 38.0,\n", + " 'upper': 45.5,\n", + " 'pos': 35,\n", + " 'q3': 41.0},\n", + " {'q1': 38.0,\n", + " 'q3': 41.0,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'average': 38.795,\n", + " 'pos': 31,\n", + " 'median': 40.0},\n", + " {'upper': 48.5,\n", + " 'pos': 45,\n", + " 'average': 37.45,\n", + " 'median': 40.0,\n", + " 'q1': 36.0,\n", + " 'q3': 41.0,\n", + " 'lower': 28.5},\n", + " {'upper': 46.0,\n", + " 'pos': 76,\n", + " 'q1': 31.0,\n", + " 'median': 35.0,\n", + " 'q3': 37.0,\n", + " 'average': 30.265,\n", + " 'lower': 22.0},\n", + " {'pos': 44,\n", + " 'q1': 37.0,\n", + " 'upper': 47.0,\n", + " 'average': 37.565,\n", + " 'lower': 31.0,\n", + " 'q3': 41.0,\n", + " 'median': 40.0},\n", + " {'upper': 45.5,\n", + " 'q3': 38.0,\n", + " 'q1': 33.0,\n", + " 'lower': 25.5,\n", + " 'median': 35.0,\n", + " 'average': 33.005,\n", + " 'pos': 71},\n", + " {'pos': 47,\n", + " 'average': 37.665,\n", + " 'median': 39.0,\n", + " 'q1': 37.0,\n", + " 'lower': 31.0,\n", + " 'upper': 47.0,\n", + " 'q3': 41.0},\n", + " {'q3': 37.0,\n", + " 'pos': 5,\n", + " 'average': 35.095,\n", + " 'median': 35.0,\n", + " 'q1': 35.0,\n", + " 'lower': 32.0,\n", + " 'upper': 40.0},\n", + " {'pos': 4,\n", + " 'average': 35.68,\n", + " 'median': 37.0,\n", + " 'q3': 37.0,\n", + " 'lower': 32.0,\n", + " 'upper': 40.0,\n", + " 'q1': 35.0},\n", + " {'upper': 47.5,\n", + " 'pos': 60,\n", + " 'median': 38.0,\n", + " 'average': 35.985,\n", + " 'q1': 35.0,\n", + " 'q3': 40.0,\n", + " 'lower': 27.5},\n", + " {'q1': 32.0,\n", + " 'average': 32.665,\n", + " 'q3': 35.0,\n", + " 'lower': 27.5,\n", + " 'median': 35.0,\n", + " 'pos': 91,\n", + " 'upper': 39.5},\n", + " {'average': 32.195,\n", + " 'median': 35.0,\n", + " 'pos': 85,\n", + " 'q1': 33.0,\n", + " 'q3': 35.0,\n", + " 'lower': 30.0,\n", + " 'upper': 38.0}]}" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pb.base_sequence_quality(\"example.fastq\")" + ] + }, + { + "cell_type": "markdown", + "id": "9886c394", + "metadata": {}, + "source": [ + "#### Usage example - .csv file" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "66c3af24", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'base_quality_warn': 'pass',\n", + " 'base_per_pos_data': [{'average': 32.195,\n", + " 'pos': 85,\n", + " 'q3': 35.0,\n", + " 'lower': 30.0,\n", + " 'upper': 38.0,\n", + " 'median': 35.0,\n", + " 'q1': 33.0},\n", + " {'average': 38.245,\n", + " 'median': 40.0,\n", + " 'q3': 40.0,\n", + " 'lower': 35.0,\n", + " 'pos': 30,\n", + " 'upper': 43.0,\n", + " 'q1': 38.0},\n", + " {'pos': 2,\n", + " 'average': 32.015,\n", + " 'q3': 34.0,\n", + " 'lower': 26.5,\n", + " 'upper': 38.5,\n", + " 'q1': 31.0,\n", + " 'median': 34.0},\n", + " {'lower': 30.0,\n", + " 'pos': 89,\n", + " 'upper': 38.0,\n", + " 'average': 32.44,\n", + " 'median': 35.0,\n", + " 'q1': 33.0,\n", + " 'q3': 35.0},\n", + " {'q3': 39.0,\n", + " 'average': 37.5,\n", + " 'q1': 37.0,\n", + " 'pos': 12,\n", + " 'median': 39.0,\n", + " 'lower': 34.0,\n", + " 'upper': 42.0},\n", + " {'median': 40.0,\n", + " 'pos': 23,\n", + " 'lower': 33.5,\n", + " 'q3': 41.0,\n", + " 'q1': 38.0,\n", + " 'upper': 45.5,\n", + " 'average': 38.635},\n", + " {'average': 38.595,\n", + " 'median': 40.0,\n", + " 'q3': 41.0,\n", + " 'lower': 33.5,\n", + " 'q1': 38.0,\n", + " 'pos': 29,\n", + " 'upper': 45.5},\n", + " {'average': 37.35,\n", + " 'pos': 57,\n", + " 'q1': 36.0,\n", + " 'median': 39.0,\n", + " 'lower': 30.0,\n", + " 'upper': 46.0,\n", + " 'q3': 40.0},\n", + " {'pos': 56,\n", + " 'average': 37.59,\n", + " 'upper': 46.0,\n", + " 'median': 39.0,\n", + " 'q1': 36.0,\n", + " 'q3': 40.0,\n", + " 'lower': 30.0},\n", + " {'average': 36.08,\n", + " 'q3': 40.0,\n", + " 'q1': 35.0,\n", + " 'median': 38.0,\n", + " 'upper': 47.5,\n", + " 'pos': 59,\n", + " 'lower': 27.5},\n", + " {'q1': 32.0,\n", + " 'median': 35.0,\n", + " 'average': 31.835,\n", + " 'q3': 35.0,\n", + " 'pos': 92,\n", + " 'lower': 27.5,\n", + " 'upper': 39.5},\n", + " {'q3': 41.0,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'pos': 24,\n", + " 'median': 40.0,\n", + " 'average': 38.265,\n", + " 'q1': 38.0},\n", + " {'lower': 30.0,\n", + " 'upper': 46.0,\n", + " 'pos': 49,\n", + " 'median': 39.0,\n", + " 'average': 37.21,\n", + " 'q1': 36.0,\n", + " 'q3': 40.0},\n", + " {'upper': 38.0,\n", + " 'pos': 90,\n", + " 'q1': 33.0,\n", + " 'average': 32.275,\n", + " 'q3': 35.0,\n", + " 'lower': 30.0,\n", + " 'median': 34.5},\n", + " {'q1': 34.0,\n", + " 'pos': 70,\n", + " 'lower': 28.0,\n", + " 'average': 33.565,\n", + " 'median': 35.0,\n", + " 'q3': 38.0,\n", + " 'upper': 44.0},\n", + " {'upper': 45.5,\n", + " 'pos': 27,\n", + " 'q1': 38.0,\n", + " 'average': 38.44,\n", + " 'median': 40.0,\n", + " 'q3': 41.0,\n", + " 'lower': 33.5},\n", + " {'upper': 42.0,\n", + " 'average': 37.675,\n", + " 'q3': 39.0,\n", + " 'pos': 10,\n", + " 'median': 39.0,\n", + " 'q1': 37.0,\n", + " 'lower': 34.0},\n", + " {'q1': 32.0,\n", + " 'upper': 39.5,\n", + " 'q3': 35.0,\n", + " 'pos': 98,\n", + " 'average': 31.55,\n", + " 'lower': 27.5,\n", + " 'median': 34.0},\n", + " {'median': 40.0,\n", + " 'pos': 13,\n", + " 'average': 38.94,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'q3': 41.0,\n", + " 'q1': 38.0},\n", + " {'upper': 43.0,\n", + " 'q3': 40.0,\n", + " 'median': 40.0,\n", + " 'pos': 21,\n", + " 'average': 38.445,\n", + " 'q1': 38.0,\n", + " 'lower': 35.0},\n", + " {'lower': 27.5,\n", + " 'median': 34.0,\n", + " 'pos': 99,\n", + " 'average': 31.25,\n", + " 'q3': 35.0,\n", + " 'q1': 32.0,\n", + " 'upper': 39.5},\n", + " {'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'q3': 41.0,\n", + " 'pos': 31,\n", + " 'average': 38.795,\n", + " 'q1': 38.0,\n", + " 'median': 40.0},\n", + " {'average': 37.855,\n", + " 'lower': 35.0,\n", + " 'upper': 43.0,\n", + " 'pos': 26,\n", + " 'q3': 40.0,\n", + " 'q1': 38.0,\n", + " 'median': 40.0},\n", + " {'pos': 33,\n", + " 'upper': 45.5,\n", + " 'average': 38.245,\n", + " 'q1': 38.0,\n", + " 'q3': 41.0,\n", + " 'lower': 33.5,\n", + " 'median': 40.0},\n", + " {'average': 37.665,\n", + " 'pos': 47,\n", + " 'q3': 41.0,\n", + " 'lower': 31.0,\n", + " 'median': 39.0,\n", + " 'q1': 37.0,\n", + " 'upper': 47.0},\n", + " {'average': 38.505,\n", + " 'q1': 38.0,\n", + " 'q3': 41.0,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'pos': 17,\n", + " 'median': 40.0},\n", + " {'q3': 40.0,\n", + " 'median': 39.0,\n", + " 'upper': 44.5,\n", + " 'average': 37.77,\n", + " 'pos': 52,\n", + " 'q1': 37.0,\n", + " 'lower': 32.5},\n", + " {'q3': 35.0,\n", + " 'upper': 39.5,\n", + " 'median': 35.0,\n", + " 'q1': 32.0,\n", + " 'lower': 27.5,\n", + " 'pos': 87,\n", + " 'average': 31.915},\n", + " {'upper': 48.5,\n", + " 'pos': 48,\n", + " 'q3': 41.0,\n", + " 'average': 37.61,\n", + " 'q1': 36.0,\n", + " 'median': 40.0,\n", + " 'lower': 28.5},\n", + " {'median': 40.0,\n", + " 'upper': 43.0,\n", + " 'q3': 40.0,\n", + " 'lower': 35.0,\n", + " 'q1': 38.0,\n", + " 'average': 37.895,\n", + " 'pos': 39},\n", + " {'upper': 45.5,\n", + " 'q1': 38.0,\n", + " 'average': 38.2,\n", + " 'q3': 41.0,\n", + " 'lower': 33.5,\n", + " 'pos': 25,\n", + " 'median': 40.0},\n", + " {'pos': 63,\n", + " 'q1': 35.0,\n", + " 'average': 36.25,\n", + " 'q3': 40.0,\n", + " 'lower': 27.5,\n", + " 'upper': 47.5,\n", + " 'median': 38.0},\n", + " {'pos': 80,\n", + " 'average': 32.61,\n", + " 'upper': 42.0,\n", + " 'q1': 32.0,\n", + " 'median': 35.0,\n", + " 'q3': 36.0,\n", + " 'lower': 26.0},\n", + " {'q3': 41.0,\n", + " 'lower': 31.0,\n", + " 'upper': 47.0,\n", + " 'q1': 37.0,\n", + " 'median': 39.0,\n", + " 'average': 37.845,\n", + " 'pos': 53},\n", + " {'upper': 45.5,\n", + " 'pos': 16,\n", + " 'median': 40.0,\n", + " 'average': 38.48,\n", + " 'q3': 41.0,\n", + " 'q1': 38.0,\n", + " 'lower': 33.5},\n", + " {'q1': 38.0,\n", + " 'pos': 14,\n", + " 'average': 38.965,\n", + " 'median': 40.0,\n", + " 'q3': 41.0,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5},\n", + " {'pos': 55,\n", + " 'q3': 40.0,\n", + " 'median': 39.0,\n", + " 'lower': 30.0,\n", + " 'q1': 36.0,\n", + " 'upper': 46.0,\n", + " 'average': 37.55},\n", + " {'average': 37.78,\n", + " 'median': 40.0,\n", + " 'q3': 40.0,\n", + " 'pos': 42,\n", + " 'q1': 37.0,\n", + " 'lower': 32.5,\n", + " 'upper': 44.5},\n", + " {'average': 37.425,\n", + " 'q1': 36.0,\n", + " 'upper': 48.5,\n", + " 'pos': 50,\n", + " 'median': 39.0,\n", + " 'q3': 41.0,\n", + " 'lower': 28.5},\n", + " {'lower': 25.0,\n", + " 'upper': 41.0,\n", + " 'q1': 31.0,\n", + " 'average': 31.105,\n", + " 'median': 34.0,\n", + " 'q3': 35.0,\n", + " 'pos': 100},\n", + " {'upper': 38.5,\n", + " 'q1': 31.0,\n", + " 'q3': 34.0,\n", + " 'lower': 26.5,\n", + " 'average': 30.135,\n", + " 'median': 33.0,\n", + " 'pos': 0},\n", + " {'lower': 26.5,\n", + " 'q1': 31.0,\n", + " 'median': 34.0,\n", + " 'upper': 38.5,\n", + " 'pos': 1,\n", + " 'q3': 34.0,\n", + " 'average': 31.21},\n", + " {'q3': 37.0,\n", + " 'q1': 32.0,\n", + " 'upper': 44.5,\n", + " 'pos': 74,\n", + " 'average': 30.83,\n", + " 'median': 35.0,\n", + " 'lower': 24.5},\n", + " {'upper': 38.0,\n", + " 'q3': 35.0,\n", + " 'median': 35.0,\n", + " 'pos': 84,\n", + " 'average': 32.415,\n", + " 'q1': 33.0,\n", + " 'lower': 30.0},\n", + " {'median': 35.0,\n", + " 'q1': 35.0,\n", + " 'q3': 37.0,\n", + " 'lower': 32.0,\n", + " 'average': 35.095,\n", + " 'pos': 5,\n", + " 'upper': 40.0},\n", + " {'pos': 3,\n", + " 'median': 37.0,\n", + " 'q1': 35.0,\n", + " 'q3': 37.0,\n", + " 'lower': 32.0,\n", + " 'average': 35.69,\n", + " 'upper': 40.0},\n", + " {'pos': 40,\n", + " 'q1': 38.0,\n", + " 'average': 37.95,\n", + " 'q3': 40.0,\n", + " 'lower': 35.0,\n", + " 'median': 40.0,\n", + " 'upper': 43.0},\n", + " {'pos': 58,\n", + " 'q3': 40.0,\n", + " 'lower': 27.5,\n", + " 'upper': 47.5,\n", + " 'median': 38.0,\n", + " 'q1': 35.0,\n", + " 'average': 36.77},\n", + " {'median': 37.0,\n", + " 'q3': 40.0,\n", + " 'lower': 27.5,\n", + " 'q1': 35.0,\n", + " 'upper': 47.5,\n", + " 'pos': 64,\n", + " 'average': 36.095},\n", + " {'pos': 41,\n", + " 'q3': 41.0,\n", + " 'median': 40.0,\n", + " 'lower': 31.0,\n", + " 'upper': 47.0,\n", + " 'q1': 37.0,\n", + " 'average': 37.87},\n", + " {'average': 35.99,\n", + " 'median': 38.0,\n", + " 'q1': 35.0,\n", + " 'q3': 40.0,\n", + " 'lower': 27.5,\n", + " 'upper': 47.5,\n", + " 'pos': 61},\n", + " {'q3': 39.0,\n", + " 'median': 39.0,\n", + " 'average': 37.625,\n", + " 'pos': 8,\n", + " 'lower': 34.0,\n", + " 'q1': 37.0,\n", + " 'upper': 42.0},\n", + " {'upper': 48.5,\n", + " 'q3': 41.0,\n", + " 'average': 37.45,\n", + " 'pos': 45,\n", + " 'q1': 36.0,\n", + " 'median': 40.0,\n", + " 'lower': 28.5},\n", + " {'pos': 71,\n", + " 'average': 33.005,\n", + " 'q1': 33.0,\n", + " 'median': 35.0,\n", + " 'upper': 45.5,\n", + " 'lower': 25.5,\n", + " 'q3': 38.0},\n", + " {'median': 35.0,\n", + " 'average': 32.03,\n", + " 'pos': 83,\n", + " 'q1': 33.0,\n", + " 'lower': 30.0,\n", + " 'upper': 38.0,\n", + " 'q3': 35.0},\n", + " {'pos': 36,\n", + " 'upper': 43.0,\n", + " 'median': 40.0,\n", + " 'average': 38.11,\n", + " 'q1': 38.0,\n", + " 'q3': 40.0,\n", + " 'lower': 35.0},\n", + " {'lower': 30.0,\n", + " 'upper': 38.0,\n", + " 'pos': 86,\n", + " 'q1': 33.0,\n", + " 'average': 31.815,\n", + " 'q3': 35.0,\n", + " 'median': 35.0},\n", + " {'lower': 35.0,\n", + " 'pos': 37,\n", + " 'upper': 43.0,\n", + " 'q3': 40.0,\n", + " 'q1': 38.0,\n", + " 'average': 38.0,\n", + " 'median': 40.0},\n", + " {'lower': 34.0,\n", + " 'upper': 42.0,\n", + " 'average': 37.36,\n", + " 'q3': 39.0,\n", + " 'q1': 37.0,\n", + " 'median': 39.0,\n", + " 'pos': 9},\n", + " {'q3': 36.0,\n", + " 'lower': 28.5,\n", + " 'median': 35.0,\n", + " 'upper': 40.5,\n", + " 'q1': 33.0,\n", + " 'average': 32.76,\n", + " 'pos': 81},\n", + " {'pos': 38,\n", + " 'q3': 41.0,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'average': 37.64,\n", + " 'q1': 38.0,\n", + " 'median': 40.0},\n", + " {'average': 32.065,\n", + " 'q3': 35.0,\n", + " 'upper': 38.0,\n", + " 'lower': 30.0,\n", + " 'median': 35.0,\n", + " 'q1': 33.0,\n", + " 'pos': 88},\n", + " {'average': 31.525,\n", + " 'q3': 36.0,\n", + " 'pos': 82,\n", + " 'lower': 28.5,\n", + " 'median': 35.0,\n", + " 'upper': 40.5,\n", + " 'q1': 33.0},\n", + " {'pos': 91,\n", + " 'average': 32.665,\n", + " 'q1': 32.0,\n", + " 'q3': 35.0,\n", + " 'median': 35.0,\n", + " 'lower': 27.5,\n", + " 'upper': 39.5},\n", + " {'q1': 34.0,\n", + " 'q3': 39.0,\n", + " 'pos': 69,\n", + " 'upper': 46.5,\n", + " 'lower': 26.5,\n", + " 'median': 36.0,\n", + " 'average': 33.7},\n", + " {'median': 35.0,\n", + " 'lower': 27.0,\n", + " 'average': 32.68,\n", + " 'pos': 73,\n", + " 'q1': 33.0,\n", + " 'q3': 37.0,\n", + " 'upper': 43.0},\n", + " {'q1': 36.0,\n", + " 'q3': 41.0,\n", + " 'lower': 28.5,\n", + " 'average': 37.53,\n", + " 'upper': 48.5,\n", + " 'pos': 51,\n", + " 'median': 39.0},\n", + " {'pos': 43,\n", + " 'median': 40.0,\n", + " 'q1': 38.0,\n", + " 'q3': 40.0,\n", + " 'lower': 35.0,\n", + " 'upper': 43.0,\n", + " 'average': 37.775},\n", + " {'q3': 39.0,\n", + " 'median': 39.0,\n", + " 'pos': 11,\n", + " 'upper': 42.0,\n", + " 'lower': 34.0,\n", + " 'q1': 37.0,\n", + " 'average': 37.71},\n", + " {'q1': 38.0,\n", + " 'pos': 28,\n", + " 'median': 40.0,\n", + " 'lower': 33.5,\n", + " 'average': 38.445,\n", + " 'q3': 41.0,\n", + " 'upper': 45.5},\n", + " {'average': 38.47,\n", + " 'q1': 38.0,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'q3': 41.0,\n", + " 'pos': 18,\n", + " 'median': 40.0},\n", + " {'median': 40.0,\n", + " 'q3': 41.0,\n", + " 'pos': 44,\n", + " 'q1': 37.0,\n", + " 'average': 37.565,\n", + " 'upper': 47.0,\n", + " 'lower': 31.0},\n", + " {'q1': 35.0,\n", + " 'pos': 6,\n", + " 'q3': 37.0,\n", + " 'median': 35.0,\n", + " 'upper': 40.0,\n", + " 'average': 35.145,\n", + " 'lower': 32.0},\n", + " {'median': 40.0,\n", + " 'q3': 41.0,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'pos': 35,\n", + " 'q1': 38.0,\n", + " 'average': 38.385},\n", + " {'pos': 60,\n", + " 'lower': 27.5,\n", + " 'median': 38.0,\n", + " 'average': 35.985,\n", + " 'upper': 47.5,\n", + " 'q1': 35.0,\n", + " 'q3': 40.0},\n", + " {'q3': 37.0,\n", + " 'average': 35.4,\n", + " 'q1': 35.0,\n", + " 'median': 36.0,\n", + " 'lower': 32.0,\n", + " 'upper': 40.0,\n", + " 'pos': 7},\n", + " {'q3': 37.0,\n", + " 'lower': 27.0,\n", + " 'upper': 43.0,\n", + " 'median': 35.0,\n", + " 'q1': 33.0,\n", + " 'pos': 72,\n", + " 'average': 33.265},\n", + " {'average': 30.265,\n", + " 'pos': 76,\n", + " 'median': 35.0,\n", + " 'q3': 37.0,\n", + " 'lower': 22.0,\n", + " 'upper': 46.0,\n", + " 'q1': 31.0},\n", + " {'q1': 35.0,\n", + " 'average': 35.875,\n", + " 'q3': 39.0,\n", + " 'upper': 45.0,\n", + " 'pos': 66,\n", + " 'lower': 29.0,\n", + " 'median': 37.0},\n", + " {'average': 36.145,\n", + " 'pos': 62,\n", + " 'q3': 40.0,\n", + " 'lower': 27.5,\n", + " 'q1': 35.0,\n", + " 'upper': 47.5,\n", + " 'median': 38.0},\n", + " {'pos': 93,\n", + " 'median': 34.0,\n", + " 'lower': 27.5,\n", + " 'upper': 39.5,\n", + " 'q1': 32.0,\n", + " 'q3': 35.0,\n", + " 'average': 31.05},\n", + " {'average': 35.68,\n", + " 'median': 37.0,\n", + " 'q3': 37.0,\n", + " 'upper': 40.0,\n", + " 'lower': 32.0,\n", + " 'pos': 4,\n", + " 'q1': 35.0},\n", + " {'pos': 46,\n", + " 'lower': 31.0,\n", + " 'q1': 37.0,\n", + " 'average': 37.79,\n", + " 'q3': 41.0,\n", + " 'median': 39.5,\n", + " 'upper': 47.0},\n", + " {'pos': 20,\n", + " 'median': 40.0,\n", + " 'q3': 41.0,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'average': 38.625,\n", + " 'q1': 38.0},\n", + " {'q1': 36.0,\n", + " 'upper': 48.5,\n", + " 'pos': 54,\n", + " 'q3': 41.0,\n", + " 'lower': 28.5,\n", + " 'average': 37.59,\n", + " 'median': 39.5},\n", + " {'pos': 95,\n", + " 'q3': 35.0,\n", + " 'q1': 32.0,\n", + " 'average': 31.425,\n", + " 'lower': 27.5,\n", + " 'upper': 39.5,\n", + " 'median': 34.0},\n", + " {'upper': 42.0,\n", + " 'lower': 26.0,\n", + " 'pos': 79,\n", + " 'q3': 36.0,\n", + " 'average': 32.46,\n", + " 'median': 35.0,\n", + " 'q1': 32.0},\n", + " {'average': 31.46,\n", + " 'lower': 23.5,\n", + " 'q3': 36.0,\n", + " 'pos': 78,\n", + " 'q1': 31.0,\n", + " 'upper': 43.5,\n", + " 'median': 35.0},\n", + " {'q1': 32.0,\n", + " 'lower': 27.5,\n", + " 'median': 34.0,\n", + " 'average': 30.775,\n", + " 'pos': 94,\n", + " 'q3': 35.0,\n", + " 'upper': 39.5},\n", + " {'q3': 35.0,\n", + " 'lower': 27.5,\n", + " 'q1': 32.0,\n", + " 'upper': 39.5,\n", + " 'pos': 96,\n", + " 'average': 31.315,\n", + " 'median': 34.0},\n", + " {'pos': 75,\n", + " 'average': 31.06,\n", + " 'q1': 31.0,\n", + " 'q3': 37.0,\n", + " 'lower': 22.0,\n", + " 'upper': 46.0,\n", + " 'median': 35.0},\n", + " {'q3': 39.0,\n", + " 'pos': 67,\n", + " 'lower': 26.5,\n", + " 'upper': 46.5,\n", + " 'median': 36.5,\n", + " 'average': 35.96,\n", + " 'q1': 34.0},\n", + " {'lower': 33.5,\n", + " 'median': 40.0,\n", + " 'q3': 41.0,\n", + " 'upper': 45.5,\n", + " 'pos': 19,\n", + " 'average': 38.425,\n", + " 'q1': 38.0},\n", + " {'average': 38.725,\n", + " 'q1': 38.0,\n", + " 'pos': 15,\n", + " 'median': 40.0,\n", + " 'q3': 41.0,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5},\n", + " {'upper': 45.5,\n", + " 'pos': 34,\n", + " 'average': 38.205,\n", + " 'lower': 33.5,\n", + " 'q1': 38.0,\n", + " 'q3': 41.0,\n", + " 'median': 40.0},\n", + " {'average': 38.41,\n", + " 'q3': 41.0,\n", + " 'pos': 22,\n", + " 'median': 40.0,\n", + " 'lower': 33.5,\n", + " 'q1': 38.0,\n", + " 'upper': 45.5},\n", + " {'average': 38.29,\n", + " 'median': 40.0,\n", + " 'q1': 38.0,\n", + " 'upper': 45.5,\n", + " 'pos': 32,\n", + " 'q3': 41.0,\n", + " 'lower': 33.5},\n", + " {'median': 35.0,\n", + " 'q1': 30.0,\n", + " 'upper': 45.0,\n", + " 'average': 30.805,\n", + " 'q3': 36.0,\n", + " 'pos': 77,\n", + " 'lower': 21.0},\n", + " {'average': 35.91,\n", + " 'q1': 34.0,\n", + " 'q3': 39.0,\n", + " 'median': 36.0,\n", + " 'lower': 26.5,\n", + " 'upper': 46.5,\n", + " 'pos': 68},\n", + " {'lower': 25.0,\n", + " 'median': 34.0,\n", + " 'upper': 41.0,\n", + " 'pos': 97,\n", + " 'q3': 35.0,\n", + " 'q1': 31.0,\n", + " 'average': 30.67},\n", + " {'lower': 29.0,\n", + " 'median': 37.0,\n", + " 'q1': 35.0,\n", + " 'q3': 39.0,\n", + " 'average': 35.995,\n", + " 'upper': 45.0,\n", + " 'pos': 65}]}" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pb.base_sequence_quality(\"example.csv\")" + ] + }, + { + "cell_type": "markdown", + "id": "5ab1da41", + "metadata": {}, + "source": [ + "#### Usage example - .parquet file" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "a2cb9c97", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'base_quality_warn': 'pass',\n", + " 'base_per_pos_data': [{'average': 35.69,\n", + " 'median': 37.0,\n", + " 'q1': 35.0,\n", + " 'lower': 32.0,\n", + " 'upper': 40.0,\n", + " 'q3': 37.0,\n", + " 'pos': 3},\n", + " {'pos': 39,\n", + " 'average': 37.895,\n", + " 'q3': 40.0,\n", + " 'lower': 35.0,\n", + " 'median': 40.0,\n", + " 'q1': 38.0,\n", + " 'upper': 43.0},\n", + " {'pos': 20,\n", + " 'average': 38.625,\n", + " 'q3': 41.0,\n", + " 'median': 40.0,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'q1': 38.0},\n", + " {'pos': 28,\n", + " 'q1': 38.0,\n", + " 'average': 38.445,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'q3': 41.0,\n", + " 'median': 40.0},\n", + " {'pos': 49,\n", + " 'average': 37.21,\n", + " 'q1': 36.0,\n", + " 'q3': 40.0,\n", + " 'lower': 30.0,\n", + " 'median': 39.0,\n", + " 'upper': 46.0},\n", + " {'q1': 35.0,\n", + " 'pos': 59,\n", + " 'upper': 47.5,\n", + " 'median': 38.0,\n", + " 'average': 36.08,\n", + " 'lower': 27.5,\n", + " 'q3': 40.0},\n", + " {'pos': 67,\n", + " 'average': 35.96,\n", + " 'lower': 26.5,\n", + " 'q1': 34.0,\n", + " 'upper': 46.5,\n", + " 'q3': 39.0,\n", + " 'median': 36.5},\n", + " {'average': 37.45,\n", + " 'median': 40.0,\n", + " 'q3': 41.0,\n", + " 'q1': 36.0,\n", + " 'lower': 28.5,\n", + " 'pos': 45,\n", + " 'upper': 48.5},\n", + " {'lower': 35.0,\n", + " 'q3': 40.0,\n", + " 'average': 38.0,\n", + " 'pos': 37,\n", + " 'median': 40.0,\n", + " 'q1': 38.0,\n", + " 'upper': 43.0},\n", + " {'pos': 22,\n", + " 'average': 38.41,\n", + " 'median': 40.0,\n", + " 'q3': 41.0,\n", + " 'q1': 38.0,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5},\n", + " {'pos': 15,\n", + " 'average': 38.725,\n", + " 'q3': 41.0,\n", + " 'lower': 33.5,\n", + " 'q1': 38.0,\n", + " 'upper': 45.5,\n", + " 'median': 40.0},\n", + " {'q3': 41.0,\n", + " 'lower': 33.5,\n", + " 'pos': 19,\n", + " 'upper': 45.5,\n", + " 'average': 38.425,\n", + " 'median': 40.0,\n", + " 'q1': 38.0},\n", + " {'median': 35.0,\n", + " 'pos': 74,\n", + " 'q3': 37.0,\n", + " 'average': 30.83,\n", + " 'upper': 44.5,\n", + " 'q1': 32.0,\n", + " 'lower': 24.5},\n", + " {'q3': 37.0,\n", + " 'pos': 76,\n", + " 'q1': 31.0,\n", + " 'upper': 46.0,\n", + " 'average': 30.265,\n", + " 'median': 35.0,\n", + " 'lower': 22.0},\n", + " {'pos': 31,\n", + " 'average': 38.795,\n", + " 'median': 40.0,\n", + " 'q3': 41.0,\n", + " 'lower': 33.5,\n", + " 'q1': 38.0,\n", + " 'upper': 45.5},\n", + " {'pos': 23,\n", + " 'average': 38.635,\n", + " 'median': 40.0,\n", + " 'q3': 41.0,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'q1': 38.0},\n", + " {'q3': 41.0,\n", + " 'median': 39.0,\n", + " 'upper': 48.5,\n", + " 'pos': 51,\n", + " 'q1': 36.0,\n", + " 'lower': 28.5,\n", + " 'average': 37.53},\n", + " {'upper': 40.0,\n", + " 'median': 37.0,\n", + " 'average': 35.68,\n", + " 'q1': 35.0,\n", + " 'q3': 37.0,\n", + " 'pos': 4,\n", + " 'lower': 32.0},\n", + " {'average': 32.46,\n", + " 'upper': 42.0,\n", + " 'median': 35.0,\n", + " 'q1': 32.0,\n", + " 'pos': 79,\n", + " 'q3': 36.0,\n", + " 'lower': 26.0},\n", + " {'average': 32.61,\n", + " 'q1': 32.0,\n", + " 'pos': 80,\n", + " 'median': 35.0,\n", + " 'q3': 36.0,\n", + " 'upper': 42.0,\n", + " 'lower': 26.0},\n", + " {'q1': 35.0,\n", + " 'median': 38.0,\n", + " 'q3': 40.0,\n", + " 'upper': 47.5,\n", + " 'lower': 27.5,\n", + " 'pos': 58,\n", + " 'average': 36.77},\n", + " {'average': 32.68,\n", + " 'median': 35.0,\n", + " 'lower': 27.0,\n", + " 'q1': 33.0,\n", + " 'q3': 37.0,\n", + " 'upper': 43.0,\n", + " 'pos': 73},\n", + " {'median': 34.0,\n", + " 'pos': 97,\n", + " 'q1': 31.0,\n", + " 'upper': 41.0,\n", + " 'q3': 35.0,\n", + " 'lower': 25.0,\n", + " 'average': 30.67},\n", + " {'median': 34.0,\n", + " 'lower': 27.5,\n", + " 'upper': 39.5,\n", + " 'average': 31.55,\n", + " 'pos': 98,\n", + " 'q3': 35.0,\n", + " 'q1': 32.0},\n", + " {'upper': 42.0,\n", + " 'median': 39.0,\n", + " 'pos': 8,\n", + " 'q1': 37.0,\n", + " 'q3': 39.0,\n", + " 'lower': 34.0,\n", + " 'average': 37.625},\n", + " {'q1': 38.0,\n", + " 'pos': 29,\n", + " 'lower': 33.5,\n", + " 'average': 38.595,\n", + " 'q3': 41.0,\n", + " 'median': 40.0,\n", + " 'upper': 45.5},\n", + " {'pos': 38,\n", + " 'q3': 41.0,\n", + " 'average': 37.64,\n", + " 'median': 40.0,\n", + " 'upper': 45.5,\n", + " 'q1': 38.0,\n", + " 'lower': 33.5},\n", + " {'q3': 41.0,\n", + " 'pos': 18,\n", + " 'q1': 38.0,\n", + " 'average': 38.47,\n", + " 'median': 40.0,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5},\n", + " {'lower': 30.0,\n", + " 'average': 37.35,\n", + " 'q1': 36.0,\n", + " 'q3': 40.0,\n", + " 'upper': 46.0,\n", + " 'pos': 57,\n", + " 'median': 39.0},\n", + " {'q3': 34.0,\n", + " 'upper': 38.5,\n", + " 'q1': 31.0,\n", + " 'average': 30.135,\n", + " 'lower': 26.5,\n", + " 'pos': 0,\n", + " 'median': 33.0},\n", + " {'pos': 71,\n", + " 'q3': 38.0,\n", + " 'lower': 25.5,\n", + " 'upper': 45.5,\n", + " 'average': 33.005,\n", + " 'median': 35.0,\n", + " 'q1': 33.0},\n", + " {'upper': 39.5,\n", + " 'q3': 35.0,\n", + " 'q1': 32.0,\n", + " 'lower': 27.5,\n", + " 'average': 32.665,\n", + " 'pos': 91,\n", + " 'median': 35.0},\n", + " {'q3': 35.0,\n", + " 'pos': 89,\n", + " 'upper': 38.0,\n", + " 'q1': 33.0,\n", + " 'lower': 30.0,\n", + " 'median': 35.0,\n", + " 'average': 32.44},\n", + " {'median': 39.5,\n", + " 'q1': 36.0,\n", + " 'average': 37.59,\n", + " 'pos': 54,\n", + " 'q3': 41.0,\n", + " 'lower': 28.5,\n", + " 'upper': 48.5},\n", + " {'median': 35.0,\n", + " 'pos': 82,\n", + " 'q3': 36.0,\n", + " 'q1': 33.0,\n", + " 'lower': 28.5,\n", + " 'upper': 40.5,\n", + " 'average': 31.525},\n", + " {'pos': 85,\n", + " 'lower': 30.0,\n", + " 'q3': 35.0,\n", + " 'upper': 38.0,\n", + " 'average': 32.195,\n", + " 'median': 35.0,\n", + " 'q1': 33.0},\n", + " {'lower': 30.0,\n", + " 'pos': 83,\n", + " 'upper': 38.0,\n", + " 'median': 35.0,\n", + " 'q1': 33.0,\n", + " 'average': 32.03,\n", + " 'q3': 35.0},\n", + " {'median': 35.0,\n", + " 'q1': 32.0,\n", + " 'q3': 35.0,\n", + " 'upper': 39.5,\n", + " 'average': 31.835,\n", + " 'lower': 27.5,\n", + " 'pos': 92},\n", + " {'average': 35.995,\n", + " 'lower': 29.0,\n", + " 'pos': 65,\n", + " 'median': 37.0,\n", + " 'q1': 35.0,\n", + " 'upper': 45.0,\n", + " 'q3': 39.0},\n", + " {'pos': 34,\n", + " 'q3': 41.0,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'q1': 38.0,\n", + " 'average': 38.205,\n", + " 'median': 40.0},\n", + " {'upper': 43.0,\n", + " 'median': 40.0,\n", + " 'q3': 40.0,\n", + " 'q1': 38.0,\n", + " 'pos': 43,\n", + " 'average': 37.775,\n", + " 'lower': 35.0},\n", + " {'pos': 68,\n", + " 'q3': 39.0,\n", + " 'lower': 26.5,\n", + " 'upper': 46.5,\n", + " 'q1': 34.0,\n", + " 'median': 36.0,\n", + " 'average': 35.91},\n", + " {'q3': 40.0,\n", + " 'median': 40.0,\n", + " 'lower': 35.0,\n", + " 'pos': 26,\n", + " 'q1': 38.0,\n", + " 'upper': 43.0,\n", + " 'average': 37.855},\n", + " {'median': 35.0,\n", + " 'pos': 70,\n", + " 'q3': 38.0,\n", + " 'lower': 28.0,\n", + " 'q1': 34.0,\n", + " 'upper': 44.0,\n", + " 'average': 33.565},\n", + " {'q1': 38.0,\n", + " 'q3': 41.0,\n", + " 'pos': 13,\n", + " 'median': 40.0,\n", + " 'lower': 33.5,\n", + " 'average': 38.94,\n", + " 'upper': 45.5},\n", + " {'pos': 88,\n", + " 'q1': 33.0,\n", + " 'q3': 35.0,\n", + " 'upper': 38.0,\n", + " 'average': 32.065,\n", + " 'lower': 30.0,\n", + " 'median': 35.0},\n", + " {'median': 34.5,\n", + " 'q1': 33.0,\n", + " 'q3': 35.0,\n", + " 'upper': 38.0,\n", + " 'average': 32.275,\n", + " 'pos': 90,\n", + " 'lower': 30.0},\n", + " {'q1': 30.0,\n", + " 'upper': 45.0,\n", + " 'q3': 36.0,\n", + " 'pos': 77,\n", + " 'average': 30.805,\n", + " 'median': 35.0,\n", + " 'lower': 21.0},\n", + " {'q1': 37.0,\n", + " 'median': 39.0,\n", + " 'average': 37.77,\n", + " 'upper': 44.5,\n", + " 'pos': 52,\n", + " 'q3': 40.0,\n", + " 'lower': 32.5},\n", + " {'average': 37.565,\n", + " 'q1': 37.0,\n", + " 'pos': 44,\n", + " 'lower': 31.0,\n", + " 'median': 40.0,\n", + " 'q3': 41.0,\n", + " 'upper': 47.0},\n", + " {'lower': 28.5,\n", + " 'average': 37.425,\n", + " 'median': 39.0,\n", + " 'q1': 36.0,\n", + " 'pos': 50,\n", + " 'upper': 48.5,\n", + " 'q3': 41.0},\n", + " {'upper': 46.0,\n", + " 'q1': 36.0,\n", + " 'lower': 30.0,\n", + " 'pos': 56,\n", + " 'average': 37.59,\n", + " 'median': 39.0,\n", + " 'q3': 40.0},\n", + " {'median': 38.0,\n", + " 'pos': 63,\n", + " 'lower': 27.5,\n", + " 'upper': 47.5,\n", + " 'q1': 35.0,\n", + " 'average': 36.25,\n", + " 'q3': 40.0},\n", + " {'lower': 31.0,\n", + " 'median': 39.0,\n", + " 'average': 37.665,\n", + " 'q1': 37.0,\n", + " 'q3': 41.0,\n", + " 'upper': 47.0,\n", + " 'pos': 47},\n", + " {'median': 39.0,\n", + " 'q3': 39.0,\n", + " 'q1': 37.0,\n", + " 'average': 37.675,\n", + " 'lower': 34.0,\n", + " 'pos': 10,\n", + " 'upper': 42.0},\n", + " {'average': 37.5,\n", + " 'q1': 37.0,\n", + " 'q3': 39.0,\n", + " 'lower': 34.0,\n", + " 'upper': 42.0,\n", + " 'pos': 12,\n", + " 'median': 39.0},\n", + " {'median': 40.0,\n", + " 'q3': 41.0,\n", + " 'q1': 38.0,\n", + " 'pos': 25,\n", + " 'average': 38.2,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5},\n", + " {'lower': 23.5,\n", + " 'pos': 78,\n", + " 'q1': 31.0,\n", + " 'upper': 43.5,\n", + " 'average': 31.46,\n", + " 'q3': 36.0,\n", + " 'median': 35.0},\n", + " {'q3': 35.0,\n", + " 'lower': 27.5,\n", + " 'upper': 39.5,\n", + " 'pos': 95,\n", + " 'q1': 32.0,\n", + " 'median': 34.0,\n", + " 'average': 31.425},\n", + " {'q3': 40.0,\n", + " 'upper': 47.5,\n", + " 'lower': 27.5,\n", + " 'average': 36.145,\n", + " 'pos': 62,\n", + " 'q1': 35.0,\n", + " 'median': 38.0},\n", + " {'pos': 21,\n", + " 'q3': 40.0,\n", + " 'median': 40.0,\n", + " 'lower': 35.0,\n", + " 'q1': 38.0,\n", + " 'average': 38.445,\n", + " 'upper': 43.0},\n", + " {'q1': 38.0,\n", + " 'lower': 35.0,\n", + " 'pos': 36,\n", + " 'q3': 40.0,\n", + " 'average': 38.11,\n", + " 'median': 40.0,\n", + " 'upper': 43.0},\n", + " {'lower': 27.5,\n", + " 'median': 38.0,\n", + " 'q1': 35.0,\n", + " 'average': 35.985,\n", + " 'upper': 47.5,\n", + " 'pos': 60,\n", + " 'q3': 40.0},\n", + " {'pos': 24,\n", + " 'average': 38.265,\n", + " 'q1': 38.0,\n", + " 'q3': 41.0,\n", + " 'upper': 45.5,\n", + " 'median': 40.0,\n", + " 'lower': 33.5},\n", + " {'q1': 37.0,\n", + " 'q3': 39.0,\n", + " 'median': 39.0,\n", + " 'lower': 34.0,\n", + " 'upper': 42.0,\n", + " 'average': 37.36,\n", + " 'pos': 9},\n", + " {'q1': 38.0,\n", + " 'q3': 40.0,\n", + " 'median': 40.0,\n", + " 'pos': 30,\n", + " 'average': 38.245,\n", + " 'lower': 35.0,\n", + " 'upper': 43.0},\n", + " {'average': 37.78,\n", + " 'q3': 40.0,\n", + " 'q1': 37.0,\n", + " 'lower': 32.5,\n", + " 'upper': 44.5,\n", + " 'pos': 42,\n", + " 'median': 40.0},\n", + " {'pos': 53,\n", + " 'q1': 37.0,\n", + " 'q3': 41.0,\n", + " 'lower': 31.0,\n", + " 'upper': 47.0,\n", + " 'median': 39.0,\n", + " 'average': 37.845},\n", + " {'q3': 37.0,\n", + " 'upper': 40.0,\n", + " 'median': 36.0,\n", + " 'average': 35.4,\n", + " 'q1': 35.0,\n", + " 'pos': 7,\n", + " 'lower': 32.0},\n", + " {'q1': 38.0,\n", + " 'upper': 45.5,\n", + " 'pos': 16,\n", + " 'q3': 41.0,\n", + " 'median': 40.0,\n", + " 'lower': 33.5,\n", + " 'average': 38.48},\n", + " {'pos': 72,\n", + " 'median': 35.0,\n", + " 'upper': 43.0,\n", + " 'average': 33.265,\n", + " 'q1': 33.0,\n", + " 'lower': 27.0,\n", + " 'q3': 37.0},\n", + " {'q1': 31.0,\n", + " 'lower': 22.0,\n", + " 'pos': 75,\n", + " 'average': 31.06,\n", + " 'q3': 37.0,\n", + " 'upper': 46.0,\n", + " 'median': 35.0},\n", + " {'average': 37.95,\n", + " 'median': 40.0,\n", + " 'q3': 40.0,\n", + " 'lower': 35.0,\n", + " 'pos': 40,\n", + " 'upper': 43.0,\n", + " 'q1': 38.0},\n", + " {'pos': 5,\n", + " 'median': 35.0,\n", + " 'q3': 37.0,\n", + " 'lower': 32.0,\n", + " 'upper': 40.0,\n", + " 'average': 35.095,\n", + " 'q1': 35.0},\n", + " {'upper': 40.0,\n", + " 'pos': 6,\n", + " 'median': 35.0,\n", + " 'average': 35.145,\n", + " 'q3': 37.0,\n", + " 'lower': 32.0,\n", + " 'q1': 35.0},\n", + " {'pos': 86,\n", + " 'q1': 33.0,\n", + " 'average': 31.815,\n", + " 'median': 35.0,\n", + " 'q3': 35.0,\n", + " 'lower': 30.0,\n", + " 'upper': 38.0},\n", + " {'lower': 30.0,\n", + " 'pos': 55,\n", + " 'average': 37.55,\n", + " 'q3': 40.0,\n", + " 'upper': 46.0,\n", + " 'median': 39.0,\n", + " 'q1': 36.0},\n", + " {'median': 34.0,\n", + " 'q1': 31.0,\n", + " 'q3': 34.0,\n", + " 'pos': 1,\n", + " 'lower': 26.5,\n", + " 'upper': 38.5,\n", + " 'average': 31.21},\n", + " {'q3': 41.0,\n", + " 'median': 40.0,\n", + " 'average': 38.44,\n", + " 'q1': 38.0,\n", + " 'pos': 27,\n", + " 'upper': 45.5,\n", + " 'lower': 33.5},\n", + " {'upper': 42.0,\n", + " 'average': 37.71,\n", + " 'lower': 34.0,\n", + " 'q3': 39.0,\n", + " 'pos': 11,\n", + " 'q1': 37.0,\n", + " 'median': 39.0},\n", + " {'median': 37.0,\n", + " 'pos': 66,\n", + " 'average': 35.875,\n", + " 'q3': 39.0,\n", + " 'q1': 35.0,\n", + " 'lower': 29.0,\n", + " 'upper': 45.0},\n", + " {'upper': 39.5,\n", + " 'q3': 35.0,\n", + " 'lower': 27.5,\n", + " 'average': 31.05,\n", + " 'median': 34.0,\n", + " 'pos': 93,\n", + " 'q1': 32.0},\n", + " {'median': 40.0,\n", + " 'q3': 41.0,\n", + " 'lower': 33.5,\n", + " 'pos': 32,\n", + " 'average': 38.29,\n", + " 'q1': 38.0,\n", + " 'upper': 45.5},\n", + " {'median': 36.0,\n", + " 'upper': 46.5,\n", + " 'q1': 34.0,\n", + " 'pos': 69,\n", + " 'q3': 39.0,\n", + " 'lower': 26.5,\n", + " 'average': 33.7},\n", + " {'lower': 33.5,\n", + " 'q3': 41.0,\n", + " 'upper': 45.5,\n", + " 'q1': 38.0,\n", + " 'pos': 14,\n", + " 'average': 38.965,\n", + " 'median': 40.0},\n", + " {'q1': 32.0,\n", + " 'median': 34.0,\n", + " 'average': 30.775,\n", + " 'q3': 35.0,\n", + " 'pos': 94,\n", + " 'lower': 27.5,\n", + " 'upper': 39.5},\n", + " {'q1': 37.0,\n", + " 'q3': 41.0,\n", + " 'lower': 31.0,\n", + " 'upper': 47.0,\n", + " 'average': 37.87,\n", + " 'pos': 41,\n", + " 'median': 40.0},\n", + " {'pos': 96,\n", + " 'q3': 35.0,\n", + " 'upper': 39.5,\n", + " 'q1': 32.0,\n", + " 'lower': 27.5,\n", + " 'median': 34.0,\n", + " 'average': 31.315},\n", + " {'pos': 17,\n", + " 'q1': 38.0,\n", + " 'median': 40.0,\n", + " 'upper': 45.5,\n", + " 'q3': 41.0,\n", + " 'lower': 33.5,\n", + " 'average': 38.505},\n", + " {'q3': 41.0,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'median': 40.0,\n", + " 'average': 38.245,\n", + " 'q1': 38.0,\n", + " 'pos': 33},\n", + " {'average': 36.095,\n", + " 'q1': 35.0,\n", + " 'lower': 27.5,\n", + " 'pos': 64,\n", + " 'q3': 40.0,\n", + " 'upper': 47.5,\n", + " 'median': 37.0},\n", + " {'pos': 35,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'average': 38.385,\n", + " 'median': 40.0,\n", + " 'q1': 38.0,\n", + " 'q3': 41.0},\n", + " {'lower': 28.5,\n", + " 'q1': 36.0,\n", + " 'pos': 48,\n", + " 'median': 40.0,\n", + " 'average': 37.61,\n", + " 'q3': 41.0,\n", + " 'upper': 48.5},\n", + " {'average': 31.915,\n", + " 'median': 35.0,\n", + " 'pos': 87,\n", + " 'q1': 32.0,\n", + " 'upper': 39.5,\n", + " 'lower': 27.5,\n", + " 'q3': 35.0},\n", + " {'upper': 47.5,\n", + " 'median': 38.0,\n", + " 'average': 35.99,\n", + " 'pos': 61,\n", + " 'q1': 35.0,\n", + " 'lower': 27.5,\n", + " 'q3': 40.0},\n", + " {'average': 37.79,\n", + " 'q3': 41.0,\n", + " 'lower': 31.0,\n", + " 'upper': 47.0,\n", + " 'q1': 37.0,\n", + " 'median': 39.5,\n", + " 'pos': 46},\n", + " {'q3': 36.0,\n", + " 'average': 32.76,\n", + " 'median': 35.0,\n", + " 'q1': 33.0,\n", + " 'upper': 40.5,\n", + " 'pos': 81,\n", + " 'lower': 28.5},\n", + " {'pos': 2,\n", + " 'average': 32.015,\n", + " 'median': 34.0,\n", + " 'q1': 31.0,\n", + " 'lower': 26.5,\n", + " 'upper': 38.5,\n", + " 'q3': 34.0},\n", + " {'lower': 27.5,\n", + " 'upper': 39.5,\n", + " 'median': 34.0,\n", + " 'average': 31.25,\n", + " 'q3': 35.0,\n", + " 'pos': 99,\n", + " 'q1': 32.0},\n", + " {'q1': 33.0,\n", + " 'average': 32.415,\n", + " 'lower': 30.0,\n", + " 'upper': 38.0,\n", + " 'pos': 84,\n", + " 'q3': 35.0,\n", + " 'median': 35.0},\n", + " {'upper': 41.0,\n", + " 'q3': 35.0,\n", + " 'pos': 100,\n", + " 'average': 31.105,\n", + " 'q1': 31.0,\n", + " 'lower': 25.0,\n", + " 'median': 34.0}]}" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pb.base_sequence_quality(\"example.parquet\")" + ] + }, + { + "cell_type": "markdown", + "id": "b519abbd", + "metadata": {}, + "source": [ + "#### Usage example - `polars.lazyframe.frame.LazyFrame` object" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "1899ca01", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:polars_bio:Table: example registered for path: ./example.fastq\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "200rows [00:00, 126946.25rows/s]\n" + ] + }, + { + "data": { + "text/plain": [ + "{'base_quality_warn': 'pass',\n", + " 'base_per_pos_data': [{'average': 38.505,\n", + " 'q3': 41.0,\n", + " 'lower': 33.5,\n", + " 'median': 40.0,\n", + " 'upper': 45.5,\n", + " 'pos': 17,\n", + " 'q1': 38.0},\n", + " {'median': 33.0,\n", + " 'average': 30.135,\n", + " 'lower': 26.5,\n", + " 'q1': 31.0,\n", + " 'q3': 34.0,\n", + " 'pos': 0,\n", + " 'upper': 38.5},\n", + " {'lower': 32.0,\n", + " 'upper': 40.0,\n", + " 'median': 35.0,\n", + " 'pos': 5,\n", + " 'average': 35.095,\n", + " 'q1': 35.0,\n", + " 'q3': 37.0},\n", + " {'pos': 20,\n", + " 'median': 40.0,\n", + " 'q1': 38.0,\n", + " 'q3': 41.0,\n", + " 'average': 38.625,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5},\n", + " {'pos': 10,\n", + " 'lower': 34.0,\n", + " 'q3': 39.0,\n", + " 'upper': 42.0,\n", + " 'average': 37.675,\n", + " 'q1': 37.0,\n", + " 'median': 39.0},\n", + " {'lower': 31.0,\n", + " 'average': 37.87,\n", + " 'upper': 47.0,\n", + " 'q1': 37.0,\n", + " 'pos': 41,\n", + " 'median': 40.0,\n", + " 'q3': 41.0},\n", + " {'pos': 56,\n", + " 'q1': 36.0,\n", + " 'lower': 30.0,\n", + " 'median': 39.0,\n", + " 'upper': 46.0,\n", + " 'q3': 40.0,\n", + " 'average': 37.59},\n", + " {'q1': 38.0,\n", + " 'upper': 43.0,\n", + " 'average': 37.855,\n", + " 'pos': 26,\n", + " 'median': 40.0,\n", + " 'lower': 35.0,\n", + " 'q3': 40.0},\n", + " {'average': 37.565,\n", + " 'pos': 44,\n", + " 'median': 40.0,\n", + " 'q3': 41.0,\n", + " 'lower': 31.0,\n", + " 'upper': 47.0,\n", + " 'q1': 37.0},\n", + " {'average': 37.59,\n", + " 'upper': 48.5,\n", + " 'pos': 54,\n", + " 'q1': 36.0,\n", + " 'lower': 28.5,\n", + " 'median': 39.5,\n", + " 'q3': 41.0},\n", + " {'median': 38.0,\n", + " 'q3': 40.0,\n", + " 'upper': 47.5,\n", + " 'lower': 27.5,\n", + " 'q1': 35.0,\n", + " 'pos': 58,\n", + " 'average': 36.77},\n", + " {'average': 36.08,\n", + " 'lower': 27.5,\n", + " 'pos': 59,\n", + " 'q1': 35.0,\n", + " 'q3': 40.0,\n", + " 'upper': 47.5,\n", + " 'median': 38.0},\n", + " {'average': 37.625,\n", + " 'median': 39.0,\n", + " 'pos': 8,\n", + " 'q1': 37.0,\n", + " 'q3': 39.0,\n", + " 'lower': 34.0,\n", + " 'upper': 42.0},\n", + " {'average': 38.205,\n", + " 'median': 40.0,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'pos': 34,\n", + " 'q1': 38.0,\n", + " 'q3': 41.0},\n", + " {'upper': 46.5,\n", + " 'pos': 67,\n", + " 'q1': 34.0,\n", + " 'q3': 39.0,\n", + " 'lower': 26.5,\n", + " 'average': 35.96,\n", + " 'median': 36.5},\n", + " {'upper': 44.5,\n", + " 'q1': 32.0,\n", + " 'pos': 74,\n", + " 'median': 35.0,\n", + " 'average': 30.83,\n", + " 'q3': 37.0,\n", + " 'lower': 24.5},\n", + " {'average': 31.46,\n", + " 'upper': 43.5,\n", + " 'pos': 78,\n", + " 'lower': 23.5,\n", + " 'median': 35.0,\n", + " 'q3': 36.0,\n", + " 'q1': 31.0},\n", + " {'pos': 28,\n", + " 'median': 40.0,\n", + " 'average': 38.445,\n", + " 'q1': 38.0,\n", + " 'q3': 41.0,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5},\n", + " {'pos': 32,\n", + " 'average': 38.29,\n", + " 'q3': 41.0,\n", + " 'upper': 45.5,\n", + " 'lower': 33.5,\n", + " 'q1': 38.0,\n", + " 'median': 40.0},\n", + " {'pos': 2,\n", + " 'median': 34.0,\n", + " 'q3': 34.0,\n", + " 'average': 32.015,\n", + " 'lower': 26.5,\n", + " 'upper': 38.5,\n", + " 'q1': 31.0},\n", + " {'lower': 30.0,\n", + " 'pos': 83,\n", + " 'median': 35.0,\n", + " 'q3': 35.0,\n", + " 'upper': 38.0,\n", + " 'average': 32.03,\n", + " 'q1': 33.0},\n", + " {'q3': 35.0,\n", + " 'average': 32.195,\n", + " 'median': 35.0,\n", + " 'lower': 30.0,\n", + " 'upper': 38.0,\n", + " 'pos': 85,\n", + " 'q1': 33.0},\n", + " {'q3': 38.0,\n", + " 'lower': 28.0,\n", + " 'upper': 44.0,\n", + " 'q1': 34.0,\n", + " 'median': 35.0,\n", + " 'average': 33.565,\n", + " 'pos': 70},\n", + " {'q1': 35.0,\n", + " 'lower': 27.5,\n", + " 'pos': 64,\n", + " 'q3': 40.0,\n", + " 'upper': 47.5,\n", + " 'median': 37.0,\n", + " 'average': 36.095},\n", + " {'median': 35.0,\n", + " 'q3': 35.0,\n", + " 'average': 32.665,\n", + " 'upper': 39.5,\n", + " 'pos': 91,\n", + " 'q1': 32.0,\n", + " 'lower': 27.5},\n", + " {'q3': 39.0,\n", + " 'median': 37.0,\n", + " 'q1': 35.0,\n", + " 'lower': 29.0,\n", + " 'upper': 45.0,\n", + " 'average': 35.995,\n", + " 'pos': 65},\n", + " {'q1': 33.0,\n", + " 'median': 35.0,\n", + " 'average': 32.76,\n", + " 'lower': 28.5,\n", + " 'upper': 40.5,\n", + " 'pos': 81,\n", + " 'q3': 36.0},\n", + " {'pos': 66,\n", + " 'median': 37.0,\n", + " 'q3': 39.0,\n", + " 'average': 35.875,\n", + " 'q1': 35.0,\n", + " 'lower': 29.0,\n", + " 'upper': 45.0},\n", + " {'upper': 42.0,\n", + " 'median': 35.0,\n", + " 'lower': 26.0,\n", + " 'average': 32.46,\n", + " 'pos': 79,\n", + " 'q1': 32.0,\n", + " 'q3': 36.0},\n", + " {'q3': 37.0,\n", + " 'pos': 7,\n", + " 'average': 35.4,\n", + " 'median': 36.0,\n", + " 'q1': 35.0,\n", + " 'lower': 32.0,\n", + " 'upper': 40.0},\n", + " {'q3': 40.0,\n", + " 'lower': 35.0,\n", + " 'q1': 38.0,\n", + " 'average': 38.245,\n", + " 'upper': 43.0,\n", + " 'pos': 30,\n", + " 'median': 40.0},\n", + " {'lower': 35.0,\n", + " 'q3': 40.0,\n", + " 'upper': 43.0,\n", + " 'average': 37.895,\n", + " 'q1': 38.0,\n", + " 'pos': 39,\n", + " 'median': 40.0},\n", + " {'q1': 36.0,\n", + " 'upper': 48.5,\n", + " 'average': 37.45,\n", + " 'q3': 41.0,\n", + " 'lower': 28.5,\n", + " 'median': 40.0,\n", + " 'pos': 45},\n", + " {'average': 37.21,\n", + " 'median': 39.0,\n", + " 'upper': 46.0,\n", + " 'lower': 30.0,\n", + " 'pos': 49,\n", + " 'q1': 36.0,\n", + " 'q3': 40.0},\n", + " {'median': 35.0,\n", + " 'q1': 33.0,\n", + " 'lower': 30.0,\n", + " 'pos': 86,\n", + " 'upper': 38.0,\n", + " 'average': 31.815,\n", + " 'q3': 35.0},\n", + " {'pos': 6,\n", + " 'q1': 35.0,\n", + " 'lower': 32.0,\n", + " 'q3': 37.0,\n", + " 'upper': 40.0,\n", + " 'average': 35.145,\n", + " 'median': 35.0},\n", + " {'q3': 40.0,\n", + " 'lower': 27.5,\n", + " 'pos': 60,\n", + " 'average': 35.985,\n", + " 'upper': 47.5,\n", + " 'median': 38.0,\n", + " 'q1': 35.0},\n", + " {'lower': 27.5,\n", + " 'average': 31.425,\n", + " 'q3': 35.0,\n", + " 'median': 34.0,\n", + " 'q1': 32.0,\n", + " 'pos': 95,\n", + " 'upper': 39.5},\n", + " {'median': 40.0,\n", + " 'pos': 13,\n", + " 'lower': 33.5,\n", + " 'q3': 41.0,\n", + " 'average': 38.94,\n", + " 'q1': 38.0,\n", + " 'upper': 45.5},\n", + " {'q1': 33.0,\n", + " 'upper': 38.0,\n", + " 'average': 32.275,\n", + " 'pos': 90,\n", + " 'q3': 35.0,\n", + " 'lower': 30.0,\n", + " 'median': 34.5},\n", + " {'upper': 45.5,\n", + " 'median': 40.0,\n", + " 'pos': 33,\n", + " 'average': 38.245,\n", + " 'q1': 38.0,\n", + " 'q3': 41.0,\n", + " 'lower': 33.5},\n", + " {'upper': 39.5,\n", + " 'pos': 87,\n", + " 'average': 31.915,\n", + " 'q1': 32.0,\n", + " 'median': 35.0,\n", + " 'q3': 35.0,\n", + " 'lower': 27.5},\n", + " {'pos': 42,\n", + " 'median': 40.0,\n", + " 'average': 37.78,\n", + " 'q3': 40.0,\n", + " 'lower': 32.5,\n", + " 'q1': 37.0,\n", + " 'upper': 44.5},\n", + " {'q3': 40.0,\n", + " 'pos': 63,\n", + " 'average': 36.25,\n", + " 'median': 38.0,\n", + " 'q1': 35.0,\n", + " 'lower': 27.5,\n", + " 'upper': 47.5},\n", + " {'q1': 36.0,\n", + " 'pos': 57,\n", + " 'median': 39.0,\n", + " 'q3': 40.0,\n", + " 'upper': 46.0,\n", + " 'average': 37.35,\n", + " 'lower': 30.0},\n", + " {'upper': 42.0,\n", + " 'average': 37.71,\n", + " 'q1': 37.0,\n", + " 'median': 39.0,\n", + " 'q3': 39.0,\n", + " 'lower': 34.0,\n", + " 'pos': 11},\n", + " {'upper': 45.5,\n", + " 'q1': 38.0,\n", + " 'lower': 33.5,\n", + " 'median': 40.0,\n", + " 'average': 38.425,\n", + " 'pos': 19,\n", + " 'q3': 41.0},\n", + " {'pos': 88,\n", + " 'upper': 38.0,\n", + " 'q1': 33.0,\n", + " 'average': 32.065,\n", + " 'median': 35.0,\n", + " 'q3': 35.0,\n", + " 'lower': 30.0},\n", + " {'upper': 39.5,\n", + " 'average': 31.315,\n", + " 'q1': 32.0,\n", + " 'pos': 96,\n", + " 'median': 34.0,\n", + " 'q3': 35.0,\n", + " 'lower': 27.5},\n", + " {'q3': 41.0,\n", + " 'lower': 28.5,\n", + " 'upper': 48.5,\n", + " 'average': 37.61,\n", + " 'median': 40.0,\n", + " 'pos': 48,\n", + " 'q1': 36.0},\n", + " {'q3': 37.0,\n", + " 'average': 35.68,\n", + " 'upper': 40.0,\n", + " 'lower': 32.0,\n", + " 'pos': 4,\n", + " 'median': 37.0,\n", + " 'q1': 35.0},\n", + " {'q1': 33.0,\n", + " 'pos': 89,\n", + " 'average': 32.44,\n", + " 'median': 35.0,\n", + " 'lower': 30.0,\n", + " 'upper': 38.0,\n", + " 'q3': 35.0},\n", + " {'q3': 39.0,\n", + " 'lower': 34.0,\n", + " 'average': 37.5,\n", + " 'median': 39.0,\n", + " 'q1': 37.0,\n", + " 'upper': 42.0,\n", + " 'pos': 12},\n", + " {'lower': 25.0,\n", + " 'q3': 35.0,\n", + " 'upper': 41.0,\n", + " 'pos': 97,\n", + " 'average': 30.67,\n", + " 'median': 34.0,\n", + " 'q1': 31.0},\n", + " {'q1': 38.0,\n", + " 'q3': 41.0,\n", + " 'pos': 27,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'median': 40.0,\n", + " 'average': 38.44},\n", + " {'lower': 31.0,\n", + " 'upper': 47.0,\n", + " 'average': 37.845,\n", + " 'q1': 37.0,\n", + " 'median': 39.0,\n", + " 'pos': 53,\n", + " 'q3': 41.0},\n", + " {'pos': 100,\n", + " 'q3': 35.0,\n", + " 'lower': 25.0,\n", + " 'average': 31.105,\n", + " 'upper': 41.0,\n", + " 'median': 34.0,\n", + " 'q1': 31.0},\n", + " {'q1': 37.0,\n", + " 'lower': 32.5,\n", + " 'upper': 44.5,\n", + " 'q3': 40.0,\n", + " 'pos': 52,\n", + " 'average': 37.77,\n", + " 'median': 39.0},\n", + " {'q3': 41.0,\n", + " 'pos': 24,\n", + " 'average': 38.265,\n", + " 'median': 40.0,\n", + " 'q1': 38.0,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5},\n", + " {'upper': 42.0,\n", + " 'median': 39.0,\n", + " 'q3': 39.0,\n", + " 'q1': 37.0,\n", + " 'average': 37.36,\n", + " 'pos': 9,\n", + " 'lower': 34.0},\n", + " {'pos': 15,\n", + " 'lower': 33.5,\n", + " 'median': 40.0,\n", + " 'upper': 45.5,\n", + " 'q3': 41.0,\n", + " 'average': 38.725,\n", + " 'q1': 38.0},\n", + " {'pos': 55,\n", + " 'average': 37.55,\n", + " 'lower': 30.0,\n", + " 'q1': 36.0,\n", + " 'median': 39.0,\n", + " 'q3': 40.0,\n", + " 'upper': 46.0},\n", + " {'median': 35.0,\n", + " 'q1': 31.0,\n", + " 'q3': 37.0,\n", + " 'pos': 75,\n", + " 'lower': 22.0,\n", + " 'upper': 46.0,\n", + " 'average': 31.06},\n", + " {'lower': 33.5,\n", + " 'pos': 29,\n", + " 'average': 38.595,\n", + " 'q3': 41.0,\n", + " 'upper': 45.5,\n", + " 'median': 40.0,\n", + " 'q1': 38.0},\n", + " {'q1': 34.0,\n", + " 'pos': 69,\n", + " 'lower': 26.5,\n", + " 'average': 33.7,\n", + " 'upper': 46.5,\n", + " 'median': 36.0,\n", + " 'q3': 39.0},\n", + " {'q3': 41.0,\n", + " 'average': 37.79,\n", + " 'lower': 31.0,\n", + " 'upper': 47.0,\n", + " 'pos': 46,\n", + " 'median': 39.5,\n", + " 'q1': 37.0},\n", + " {'upper': 39.5,\n", + " 'pos': 93,\n", + " 'average': 31.05,\n", + " 'q1': 32.0,\n", + " 'q3': 35.0,\n", + " 'median': 34.0,\n", + " 'lower': 27.5},\n", + " {'average': 37.775,\n", + " 'pos': 43,\n", + " 'q1': 38.0,\n", + " 'q3': 40.0,\n", + " 'lower': 35.0,\n", + " 'upper': 43.0,\n", + " 'median': 40.0},\n", + " {'q1': 38.0,\n", + " 'lower': 33.5,\n", + " 'pos': 23,\n", + " 'average': 38.635,\n", + " 'median': 40.0,\n", + " 'q3': 41.0,\n", + " 'upper': 45.5},\n", + " {'q3': 37.0,\n", + " 'median': 35.0,\n", + " 'pos': 73,\n", + " 'average': 32.68,\n", + " 'q1': 33.0,\n", + " 'lower': 27.0,\n", + " 'upper': 43.0},\n", + " {'q3': 41.0,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'pos': 14,\n", + " 'average': 38.965,\n", + " 'q1': 38.0,\n", + " 'median': 40.0},\n", + " {'median': 40.0,\n", + " 'q3': 40.0,\n", + " 'q1': 38.0,\n", + " 'pos': 37,\n", + " 'upper': 43.0,\n", + " 'lower': 35.0,\n", + " 'average': 38.0},\n", + " {'pos': 76,\n", + " 'median': 35.0,\n", + " 'lower': 22.0,\n", + " 'upper': 46.0,\n", + " 'q3': 37.0,\n", + " 'average': 30.265,\n", + " 'q1': 31.0},\n", + " {'q3': 36.0,\n", + " 'lower': 26.0,\n", + " 'upper': 42.0,\n", + " 'median': 35.0,\n", + " 'average': 32.61,\n", + " 'pos': 80,\n", + " 'q1': 32.0},\n", + " {'average': 37.665,\n", + " 'q3': 41.0,\n", + " 'pos': 47,\n", + " 'q1': 37.0,\n", + " 'lower': 31.0,\n", + " 'median': 39.0,\n", + " 'upper': 47.0},\n", + " {'average': 33.265,\n", + " 'median': 35.0,\n", + " 'pos': 72,\n", + " 'q1': 33.0,\n", + " 'q3': 37.0,\n", + " 'lower': 27.0,\n", + " 'upper': 43.0},\n", + " {'median': 40.0,\n", + " 'q1': 38.0,\n", + " 'lower': 33.5,\n", + " 'pos': 18,\n", + " 'upper': 45.5,\n", + " 'q3': 41.0,\n", + " 'average': 38.47},\n", + " {'q1': 33.0,\n", + " 'lower': 28.5,\n", + " 'pos': 82,\n", + " 'q3': 36.0,\n", + " 'upper': 40.5,\n", + " 'median': 35.0,\n", + " 'average': 31.525},\n", + " {'average': 35.69,\n", + " 'median': 37.0,\n", + " 'lower': 32.0,\n", + " 'pos': 3,\n", + " 'q3': 37.0,\n", + " 'upper': 40.0,\n", + " 'q1': 35.0},\n", + " {'average': 35.99,\n", + " 'q1': 35.0,\n", + " 'upper': 47.5,\n", + " 'q3': 40.0,\n", + " 'lower': 27.5,\n", + " 'pos': 61,\n", + " 'median': 38.0},\n", + " {'upper': 48.5,\n", + " 'lower': 28.5,\n", + " 'pos': 50,\n", + " 'q1': 36.0,\n", + " 'q3': 41.0,\n", + " 'median': 39.0,\n", + " 'average': 37.425},\n", + " {'average': 36.145,\n", + " 'upper': 47.5,\n", + " 'q3': 40.0,\n", + " 'pos': 62,\n", + " 'median': 38.0,\n", + " 'q1': 35.0,\n", + " 'lower': 27.5},\n", + " {'pos': 51,\n", + " 'average': 37.53,\n", + " 'lower': 28.5,\n", + " 'median': 39.0,\n", + " 'upper': 48.5,\n", + " 'q3': 41.0,\n", + " 'q1': 36.0},\n", + " {'upper': 43.0,\n", + " 'average': 37.95,\n", + " 'q1': 38.0,\n", + " 'median': 40.0,\n", + " 'lower': 35.0,\n", + " 'pos': 40,\n", + " 'q3': 40.0},\n", + " {'upper': 46.5,\n", + " 'average': 35.91,\n", + " 'q1': 34.0,\n", + " 'q3': 39.0,\n", + " 'lower': 26.5,\n", + " 'median': 36.0,\n", + " 'pos': 68},\n", + " {'median': 35.0,\n", + " 'q1': 30.0,\n", + " 'q3': 36.0,\n", + " 'lower': 21.0,\n", + " 'pos': 77,\n", + " 'average': 30.805,\n", + " 'upper': 45.0},\n", + " {'average': 33.005,\n", + " 'pos': 71,\n", + " 'q1': 33.0,\n", + " 'q3': 38.0,\n", + " 'lower': 25.5,\n", + " 'median': 35.0,\n", + " 'upper': 45.5},\n", + " {'q3': 35.0,\n", + " 'pos': 98,\n", + " 'average': 31.55,\n", + " 'lower': 27.5,\n", + " 'upper': 39.5,\n", + " 'median': 34.0,\n", + " 'q1': 32.0},\n", + " {'average': 31.25,\n", + " 'median': 34.0,\n", + " 'upper': 39.5,\n", + " 'pos': 99,\n", + " 'q1': 32.0,\n", + " 'q3': 35.0,\n", + " 'lower': 27.5},\n", + " {'q3': 41.0,\n", + " 'lower': 33.5,\n", + " 'median': 40.0,\n", + " 'upper': 45.5,\n", + " 'pos': 38,\n", + " 'average': 37.64,\n", + " 'q1': 38.0},\n", + " {'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'median': 40.0,\n", + " 'q1': 38.0,\n", + " 'pos': 25,\n", + " 'q3': 41.0,\n", + " 'average': 38.2},\n", + " {'q3': 41.0,\n", + " 'lower': 33.5,\n", + " 'median': 40.0,\n", + " 'pos': 31,\n", + " 'average': 38.795,\n", + " 'q1': 38.0,\n", + " 'upper': 45.5},\n", + " {'average': 38.385,\n", + " 'upper': 45.5,\n", + " 'q3': 41.0,\n", + " 'pos': 35,\n", + " 'median': 40.0,\n", + " 'lower': 33.5,\n", + " 'q1': 38.0},\n", + " {'q1': 33.0,\n", + " 'q3': 35.0,\n", + " 'pos': 84,\n", + " 'lower': 30.0,\n", + " 'median': 35.0,\n", + " 'upper': 38.0,\n", + " 'average': 32.415},\n", + " {'pos': 92,\n", + " 'median': 35.0,\n", + " 'upper': 39.5,\n", + " 'average': 31.835,\n", + " 'lower': 27.5,\n", + " 'q1': 32.0,\n", + " 'q3': 35.0},\n", + " {'q1': 32.0,\n", + " 'lower': 27.5,\n", + " 'median': 34.0,\n", + " 'pos': 94,\n", + " 'upper': 39.5,\n", + " 'average': 30.775,\n", + " 'q3': 35.0},\n", + " {'pos': 1,\n", + " 'median': 34.0,\n", + " 'q3': 34.0,\n", + " 'average': 31.21,\n", + " 'lower': 26.5,\n", + " 'q1': 31.0,\n", + " 'upper': 38.5},\n", + " {'upper': 45.5,\n", + " 'q1': 38.0,\n", + " 'average': 38.41,\n", + " 'median': 40.0,\n", + " 'lower': 33.5,\n", + " 'q3': 41.0,\n", + " 'pos': 22},\n", + " {'q3': 40.0,\n", + " 'lower': 35.0,\n", + " 'upper': 43.0,\n", + " 'pos': 36,\n", + " 'average': 38.11,\n", + " 'q1': 38.0,\n", + " 'median': 40.0},\n", + " {'lower': 35.0,\n", + " 'average': 38.445,\n", + " 'median': 40.0,\n", + " 'q1': 38.0,\n", + " 'q3': 40.0,\n", + " 'upper': 43.0,\n", + " 'pos': 21},\n", + " {'q1': 38.0,\n", + " 'pos': 16,\n", + " 'q3': 41.0,\n", + " 'average': 38.48,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'median': 40.0}]}" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a_lazyframe = pb.read_fastq(\"./example.fastq\")\n", + "print(type(a_lazyframe))\n", + "pb.base_sequence_quality(a_lazyframe)" + ] + }, + { + "cell_type": "markdown", + "id": "cdb4aad6", + "metadata": {}, + "source": [ + "#### Usage example - `polars.dataframe.frame.DataFrame` object" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "7830b8aa", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:polars_bio:Table: example registered for path: ./example.fastq\n", + "200rows [00:00, 80924.25rows/s]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + }, + { + "data": { + "text/plain": [ + "{'base_quality_warn': 'pass',\n", + " 'base_per_pos_data': [{'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'median': 40.0,\n", + " 'average': 38.265,\n", + " 'pos': 24,\n", + " 'q3': 41.0,\n", + " 'q1': 38.0},\n", + " {'median': 35.0,\n", + " 'average': 30.83,\n", + " 'pos': 74,\n", + " 'q1': 32.0,\n", + " 'lower': 24.5,\n", + " 'q3': 37.0,\n", + " 'upper': 44.5},\n", + " {'pos': 93,\n", + " 'upper': 39.5,\n", + " 'average': 31.05,\n", + " 'median': 34.0,\n", + " 'q1': 32.0,\n", + " 'q3': 35.0,\n", + " 'lower': 27.5},\n", + " {'q1': 37.0,\n", + " 'pos': 10,\n", + " 'q3': 39.0,\n", + " 'lower': 34.0,\n", + " 'upper': 42.0,\n", + " 'median': 39.0,\n", + " 'average': 37.675},\n", + " {'lower': 28.5,\n", + " 'upper': 48.5,\n", + " 'median': 39.0,\n", + " 'average': 37.425,\n", + " 'pos': 50,\n", + " 'q1': 36.0,\n", + " 'q3': 41.0},\n", + " {'q1': 36.0,\n", + " 'lower': 30.0,\n", + " 'pos': 55,\n", + " 'average': 37.55,\n", + " 'q3': 40.0,\n", + " 'upper': 46.0,\n", + " 'median': 39.0},\n", + " {'average': 32.195,\n", + " 'q1': 33.0,\n", + " 'q3': 35.0,\n", + " 'lower': 30.0,\n", + " 'pos': 85,\n", + " 'upper': 38.0,\n", + " 'median': 35.0},\n", + " {'pos': 91,\n", + " 'q1': 32.0,\n", + " 'upper': 39.5,\n", + " 'q3': 35.0,\n", + " 'average': 32.665,\n", + " 'lower': 27.5,\n", + " 'median': 35.0},\n", + " {'pos': 92,\n", + " 'q1': 32.0,\n", + " 'median': 35.0,\n", + " 'upper': 39.5,\n", + " 'q3': 35.0,\n", + " 'average': 31.835,\n", + " 'lower': 27.5},\n", + " {'lower': 31.0,\n", + " 'upper': 47.0,\n", + " 'q1': 37.0,\n", + " 'median': 39.5,\n", + " 'average': 37.79,\n", + " 'pos': 46,\n", + " 'q3': 41.0},\n", + " {'q3': 40.0,\n", + " 'q1': 36.0,\n", + " 'upper': 46.0,\n", + " 'pos': 57,\n", + " 'average': 37.35,\n", + " 'median': 39.0,\n", + " 'lower': 30.0},\n", + " {'pos': 66,\n", + " 'average': 35.875,\n", + " 'median': 37.0,\n", + " 'q1': 35.0,\n", + " 'q3': 39.0,\n", + " 'lower': 29.0,\n", + " 'upper': 45.0},\n", + " {'pos': 69,\n", + " 'q3': 39.0,\n", + " 'lower': 26.5,\n", + " 'average': 33.7,\n", + " 'upper': 46.5,\n", + " 'q1': 34.0,\n", + " 'median': 36.0},\n", + " {'median': 38.0,\n", + " 'pos': 59,\n", + " 'q3': 40.0,\n", + " 'average': 36.08,\n", + " 'lower': 27.5,\n", + " 'upper': 47.5,\n", + " 'q1': 35.0},\n", + " {'q3': 35.0,\n", + " 'lower': 27.5,\n", + " 'upper': 39.5,\n", + " 'q1': 32.0,\n", + " 'pos': 99,\n", + " 'average': 31.25,\n", + " 'median': 34.0},\n", + " {'upper': 43.0,\n", + " 'q3': 40.0,\n", + " 'pos': 39,\n", + " 'q1': 38.0,\n", + " 'average': 37.895,\n", + " 'median': 40.0,\n", + " 'lower': 35.0},\n", + " {'upper': 43.0,\n", + " 'average': 37.95,\n", + " 'q1': 38.0,\n", + " 'pos': 40,\n", + " 'q3': 40.0,\n", + " 'median': 40.0,\n", + " 'lower': 35.0},\n", + " {'pos': 28,\n", + " 'q3': 41.0,\n", + " 'median': 40.0,\n", + " 'lower': 33.5,\n", + " 'q1': 38.0,\n", + " 'upper': 45.5,\n", + " 'average': 38.445},\n", + " {'q1': 37.0,\n", + " 'q3': 39.0,\n", + " 'average': 37.5,\n", + " 'lower': 34.0,\n", + " 'upper': 42.0,\n", + " 'pos': 12,\n", + " 'median': 39.0},\n", + " {'q3': 41.0,\n", + " 'pos': 23,\n", + " 'upper': 45.5,\n", + " 'lower': 33.5,\n", + " 'q1': 38.0,\n", + " 'median': 40.0,\n", + " 'average': 38.635},\n", + " {'pos': 0,\n", + " 'average': 30.135,\n", + " 'median': 33.0,\n", + " 'q3': 34.0,\n", + " 'lower': 26.5,\n", + " 'upper': 38.5,\n", + " 'q1': 31.0},\n", + " {'lower': 34.0,\n", + " 'pos': 8,\n", + " 'upper': 42.0,\n", + " 'average': 37.625,\n", + " 'median': 39.0,\n", + " 'q1': 37.0,\n", + " 'q3': 39.0},\n", + " {'median': 40.0,\n", + " 'lower': 28.5,\n", + " 'pos': 48,\n", + " 'q3': 41.0,\n", + " 'q1': 36.0,\n", + " 'average': 37.61,\n", + " 'upper': 48.5},\n", + " {'q1': 33.0,\n", + " 'pos': 82,\n", + " 'median': 35.0,\n", + " 'q3': 36.0,\n", + " 'lower': 28.5,\n", + " 'average': 31.525,\n", + " 'upper': 40.5},\n", + " {'pos': 96,\n", + " 'average': 31.315,\n", + " 'median': 34.0,\n", + " 'q1': 32.0,\n", + " 'q3': 35.0,\n", + " 'lower': 27.5,\n", + " 'upper': 39.5},\n", + " {'upper': 47.0,\n", + " 'pos': 53,\n", + " 'median': 39.0,\n", + " 'average': 37.845,\n", + " 'q1': 37.0,\n", + " 'q3': 41.0,\n", + " 'lower': 31.0},\n", + " {'lower': 27.5,\n", + " 'upper': 47.5,\n", + " 'median': 38.0,\n", + " 'pos': 62,\n", + " 'q3': 40.0,\n", + " 'average': 36.145,\n", + " 'q1': 35.0},\n", + " {'upper': 38.0,\n", + " 'median': 34.5,\n", + " 'average': 32.275,\n", + " 'q3': 35.0,\n", + " 'pos': 90,\n", + " 'q1': 33.0,\n", + " 'lower': 30.0},\n", + " {'q1': 35.0,\n", + " 'average': 35.145,\n", + " 'pos': 6,\n", + " 'q3': 37.0,\n", + " 'lower': 32.0,\n", + " 'upper': 40.0,\n", + " 'median': 35.0},\n", + " {'lower': 35.0,\n", + " 'upper': 43.0,\n", + " 'average': 38.245,\n", + " 'pos': 30,\n", + " 'q3': 40.0,\n", + " 'median': 40.0,\n", + " 'q1': 38.0},\n", + " {'q1': 38.0,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'q3': 41.0,\n", + " 'average': 38.725,\n", + " 'median': 40.0,\n", + " 'pos': 15},\n", + " {'median': 40.0,\n", + " 'upper': 45.5,\n", + " 'average': 38.245,\n", + " 'pos': 33,\n", + " 'q1': 38.0,\n", + " 'q3': 41.0,\n", + " 'lower': 33.5},\n", + " {'pos': 42,\n", + " 'average': 37.78,\n", + " 'median': 40.0,\n", + " 'q1': 37.0,\n", + " 'lower': 32.5,\n", + " 'upper': 44.5,\n", + " 'q3': 40.0},\n", + " {'pos': 44,\n", + " 'upper': 47.0,\n", + " 'q1': 37.0,\n", + " 'average': 37.565,\n", + " 'q3': 41.0,\n", + " 'median': 40.0,\n", + " 'lower': 31.0},\n", + " {'q3': 41.0,\n", + " 'upper': 48.5,\n", + " 'lower': 28.5,\n", + " 'average': 37.59,\n", + " 'median': 39.5,\n", + " 'q1': 36.0,\n", + " 'pos': 54},\n", + " {'average': 32.68,\n", + " 'pos': 73,\n", + " 'median': 35.0,\n", + " 'q1': 33.0,\n", + " 'q3': 37.0,\n", + " 'lower': 27.0,\n", + " 'upper': 43.0},\n", + " {'pos': 37,\n", + " 'average': 38.0,\n", + " 'q1': 38.0,\n", + " 'median': 40.0,\n", + " 'q3': 40.0,\n", + " 'lower': 35.0,\n", + " 'upper': 43.0},\n", + " {'average': 38.625,\n", + " 'q1': 38.0,\n", + " 'upper': 45.5,\n", + " 'lower': 33.5,\n", + " 'pos': 20,\n", + " 'q3': 41.0,\n", + " 'median': 40.0},\n", + " {'q3': 41.0,\n", + " 'lower': 31.0,\n", + " 'upper': 47.0,\n", + " 'pos': 47,\n", + " 'median': 39.0,\n", + " 'q1': 37.0,\n", + " 'average': 37.665},\n", + " {'average': 32.44,\n", + " 'lower': 30.0,\n", + " 'q1': 33.0,\n", + " 'upper': 38.0,\n", + " 'pos': 89,\n", + " 'median': 35.0,\n", + " 'q3': 35.0},\n", + " {'upper': 43.5,\n", + " 'q3': 36.0,\n", + " 'average': 31.46,\n", + " 'median': 35.0,\n", + " 'pos': 78,\n", + " 'q1': 31.0,\n", + " 'lower': 23.5},\n", + " {'upper': 40.0,\n", + " 'q3': 37.0,\n", + " 'median': 36.0,\n", + " 'average': 35.4,\n", + " 'q1': 35.0,\n", + " 'pos': 7,\n", + " 'lower': 32.0},\n", + " {'median': 39.0,\n", + " 'pos': 9,\n", + " 'average': 37.36,\n", + " 'q1': 37.0,\n", + " 'q3': 39.0,\n", + " 'lower': 34.0,\n", + " 'upper': 42.0},\n", + " {'upper': 48.5,\n", + " 'pos': 51,\n", + " 'q1': 36.0,\n", + " 'average': 37.53,\n", + " 'median': 39.0,\n", + " 'lower': 28.5,\n", + " 'q3': 41.0},\n", + " {'median': 34.0,\n", + " 'lower': 25.0,\n", + " 'pos': 97,\n", + " 'upper': 41.0,\n", + " 'q1': 31.0,\n", + " 'q3': 35.0,\n", + " 'average': 30.67},\n", + " {'q1': 38.0,\n", + " 'q3': 40.0,\n", + " 'lower': 35.0,\n", + " 'upper': 43.0,\n", + " 'pos': 26,\n", + " 'average': 37.855,\n", + " 'median': 40.0},\n", + " {'pos': 76,\n", + " 'median': 35.0,\n", + " 'q3': 37.0,\n", + " 'lower': 22.0,\n", + " 'upper': 46.0,\n", + " 'average': 30.265,\n", + " 'q1': 31.0},\n", + " {'q3': 36.0,\n", + " 'lower': 26.0,\n", + " 'pos': 80,\n", + " 'average': 32.61,\n", + " 'upper': 42.0,\n", + " 'median': 35.0,\n", + " 'q1': 32.0},\n", + " {'q1': 38.0,\n", + " 'lower': 33.5,\n", + " 'q3': 41.0,\n", + " 'median': 40.0,\n", + " 'average': 38.47,\n", + " 'upper': 45.5,\n", + " 'pos': 18},\n", + " {'pos': 35,\n", + " 'median': 40.0,\n", + " 'q1': 38.0,\n", + " 'q3': 41.0,\n", + " 'average': 38.385,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5},\n", + " {'upper': 38.0,\n", + " 'lower': 30.0,\n", + " 'average': 32.03,\n", + " 'q3': 35.0,\n", + " 'pos': 83,\n", + " 'median': 35.0,\n", + " 'q1': 33.0},\n", + " {'pos': 31,\n", + " 'median': 40.0,\n", + " 'q3': 41.0,\n", + " 'average': 38.795,\n", + " 'q1': 38.0,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5},\n", + " {'pos': 3,\n", + " 'median': 37.0,\n", + " 'upper': 40.0,\n", + " 'average': 35.69,\n", + " 'lower': 32.0,\n", + " 'q3': 37.0,\n", + " 'q1': 35.0},\n", + " {'pos': 56,\n", + " 'average': 37.59,\n", + " 'q1': 36.0,\n", + " 'q3': 40.0,\n", + " 'lower': 30.0,\n", + " 'median': 39.0,\n", + " 'upper': 46.0},\n", + " {'upper': 47.5,\n", + " 'pos': 58,\n", + " 'average': 36.77,\n", + " 'median': 38.0,\n", + " 'q1': 35.0,\n", + " 'q3': 40.0,\n", + " 'lower': 27.5},\n", + " {'q3': 40.0,\n", + " 'average': 35.99,\n", + " 'lower': 27.5,\n", + " 'upper': 47.5,\n", + " 'pos': 61,\n", + " 'median': 38.0,\n", + " 'q1': 35.0},\n", + " {'median': 37.0,\n", + " 'q1': 35.0,\n", + " 'average': 36.095,\n", + " 'q3': 40.0,\n", + " 'upper': 47.5,\n", + " 'lower': 27.5,\n", + " 'pos': 64},\n", + " {'q3': 37.0,\n", + " 'pos': 5,\n", + " 'lower': 32.0,\n", + " 'median': 35.0,\n", + " 'average': 35.095,\n", + " 'q1': 35.0,\n", + " 'upper': 40.0},\n", + " {'q1': 34.0,\n", + " 'pos': 68,\n", + " 'lower': 26.5,\n", + " 'q3': 39.0,\n", + " 'average': 35.91,\n", + " 'upper': 46.5,\n", + " 'median': 36.0},\n", + " {'pos': 87,\n", + " 'q1': 32.0,\n", + " 'lower': 27.5,\n", + " 'average': 31.915,\n", + " 'upper': 39.5,\n", + " 'q3': 35.0,\n", + " 'median': 35.0},\n", + " {'lower': 27.5,\n", + " 'upper': 39.5,\n", + " 'median': 34.0,\n", + " 'pos': 95,\n", + " 'q1': 32.0,\n", + " 'q3': 35.0,\n", + " 'average': 31.425},\n", + " {'average': 38.94,\n", + " 'q3': 41.0,\n", + " 'upper': 45.5,\n", + " 'pos': 13,\n", + " 'median': 40.0,\n", + " 'lower': 33.5,\n", + " 'q1': 38.0},\n", + " {'upper': 45.5,\n", + " 'median': 40.0,\n", + " 'q3': 41.0,\n", + " 'pos': 22,\n", + " 'lower': 33.5,\n", + " 'q1': 38.0,\n", + " 'average': 38.41},\n", + " {'pos': 70,\n", + " 'q3': 38.0,\n", + " 'average': 33.565,\n", + " 'q1': 34.0,\n", + " 'lower': 28.0,\n", + " 'median': 35.0,\n", + " 'upper': 44.0},\n", + " {'pos': 45,\n", + " 'q1': 36.0,\n", + " 'median': 40.0,\n", + " 'q3': 41.0,\n", + " 'lower': 28.5,\n", + " 'upper': 48.5,\n", + " 'average': 37.45},\n", + " {'upper': 46.0,\n", + " 'average': 31.06,\n", + " 'median': 35.0,\n", + " 'pos': 75,\n", + " 'q1': 31.0,\n", + " 'q3': 37.0,\n", + " 'lower': 22.0},\n", + " {'pos': 94,\n", + " 'median': 34.0,\n", + " 'q1': 32.0,\n", + " 'q3': 35.0,\n", + " 'average': 30.775,\n", + " 'lower': 27.5,\n", + " 'upper': 39.5},\n", + " {'median': 40.0,\n", + " 'upper': 43.0,\n", + " 'pos': 21,\n", + " 'q1': 38.0,\n", + " 'q3': 40.0,\n", + " 'lower': 35.0,\n", + " 'average': 38.445},\n", + " {'upper': 45.5,\n", + " 'median': 40.0,\n", + " 'pos': 16,\n", + " 'average': 38.48,\n", + " 'q1': 38.0,\n", + " 'q3': 41.0,\n", + " 'lower': 33.5},\n", + " {'average': 38.11,\n", + " 'median': 40.0,\n", + " 'lower': 35.0,\n", + " 'q1': 38.0,\n", + " 'upper': 43.0,\n", + " 'q3': 40.0,\n", + " 'pos': 36},\n", + " {'lower': 27.0,\n", + " 'average': 33.265,\n", + " 'median': 35.0,\n", + " 'q3': 37.0,\n", + " 'upper': 43.0,\n", + " 'pos': 72,\n", + " 'q1': 33.0},\n", + " {'average': 32.065,\n", + " 'q3': 35.0,\n", + " 'lower': 30.0,\n", + " 'pos': 88,\n", + " 'upper': 38.0,\n", + " 'median': 35.0,\n", + " 'q1': 33.0},\n", + " {'upper': 47.0,\n", + " 'q3': 41.0,\n", + " 'pos': 41,\n", + " 'q1': 37.0,\n", + " 'median': 40.0,\n", + " 'lower': 31.0,\n", + " 'average': 37.87},\n", + " {'pos': 43,\n", + " 'upper': 43.0,\n", + " 'q1': 38.0,\n", + " 'lower': 35.0,\n", + " 'median': 40.0,\n", + " 'q3': 40.0,\n", + " 'average': 37.775},\n", + " {'pos': 100,\n", + " 'average': 31.105,\n", + " 'q1': 31.0,\n", + " 'median': 34.0,\n", + " 'upper': 41.0,\n", + " 'q3': 35.0,\n", + " 'lower': 25.0},\n", + " {'pos': 32,\n", + " 'q3': 41.0,\n", + " 'lower': 33.5,\n", + " 'median': 40.0,\n", + " 'average': 38.29,\n", + " 'upper': 45.5,\n", + " 'q1': 38.0},\n", + " {'average': 37.64,\n", + " 'pos': 38,\n", + " 'q1': 38.0,\n", + " 'q3': 41.0,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'median': 40.0},\n", + " {'pos': 67,\n", + " 'median': 36.5,\n", + " 'q1': 34.0,\n", + " 'q3': 39.0,\n", + " 'lower': 26.5,\n", + " 'upper': 46.5,\n", + " 'average': 35.96},\n", + " {'q1': 38.0,\n", + " 'q3': 41.0,\n", + " 'median': 40.0,\n", + " 'average': 38.205,\n", + " 'pos': 34,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5},\n", + " {'upper': 38.0,\n", + " 'q3': 35.0,\n", + " 'q1': 33.0,\n", + " 'average': 32.415,\n", + " 'pos': 84,\n", + " 'median': 35.0,\n", + " 'lower': 30.0},\n", + " {'upper': 40.0,\n", + " 'pos': 4,\n", + " 'average': 35.68,\n", + " 'q1': 35.0,\n", + " 'median': 37.0,\n", + " 'q3': 37.0,\n", + " 'lower': 32.0},\n", + " {'q3': 41.0,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'pos': 27,\n", + " 'average': 38.44,\n", + " 'median': 40.0,\n", + " 'q1': 38.0},\n", + " {'lower': 30.0,\n", + " 'average': 37.21,\n", + " 'q3': 40.0,\n", + " 'pos': 49,\n", + " 'upper': 46.0,\n", + " 'median': 39.0,\n", + " 'q1': 36.0},\n", + " {'q3': 39.0,\n", + " 'upper': 45.0,\n", + " 'average': 35.995,\n", + " 'lower': 29.0,\n", + " 'q1': 35.0,\n", + " 'pos': 65,\n", + " 'median': 37.0},\n", + " {'upper': 40.5,\n", + " 'average': 32.76,\n", + " 'q1': 33.0,\n", + " 'q3': 36.0,\n", + " 'median': 35.0,\n", + " 'pos': 81,\n", + " 'lower': 28.5},\n", + " {'pos': 17,\n", + " 'q3': 41.0,\n", + " 'upper': 45.5,\n", + " 'lower': 33.5,\n", + " 'average': 38.505,\n", + " 'q1': 38.0,\n", + " 'median': 40.0},\n", + " {'lower': 33.5,\n", + " 'pos': 25,\n", + " 'upper': 45.5,\n", + " 'average': 38.2,\n", + " 'median': 40.0,\n", + " 'q3': 41.0,\n", + " 'q1': 38.0},\n", + " {'upper': 45.5,\n", + " 'q3': 38.0,\n", + " 'pos': 71,\n", + " 'average': 33.005,\n", + " 'q1': 33.0,\n", + " 'lower': 25.5,\n", + " 'median': 35.0},\n", + " {'pos': 14,\n", + " 'average': 38.965,\n", + " 'q1': 38.0,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'q3': 41.0,\n", + " 'median': 40.0},\n", + " {'q1': 31.0,\n", + " 'upper': 38.5,\n", + " 'q3': 34.0,\n", + " 'lower': 26.5,\n", + " 'median': 34.0,\n", + " 'average': 31.21,\n", + " 'pos': 1},\n", + " {'lower': 27.5,\n", + " 'upper': 47.5,\n", + " 'q3': 40.0,\n", + " 'median': 38.0,\n", + " 'q1': 35.0,\n", + " 'pos': 63,\n", + " 'average': 36.25},\n", + " {'average': 30.805,\n", + " 'q1': 30.0,\n", + " 'lower': 21.0,\n", + " 'upper': 45.0,\n", + " 'pos': 77,\n", + " 'median': 35.0,\n", + " 'q3': 36.0},\n", + " {'q1': 32.0,\n", + " 'pos': 79,\n", + " 'median': 35.0,\n", + " 'q3': 36.0,\n", + " 'average': 32.46,\n", + " 'lower': 26.0,\n", + " 'upper': 42.0},\n", + " {'average': 32.015,\n", + " 'q1': 31.0,\n", + " 'lower': 26.5,\n", + " 'pos': 2,\n", + " 'q3': 34.0,\n", + " 'upper': 38.5,\n", + " 'median': 34.0},\n", + " {'upper': 44.5,\n", + " 'lower': 32.5,\n", + " 'q1': 37.0,\n", + " 'pos': 52,\n", + " 'median': 39.0,\n", + " 'average': 37.77,\n", + " 'q3': 40.0},\n", + " {'average': 35.985,\n", + " 'pos': 60,\n", + " 'q1': 35.0,\n", + " 'lower': 27.5,\n", + " 'upper': 47.5,\n", + " 'q3': 40.0,\n", + " 'median': 38.0},\n", + " {'lower': 30.0,\n", + " 'average': 31.815,\n", + " 'median': 35.0,\n", + " 'upper': 38.0,\n", + " 'pos': 86,\n", + " 'q1': 33.0,\n", + " 'q3': 35.0},\n", + " {'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'q1': 38.0,\n", + " 'pos': 29,\n", + " 'median': 40.0,\n", + " 'q3': 41.0,\n", + " 'average': 38.595},\n", + " {'average': 31.55,\n", + " 'median': 34.0,\n", + " 'q1': 32.0,\n", + " 'upper': 39.5,\n", + " 'pos': 98,\n", + " 'lower': 27.5,\n", + " 'q3': 35.0},\n", + " {'q3': 41.0,\n", + " 'median': 40.0,\n", + " 'q1': 38.0,\n", + " 'lower': 33.5,\n", + " 'pos': 19,\n", + " 'upper': 45.5,\n", + " 'average': 38.425},\n", + " {'pos': 11,\n", + " 'average': 37.71,\n", + " 'median': 39.0,\n", + " 'q1': 37.0,\n", + " 'q3': 39.0,\n", + " 'lower': 34.0,\n", + " 'upper': 42.0}]}" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a_lazyframe = pb.read_fastq(\"./example.fastq\")\n", + "a_dataframe = a_lazyframe.collect()\n", + "print(type(a_dataframe))\n", + "pb.base_sequence_quality(a_dataframe)" + ] + }, + { + "cell_type": "markdown", + "id": "ddf5da9d", + "metadata": {}, + "source": [ + "#### Usage example - `pandas.core.frame.DataFrame` object" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "56817174", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:polars_bio:Table: example registered for path: ./example.fastq\n", + "200rows [00:00, 120508.66rows/s]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n" + ] + }, + { + "data": { + "text/plain": [ + "{'base_quality_warn': 'pass',\n", + " 'base_per_pos_data': [{'upper': 41.0,\n", + " 'q3': 35.0,\n", + " 'lower': 25.0,\n", + " 'pos': 97,\n", + " 'average': 30.67,\n", + " 'median': 34.0,\n", + " 'q1': 31.0},\n", + " {'q1': 38.0,\n", + " 'pos': 14,\n", + " 'average': 38.965,\n", + " 'lower': 33.5,\n", + " 'median': 40.0,\n", + " 'upper': 45.5,\n", + " 'q3': 41.0},\n", + " {'pos': 23,\n", + " 'upper': 45.5,\n", + " 'q1': 38.0,\n", + " 'q3': 41.0,\n", + " 'average': 38.635,\n", + " 'lower': 33.5,\n", + " 'median': 40.0},\n", + " {'q1': 37.0,\n", + " 'lower': 34.0,\n", + " 'average': 37.71,\n", + " 'upper': 42.0,\n", + " 'q3': 39.0,\n", + " 'median': 39.0,\n", + " 'pos': 11},\n", + " {'average': 38.425,\n", + " 'q1': 38.0,\n", + " 'q3': 41.0,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'median': 40.0,\n", + " 'pos': 19},\n", + " {'q3': 34.0,\n", + " 'upper': 38.5,\n", + " 'average': 32.015,\n", + " 'q1': 31.0,\n", + " 'lower': 26.5,\n", + " 'pos': 2,\n", + " 'median': 34.0},\n", + " {'upper': 48.5,\n", + " 'q1': 36.0,\n", + " 'average': 37.45,\n", + " 'median': 40.0,\n", + " 'pos': 45,\n", + " 'q3': 41.0,\n", + " 'lower': 28.5},\n", + " {'average': 37.61,\n", + " 'pos': 48,\n", + " 'median': 40.0,\n", + " 'q1': 36.0,\n", + " 'upper': 48.5,\n", + " 'q3': 41.0,\n", + " 'lower': 28.5},\n", + " {'q1': 38.0,\n", + " 'median': 40.0,\n", + " 'lower': 35.0,\n", + " 'pos': 37,\n", + " 'q3': 40.0,\n", + " 'upper': 43.0,\n", + " 'average': 38.0},\n", + " {'pos': 74,\n", + " 'median': 35.0,\n", + " 'q3': 37.0,\n", + " 'q1': 32.0,\n", + " 'average': 30.83,\n", + " 'lower': 24.5,\n", + " 'upper': 44.5},\n", + " {'average': 33.565,\n", + " 'pos': 70,\n", + " 'q1': 34.0,\n", + " 'q3': 38.0,\n", + " 'lower': 28.0,\n", + " 'upper': 44.0,\n", + " 'median': 35.0},\n", + " {'upper': 45.5,\n", + " 'pos': 31,\n", + " 'q3': 41.0,\n", + " 'median': 40.0,\n", + " 'q1': 38.0,\n", + " 'lower': 33.5,\n", + " 'average': 38.795},\n", + " {'average': 32.195,\n", + " 'median': 35.0,\n", + " 'upper': 38.0,\n", + " 'q1': 33.0,\n", + " 'q3': 35.0,\n", + " 'lower': 30.0,\n", + " 'pos': 85},\n", + " {'pos': 15,\n", + " 'upper': 45.5,\n", + " 'lower': 33.5,\n", + " 'median': 40.0,\n", + " 'q3': 41.0,\n", + " 'q1': 38.0,\n", + " 'average': 38.725},\n", + " {'q1': 32.0,\n", + " 'median': 35.0,\n", + " 'lower': 27.5,\n", + " 'pos': 91,\n", + " 'q3': 35.0,\n", + " 'upper': 39.5,\n", + " 'average': 32.665},\n", + " {'median': 34.0,\n", + " 'pos': 1,\n", + " 'q1': 31.0,\n", + " 'lower': 26.5,\n", + " 'average': 31.21,\n", + " 'q3': 34.0,\n", + " 'upper': 38.5},\n", + " {'median': 34.0,\n", + " 'q3': 35.0,\n", + " 'upper': 39.5,\n", + " 'q1': 32.0,\n", + " 'pos': 96,\n", + " 'average': 31.315,\n", + " 'lower': 27.5},\n", + " {'upper': 39.5,\n", + " 'median': 34.0,\n", + " 'lower': 27.5,\n", + " 'pos': 99,\n", + " 'q1': 32.0,\n", + " 'average': 31.25,\n", + " 'q3': 35.0},\n", + " {'upper': 45.5,\n", + " 'median': 40.0,\n", + " 'average': 38.595,\n", + " 'q1': 38.0,\n", + " 'q3': 41.0,\n", + " 'pos': 29,\n", + " 'lower': 33.5},\n", + " {'median': 40.0,\n", + " 'upper': 43.0,\n", + " 'q1': 38.0,\n", + " 'average': 38.245,\n", + " 'pos': 30,\n", + " 'lower': 35.0,\n", + " 'q3': 40.0},\n", + " {'q3': 35.0,\n", + " 'q1': 32.0,\n", + " 'average': 31.55,\n", + " 'median': 34.0,\n", + " 'upper': 39.5,\n", + " 'lower': 27.5,\n", + " 'pos': 98},\n", + " {'pos': 52,\n", + " 'q1': 37.0,\n", + " 'q3': 40.0,\n", + " 'upper': 44.5,\n", + " 'lower': 32.5,\n", + " 'median': 39.0,\n", + " 'average': 37.77},\n", + " {'lower': 32.0,\n", + " 'pos': 4,\n", + " 'q1': 35.0,\n", + " 'average': 35.68,\n", + " 'q3': 37.0,\n", + " 'median': 37.0,\n", + " 'upper': 40.0},\n", + " {'average': 35.69,\n", + " 'q3': 37.0,\n", + " 'lower': 32.0,\n", + " 'upper': 40.0,\n", + " 'median': 37.0,\n", + " 'q1': 35.0,\n", + " 'pos': 3},\n", + " {'median': 40.0,\n", + " 'pos': 38,\n", + " 'average': 37.64,\n", + " 'q3': 41.0,\n", + " 'q1': 38.0,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5},\n", + " {'pos': 46,\n", + " 'upper': 47.0,\n", + " 'q3': 41.0,\n", + " 'q1': 37.0,\n", + " 'average': 37.79,\n", + " 'median': 39.5,\n", + " 'lower': 31.0},\n", + " {'pos': 82,\n", + " 'average': 31.525,\n", + " 'lower': 28.5,\n", + " 'upper': 40.5,\n", + " 'median': 35.0,\n", + " 'q3': 36.0,\n", + " 'q1': 33.0},\n", + " {'upper': 40.0,\n", + " 'lower': 32.0,\n", + " 'average': 35.095,\n", + " 'pos': 5,\n", + " 'median': 35.0,\n", + " 'q1': 35.0,\n", + " 'q3': 37.0},\n", + " {'upper': 45.5,\n", + " 'q1': 38.0,\n", + " 'median': 40.0,\n", + " 'average': 38.2,\n", + " 'pos': 25,\n", + " 'q3': 41.0,\n", + " 'lower': 33.5},\n", + " {'pos': 33,\n", + " 'q3': 41.0,\n", + " 'median': 40.0,\n", + " 'upper': 45.5,\n", + " 'q1': 38.0,\n", + " 'lower': 33.5,\n", + " 'average': 38.245},\n", + " {'lower': 33.5,\n", + " 'median': 40.0,\n", + " 'upper': 45.5,\n", + " 'pos': 24,\n", + " 'q1': 38.0,\n", + " 'q3': 41.0,\n", + " 'average': 38.265},\n", + " {'pos': 43,\n", + " 'average': 37.775,\n", + " 'q1': 38.0,\n", + " 'lower': 35.0,\n", + " 'q3': 40.0,\n", + " 'upper': 43.0,\n", + " 'median': 40.0},\n", + " {'median': 39.0,\n", + " 'q3': 40.0,\n", + " 'pos': 56,\n", + " 'lower': 30.0,\n", + " 'q1': 36.0,\n", + " 'upper': 46.0,\n", + " 'average': 37.59},\n", + " {'median': 37.0,\n", + " 'q3': 39.0,\n", + " 'lower': 29.0,\n", + " 'average': 35.875,\n", + " 'pos': 66,\n", + " 'q1': 35.0,\n", + " 'upper': 45.0},\n", + " {'upper': 45.5,\n", + " 'median': 35.0,\n", + " 'q3': 38.0,\n", + " 'pos': 71,\n", + " 'q1': 33.0,\n", + " 'average': 33.005,\n", + " 'lower': 25.5},\n", + " {'pos': 34,\n", + " 'median': 40.0,\n", + " 'q1': 38.0,\n", + " 'q3': 41.0,\n", + " 'average': 38.205,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5},\n", + " {'pos': 68,\n", + " 'upper': 46.5,\n", + " 'lower': 26.5,\n", + " 'median': 36.0,\n", + " 'q1': 34.0,\n", + " 'q3': 39.0,\n", + " 'average': 35.91},\n", + " {'average': 31.425,\n", + " 'lower': 27.5,\n", + " 'upper': 39.5,\n", + " 'median': 34.0,\n", + " 'pos': 95,\n", + " 'q1': 32.0,\n", + " 'q3': 35.0},\n", + " {'median': 39.0,\n", + " 'q1': 37.0,\n", + " 'average': 37.665,\n", + " 'q3': 41.0,\n", + " 'lower': 31.0,\n", + " 'pos': 47,\n", + " 'upper': 47.0},\n", + " {'median': 38.0,\n", + " 'q3': 40.0,\n", + " 'upper': 47.5,\n", + " 'average': 36.145,\n", + " 'lower': 27.5,\n", + " 'pos': 62,\n", + " 'q1': 35.0},\n", + " {'upper': 46.0,\n", + " 'median': 39.0,\n", + " 'q1': 36.0,\n", + " 'lower': 30.0,\n", + " 'q3': 40.0,\n", + " 'pos': 49,\n", + " 'average': 37.21},\n", + " {'upper': 44.5,\n", + " 'q3': 40.0,\n", + " 'q1': 37.0,\n", + " 'average': 37.78,\n", + " 'pos': 42,\n", + " 'median': 40.0,\n", + " 'lower': 32.5},\n", + " {'pos': 10,\n", + " 'average': 37.675,\n", + " 'lower': 34.0,\n", + " 'median': 39.0,\n", + " 'q3': 39.0,\n", + " 'q1': 37.0,\n", + " 'upper': 42.0},\n", + " {'median': 39.0,\n", + " 'q3': 40.0,\n", + " 'lower': 30.0,\n", + " 'average': 37.55,\n", + " 'q1': 36.0,\n", + " 'pos': 55,\n", + " 'upper': 46.0},\n", + " {'median': 34.5,\n", + " 'q3': 35.0,\n", + " 'average': 32.275,\n", + " 'pos': 90,\n", + " 'lower': 30.0,\n", + " 'upper': 38.0,\n", + " 'q1': 33.0},\n", + " {'q1': 36.0,\n", + " 'average': 37.425,\n", + " 'upper': 48.5,\n", + " 'pos': 50,\n", + " 'lower': 28.5,\n", + " 'q3': 41.0,\n", + " 'median': 39.0},\n", + " {'average': 38.48,\n", + " 'q3': 41.0,\n", + " 'median': 40.0,\n", + " 'pos': 16,\n", + " 'q1': 38.0,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5},\n", + " {'lower': 33.5,\n", + " 'median': 40.0,\n", + " 'q3': 41.0,\n", + " 'upper': 45.5,\n", + " 'pos': 18,\n", + " 'average': 38.47,\n", + " 'q1': 38.0},\n", + " {'median': 40.0,\n", + " 'pos': 28,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'q3': 41.0,\n", + " 'q1': 38.0,\n", + " 'average': 38.445},\n", + " {'upper': 48.5,\n", + " 'q3': 41.0,\n", + " 'q1': 36.0,\n", + " 'average': 37.53,\n", + " 'median': 39.0,\n", + " 'pos': 51,\n", + " 'lower': 28.5},\n", + " {'pos': 100,\n", + " 'q3': 35.0,\n", + " 'upper': 41.0,\n", + " 'q1': 31.0,\n", + " 'lower': 25.0,\n", + " 'average': 31.105,\n", + " 'median': 34.0},\n", + " {'median': 40.0,\n", + " 'average': 37.95,\n", + " 'q1': 38.0,\n", + " 'pos': 40,\n", + " 'lower': 35.0,\n", + " 'upper': 43.0,\n", + " 'q3': 40.0},\n", + " {'q1': 37.0,\n", + " 'q3': 39.0,\n", + " 'lower': 34.0,\n", + " 'upper': 42.0,\n", + " 'median': 39.0,\n", + " 'average': 37.36,\n", + " 'pos': 9},\n", + " {'pos': 69,\n", + " 'q3': 39.0,\n", + " 'lower': 26.5,\n", + " 'upper': 46.5,\n", + " 'q1': 34.0,\n", + " 'median': 36.0,\n", + " 'average': 33.7},\n", + " {'pos': 89,\n", + " 'average': 32.44,\n", + " 'median': 35.0,\n", + " 'q1': 33.0,\n", + " 'q3': 35.0,\n", + " 'lower': 30.0,\n", + " 'upper': 38.0},\n", + " {'average': 32.03,\n", + " 'pos': 83,\n", + " 'q1': 33.0,\n", + " 'q3': 35.0,\n", + " 'median': 35.0,\n", + " 'upper': 38.0,\n", + " 'lower': 30.0},\n", + " {'q3': 34.0,\n", + " 'lower': 26.5,\n", + " 'average': 30.135,\n", + " 'pos': 0,\n", + " 'upper': 38.5,\n", + " 'q1': 31.0,\n", + " 'median': 33.0},\n", + " {'average': 36.08,\n", + " 'lower': 27.5,\n", + " 'upper': 47.5,\n", + " 'median': 38.0,\n", + " 'pos': 59,\n", + " 'q1': 35.0,\n", + " 'q3': 40.0},\n", + " {'median': 40.0,\n", + " 'q3': 41.0,\n", + " 'average': 38.385,\n", + " 'q1': 38.0,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'pos': 35},\n", + " {'pos': 39,\n", + " 'average': 37.895,\n", + " 'q1': 38.0,\n", + " 'lower': 35.0,\n", + " 'q3': 40.0,\n", + " 'upper': 43.0,\n", + " 'median': 40.0},\n", + " {'median': 40.0,\n", + " 'average': 38.505,\n", + " 'q1': 38.0,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'pos': 17,\n", + " 'q3': 41.0},\n", + " {'pos': 20,\n", + " 'median': 40.0,\n", + " 'q3': 41.0,\n", + " 'average': 38.625,\n", + " 'lower': 33.5,\n", + " 'q1': 38.0,\n", + " 'upper': 45.5},\n", + " {'q3': 37.0,\n", + " 'q1': 35.0,\n", + " 'upper': 40.0,\n", + " 'pos': 7,\n", + " 'median': 36.0,\n", + " 'average': 35.4,\n", + " 'lower': 32.0},\n", + " {'average': 32.415,\n", + " 'q1': 33.0,\n", + " 'median': 35.0,\n", + " 'q3': 35.0,\n", + " 'lower': 30.0,\n", + " 'upper': 38.0,\n", + " 'pos': 84},\n", + " {'pos': 67,\n", + " 'q1': 34.0,\n", + " 'average': 35.96,\n", + " 'median': 36.5,\n", + " 'q3': 39.0,\n", + " 'upper': 46.5,\n", + " 'lower': 26.5},\n", + " {'q1': 38.0,\n", + " 'average': 38.11,\n", + " 'pos': 36,\n", + " 'lower': 35.0,\n", + " 'upper': 43.0,\n", + " 'q3': 40.0,\n", + " 'median': 40.0},\n", + " {'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'median': 40.0,\n", + " 'average': 38.41,\n", + " 'pos': 22,\n", + " 'q1': 38.0,\n", + " 'q3': 41.0},\n", + " {'q1': 35.0,\n", + " 'lower': 27.5,\n", + " 'average': 36.77,\n", + " 'median': 38.0,\n", + " 'pos': 58,\n", + " 'q3': 40.0,\n", + " 'upper': 47.5},\n", + " {'q1': 33.0,\n", + " 'lower': 27.0,\n", + " 'average': 32.68,\n", + " 'pos': 73,\n", + " 'upper': 43.0,\n", + " 'median': 35.0,\n", + " 'q3': 37.0},\n", + " {'median': 40.0,\n", + " 'pos': 32,\n", + " 'q1': 38.0,\n", + " 'lower': 33.5,\n", + " 'average': 38.29,\n", + " 'q3': 41.0,\n", + " 'upper': 45.5},\n", + " {'pos': 72,\n", + " 'average': 33.265,\n", + " 'q3': 37.0,\n", + " 'q1': 33.0,\n", + " 'lower': 27.0,\n", + " 'upper': 43.0,\n", + " 'median': 35.0},\n", + " {'average': 35.99,\n", + " 'q1': 35.0,\n", + " 'pos': 61,\n", + " 'q3': 40.0,\n", + " 'lower': 27.5,\n", + " 'upper': 47.5,\n", + " 'median': 38.0},\n", + " {'pos': 76,\n", + " 'average': 30.265,\n", + " 'median': 35.0,\n", + " 'q3': 37.0,\n", + " 'lower': 22.0,\n", + " 'upper': 46.0,\n", + " 'q1': 31.0},\n", + " {'pos': 79,\n", + " 'q1': 32.0,\n", + " 'lower': 26.0,\n", + " 'average': 32.46,\n", + " 'upper': 42.0,\n", + " 'median': 35.0,\n", + " 'q3': 36.0},\n", + " {'pos': 26,\n", + " 'average': 37.855,\n", + " 'median': 40.0,\n", + " 'lower': 35.0,\n", + " 'upper': 43.0,\n", + " 'q1': 38.0,\n", + " 'q3': 40.0},\n", + " {'pos': 93,\n", + " 'q3': 35.0,\n", + " 'upper': 39.5,\n", + " 'lower': 27.5,\n", + " 'q1': 32.0,\n", + " 'median': 34.0,\n", + " 'average': 31.05},\n", + " {'pos': 75,\n", + " 'q3': 37.0,\n", + " 'lower': 22.0,\n", + " 'median': 35.0,\n", + " 'q1': 31.0,\n", + " 'average': 31.06,\n", + " 'upper': 46.0},\n", + " {'average': 37.35,\n", + " 'q3': 40.0,\n", + " 'q1': 36.0,\n", + " 'lower': 30.0,\n", + " 'upper': 46.0,\n", + " 'pos': 57,\n", + " 'median': 39.0},\n", + " {'lower': 27.5,\n", + " 'average': 35.985,\n", + " 'pos': 60,\n", + " 'q1': 35.0,\n", + " 'q3': 40.0,\n", + " 'upper': 47.5,\n", + " 'median': 38.0},\n", + " {'upper': 47.0,\n", + " 'lower': 31.0,\n", + " 'q1': 37.0,\n", + " 'pos': 44,\n", + " 'average': 37.565,\n", + " 'median': 40.0,\n", + " 'q3': 41.0},\n", + " {'median': 35.0,\n", + " 'q1': 32.0,\n", + " 'lower': 27.5,\n", + " 'average': 31.915,\n", + " 'pos': 87,\n", + " 'upper': 39.5,\n", + " 'q3': 35.0},\n", + " {'average': 32.065,\n", + " 'median': 35.0,\n", + " 'q3': 35.0,\n", + " 'pos': 88,\n", + " 'lower': 30.0,\n", + " 'upper': 38.0,\n", + " 'q1': 33.0},\n", + " {'upper': 47.0,\n", + " 'pos': 53,\n", + " 'q1': 37.0,\n", + " 'average': 37.845,\n", + " 'q3': 41.0,\n", + " 'median': 39.0,\n", + " 'lower': 31.0},\n", + " {'median': 35.0,\n", + " 'q3': 36.0,\n", + " 'pos': 81,\n", + " 'q1': 33.0,\n", + " 'lower': 28.5,\n", + " 'upper': 40.5,\n", + " 'average': 32.76},\n", + " {'pos': 8,\n", + " 'lower': 34.0,\n", + " 'upper': 42.0,\n", + " 'average': 37.625,\n", + " 'median': 39.0,\n", + " 'q3': 39.0,\n", + " 'q1': 37.0},\n", + " {'pos': 12,\n", + " 'average': 37.5,\n", + " 'upper': 42.0,\n", + " 'q1': 37.0,\n", + " 'median': 39.0,\n", + " 'q3': 39.0,\n", + " 'lower': 34.0},\n", + " {'q1': 36.0,\n", + " 'average': 37.59,\n", + " 'q3': 41.0,\n", + " 'lower': 28.5,\n", + " 'upper': 48.5,\n", + " 'pos': 54,\n", + " 'median': 39.5},\n", + " {'average': 36.25,\n", + " 'median': 38.0,\n", + " 'q1': 35.0,\n", + " 'lower': 27.5,\n", + " 'upper': 47.5,\n", + " 'pos': 63,\n", + " 'q3': 40.0},\n", + " {'q1': 32.0,\n", + " 'pos': 80,\n", + " 'average': 32.61,\n", + " 'median': 35.0,\n", + " 'upper': 42.0,\n", + " 'q3': 36.0,\n", + " 'lower': 26.0},\n", + " {'lower': 27.5,\n", + " 'median': 35.0,\n", + " 'q1': 32.0,\n", + " 'average': 31.835,\n", + " 'q3': 35.0,\n", + " 'upper': 39.5,\n", + " 'pos': 92},\n", + " {'upper': 38.0,\n", + " 'median': 35.0,\n", + " 'lower': 30.0,\n", + " 'q3': 35.0,\n", + " 'average': 31.815,\n", + " 'pos': 86,\n", + " 'q1': 33.0},\n", + " {'q3': 41.0,\n", + " 'upper': 45.5,\n", + " 'lower': 33.5,\n", + " 'pos': 27,\n", + " 'average': 38.44,\n", + " 'median': 40.0,\n", + " 'q1': 38.0},\n", + " {'pos': 94,\n", + " 'q1': 32.0,\n", + " 'lower': 27.5,\n", + " 'upper': 39.5,\n", + " 'average': 30.775,\n", + " 'median': 34.0,\n", + " 'q3': 35.0},\n", + " {'pos': 65,\n", + " 'upper': 45.0,\n", + " 'median': 37.0,\n", + " 'q1': 35.0,\n", + " 'q3': 39.0,\n", + " 'lower': 29.0,\n", + " 'average': 35.995},\n", + " {'average': 37.87,\n", + " 'q3': 41.0,\n", + " 'upper': 47.0,\n", + " 'q1': 37.0,\n", + " 'lower': 31.0,\n", + " 'pos': 41,\n", + " 'median': 40.0},\n", + " {'pos': 77,\n", + " 'average': 30.805,\n", + " 'upper': 45.0,\n", + " 'median': 35.0,\n", + " 'q3': 36.0,\n", + " 'q1': 30.0,\n", + " 'lower': 21.0},\n", + " {'pos': 13,\n", + " 'q1': 38.0,\n", + " 'q3': 41.0,\n", + " 'lower': 33.5,\n", + " 'upper': 45.5,\n", + " 'median': 40.0,\n", + " 'average': 38.94},\n", + " {'lower': 35.0,\n", + " 'q1': 38.0,\n", + " 'q3': 40.0,\n", + " 'upper': 43.0,\n", + " 'pos': 21,\n", + " 'average': 38.445,\n", + " 'median': 40.0},\n", + " {'q3': 36.0,\n", + " 'median': 35.0,\n", + " 'average': 31.46,\n", + " 'q1': 31.0,\n", + " 'pos': 78,\n", + " 'lower': 23.5,\n", + " 'upper': 43.5},\n", + " {'q3': 37.0,\n", + " 'lower': 32.0,\n", + " 'pos': 6,\n", + " 'upper': 40.0,\n", + " 'median': 35.0,\n", + " 'q1': 35.0,\n", + " 'average': 35.145},\n", + " {'pos': 64,\n", + " 'q3': 40.0,\n", + " 'median': 37.0,\n", + " 'lower': 27.5,\n", + " 'q1': 35.0,\n", + " 'upper': 47.5,\n", + " 'average': 36.095}]}" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a_lazyframe = pb.read_fastq(\"./example.fastq\")\n", + "a_pandas_dataframe = a_lazyframe.collect().to_pandas()\n", + "print(type(a_pandas_dataframe))\n", + "pb.base_sequence_quality(a_pandas_dataframe)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "3.12.9", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From a982f0e144743d13483359d4f4cd3cc7e94e5b67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20=C5=9Acise=C5=82?= Date: Wed, 4 Jun 2025 21:20:54 +0200 Subject: [PATCH 05/13] Refactor base sequence quality computation and integrate DataFusion - Updated `base_sequence_quality` function to accept a quality scores column and output type. - Introduced `BaseSequenceQualityProvider` and `BaseSequenceQualityExec` in Rust for efficient execution plans. - Removed the custom UDAF for quality scores and replaced it with a DataFusion table provider. - Simplified data handling by directly using DataFrames from DataFusion. - Cleaned up unnecessary code and files related to UDAF implementation. - Enhanced error handling and type checking for input data. --- docs/notebooks/base_sequence_quality.ipynb | 4461 +------------------- docs/notebooks/tutorial.ipynb | 336 +- polars_bio/quality_stats.py | 48 +- src/base_sequence_quality.rs | 247 ++ src/context.rs | 17 - src/lib.rs | 138 +- src/operation.rs | 41 +- src/scan.rs | 4 - src/udaf.rs | 210 - 9 files changed, 776 insertions(+), 4726 deletions(-) create mode 100644 src/base_sequence_quality.rs delete mode 100644 src/udaf.rs diff --git a/docs/notebooks/base_sequence_quality.ipynb b/docs/notebooks/base_sequence_quality.ipynb index 35d8bed5..cac9a2ce 100644 --- a/docs/notebooks/base_sequence_quality.ipynb +++ b/docs/notebooks/base_sequence_quality.ipynb @@ -47,37 +47,15 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "5f6fccf3", "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "INFO:polars_bio:Table: example registered for path: ./example.fastq\n", - "1rows [00:00, 327.48rows/s]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'base_quality_warn': 'pass', 'base_per_pos_data': [{'pos': 89, 'average': 32.44, 'median': 35.0, 'q1': 33.0, 'q3': 35.0, 'lower': 30.0, 'upper': 38.0}, {'pos': 84, 'average': 32.415, 'median': 35.0, 'q1': 33.0, 'q3': 35.0, 'lower': 30.0, 'upper': 38.0}, {'pos': 96, 'average': 31.315, 'median': 34.0, 'q1': 32.0, 'q3': 35.0, 'lower': 27.5, 'upper': 39.5}, {'pos': 31, 'average': 38.795, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 49, 'average': 37.21, 'median': 39.0, 'q1': 36.0, 'q3': 40.0, 'lower': 30.0, 'upper': 46.0}, {'pos': 69, 'average': 33.7, 'median': 36.0, 'q1': 34.0, 'q3': 39.0, 'lower': 26.5, 'upper': 46.5}, {'pos': 63, 'average': 36.25, 'median': 38.0, 'q1': 35.0, 'q3': 40.0, 'lower': 27.5, 'upper': 47.5}, {'pos': 65, 'average': 35.995, 'median': 37.0, 'q1': 35.0, 'q3': 39.0, 'lower': 29.0, 'upper': 45.0}, {'pos': 70, 'average': 33.565, 'median': 35.0, 'q1': 34.0, 'q3': 38.0, 'lower': 28.0, 'upper': 44.0}, {'pos': 68, 'average': 35.91, 'median': 36.0, 'q1': 34.0, 'q3': 39.0, 'lower': 26.5, 'upper': 46.5}, {'pos': 55, 'average': 37.55, 'median': 39.0, 'q1': 36.0, 'q3': 40.0, 'lower': 30.0, 'upper': 46.0}, {'pos': 24, 'average': 38.265, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 21, 'average': 38.445, 'median': 40.0, 'q1': 38.0, 'q3': 40.0, 'lower': 35.0, 'upper': 43.0}, {'pos': 60, 'average': 35.985, 'median': 38.0, 'q1': 35.0, 'q3': 40.0, 'lower': 27.5, 'upper': 47.5}, {'pos': 45, 'average': 37.45, 'median': 40.0, 'q1': 36.0, 'q3': 41.0, 'lower': 28.5, 'upper': 48.5}, {'pos': 30, 'average': 38.245, 'median': 40.0, 'q1': 38.0, 'q3': 40.0, 'lower': 35.0, 'upper': 43.0}, {'pos': 20, 'average': 38.625, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 82, 'average': 31.525, 'median': 35.0, 'q1': 33.0, 'q3': 36.0, 'lower': 28.5, 'upper': 40.5}, {'pos': 85, 'average': 32.195, 'median': 35.0, 'q1': 33.0, 'q3': 35.0, 'lower': 30.0, 'upper': 38.0}, {'pos': 35, 'average': 38.385, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 57, 'average': 37.35, 'median': 39.0, 'q1': 36.0, 'q3': 40.0, 'lower': 30.0, 'upper': 46.0}, {'pos': 66, 'average': 35.875, 'median': 37.0, 'q1': 35.0, 'q3': 39.0, 'lower': 29.0, 'upper': 45.0}, {'pos': 74, 'average': 30.83, 'median': 35.0, 'q1': 32.0, 'q3': 37.0, 'lower': 24.5, 'upper': 44.5}, {'pos': 86, 'average': 31.815, 'median': 35.0, 'q1': 33.0, 'q3': 35.0, 'lower': 30.0, 'upper': 38.0}, {'pos': 87, 'average': 31.915, 'median': 35.0, 'q1': 32.0, 'q3': 35.0, 'lower': 27.5, 'upper': 39.5}, {'pos': 88, 'average': 32.065, 'median': 35.0, 'q1': 33.0, 'q3': 35.0, 'lower': 30.0, 'upper': 38.0}, {'pos': 42, 'average': 37.78, 'median': 40.0, 'q1': 37.0, 'q3': 40.0, 'lower': 32.5, 'upper': 44.5}, {'pos': 51, 'average': 37.53, 'median': 39.0, 'q1': 36.0, 'q3': 41.0, 'lower': 28.5, 'upper': 48.5}, {'pos': 71, 'average': 33.005, 'median': 35.0, 'q1': 33.0, 'q3': 38.0, 'lower': 25.5, 'upper': 45.5}, {'pos': 72, 'average': 33.265, 'median': 35.0, 'q1': 33.0, 'q3': 37.0, 'lower': 27.0, 'upper': 43.0}, {'pos': 90, 'average': 32.275, 'median': 34.5, 'q1': 33.0, 'q3': 35.0, 'lower': 30.0, 'upper': 38.0}, {'pos': 23, 'average': 38.635, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 32, 'average': 38.29, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 11, 'average': 37.71, 'median': 39.0, 'q1': 37.0, 'q3': 39.0, 'lower': 34.0, 'upper': 42.0}, {'pos': 43, 'average': 37.775, 'median': 40.0, 'q1': 38.0, 'q3': 40.0, 'lower': 35.0, 'upper': 43.0}, {'pos': 91, 'average': 32.665, 'median': 35.0, 'q1': 32.0, 'q3': 35.0, 'lower': 27.5, 'upper': 39.5}, {'pos': 6, 'average': 35.145, 'median': 35.0, 'q1': 35.0, 'q3': 37.0, 'lower': 32.0, 'upper': 40.0}, {'pos': 67, 'average': 35.96, 'median': 36.5, 'q1': 34.0, 'q3': 39.0, 'lower': 26.5, 'upper': 46.5}, {'pos': 76, 'average': 30.265, 'median': 35.0, 'q1': 31.0, 'q3': 37.0, 'lower': 22.0, 'upper': 46.0}, {'pos': 52, 'average': 37.77, 'median': 39.0, 'q1': 37.0, 'q3': 40.0, 'lower': 32.5, 'upper': 44.5}, {'pos': 73, 'average': 32.68, 'median': 35.0, 'q1': 33.0, 'q3': 37.0, 'lower': 27.0, 'upper': 43.0}, {'pos': 29, 'average': 38.595, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 17, 'average': 38.505, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 53, 'average': 37.845, 'median': 39.0, 'q1': 37.0, 'q3': 41.0, 'lower': 31.0, 'upper': 47.0}, {'pos': 77, 'average': 30.805, 'median': 35.0, 'q1': 30.0, 'q3': 36.0, 'lower': 21.0, 'upper': 45.0}, {'pos': 12, 'average': 37.5, 'median': 39.0, 'q1': 37.0, 'q3': 39.0, 'lower': 34.0, 'upper': 42.0}, {'pos': 37, 'average': 38.0, 'median': 40.0, 'q1': 38.0, 'q3': 40.0, 'lower': 35.0, 'upper': 43.0}, {'pos': 83, 'average': 32.03, 'median': 35.0, 'q1': 33.0, 'q3': 35.0, 'lower': 30.0, 'upper': 38.0}, {'pos': 99, 'average': 31.25, 'median': 34.0, 'q1': 32.0, 'q3': 35.0, 'lower': 27.5, 'upper': 39.5}, {'pos': 48, 'average': 37.61, 'median': 40.0, 'q1': 36.0, 'q3': 41.0, 'lower': 28.5, 'upper': 48.5}, {'pos': 4, 'average': 35.68, 'median': 37.0, 'q1': 35.0, 'q3': 37.0, 'lower': 32.0, 'upper': 40.0}, {'pos': 56, 'average': 37.59, 'median': 39.0, 'q1': 36.0, 'q3': 40.0, 'lower': 30.0, 'upper': 46.0}, {'pos': 8, 'average': 37.625, 'median': 39.0, 'q1': 37.0, 'q3': 39.0, 'lower': 34.0, 'upper': 42.0}, {'pos': 18, 'average': 38.47, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 38, 'average': 37.64, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 39, 'average': 37.895, 'median': 40.0, 'q1': 38.0, 'q3': 40.0, 'lower': 35.0, 'upper': 43.0}, {'pos': 41, 'average': 37.87, 'median': 40.0, 'q1': 37.0, 'q3': 41.0, 'lower': 31.0, 'upper': 47.0}, {'pos': 19, 'average': 38.425, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 15, 'average': 38.725, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 78, 'average': 31.46, 'median': 35.0, 'q1': 31.0, 'q3': 36.0, 'lower': 23.5, 'upper': 43.5}, {'pos': 62, 'average': 36.145, 'median': 38.0, 'q1': 35.0, 'q3': 40.0, 'lower': 27.5, 'upper': 47.5}, {'pos': 13, 'average': 38.94, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 28, 'average': 38.445, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 93, 'average': 31.05, 'median': 34.0, 'q1': 32.0, 'q3': 35.0, 'lower': 27.5, 'upper': 39.5}, {'pos': 94, 'average': 30.775, 'median': 34.0, 'q1': 32.0, 'q3': 35.0, 'lower': 27.5, 'upper': 39.5}, {'pos': 100, 'average': 31.105, 'median': 34.0, 'q1': 31.0, 'q3': 35.0, 'lower': 25.0, 'upper': 41.0}, {'pos': 64, 'average': 36.095, 'median': 37.0, 'q1': 35.0, 'q3': 40.0, 'lower': 27.5, 'upper': 47.5}, {'pos': 61, 'average': 35.99, 'median': 38.0, 'q1': 35.0, 'q3': 40.0, 'lower': 27.5, 'upper': 47.5}, {'pos': 44, 'average': 37.565, 'median': 40.0, 'q1': 37.0, 'q3': 41.0, 'lower': 31.0, 'upper': 47.0}, {'pos': 40, 'average': 37.95, 'median': 40.0, 'q1': 38.0, 'q3': 40.0, 'lower': 35.0, 'upper': 43.0}, {'pos': 92, 'average': 31.835, 'median': 35.0, 'q1': 32.0, 'q3': 35.0, 'lower': 27.5, 'upper': 39.5}, {'pos': 46, 'average': 37.79, 'median': 39.5, 'q1': 37.0, 'q3': 41.0, 'lower': 31.0, 'upper': 47.0}, {'pos': 10, 'average': 37.675, 'median': 39.0, 'q1': 37.0, 'q3': 39.0, 'lower': 34.0, 'upper': 42.0}, {'pos': 36, 'average': 38.11, 'median': 40.0, 'q1': 38.0, 'q3': 40.0, 'lower': 35.0, 'upper': 43.0}, {'pos': 0, 'average': 30.135, 'median': 33.0, 'q1': 31.0, 'q3': 34.0, 'lower': 26.5, 'upper': 38.5}, {'pos': 33, 'average': 38.245, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 26, 'average': 37.855, 'median': 40.0, 'q1': 38.0, 'q3': 40.0, 'lower': 35.0, 'upper': 43.0}, {'pos': 95, 'average': 31.425, 'median': 34.0, 'q1': 32.0, 'q3': 35.0, 'lower': 27.5, 'upper': 39.5}, {'pos': 98, 'average': 31.55, 'median': 34.0, 'q1': 32.0, 'q3': 35.0, 'lower': 27.5, 'upper': 39.5}, {'pos': 81, 'average': 32.76, 'median': 35.0, 'q1': 33.0, 'q3': 36.0, 'lower': 28.5, 'upper': 40.5}, {'pos': 14, 'average': 38.965, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 75, 'average': 31.06, 'median': 35.0, 'q1': 31.0, 'q3': 37.0, 'lower': 22.0, 'upper': 46.0}, {'pos': 5, 'average': 35.095, 'median': 35.0, 'q1': 35.0, 'q3': 37.0, 'lower': 32.0, 'upper': 40.0}, {'pos': 16, 'average': 38.48, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 3, 'average': 35.69, 'median': 37.0, 'q1': 35.0, 'q3': 37.0, 'lower': 32.0, 'upper': 40.0}, {'pos': 27, 'average': 38.44, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 54, 'average': 37.59, 'median': 39.5, 'q1': 36.0, 'q3': 41.0, 'lower': 28.5, 'upper': 48.5}, {'pos': 9, 'average': 37.36, 'median': 39.0, 'q1': 37.0, 'q3': 39.0, 'lower': 34.0, 'upper': 42.0}, {'pos': 97, 'average': 30.67, 'median': 34.0, 'q1': 31.0, 'q3': 35.0, 'lower': 25.0, 'upper': 41.0}, {'pos': 7, 'average': 35.4, 'median': 36.0, 'q1': 35.0, 'q3': 37.0, 'lower': 32.0, 'upper': 40.0}, {'pos': 22, 'average': 38.41, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 47, 'average': 37.665, 'median': 39.0, 'q1': 37.0, 'q3': 41.0, 'lower': 31.0, 'upper': 47.0}, {'pos': 59, 'average': 36.08, 'median': 38.0, 'q1': 35.0, 'q3': 40.0, 'lower': 27.5, 'upper': 47.5}, {'pos': 79, 'average': 32.46, 'median': 35.0, 'q1': 32.0, 'q3': 36.0, 'lower': 26.0, 'upper': 42.0}, {'pos': 50, 'average': 37.425, 'median': 39.0, 'q1': 36.0, 'q3': 41.0, 'lower': 28.5, 'upper': 48.5}, {'pos': 34, 'average': 38.205, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 58, 'average': 36.77, 'median': 38.0, 'q1': 35.0, 'q3': 40.0, 'lower': 27.5, 'upper': 47.5}, {'pos': 25, 'average': 38.2, 'median': 40.0, 'q1': 38.0, 'q3': 41.0, 'lower': 33.5, 'upper': 45.5}, {'pos': 2, 'average': 32.015, 'median': 34.0, 'q1': 31.0, 'q3': 34.0, 'lower': 26.5, 'upper': 38.5}, {'pos': 1, 'average': 31.21, 'median': 34.0, 'q1': 31.0, 'q3': 34.0, 'lower': 26.5, 'upper': 38.5}, {'pos': 80, 'average': 32.61, 'median': 35.0, 'q1': 32.0, 'q3': 36.0, 'lower': 26.0, 'upper': 42.0}]}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "\n" - ] - } - ], + "outputs": [], "source": [ "a_lazyframe = pb.read_fastq(\"./example.fastq\")\n", - "result = pb.sql(\"SELECT base_sequence_quality(quality_scores) FROM example\").collect()\n", - "print(result.item())" + "# not implemented yet\n", + "result = pb.sql(\"???\").collect()\n", + "print(result)" ] }, { @@ -95,725 +73,29 @@ "metadata": {}, "outputs": [ { - "data": { - "text/plain": [ - "{'base_quality_warn': 'pass',\n", - " 'base_per_pos_data': [{'lower': 33.5,\n", - " 'q3': 41.0,\n", - " 'q1': 38.0,\n", - " 'median': 40.0,\n", - " 'average': 38.205,\n", - " 'upper': 45.5,\n", - " 'pos': 34},\n", - " {'average': 38.47,\n", - " 'q1': 38.0,\n", - " 'lower': 33.5,\n", - " 'median': 40.0,\n", - " 'q3': 41.0,\n", - " 'pos': 18,\n", - " 'upper': 45.5},\n", - " {'q3': 35.0,\n", - " 'average': 31.815,\n", - " 'median': 35.0,\n", - " 'q1': 33.0,\n", - " 'pos': 86,\n", - " 'lower': 30.0,\n", - " 'upper': 38.0},\n", - " {'q3': 40.0,\n", - " 'lower': 35.0,\n", - " 'upper': 43.0,\n", - " 'pos': 21,\n", - " 'average': 38.445,\n", - " 'q1': 38.0,\n", - " 'median': 40.0},\n", - " {'lower': 27.5,\n", - " 'average': 31.835,\n", - " 'q3': 35.0,\n", - " 'median': 35.0,\n", - " 'q1': 32.0,\n", - " 'upper': 39.5,\n", - " 'pos': 92},\n", - " {'q3': 35.0,\n", - " 'lower': 27.5,\n", - " 'pos': 95,\n", - " 'upper': 39.5,\n", - " 'median': 34.0,\n", - " 'q1': 32.0,\n", - " 'average': 31.425},\n", - " {'average': 35.91,\n", - " 'q3': 39.0,\n", - " 'lower': 26.5,\n", - " 'median': 36.0,\n", - " 'pos': 68,\n", - " 'upper': 46.5,\n", - " 'q1': 34.0},\n", - " {'pos': 61,\n", - " 'average': 35.99,\n", - " 'median': 38.0,\n", - " 'q3': 40.0,\n", - " 'q1': 35.0,\n", - " 'lower': 27.5,\n", - " 'upper': 47.5},\n", - " {'median': 39.0,\n", - " 'lower': 30.0,\n", - " 'upper': 46.0,\n", - " 'average': 37.59,\n", - " 'q1': 36.0,\n", - " 'pos': 56,\n", - " 'q3': 40.0},\n", - " {'q3': 35.0,\n", - " 'upper': 38.0,\n", - " 'q1': 33.0,\n", - " 'pos': 89,\n", - " 'average': 32.44,\n", - " 'median': 35.0,\n", - " 'lower': 30.0},\n", - " {'lower': 35.0,\n", - " 'median': 40.0,\n", - " 'upper': 43.0,\n", - " 'pos': 37,\n", - " 'q1': 38.0,\n", - " 'average': 38.0,\n", - " 'q3': 40.0},\n", - " {'average': 37.71,\n", - " 'median': 39.0,\n", - " 'q1': 37.0,\n", - " 'pos': 11,\n", - " 'lower': 34.0,\n", - " 'q3': 39.0,\n", - " 'upper': 42.0},\n", - " {'average': 32.015,\n", - " 'median': 34.0,\n", - " 'lower': 26.5,\n", - " 'pos': 2,\n", - " 'q1': 31.0,\n", - " 'q3': 34.0,\n", - " 'upper': 38.5},\n", - " {'upper': 41.0,\n", - " 'q1': 31.0,\n", - " 'average': 30.67,\n", - " 'lower': 25.0,\n", - " 'pos': 97,\n", - " 'q3': 35.0,\n", - " 'median': 34.0},\n", - " {'lower': 33.5,\n", - " 'q1': 38.0,\n", - " 'median': 40.0,\n", - " 'q3': 41.0,\n", - " 'average': 38.595,\n", - " 'upper': 45.5,\n", - " 'pos': 29},\n", - " {'pos': 39,\n", - " 'lower': 35.0,\n", - " 'upper': 43.0,\n", - " 'q3': 40.0,\n", - " 'q1': 38.0,\n", - " 'median': 40.0,\n", - " 'average': 37.895},\n", - " {'upper': 39.5,\n", - " 'average': 31.25,\n", - " 'median': 34.0,\n", - " 'pos': 99,\n", - " 'q3': 35.0,\n", - " 'q1': 32.0,\n", - " 'lower': 27.5},\n", - " {'average': 37.425,\n", - " 'upper': 48.5,\n", - " 'pos': 50,\n", - " 'q1': 36.0,\n", - " 'lower': 28.5,\n", - " 'q3': 41.0,\n", - " 'median': 39.0},\n", - " {'median': 37.0,\n", - " 'pos': 66,\n", - " 'q3': 39.0,\n", - " 'upper': 45.0,\n", - " 'q1': 35.0,\n", - " 'lower': 29.0,\n", - " 'average': 35.875},\n", - " {'average': 38.94,\n", - " 'pos': 13,\n", - " 'median': 40.0,\n", - " 'q1': 38.0,\n", - " 'q3': 41.0,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5},\n", - " {'q1': 32.0,\n", - " 'average': 32.61,\n", - " 'median': 35.0,\n", - " 'pos': 80,\n", - " 'q3': 36.0,\n", - " 'lower': 26.0,\n", - " 'upper': 42.0},\n", - " {'lower': 27.5,\n", - " 'q1': 35.0,\n", - " 'upper': 47.5,\n", - " 'median': 38.0,\n", - " 'pos': 59,\n", - " 'average': 36.08,\n", - " 'q3': 40.0},\n", - " {'average': 31.55,\n", - " 'q3': 35.0,\n", - " 'pos': 98,\n", - " 'lower': 27.5,\n", - " 'median': 34.0,\n", - " 'upper': 39.5,\n", - " 'q1': 32.0},\n", - " {'average': 38.505,\n", - " 'q1': 38.0,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'pos': 17,\n", - " 'median': 40.0,\n", - " 'q3': 41.0},\n", - " {'q3': 41.0,\n", - " 'upper': 45.5,\n", - " 'median': 40.0,\n", - " 'pos': 20,\n", - " 'lower': 33.5,\n", - " 'average': 38.625,\n", - " 'q1': 38.0},\n", - " {'upper': 47.0,\n", - " 'average': 37.87,\n", - " 'q3': 41.0,\n", - " 'median': 40.0,\n", - " 'q1': 37.0,\n", - " 'lower': 31.0,\n", - " 'pos': 41},\n", - " {'q1': 38.0,\n", - " 'upper': 43.0,\n", - " 'lower': 35.0,\n", - " 'average': 37.775,\n", - " 'median': 40.0,\n", - " 'q3': 40.0,\n", - " 'pos': 43},\n", - " {'q1': 33.0,\n", - " 'average': 33.265,\n", - " 'pos': 72,\n", - " 'median': 35.0,\n", - " 'lower': 27.0,\n", - " 'upper': 43.0,\n", - " 'q3': 37.0},\n", - " {'median': 35.0,\n", - " 'average': 31.525,\n", - " 'q1': 33.0,\n", - " 'q3': 36.0,\n", - " 'pos': 82,\n", - " 'upper': 40.5,\n", - " 'lower': 28.5},\n", - " {'median': 39.0,\n", - " 'q1': 37.0,\n", - " 'pos': 8,\n", - " 'q3': 39.0,\n", - " 'lower': 34.0,\n", - " 'average': 37.625,\n", - " 'upper': 42.0},\n", - " {'median': 39.0,\n", - " 'q3': 39.0,\n", - " 'upper': 42.0,\n", - " 'lower': 34.0,\n", - " 'average': 37.5,\n", - " 'q1': 37.0,\n", - " 'pos': 12},\n", - " {'pos': 40,\n", - " 'lower': 35.0,\n", - " 'median': 40.0,\n", - " 'q1': 38.0,\n", - " 'upper': 43.0,\n", - " 'average': 37.95,\n", - " 'q3': 40.0},\n", - " {'q1': 36.0,\n", - " 'median': 39.0,\n", - " 'lower': 30.0,\n", - " 'q3': 40.0,\n", - " 'average': 37.35,\n", - " 'pos': 57,\n", - " 'upper': 46.0},\n", - " {'lower': 32.0,\n", - " 'upper': 40.0,\n", - " 'pos': 7,\n", - " 'q3': 37.0,\n", - " 'median': 36.0,\n", - " 'q1': 35.0,\n", - " 'average': 35.4},\n", - " {'median': 35.0,\n", - " 'lower': 30.0,\n", - " 'upper': 38.0,\n", - " 'average': 32.03,\n", - " 'pos': 83,\n", - " 'q1': 33.0,\n", - " 'q3': 35.0},\n", - " {'pos': 6,\n", - " 'q3': 37.0,\n", - " 'q1': 35.0,\n", - " 'lower': 32.0,\n", - " 'upper': 40.0,\n", - " 'median': 35.0,\n", - " 'average': 35.145},\n", - " {'q3': 39.0,\n", - " 'lower': 34.0,\n", - " 'median': 39.0,\n", - " 'upper': 42.0,\n", - " 'average': 37.675,\n", - " 'q1': 37.0,\n", - " 'pos': 10},\n", - " {'q1': 31.0,\n", - " 'q3': 34.0,\n", - " 'median': 33.0,\n", - " 'lower': 26.5,\n", - " 'pos': 0,\n", - " 'average': 30.135,\n", - " 'upper': 38.5},\n", - " {'pos': 1,\n", - " 'lower': 26.5,\n", - " 'average': 31.21,\n", - " 'q3': 34.0,\n", - " 'q1': 31.0,\n", - " 'median': 34.0,\n", - " 'upper': 38.5},\n", - " {'upper': 47.5,\n", - " 'average': 36.095,\n", - " 'q1': 35.0,\n", - " 'pos': 64,\n", - " 'median': 37.0,\n", - " 'q3': 40.0,\n", - " 'lower': 27.5},\n", - " {'average': 37.55,\n", - " 'q3': 40.0,\n", - " 'pos': 55,\n", - " 'lower': 30.0,\n", - " 'q1': 36.0,\n", - " 'median': 39.0,\n", - " 'upper': 46.0},\n", - " {'average': 30.83,\n", - " 'q3': 37.0,\n", - " 'lower': 24.5,\n", - " 'upper': 44.5,\n", - " 'q1': 32.0,\n", - " 'median': 35.0,\n", - " 'pos': 74},\n", - " {'lower': 28.5,\n", - " 'upper': 48.5,\n", - " 'average': 37.61,\n", - " 'pos': 48,\n", - " 'q1': 36.0,\n", - " 'median': 40.0,\n", - " 'q3': 41.0},\n", - " {'pos': 23,\n", - " 'q1': 38.0,\n", - " 'average': 38.635,\n", - " 'q3': 41.0,\n", - " 'lower': 33.5,\n", - " 'median': 40.0,\n", - " 'upper': 45.5},\n", - " {'pos': 32,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'average': 38.29,\n", - " 'median': 40.0,\n", - " 'q1': 38.0,\n", - " 'q3': 41.0},\n", - " {'upper': 45.5,\n", - " 'q1': 38.0,\n", - " 'q3': 41.0,\n", - " 'pos': 38,\n", - " 'lower': 33.5,\n", - " 'median': 40.0,\n", - " 'average': 37.64},\n", - " {'pos': 16,\n", - " 'lower': 33.5,\n", - " 'q1': 38.0,\n", - " 'upper': 45.5,\n", - " 'average': 38.48,\n", - " 'q3': 41.0,\n", - " 'median': 40.0},\n", - " {'median': 39.0,\n", - " 'upper': 42.0,\n", - " 'q1': 37.0,\n", - " 'pos': 9,\n", - " 'q3': 39.0,\n", - " 'average': 37.36,\n", - " 'lower': 34.0},\n", - " {'upper': 43.0,\n", - " 'average': 38.11,\n", - " 'q3': 40.0,\n", - " 'pos': 36,\n", - " 'median': 40.0,\n", - " 'q1': 38.0,\n", - " 'lower': 35.0},\n", - " {'lower': 35.0,\n", - " 'upper': 43.0,\n", - " 'median': 40.0,\n", - " 'q1': 38.0,\n", - " 'q3': 40.0,\n", - " 'average': 37.855,\n", - " 'pos': 26},\n", - " {'upper': 46.0,\n", - " 'pos': 75,\n", - " 'q1': 31.0,\n", - " 'average': 31.06,\n", - " 'median': 35.0,\n", - " 'lower': 22.0,\n", - " 'q3': 37.0},\n", - " {'median': 40.0,\n", - " 'q1': 38.0,\n", - " 'q3': 41.0,\n", - " 'upper': 45.5,\n", - " 'lower': 33.5,\n", - " 'pos': 24,\n", - " 'average': 38.265},\n", - " {'pos': 30,\n", - " 'median': 40.0,\n", - " 'q1': 38.0,\n", - " 'q3': 40.0,\n", - " 'upper': 43.0,\n", - " 'lower': 35.0,\n", - " 'average': 38.245},\n", - " {'pos': 69,\n", - " 'q1': 34.0,\n", - " 'q3': 39.0,\n", - " 'lower': 26.5,\n", - " 'upper': 46.5,\n", - " 'average': 33.7,\n", - " 'median': 36.0},\n", - " {'pos': 77,\n", - " 'q1': 30.0,\n", - " 'q3': 36.0,\n", - " 'lower': 21.0,\n", - " 'upper': 45.0,\n", - " 'median': 35.0,\n", - " 'average': 30.805},\n", - " {'upper': 45.5,\n", - " 'q1': 38.0,\n", - " 'pos': 28,\n", - " 'q3': 41.0,\n", - " 'median': 40.0,\n", - " 'lower': 33.5,\n", - " 'average': 38.445},\n", - " {'q1': 38.0,\n", - " 'average': 38.44,\n", - " 'median': 40.0,\n", - " 'q3': 41.0,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'pos': 27},\n", - " {'q3': 37.0,\n", - " 'pos': 3,\n", - " 'average': 35.69,\n", - " 'q1': 35.0,\n", - " 'lower': 32.0,\n", - " 'upper': 40.0,\n", - " 'median': 37.0},\n", - " {'median': 36.5,\n", - " 'lower': 26.5,\n", - " 'upper': 46.5,\n", - " 'average': 35.96,\n", - " 'q3': 39.0,\n", - " 'pos': 67,\n", - " 'q1': 34.0},\n", - " {'q3': 38.0,\n", - " 'lower': 28.0,\n", - " 'upper': 44.0,\n", - " 'average': 33.565,\n", - " 'median': 35.0,\n", - " 'pos': 70,\n", - " 'q1': 34.0},\n", - " {'upper': 39.5,\n", - " 'lower': 27.5,\n", - " 'pos': 87,\n", - " 'median': 35.0,\n", - " 'average': 31.915,\n", - " 'q1': 32.0,\n", - " 'q3': 35.0},\n", - " {'lower': 30.0,\n", - " 'pos': 88,\n", - " 'average': 32.065,\n", - " 'upper': 38.0,\n", - " 'median': 35.0,\n", - " 'q1': 33.0,\n", - " 'q3': 35.0},\n", - " {'q3': 35.0,\n", - " 'lower': 27.5,\n", - " 'upper': 39.5,\n", - " 'median': 34.0,\n", - " 'average': 31.05,\n", - " 'q1': 32.0,\n", - " 'pos': 93},\n", - " {'upper': 47.0,\n", - " 'median': 39.5,\n", - " 'q3': 41.0,\n", - " 'q1': 37.0,\n", - " 'average': 37.79,\n", - " 'lower': 31.0,\n", - " 'pos': 46},\n", - " {'pos': 96,\n", - " 'average': 31.315,\n", - " 'median': 34.0,\n", - " 'q1': 32.0,\n", - " 'upper': 39.5,\n", - " 'lower': 27.5,\n", - " 'q3': 35.0},\n", - " {'average': 31.105,\n", - " 'upper': 41.0,\n", - " 'pos': 100,\n", - " 'median': 34.0,\n", - " 'q1': 31.0,\n", - " 'q3': 35.0,\n", - " 'lower': 25.0},\n", - " {'q3': 37.0,\n", - " 'average': 32.68,\n", - " 'q1': 33.0,\n", - " 'pos': 73,\n", - " 'lower': 27.0,\n", - " 'upper': 43.0,\n", - " 'median': 35.0},\n", - " {'median': 40.0,\n", - " 'lower': 33.5,\n", - " 'average': 38.2,\n", - " 'upper': 45.5,\n", - " 'pos': 25,\n", - " 'q3': 41.0,\n", - " 'q1': 38.0},\n", - " {'upper': 47.0,\n", - " 'q3': 41.0,\n", - " 'q1': 37.0,\n", - " 'average': 37.845,\n", - " 'median': 39.0,\n", - " 'pos': 53,\n", - " 'lower': 31.0},\n", - " {'q3': 39.0,\n", - " 'upper': 45.0,\n", - " 'lower': 29.0,\n", - " 'pos': 65,\n", - " 'median': 37.0,\n", - " 'q1': 35.0,\n", - " 'average': 35.995},\n", - " {'upper': 38.0,\n", - " 'median': 35.0,\n", - " 'q1': 33.0,\n", - " 'lower': 30.0,\n", - " 'q3': 35.0,\n", - " 'pos': 84,\n", - " 'average': 32.415},\n", - " {'median': 39.5,\n", - " 'pos': 54,\n", - " 'q1': 36.0,\n", - " 'upper': 48.5,\n", - " 'average': 37.59,\n", - " 'q3': 41.0,\n", - " 'lower': 28.5},\n", - " {'average': 37.77,\n", - " 'q1': 37.0,\n", - " 'lower': 32.5,\n", - " 'upper': 44.5,\n", - " 'q3': 40.0,\n", - " 'pos': 52,\n", - " 'median': 39.0},\n", - " {'upper': 47.5,\n", - " 'pos': 58,\n", - " 'median': 38.0,\n", - " 'average': 36.77,\n", - " 'q1': 35.0,\n", - " 'q3': 40.0,\n", - " 'lower': 27.5},\n", - " {'average': 36.25,\n", - " 'q3': 40.0,\n", - " 'q1': 35.0,\n", - " 'lower': 27.5,\n", - " 'median': 38.0,\n", - " 'pos': 63,\n", - " 'upper': 47.5},\n", - " {'q1': 38.0,\n", - " 'q3': 41.0,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'pos': 15,\n", - " 'average': 38.725,\n", - " 'median': 40.0},\n", - " {'pos': 94,\n", - " 'q3': 35.0,\n", - " 'q1': 32.0,\n", - " 'upper': 39.5,\n", - " 'average': 30.775,\n", - " 'median': 34.0,\n", - " 'lower': 27.5},\n", - " {'median': 39.0,\n", - " 'q1': 36.0,\n", - " 'q3': 41.0,\n", - " 'pos': 51,\n", - " 'lower': 28.5,\n", - " 'upper': 48.5,\n", - " 'average': 37.53},\n", - " {'q1': 33.0,\n", - " 'upper': 40.5,\n", - " 'median': 35.0,\n", - " 'average': 32.76,\n", - " 'pos': 81,\n", - " 'lower': 28.5,\n", - " 'q3': 36.0},\n", - " {'average': 37.78,\n", - " 'q3': 40.0,\n", - " 'lower': 32.5,\n", - " 'median': 40.0,\n", - " 'upper': 44.5,\n", - " 'pos': 42,\n", - " 'q1': 37.0},\n", - " {'upper': 42.0,\n", - " 'q1': 32.0,\n", - " 'lower': 26.0,\n", - " 'median': 35.0,\n", - " 'pos': 79,\n", - " 'average': 32.46,\n", - " 'q3': 36.0},\n", - " {'q1': 36.0,\n", - " 'pos': 49,\n", - " 'average': 37.21,\n", - " 'lower': 30.0,\n", - " 'upper': 46.0,\n", - " 'median': 39.0,\n", - " 'q3': 40.0},\n", - " {'upper': 47.5,\n", - " 'pos': 62,\n", - " 'q1': 35.0,\n", - " 'q3': 40.0,\n", - " 'median': 38.0,\n", - " 'lower': 27.5,\n", - " 'average': 36.145},\n", - " {'q3': 36.0,\n", - " 'average': 31.46,\n", - " 'pos': 78,\n", - " 'median': 35.0,\n", - " 'lower': 23.5,\n", - " 'upper': 43.5,\n", - " 'q1': 31.0},\n", - " {'median': 40.0,\n", - " 'average': 38.245,\n", - " 'q3': 41.0,\n", - " 'pos': 33,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'q1': 38.0},\n", - " {'q3': 41.0,\n", - " 'lower': 33.5,\n", - " 'q1': 38.0,\n", - " 'upper': 45.5,\n", - " 'pos': 14,\n", - " 'average': 38.965,\n", - " 'median': 40.0},\n", - " {'median': 40.0,\n", - " 'q1': 38.0,\n", - " 'q3': 41.0,\n", - " 'lower': 33.5,\n", - " 'average': 38.41,\n", - " 'upper': 45.5,\n", - " 'pos': 22},\n", - " {'q3': 35.0,\n", - " 'median': 34.5,\n", - " 'upper': 38.0,\n", - " 'pos': 90,\n", - " 'q1': 33.0,\n", - " 'lower': 30.0,\n", - " 'average': 32.275},\n", - " {'lower': 33.5,\n", - " 'median': 40.0,\n", - " 'pos': 19,\n", - " 'average': 38.425,\n", - " 'q1': 38.0,\n", - " 'q3': 41.0,\n", - " 'upper': 45.5},\n", - " {'average': 38.385,\n", - " 'median': 40.0,\n", - " 'lower': 33.5,\n", - " 'q1': 38.0,\n", - " 'upper': 45.5,\n", - " 'pos': 35,\n", - " 'q3': 41.0},\n", - " {'q1': 38.0,\n", - " 'q3': 41.0,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'average': 38.795,\n", - " 'pos': 31,\n", - " 'median': 40.0},\n", - " {'upper': 48.5,\n", - " 'pos': 45,\n", - " 'average': 37.45,\n", - " 'median': 40.0,\n", - " 'q1': 36.0,\n", - " 'q3': 41.0,\n", - " 'lower': 28.5},\n", - " {'upper': 46.0,\n", - " 'pos': 76,\n", - " 'q1': 31.0,\n", - " 'median': 35.0,\n", - " 'q3': 37.0,\n", - " 'average': 30.265,\n", - " 'lower': 22.0},\n", - " {'pos': 44,\n", - " 'q1': 37.0,\n", - " 'upper': 47.0,\n", - " 'average': 37.565,\n", - " 'lower': 31.0,\n", - " 'q3': 41.0,\n", - " 'median': 40.0},\n", - " {'upper': 45.5,\n", - " 'q3': 38.0,\n", - " 'q1': 33.0,\n", - " 'lower': 25.5,\n", - " 'median': 35.0,\n", - " 'average': 33.005,\n", - " 'pos': 71},\n", - " {'pos': 47,\n", - " 'average': 37.665,\n", - " 'median': 39.0,\n", - " 'q1': 37.0,\n", - " 'lower': 31.0,\n", - " 'upper': 47.0,\n", - " 'q3': 41.0},\n", - " {'q3': 37.0,\n", - " 'pos': 5,\n", - " 'average': 35.095,\n", - " 'median': 35.0,\n", - " 'q1': 35.0,\n", - " 'lower': 32.0,\n", - " 'upper': 40.0},\n", - " {'pos': 4,\n", - " 'average': 35.68,\n", - " 'median': 37.0,\n", - " 'q3': 37.0,\n", - " 'lower': 32.0,\n", - " 'upper': 40.0,\n", - " 'q1': 35.0},\n", - " {'upper': 47.5,\n", - " 'pos': 60,\n", - " 'median': 38.0,\n", - " 'average': 35.985,\n", - " 'q1': 35.0,\n", - " 'q3': 40.0,\n", - " 'lower': 27.5},\n", - " {'q1': 32.0,\n", - " 'average': 32.665,\n", - " 'q3': 35.0,\n", - " 'lower': 27.5,\n", - " 'median': 35.0,\n", - " 'pos': 91,\n", - " 'upper': 39.5},\n", - " {'average': 32.195,\n", - " 'median': 35.0,\n", - " 'pos': 85,\n", - " 'q1': 33.0,\n", - " 'q3': 35.0,\n", - " 'lower': 30.0,\n", - " 'upper': 38.0}]}" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" + "name": "stdout", + "output_type": "stream", + "text": [ + " pos score\n", + "0 0 2\n", + "1 1 19\n", + "2 2 33\n", + "3 3 35\n", + "4 4 37\n", + "... ... ...\n", + "20195 96 35\n", + "20196 97 32\n", + "20197 98 35\n", + "20198 99 35\n", + "20199 100 33\n", + "\n", + "[20200 rows x 2 columns]\n" + ] } ], "source": [ - "pb.base_sequence_quality(\"example.fastq\")" + "result = pb.base_sequence_quality(\"example.fastq\", output_type=\"pandas.DataFrame\")\n", + "print(result)" ] }, { @@ -832,715 +114,35 @@ "outputs": [ { "data": { + "text/html": [ + "
\n", + "shape: (20_200, 2)
posscore
i64i8
02
119
233
335
437
9635
9732
9835
9935
10033
" + ], "text/plain": [ - "{'base_quality_warn': 'pass',\n", - " 'base_per_pos_data': [{'average': 32.195,\n", - " 'pos': 85,\n", - " 'q3': 35.0,\n", - " 'lower': 30.0,\n", - " 'upper': 38.0,\n", - " 'median': 35.0,\n", - " 'q1': 33.0},\n", - " {'average': 38.245,\n", - " 'median': 40.0,\n", - " 'q3': 40.0,\n", - " 'lower': 35.0,\n", - " 'pos': 30,\n", - " 'upper': 43.0,\n", - " 'q1': 38.0},\n", - " {'pos': 2,\n", - " 'average': 32.015,\n", - " 'q3': 34.0,\n", - " 'lower': 26.5,\n", - " 'upper': 38.5,\n", - " 'q1': 31.0,\n", - " 'median': 34.0},\n", - " {'lower': 30.0,\n", - " 'pos': 89,\n", - " 'upper': 38.0,\n", - " 'average': 32.44,\n", - " 'median': 35.0,\n", - " 'q1': 33.0,\n", - " 'q3': 35.0},\n", - " {'q3': 39.0,\n", - " 'average': 37.5,\n", - " 'q1': 37.0,\n", - " 'pos': 12,\n", - " 'median': 39.0,\n", - " 'lower': 34.0,\n", - " 'upper': 42.0},\n", - " {'median': 40.0,\n", - " 'pos': 23,\n", - " 'lower': 33.5,\n", - " 'q3': 41.0,\n", - " 'q1': 38.0,\n", - " 'upper': 45.5,\n", - " 'average': 38.635},\n", - " {'average': 38.595,\n", - " 'median': 40.0,\n", - " 'q3': 41.0,\n", - " 'lower': 33.5,\n", - " 'q1': 38.0,\n", - " 'pos': 29,\n", - " 'upper': 45.5},\n", - " {'average': 37.35,\n", - " 'pos': 57,\n", - " 'q1': 36.0,\n", - " 'median': 39.0,\n", - " 'lower': 30.0,\n", - " 'upper': 46.0,\n", - " 'q3': 40.0},\n", - " {'pos': 56,\n", - " 'average': 37.59,\n", - " 'upper': 46.0,\n", - " 'median': 39.0,\n", - " 'q1': 36.0,\n", - " 'q3': 40.0,\n", - " 'lower': 30.0},\n", - " {'average': 36.08,\n", - " 'q3': 40.0,\n", - " 'q1': 35.0,\n", - " 'median': 38.0,\n", - " 'upper': 47.5,\n", - " 'pos': 59,\n", - " 'lower': 27.5},\n", - " {'q1': 32.0,\n", - " 'median': 35.0,\n", - " 'average': 31.835,\n", - " 'q3': 35.0,\n", - " 'pos': 92,\n", - " 'lower': 27.5,\n", - " 'upper': 39.5},\n", - " {'q3': 41.0,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'pos': 24,\n", - " 'median': 40.0,\n", - " 'average': 38.265,\n", - " 'q1': 38.0},\n", - " {'lower': 30.0,\n", - " 'upper': 46.0,\n", - " 'pos': 49,\n", - " 'median': 39.0,\n", - " 'average': 37.21,\n", - " 'q1': 36.0,\n", - " 'q3': 40.0},\n", - " {'upper': 38.0,\n", - " 'pos': 90,\n", - " 'q1': 33.0,\n", - " 'average': 32.275,\n", - " 'q3': 35.0,\n", - " 'lower': 30.0,\n", - " 'median': 34.5},\n", - " {'q1': 34.0,\n", - " 'pos': 70,\n", - " 'lower': 28.0,\n", - " 'average': 33.565,\n", - " 'median': 35.0,\n", - " 'q3': 38.0,\n", - " 'upper': 44.0},\n", - " {'upper': 45.5,\n", - " 'pos': 27,\n", - " 'q1': 38.0,\n", - " 'average': 38.44,\n", - " 'median': 40.0,\n", - " 'q3': 41.0,\n", - " 'lower': 33.5},\n", - " {'upper': 42.0,\n", - " 'average': 37.675,\n", - " 'q3': 39.0,\n", - " 'pos': 10,\n", - " 'median': 39.0,\n", - " 'q1': 37.0,\n", - " 'lower': 34.0},\n", - " {'q1': 32.0,\n", - " 'upper': 39.5,\n", - " 'q3': 35.0,\n", - " 'pos': 98,\n", - " 'average': 31.55,\n", - " 'lower': 27.5,\n", - " 'median': 34.0},\n", - " {'median': 40.0,\n", - " 'pos': 13,\n", - " 'average': 38.94,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'q3': 41.0,\n", - " 'q1': 38.0},\n", - " {'upper': 43.0,\n", - " 'q3': 40.0,\n", - " 'median': 40.0,\n", - " 'pos': 21,\n", - " 'average': 38.445,\n", - " 'q1': 38.0,\n", - " 'lower': 35.0},\n", - " {'lower': 27.5,\n", - " 'median': 34.0,\n", - " 'pos': 99,\n", - " 'average': 31.25,\n", - " 'q3': 35.0,\n", - " 'q1': 32.0,\n", - " 'upper': 39.5},\n", - " {'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'q3': 41.0,\n", - " 'pos': 31,\n", - " 'average': 38.795,\n", - " 'q1': 38.0,\n", - " 'median': 40.0},\n", - " {'average': 37.855,\n", - " 'lower': 35.0,\n", - " 'upper': 43.0,\n", - " 'pos': 26,\n", - " 'q3': 40.0,\n", - " 'q1': 38.0,\n", - " 'median': 40.0},\n", - " {'pos': 33,\n", - " 'upper': 45.5,\n", - " 'average': 38.245,\n", - " 'q1': 38.0,\n", - " 'q3': 41.0,\n", - " 'lower': 33.5,\n", - " 'median': 40.0},\n", - " {'average': 37.665,\n", - " 'pos': 47,\n", - " 'q3': 41.0,\n", - " 'lower': 31.0,\n", - " 'median': 39.0,\n", - " 'q1': 37.0,\n", - " 'upper': 47.0},\n", - " {'average': 38.505,\n", - " 'q1': 38.0,\n", - " 'q3': 41.0,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'pos': 17,\n", - " 'median': 40.0},\n", - " {'q3': 40.0,\n", - " 'median': 39.0,\n", - " 'upper': 44.5,\n", - " 'average': 37.77,\n", - " 'pos': 52,\n", - " 'q1': 37.0,\n", - " 'lower': 32.5},\n", - " {'q3': 35.0,\n", - " 'upper': 39.5,\n", - " 'median': 35.0,\n", - " 'q1': 32.0,\n", - " 'lower': 27.5,\n", - " 'pos': 87,\n", - " 'average': 31.915},\n", - " {'upper': 48.5,\n", - " 'pos': 48,\n", - " 'q3': 41.0,\n", - " 'average': 37.61,\n", - " 'q1': 36.0,\n", - " 'median': 40.0,\n", - " 'lower': 28.5},\n", - " {'median': 40.0,\n", - " 'upper': 43.0,\n", - " 'q3': 40.0,\n", - " 'lower': 35.0,\n", - " 'q1': 38.0,\n", - " 'average': 37.895,\n", - " 'pos': 39},\n", - " {'upper': 45.5,\n", - " 'q1': 38.0,\n", - " 'average': 38.2,\n", - " 'q3': 41.0,\n", - " 'lower': 33.5,\n", - " 'pos': 25,\n", - " 'median': 40.0},\n", - " {'pos': 63,\n", - " 'q1': 35.0,\n", - " 'average': 36.25,\n", - " 'q3': 40.0,\n", - " 'lower': 27.5,\n", - " 'upper': 47.5,\n", - " 'median': 38.0},\n", - " {'pos': 80,\n", - " 'average': 32.61,\n", - " 'upper': 42.0,\n", - " 'q1': 32.0,\n", - " 'median': 35.0,\n", - " 'q3': 36.0,\n", - " 'lower': 26.0},\n", - " {'q3': 41.0,\n", - " 'lower': 31.0,\n", - " 'upper': 47.0,\n", - " 'q1': 37.0,\n", - " 'median': 39.0,\n", - " 'average': 37.845,\n", - " 'pos': 53},\n", - " {'upper': 45.5,\n", - " 'pos': 16,\n", - " 'median': 40.0,\n", - " 'average': 38.48,\n", - " 'q3': 41.0,\n", - " 'q1': 38.0,\n", - " 'lower': 33.5},\n", - " {'q1': 38.0,\n", - " 'pos': 14,\n", - " 'average': 38.965,\n", - " 'median': 40.0,\n", - " 'q3': 41.0,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5},\n", - " {'pos': 55,\n", - " 'q3': 40.0,\n", - " 'median': 39.0,\n", - " 'lower': 30.0,\n", - " 'q1': 36.0,\n", - " 'upper': 46.0,\n", - " 'average': 37.55},\n", - " {'average': 37.78,\n", - " 'median': 40.0,\n", - " 'q3': 40.0,\n", - " 'pos': 42,\n", - " 'q1': 37.0,\n", - " 'lower': 32.5,\n", - " 'upper': 44.5},\n", - " {'average': 37.425,\n", - " 'q1': 36.0,\n", - " 'upper': 48.5,\n", - " 'pos': 50,\n", - " 'median': 39.0,\n", - " 'q3': 41.0,\n", - " 'lower': 28.5},\n", - " {'lower': 25.0,\n", - " 'upper': 41.0,\n", - " 'q1': 31.0,\n", - " 'average': 31.105,\n", - " 'median': 34.0,\n", - " 'q3': 35.0,\n", - " 'pos': 100},\n", - " {'upper': 38.5,\n", - " 'q1': 31.0,\n", - " 'q3': 34.0,\n", - " 'lower': 26.5,\n", - " 'average': 30.135,\n", - " 'median': 33.0,\n", - " 'pos': 0},\n", - " {'lower': 26.5,\n", - " 'q1': 31.0,\n", - " 'median': 34.0,\n", - " 'upper': 38.5,\n", - " 'pos': 1,\n", - " 'q3': 34.0,\n", - " 'average': 31.21},\n", - " {'q3': 37.0,\n", - " 'q1': 32.0,\n", - " 'upper': 44.5,\n", - " 'pos': 74,\n", - " 'average': 30.83,\n", - " 'median': 35.0,\n", - " 'lower': 24.5},\n", - " {'upper': 38.0,\n", - " 'q3': 35.0,\n", - " 'median': 35.0,\n", - " 'pos': 84,\n", - " 'average': 32.415,\n", - " 'q1': 33.0,\n", - " 'lower': 30.0},\n", - " {'median': 35.0,\n", - " 'q1': 35.0,\n", - " 'q3': 37.0,\n", - " 'lower': 32.0,\n", - " 'average': 35.095,\n", - " 'pos': 5,\n", - " 'upper': 40.0},\n", - " {'pos': 3,\n", - " 'median': 37.0,\n", - " 'q1': 35.0,\n", - " 'q3': 37.0,\n", - " 'lower': 32.0,\n", - " 'average': 35.69,\n", - " 'upper': 40.0},\n", - " {'pos': 40,\n", - " 'q1': 38.0,\n", - " 'average': 37.95,\n", - " 'q3': 40.0,\n", - " 'lower': 35.0,\n", - " 'median': 40.0,\n", - " 'upper': 43.0},\n", - " {'pos': 58,\n", - " 'q3': 40.0,\n", - " 'lower': 27.5,\n", - " 'upper': 47.5,\n", - " 'median': 38.0,\n", - " 'q1': 35.0,\n", - " 'average': 36.77},\n", - " {'median': 37.0,\n", - " 'q3': 40.0,\n", - " 'lower': 27.5,\n", - " 'q1': 35.0,\n", - " 'upper': 47.5,\n", - " 'pos': 64,\n", - " 'average': 36.095},\n", - " {'pos': 41,\n", - " 'q3': 41.0,\n", - " 'median': 40.0,\n", - " 'lower': 31.0,\n", - " 'upper': 47.0,\n", - " 'q1': 37.0,\n", - " 'average': 37.87},\n", - " {'average': 35.99,\n", - " 'median': 38.0,\n", - " 'q1': 35.0,\n", - " 'q3': 40.0,\n", - " 'lower': 27.5,\n", - " 'upper': 47.5,\n", - " 'pos': 61},\n", - " {'q3': 39.0,\n", - " 'median': 39.0,\n", - " 'average': 37.625,\n", - " 'pos': 8,\n", - " 'lower': 34.0,\n", - " 'q1': 37.0,\n", - " 'upper': 42.0},\n", - " {'upper': 48.5,\n", - " 'q3': 41.0,\n", - " 'average': 37.45,\n", - " 'pos': 45,\n", - " 'q1': 36.0,\n", - " 'median': 40.0,\n", - " 'lower': 28.5},\n", - " {'pos': 71,\n", - " 'average': 33.005,\n", - " 'q1': 33.0,\n", - " 'median': 35.0,\n", - " 'upper': 45.5,\n", - " 'lower': 25.5,\n", - " 'q3': 38.0},\n", - " {'median': 35.0,\n", - " 'average': 32.03,\n", - " 'pos': 83,\n", - " 'q1': 33.0,\n", - " 'lower': 30.0,\n", - " 'upper': 38.0,\n", - " 'q3': 35.0},\n", - " {'pos': 36,\n", - " 'upper': 43.0,\n", - " 'median': 40.0,\n", - " 'average': 38.11,\n", - " 'q1': 38.0,\n", - " 'q3': 40.0,\n", - " 'lower': 35.0},\n", - " {'lower': 30.0,\n", - " 'upper': 38.0,\n", - " 'pos': 86,\n", - " 'q1': 33.0,\n", - " 'average': 31.815,\n", - " 'q3': 35.0,\n", - " 'median': 35.0},\n", - " {'lower': 35.0,\n", - " 'pos': 37,\n", - " 'upper': 43.0,\n", - " 'q3': 40.0,\n", - " 'q1': 38.0,\n", - " 'average': 38.0,\n", - " 'median': 40.0},\n", - " {'lower': 34.0,\n", - " 'upper': 42.0,\n", - " 'average': 37.36,\n", - " 'q3': 39.0,\n", - " 'q1': 37.0,\n", - " 'median': 39.0,\n", - " 'pos': 9},\n", - " {'q3': 36.0,\n", - " 'lower': 28.5,\n", - " 'median': 35.0,\n", - " 'upper': 40.5,\n", - " 'q1': 33.0,\n", - " 'average': 32.76,\n", - " 'pos': 81},\n", - " {'pos': 38,\n", - " 'q3': 41.0,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'average': 37.64,\n", - " 'q1': 38.0,\n", - " 'median': 40.0},\n", - " {'average': 32.065,\n", - " 'q3': 35.0,\n", - " 'upper': 38.0,\n", - " 'lower': 30.0,\n", - " 'median': 35.0,\n", - " 'q1': 33.0,\n", - " 'pos': 88},\n", - " {'average': 31.525,\n", - " 'q3': 36.0,\n", - " 'pos': 82,\n", - " 'lower': 28.5,\n", - " 'median': 35.0,\n", - " 'upper': 40.5,\n", - " 'q1': 33.0},\n", - " {'pos': 91,\n", - " 'average': 32.665,\n", - " 'q1': 32.0,\n", - " 'q3': 35.0,\n", - " 'median': 35.0,\n", - " 'lower': 27.5,\n", - " 'upper': 39.5},\n", - " {'q1': 34.0,\n", - " 'q3': 39.0,\n", - " 'pos': 69,\n", - " 'upper': 46.5,\n", - " 'lower': 26.5,\n", - " 'median': 36.0,\n", - " 'average': 33.7},\n", - " {'median': 35.0,\n", - " 'lower': 27.0,\n", - " 'average': 32.68,\n", - " 'pos': 73,\n", - " 'q1': 33.0,\n", - " 'q3': 37.0,\n", - " 'upper': 43.0},\n", - " {'q1': 36.0,\n", - " 'q3': 41.0,\n", - " 'lower': 28.5,\n", - " 'average': 37.53,\n", - " 'upper': 48.5,\n", - " 'pos': 51,\n", - " 'median': 39.0},\n", - " {'pos': 43,\n", - " 'median': 40.0,\n", - " 'q1': 38.0,\n", - " 'q3': 40.0,\n", - " 'lower': 35.0,\n", - " 'upper': 43.0,\n", - " 'average': 37.775},\n", - " {'q3': 39.0,\n", - " 'median': 39.0,\n", - " 'pos': 11,\n", - " 'upper': 42.0,\n", - " 'lower': 34.0,\n", - " 'q1': 37.0,\n", - " 'average': 37.71},\n", - " {'q1': 38.0,\n", - " 'pos': 28,\n", - " 'median': 40.0,\n", - " 'lower': 33.5,\n", - " 'average': 38.445,\n", - " 'q3': 41.0,\n", - " 'upper': 45.5},\n", - " {'average': 38.47,\n", - " 'q1': 38.0,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'q3': 41.0,\n", - " 'pos': 18,\n", - " 'median': 40.0},\n", - " {'median': 40.0,\n", - " 'q3': 41.0,\n", - " 'pos': 44,\n", - " 'q1': 37.0,\n", - " 'average': 37.565,\n", - " 'upper': 47.0,\n", - " 'lower': 31.0},\n", - " {'q1': 35.0,\n", - " 'pos': 6,\n", - " 'q3': 37.0,\n", - " 'median': 35.0,\n", - " 'upper': 40.0,\n", - " 'average': 35.145,\n", - " 'lower': 32.0},\n", - " {'median': 40.0,\n", - " 'q3': 41.0,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'pos': 35,\n", - " 'q1': 38.0,\n", - " 'average': 38.385},\n", - " {'pos': 60,\n", - " 'lower': 27.5,\n", - " 'median': 38.0,\n", - " 'average': 35.985,\n", - " 'upper': 47.5,\n", - " 'q1': 35.0,\n", - " 'q3': 40.0},\n", - " {'q3': 37.0,\n", - " 'average': 35.4,\n", - " 'q1': 35.0,\n", - " 'median': 36.0,\n", - " 'lower': 32.0,\n", - " 'upper': 40.0,\n", - " 'pos': 7},\n", - " {'q3': 37.0,\n", - " 'lower': 27.0,\n", - " 'upper': 43.0,\n", - " 'median': 35.0,\n", - " 'q1': 33.0,\n", - " 'pos': 72,\n", - " 'average': 33.265},\n", - " {'average': 30.265,\n", - " 'pos': 76,\n", - " 'median': 35.0,\n", - " 'q3': 37.0,\n", - " 'lower': 22.0,\n", - " 'upper': 46.0,\n", - " 'q1': 31.0},\n", - " {'q1': 35.0,\n", - " 'average': 35.875,\n", - " 'q3': 39.0,\n", - " 'upper': 45.0,\n", - " 'pos': 66,\n", - " 'lower': 29.0,\n", - " 'median': 37.0},\n", - " {'average': 36.145,\n", - " 'pos': 62,\n", - " 'q3': 40.0,\n", - " 'lower': 27.5,\n", - " 'q1': 35.0,\n", - " 'upper': 47.5,\n", - " 'median': 38.0},\n", - " {'pos': 93,\n", - " 'median': 34.0,\n", - " 'lower': 27.5,\n", - " 'upper': 39.5,\n", - " 'q1': 32.0,\n", - " 'q3': 35.0,\n", - " 'average': 31.05},\n", - " {'average': 35.68,\n", - " 'median': 37.0,\n", - " 'q3': 37.0,\n", - " 'upper': 40.0,\n", - " 'lower': 32.0,\n", - " 'pos': 4,\n", - " 'q1': 35.0},\n", - " {'pos': 46,\n", - " 'lower': 31.0,\n", - " 'q1': 37.0,\n", - " 'average': 37.79,\n", - " 'q3': 41.0,\n", - " 'median': 39.5,\n", - " 'upper': 47.0},\n", - " {'pos': 20,\n", - " 'median': 40.0,\n", - " 'q3': 41.0,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'average': 38.625,\n", - " 'q1': 38.0},\n", - " {'q1': 36.0,\n", - " 'upper': 48.5,\n", - " 'pos': 54,\n", - " 'q3': 41.0,\n", - " 'lower': 28.5,\n", - " 'average': 37.59,\n", - " 'median': 39.5},\n", - " {'pos': 95,\n", - " 'q3': 35.0,\n", - " 'q1': 32.0,\n", - " 'average': 31.425,\n", - " 'lower': 27.5,\n", - " 'upper': 39.5,\n", - " 'median': 34.0},\n", - " {'upper': 42.0,\n", - " 'lower': 26.0,\n", - " 'pos': 79,\n", - " 'q3': 36.0,\n", - " 'average': 32.46,\n", - " 'median': 35.0,\n", - " 'q1': 32.0},\n", - " {'average': 31.46,\n", - " 'lower': 23.5,\n", - " 'q3': 36.0,\n", - " 'pos': 78,\n", - " 'q1': 31.0,\n", - " 'upper': 43.5,\n", - " 'median': 35.0},\n", - " {'q1': 32.0,\n", - " 'lower': 27.5,\n", - " 'median': 34.0,\n", - " 'average': 30.775,\n", - " 'pos': 94,\n", - " 'q3': 35.0,\n", - " 'upper': 39.5},\n", - " {'q3': 35.0,\n", - " 'lower': 27.5,\n", - " 'q1': 32.0,\n", - " 'upper': 39.5,\n", - " 'pos': 96,\n", - " 'average': 31.315,\n", - " 'median': 34.0},\n", - " {'pos': 75,\n", - " 'average': 31.06,\n", - " 'q1': 31.0,\n", - " 'q3': 37.0,\n", - " 'lower': 22.0,\n", - " 'upper': 46.0,\n", - " 'median': 35.0},\n", - " {'q3': 39.0,\n", - " 'pos': 67,\n", - " 'lower': 26.5,\n", - " 'upper': 46.5,\n", - " 'median': 36.5,\n", - " 'average': 35.96,\n", - " 'q1': 34.0},\n", - " {'lower': 33.5,\n", - " 'median': 40.0,\n", - " 'q3': 41.0,\n", - " 'upper': 45.5,\n", - " 'pos': 19,\n", - " 'average': 38.425,\n", - " 'q1': 38.0},\n", - " {'average': 38.725,\n", - " 'q1': 38.0,\n", - " 'pos': 15,\n", - " 'median': 40.0,\n", - " 'q3': 41.0,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5},\n", - " {'upper': 45.5,\n", - " 'pos': 34,\n", - " 'average': 38.205,\n", - " 'lower': 33.5,\n", - " 'q1': 38.0,\n", - " 'q3': 41.0,\n", - " 'median': 40.0},\n", - " {'average': 38.41,\n", - " 'q3': 41.0,\n", - " 'pos': 22,\n", - " 'median': 40.0,\n", - " 'lower': 33.5,\n", - " 'q1': 38.0,\n", - " 'upper': 45.5},\n", - " {'average': 38.29,\n", - " 'median': 40.0,\n", - " 'q1': 38.0,\n", - " 'upper': 45.5,\n", - " 'pos': 32,\n", - " 'q3': 41.0,\n", - " 'lower': 33.5},\n", - " {'median': 35.0,\n", - " 'q1': 30.0,\n", - " 'upper': 45.0,\n", - " 'average': 30.805,\n", - " 'q3': 36.0,\n", - " 'pos': 77,\n", - " 'lower': 21.0},\n", - " {'average': 35.91,\n", - " 'q1': 34.0,\n", - " 'q3': 39.0,\n", - " 'median': 36.0,\n", - " 'lower': 26.5,\n", - " 'upper': 46.5,\n", - " 'pos': 68},\n", - " {'lower': 25.0,\n", - " 'median': 34.0,\n", - " 'upper': 41.0,\n", - " 'pos': 97,\n", - " 'q3': 35.0,\n", - " 'q1': 31.0,\n", - " 'average': 30.67},\n", - " {'lower': 29.0,\n", - " 'median': 37.0,\n", - " 'q1': 35.0,\n", - " 'q3': 39.0,\n", - " 'average': 35.995,\n", - " 'upper': 45.0,\n", - " 'pos': 65}]}" + "shape: (20_200, 2)\n", + "┌─────┬───────┐\n", + "│ pos ┆ score │\n", + "│ --- ┆ --- │\n", + "│ i64 ┆ i8 │\n", + "╞═════╪═══════╡\n", + "│ 0 ┆ 2 │\n", + "│ 1 ┆ 19 │\n", + "│ 2 ┆ 33 │\n", + "│ 3 ┆ 35 │\n", + "│ 4 ┆ 37 │\n", + "│ … ┆ … │\n", + "│ 96 ┆ 35 │\n", + "│ 97 ┆ 32 │\n", + "│ 98 ┆ 35 │\n", + "│ 99 ┆ 35 │\n", + "│ 100 ┆ 33 │\n", + "└─────┴───────┘" ] }, "execution_count": 4, @@ -1568,715 +170,35 @@ "outputs": [ { "data": { + "text/html": [ + "
\n", + "shape: (20_200, 2)
posscore
i64i8
02
119
233
335
437
9635
9732
9835
9935
10033
" + ], "text/plain": [ - "{'base_quality_warn': 'pass',\n", - " 'base_per_pos_data': [{'average': 35.69,\n", - " 'median': 37.0,\n", - " 'q1': 35.0,\n", - " 'lower': 32.0,\n", - " 'upper': 40.0,\n", - " 'q3': 37.0,\n", - " 'pos': 3},\n", - " {'pos': 39,\n", - " 'average': 37.895,\n", - " 'q3': 40.0,\n", - " 'lower': 35.0,\n", - " 'median': 40.0,\n", - " 'q1': 38.0,\n", - " 'upper': 43.0},\n", - " {'pos': 20,\n", - " 'average': 38.625,\n", - " 'q3': 41.0,\n", - " 'median': 40.0,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'q1': 38.0},\n", - " {'pos': 28,\n", - " 'q1': 38.0,\n", - " 'average': 38.445,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'q3': 41.0,\n", - " 'median': 40.0},\n", - " {'pos': 49,\n", - " 'average': 37.21,\n", - " 'q1': 36.0,\n", - " 'q3': 40.0,\n", - " 'lower': 30.0,\n", - " 'median': 39.0,\n", - " 'upper': 46.0},\n", - " {'q1': 35.0,\n", - " 'pos': 59,\n", - " 'upper': 47.5,\n", - " 'median': 38.0,\n", - " 'average': 36.08,\n", - " 'lower': 27.5,\n", - " 'q3': 40.0},\n", - " {'pos': 67,\n", - " 'average': 35.96,\n", - " 'lower': 26.5,\n", - " 'q1': 34.0,\n", - " 'upper': 46.5,\n", - " 'q3': 39.0,\n", - " 'median': 36.5},\n", - " {'average': 37.45,\n", - " 'median': 40.0,\n", - " 'q3': 41.0,\n", - " 'q1': 36.0,\n", - " 'lower': 28.5,\n", - " 'pos': 45,\n", - " 'upper': 48.5},\n", - " {'lower': 35.0,\n", - " 'q3': 40.0,\n", - " 'average': 38.0,\n", - " 'pos': 37,\n", - " 'median': 40.0,\n", - " 'q1': 38.0,\n", - " 'upper': 43.0},\n", - " {'pos': 22,\n", - " 'average': 38.41,\n", - " 'median': 40.0,\n", - " 'q3': 41.0,\n", - " 'q1': 38.0,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5},\n", - " {'pos': 15,\n", - " 'average': 38.725,\n", - " 'q3': 41.0,\n", - " 'lower': 33.5,\n", - " 'q1': 38.0,\n", - " 'upper': 45.5,\n", - " 'median': 40.0},\n", - " {'q3': 41.0,\n", - " 'lower': 33.5,\n", - " 'pos': 19,\n", - " 'upper': 45.5,\n", - " 'average': 38.425,\n", - " 'median': 40.0,\n", - " 'q1': 38.0},\n", - " {'median': 35.0,\n", - " 'pos': 74,\n", - " 'q3': 37.0,\n", - " 'average': 30.83,\n", - " 'upper': 44.5,\n", - " 'q1': 32.0,\n", - " 'lower': 24.5},\n", - " {'q3': 37.0,\n", - " 'pos': 76,\n", - " 'q1': 31.0,\n", - " 'upper': 46.0,\n", - " 'average': 30.265,\n", - " 'median': 35.0,\n", - " 'lower': 22.0},\n", - " {'pos': 31,\n", - " 'average': 38.795,\n", - " 'median': 40.0,\n", - " 'q3': 41.0,\n", - " 'lower': 33.5,\n", - " 'q1': 38.0,\n", - " 'upper': 45.5},\n", - " {'pos': 23,\n", - " 'average': 38.635,\n", - " 'median': 40.0,\n", - " 'q3': 41.0,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'q1': 38.0},\n", - " {'q3': 41.0,\n", - " 'median': 39.0,\n", - " 'upper': 48.5,\n", - " 'pos': 51,\n", - " 'q1': 36.0,\n", - " 'lower': 28.5,\n", - " 'average': 37.53},\n", - " {'upper': 40.0,\n", - " 'median': 37.0,\n", - " 'average': 35.68,\n", - " 'q1': 35.0,\n", - " 'q3': 37.0,\n", - " 'pos': 4,\n", - " 'lower': 32.0},\n", - " {'average': 32.46,\n", - " 'upper': 42.0,\n", - " 'median': 35.0,\n", - " 'q1': 32.0,\n", - " 'pos': 79,\n", - " 'q3': 36.0,\n", - " 'lower': 26.0},\n", - " {'average': 32.61,\n", - " 'q1': 32.0,\n", - " 'pos': 80,\n", - " 'median': 35.0,\n", - " 'q3': 36.0,\n", - " 'upper': 42.0,\n", - " 'lower': 26.0},\n", - " {'q1': 35.0,\n", - " 'median': 38.0,\n", - " 'q3': 40.0,\n", - " 'upper': 47.5,\n", - " 'lower': 27.5,\n", - " 'pos': 58,\n", - " 'average': 36.77},\n", - " {'average': 32.68,\n", - " 'median': 35.0,\n", - " 'lower': 27.0,\n", - " 'q1': 33.0,\n", - " 'q3': 37.0,\n", - " 'upper': 43.0,\n", - " 'pos': 73},\n", - " {'median': 34.0,\n", - " 'pos': 97,\n", - " 'q1': 31.0,\n", - " 'upper': 41.0,\n", - " 'q3': 35.0,\n", - " 'lower': 25.0,\n", - " 'average': 30.67},\n", - " {'median': 34.0,\n", - " 'lower': 27.5,\n", - " 'upper': 39.5,\n", - " 'average': 31.55,\n", - " 'pos': 98,\n", - " 'q3': 35.0,\n", - " 'q1': 32.0},\n", - " {'upper': 42.0,\n", - " 'median': 39.0,\n", - " 'pos': 8,\n", - " 'q1': 37.0,\n", - " 'q3': 39.0,\n", - " 'lower': 34.0,\n", - " 'average': 37.625},\n", - " {'q1': 38.0,\n", - " 'pos': 29,\n", - " 'lower': 33.5,\n", - " 'average': 38.595,\n", - " 'q3': 41.0,\n", - " 'median': 40.0,\n", - " 'upper': 45.5},\n", - " {'pos': 38,\n", - " 'q3': 41.0,\n", - " 'average': 37.64,\n", - " 'median': 40.0,\n", - " 'upper': 45.5,\n", - " 'q1': 38.0,\n", - " 'lower': 33.5},\n", - " {'q3': 41.0,\n", - " 'pos': 18,\n", - " 'q1': 38.0,\n", - " 'average': 38.47,\n", - " 'median': 40.0,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5},\n", - " {'lower': 30.0,\n", - " 'average': 37.35,\n", - " 'q1': 36.0,\n", - " 'q3': 40.0,\n", - " 'upper': 46.0,\n", - " 'pos': 57,\n", - " 'median': 39.0},\n", - " {'q3': 34.0,\n", - " 'upper': 38.5,\n", - " 'q1': 31.0,\n", - " 'average': 30.135,\n", - " 'lower': 26.5,\n", - " 'pos': 0,\n", - " 'median': 33.0},\n", - " {'pos': 71,\n", - " 'q3': 38.0,\n", - " 'lower': 25.5,\n", - " 'upper': 45.5,\n", - " 'average': 33.005,\n", - " 'median': 35.0,\n", - " 'q1': 33.0},\n", - " {'upper': 39.5,\n", - " 'q3': 35.0,\n", - " 'q1': 32.0,\n", - " 'lower': 27.5,\n", - " 'average': 32.665,\n", - " 'pos': 91,\n", - " 'median': 35.0},\n", - " {'q3': 35.0,\n", - " 'pos': 89,\n", - " 'upper': 38.0,\n", - " 'q1': 33.0,\n", - " 'lower': 30.0,\n", - " 'median': 35.0,\n", - " 'average': 32.44},\n", - " {'median': 39.5,\n", - " 'q1': 36.0,\n", - " 'average': 37.59,\n", - " 'pos': 54,\n", - " 'q3': 41.0,\n", - " 'lower': 28.5,\n", - " 'upper': 48.5},\n", - " {'median': 35.0,\n", - " 'pos': 82,\n", - " 'q3': 36.0,\n", - " 'q1': 33.0,\n", - " 'lower': 28.5,\n", - " 'upper': 40.5,\n", - " 'average': 31.525},\n", - " {'pos': 85,\n", - " 'lower': 30.0,\n", - " 'q3': 35.0,\n", - " 'upper': 38.0,\n", - " 'average': 32.195,\n", - " 'median': 35.0,\n", - " 'q1': 33.0},\n", - " {'lower': 30.0,\n", - " 'pos': 83,\n", - " 'upper': 38.0,\n", - " 'median': 35.0,\n", - " 'q1': 33.0,\n", - " 'average': 32.03,\n", - " 'q3': 35.0},\n", - " {'median': 35.0,\n", - " 'q1': 32.0,\n", - " 'q3': 35.0,\n", - " 'upper': 39.5,\n", - " 'average': 31.835,\n", - " 'lower': 27.5,\n", - " 'pos': 92},\n", - " {'average': 35.995,\n", - " 'lower': 29.0,\n", - " 'pos': 65,\n", - " 'median': 37.0,\n", - " 'q1': 35.0,\n", - " 'upper': 45.0,\n", - " 'q3': 39.0},\n", - " {'pos': 34,\n", - " 'q3': 41.0,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'q1': 38.0,\n", - " 'average': 38.205,\n", - " 'median': 40.0},\n", - " {'upper': 43.0,\n", - " 'median': 40.0,\n", - " 'q3': 40.0,\n", - " 'q1': 38.0,\n", - " 'pos': 43,\n", - " 'average': 37.775,\n", - " 'lower': 35.0},\n", - " {'pos': 68,\n", - " 'q3': 39.0,\n", - " 'lower': 26.5,\n", - " 'upper': 46.5,\n", - " 'q1': 34.0,\n", - " 'median': 36.0,\n", - " 'average': 35.91},\n", - " {'q3': 40.0,\n", - " 'median': 40.0,\n", - " 'lower': 35.0,\n", - " 'pos': 26,\n", - " 'q1': 38.0,\n", - " 'upper': 43.0,\n", - " 'average': 37.855},\n", - " {'median': 35.0,\n", - " 'pos': 70,\n", - " 'q3': 38.0,\n", - " 'lower': 28.0,\n", - " 'q1': 34.0,\n", - " 'upper': 44.0,\n", - " 'average': 33.565},\n", - " {'q1': 38.0,\n", - " 'q3': 41.0,\n", - " 'pos': 13,\n", - " 'median': 40.0,\n", - " 'lower': 33.5,\n", - " 'average': 38.94,\n", - " 'upper': 45.5},\n", - " {'pos': 88,\n", - " 'q1': 33.0,\n", - " 'q3': 35.0,\n", - " 'upper': 38.0,\n", - " 'average': 32.065,\n", - " 'lower': 30.0,\n", - " 'median': 35.0},\n", - " {'median': 34.5,\n", - " 'q1': 33.0,\n", - " 'q3': 35.0,\n", - " 'upper': 38.0,\n", - " 'average': 32.275,\n", - " 'pos': 90,\n", - " 'lower': 30.0},\n", - " {'q1': 30.0,\n", - " 'upper': 45.0,\n", - " 'q3': 36.0,\n", - " 'pos': 77,\n", - " 'average': 30.805,\n", - " 'median': 35.0,\n", - " 'lower': 21.0},\n", - " {'q1': 37.0,\n", - " 'median': 39.0,\n", - " 'average': 37.77,\n", - " 'upper': 44.5,\n", - " 'pos': 52,\n", - " 'q3': 40.0,\n", - " 'lower': 32.5},\n", - " {'average': 37.565,\n", - " 'q1': 37.0,\n", - " 'pos': 44,\n", - " 'lower': 31.0,\n", - " 'median': 40.0,\n", - " 'q3': 41.0,\n", - " 'upper': 47.0},\n", - " {'lower': 28.5,\n", - " 'average': 37.425,\n", - " 'median': 39.0,\n", - " 'q1': 36.0,\n", - " 'pos': 50,\n", - " 'upper': 48.5,\n", - " 'q3': 41.0},\n", - " {'upper': 46.0,\n", - " 'q1': 36.0,\n", - " 'lower': 30.0,\n", - " 'pos': 56,\n", - " 'average': 37.59,\n", - " 'median': 39.0,\n", - " 'q3': 40.0},\n", - " {'median': 38.0,\n", - " 'pos': 63,\n", - " 'lower': 27.5,\n", - " 'upper': 47.5,\n", - " 'q1': 35.0,\n", - " 'average': 36.25,\n", - " 'q3': 40.0},\n", - " {'lower': 31.0,\n", - " 'median': 39.0,\n", - " 'average': 37.665,\n", - " 'q1': 37.0,\n", - " 'q3': 41.0,\n", - " 'upper': 47.0,\n", - " 'pos': 47},\n", - " {'median': 39.0,\n", - " 'q3': 39.0,\n", - " 'q1': 37.0,\n", - " 'average': 37.675,\n", - " 'lower': 34.0,\n", - " 'pos': 10,\n", - " 'upper': 42.0},\n", - " {'average': 37.5,\n", - " 'q1': 37.0,\n", - " 'q3': 39.0,\n", - " 'lower': 34.0,\n", - " 'upper': 42.0,\n", - " 'pos': 12,\n", - " 'median': 39.0},\n", - " {'median': 40.0,\n", - " 'q3': 41.0,\n", - " 'q1': 38.0,\n", - " 'pos': 25,\n", - " 'average': 38.2,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5},\n", - " {'lower': 23.5,\n", - " 'pos': 78,\n", - " 'q1': 31.0,\n", - " 'upper': 43.5,\n", - " 'average': 31.46,\n", - " 'q3': 36.0,\n", - " 'median': 35.0},\n", - " {'q3': 35.0,\n", - " 'lower': 27.5,\n", - " 'upper': 39.5,\n", - " 'pos': 95,\n", - " 'q1': 32.0,\n", - " 'median': 34.0,\n", - " 'average': 31.425},\n", - " {'q3': 40.0,\n", - " 'upper': 47.5,\n", - " 'lower': 27.5,\n", - " 'average': 36.145,\n", - " 'pos': 62,\n", - " 'q1': 35.0,\n", - " 'median': 38.0},\n", - " {'pos': 21,\n", - " 'q3': 40.0,\n", - " 'median': 40.0,\n", - " 'lower': 35.0,\n", - " 'q1': 38.0,\n", - " 'average': 38.445,\n", - " 'upper': 43.0},\n", - " {'q1': 38.0,\n", - " 'lower': 35.0,\n", - " 'pos': 36,\n", - " 'q3': 40.0,\n", - " 'average': 38.11,\n", - " 'median': 40.0,\n", - " 'upper': 43.0},\n", - " {'lower': 27.5,\n", - " 'median': 38.0,\n", - " 'q1': 35.0,\n", - " 'average': 35.985,\n", - " 'upper': 47.5,\n", - " 'pos': 60,\n", - " 'q3': 40.0},\n", - " {'pos': 24,\n", - " 'average': 38.265,\n", - " 'q1': 38.0,\n", - " 'q3': 41.0,\n", - " 'upper': 45.5,\n", - " 'median': 40.0,\n", - " 'lower': 33.5},\n", - " {'q1': 37.0,\n", - " 'q3': 39.0,\n", - " 'median': 39.0,\n", - " 'lower': 34.0,\n", - " 'upper': 42.0,\n", - " 'average': 37.36,\n", - " 'pos': 9},\n", - " {'q1': 38.0,\n", - " 'q3': 40.0,\n", - " 'median': 40.0,\n", - " 'pos': 30,\n", - " 'average': 38.245,\n", - " 'lower': 35.0,\n", - " 'upper': 43.0},\n", - " {'average': 37.78,\n", - " 'q3': 40.0,\n", - " 'q1': 37.0,\n", - " 'lower': 32.5,\n", - " 'upper': 44.5,\n", - " 'pos': 42,\n", - " 'median': 40.0},\n", - " {'pos': 53,\n", - " 'q1': 37.0,\n", - " 'q3': 41.0,\n", - " 'lower': 31.0,\n", - " 'upper': 47.0,\n", - " 'median': 39.0,\n", - " 'average': 37.845},\n", - " {'q3': 37.0,\n", - " 'upper': 40.0,\n", - " 'median': 36.0,\n", - " 'average': 35.4,\n", - " 'q1': 35.0,\n", - " 'pos': 7,\n", - " 'lower': 32.0},\n", - " {'q1': 38.0,\n", - " 'upper': 45.5,\n", - " 'pos': 16,\n", - " 'q3': 41.0,\n", - " 'median': 40.0,\n", - " 'lower': 33.5,\n", - " 'average': 38.48},\n", - " {'pos': 72,\n", - " 'median': 35.0,\n", - " 'upper': 43.0,\n", - " 'average': 33.265,\n", - " 'q1': 33.0,\n", - " 'lower': 27.0,\n", - " 'q3': 37.0},\n", - " {'q1': 31.0,\n", - " 'lower': 22.0,\n", - " 'pos': 75,\n", - " 'average': 31.06,\n", - " 'q3': 37.0,\n", - " 'upper': 46.0,\n", - " 'median': 35.0},\n", - " {'average': 37.95,\n", - " 'median': 40.0,\n", - " 'q3': 40.0,\n", - " 'lower': 35.0,\n", - " 'pos': 40,\n", - " 'upper': 43.0,\n", - " 'q1': 38.0},\n", - " {'pos': 5,\n", - " 'median': 35.0,\n", - " 'q3': 37.0,\n", - " 'lower': 32.0,\n", - " 'upper': 40.0,\n", - " 'average': 35.095,\n", - " 'q1': 35.0},\n", - " {'upper': 40.0,\n", - " 'pos': 6,\n", - " 'median': 35.0,\n", - " 'average': 35.145,\n", - " 'q3': 37.0,\n", - " 'lower': 32.0,\n", - " 'q1': 35.0},\n", - " {'pos': 86,\n", - " 'q1': 33.0,\n", - " 'average': 31.815,\n", - " 'median': 35.0,\n", - " 'q3': 35.0,\n", - " 'lower': 30.0,\n", - " 'upper': 38.0},\n", - " {'lower': 30.0,\n", - " 'pos': 55,\n", - " 'average': 37.55,\n", - " 'q3': 40.0,\n", - " 'upper': 46.0,\n", - " 'median': 39.0,\n", - " 'q1': 36.0},\n", - " {'median': 34.0,\n", - " 'q1': 31.0,\n", - " 'q3': 34.0,\n", - " 'pos': 1,\n", - " 'lower': 26.5,\n", - " 'upper': 38.5,\n", - " 'average': 31.21},\n", - " {'q3': 41.0,\n", - " 'median': 40.0,\n", - " 'average': 38.44,\n", - " 'q1': 38.0,\n", - " 'pos': 27,\n", - " 'upper': 45.5,\n", - " 'lower': 33.5},\n", - " {'upper': 42.0,\n", - " 'average': 37.71,\n", - " 'lower': 34.0,\n", - " 'q3': 39.0,\n", - " 'pos': 11,\n", - " 'q1': 37.0,\n", - " 'median': 39.0},\n", - " {'median': 37.0,\n", - " 'pos': 66,\n", - " 'average': 35.875,\n", - " 'q3': 39.0,\n", - " 'q1': 35.0,\n", - " 'lower': 29.0,\n", - " 'upper': 45.0},\n", - " {'upper': 39.5,\n", - " 'q3': 35.0,\n", - " 'lower': 27.5,\n", - " 'average': 31.05,\n", - " 'median': 34.0,\n", - " 'pos': 93,\n", - " 'q1': 32.0},\n", - " {'median': 40.0,\n", - " 'q3': 41.0,\n", - " 'lower': 33.5,\n", - " 'pos': 32,\n", - " 'average': 38.29,\n", - " 'q1': 38.0,\n", - " 'upper': 45.5},\n", - " {'median': 36.0,\n", - " 'upper': 46.5,\n", - " 'q1': 34.0,\n", - " 'pos': 69,\n", - " 'q3': 39.0,\n", - " 'lower': 26.5,\n", - " 'average': 33.7},\n", - " {'lower': 33.5,\n", - " 'q3': 41.0,\n", - " 'upper': 45.5,\n", - " 'q1': 38.0,\n", - " 'pos': 14,\n", - " 'average': 38.965,\n", - " 'median': 40.0},\n", - " {'q1': 32.0,\n", - " 'median': 34.0,\n", - " 'average': 30.775,\n", - " 'q3': 35.0,\n", - " 'pos': 94,\n", - " 'lower': 27.5,\n", - " 'upper': 39.5},\n", - " {'q1': 37.0,\n", - " 'q3': 41.0,\n", - " 'lower': 31.0,\n", - " 'upper': 47.0,\n", - " 'average': 37.87,\n", - " 'pos': 41,\n", - " 'median': 40.0},\n", - " {'pos': 96,\n", - " 'q3': 35.0,\n", - " 'upper': 39.5,\n", - " 'q1': 32.0,\n", - " 'lower': 27.5,\n", - " 'median': 34.0,\n", - " 'average': 31.315},\n", - " {'pos': 17,\n", - " 'q1': 38.0,\n", - " 'median': 40.0,\n", - " 'upper': 45.5,\n", - " 'q3': 41.0,\n", - " 'lower': 33.5,\n", - " 'average': 38.505},\n", - " {'q3': 41.0,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'median': 40.0,\n", - " 'average': 38.245,\n", - " 'q1': 38.0,\n", - " 'pos': 33},\n", - " {'average': 36.095,\n", - " 'q1': 35.0,\n", - " 'lower': 27.5,\n", - " 'pos': 64,\n", - " 'q3': 40.0,\n", - " 'upper': 47.5,\n", - " 'median': 37.0},\n", - " {'pos': 35,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'average': 38.385,\n", - " 'median': 40.0,\n", - " 'q1': 38.0,\n", - " 'q3': 41.0},\n", - " {'lower': 28.5,\n", - " 'q1': 36.0,\n", - " 'pos': 48,\n", - " 'median': 40.0,\n", - " 'average': 37.61,\n", - " 'q3': 41.0,\n", - " 'upper': 48.5},\n", - " {'average': 31.915,\n", - " 'median': 35.0,\n", - " 'pos': 87,\n", - " 'q1': 32.0,\n", - " 'upper': 39.5,\n", - " 'lower': 27.5,\n", - " 'q3': 35.0},\n", - " {'upper': 47.5,\n", - " 'median': 38.0,\n", - " 'average': 35.99,\n", - " 'pos': 61,\n", - " 'q1': 35.0,\n", - " 'lower': 27.5,\n", - " 'q3': 40.0},\n", - " {'average': 37.79,\n", - " 'q3': 41.0,\n", - " 'lower': 31.0,\n", - " 'upper': 47.0,\n", - " 'q1': 37.0,\n", - " 'median': 39.5,\n", - " 'pos': 46},\n", - " {'q3': 36.0,\n", - " 'average': 32.76,\n", - " 'median': 35.0,\n", - " 'q1': 33.0,\n", - " 'upper': 40.5,\n", - " 'pos': 81,\n", - " 'lower': 28.5},\n", - " {'pos': 2,\n", - " 'average': 32.015,\n", - " 'median': 34.0,\n", - " 'q1': 31.0,\n", - " 'lower': 26.5,\n", - " 'upper': 38.5,\n", - " 'q3': 34.0},\n", - " {'lower': 27.5,\n", - " 'upper': 39.5,\n", - " 'median': 34.0,\n", - " 'average': 31.25,\n", - " 'q3': 35.0,\n", - " 'pos': 99,\n", - " 'q1': 32.0},\n", - " {'q1': 33.0,\n", - " 'average': 32.415,\n", - " 'lower': 30.0,\n", - " 'upper': 38.0,\n", - " 'pos': 84,\n", - " 'q3': 35.0,\n", - " 'median': 35.0},\n", - " {'upper': 41.0,\n", - " 'q3': 35.0,\n", - " 'pos': 100,\n", - " 'average': 31.105,\n", - " 'q1': 31.0,\n", - " 'lower': 25.0,\n", - " 'median': 34.0}]}" + "shape: (20_200, 2)\n", + "┌─────┬───────┐\n", + "│ pos ┆ score │\n", + "│ --- ┆ --- │\n", + "│ i64 ┆ i8 │\n", + "╞═════╪═══════╡\n", + "│ 0 ┆ 2 │\n", + "│ 1 ┆ 19 │\n", + "│ 2 ┆ 33 │\n", + "│ 3 ┆ 35 │\n", + "│ 4 ┆ 37 │\n", + "│ … ┆ … │\n", + "│ 96 ┆ 35 │\n", + "│ 97 ┆ 32 │\n", + "│ 98 ┆ 35 │\n", + "│ 99 ┆ 35 │\n", + "│ 100 ┆ 33 │\n", + "└─────┴───────┘" ] }, "execution_count": 5, @@ -2320,720 +242,40 @@ "name": "stderr", "output_type": "stream", "text": [ - "200rows [00:00, 126946.25rows/s]\n" + "200rows [00:00, 85580.58rows/s]\n" ] }, { "data": { + "text/html": [ + "
\n", + "shape: (20_200, 2)
posscore
i64i8
02
119
233
335
437
9635
9732
9835
9935
10033
" + ], "text/plain": [ - "{'base_quality_warn': 'pass',\n", - " 'base_per_pos_data': [{'average': 38.505,\n", - " 'q3': 41.0,\n", - " 'lower': 33.5,\n", - " 'median': 40.0,\n", - " 'upper': 45.5,\n", - " 'pos': 17,\n", - " 'q1': 38.0},\n", - " {'median': 33.0,\n", - " 'average': 30.135,\n", - " 'lower': 26.5,\n", - " 'q1': 31.0,\n", - " 'q3': 34.0,\n", - " 'pos': 0,\n", - " 'upper': 38.5},\n", - " {'lower': 32.0,\n", - " 'upper': 40.0,\n", - " 'median': 35.0,\n", - " 'pos': 5,\n", - " 'average': 35.095,\n", - " 'q1': 35.0,\n", - " 'q3': 37.0},\n", - " {'pos': 20,\n", - " 'median': 40.0,\n", - " 'q1': 38.0,\n", - " 'q3': 41.0,\n", - " 'average': 38.625,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5},\n", - " {'pos': 10,\n", - " 'lower': 34.0,\n", - " 'q3': 39.0,\n", - " 'upper': 42.0,\n", - " 'average': 37.675,\n", - " 'q1': 37.0,\n", - " 'median': 39.0},\n", - " {'lower': 31.0,\n", - " 'average': 37.87,\n", - " 'upper': 47.0,\n", - " 'q1': 37.0,\n", - " 'pos': 41,\n", - " 'median': 40.0,\n", - " 'q3': 41.0},\n", - " {'pos': 56,\n", - " 'q1': 36.0,\n", - " 'lower': 30.0,\n", - " 'median': 39.0,\n", - " 'upper': 46.0,\n", - " 'q3': 40.0,\n", - " 'average': 37.59},\n", - " {'q1': 38.0,\n", - " 'upper': 43.0,\n", - " 'average': 37.855,\n", - " 'pos': 26,\n", - " 'median': 40.0,\n", - " 'lower': 35.0,\n", - " 'q3': 40.0},\n", - " {'average': 37.565,\n", - " 'pos': 44,\n", - " 'median': 40.0,\n", - " 'q3': 41.0,\n", - " 'lower': 31.0,\n", - " 'upper': 47.0,\n", - " 'q1': 37.0},\n", - " {'average': 37.59,\n", - " 'upper': 48.5,\n", - " 'pos': 54,\n", - " 'q1': 36.0,\n", - " 'lower': 28.5,\n", - " 'median': 39.5,\n", - " 'q3': 41.0},\n", - " {'median': 38.0,\n", - " 'q3': 40.0,\n", - " 'upper': 47.5,\n", - " 'lower': 27.5,\n", - " 'q1': 35.0,\n", - " 'pos': 58,\n", - " 'average': 36.77},\n", - " {'average': 36.08,\n", - " 'lower': 27.5,\n", - " 'pos': 59,\n", - " 'q1': 35.0,\n", - " 'q3': 40.0,\n", - " 'upper': 47.5,\n", - " 'median': 38.0},\n", - " {'average': 37.625,\n", - " 'median': 39.0,\n", - " 'pos': 8,\n", - " 'q1': 37.0,\n", - " 'q3': 39.0,\n", - " 'lower': 34.0,\n", - " 'upper': 42.0},\n", - " {'average': 38.205,\n", - " 'median': 40.0,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'pos': 34,\n", - " 'q1': 38.0,\n", - " 'q3': 41.0},\n", - " {'upper': 46.5,\n", - " 'pos': 67,\n", - " 'q1': 34.0,\n", - " 'q3': 39.0,\n", - " 'lower': 26.5,\n", - " 'average': 35.96,\n", - " 'median': 36.5},\n", - " {'upper': 44.5,\n", - " 'q1': 32.0,\n", - " 'pos': 74,\n", - " 'median': 35.0,\n", - " 'average': 30.83,\n", - " 'q3': 37.0,\n", - " 'lower': 24.5},\n", - " {'average': 31.46,\n", - " 'upper': 43.5,\n", - " 'pos': 78,\n", - " 'lower': 23.5,\n", - " 'median': 35.0,\n", - " 'q3': 36.0,\n", - " 'q1': 31.0},\n", - " {'pos': 28,\n", - " 'median': 40.0,\n", - " 'average': 38.445,\n", - " 'q1': 38.0,\n", - " 'q3': 41.0,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5},\n", - " {'pos': 32,\n", - " 'average': 38.29,\n", - " 'q3': 41.0,\n", - " 'upper': 45.5,\n", - " 'lower': 33.5,\n", - " 'q1': 38.0,\n", - " 'median': 40.0},\n", - " {'pos': 2,\n", - " 'median': 34.0,\n", - " 'q3': 34.0,\n", - " 'average': 32.015,\n", - " 'lower': 26.5,\n", - " 'upper': 38.5,\n", - " 'q1': 31.0},\n", - " {'lower': 30.0,\n", - " 'pos': 83,\n", - " 'median': 35.0,\n", - " 'q3': 35.0,\n", - " 'upper': 38.0,\n", - " 'average': 32.03,\n", - " 'q1': 33.0},\n", - " {'q3': 35.0,\n", - " 'average': 32.195,\n", - " 'median': 35.0,\n", - " 'lower': 30.0,\n", - " 'upper': 38.0,\n", - " 'pos': 85,\n", - " 'q1': 33.0},\n", - " {'q3': 38.0,\n", - " 'lower': 28.0,\n", - " 'upper': 44.0,\n", - " 'q1': 34.0,\n", - " 'median': 35.0,\n", - " 'average': 33.565,\n", - " 'pos': 70},\n", - " {'q1': 35.0,\n", - " 'lower': 27.5,\n", - " 'pos': 64,\n", - " 'q3': 40.0,\n", - " 'upper': 47.5,\n", - " 'median': 37.0,\n", - " 'average': 36.095},\n", - " {'median': 35.0,\n", - " 'q3': 35.0,\n", - " 'average': 32.665,\n", - " 'upper': 39.5,\n", - " 'pos': 91,\n", - " 'q1': 32.0,\n", - " 'lower': 27.5},\n", - " {'q3': 39.0,\n", - " 'median': 37.0,\n", - " 'q1': 35.0,\n", - " 'lower': 29.0,\n", - " 'upper': 45.0,\n", - " 'average': 35.995,\n", - " 'pos': 65},\n", - " {'q1': 33.0,\n", - " 'median': 35.0,\n", - " 'average': 32.76,\n", - " 'lower': 28.5,\n", - " 'upper': 40.5,\n", - " 'pos': 81,\n", - " 'q3': 36.0},\n", - " {'pos': 66,\n", - " 'median': 37.0,\n", - " 'q3': 39.0,\n", - " 'average': 35.875,\n", - " 'q1': 35.0,\n", - " 'lower': 29.0,\n", - " 'upper': 45.0},\n", - " {'upper': 42.0,\n", - " 'median': 35.0,\n", - " 'lower': 26.0,\n", - " 'average': 32.46,\n", - " 'pos': 79,\n", - " 'q1': 32.0,\n", - " 'q3': 36.0},\n", - " {'q3': 37.0,\n", - " 'pos': 7,\n", - " 'average': 35.4,\n", - " 'median': 36.0,\n", - " 'q1': 35.0,\n", - " 'lower': 32.0,\n", - " 'upper': 40.0},\n", - " {'q3': 40.0,\n", - " 'lower': 35.0,\n", - " 'q1': 38.0,\n", - " 'average': 38.245,\n", - " 'upper': 43.0,\n", - " 'pos': 30,\n", - " 'median': 40.0},\n", - " {'lower': 35.0,\n", - " 'q3': 40.0,\n", - " 'upper': 43.0,\n", - " 'average': 37.895,\n", - " 'q1': 38.0,\n", - " 'pos': 39,\n", - " 'median': 40.0},\n", - " {'q1': 36.0,\n", - " 'upper': 48.5,\n", - " 'average': 37.45,\n", - " 'q3': 41.0,\n", - " 'lower': 28.5,\n", - " 'median': 40.0,\n", - " 'pos': 45},\n", - " {'average': 37.21,\n", - " 'median': 39.0,\n", - " 'upper': 46.0,\n", - " 'lower': 30.0,\n", - " 'pos': 49,\n", - " 'q1': 36.0,\n", - " 'q3': 40.0},\n", - " {'median': 35.0,\n", - " 'q1': 33.0,\n", - " 'lower': 30.0,\n", - " 'pos': 86,\n", - " 'upper': 38.0,\n", - " 'average': 31.815,\n", - " 'q3': 35.0},\n", - " {'pos': 6,\n", - " 'q1': 35.0,\n", - " 'lower': 32.0,\n", - " 'q3': 37.0,\n", - " 'upper': 40.0,\n", - " 'average': 35.145,\n", - " 'median': 35.0},\n", - " {'q3': 40.0,\n", - " 'lower': 27.5,\n", - " 'pos': 60,\n", - " 'average': 35.985,\n", - " 'upper': 47.5,\n", - " 'median': 38.0,\n", - " 'q1': 35.0},\n", - " {'lower': 27.5,\n", - " 'average': 31.425,\n", - " 'q3': 35.0,\n", - " 'median': 34.0,\n", - " 'q1': 32.0,\n", - " 'pos': 95,\n", - " 'upper': 39.5},\n", - " {'median': 40.0,\n", - " 'pos': 13,\n", - " 'lower': 33.5,\n", - " 'q3': 41.0,\n", - " 'average': 38.94,\n", - " 'q1': 38.0,\n", - " 'upper': 45.5},\n", - " {'q1': 33.0,\n", - " 'upper': 38.0,\n", - " 'average': 32.275,\n", - " 'pos': 90,\n", - " 'q3': 35.0,\n", - " 'lower': 30.0,\n", - " 'median': 34.5},\n", - " {'upper': 45.5,\n", - " 'median': 40.0,\n", - " 'pos': 33,\n", - " 'average': 38.245,\n", - " 'q1': 38.0,\n", - " 'q3': 41.0,\n", - " 'lower': 33.5},\n", - " {'upper': 39.5,\n", - " 'pos': 87,\n", - " 'average': 31.915,\n", - " 'q1': 32.0,\n", - " 'median': 35.0,\n", - " 'q3': 35.0,\n", - " 'lower': 27.5},\n", - " {'pos': 42,\n", - " 'median': 40.0,\n", - " 'average': 37.78,\n", - " 'q3': 40.0,\n", - " 'lower': 32.5,\n", - " 'q1': 37.0,\n", - " 'upper': 44.5},\n", - " {'q3': 40.0,\n", - " 'pos': 63,\n", - " 'average': 36.25,\n", - " 'median': 38.0,\n", - " 'q1': 35.0,\n", - " 'lower': 27.5,\n", - " 'upper': 47.5},\n", - " {'q1': 36.0,\n", - " 'pos': 57,\n", - " 'median': 39.0,\n", - " 'q3': 40.0,\n", - " 'upper': 46.0,\n", - " 'average': 37.35,\n", - " 'lower': 30.0},\n", - " {'upper': 42.0,\n", - " 'average': 37.71,\n", - " 'q1': 37.0,\n", - " 'median': 39.0,\n", - " 'q3': 39.0,\n", - " 'lower': 34.0,\n", - " 'pos': 11},\n", - " {'upper': 45.5,\n", - " 'q1': 38.0,\n", - " 'lower': 33.5,\n", - " 'median': 40.0,\n", - " 'average': 38.425,\n", - " 'pos': 19,\n", - " 'q3': 41.0},\n", - " {'pos': 88,\n", - " 'upper': 38.0,\n", - " 'q1': 33.0,\n", - " 'average': 32.065,\n", - " 'median': 35.0,\n", - " 'q3': 35.0,\n", - " 'lower': 30.0},\n", - " {'upper': 39.5,\n", - " 'average': 31.315,\n", - " 'q1': 32.0,\n", - " 'pos': 96,\n", - " 'median': 34.0,\n", - " 'q3': 35.0,\n", - " 'lower': 27.5},\n", - " {'q3': 41.0,\n", - " 'lower': 28.5,\n", - " 'upper': 48.5,\n", - " 'average': 37.61,\n", - " 'median': 40.0,\n", - " 'pos': 48,\n", - " 'q1': 36.0},\n", - " {'q3': 37.0,\n", - " 'average': 35.68,\n", - " 'upper': 40.0,\n", - " 'lower': 32.0,\n", - " 'pos': 4,\n", - " 'median': 37.0,\n", - " 'q1': 35.0},\n", - " {'q1': 33.0,\n", - " 'pos': 89,\n", - " 'average': 32.44,\n", - " 'median': 35.0,\n", - " 'lower': 30.0,\n", - " 'upper': 38.0,\n", - " 'q3': 35.0},\n", - " {'q3': 39.0,\n", - " 'lower': 34.0,\n", - " 'average': 37.5,\n", - " 'median': 39.0,\n", - " 'q1': 37.0,\n", - " 'upper': 42.0,\n", - " 'pos': 12},\n", - " {'lower': 25.0,\n", - " 'q3': 35.0,\n", - " 'upper': 41.0,\n", - " 'pos': 97,\n", - " 'average': 30.67,\n", - " 'median': 34.0,\n", - " 'q1': 31.0},\n", - " {'q1': 38.0,\n", - " 'q3': 41.0,\n", - " 'pos': 27,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'median': 40.0,\n", - " 'average': 38.44},\n", - " {'lower': 31.0,\n", - " 'upper': 47.0,\n", - " 'average': 37.845,\n", - " 'q1': 37.0,\n", - " 'median': 39.0,\n", - " 'pos': 53,\n", - " 'q3': 41.0},\n", - " {'pos': 100,\n", - " 'q3': 35.0,\n", - " 'lower': 25.0,\n", - " 'average': 31.105,\n", - " 'upper': 41.0,\n", - " 'median': 34.0,\n", - " 'q1': 31.0},\n", - " {'q1': 37.0,\n", - " 'lower': 32.5,\n", - " 'upper': 44.5,\n", - " 'q3': 40.0,\n", - " 'pos': 52,\n", - " 'average': 37.77,\n", - " 'median': 39.0},\n", - " {'q3': 41.0,\n", - " 'pos': 24,\n", - " 'average': 38.265,\n", - " 'median': 40.0,\n", - " 'q1': 38.0,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5},\n", - " {'upper': 42.0,\n", - " 'median': 39.0,\n", - " 'q3': 39.0,\n", - " 'q1': 37.0,\n", - " 'average': 37.36,\n", - " 'pos': 9,\n", - " 'lower': 34.0},\n", - " {'pos': 15,\n", - " 'lower': 33.5,\n", - " 'median': 40.0,\n", - " 'upper': 45.5,\n", - " 'q3': 41.0,\n", - " 'average': 38.725,\n", - " 'q1': 38.0},\n", - " {'pos': 55,\n", - " 'average': 37.55,\n", - " 'lower': 30.0,\n", - " 'q1': 36.0,\n", - " 'median': 39.0,\n", - " 'q3': 40.0,\n", - " 'upper': 46.0},\n", - " {'median': 35.0,\n", - " 'q1': 31.0,\n", - " 'q3': 37.0,\n", - " 'pos': 75,\n", - " 'lower': 22.0,\n", - " 'upper': 46.0,\n", - " 'average': 31.06},\n", - " {'lower': 33.5,\n", - " 'pos': 29,\n", - " 'average': 38.595,\n", - " 'q3': 41.0,\n", - " 'upper': 45.5,\n", - " 'median': 40.0,\n", - " 'q1': 38.0},\n", - " {'q1': 34.0,\n", - " 'pos': 69,\n", - " 'lower': 26.5,\n", - " 'average': 33.7,\n", - " 'upper': 46.5,\n", - " 'median': 36.0,\n", - " 'q3': 39.0},\n", - " {'q3': 41.0,\n", - " 'average': 37.79,\n", - " 'lower': 31.0,\n", - " 'upper': 47.0,\n", - " 'pos': 46,\n", - " 'median': 39.5,\n", - " 'q1': 37.0},\n", - " {'upper': 39.5,\n", - " 'pos': 93,\n", - " 'average': 31.05,\n", - " 'q1': 32.0,\n", - " 'q3': 35.0,\n", - " 'median': 34.0,\n", - " 'lower': 27.5},\n", - " {'average': 37.775,\n", - " 'pos': 43,\n", - " 'q1': 38.0,\n", - " 'q3': 40.0,\n", - " 'lower': 35.0,\n", - " 'upper': 43.0,\n", - " 'median': 40.0},\n", - " {'q1': 38.0,\n", - " 'lower': 33.5,\n", - " 'pos': 23,\n", - " 'average': 38.635,\n", - " 'median': 40.0,\n", - " 'q3': 41.0,\n", - " 'upper': 45.5},\n", - " {'q3': 37.0,\n", - " 'median': 35.0,\n", - " 'pos': 73,\n", - " 'average': 32.68,\n", - " 'q1': 33.0,\n", - " 'lower': 27.0,\n", - " 'upper': 43.0},\n", - " {'q3': 41.0,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'pos': 14,\n", - " 'average': 38.965,\n", - " 'q1': 38.0,\n", - " 'median': 40.0},\n", - " {'median': 40.0,\n", - " 'q3': 40.0,\n", - " 'q1': 38.0,\n", - " 'pos': 37,\n", - " 'upper': 43.0,\n", - " 'lower': 35.0,\n", - " 'average': 38.0},\n", - " {'pos': 76,\n", - " 'median': 35.0,\n", - " 'lower': 22.0,\n", - " 'upper': 46.0,\n", - " 'q3': 37.0,\n", - " 'average': 30.265,\n", - " 'q1': 31.0},\n", - " {'q3': 36.0,\n", - " 'lower': 26.0,\n", - " 'upper': 42.0,\n", - " 'median': 35.0,\n", - " 'average': 32.61,\n", - " 'pos': 80,\n", - " 'q1': 32.0},\n", - " {'average': 37.665,\n", - " 'q3': 41.0,\n", - " 'pos': 47,\n", - " 'q1': 37.0,\n", - " 'lower': 31.0,\n", - " 'median': 39.0,\n", - " 'upper': 47.0},\n", - " {'average': 33.265,\n", - " 'median': 35.0,\n", - " 'pos': 72,\n", - " 'q1': 33.0,\n", - " 'q3': 37.0,\n", - " 'lower': 27.0,\n", - " 'upper': 43.0},\n", - " {'median': 40.0,\n", - " 'q1': 38.0,\n", - " 'lower': 33.5,\n", - " 'pos': 18,\n", - " 'upper': 45.5,\n", - " 'q3': 41.0,\n", - " 'average': 38.47},\n", - " {'q1': 33.0,\n", - " 'lower': 28.5,\n", - " 'pos': 82,\n", - " 'q3': 36.0,\n", - " 'upper': 40.5,\n", - " 'median': 35.0,\n", - " 'average': 31.525},\n", - " {'average': 35.69,\n", - " 'median': 37.0,\n", - " 'lower': 32.0,\n", - " 'pos': 3,\n", - " 'q3': 37.0,\n", - " 'upper': 40.0,\n", - " 'q1': 35.0},\n", - " {'average': 35.99,\n", - " 'q1': 35.0,\n", - " 'upper': 47.5,\n", - " 'q3': 40.0,\n", - " 'lower': 27.5,\n", - " 'pos': 61,\n", - " 'median': 38.0},\n", - " {'upper': 48.5,\n", - " 'lower': 28.5,\n", - " 'pos': 50,\n", - " 'q1': 36.0,\n", - " 'q3': 41.0,\n", - " 'median': 39.0,\n", - " 'average': 37.425},\n", - " {'average': 36.145,\n", - " 'upper': 47.5,\n", - " 'q3': 40.0,\n", - " 'pos': 62,\n", - " 'median': 38.0,\n", - " 'q1': 35.0,\n", - " 'lower': 27.5},\n", - " {'pos': 51,\n", - " 'average': 37.53,\n", - " 'lower': 28.5,\n", - " 'median': 39.0,\n", - " 'upper': 48.5,\n", - " 'q3': 41.0,\n", - " 'q1': 36.0},\n", - " {'upper': 43.0,\n", - " 'average': 37.95,\n", - " 'q1': 38.0,\n", - " 'median': 40.0,\n", - " 'lower': 35.0,\n", - " 'pos': 40,\n", - " 'q3': 40.0},\n", - " {'upper': 46.5,\n", - " 'average': 35.91,\n", - " 'q1': 34.0,\n", - " 'q3': 39.0,\n", - " 'lower': 26.5,\n", - " 'median': 36.0,\n", - " 'pos': 68},\n", - " {'median': 35.0,\n", - " 'q1': 30.0,\n", - " 'q3': 36.0,\n", - " 'lower': 21.0,\n", - " 'pos': 77,\n", - " 'average': 30.805,\n", - " 'upper': 45.0},\n", - " {'average': 33.005,\n", - " 'pos': 71,\n", - " 'q1': 33.0,\n", - " 'q3': 38.0,\n", - " 'lower': 25.5,\n", - " 'median': 35.0,\n", - " 'upper': 45.5},\n", - " {'q3': 35.0,\n", - " 'pos': 98,\n", - " 'average': 31.55,\n", - " 'lower': 27.5,\n", - " 'upper': 39.5,\n", - " 'median': 34.0,\n", - " 'q1': 32.0},\n", - " {'average': 31.25,\n", - " 'median': 34.0,\n", - " 'upper': 39.5,\n", - " 'pos': 99,\n", - " 'q1': 32.0,\n", - " 'q3': 35.0,\n", - " 'lower': 27.5},\n", - " {'q3': 41.0,\n", - " 'lower': 33.5,\n", - " 'median': 40.0,\n", - " 'upper': 45.5,\n", - " 'pos': 38,\n", - " 'average': 37.64,\n", - " 'q1': 38.0},\n", - " {'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'median': 40.0,\n", - " 'q1': 38.0,\n", - " 'pos': 25,\n", - " 'q3': 41.0,\n", - " 'average': 38.2},\n", - " {'q3': 41.0,\n", - " 'lower': 33.5,\n", - " 'median': 40.0,\n", - " 'pos': 31,\n", - " 'average': 38.795,\n", - " 'q1': 38.0,\n", - " 'upper': 45.5},\n", - " {'average': 38.385,\n", - " 'upper': 45.5,\n", - " 'q3': 41.0,\n", - " 'pos': 35,\n", - " 'median': 40.0,\n", - " 'lower': 33.5,\n", - " 'q1': 38.0},\n", - " {'q1': 33.0,\n", - " 'q3': 35.0,\n", - " 'pos': 84,\n", - " 'lower': 30.0,\n", - " 'median': 35.0,\n", - " 'upper': 38.0,\n", - " 'average': 32.415},\n", - " {'pos': 92,\n", - " 'median': 35.0,\n", - " 'upper': 39.5,\n", - " 'average': 31.835,\n", - " 'lower': 27.5,\n", - " 'q1': 32.0,\n", - " 'q3': 35.0},\n", - " {'q1': 32.0,\n", - " 'lower': 27.5,\n", - " 'median': 34.0,\n", - " 'pos': 94,\n", - " 'upper': 39.5,\n", - " 'average': 30.775,\n", - " 'q3': 35.0},\n", - " {'pos': 1,\n", - " 'median': 34.0,\n", - " 'q3': 34.0,\n", - " 'average': 31.21,\n", - " 'lower': 26.5,\n", - " 'q1': 31.0,\n", - " 'upper': 38.5},\n", - " {'upper': 45.5,\n", - " 'q1': 38.0,\n", - " 'average': 38.41,\n", - " 'median': 40.0,\n", - " 'lower': 33.5,\n", - " 'q3': 41.0,\n", - " 'pos': 22},\n", - " {'q3': 40.0,\n", - " 'lower': 35.0,\n", - " 'upper': 43.0,\n", - " 'pos': 36,\n", - " 'average': 38.11,\n", - " 'q1': 38.0,\n", - " 'median': 40.0},\n", - " {'lower': 35.0,\n", - " 'average': 38.445,\n", - " 'median': 40.0,\n", - " 'q1': 38.0,\n", - " 'q3': 40.0,\n", - " 'upper': 43.0,\n", - " 'pos': 21},\n", - " {'q1': 38.0,\n", - " 'pos': 16,\n", - " 'q3': 41.0,\n", - " 'average': 38.48,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'median': 40.0}]}" + "shape: (20_200, 2)\n", + "┌─────┬───────┐\n", + "│ pos ┆ score │\n", + "│ --- ┆ --- │\n", + "│ i64 ┆ i8 │\n", + "╞═════╪═══════╡\n", + "│ 0 ┆ 2 │\n", + "│ 1 ┆ 19 │\n", + "│ 2 ┆ 33 │\n", + "│ 3 ┆ 35 │\n", + "│ 4 ┆ 37 │\n", + "│ … ┆ … │\n", + "│ 96 ┆ 35 │\n", + "│ 97 ┆ 32 │\n", + "│ 98 ┆ 35 │\n", + "│ 99 ┆ 35 │\n", + "│ 100 ┆ 33 │\n", + "└─────┴───────┘" ] }, "execution_count": 6, @@ -3066,7 +308,7 @@ "output_type": "stream", "text": [ "INFO:polars_bio:Table: example registered for path: ./example.fastq\n", - "200rows [00:00, 80924.25rows/s]\n" + "200rows [00:00, 99332.24rows/s]" ] }, { @@ -3076,717 +318,44 @@ "\n" ] }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n" + ] + }, { "data": { + "text/html": [ + "
\n", + "shape: (20_200, 2)
posscore
i64i8
02
119
233
335
437
9635
9732
9835
9935
10033
" + ], "text/plain": [ - "{'base_quality_warn': 'pass',\n", - " 'base_per_pos_data': [{'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'median': 40.0,\n", - " 'average': 38.265,\n", - " 'pos': 24,\n", - " 'q3': 41.0,\n", - " 'q1': 38.0},\n", - " {'median': 35.0,\n", - " 'average': 30.83,\n", - " 'pos': 74,\n", - " 'q1': 32.0,\n", - " 'lower': 24.5,\n", - " 'q3': 37.0,\n", - " 'upper': 44.5},\n", - " {'pos': 93,\n", - " 'upper': 39.5,\n", - " 'average': 31.05,\n", - " 'median': 34.0,\n", - " 'q1': 32.0,\n", - " 'q3': 35.0,\n", - " 'lower': 27.5},\n", - " {'q1': 37.0,\n", - " 'pos': 10,\n", - " 'q3': 39.0,\n", - " 'lower': 34.0,\n", - " 'upper': 42.0,\n", - " 'median': 39.0,\n", - " 'average': 37.675},\n", - " {'lower': 28.5,\n", - " 'upper': 48.5,\n", - " 'median': 39.0,\n", - " 'average': 37.425,\n", - " 'pos': 50,\n", - " 'q1': 36.0,\n", - " 'q3': 41.0},\n", - " {'q1': 36.0,\n", - " 'lower': 30.0,\n", - " 'pos': 55,\n", - " 'average': 37.55,\n", - " 'q3': 40.0,\n", - " 'upper': 46.0,\n", - " 'median': 39.0},\n", - " {'average': 32.195,\n", - " 'q1': 33.0,\n", - " 'q3': 35.0,\n", - " 'lower': 30.0,\n", - " 'pos': 85,\n", - " 'upper': 38.0,\n", - " 'median': 35.0},\n", - " {'pos': 91,\n", - " 'q1': 32.0,\n", - " 'upper': 39.5,\n", - " 'q3': 35.0,\n", - " 'average': 32.665,\n", - " 'lower': 27.5,\n", - " 'median': 35.0},\n", - " {'pos': 92,\n", - " 'q1': 32.0,\n", - " 'median': 35.0,\n", - " 'upper': 39.5,\n", - " 'q3': 35.0,\n", - " 'average': 31.835,\n", - " 'lower': 27.5},\n", - " {'lower': 31.0,\n", - " 'upper': 47.0,\n", - " 'q1': 37.0,\n", - " 'median': 39.5,\n", - " 'average': 37.79,\n", - " 'pos': 46,\n", - " 'q3': 41.0},\n", - " {'q3': 40.0,\n", - " 'q1': 36.0,\n", - " 'upper': 46.0,\n", - " 'pos': 57,\n", - " 'average': 37.35,\n", - " 'median': 39.0,\n", - " 'lower': 30.0},\n", - " {'pos': 66,\n", - " 'average': 35.875,\n", - " 'median': 37.0,\n", - " 'q1': 35.0,\n", - " 'q3': 39.0,\n", - " 'lower': 29.0,\n", - " 'upper': 45.0},\n", - " {'pos': 69,\n", - " 'q3': 39.0,\n", - " 'lower': 26.5,\n", - " 'average': 33.7,\n", - " 'upper': 46.5,\n", - " 'q1': 34.0,\n", - " 'median': 36.0},\n", - " {'median': 38.0,\n", - " 'pos': 59,\n", - " 'q3': 40.0,\n", - " 'average': 36.08,\n", - " 'lower': 27.5,\n", - " 'upper': 47.5,\n", - " 'q1': 35.0},\n", - " {'q3': 35.0,\n", - " 'lower': 27.5,\n", - " 'upper': 39.5,\n", - " 'q1': 32.0,\n", - " 'pos': 99,\n", - " 'average': 31.25,\n", - " 'median': 34.0},\n", - " {'upper': 43.0,\n", - " 'q3': 40.0,\n", - " 'pos': 39,\n", - " 'q1': 38.0,\n", - " 'average': 37.895,\n", - " 'median': 40.0,\n", - " 'lower': 35.0},\n", - " {'upper': 43.0,\n", - " 'average': 37.95,\n", - " 'q1': 38.0,\n", - " 'pos': 40,\n", - " 'q3': 40.0,\n", - " 'median': 40.0,\n", - " 'lower': 35.0},\n", - " {'pos': 28,\n", - " 'q3': 41.0,\n", - " 'median': 40.0,\n", - " 'lower': 33.5,\n", - " 'q1': 38.0,\n", - " 'upper': 45.5,\n", - " 'average': 38.445},\n", - " {'q1': 37.0,\n", - " 'q3': 39.0,\n", - " 'average': 37.5,\n", - " 'lower': 34.0,\n", - " 'upper': 42.0,\n", - " 'pos': 12,\n", - " 'median': 39.0},\n", - " {'q3': 41.0,\n", - " 'pos': 23,\n", - " 'upper': 45.5,\n", - " 'lower': 33.5,\n", - " 'q1': 38.0,\n", - " 'median': 40.0,\n", - " 'average': 38.635},\n", - " {'pos': 0,\n", - " 'average': 30.135,\n", - " 'median': 33.0,\n", - " 'q3': 34.0,\n", - " 'lower': 26.5,\n", - " 'upper': 38.5,\n", - " 'q1': 31.0},\n", - " {'lower': 34.0,\n", - " 'pos': 8,\n", - " 'upper': 42.0,\n", - " 'average': 37.625,\n", - " 'median': 39.0,\n", - " 'q1': 37.0,\n", - " 'q3': 39.0},\n", - " {'median': 40.0,\n", - " 'lower': 28.5,\n", - " 'pos': 48,\n", - " 'q3': 41.0,\n", - " 'q1': 36.0,\n", - " 'average': 37.61,\n", - " 'upper': 48.5},\n", - " {'q1': 33.0,\n", - " 'pos': 82,\n", - " 'median': 35.0,\n", - " 'q3': 36.0,\n", - " 'lower': 28.5,\n", - " 'average': 31.525,\n", - " 'upper': 40.5},\n", - " {'pos': 96,\n", - " 'average': 31.315,\n", - " 'median': 34.0,\n", - " 'q1': 32.0,\n", - " 'q3': 35.0,\n", - " 'lower': 27.5,\n", - " 'upper': 39.5},\n", - " {'upper': 47.0,\n", - " 'pos': 53,\n", - " 'median': 39.0,\n", - " 'average': 37.845,\n", - " 'q1': 37.0,\n", - " 'q3': 41.0,\n", - " 'lower': 31.0},\n", - " {'lower': 27.5,\n", - " 'upper': 47.5,\n", - " 'median': 38.0,\n", - " 'pos': 62,\n", - " 'q3': 40.0,\n", - " 'average': 36.145,\n", - " 'q1': 35.0},\n", - " {'upper': 38.0,\n", - " 'median': 34.5,\n", - " 'average': 32.275,\n", - " 'q3': 35.0,\n", - " 'pos': 90,\n", - " 'q1': 33.0,\n", - " 'lower': 30.0},\n", - " {'q1': 35.0,\n", - " 'average': 35.145,\n", - " 'pos': 6,\n", - " 'q3': 37.0,\n", - " 'lower': 32.0,\n", - " 'upper': 40.0,\n", - " 'median': 35.0},\n", - " {'lower': 35.0,\n", - " 'upper': 43.0,\n", - " 'average': 38.245,\n", - " 'pos': 30,\n", - " 'q3': 40.0,\n", - " 'median': 40.0,\n", - " 'q1': 38.0},\n", - " {'q1': 38.0,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'q3': 41.0,\n", - " 'average': 38.725,\n", - " 'median': 40.0,\n", - " 'pos': 15},\n", - " {'median': 40.0,\n", - " 'upper': 45.5,\n", - " 'average': 38.245,\n", - " 'pos': 33,\n", - " 'q1': 38.0,\n", - " 'q3': 41.0,\n", - " 'lower': 33.5},\n", - " {'pos': 42,\n", - " 'average': 37.78,\n", - " 'median': 40.0,\n", - " 'q1': 37.0,\n", - " 'lower': 32.5,\n", - " 'upper': 44.5,\n", - " 'q3': 40.0},\n", - " {'pos': 44,\n", - " 'upper': 47.0,\n", - " 'q1': 37.0,\n", - " 'average': 37.565,\n", - " 'q3': 41.0,\n", - " 'median': 40.0,\n", - " 'lower': 31.0},\n", - " {'q3': 41.0,\n", - " 'upper': 48.5,\n", - " 'lower': 28.5,\n", - " 'average': 37.59,\n", - " 'median': 39.5,\n", - " 'q1': 36.0,\n", - " 'pos': 54},\n", - " {'average': 32.68,\n", - " 'pos': 73,\n", - " 'median': 35.0,\n", - " 'q1': 33.0,\n", - " 'q3': 37.0,\n", - " 'lower': 27.0,\n", - " 'upper': 43.0},\n", - " {'pos': 37,\n", - " 'average': 38.0,\n", - " 'q1': 38.0,\n", - " 'median': 40.0,\n", - " 'q3': 40.0,\n", - " 'lower': 35.0,\n", - " 'upper': 43.0},\n", - " {'average': 38.625,\n", - " 'q1': 38.0,\n", - " 'upper': 45.5,\n", - " 'lower': 33.5,\n", - " 'pos': 20,\n", - " 'q3': 41.0,\n", - " 'median': 40.0},\n", - " {'q3': 41.0,\n", - " 'lower': 31.0,\n", - " 'upper': 47.0,\n", - " 'pos': 47,\n", - " 'median': 39.0,\n", - " 'q1': 37.0,\n", - " 'average': 37.665},\n", - " {'average': 32.44,\n", - " 'lower': 30.0,\n", - " 'q1': 33.0,\n", - " 'upper': 38.0,\n", - " 'pos': 89,\n", - " 'median': 35.0,\n", - " 'q3': 35.0},\n", - " {'upper': 43.5,\n", - " 'q3': 36.0,\n", - " 'average': 31.46,\n", - " 'median': 35.0,\n", - " 'pos': 78,\n", - " 'q1': 31.0,\n", - " 'lower': 23.5},\n", - " {'upper': 40.0,\n", - " 'q3': 37.0,\n", - " 'median': 36.0,\n", - " 'average': 35.4,\n", - " 'q1': 35.0,\n", - " 'pos': 7,\n", - " 'lower': 32.0},\n", - " {'median': 39.0,\n", - " 'pos': 9,\n", - " 'average': 37.36,\n", - " 'q1': 37.0,\n", - " 'q3': 39.0,\n", - " 'lower': 34.0,\n", - " 'upper': 42.0},\n", - " {'upper': 48.5,\n", - " 'pos': 51,\n", - " 'q1': 36.0,\n", - " 'average': 37.53,\n", - " 'median': 39.0,\n", - " 'lower': 28.5,\n", - " 'q3': 41.0},\n", - " {'median': 34.0,\n", - " 'lower': 25.0,\n", - " 'pos': 97,\n", - " 'upper': 41.0,\n", - " 'q1': 31.0,\n", - " 'q3': 35.0,\n", - " 'average': 30.67},\n", - " {'q1': 38.0,\n", - " 'q3': 40.0,\n", - " 'lower': 35.0,\n", - " 'upper': 43.0,\n", - " 'pos': 26,\n", - " 'average': 37.855,\n", - " 'median': 40.0},\n", - " {'pos': 76,\n", - " 'median': 35.0,\n", - " 'q3': 37.0,\n", - " 'lower': 22.0,\n", - " 'upper': 46.0,\n", - " 'average': 30.265,\n", - " 'q1': 31.0},\n", - " {'q3': 36.0,\n", - " 'lower': 26.0,\n", - " 'pos': 80,\n", - " 'average': 32.61,\n", - " 'upper': 42.0,\n", - " 'median': 35.0,\n", - " 'q1': 32.0},\n", - " {'q1': 38.0,\n", - " 'lower': 33.5,\n", - " 'q3': 41.0,\n", - " 'median': 40.0,\n", - " 'average': 38.47,\n", - " 'upper': 45.5,\n", - " 'pos': 18},\n", - " {'pos': 35,\n", - " 'median': 40.0,\n", - " 'q1': 38.0,\n", - " 'q3': 41.0,\n", - " 'average': 38.385,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5},\n", - " {'upper': 38.0,\n", - " 'lower': 30.0,\n", - " 'average': 32.03,\n", - " 'q3': 35.0,\n", - " 'pos': 83,\n", - " 'median': 35.0,\n", - " 'q1': 33.0},\n", - " {'pos': 31,\n", - " 'median': 40.0,\n", - " 'q3': 41.0,\n", - " 'average': 38.795,\n", - " 'q1': 38.0,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5},\n", - " {'pos': 3,\n", - " 'median': 37.0,\n", - " 'upper': 40.0,\n", - " 'average': 35.69,\n", - " 'lower': 32.0,\n", - " 'q3': 37.0,\n", - " 'q1': 35.0},\n", - " {'pos': 56,\n", - " 'average': 37.59,\n", - " 'q1': 36.0,\n", - " 'q3': 40.0,\n", - " 'lower': 30.0,\n", - " 'median': 39.0,\n", - " 'upper': 46.0},\n", - " {'upper': 47.5,\n", - " 'pos': 58,\n", - " 'average': 36.77,\n", - " 'median': 38.0,\n", - " 'q1': 35.0,\n", - " 'q3': 40.0,\n", - " 'lower': 27.5},\n", - " {'q3': 40.0,\n", - " 'average': 35.99,\n", - " 'lower': 27.5,\n", - " 'upper': 47.5,\n", - " 'pos': 61,\n", - " 'median': 38.0,\n", - " 'q1': 35.0},\n", - " {'median': 37.0,\n", - " 'q1': 35.0,\n", - " 'average': 36.095,\n", - " 'q3': 40.0,\n", - " 'upper': 47.5,\n", - " 'lower': 27.5,\n", - " 'pos': 64},\n", - " {'q3': 37.0,\n", - " 'pos': 5,\n", - " 'lower': 32.0,\n", - " 'median': 35.0,\n", - " 'average': 35.095,\n", - " 'q1': 35.0,\n", - " 'upper': 40.0},\n", - " {'q1': 34.0,\n", - " 'pos': 68,\n", - " 'lower': 26.5,\n", - " 'q3': 39.0,\n", - " 'average': 35.91,\n", - " 'upper': 46.5,\n", - " 'median': 36.0},\n", - " {'pos': 87,\n", - " 'q1': 32.0,\n", - " 'lower': 27.5,\n", - " 'average': 31.915,\n", - " 'upper': 39.5,\n", - " 'q3': 35.0,\n", - " 'median': 35.0},\n", - " {'lower': 27.5,\n", - " 'upper': 39.5,\n", - " 'median': 34.0,\n", - " 'pos': 95,\n", - " 'q1': 32.0,\n", - " 'q3': 35.0,\n", - " 'average': 31.425},\n", - " {'average': 38.94,\n", - " 'q3': 41.0,\n", - " 'upper': 45.5,\n", - " 'pos': 13,\n", - " 'median': 40.0,\n", - " 'lower': 33.5,\n", - " 'q1': 38.0},\n", - " {'upper': 45.5,\n", - " 'median': 40.0,\n", - " 'q3': 41.0,\n", - " 'pos': 22,\n", - " 'lower': 33.5,\n", - " 'q1': 38.0,\n", - " 'average': 38.41},\n", - " {'pos': 70,\n", - " 'q3': 38.0,\n", - " 'average': 33.565,\n", - " 'q1': 34.0,\n", - " 'lower': 28.0,\n", - " 'median': 35.0,\n", - " 'upper': 44.0},\n", - " {'pos': 45,\n", - " 'q1': 36.0,\n", - " 'median': 40.0,\n", - " 'q3': 41.0,\n", - " 'lower': 28.5,\n", - " 'upper': 48.5,\n", - " 'average': 37.45},\n", - " {'upper': 46.0,\n", - " 'average': 31.06,\n", - " 'median': 35.0,\n", - " 'pos': 75,\n", - " 'q1': 31.0,\n", - " 'q3': 37.0,\n", - " 'lower': 22.0},\n", - " {'pos': 94,\n", - " 'median': 34.0,\n", - " 'q1': 32.0,\n", - " 'q3': 35.0,\n", - " 'average': 30.775,\n", - " 'lower': 27.5,\n", - " 'upper': 39.5},\n", - " {'median': 40.0,\n", - " 'upper': 43.0,\n", - " 'pos': 21,\n", - " 'q1': 38.0,\n", - " 'q3': 40.0,\n", - " 'lower': 35.0,\n", - " 'average': 38.445},\n", - " {'upper': 45.5,\n", - " 'median': 40.0,\n", - " 'pos': 16,\n", - " 'average': 38.48,\n", - " 'q1': 38.0,\n", - " 'q3': 41.0,\n", - " 'lower': 33.5},\n", - " {'average': 38.11,\n", - " 'median': 40.0,\n", - " 'lower': 35.0,\n", - " 'q1': 38.0,\n", - " 'upper': 43.0,\n", - " 'q3': 40.0,\n", - " 'pos': 36},\n", - " {'lower': 27.0,\n", - " 'average': 33.265,\n", - " 'median': 35.0,\n", - " 'q3': 37.0,\n", - " 'upper': 43.0,\n", - " 'pos': 72,\n", - " 'q1': 33.0},\n", - " {'average': 32.065,\n", - " 'q3': 35.0,\n", - " 'lower': 30.0,\n", - " 'pos': 88,\n", - " 'upper': 38.0,\n", - " 'median': 35.0,\n", - " 'q1': 33.0},\n", - " {'upper': 47.0,\n", - " 'q3': 41.0,\n", - " 'pos': 41,\n", - " 'q1': 37.0,\n", - " 'median': 40.0,\n", - " 'lower': 31.0,\n", - " 'average': 37.87},\n", - " {'pos': 43,\n", - " 'upper': 43.0,\n", - " 'q1': 38.0,\n", - " 'lower': 35.0,\n", - " 'median': 40.0,\n", - " 'q3': 40.0,\n", - " 'average': 37.775},\n", - " {'pos': 100,\n", - " 'average': 31.105,\n", - " 'q1': 31.0,\n", - " 'median': 34.0,\n", - " 'upper': 41.0,\n", - " 'q3': 35.0,\n", - " 'lower': 25.0},\n", - " {'pos': 32,\n", - " 'q3': 41.0,\n", - " 'lower': 33.5,\n", - " 'median': 40.0,\n", - " 'average': 38.29,\n", - " 'upper': 45.5,\n", - " 'q1': 38.0},\n", - " {'average': 37.64,\n", - " 'pos': 38,\n", - " 'q1': 38.0,\n", - " 'q3': 41.0,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'median': 40.0},\n", - " {'pos': 67,\n", - " 'median': 36.5,\n", - " 'q1': 34.0,\n", - " 'q3': 39.0,\n", - " 'lower': 26.5,\n", - " 'upper': 46.5,\n", - " 'average': 35.96},\n", - " {'q1': 38.0,\n", - " 'q3': 41.0,\n", - " 'median': 40.0,\n", - " 'average': 38.205,\n", - " 'pos': 34,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5},\n", - " {'upper': 38.0,\n", - " 'q3': 35.0,\n", - " 'q1': 33.0,\n", - " 'average': 32.415,\n", - " 'pos': 84,\n", - " 'median': 35.0,\n", - " 'lower': 30.0},\n", - " {'upper': 40.0,\n", - " 'pos': 4,\n", - " 'average': 35.68,\n", - " 'q1': 35.0,\n", - " 'median': 37.0,\n", - " 'q3': 37.0,\n", - " 'lower': 32.0},\n", - " {'q3': 41.0,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'pos': 27,\n", - " 'average': 38.44,\n", - " 'median': 40.0,\n", - " 'q1': 38.0},\n", - " {'lower': 30.0,\n", - " 'average': 37.21,\n", - " 'q3': 40.0,\n", - " 'pos': 49,\n", - " 'upper': 46.0,\n", - " 'median': 39.0,\n", - " 'q1': 36.0},\n", - " {'q3': 39.0,\n", - " 'upper': 45.0,\n", - " 'average': 35.995,\n", - " 'lower': 29.0,\n", - " 'q1': 35.0,\n", - " 'pos': 65,\n", - " 'median': 37.0},\n", - " {'upper': 40.5,\n", - " 'average': 32.76,\n", - " 'q1': 33.0,\n", - " 'q3': 36.0,\n", - " 'median': 35.0,\n", - " 'pos': 81,\n", - " 'lower': 28.5},\n", - " {'pos': 17,\n", - " 'q3': 41.0,\n", - " 'upper': 45.5,\n", - " 'lower': 33.5,\n", - " 'average': 38.505,\n", - " 'q1': 38.0,\n", - " 'median': 40.0},\n", - " {'lower': 33.5,\n", - " 'pos': 25,\n", - " 'upper': 45.5,\n", - " 'average': 38.2,\n", - " 'median': 40.0,\n", - " 'q3': 41.0,\n", - " 'q1': 38.0},\n", - " {'upper': 45.5,\n", - " 'q3': 38.0,\n", - " 'pos': 71,\n", - " 'average': 33.005,\n", - " 'q1': 33.0,\n", - " 'lower': 25.5,\n", - " 'median': 35.0},\n", - " {'pos': 14,\n", - " 'average': 38.965,\n", - " 'q1': 38.0,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'q3': 41.0,\n", - " 'median': 40.0},\n", - " {'q1': 31.0,\n", - " 'upper': 38.5,\n", - " 'q3': 34.0,\n", - " 'lower': 26.5,\n", - " 'median': 34.0,\n", - " 'average': 31.21,\n", - " 'pos': 1},\n", - " {'lower': 27.5,\n", - " 'upper': 47.5,\n", - " 'q3': 40.0,\n", - " 'median': 38.0,\n", - " 'q1': 35.0,\n", - " 'pos': 63,\n", - " 'average': 36.25},\n", - " {'average': 30.805,\n", - " 'q1': 30.0,\n", - " 'lower': 21.0,\n", - " 'upper': 45.0,\n", - " 'pos': 77,\n", - " 'median': 35.0,\n", - " 'q3': 36.0},\n", - " {'q1': 32.0,\n", - " 'pos': 79,\n", - " 'median': 35.0,\n", - " 'q3': 36.0,\n", - " 'average': 32.46,\n", - " 'lower': 26.0,\n", - " 'upper': 42.0},\n", - " {'average': 32.015,\n", - " 'q1': 31.0,\n", - " 'lower': 26.5,\n", - " 'pos': 2,\n", - " 'q3': 34.0,\n", - " 'upper': 38.5,\n", - " 'median': 34.0},\n", - " {'upper': 44.5,\n", - " 'lower': 32.5,\n", - " 'q1': 37.0,\n", - " 'pos': 52,\n", - " 'median': 39.0,\n", - " 'average': 37.77,\n", - " 'q3': 40.0},\n", - " {'average': 35.985,\n", - " 'pos': 60,\n", - " 'q1': 35.0,\n", - " 'lower': 27.5,\n", - " 'upper': 47.5,\n", - " 'q3': 40.0,\n", - " 'median': 38.0},\n", - " {'lower': 30.0,\n", - " 'average': 31.815,\n", - " 'median': 35.0,\n", - " 'upper': 38.0,\n", - " 'pos': 86,\n", - " 'q1': 33.0,\n", - " 'q3': 35.0},\n", - " {'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'q1': 38.0,\n", - " 'pos': 29,\n", - " 'median': 40.0,\n", - " 'q3': 41.0,\n", - " 'average': 38.595},\n", - " {'average': 31.55,\n", - " 'median': 34.0,\n", - " 'q1': 32.0,\n", - " 'upper': 39.5,\n", - " 'pos': 98,\n", - " 'lower': 27.5,\n", - " 'q3': 35.0},\n", - " {'q3': 41.0,\n", - " 'median': 40.0,\n", - " 'q1': 38.0,\n", - " 'lower': 33.5,\n", - " 'pos': 19,\n", - " 'upper': 45.5,\n", - " 'average': 38.425},\n", - " {'pos': 11,\n", - " 'average': 37.71,\n", - " 'median': 39.0,\n", - " 'q1': 37.0,\n", - " 'q3': 39.0,\n", - " 'lower': 34.0,\n", - " 'upper': 42.0}]}" + "shape: (20_200, 2)\n", + "┌─────┬───────┐\n", + "│ pos ┆ score │\n", + "│ --- ┆ --- │\n", + "│ i64 ┆ i8 │\n", + "╞═════╪═══════╡\n", + "│ 0 ┆ 2 │\n", + "│ 1 ┆ 19 │\n", + "│ 2 ┆ 33 │\n", + "│ 3 ┆ 35 │\n", + "│ 4 ┆ 37 │\n", + "│ … ┆ … │\n", + "│ 96 ┆ 35 │\n", + "│ 97 ┆ 32 │\n", + "│ 98 ┆ 35 │\n", + "│ 99 ┆ 35 │\n", + "│ 100 ┆ 33 │\n", + "└─────┴───────┘" ] }, "execution_count": 7, @@ -3820,7 +389,7 @@ "output_type": "stream", "text": [ "INFO:polars_bio:Table: example registered for path: ./example.fastq\n", - "200rows [00:00, 120508.66rows/s]" + "200rows [00:00, 91638.72rows/s]" ] }, { @@ -3839,715 +408,35 @@ }, { "data": { + "text/html": [ + "
\n", + "shape: (20_200, 2)
posscore
i64i8
02
119
233
335
437
9635
9732
9835
9935
10033
" + ], "text/plain": [ - "{'base_quality_warn': 'pass',\n", - " 'base_per_pos_data': [{'upper': 41.0,\n", - " 'q3': 35.0,\n", - " 'lower': 25.0,\n", - " 'pos': 97,\n", - " 'average': 30.67,\n", - " 'median': 34.0,\n", - " 'q1': 31.0},\n", - " {'q1': 38.0,\n", - " 'pos': 14,\n", - " 'average': 38.965,\n", - " 'lower': 33.5,\n", - " 'median': 40.0,\n", - " 'upper': 45.5,\n", - " 'q3': 41.0},\n", - " {'pos': 23,\n", - " 'upper': 45.5,\n", - " 'q1': 38.0,\n", - " 'q3': 41.0,\n", - " 'average': 38.635,\n", - " 'lower': 33.5,\n", - " 'median': 40.0},\n", - " {'q1': 37.0,\n", - " 'lower': 34.0,\n", - " 'average': 37.71,\n", - " 'upper': 42.0,\n", - " 'q3': 39.0,\n", - " 'median': 39.0,\n", - " 'pos': 11},\n", - " {'average': 38.425,\n", - " 'q1': 38.0,\n", - " 'q3': 41.0,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'median': 40.0,\n", - " 'pos': 19},\n", - " {'q3': 34.0,\n", - " 'upper': 38.5,\n", - " 'average': 32.015,\n", - " 'q1': 31.0,\n", - " 'lower': 26.5,\n", - " 'pos': 2,\n", - " 'median': 34.0},\n", - " {'upper': 48.5,\n", - " 'q1': 36.0,\n", - " 'average': 37.45,\n", - " 'median': 40.0,\n", - " 'pos': 45,\n", - " 'q3': 41.0,\n", - " 'lower': 28.5},\n", - " {'average': 37.61,\n", - " 'pos': 48,\n", - " 'median': 40.0,\n", - " 'q1': 36.0,\n", - " 'upper': 48.5,\n", - " 'q3': 41.0,\n", - " 'lower': 28.5},\n", - " {'q1': 38.0,\n", - " 'median': 40.0,\n", - " 'lower': 35.0,\n", - " 'pos': 37,\n", - " 'q3': 40.0,\n", - " 'upper': 43.0,\n", - " 'average': 38.0},\n", - " {'pos': 74,\n", - " 'median': 35.0,\n", - " 'q3': 37.0,\n", - " 'q1': 32.0,\n", - " 'average': 30.83,\n", - " 'lower': 24.5,\n", - " 'upper': 44.5},\n", - " {'average': 33.565,\n", - " 'pos': 70,\n", - " 'q1': 34.0,\n", - " 'q3': 38.0,\n", - " 'lower': 28.0,\n", - " 'upper': 44.0,\n", - " 'median': 35.0},\n", - " {'upper': 45.5,\n", - " 'pos': 31,\n", - " 'q3': 41.0,\n", - " 'median': 40.0,\n", - " 'q1': 38.0,\n", - " 'lower': 33.5,\n", - " 'average': 38.795},\n", - " {'average': 32.195,\n", - " 'median': 35.0,\n", - " 'upper': 38.0,\n", - " 'q1': 33.0,\n", - " 'q3': 35.0,\n", - " 'lower': 30.0,\n", - " 'pos': 85},\n", - " {'pos': 15,\n", - " 'upper': 45.5,\n", - " 'lower': 33.5,\n", - " 'median': 40.0,\n", - " 'q3': 41.0,\n", - " 'q1': 38.0,\n", - " 'average': 38.725},\n", - " {'q1': 32.0,\n", - " 'median': 35.0,\n", - " 'lower': 27.5,\n", - " 'pos': 91,\n", - " 'q3': 35.0,\n", - " 'upper': 39.5,\n", - " 'average': 32.665},\n", - " {'median': 34.0,\n", - " 'pos': 1,\n", - " 'q1': 31.0,\n", - " 'lower': 26.5,\n", - " 'average': 31.21,\n", - " 'q3': 34.0,\n", - " 'upper': 38.5},\n", - " {'median': 34.0,\n", - " 'q3': 35.0,\n", - " 'upper': 39.5,\n", - " 'q1': 32.0,\n", - " 'pos': 96,\n", - " 'average': 31.315,\n", - " 'lower': 27.5},\n", - " {'upper': 39.5,\n", - " 'median': 34.0,\n", - " 'lower': 27.5,\n", - " 'pos': 99,\n", - " 'q1': 32.0,\n", - " 'average': 31.25,\n", - " 'q3': 35.0},\n", - " {'upper': 45.5,\n", - " 'median': 40.0,\n", - " 'average': 38.595,\n", - " 'q1': 38.0,\n", - " 'q3': 41.0,\n", - " 'pos': 29,\n", - " 'lower': 33.5},\n", - " {'median': 40.0,\n", - " 'upper': 43.0,\n", - " 'q1': 38.0,\n", - " 'average': 38.245,\n", - " 'pos': 30,\n", - " 'lower': 35.0,\n", - " 'q3': 40.0},\n", - " {'q3': 35.0,\n", - " 'q1': 32.0,\n", - " 'average': 31.55,\n", - " 'median': 34.0,\n", - " 'upper': 39.5,\n", - " 'lower': 27.5,\n", - " 'pos': 98},\n", - " {'pos': 52,\n", - " 'q1': 37.0,\n", - " 'q3': 40.0,\n", - " 'upper': 44.5,\n", - " 'lower': 32.5,\n", - " 'median': 39.0,\n", - " 'average': 37.77},\n", - " {'lower': 32.0,\n", - " 'pos': 4,\n", - " 'q1': 35.0,\n", - " 'average': 35.68,\n", - " 'q3': 37.0,\n", - " 'median': 37.0,\n", - " 'upper': 40.0},\n", - " {'average': 35.69,\n", - " 'q3': 37.0,\n", - " 'lower': 32.0,\n", - " 'upper': 40.0,\n", - " 'median': 37.0,\n", - " 'q1': 35.0,\n", - " 'pos': 3},\n", - " {'median': 40.0,\n", - " 'pos': 38,\n", - " 'average': 37.64,\n", - " 'q3': 41.0,\n", - " 'q1': 38.0,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5},\n", - " {'pos': 46,\n", - " 'upper': 47.0,\n", - " 'q3': 41.0,\n", - " 'q1': 37.0,\n", - " 'average': 37.79,\n", - " 'median': 39.5,\n", - " 'lower': 31.0},\n", - " {'pos': 82,\n", - " 'average': 31.525,\n", - " 'lower': 28.5,\n", - " 'upper': 40.5,\n", - " 'median': 35.0,\n", - " 'q3': 36.0,\n", - " 'q1': 33.0},\n", - " {'upper': 40.0,\n", - " 'lower': 32.0,\n", - " 'average': 35.095,\n", - " 'pos': 5,\n", - " 'median': 35.0,\n", - " 'q1': 35.0,\n", - " 'q3': 37.0},\n", - " {'upper': 45.5,\n", - " 'q1': 38.0,\n", - " 'median': 40.0,\n", - " 'average': 38.2,\n", - " 'pos': 25,\n", - " 'q3': 41.0,\n", - " 'lower': 33.5},\n", - " {'pos': 33,\n", - " 'q3': 41.0,\n", - " 'median': 40.0,\n", - " 'upper': 45.5,\n", - " 'q1': 38.0,\n", - " 'lower': 33.5,\n", - " 'average': 38.245},\n", - " {'lower': 33.5,\n", - " 'median': 40.0,\n", - " 'upper': 45.5,\n", - " 'pos': 24,\n", - " 'q1': 38.0,\n", - " 'q3': 41.0,\n", - " 'average': 38.265},\n", - " {'pos': 43,\n", - " 'average': 37.775,\n", - " 'q1': 38.0,\n", - " 'lower': 35.0,\n", - " 'q3': 40.0,\n", - " 'upper': 43.0,\n", - " 'median': 40.0},\n", - " {'median': 39.0,\n", - " 'q3': 40.0,\n", - " 'pos': 56,\n", - " 'lower': 30.0,\n", - " 'q1': 36.0,\n", - " 'upper': 46.0,\n", - " 'average': 37.59},\n", - " {'median': 37.0,\n", - " 'q3': 39.0,\n", - " 'lower': 29.0,\n", - " 'average': 35.875,\n", - " 'pos': 66,\n", - " 'q1': 35.0,\n", - " 'upper': 45.0},\n", - " {'upper': 45.5,\n", - " 'median': 35.0,\n", - " 'q3': 38.0,\n", - " 'pos': 71,\n", - " 'q1': 33.0,\n", - " 'average': 33.005,\n", - " 'lower': 25.5},\n", - " {'pos': 34,\n", - " 'median': 40.0,\n", - " 'q1': 38.0,\n", - " 'q3': 41.0,\n", - " 'average': 38.205,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5},\n", - " {'pos': 68,\n", - " 'upper': 46.5,\n", - " 'lower': 26.5,\n", - " 'median': 36.0,\n", - " 'q1': 34.0,\n", - " 'q3': 39.0,\n", - " 'average': 35.91},\n", - " {'average': 31.425,\n", - " 'lower': 27.5,\n", - " 'upper': 39.5,\n", - " 'median': 34.0,\n", - " 'pos': 95,\n", - " 'q1': 32.0,\n", - " 'q3': 35.0},\n", - " {'median': 39.0,\n", - " 'q1': 37.0,\n", - " 'average': 37.665,\n", - " 'q3': 41.0,\n", - " 'lower': 31.0,\n", - " 'pos': 47,\n", - " 'upper': 47.0},\n", - " {'median': 38.0,\n", - " 'q3': 40.0,\n", - " 'upper': 47.5,\n", - " 'average': 36.145,\n", - " 'lower': 27.5,\n", - " 'pos': 62,\n", - " 'q1': 35.0},\n", - " {'upper': 46.0,\n", - " 'median': 39.0,\n", - " 'q1': 36.0,\n", - " 'lower': 30.0,\n", - " 'q3': 40.0,\n", - " 'pos': 49,\n", - " 'average': 37.21},\n", - " {'upper': 44.5,\n", - " 'q3': 40.0,\n", - " 'q1': 37.0,\n", - " 'average': 37.78,\n", - " 'pos': 42,\n", - " 'median': 40.0,\n", - " 'lower': 32.5},\n", - " {'pos': 10,\n", - " 'average': 37.675,\n", - " 'lower': 34.0,\n", - " 'median': 39.0,\n", - " 'q3': 39.0,\n", - " 'q1': 37.0,\n", - " 'upper': 42.0},\n", - " {'median': 39.0,\n", - " 'q3': 40.0,\n", - " 'lower': 30.0,\n", - " 'average': 37.55,\n", - " 'q1': 36.0,\n", - " 'pos': 55,\n", - " 'upper': 46.0},\n", - " {'median': 34.5,\n", - " 'q3': 35.0,\n", - " 'average': 32.275,\n", - " 'pos': 90,\n", - " 'lower': 30.0,\n", - " 'upper': 38.0,\n", - " 'q1': 33.0},\n", - " {'q1': 36.0,\n", - " 'average': 37.425,\n", - " 'upper': 48.5,\n", - " 'pos': 50,\n", - " 'lower': 28.5,\n", - " 'q3': 41.0,\n", - " 'median': 39.0},\n", - " {'average': 38.48,\n", - " 'q3': 41.0,\n", - " 'median': 40.0,\n", - " 'pos': 16,\n", - " 'q1': 38.0,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5},\n", - " {'lower': 33.5,\n", - " 'median': 40.0,\n", - " 'q3': 41.0,\n", - " 'upper': 45.5,\n", - " 'pos': 18,\n", - " 'average': 38.47,\n", - " 'q1': 38.0},\n", - " {'median': 40.0,\n", - " 'pos': 28,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'q3': 41.0,\n", - " 'q1': 38.0,\n", - " 'average': 38.445},\n", - " {'upper': 48.5,\n", - " 'q3': 41.0,\n", - " 'q1': 36.0,\n", - " 'average': 37.53,\n", - " 'median': 39.0,\n", - " 'pos': 51,\n", - " 'lower': 28.5},\n", - " {'pos': 100,\n", - " 'q3': 35.0,\n", - " 'upper': 41.0,\n", - " 'q1': 31.0,\n", - " 'lower': 25.0,\n", - " 'average': 31.105,\n", - " 'median': 34.0},\n", - " {'median': 40.0,\n", - " 'average': 37.95,\n", - " 'q1': 38.0,\n", - " 'pos': 40,\n", - " 'lower': 35.0,\n", - " 'upper': 43.0,\n", - " 'q3': 40.0},\n", - " {'q1': 37.0,\n", - " 'q3': 39.0,\n", - " 'lower': 34.0,\n", - " 'upper': 42.0,\n", - " 'median': 39.0,\n", - " 'average': 37.36,\n", - " 'pos': 9},\n", - " {'pos': 69,\n", - " 'q3': 39.0,\n", - " 'lower': 26.5,\n", - " 'upper': 46.5,\n", - " 'q1': 34.0,\n", - " 'median': 36.0,\n", - " 'average': 33.7},\n", - " {'pos': 89,\n", - " 'average': 32.44,\n", - " 'median': 35.0,\n", - " 'q1': 33.0,\n", - " 'q3': 35.0,\n", - " 'lower': 30.0,\n", - " 'upper': 38.0},\n", - " {'average': 32.03,\n", - " 'pos': 83,\n", - " 'q1': 33.0,\n", - " 'q3': 35.0,\n", - " 'median': 35.0,\n", - " 'upper': 38.0,\n", - " 'lower': 30.0},\n", - " {'q3': 34.0,\n", - " 'lower': 26.5,\n", - " 'average': 30.135,\n", - " 'pos': 0,\n", - " 'upper': 38.5,\n", - " 'q1': 31.0,\n", - " 'median': 33.0},\n", - " {'average': 36.08,\n", - " 'lower': 27.5,\n", - " 'upper': 47.5,\n", - " 'median': 38.0,\n", - " 'pos': 59,\n", - " 'q1': 35.0,\n", - " 'q3': 40.0},\n", - " {'median': 40.0,\n", - " 'q3': 41.0,\n", - " 'average': 38.385,\n", - " 'q1': 38.0,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'pos': 35},\n", - " {'pos': 39,\n", - " 'average': 37.895,\n", - " 'q1': 38.0,\n", - " 'lower': 35.0,\n", - " 'q3': 40.0,\n", - " 'upper': 43.0,\n", - " 'median': 40.0},\n", - " {'median': 40.0,\n", - " 'average': 38.505,\n", - " 'q1': 38.0,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'pos': 17,\n", - " 'q3': 41.0},\n", - " {'pos': 20,\n", - " 'median': 40.0,\n", - " 'q3': 41.0,\n", - " 'average': 38.625,\n", - " 'lower': 33.5,\n", - " 'q1': 38.0,\n", - " 'upper': 45.5},\n", - " {'q3': 37.0,\n", - " 'q1': 35.0,\n", - " 'upper': 40.0,\n", - " 'pos': 7,\n", - " 'median': 36.0,\n", - " 'average': 35.4,\n", - " 'lower': 32.0},\n", - " {'average': 32.415,\n", - " 'q1': 33.0,\n", - " 'median': 35.0,\n", - " 'q3': 35.0,\n", - " 'lower': 30.0,\n", - " 'upper': 38.0,\n", - " 'pos': 84},\n", - " {'pos': 67,\n", - " 'q1': 34.0,\n", - " 'average': 35.96,\n", - " 'median': 36.5,\n", - " 'q3': 39.0,\n", - " 'upper': 46.5,\n", - " 'lower': 26.5},\n", - " {'q1': 38.0,\n", - " 'average': 38.11,\n", - " 'pos': 36,\n", - " 'lower': 35.0,\n", - " 'upper': 43.0,\n", - " 'q3': 40.0,\n", - " 'median': 40.0},\n", - " {'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'median': 40.0,\n", - " 'average': 38.41,\n", - " 'pos': 22,\n", - " 'q1': 38.0,\n", - " 'q3': 41.0},\n", - " {'q1': 35.0,\n", - " 'lower': 27.5,\n", - " 'average': 36.77,\n", - " 'median': 38.0,\n", - " 'pos': 58,\n", - " 'q3': 40.0,\n", - " 'upper': 47.5},\n", - " {'q1': 33.0,\n", - " 'lower': 27.0,\n", - " 'average': 32.68,\n", - " 'pos': 73,\n", - " 'upper': 43.0,\n", - " 'median': 35.0,\n", - " 'q3': 37.0},\n", - " {'median': 40.0,\n", - " 'pos': 32,\n", - " 'q1': 38.0,\n", - " 'lower': 33.5,\n", - " 'average': 38.29,\n", - " 'q3': 41.0,\n", - " 'upper': 45.5},\n", - " {'pos': 72,\n", - " 'average': 33.265,\n", - " 'q3': 37.0,\n", - " 'q1': 33.0,\n", - " 'lower': 27.0,\n", - " 'upper': 43.0,\n", - " 'median': 35.0},\n", - " {'average': 35.99,\n", - " 'q1': 35.0,\n", - " 'pos': 61,\n", - " 'q3': 40.0,\n", - " 'lower': 27.5,\n", - " 'upper': 47.5,\n", - " 'median': 38.0},\n", - " {'pos': 76,\n", - " 'average': 30.265,\n", - " 'median': 35.0,\n", - " 'q3': 37.0,\n", - " 'lower': 22.0,\n", - " 'upper': 46.0,\n", - " 'q1': 31.0},\n", - " {'pos': 79,\n", - " 'q1': 32.0,\n", - " 'lower': 26.0,\n", - " 'average': 32.46,\n", - " 'upper': 42.0,\n", - " 'median': 35.0,\n", - " 'q3': 36.0},\n", - " {'pos': 26,\n", - " 'average': 37.855,\n", - " 'median': 40.0,\n", - " 'lower': 35.0,\n", - " 'upper': 43.0,\n", - " 'q1': 38.0,\n", - " 'q3': 40.0},\n", - " {'pos': 93,\n", - " 'q3': 35.0,\n", - " 'upper': 39.5,\n", - " 'lower': 27.5,\n", - " 'q1': 32.0,\n", - " 'median': 34.0,\n", - " 'average': 31.05},\n", - " {'pos': 75,\n", - " 'q3': 37.0,\n", - " 'lower': 22.0,\n", - " 'median': 35.0,\n", - " 'q1': 31.0,\n", - " 'average': 31.06,\n", - " 'upper': 46.0},\n", - " {'average': 37.35,\n", - " 'q3': 40.0,\n", - " 'q1': 36.0,\n", - " 'lower': 30.0,\n", - " 'upper': 46.0,\n", - " 'pos': 57,\n", - " 'median': 39.0},\n", - " {'lower': 27.5,\n", - " 'average': 35.985,\n", - " 'pos': 60,\n", - " 'q1': 35.0,\n", - " 'q3': 40.0,\n", - " 'upper': 47.5,\n", - " 'median': 38.0},\n", - " {'upper': 47.0,\n", - " 'lower': 31.0,\n", - " 'q1': 37.0,\n", - " 'pos': 44,\n", - " 'average': 37.565,\n", - " 'median': 40.0,\n", - " 'q3': 41.0},\n", - " {'median': 35.0,\n", - " 'q1': 32.0,\n", - " 'lower': 27.5,\n", - " 'average': 31.915,\n", - " 'pos': 87,\n", - " 'upper': 39.5,\n", - " 'q3': 35.0},\n", - " {'average': 32.065,\n", - " 'median': 35.0,\n", - " 'q3': 35.0,\n", - " 'pos': 88,\n", - " 'lower': 30.0,\n", - " 'upper': 38.0,\n", - " 'q1': 33.0},\n", - " {'upper': 47.0,\n", - " 'pos': 53,\n", - " 'q1': 37.0,\n", - " 'average': 37.845,\n", - " 'q3': 41.0,\n", - " 'median': 39.0,\n", - " 'lower': 31.0},\n", - " {'median': 35.0,\n", - " 'q3': 36.0,\n", - " 'pos': 81,\n", - " 'q1': 33.0,\n", - " 'lower': 28.5,\n", - " 'upper': 40.5,\n", - " 'average': 32.76},\n", - " {'pos': 8,\n", - " 'lower': 34.0,\n", - " 'upper': 42.0,\n", - " 'average': 37.625,\n", - " 'median': 39.0,\n", - " 'q3': 39.0,\n", - " 'q1': 37.0},\n", - " {'pos': 12,\n", - " 'average': 37.5,\n", - " 'upper': 42.0,\n", - " 'q1': 37.0,\n", - " 'median': 39.0,\n", - " 'q3': 39.0,\n", - " 'lower': 34.0},\n", - " {'q1': 36.0,\n", - " 'average': 37.59,\n", - " 'q3': 41.0,\n", - " 'lower': 28.5,\n", - " 'upper': 48.5,\n", - " 'pos': 54,\n", - " 'median': 39.5},\n", - " {'average': 36.25,\n", - " 'median': 38.0,\n", - " 'q1': 35.0,\n", - " 'lower': 27.5,\n", - " 'upper': 47.5,\n", - " 'pos': 63,\n", - " 'q3': 40.0},\n", - " {'q1': 32.0,\n", - " 'pos': 80,\n", - " 'average': 32.61,\n", - " 'median': 35.0,\n", - " 'upper': 42.0,\n", - " 'q3': 36.0,\n", - " 'lower': 26.0},\n", - " {'lower': 27.5,\n", - " 'median': 35.0,\n", - " 'q1': 32.0,\n", - " 'average': 31.835,\n", - " 'q3': 35.0,\n", - " 'upper': 39.5,\n", - " 'pos': 92},\n", - " {'upper': 38.0,\n", - " 'median': 35.0,\n", - " 'lower': 30.0,\n", - " 'q3': 35.0,\n", - " 'average': 31.815,\n", - " 'pos': 86,\n", - " 'q1': 33.0},\n", - " {'q3': 41.0,\n", - " 'upper': 45.5,\n", - " 'lower': 33.5,\n", - " 'pos': 27,\n", - " 'average': 38.44,\n", - " 'median': 40.0,\n", - " 'q1': 38.0},\n", - " {'pos': 94,\n", - " 'q1': 32.0,\n", - " 'lower': 27.5,\n", - " 'upper': 39.5,\n", - " 'average': 30.775,\n", - " 'median': 34.0,\n", - " 'q3': 35.0},\n", - " {'pos': 65,\n", - " 'upper': 45.0,\n", - " 'median': 37.0,\n", - " 'q1': 35.0,\n", - " 'q3': 39.0,\n", - " 'lower': 29.0,\n", - " 'average': 35.995},\n", - " {'average': 37.87,\n", - " 'q3': 41.0,\n", - " 'upper': 47.0,\n", - " 'q1': 37.0,\n", - " 'lower': 31.0,\n", - " 'pos': 41,\n", - " 'median': 40.0},\n", - " {'pos': 77,\n", - " 'average': 30.805,\n", - " 'upper': 45.0,\n", - " 'median': 35.0,\n", - " 'q3': 36.0,\n", - " 'q1': 30.0,\n", - " 'lower': 21.0},\n", - " {'pos': 13,\n", - " 'q1': 38.0,\n", - " 'q3': 41.0,\n", - " 'lower': 33.5,\n", - " 'upper': 45.5,\n", - " 'median': 40.0,\n", - " 'average': 38.94},\n", - " {'lower': 35.0,\n", - " 'q1': 38.0,\n", - " 'q3': 40.0,\n", - " 'upper': 43.0,\n", - " 'pos': 21,\n", - " 'average': 38.445,\n", - " 'median': 40.0},\n", - " {'q3': 36.0,\n", - " 'median': 35.0,\n", - " 'average': 31.46,\n", - " 'q1': 31.0,\n", - " 'pos': 78,\n", - " 'lower': 23.5,\n", - " 'upper': 43.5},\n", - " {'q3': 37.0,\n", - " 'lower': 32.0,\n", - " 'pos': 6,\n", - " 'upper': 40.0,\n", - " 'median': 35.0,\n", - " 'q1': 35.0,\n", - " 'average': 35.145},\n", - " {'pos': 64,\n", - " 'q3': 40.0,\n", - " 'median': 37.0,\n", - " 'lower': 27.5,\n", - " 'q1': 35.0,\n", - " 'upper': 47.5,\n", - " 'average': 36.095}]}" + "shape: (20_200, 2)\n", + "┌─────┬───────┐\n", + "│ pos ┆ score │\n", + "│ --- ┆ --- │\n", + "│ i64 ┆ i8 │\n", + "╞═════╪═══════╡\n", + "│ 0 ┆ 2 │\n", + "│ 1 ┆ 19 │\n", + "│ 2 ┆ 33 │\n", + "│ 3 ┆ 35 │\n", + "│ 4 ┆ 37 │\n", + "│ … ┆ … │\n", + "│ 96 ┆ 35 │\n", + "│ 97 ┆ 32 │\n", + "│ 98 ┆ 35 │\n", + "│ 99 ┆ 35 │\n", + "│ 100 ┆ 33 │\n", + "└─────┴───────┘" ] }, "execution_count": 8, diff --git a/docs/notebooks/tutorial.ipynb b/docs/notebooks/tutorial.ipynb index 5b98a620..acd8b329 100644 --- a/docs/notebooks/tutorial.ipynb +++ b/docs/notebooks/tutorial.ipynb @@ -4,13 +4,10 @@ "cell_type": "markdown", "id": "947f441f13ced60a", "metadata": {}, - "source": [ - "### Import dependencies" - ] + "source": "### Import dependencies" }, { "cell_type": "code", - "execution_count": null, "id": "7b173024d3e8f76", "metadata": { "ExecuteTime": { @@ -18,49 +15,30 @@ "start_time": "2025-02-24T16:59:36.960817Z" } }, - "outputs": [], "source": [ "import polars_bio as pb\n", "import pandas as pd\n", - "\n", - "# print(type(a_lazyframe))\n", - "# # display types of columns\n", - "# print(a_lazyframe.dtypes)\n", - "# print(type(a_dataframe))\n", - "# print(type(a_pandas_dataframe))\n", - "# print(pb.sql(\"SHOW TABLES\").collect())\n", - "print(pb.sql(\"SHOW TABLES\").collect())\n", - "\n", - "# a_lazyframe = pb.read_fastq(\"./example.fastq\")\n", - "# a_dataframe = a_lazyframe.collect()\n", - "# a_pandas_dataframe = a_lazyframe.collect().to_pandas()\n", - "# print(pb.base_sequence_quality(a_lazyframe))\n", - "# print(pb.base_sequence_quality(a_dataframe))\n", - "# print(pb.base_sequence_quality(a_pandas_dataframe))\n", - "\n", - "# result = pb.sql(\"SELECT base_sequence_quality(quality_scores) FROM example\").collect()\n", - "# print(result.item())\n", - "# print(pb.base_sequence_quality(\"./example.csv\"))\n", - "print(pb.base_sequence_quality(\"./example.fastq\"))\n", - "# print(pb.base_sequence_quality(\"./example.parquet\"))\n", - "\n", - "# sql display all tables and print it\n", - "print(pb.sql(\"SHOW TABLES\").collect())\n", - "# use sql and display result (it is aggregate function that returns string)\n", - "# print(result.item())\n" - ] + "from polars_bio.range_viz import visualize_intervals" + ], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:polars_bio:Creating BioSessionContext\n" + ] + } + ], + "execution_count": 1 }, { "cell_type": "markdown", "id": "d2bb8c193890f27f", "metadata": {}, - "source": [ - "### Sample data" - ] + "source": "### Sample data" }, { "cell_type": "code", - "execution_count": null, "id": "86fe039c3780140e", "metadata": { "ExecuteTime": { @@ -68,31 +46,27 @@ "start_time": "2025-02-24T16:59:37.452650Z" } }, - "outputs": [], "source": [ "df1 = pd.DataFrame(\n", " [[\"chr1\", 1, 5], [\"chr1\", 3, 8], [\"chr1\", 8, 10], [\"chr1\", 12, 14]],\n", " columns=[\"chrom\", \"start\", \"end\"],\n", ")\n", "\n", - "pb.base_sequence_quality(df1)\n", - "\n", "df2 = pd.DataFrame(\n", " [[\"chr1\", 4, 8], [\"chr1\", 10, 11]], columns=[\"chrom\", \"start\", \"end\"]\n", ")" - ] + ], + "outputs": [], + "execution_count": 2 }, { "cell_type": "markdown", "id": "a884cd2960796fdb", "metadata": {}, - "source": [ - "### Overlap" - ] + "source": "### Overlap" }, { "cell_type": "code", - "execution_count": null, "id": "304f3aa6fcdc9650", "metadata": { "ExecuteTime": { @@ -100,14 +74,22 @@ "start_time": "2025-02-24T16:59:37.538707Z" } }, - "outputs": [], "source": [ "overlapping_intervals = pb.overlap(df1, df2, output_type=\"pandas.DataFrame\")" - ] + ], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:polars_bio.operation:Running Overlap operation with algorithm Coitrees and 1 thread(s)...\n" + ] + } + ], + "execution_count": 3 }, { "cell_type": "code", - "execution_count": null, "id": "61c9254622598622", "metadata": { "ExecuteTime": { @@ -115,14 +97,76 @@ "start_time": "2025-02-24T16:59:37.552440Z" } }, - "outputs": [], "source": [ "display(overlapping_intervals)" - ] + ], + "outputs": [ + { + "data": { + "text/plain": [ + " chrom_1 start_1 end_1 chrom_2 start_2 end_2\n", + "0 chr1 1 5 chr1 4 8\n", + "1 chr1 3 8 chr1 4 8" + ], + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
chrom_1start_1end_1chrom_2start_2end_2
0chr115chr148
1chr138chr148
\n", + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "execution_count": 4 }, { "cell_type": "code", - "execution_count": null, "id": "e640901ec6e6ce11", "metadata": { "ExecuteTime": { @@ -130,22 +174,41 @@ "start_time": "2025-02-24T16:59:37.581481Z" } }, - "outputs": [], "source": [ "visualize_intervals(overlapping_intervals)" - ] + ], + "outputs": [ + { + "data": { + "text/plain": [ + "
" + ], + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAygAAADTCAYAAABqSTe2AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8ekN5oAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAZEUlEQVR4nO3dB5QdVf0H8BtIQgshBCQQJPTeiyBFooAUI1KkChIIRwXpKiIqhB6K1MChKAKKNKWDlCABQQgdpCg1hibtHyAsSBLI+5/f9bx1d7OBbNjNXPZ9Pue8ZN+8dmdm3879zi3To1ar1RIAAEABZqm6AAAAAHUCCgAAUAwBBQAAKIaAAgAAFENAAQAAiiGgAAAAxRBQAACAYggoAABAMQQUAACgGAIKQEHuuOOO1KNHj/x/CY444ohcnu4i1iXWCYByCSgAMIPeeeedNMsss6Rbbrkl37/66qvTbLPNliZOnDjVc2PZIYcckgYOHJjmmGOOtM4666RRo0ZVUGqAsgkoAEzTL3/5y/Sf//wndRexLrFOneX+++/P/0fYCPfee29affXVc0hpa/fdd0+nnHJK2mWXXdLpp5+eZp111vSNb3wj3X333Z1WHoDuoGfVBQAgpQ8//DD17t07laZnz5751l3MPvvsn/qc999/P80111zTHVCWXXbZ1K9fv+aAUg8rbZ932WWXpZNOOin95Cc/yct22223tNJKK6Wf/vSn6Z577unwugB0V1pQgIb2yCOPpC222CL17ds39enTJ2288cZpzJgxzY8/+OCDedzCRRddNNVro1tPPHbDDTc0L3vllVfSsGHD0oABA/JZ9BVXXDH99re/bXecSVRY42z+wgsvnOacc840YcKEdst41113pe233z4NGjQov+ciiyySDjrooKlaNuIMfazDCy+8kDbbbLNcyY7uREcddVSq1WrNz/vXv/6VP/9Xv/pVOvXUU9Oiiy6auxwNHjw4PfHEE586BiXu77vvvumaa67JFez6et58881TlT3Wda211srBYMkll0znnnvudI9r+epXv5rf/6GHHkrrrbdeLuPiiy+ezjnnnFbPmzRpUjr88MPTmmuumeaZZ5683l/5ylfS6NGjP3UMSr0sTz31VPrOd76T5p133rTBBht8Yrnefffd9NZbb+VbBJJVV101//z666/nsi633HL5fjyv7k9/+lNuMfn+97/fvCy2yZ577pnf46WXXvrU7QHQKLrPaTGADnryySdzRTbCSZzF7tWrV65AR8X4zjvvzGfCo3K9xBJLpCuuuCINHTq01esvv/zyXKGNMBCigvrlL3+5uQL/hS98Id100025Ehrh48ADD2z1+qOPPjq3msQZ9RifMK0WlD/+8Y/pgw8+SHvvvXeab7758tn4kSNHppdffjk/1tLHH3+cNt9881yOE088MYeG4cOHp48++igHlZZ+97vfpffeey/ts88+uQUnuh1ttNFG6fHHH88B65NEt6Srrroq/fCHP0xzzz13OuOMM9K3v/3t9OKLL+Yy1sNflGWhhRZKRx55ZC5blCG2y/R6++23czeoHXbYIe288855P8R2iG0VQTDEtv3Nb36TH//e976X1+n888/P+yW21WqrrfapnxMBcOmll07HHXdcqzDXnq222ir/frT9XaiLbRK3CHz1yQ5iWyyzzDL5d62ltddeO///6KOP5uAJQErxhxigIW299da13r17155//vnmZa+++mpt7rnnrm244YbNyw499NBar169auPHj29eNnHixFq/fv1qw4YNa16255571hZaaKHaW2+91epzdtppp9o888xT++CDD/L90aNHRw24tsQSSzQvq6s/Fv/XtX1OGDFiRK1Hjx61cePGNS8bOnRofu1+++3XvGzKlCm1IUOG5PV8880387KxY8fm580xxxy1l19+ufm59913X15+0EEHNS8bPnx4XtZS3I/3e+6555qXPfbYY3n5yJEjm5dtueWWtTnnnLP2yiuvNC979tlnaz179pzqPdszePDg/LyTTz651XZfbbXVagsssEBt0qRJedlHH32Ul7f09ttv1wYMGNBq/9TLHuvUdv123nnn2vR68MEHa6NGjaqdddZZ+bUXX3xxvr/77rvXFllkkfxz3OJ5dSuuuGJto402muq9nnzyyfwe55xzznR/PkB3p4sX0JDibP6tt96att5669xCUhdn+6OrT7QQ1Ltc7bjjjmny5Mm5xaAuXhszOMVjIeq+V155Zdpyyy3zz/UuQHGLM/nR3efhhx9uVYZokYluS5+m5XNifES8Z3R5is+JM/NtRetNXb01J7pB3Xbbba2eF+se3ctans2PVqM///nPn1qmTTbZJHfZqltllVVy60B0L6tv3/i8+IzoZla31FJL5S510yvG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qmcfVM8+qJ590L22/wwNkgcAAOgKungBAADFEFAAAIBiCCgAAEAxBBQAAODzHVDOOuustNhii6XZZ589rbPOOun+++/v/JLRrhEjRqQvfelLae65504LLLBA2nrrrdPTTz9ddbEa1vHHH5969OiRDjzwwKqL0nBeeeWVtOuuu6b55psvzTHHHGnllVdODz74YNXFaggff/xxOuyww9Liiy+et/2SSy6Zjj766GTOla7117/+NW255ZZp4MCB+e/ONddc0+rx2P6HH354WmihhfJ+2WSTTdKzzz5bWXkbaftPnjw5HXLIIfnv0FxzzZWfs9tuu6VXX3210jI32negpb322is/57TTTpupZezu/jod++Af//hH+ta3vpWvLB/fh6i3vvjii10bUC6//PL0ox/9KE8l9vDDD6dVV101bbbZZumNN97o6FsxA+688860zz77pDFjxqRRo0blP4qbbrppev/996suWsN54IEH0rnnnptWWWWVqovScN5+++20/vrrp169eqWbbropPfXUU+nkk09O8847b9VFawgnnHBCOvvss9OZZ56ZD0Rx/8QTT0wjR46sumjdWvydj2NunCRsT+yDM844I51zzjnpvvvuyxWDOD5/+OGHM72sjbb9P/jgg1wniuAe/1911VX55GFU0ph534G6q6++OteTohLNzN0Hzz//fNpggw3Scsstl+64447097//PX8volGjQ2odtPbaa9f22Wef5vsff/xxbeDAgbURI0Z09K3oBG+88UacsqzdeeedVRelobz33nu1pZdeujZq1Kja4MGDawcccEDVRWoohxxySG2DDTaouhgNa8iQIbVhw4a1WrbtttvWdtlll8rK1Gji7/7VV1/dfH/KlCm1BRdcsHbSSSc1L3vnnXdqs802W+3SSy+tqJSNs/3bc//99+fnjRs3bqaVq5FMax+8/PLLtYUXXrj2xBNP1BZddNHaqaeeWkn5GnUf7LjjjrVdd931M793h1pQJk2alB566KHcbFw3yyyz5Pv33ntvx5IRneLdd9/N//fv37/qojSUaMUaMmRIq+8CM891112X1lprrbT99tvnro6rr756+vWvf111sRrGeuutl/7yl7+kZ555Jt9/7LHH0t1335222GKLqovWsMaOHZtee+21Vn+TontFdMN2fK7u+BxdYPr161d1URrGlClT0ne/+9108MEHpxVXXLHq4jTk9r/xxhvTMsssk1tv4/gcf4M+qSvetHQooLz11lu57/GAAQNaLY/78YeRmf+LEGMfoqvLSiutVHVxGsZll12Wm/BjPBDVeOGFF3IXo6WXXjrdcsstae+99077779/uuiii6ouWkP42c9+lnbaaafchB/d7CIgxt+iXXbZpeqiNaz6MdjxuQzRrS7GpOy8886pb9++VRenYUR30549e+bjATNfDPdoamrK43M333zzdOutt6ZtttkmbbvttnmIQkf07LJSMlPO4j/xxBP5zCUzx0svvZQOOOCAPP6nw/0p6dRwHi0oxx13XL4fFeT4LkTf+6FDh1ZdvG7viiuuSH/4wx/SJZdcks9SPvroozmgRH9v259GF2NDd9hhhzxpQZxIYeaIHj6nn356PoEYLVdUc2wOW221VTrooIPyz6uttlq655578vF58ODBXdOCMv/886dZZ501vf76662Wx/0FF1ywI2/FZ7TvvvumG264IY0ePTp98YtfrLo4DfUHMM4QrLHGGvksTdzirEAMTI2fo4WRrhezFK2wwgqtli2//PIdniWEGRPdJ+qtKDFrUXSpiIORVsXq1I/Bjs9lhJNx48blE1laT2aeu+66Kx+fBw0a1Hx8jv3w4x//OM88S9eLnBDbvTOOzx0KKL17905rrrlm7nvcMi3F/XXXXbdDH8yMiTMyEU5ihorbb789T/PJzLPxxhunxx9/PJ8xrt/iTH50bYmfI8DT9aJbY9vptWM8xKKLLlpZmRpJzFgU4w9bit/9+tkzZr44FkQQaXl8njBhQp7Ny/F55oaTmNr5tttuy1OgM/PEiZKYMarl8TladeOESnQFputFTogphTvj+NzhLl4xxXA04UelbO21187zS8eUY3vssUdH34oZ7NYV3SquvfbafC2Uet/iGAwZ897TtWKbtx3vE1N5xoHIOKCZJ87Wx0Dt6OIVFYK4FtN5552Xb3S9mAP/2GOPzWcqo4vXI488kk455ZQ0bNiwqovWrUXf7ueee67VwPiohMUkKbEvopvdMccck8dmRWCJqT2jghbXy6Jrt3+06m633Xa5e1H0bojW9PrxOR6Pihtd/x1oGwpjjFwE92WXXbaC0jbmPjj44IPTjjvumDbccMP0ta99Ld18883p+uuvz1MOd8iMTP01cuTI2qBBg2q9e/fO0w6PGTPmM08nxvSJXdbe7YILLqi6aA3LNMPVuP7662srrbRSnkZ1ueWWq5133nlVF6lhTJgwIf/Ox3Fg9tlnry2xxBK1X/ziF7WJEydWXbRubfTo0e3+/R86dGjzVMOHHXZYbcCAAfl7sfHGG9eefvrpqovdENt/7Nix0zw+x+uYOd+BtkwzXM0+OP/882tLLbVUPj6suuqqtWuuuabDn9Mj/un8fAUAANBxHb6SPAAAQFcRUAAAgGIIKAAAQDEEFAAAoBgCCgAAUAwBBQAAKIaAAgAAFENAAQAAiiGgAAAAxRBQAACAYggoAABAMQQUAAAgleL/ATwTEzjW7N/GAAAAAElFTkSuQmCC" + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "
" + ], + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAygAAADTCAYAAABqSTe2AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8ekN5oAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAY4klEQVR4nO3dCbgd8/0/8G/IhogIlaASu9h3ak01ammqltZWKsSjpbFWVTdiTSxVS3iQUvRRa+3UEhpKiZ1Sak1jq+0XRKgkkvk/n+//Ofe59+aGe5N7MyPn9Xqek3tmzpxzvjOTc2be811Op6IoigQAAFAB85VdAAAAgBoBBQAAqAwBBQAAqAwBBQAAqAwBBQAAqAwBBQAAqAwBBQAAqAwBBQAAqAwBBQAAqAwBBaBC7r333tSpU6f8twqOO+64XJ55RaxLrBMA1SWgAMBs+vDDD9N8882X7rzzzjx9ww03pG7duqUpU6Y0WW7y5Mlp+PDhabvttku9e/fOQenSSy8tqdQA1SagADBLv/3tb9P//ve/NK+IdYl1ai+PPPJI/rvxxhvnvw899FBad911c0hp7P33308nnHBCev7559Paa6/dbu8PMC/qXHYBAEjps88+S127dk1V07lz53ybV3Tv3v1Ll/nkk0/SQgst1OqAssoqq6RevXo1BJRaWGlsySWXTP/9739T375902OPPZY23HDD2Sg9QH1QgwLUtSeffDJtv/32qWfPnqlHjx5p0KBBady4cQ2Px8lkNMe57LLLZnpuNOuJx2699daGeW+++WYaOnRo6tOnT76Kvvrqq6c//vGPLfYzueqqq/LV/KWXXjotuOCCadKkSS2W8f7770+77rpr6tevX37NZZZZJh1xxBEz1Wzsu+++eR1effXVtO222+aT7KWWWipfuS+KomG5//znP/n9f/e736Uzzzwz9e/fPy2wwAJp4MCB6dlnn/3SPigxffDBB6cbb7wxrbHGGg3reccdd8xU9ljXDTbYIAeDFVZYIV144YWt7tfyzW9+M7/+448/njbddNNcxuWWWy5dcMEFTZabOnVqOvbYY9P666+fFllkkbzeW2yxRRo7duyX9kGpleW5555LP/zhD9Oiiy6aNt988y8s10cffZRrROIWgSRqROL+O++8k8s6YMCAPB3L1cQ2inACwJebdy6LAbTRv/71r3wiG+HkF7/4RerSpUs+gY4T4/vuuy9fCY+T6+WXXz5dc801aciQIU2ef/XVV+cT2ggDIU5Qv/GNbzScwH/ta19Lt99+e9p///1z+Dj88MObPP/EE0/MtSY///nPc5+FWdWgXHvttenTTz9NBx10UFpsscXyVftRo0alN954Iz/W2PTp03M/hyjHaaedlkND9H34/PPPc1Bp7E9/+lP6+OOP07Bhw3INztlnn52+9a1vpWeeeSYHrC/ywAMPpOuvvz799Kc/TQsvvHA655xz0ve///302muv5TLWwl+UJWoPjj/++Fy2KENsl9b64IMP0ne+85202267pT333DPvh9gOsa0iCIbYthdddFF+/IADDsjrdPHFF+f9EttqnXXW+dL3iQC40korpREjRjQJcy3Zcccd8/+P5v8XamKbxC0CX1UGOwD4SikA6tROO+1UdO3atXjllVca5r311lvFwgsvXGy55ZYN8371q18VXbp0KSZOnNgwb8qUKUWvXr2KoUOHNszbf//9iyWXXLJ4//33m7zPHnvsUSyyyCLFp59+mqfHjh0bZ8DF8ssv3zCvpvZY/K1pvkwYOXJk0alTp2LChAkN84YMGZKfe8ghhzTMmzFjRjF48OC8nu+9916eN378+LzcAgssULzxxhsNyz788MN5/hFHHNEwb/jw4XleYzEdr/fyyy83zHv66afz/FGjRjXM22GHHYoFF1ywePPNNxvmvfTSS0Xnzp1nes2WDBw4MC93xhlnNNnu66yzTrHEEksUU6dOzfM+//zzPL+xDz74oOjTp0+T/VMre6xT8/Xbc889i9Z67LHHijFjxhTnnXdefu7ll1+ep/fdd99imWWWyffjFsu15NFHH83Pu+SSS1r9ngD1RBMvoC7F1fy77ror7bTTTrmGpCau9kdTn6ghqDW52n333dO0adNyjUFNPDdGcIrHQpz7XnfddWmHHXbI92tNgOIWV/Kjuc8TTzzRpAxRIxPNlr5M42Wif0S8ZjR5iveJWormovamplabE82g7r777ibLxbpH87KajTbaKNca/fWvf/3SMm299da5yVbNWmutlWuionlZbfvG+8V7RDOzmhVXXDE3qWut6P/yk5/8pGE6ak5i+t13383NqcL888/fUPs0Y8aMNHHixFxjFLVfzbf5rBx44IGtLlM0JYv1j/eIddtrr73y9HvvvZebCMb9uMVy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VIaAAgAAfLUDynnnnZeWXXbZ1L1797TxxhunRx55pP1LRotGjhyZNtxww7TwwgunJZZYIu20007phRdeKLtYdeuUU05JnTp1SocffnjZRak7b775Ztp7773TYostlhZYYIG05pprpscee6zsYtWF6dOnp2OOOSYtt9xyeduvsMIK6cQTT0zGXOlYf//739MOO+yQllpqqfy9c+ONNzZ5PLb/sccem5Zccsm8X7beeuv00ksvlVbeetr+06ZNS0cffXT+HlpooYXyMvvss0966623Si1zvX0GGjvwwAPzMmedddZcLeO87u+t2AfPP/98+t73vpd/WT4+D3He+tprr3VsQLn66qvTz372szyU2BNPPJHWXnvttO2226Z33323rS/FbLjvvvvSsGHD0rhx49KYMWPyl+I222yTPvnkk7KLVnceffTRdOGFF6a11lqr7KLUnQ8++CBtttlmqUuXLun2229Pzz33XDrjjDPSoosuWnbR6sKpp56azj///HTuuefmA1FMn3baaWnUqFFlF22eFt/zccyNi4QtiX1wzjnnpAsuuCA9/PDD+cQgjs+fffbZXC9rvW3/Tz/9NJ8TRXCPv9dff32+eBgnacy9z0DNDTfckM+T4iSaubsPXnnllbT55punAQMGpHvvvTf985//zJ+LqNRok6KNNtpoo2LYsGEN09OnTy+WWmqpYuTIkW19KdrBu+++G5csi/vuu6/sotSVjz/+uFhppZWKMWPGFAMHDiwOO+ywsotUV44++uhi8803L7sYdWvw4MHF0KFDm8zbZZddir322qu0MtWb+N6/4YYbGqZnzJhR9O3btzj99NMb5n344YdFt27diiuvvLKkUtbP9m/JI488kpebMGHCXCtXPZnVPnjjjTeKpZdeunj22WeL/v37F2eeeWYp5avXfbD77rsXe++99xy/dptqUKZOnZoef/zxXG1cM9988+Xphx56qG3JiHbx0Ucf5b+9e/cuuyh1JWqxBg8e3OSzwNxz8803pw022CDtuuuuuanjuuuum/7whz+UXay6semmm6Z77rknvfjii3n66aefTg888EDafvvtyy5a3Ro/fnx6++23m3wnRfOKaIbt+Fze8TmawPTq1avsotSNGTNmpB/96EfpqKOOSquvvnrZxanL7X/bbbellVdeOdfexvE5voO+qCnerLQpoLz//vu57XGfPn2azI/p+GJk7v9HiL4P0dRljTXWKLs4deOqq67KVfjRH4hyvPrqq7mJ0UorrZTuvPPOdNBBB6VDDz00XXbZZWUXrS788pe/THvssUeuwo9mdhEQ47tor732Krtodat2DHZ8roZoVhd9Uvbcc8/Us2fPsotTN6K5aefOnfPxgLkvuntMnjw598/dbrvt0l133ZV23nnntMsuu+QuCm3RucNKyVy5iv/ss8/mK5fMHa+//no67LDDcv+fNrenpF3DedSgjBgxIk/HCXJ8FqLt/ZAhQ8ou3jzvmmuuSX/+85/TFVdcka9SPvXUUzmgRHtv2596F31Dd9tttzxoQVxIYe6IFj5nn312voAYNVeUc2wOO+64YzriiCPy/XXWWSc9+OCD+fg8cODAjqlBWXzxxdP888+f3nnnnSbzY7pv375teSnm0MEHH5xuvfXWNHbs2PT1r3+97OLU1RdgXCFYb7318lWauMVVgeiYGvejhpGOF6MUrbbaak3mrbrqqm0eJYTZE80narUoMWpRNKmIg5FaxfLUjsGOz9UIJxMmTMgXstSezD33339/Pj7369ev4fgc++HII4/MI8/S8SInxHZvj+NzmwJK165d0/rrr5/bHjdOSzG9ySabtOmNmT1xRSbCSYxQ8be//S0P88ncM2jQoPTMM8/kK8a1W1zJj6YtcT8CPB0vmjU2H147+kP079+/tDLVkxixKPofNhb/92tXz5j74lgQQaTx8XnSpEl5NC/H57kbTmJo57vvvjsPgc7cExdKYsSoxsfnqNWNCyrRFJiOFzkhhhRuj+Nzm5t4xRDDUYUfJ2UbbbRRHl86hhzbb7/92vpSzGazrmhWcdNNN+XfQqm1LY7OkDHuPR0rtnnz/j4xlGcciPQDmnvian101I4mXnFCEL/FNHr06Hyj48UY+CeffHK+UhlNvJ588sn0+9//Pg0dOrTsos3Tom33yy+/3KRjfJyExSApsS+imd1JJ52U+2ZFYImhPeMELX4vi47d/lGr+4Mf/CA3L4rWDVGbXjs+x+Nx4kbHfwaah8LoIxfBfZVVVimhtPW5D4466qi0++67py233DJttdVW6Y477ki33HJLHnK4TWZn6K9Ro0YV/fr1K7p27ZqHHR43btwcDydG68Qua+l2ySWXlF20umWY4XLccsstxRprrJGHUR0wYEAxevTosotUNyZNmpT/z8dxoHv37sXyyy9f/OY3vymmTJlSdtHmaWPHjm3x+3/IkCENQw0fc8wxRZ8+ffLnYtCgQcULL7xQdrHrYvuPHz9+lsfneB5z5zPQnGGGy9kHF198cbHiiivm48Paa69d3HjjjW1+n07xT/vnKwAAgLZr8y/JAwAAdBQBBQAAqAwBBQAAqAwBBQAAqAwBBQAAqAwBBQAAqAwBBQAAqAwBBQAAqAwBBQAAqAwBBQAAqAwBBQAAqAwBBQAASFXx/wAOW0rnl+0oyQAAAABJRU5ErkJggg==" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "execution_count": 5 }, { "cell_type": "markdown", "id": "8e2509b9cb5237d8", "metadata": {}, - "source": [ - "### Nearest" - ] + "source": "### Nearest" }, { "cell_type": "code", - "execution_count": null, "id": "bc0f8689c31221b3", "metadata": { "ExecuteTime": { @@ -153,14 +216,22 @@ "start_time": "2025-02-24T16:59:37.652480Z" } }, - "outputs": [], "source": [ "nearest_intervals = pb.nearest(df1, df2, output_type=\"pandas.DataFrame\")" - ] + ], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:polars_bio.operation:Running Nearest operation with algorithm Coitrees and 1 thread(s)...\n" + ] + } + ], + "execution_count": 6 }, { "cell_type": "code", - "execution_count": null, "id": "aad83ab53e1294fc", "metadata": { "ExecuteTime": { @@ -168,14 +239,101 @@ "start_time": "2025-02-24T16:59:37.665033Z" } }, - "outputs": [], "source": [ "display(nearest_intervals)" - ] + ], + "outputs": [ + { + "data": { + "text/plain": [ + " chrom_1 start_1 end_1 chrom_2 start_2 end_2 distance\n", + "0 chr1 1 5 chr1 4 8 0\n", + "1 chr1 3 8 chr1 4 8 0\n", + "2 chr1 8 10 chr1 4 8 0\n", + "3 chr1 12 14 chr1 10 11 1" + ], + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
chrom_1start_1end_1chrom_2start_2end_2distance
0chr115chr1480
1chr138chr1480
2chr1810chr1480
3chr11214chr110111
\n", + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "execution_count": 7 }, { "cell_type": "code", - "execution_count": null, "id": "5f69f700b50f58e2", "metadata": { "ExecuteTime": { @@ -183,29 +341,71 @@ "start_time": "2025-02-24T16:59:37.673937Z" } }, - "outputs": [], "source": [ "visualize_intervals(nearest_intervals, \"nearest pair\")" - ] + ], + "outputs": [ + { + "data": { + "text/plain": [ + "
" + ], + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAygAAADTCAYAAABqSTe2AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8ekN5oAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAXGUlEQVR4nO3dCbRVZf0/4BdlUhEVTBANNHM2UVEyNcmFaWaZmmOaJLVSc0rNpQ2KMymZYznVQlc5VYpTOWDiUEpgakEaDiE4pKioeJ0gPf/1fX//c9e9CMLFy92vnOdZ63DPPnffs9+zN+fs97Pf4XSq1Wq1BAAAUIClqi4AAABAnYACAAAUQ0ABAACKIaAAAADFEFAAAIBiCCgAAEAxBBQAAKAYAgoAAFAMAQUAACiGgAJA8b71rW+lNdZYo+piANABBBQAPtRbb72VTjrppHT33XenJcluu+2W9t1333y/VqullVZaKV1++eXzXPemm25Km222WerevXvq379/GjFiRPrf//7XwSUGaAwCCgALDCgnn3xypQHlsssuS1OmTGnX55wwYULacsst8/3HHnssvfbaa83LLd16661p1113TSuuuGK64IIL8v3TTjstHX744e1aHgD+T+f//xOAJcSbb76ZlltuubQk6dKlywLXiRaN999/P3Xt2nWB6z777LPp+eefbw4kDzzwQFphhRXSuuuu+4F1f/CDH6SNN9443XHHHalz5/87bfbs2TOdccYZ6cgjj0zrrbfeIr0mAOZNCwrARxTdnzp16pSefPLJPFYirrRHZffAAw/MrQ9z++1vf5sGDRqUlllmmdSrV6+0zz77pGeeeabVOvfdd1/ac889c3eibt26pU9+8pPpqKOOSm+//Xar9WJ7PXr0SE899VT68pe/nJZffvm033775d9FZf3cc89NG264Ye6a1KdPn3TQQQelV199tdVzPPjgg2nHHXdMK6+8ci7TmmuumYYPH55/9/TTT6dPfOIT+X60osTrjFu85vmJblKxzr333pu317t371yhP+CAAz6w7RtvvDHtvPPOqV+/fvl1rrXWWunUU09N77333oeOQYlyxTZ+9rOf5dcYfxd//+ijj863XO+++256+eWX823cuHE59MR+jeUoa4SQV155JS/HvgvxfHH77ne/2xxOwve+973cLewPf/jDfLcHwKLRggLQTvbaa69cuR85cmR66KGH0q9+9au0yiqrpDPPPLN5ndNPPz2dcMIJed3vfOc76aWXXsrdhrbddtv08MMP53ATfv/73+dwc8ghh+QKfnRHivXiyn/8bu6WgwgY22yzTa6wL7vssvnxCAcRFiIoHXHEEWnq1KnpwgsvzNv561//mivoM2bMSDvssEMOIccff3zeflT+r7/++vwc8fhFF12UyxFjNnbffff8eFTmF+Swww7LzxdhJrpnxfNMmzYtdxWLcBGifBGwjj766PzzrrvuSieeeGKaNWtWGjVq1AK3MXr06PTOO+/kABEBJQLf/Fx99dV5X7S02mqrtVquh7HYVxGIYl+FzTffvNV6EahWX3315t8D0I5qAHwkI0aMqMXH6fDhw1s9vttuu9V69+7dvPz000/Xll566drpp5/ear1JkybVOnfu3Orxt9566wPbGTlyZK1Tp061adOmNT82bNiwvO3jjz++1br33XdffvzKK69s9fhtt93W6vExY8bk5YkTJ8739b300kt5nXidC2P06NF5/UGDBtVmz57d/PhZZ52VH7/xxhs/9HUedNBBtWWXXbb2zjvvtHqdAwYMaF6eOnVqfq6ePXvWZsyYsVDlev7552tjx47Nt3iuAw44IN+/+uqr83Odf/75zb9/++2389+MGjUq/2769OkfeL4tttiituWWWy7UtgFYeLp4AbSTgw8+uNXy5z//+dxlKFoDQrRKRNehaD2pdzWKW9++fdPaa6+dux3VRVerlmNKYr2tttoqdyua11X7aOFoKVpZopvZF7/4xVbbiq5l0VJR31a9xeaWW25Jc+bMadf9Ea0aLceORBmjm9Sf/vSneb7ON954I5cx9lu0Hv373/9e4Da+/vWvN7d6LMiqq66att9++9waEl3qoitcLEeZogtclDeW4xbLod6lLlpn5hbrzN3lDoCPThcvgHYS40VaimlrQ4y7iDEYTzzxRA4YEUbmpWVlfvr06bmrU0xvO/e4jddff73VclSwo7tRS7GtWC+6mM1LdO0KQ4YMyZX8GF9yzjnnpC984Qt5lqpvfOMb86yUt8XcrzOCUYSE6EJW969//Sv95Cc/yV276kFufq9zXqJL3cKI8FV/vttvvz0ttdRSeXB7BKJY3nTTTXNAilsEu/qxqAeoGL8yt+ha1jJgAdA+BBSAdrL00kvP8/EIJSFaT2Ls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3gN1Y8aMyfWkqETTscfgqaeeSttss01ab7310t13353++c9/5vdFNGq0Sa2NBg8eXDv00EObl997771av379aiNHjmzrU9EOZsyYEZcsa/fcc0/VRWkob7zxRm3ttdeujR07tjZkyJDakUceWXWRGspxxx1X22abbaouRsPaeeeda8OHD2/12O67717bb7/9KitTo4nP/TFjxjQvv//++7W+ffvWRo0a1fzYa6+9VuvWrVvt6quvrqiUjbP/52XChAl5vWnTpnVYuRrJ/I7Bs88+W1tttdVqkydPrg0YMKB2zjnnVFK+Rj0Ge++9d23//ff/yM/dphaU2bNnp7///e+52bhuqaWWyssPPPBA25IR7eL111/PP3v16lV1URpKtGLtvPPOrd4LdJybbropbb755mnPPffMXR033XTTdNlll1VdrIax1VZbpT//+c/p8ccfz8v/+Mc/0l/+8pe00047VV20hjV16tT0wgsvtPpMiu4V0Q3b+bm683N0gVlxxRWrLkrDeP/999M3v/nNdOyxx6YNN9yw6uI05P7/4x//mNZZZ53cehvn5/gM+rCuePPTpoDy8ssv577Hffr0afV4LMcHIx3/HyHGPkRXl4022qjq4jSMa665Jjfhx3ggqvGf//wndzFae+210+23354OOeSQdMQRR6Qrrrii6qI1hOOPPz7ts88+uQk/utlFQIzPov3226/qojWs+jnY+bkM0a0uxqTsu+++qWfPnlUXp2FEd9POnTvn8wEdL4Z7NDU15fG5X/rSl9Idd9yRdtttt7T77rvnIQpt0XmxlZIOuYo/efLkfOWSjvHMM8+kI488Mo//aXN/Sto1nEcLyhlnnJGXo4Ic74Xoez9s2LCqi7fE+93vfpeuvPLKdNVVV+WrlI888kgOKNHf2/6n0cXY0L322itPWhAXUugY0cPnvPPOyxcQo+WKas7N4Wtf+1o66qij8v1NNtkk3X///fn8PGTIkMXTgrLyyiunpZdeOr344outHo/lvn37tuWp+IgOO+ywdMstt6Rx48al1VdfveriNNQHYFwh2GyzzfJVmrjFVYEYmBr3o4WRxS9mKdpggw1aPbb++uu3eZYQFk10n6i3osSsRdGlIk5GWhWrUz8HOz+XEU6mTZuWL2RpPek49913Xz4/9+/fv/n8HMfhmGOOyTPPsvhFToj93h7n5zYFlK5du6ZBgwblvsct01Isf+5zn2vThlk0cUUmwknMUHHXXXflaT7pOEOHDk2TJk3KV4zrt7iSH11b4n4EeBa/6NY49/TaMR5iwIABlZWpkcSMRTH+sKX4v1+/ekbHi3NBBJGW5+dZs2bl2bycnzs2nMTUznfeeWeeAp2OExdKYsaolufnaNWNCyrRFZjFL3JCTCncHufnNnfxiimGowk/KmWDBw/O80vHlGMHHnhgW5+KRezWFd0qbrzxxvxdKPW+xTEYMua9Z/GKfT73eJ+YyjNORMYBdZy4Wh8DtaOLV1QI4ruYLr300nxj8Ys58E8//fR8pTK6eD388MPp5z//eRo+fHjVRVuiRd/uJ598stXA+KiExSQpcSyim91pp52Wx2ZFYImpPaOCFt+XxeLd/9Gqu8cee+TuRdG7IVrT6+fn+H1U3Fj874G5Q2GMkYvgvu6661ZQ2sY8Bscee2zae++907bbbpu22267dNttt6Wbb745TzncJosy9dcFF1xQ69+/f61r16552uHx48d/5OnEWDhxyOZ1Gz16dNVFa1imGa7GzTffXNtoo43yNKrrrbde7dJLL626SA1j1qxZ+f98nAe6d+9e+9SnPlX78Y9/XHv33XerLtoSbdy4cfP8/B82bFjzVMMnnHBCrU+fPvl9MXTo0NqUKVOqLnZD7P+pU6fO9/wcf0fHvAfmZprhao7Br3/969qnP/3pfH4YOHBg7YYbbmjzdjrFP+2frwAAANquzd8kDwAAsLgIKAAAQDEEFAAAoBgCCgAAUAwBBQAAKIaAAgAAFENAAQAAiiGgAAAAxRBQAACAYggoAABAMQQUAACgGAIKAACQSvH/AFFsXXBd2e9cAAAAAElFTkSuQmCC" + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "
" + ], + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAygAAADTCAYAAABqSTe2AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8ekN5oAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAWgUlEQVR4nO3dC7AWZf0H8Ae5iIqoYIpooBlqYqJpVspfcjTNmEzIG0GS1KSOpqk52gXxRqRmXstbDTqFaKWIWGqYeCklMbU0zVuItxQVBY+okL7/+T0z75lzEJQD55x95Hw+My+c3bPsPu8u77v73eeynWq1Wi0BAAAUYLWqCwAAAFAnoAAAAMUQUAAAgGIIKAAAQDEEFAAAoBgCCgAAUAwBBQAAKIaAAgAAFENAAQAAiiGgAFC8b3zjG2nTTTetuhgAtAMBBYD3tXDhwnTyySen2267La1Khg0blkaMGJF/rtVqab311kuXX375e5a7+uqr06hRo9KAAQNSp06d0uc///kKSgvQcQgoAHxgQDnllFMqDSiXXXZZevTRR1t1nffcc0/67Gc/m39+5JFH0muvvdY43dRFF12Upk6dmj760Y/mEANA2+rSxusHoJ298cYbaa211kqrkq5du37gMv/73//Su+++m7p16/aByz777LPp+eefbwwkd999d1pnnXXSlltu+Z5lf/3rX6eNN944rbbaammbbbZZwXcAwPJSgwKwkqL5UzT9eeKJJ3JfiXXXXTdf7B5yyCG59mFJv/nNb9IOO+yQ1lhjjdSrV6900EEHpWeeeabZMnfeeWfaf//9U79+/dLqq6+e794fc8wx6c0332y2XGyvR48e6cknn0xf+tKX0tprr51GjhyZfxcX6+eee24aOHBg6t69e9pwww3ToYceml599dVm67j33nvTXnvtldZff/1cps022yyNGTMm/+6pp55KH/nIR/LPUYsS7zNe8Z6XJZpJxTJ33HFH3l7v3r1Tz54908EHH/yebUfNxNChQ1Pfvn3z+9x8883Taaedlt5555337YMS5Ypt/PSnP83vMf5d/PuHH354meV6++2308svv5xfM2bMyKEn9mtMR1m33Xbb9Morr+Tp2Hd1sUyEEwDahxoUgFZywAEH5Iv7CRMmpPvuuy/98pe/TBtssEE644wzGpcZP358Gjt2bF72W9/6VnrppZfSBRdckHbdddd0//3353ATfve73+Vwc/jhh+cL/GiOFMvFnf/43ZI1BxEwBg8enC/Y11xzzTw/wkGEhQhKRx11VJo9e3a68MIL83b++te/5gv0uXPnpj333DOHkBNPPDFvPy7+r7322ryOmB9NnKIc0Wdj+PDheX5czH+QI488Mq8vwkw0z4r1zJkzJzcVi3ARonwRsI499tj896233ppOOumktGDBgnTWWWd94DYmTpyY3nrrrfTtb387B5QIfMsyefLkvC+aipqRpuphLPaVTvkAFakBsFLGjRtXi6/TMWPGNJs/bNiwWu/evRunn3rqqVrnzp1r48ePb7bcgw8+WOvSpUuz+QsXLnzPdiZMmFDr1KlTbc6cOY3zRo8enbd94oknNlv2zjvvzPMnTZrUbP5NN93UbP6UKVPy9KxZs5b5/l566aW8TLzP5TFx4sS8/A477FBbtGhR4/wzzzwzz586der7vs9DDz20tuaaa9beeuutZu+zf//+jdOzZ8/O6+rZs2dt7ty5y1Wu559/vjZ9+vT8inUdfPDB+efJkyfndZ1//vmNv3/zzTeXuo6BAwfWhgwZslzbA2DFqLMGaCWHHXZYs+n/+7//y02GojYgRK1ENB2K2pN6U6N49enTJ48QFc2O6qKpVdM+JbHczjvvnEebihqQJUUNR1NRyxLNzL7whS8021Y0LYuaivq26jU2N9xwQ1q8eHGr7o+o1WjadyTK2KVLl/THP/5xqe/z9ddfz2WM/Ra1R//+978/cBtf/epXG2s9PshGG22U9thjj7TjjjvmJnXRFC6mo0zRBC7KG9PximkAqqGJF0Arif4iTdVHfIp+F9EH4/HHH88BI8LI0jS9mH/66adzU6frr7/+Pf025s+f32w6LrA32WSTZvNiW7FcNDFbmmjaFYYMGZIv8qN/yTnnnJOH0N13333T1772tdxkamUs+T4jGEVIiCZkdf/617/Sj370o9y0qx7klvU+lyaa1C2PCF/19d188825T8lWW22VA1FMb7/99jkgxSuC3fJ0ygegbQgoAK2kc+fOS50foSRE7Un0vbjxxhuXumxcwIfoIB41H/PmzUsnnHBCvpCOUbmee+653Fm8aQfuEEFiyU7csUyEk0mTJi21TPVahyjP73//+zRz5sw0bdq0fLEeHeTPPvvsPK9eprYQw/pGQIrwduqpp+aO7lFz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UAAAgGIIKAAAQDEEFAAAoBgCCgAAUAwBBQAAKIaAAgAAFENAAQAAiiGgAAAAxRBQAACAYggoAABAMQQUAACgGAIKAABQDAEFAAAohoACAAAUQ0ABAACKIaAAAADFEFAAAIBiCCgAAEAxBBQAAKAYAgoAAPDhDihvv/12Ovnkk/PfVMMxqJ5jUD3HoHqOQfUcg+o5BtVzDFat/d+pVqvVWvqPFixYkNZZZ500f/781LNnz1YpCC3jGFTPMaieY1A9x6B6jkH1HIPqOQar1v7XxAsAACiGgAIAABRDQAEAAD7cAWX11VdP48aNy39TDcegeo5B9RyD6jkG1XMMqucYVM8xWLX2/wp1kgcAAGgLmngBAADFEFAAAIBiCCgAAEAxBBQAAODDHVB+/vOfp0033TR17949feYzn0n33HNP65eMpZowYUL69Kc/ndZee+20wQYbpH333Tc9+uijVRerw/rJT36SOnXqlL773e9WXZQO57nnnkujRo1KvXv3TmussUb65Cc/me69996qi9UhvPPOO2ns2LFps802y/t+8803T6eddloy5krbuuOOO9KXv/zl1Ldv3/y9c9111zX7fez/k046KW200Ub5uOyxxx7p8ccfr6y8HWn/L168OJ1wwgn5e2ittdbKyxx88MHp+eefr7TMHe0z0NRhhx2Wlzn33HPbtYyrujuW4xg88sgjaZ999slPlo/PQ1y3Pv30020bUK6++up07LHH5qHE7rvvvjRo0KC01157pblz57Z0VayA22+/PR1xxBFp5syZafr06flLcc8990xvvPFG1UXrcGbNmpUuueSStO2221ZdlA7n1VdfTbvsskvq2rVruvHGG9PDDz+czj777LTeeutVXbQO4YwzzkgXXXRRuvDCC/OJKKbPPPPMdMEFF1RdtFVafM/HOTduEi5NHIPzzz8/XXzxxelvf/tbvjCI8/Nbb73V7mXtaPt/4cKF+Zoognv8fe211+abh3GRRvt9BuqmTJmSr5PiIpr2PQZPPvlkGjx4cNpqq63Sbbfdlv75z3/mz0VUarRIrYV22mmn2hFHHNE4/c4779T69u1bmzBhQktXRSuYO3du3LKs3X777VUXpUN5/fXXawMGDKhNnz69NmTIkNrRRx9ddZE6lBNOOKE2ePDgqovRYQ0dOrQ2ZsyYZvOGDx9eGzlyZGVl6mjie3/KlCmN0++++26tT58+tbPOOqtx3muvvVZbffXVa5MnT66olB1n/y/NPffck5ebM2dOu5WrI1nWMXj22WdrG2+8ce2hhx6q9e/fv3bOOedUUr6OegwOPPDA2qhRo1Z63S2qQVm0aFH6+9//nquN61ZbbbU8fffdd7csGdEq5s+fn//u1atX1UXpUKIWa+jQoc0+C7Sf66+/Pu24445p//33z00dt99++3TZZZdVXawOY+edd05//vOf02OPPZan//GPf6S//OUvae+99666aB3W7Nmz0wsvvNDsOymaV0QzbOfn6s7P0QRm3XXXrbooHca7776bvv71r6fjjz8+DRw4sOridMj9/4c//CFtscUWufY2zs/xHfR+TfGWpUUB5eWXX85tjzfccMNm82M6vhhp//8I0fchmrpss802VRenw7jqqqtyFX70B6Ia//nPf3ITowEDBqSbb745HX744emoo45KV1xxRdVF6xBOPPHEdNBBB+Uq/GhmFwExvotGjhxZddE6rPo52Pm5DNGsLvqkjBgxIvXs2bPq4nQY0dy0S5cu+XxA+4vuHg0NDbl/7he/+MX0pz/9KQ0bNiwNHz48d1FoiS5tVkra5S7+Qw89lO9c0j6eeeaZdPTRR+f+Py1uT0mrhvOoQfnxj3+cp+MCOT4L0fZ+9OjRVRdvlffb3/42TZo0KV155ZX5LuUDDzyQA0q097b/6eiib+gBBxyQBy2IGym0j2jhc9555+UbiFFzRTXn5vCVr3wlHXPMMfnn7bbbLt111135/DxkyJC2qUFZf/31U+fOndOLL77YbH5M9+nTpyWrYiUdeeSR6YYbbkgzZsxIm2yySdXF6VBfgHGH4FOf+lS+SxOvuCsQHVPj56hhpO3FKEVbb711s3mf+MQnWjxKCCsmmk/Ua1Fi1KJoUhEnI7WK1amfg52fywgnc+bMyTey1J60nzvvvDOfn/v169d4fo7jcNxxx+WRZ2l7kRNiv7fG+blFAaVbt25phx12yG2Pm6almP7c5z7Xog2zYuKOTISTGKHi1ltvzcN80n5233339OCDD+Y7xvVX3MmPpi3xcwR42l40a1xyeO3oD9G/f//KytSRxIhF0f+wqfi/X797RvuLc0EEkabn5wULFuTRvJyf2zecxNDOt9xySx4CnfYTN0pixKim5+eo1Y0bKtEUmLYXOSGGFG6N83OLm3jFEMNRhR8XZTvttFMeXzqGHDvkkENauipWsFlXNKuYOnVqfhZKvW1xdIaMce9pW7HPl+zvE0N5xolIP6D2E3fro6N2NPGKC4J4FtOll16aX7S9GAN//Pjx+U5lNPG6//77089+9rM0ZsyYqou2Sou23U888USzjvFxERaDpMSxiGZ2p59+eu6bFYElhvaMC7R4XhZtu/+jVne//fbLzYuidUPUptfPz/H7uHCj7T8DS4bC6CMXwX3LLbesoLQd8xgcf/zx6cADD0y77rpr2m233dJNN92Upk2bloccbpEVGfrrggsuqPXr16/WrVu3POzwzJkzV3o4MZZPHLKlvSZOnFh10ToswwxXY9q0abVtttkmD6O61VZb1S699NKqi9RhLFiwIP+fj/NA9+7dax/72MdqP/zhD2tvv/121UVbpc2YMWOp3/+jR49uHGp47NixtQ033DB/Lnbffffao48+WnWxO8T+nz179jLPz/HvaJ/PwJIMM1zNMfjVr35V+/jHP57PD4MGDapdd911Ld5Op/ij9fMVAABAy7X4SfIAAABtRUABAACKIaAAAADFEFAAAIBiCCgAAEAxBBQAAKAYAgoAAFAMAQUAACiGgAIAABRDQAEAAIohoAAAAMUQUAAAgFSK/wf6+B9vMqhECAAAAABJRU5ErkJggg==" + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "
" + ], + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAygAAADTCAYAAABqSTe2AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8ekN5oAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAXCUlEQVR4nO3dCbRd4/0/4DdkQgSJEqGJoSFFDY1qa0otStWqilkNqbSrKDVWpVViSmOomZraFdoS2hJTi0bF0JKiaKPUGDGVICSuKWmc//q+v//Jyo2E3OTeu1/3PM9ax7373J2z37O3c/b72e+wO9VqtVoCAAAowGJVFwAAAKBOQAEAAIohoAAAAMUQUAAAgGIIKAAAQDEEFAAAoBgCCgAAUAwBBQAAKIaAAgAAFENAAaB43/72t9Oqq65adTEAaAcCCgAf6Z133knHH398uuOOO1JHMmTIkLTnnnvm32u1WlpuueXSZZdd1myd119/PZ1++ulpiy22SJ/61KfSsssum770pS+lq6++uqJSA3R8AgoAHxtQTjjhhEoDyqWXXpoef/zxVn3N++67L4eN8Nhjj6U333xz9nLdvffem4455pjUq1ev9NOf/jSNHDkyLbnkkmmPPfZII0aMaNXyAPB/Ov//nwB0EG+//XZaaqmlUkfSpUuXj13nf//7X/rggw9S165dP3bdF154Ib300kuzA0kEkWWWWSattdZazdZbZ5110pNPPpn69+8/+7nvf//7aeutt06nnnpq+tGPftTh9jVA1bSgACyi6P7UqVOn9NRTT+WxEtENKCq7++23X259mNtvf/vbNGjQoLTEEkvkK/NxNf75559vts7dd9+ddt1119SvX7/UrVu39OlPfzodfvjh6d133222XmyvR48e6emnn05f//rX09JLL5322muv/LeorJ999tm5kt29e/e04oorpv333z+98cYbzV7jgQceSNtuu21afvnlc5lWW221NGzYsPy3Z599NndtCtGKEu8zHvGe5ye6ScU6d911V95e7969U8+ePdO+++77oW1ff/31afvtt099+/bN73ONNdZIJ510Upo1a9ZHjkGJcsU2fv7zn+f3GP8u/v2jjz4633K9//776bXXXsuP8ePH59AT+zWWo6zrrbde7tIVy7HvQuyLOcNJiO3uuOOO+fWeeeaZ+W4PgIWjBQWgley22265Qjtq1Kj04IMPpl/+8pdphRVWyFfa66KL0LHHHpvX/e53v5teffXVdN555+UxDg899FAON+H3v/99DjcHHnhgruBHd6RYL678x9/mbjmIgLHZZpvlCnt0QQoRDiIsRFA65JBD0qRJk9L555+ft/O3v/0tV9CnTJmSttlmmxxChg8fnrcflf9rr702v0Y8f+GFF+ZyxJiNnXbaKT8flfmPc/DBB+fXizAT3bPidSZPnpy7ikUlP0T5ImAdccQR+eftt9+ejjvuuDR9+vQ89uPjjB49Or333nvpe9/7Xg4oEfjmZ8yYMXlfzGnllVdutlwPY7GvPmpQ/ssvv5x/RqgDoJXVAFgkI0aMqMXX6bBhw5o9P2TIkFrv3r1nLz/77LO1xRdfvDZy5Mhm602cOLHWuXPnZs+/8847H9rOqFGjap06dapNnjx59nNDhw7N2x4+fHizde++++78/BVXXNHs+VtuuaXZ82PHjs3L999//3zf36uvvprXife5IEaPHp3XHzRoUG3GjBmznz/ttNPy89dff/1Hvs/999+/tuSSS9bee++9Zu+zf//+s5cnTZqUX6tnz561KVOmLFC5Xnrppdq4cePyI15r3333zb+PGTMmv9a55547++/vvvvufF/n9ddfr62wwgq1zTfffIG2C0DL6OIF0EoOOOCAZsubb7557jIUrQEhWiWi61C0ntS7GsWjT58+acCAAbnbUV10tZpzTEmst8kmm+TZpqIFZG7RwjGnaGWJbmZf/epXm20rupZFS0V9W/UWm5tuuinNnDmzVfdHtGrMOXYkyti5c+f0pz/9aZ7v86233spljP0WrUf/+c9/PnYbO++88+xWj4+z0kor5bEjG220Ue5SF13hYjnKFF3goryxHI9Ynpc4fvHvYkB9tGgB0Pp08QJoJTFeZE4xbW2IcRcxBiMGW0fAiDAyL3NW5p977rnc1emGG2740LiNadOmNVuOCvYqq6zS7LnYVqwXXczmJbp2hcGDB+dKfowvOeuss9JXvvKVPL7iW9/6Vu4ytSjmfp8RjCIkRBeyun//+995dqzo2lUPcvN7n/MSXeoWRISv+uvdeuutabHFFksDBw7MgSiWN9xwwxyQ4hHBbn6D8n/wgx+kW265Jf36179O66+//gJtG4CWEVAAWsniiy8+z+cjlNSvvsfYi5tvvnme60YFPsQA8Wj5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AMUQUAAAgGIIKAAAQDEEFAAAoBgCCgAAUAwBBQAAKIaAAgAAFENAAQAAiiGgAAAAxRBQAACAYggoAABAMQQUAACgGAIKAABQDAEFAAAohoACAAAUQ0ABAACKIaAAAADFEFAAAIBiCCgAAEAxBBQAAKAYAgoAAFAMAQUAACiGgAIAABRDQAEAAIohoAAAAMUQUAAAgGIIKAAAQDEEFAAAoBgCCgAAUAwBBQAAKIaAAgAAFENAAQAAiiGgAAAAxRBQAACAYggoAABAMQQUAACgGAIKAABQDAEFAAAohoACAAAUQ0ABAACKIaAAAADFEFAAAIBiCCgAAEAxBBQAAOCTHVDef//9dPzxx+efVMMxqJ5jUD3HoHqOQfUcg+o5BtVzDDrW/u9Uq9VqLf1H06dPT8sss0yaNm1a6tmzZ6sUhJZxDKrnGFTPMaieY1A9x6B6jkH1HIOOtf918QIAAIohoAAAAMUQUAAAgE92QOnWrVsaMWJE/kk1HIPqOQbVcwyq5xhUzzGonmNQPcegY+3/hRokDwAA0BZ08QIAAIohoAAAAMUQUAAAgGIIKAAAwCc7oFxwwQVp1VVXTd27d09f/OIX03333df6JWOeRo0alb7whS+kpZdeOq2wwgppxx13TI8//njVxWpYp5xySurUqVM67LDDqi5Kw3nxxRfT3nvvnXr37p2WWGKJ9LnPfS498MADVRerIcyaNSsde+yxabXVVsv7fo011kgnnXRSMudK27rrrrvSN77xjdS3b9/8vXPdddc1+3vs/+OOOy6ttNJK+bhsvfXW6cknn6ysvI20/2fOnJmOPvro/D201FJL5XX23Xff9NJLL1Va5kb7DMzpgAMOyOucffbZ7VrGju6uBTgGjz32WNphhx3yneXj8xD11ueee65tA8rVV1+djjjiiDyV2IMPPpjWX3/9tO2226YpU6a09KVYCHfeeWc66KCD0oQJE9K4cePyl+I222yT3n777aqL1nDuv//+dPHFF6f11luv6qI0nDfeeCNtuummqUuXLunmm29Ojz76aDrjjDPScsstV3XRGsKpp56aLrzwwnT++efnE1Esn3baaem8886rumgdWnzPxzk3LhLOSxyDc889N1100UXp73//e64YxPn5vffea/eyNtr+f+edd3KdKIJ7/Lz22mvzxcOopNF+n4G6sWPH5npSVKJp32Pw9NNPp8022ywNHDgw3XHHHelf//pX/lxEo0aL1Fpo4403rh100EGzl2fNmlXr27dvbdSoUS19KVrBlClT4pJl7c4776y6KA3lrbfeqg0YMKA2bty42uDBg2uHHnpo1UVqKEcffXRts802q7oYDWv77bevDRs2rNlzO+20U22vvfaqrEyNJr73x44dO3v5gw8+qPXp06d2+umnz37uzTffrHXr1q02ZsyYikrZOPt/Xu6777683uTJk9utXI1kfsfghRdeqK288sq1Rx55pNa/f//aWWedVUn5GvUY7L777rW99957kV+7RS0oM2bMSP/4xz9ys3HdYostlpfvvffeliUjWsW0adPyz169elVdlIYSrVjbb799s88C7eeGG25IG220Udp1111zV8cNN9wwXXrppVUXq2Fssskm6S9/+Ut64okn8vI///nP9Ne//jVtt912VRetYU2aNCm9/PLLzb6TontFdMN2fq7u/BxdYJZddtmqi9IwPvjgg7TPPvuko446Kq2zzjpVF6ch9/8f//jHtOaaa+bW2zg/x3fQR3XFm58WBZTXXnst9z1eccUVmz0fy/HFSPv/jxBjH6Kry7rrrlt1cRrGVVddlZvwYzwQ1XjmmWdyF6MBAwakW2+9NR144IHpkEMOSZdffnnVRWsIw4cPT3vssUduwo9udhEQ47tor732qrpoDat+DnZ+LkN0q4sxKXvuuWfq2bNn1cVpGNHdtHPnzvl8QPuL4R5NTU15fO7Xvva19Oc//zkNGTIk7bTTTnmIQkt0brNS0i5X8R955JF85ZL28fzzz6dDDz00j/9pcX9KWjWcRwvKz372s7wcFeT4LETf+6FDh1ZdvA7vd7/7XbriiivSlVdema9SPvzwwzmgRH9v+59GF2NDd9tttzxpQVxIoX1ED59zzjknX0CMliuqOTeHb37zm+nwww/Pv2+wwQbpnnvuyefnwYMHt00LyvLLL58WX3zx9MorrzR7Ppb79OnTkpdiER188MHppptuSuPHj0+rrLJK1cVpqC/AuELw+c9/Pl+liUdcFYiBqfF7tDDS9mKWorXXXrvZc5/97GdbPEsICye6T9RbUWLWouhSEScjrYrVqZ+DnZ/LCCeTJ0/OF7K0nrSfu+++O5+f+/XrN/v8HMfhyCOPzDPP0vYiJ8R+b43zc4sCSteuXdOgQYNy3+M501Isf/nLX27Rhlk4cUUmwknMUHH77bfnaT5pP1tttVWaOHFivmJcf8SV/OjaEr9HgKftRbfGuafXjvEQ/fv3r6xMjSRmLIrxh3OK//frV89of3EuiCAy5/l5+vTpeTYv5+f2DScxtfNtt92Wp0Cn/cSFkpgxas7zc7TqxgWV6ApM24ucEFMKt8b5ucVdvGKK4WjCj0rZxhtvnOeXjinH9ttvv5a+FAvZrSu6VVx//fX5Xij1vsUxGDLmvadtxT6fe7xPTOUZJyLjgNpPXK2PgdrRxSsqBHEvpksuuSQ/aHsxB/7IkSPzlcro4vXQQw+lM888Mw0bNqzqonVo0bf7qaeeajYwPiphMUlKHIvoZnfyySfnsVkRWGJqz6igxf2yaNv9H626u+yyS+5eFL0bojW9fn6Ov0fFjbb/DMwdCmOMXAT3tdZaq4LSNuYxOOqoo9Luu++etthii7TlllumW265Jd144415yuEWWZipv84777xav379al27ds3TDk+YMGGRpxNjwcQhm9dj9OjRVRetYZlmuBo33nhjbd11183TqA4cOLB2ySWXVF2khjF9+vT8/3ycB7p3715bffXVa8ccc0zt/fffr7poHdr48ePn+f0/dOjQ2VMNH3vssbUVV1wxfy622mqr2uOPP151sRti/0+aNGm+5+f4d7TPZ2Buphmu5hj86le/qn3mM5/J54f111+/dt1117V4O53iP62frwAAAFquxXeSBwAAaCsCCgAAUAwBBQAAKIaAAgAAFENAAQAAiiGgAAAAxRBQAACAYggoAABAMQQUAACgGAIKAABQDAEFAAAohoACAACkUvw/PStWp8dTGfAAAAAASUVORK5CYII=" + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "
" + ], + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAygAAADTCAYAAABqSTe2AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8ekN5oAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAXCElEQVR4nO3dCbRVVf0H8I0CTogKJogGmqmoOJuV8pdcmGaunHIiEJJaqUvT1EwbECfCIXMsp1rqKqdKwaHUMFExJTG1NM0pxClFRcXnBOn9r99e67J4DMKT997Zj/v5rHV579x33j37nsO7Z3/PHk6nWq1WSwAAAAVYpuoCAAAA1AkoAABAMQQUAACgGAIKAABQDAEFAAAohoACAAAUQ0ABAACKIaAAAADFEFAAAIBiCCgAFO+b3/xmWmeddaouBgDtQEAB4GO9++676cQTT0x33nlnWprstddeaciQIfn7Wq2WVltttXT55ZfPt95RRx2Vttpqq9SjR4+04oorpo022ijvj6ampgpKDbD061x1AQAoP6CcdNJJ+fsvfelLlZTh0ksvTR999FGrvub999+ffvCDH+TvH3/88fTmm2+mL3zhC/OtN2XKlPR///d/6aCDDkrLL798euihh9Jpp52Wbr/99nT33XenZZZxrQ+gNQkoAEuZd955J6200kppadKlS5dFrvO///0vh5iuXbsuct0XXnghvfTSS3MCyX333ZdWWWWVtOGGG8637j333DPfc+utt176/ve/n0POgkINAJ+cyz4ASyi6+3Tq1Ck9/fTTeazEqquumiu7ccU9Wh/m9dvf/jZtvfXWaYUVVsjdhg444ID0/PPPN1tn0qRJad999019+/ZNyy23XPr0pz+duxq99957zdaL7XXr1i0988wz6atf/WpaeeWV09ChQ/PPorJ+zjnnpE022SRf+e/Vq1c6+OCD0xtvvNHsNR544IG0yy67pNVXXz2Xad11100jR47MP3v22WfTpz71qfx9tKLE+4xHvOeFiW5SsU60LsT2evbsmbp3756GDx8+37ZvuOGGtNtuu6U+ffrk9xkV/1NOOSV9+OGHHzsGJcoV2/jZz36W32P8Xvz+Y489ttByffDBB+m1117Lj4kTJ+bQE/s1lqOsm222WXr99dfz8qJaa+pliVYXAFqXFhSAVrLffvvlyv3YsWPTgw8+mH71q1+lNdZYI51++ulz1hkzZkwaNWpUXvfb3/52evXVV9P555+fdthhh9x1KMJN+P3vf5/DzaGHHpor+HGlPtaLK//xs3lbDiJgDBw4MFfYY5xEiHAQYSGC0hFHHJGmTp2aLrjggrydv/71r7mCPn369LTzzjvnEHL88cfn7Ufl//rrr8+vEc9feOGFuRwxZmPvvffOz0dlflEOP/zw/HoRZp544on8OtOmTctjWSJchChfBKyjjz46f73jjjvSCSeckGbOnJnOPPPMRW7jsssuS++//376zne+kwNKBL6Fufrqq/O+mNtaa63VbLkexmJfzR2IYh9HGJk1a1Z69NFH009+8pMcBrfddttFlhGAFqoBsERGjx5di4/TkSNHNnt+r732qvXs2XPO8rPPPltbdtlla2PGjGm23iOPPFLr3Llzs+fffffd+bYzduzYWqdOnWrTpk2b89yIESPyto8//vhm606aNCk/f+WVVzZ7/tZbb232/Lhx4/LylClTFvr+Xn311bxOvM/Fcdlll+X1t95669qsWbPmPH/GGWfk52+44YaPfZ8HH3xwbcUVV6y9//77zd5nv3795ixPnTo1v1b37t1r06dPX6xyvfTSS7UJEybkR7zW8OHD8/dXX311fq3zzjtvzs/fe++9Zr9733335XXqjw033LA2ceLExdouAC2jixdAKznkkEOaLcfA6ugyFK0BIVoloutQtJ7UuxrFo3fv3mn99dfP3Y7qoqvV3GNKYr3tttsuzzYVLSDzihaOuUUrS3Qz+/KXv9xsW9G1LFoq6tuqt9jcfPPNafbs2a26P6JVY+6xI1HGzp07pz/96U8LfJ9vv/12LmPst2g9+ve//73IbXz961+f0+qxKGuuuWbaaaed0jbbbJO71EVXuFiOMkUXuChvLMcjlue28cYbpwkTJqTx48fngfUxxscsXgBtQxcvgFYS40XmFtPWhhh3EWMwnnrqqRwwIowsyNyV+eeeey53dbrxxhvnG7fx1ltvNVuOCvbaa6/d7LnYVqwXXcwWJLp2hUGDBuVKfowvOfvss/MsXXvuuWf6xje+kbtMLYl532cEowgJ0YWs7l//+lfuLhVdu+pBbmHvc0GiS93iiPBVf73bbrstz7zVv3//HIhiecstt8wBKR4R7OYdlB/HL4JL2GOPPdJVV12Vv0ZXvs0333yxygDA4hFQAFrJ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YggoAABAMQQUAACgGAIKAABQDAEFAAAohoACAAAUQ0ABAACKIaAAAADFEFAAAIBiCCgAAEAxBBQAAKAYAgoAAFAMAQUAACiGgAIAABRDQAEAAIohoAAAAMUQUAAAgGIIKAAAQDEEFAAAoBgCCgAAUAwBBQAAKIaAAgAAFENAAQAAiiGgAAAAxRBQAACAYggoAABAMQQUAACgGAIKAABQDAEFAAAohoACAAAUQ0ABAACKIaAAAADFEFAAAIBiCCgAAEAxBBQAAKAYAgoAAFAMAQUAACiGgAIAABRDQAEAAIohoAAAAMUQUAAAgGIIKAAAQDEEFAAAoBgCCgAA0LEDygcffJBOPPHE/JVqOAbVcwyq5xhUzzGonmNQPcegeo7B0rX/O9VqtVpLf2nmzJlplVVWSW+99Vbq3r17qxSElnEMqucYVM8xqJ5jUD3HoHqOQfUcg6Vr/+viBQAAFENAAQAAiiGgAAAAHTugLLfccmn06NH5K9VwDKrnGFTPMaieY1A9x6B6jkH1HIOla/9/okHyAAAAbUEXLwAAoBgCCgAAUAwBBQAAKIaAAgAAdOyA8otf/CKts846afnll0+f//zn0/3339/6JWOBxo4dmz73uc+llVdeOa2xxhppzz33TE888UTVxWpYp512WurUqVP63ve+V3VRGs6LL76Yhg0blnr27JlWWGGFtOmmm6YHHnig6mI1hA8//DCNGjUqrbvuunnfr7feeumUU05J5lxpW3fffXf62te+lvr06ZM/d8aPH9/s57H/TzjhhLTmmmvm47LTTjulp556qrLyNtL+nz17djruuOPy59BKK62U1xk+fHh66aWXKi1zo/0NzO2QQw7J65xzzjntWsal3d2LcQwef/zxtPvuu+c7y8ffQ9Rbn3vuubYNKNdee206+uij81RiDz74YNp8883TLrvskqZPn97Sl+ITuOuuu9Jhhx2WJk+enCZMmJA/FHfeeef0zjvvVF20hjNlypR08cUXp80226zqojScN954I22//fapS5cu6ZZbbkmPPfZYOuuss9Jqq61WddEawumnn54uvPDCdMEFF+QTUSyfccYZ6fzzz6+6aEu1+JyPc25cJFyQOAbnnXdeuuiii9Lf/va3XDGI8/P777/f7mVttP3/7rvv5jpRBPf4ev311+eLh1FJo/3+BurGjRuX60lRiaZ9j8EzzzyTBg4cmPr375/uvPPO9M9//jP/XUSjRovUWmjbbbetHXbYYXOWP/zww1qfPn1qY8eObelL0QqmT58elyxrd911V9VFaShvv/12bf31169NmDChNmjQoNqRRx5ZdZEaynHHHVcbOHBg1cVoWLvttltt5MiRzZ7be++9a0OHDq2sTI0mPvfHjRs3Z/mjjz6q9e7du3bmmWfOee7NN9+sLbfccrWrr766olI2zv5fkPvvvz+vN23atHYrVyNZ2DF44YUXamuttVbt0UcfrfXr16929tlnV1K+Rj0G+++/f23YsGFL/NotakGZNWtW+vvf/56bjeuWWWaZvHzfffe1LBnRKt566638tUePHlUXpaFEK9Zuu+3W7G+B9nPjjTembbbZJu277765q+OWW26ZLr300qqL1TC222679Je//CU9+eSTefkf//hHuueee9Kuu+5addEa1tSpU9PLL7/c7DMpuldEN2zn5+rOz9EFZtVVV626KA3jo48+SgceeGA69thj0yabbFJ1cRpy///xj39MG2ywQW69jfNzfAZ9XFe8hWlRQHnttddy3+NevXo1ez6W44OR9v+PEGMfoqvLgAEDqi5Ow7jmmmtyE36MB6Ia//nPf3IXo/XXXz/ddttt6dBDD01HHHFEuuKKK6ouWkM4/vjj0wEHHJCb8KObXQTE+CwaOnRo1UVrWPVzsPNzGaJbXYxJGTJkSOrevXvVxWkY0d20c+fO+XxA+4vhHk1NTXl87le+8pX05z//Oe21115p7733zkMUWqJzm5WSdrmK/+ijj+Yrl7SP559/Ph155JF5/E+L+1PSquE8WlB++tOf5uWoIMffQvS9HzFiRNXFW+r97ne/S1deeWW66qqr8lXKhx9+OAeU6O9t/9PoYmzofvvtlyctiAsptI/o4XPuuefmC4jRckU15+awxx57pKOOOip/v8UWW6R77703n58HDRrUNi0oq6++elp22WXTK6+80uz5WO7du3dLXooldPjhh6ebb745TZw4Ma299tpVF6ehPgDjCsFWW22Vr9LEI64KxMDU+D5aGGl7MUvRxhtv3Oy5jTbaqMWzhPDJRPeJeitKzFoUXSriZKRVsTr1c7DzcxnhZNq0aflCltaT9jNp0qR8fu7bt++c83Mch2OOOSbPPEvbi5wQ+701zs8tCihdu3ZNW2+9de57PHdaiuUvfvGLLdown0xckYlwEjNU3HHHHXmaT9rP4MGD0yOPPJKvGNcfcSU/urbE9xHgaXvRrXHe6bVjPES/fv0qK1MjiRmLYvzh3OL/fv3qGe0vzgURROY+P8+cOTPP5uX83L7hJKZ2vv322/MU6LSfuFASM0bNfX6OVt24oBJdgWl7kRNiSuHWOD+3uItXTDEcTfhRKdt2223z/NIx5dhBBx3U0pfiE3brim4VN9xwQ74XSr1vcQyGjHnvaVuxz+cd7xNTecaJyDig9hNX62OgdnTxigpB3IvpkksuyQ/aXsyBP2bMmHylMrp4PfTQQ+nnP/95GjlyZNVFW6pF3+6nn3662cD4qITFJClxLKKb3amnnprHZkVgiak9o4IW98uibfd/tOrus88+uXtR9G6I1vT6+Tl+HhU32v5vYN5QGGPkIrhvuOGGFZS2MY/Bsccem/bff/+0ww47pB133DHdeuut6aabbspTDrfIJ5n66/zzz6/17du31rVr1zzt8OTJk5d4OjEWTxyyBT0uu+yyqovWsEwzXI2bbrqpNmDAgDyNav/+/WuXXHJJ1UVqGDNnzsz/5+M8sPzyy9c+85nP1H784x/XPvjgg6qLtlSbOHHiAj//R4wYMWeq4VGjRtV69eqV/y4GDx5ce+KJJ6oudkPs/6lTpy70/By/R/v8DczLNMPVHINf//rXtc9+9rP5/LD55pvXxo8f3+LtdIp/Wj9fAQAAtFyL7yQPAADQVgQUAACgGAIKAABQDAEFAAAohoACAAAUQ0ABAACKIaAAAADFEFAAAIBiCCgAAEAxBBQAAKAYAgoAAFAMAQUAAEil+H91/GLN46PRBQAAAABJRU5ErkJggg==" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "execution_count": 8 } ], "metadata": { "kernelspec": { - "display_name": "3.12.9", + "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", - "version": 3 + "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.9" + "pygments_lexer": "ipython2", + "version": "2.7.6" } }, "nbformat": 4, diff --git a/polars_bio/quality_stats.py b/polars_bio/quality_stats.py index c18ec841..d19daec9 100644 --- a/polars_bio/quality_stats.py +++ b/polars_bio/quality_stats.py @@ -1,5 +1,6 @@ from pathlib import Path from typing import Union +import datafusion import polars as pl import pandas as pd import pyarrow as pa @@ -10,19 +11,42 @@ ) -def base_sequence_quality(df: Union[str, pl.DataFrame, pl.LazyFrame, pd.DataFrame]): +def base_sequence_quality( + df: Union[str, pl.DataFrame, pl.LazyFrame, pd.DataFrame], + quality_scores_column: str = "quality_scores", + output_type: str = "polars.DataFrame", +) -> Union[pl.DataFrame, pd.DataFrame]: + """ + Compute base sequence quality statistics from various dataframe/file types. + + Args: + df: Input data as a file path or dataframe. + quality_scores_column: Name of the column with quality scores. + output_type: Output type, either "polars.DataFrame" or "pandas.DataFrame". + + Returns: + DataFrame with base sequence quality statistics. + """ if isinstance(df, str): - supported_exts = set([".parquet", ".csv", ".bed", ".vcf", ".fastq"]) + supported_exts = {".parquet", ".csv", ".bed", ".vcf", ".fastq"} ext = set(Path(df).suffixes) - assert ( - len(supported_exts.intersection(ext)) > 0 or len(ext) == 0 - ), "Dataframe1 must be a Parquet, CSV, BED, VCF, or FASTQ file." - return base_sequance_quality_scan(ctx, df) + if not (supported_exts & ext or not ext): + raise ValueError("Input file must be a Parquet, CSV, BED, VCF, or FASTQ file.") + result: datafusion.DataFrame = base_sequance_quality_scan(ctx, df, quality_scores_column) else: - if isinstance(df, pl.DataFrame): - df = df.to_arrow().to_reader() + if isinstance(df, pl.LazyFrame): + arrow_table = df.collect().to_arrow() + elif isinstance(df, pl.DataFrame): + arrow_table = df.to_arrow() elif isinstance(df, pd.DataFrame): - df = pa.Table.from_pandas(df) - elif isinstance(df, pl.LazyFrame): - df = df.collect().to_arrow().to_reader() - return base_sequance_quality_frame(ctx, df) + arrow_table = pa.Table.from_pandas(df) + else: + raise TypeError("Unsupported dataframe type.") + result: datafusion.DataFrame = base_sequance_quality_frame(ctx, arrow_table, quality_scores_column) + + if output_type == "polars.DataFrame": + return result.to_polars() + elif output_type == "pandas.DataFrame": + return result.to_pandas() + else: + raise ValueError("output_type must be 'polars.DataFrame' or 'pandas.DataFrame'") diff --git a/src/base_sequence_quality.rs b/src/base_sequence_quality.rs new file mode 100644 index 00000000..1ca4d1e4 --- /dev/null +++ b/src/base_sequence_quality.rs @@ -0,0 +1,247 @@ +use std::fmt::{Debug, Formatter}; +use std::sync::Arc; + +use arrow_array::{Array, StringArray}; +use async_trait::async_trait; +use datafusion::arrow::datatypes::{DataType, Field, Schema, SchemaRef}; +use datafusion::arrow::record_batch::RecordBatch; +use datafusion::catalog::{Session, TableProvider}; +use datafusion::error::{DataFusionError, Result}; +use datafusion::execution::context::TaskContext; +use datafusion::physical_expr::EquivalenceProperties; +use datafusion::physical_plan::repartition::RepartitionExec; +use datafusion::physical_plan::stream::RecordBatchStreamAdapter; +use datafusion::physical_plan::{ + DisplayAs, DisplayFormatType, ExecutionMode, ExecutionPlan, Partitioning, PlanProperties, + SendableRecordBatchStream, +}; +use datafusion::prelude::SessionContext; +use futures::stream::BoxStream; +use futures::{StreamExt, TryStreamExt}; + +pub struct BaseSequenceQualityProvider { + session: Arc, + table_name: String, + column_name: String, + schema: SchemaRef, +} + +impl BaseSequenceQualityProvider { + pub fn new(session: Arc, table_name: String, column_name: String) -> Self { + let schema = Arc::new(Schema::new(vec![ + Field::new("pos", DataType::Int64, false), + Field::new("score", DataType::Int8, false), + ])); + Self { + session, + table_name, + column_name, + schema, + } + } +} + +impl Debug for BaseSequenceQualityProvider { + fn fmt(&self, _f: &mut Formatter<'_>) -> std::fmt::Result { + Ok(()) + } +} + +#[async_trait] +impl TableProvider for BaseSequenceQualityProvider { + fn as_any(&self) -> &dyn std::any::Any { + self + } + + fn schema(&self) -> SchemaRef { + self.schema.clone() + } + + fn table_type(&self) -> datafusion::datasource::TableType { + datafusion::datasource::TableType::Base + } + + async fn scan( + &self, + _state: &dyn Session, + _projection: Option<&Vec>, + _filters: &[datafusion::prelude::Expr], + _limit: Option, + ) -> Result> { + let target_partitions = self.session.state().config().target_partitions(); + + Ok(Arc::new(BaseSequenceQualityExec { + schema: self.schema.clone(), + session: Arc::clone(&self.session), + table_name: self.table_name.clone(), + column_name: self.column_name.clone(), + cache: PlanProperties::new( + EquivalenceProperties::new(self.schema.clone()), + Partitioning::UnknownPartitioning(target_partitions), + ExecutionMode::Bounded, + ), + })) + } +} + +pub struct BaseSequenceQualityExec { + schema: SchemaRef, + session: Arc, + table_name: String, + column_name: String, + cache: PlanProperties, +} + +impl Debug for BaseSequenceQualityExec { + fn fmt(&self, _f: &mut Formatter<'_>) -> std::fmt::Result { + Ok(()) + } +} + +impl DisplayAs for BaseSequenceQualityExec { + fn fmt_as(&self, _t: DisplayFormatType, _f: &mut Formatter) -> std::fmt::Result { + Ok(()) + } +} + +impl ExecutionPlan for BaseSequenceQualityExec { + fn name(&self) -> &str { + "BaseSequenceQualityExec" + } + + fn as_any(&self) -> &dyn std::any::Any { + self + } + + fn schema(&self) -> SchemaRef { + self.schema.clone() + } + + fn properties(&self) -> &PlanProperties { + &self.cache + } + + fn children(&self) -> Vec<&Arc> { + vec![] + } + + fn with_new_children( + self: Arc, + _children: Vec>, + ) -> Result> { + Ok(self) + } + + fn execute( + &self, + partition: usize, + context: Arc, + ) -> Result { + let fut = get_stream( + Arc::clone(&self.session), + self.table_name.clone(), + self.column_name.clone(), + self.cache.partitioning.partition_count(), + partition, + context, + self.schema.clone(), + ); + let stream = futures::stream::once(fut).try_flatten(); + let schema = self.schema.clone(); + Ok(Box::pin(RecordBatchStreamAdapter::new(schema, stream))) + } +} + +fn decode_score(c: char) -> Option { + let ascii = c as u8; + if ascii >= 33 { + Some(ascii - 33) + } else { + None + } +} + +fn calc_stats(values: &mut Vec) -> (f64, f64, f64, f64, f64, f64) { + values.sort_unstable(); + let n = values.len(); + let average = values.iter().map(|&v| v as f64).sum::() / n as f64; + let median = if n % 2 == 0 { + (values[n / 2 - 1] as f64 + values[n / 2] as f64) / 2.0 + } else { + values[n / 2] as f64 + }; + let q1 = values[n / 4] as f64; + let q3 = values[(3 * n) / 4] as f64; + let iqr = q3 - q1; + let lower = q1 - 1.5 * iqr; + let upper = q3 + 1.5 * iqr; + (average, median, q1, q3, lower, upper) +} + +async fn get_stream( + session: Arc, + table_name: String, + column_name: String, + target_partitions: usize, + partition: usize, + context: Arc, + new_schema: SchemaRef, +) -> Result { + let table_stream = session.table(table_name).await?; + let plan = table_stream.create_physical_plan().await?; + let repartition_stream = + RepartitionExec::try_new(plan, Partitioning::RoundRobinBatch(target_partitions))?; + let partition_stream = repartition_stream.execute(partition, context)?; + let new_schema_out = new_schema.clone(); + let iter = partition_stream.map(move |batch| match batch { + Ok(batch) => { + let index = match batch.schema().index_of(&column_name) { + Ok(idx) => idx, + Err(_) => { + return Err(DataFusionError::Internal(format!( + "Column '{}' not found in schema", + column_name + ))) + }, + }; + let col = batch.column(index); + + // Try to cast to StringArray if possible + let col = arrow::compute::cast(col, &DataType::Utf8) + .map_err(|e| DataFusionError::Internal(format!("Cast error: {e}")))?; + + let col = col + .as_any() + .downcast_ref::() + .ok_or_else(|| DataFusionError::Internal("Expected StringArray".into()))?; + + let mut positions = Vec::new(); + let mut scores = Vec::new(); + + for row in 0..col.len() { + if col.is_null(row) { + continue; + } + let s = col.value(row); + for (pos, byte) in s.bytes().enumerate() { + if let Some(score) = decode_score(byte as char) { + positions.push(pos as i64); + scores.push(score as i8); + } + } + } + + let pos_array = Arc::new(arrow_array::Int64Array::from(positions)); + let score_array = Arc::new(arrow_array::Int8Array::from(scores)); + let new_batch = + RecordBatch::try_new(new_schema.clone(), vec![pos_array, score_array]).unwrap(); + + Ok(new_batch) + }, + Err(e) => Err(e), + }); + + let adapted_stream = + RecordBatchStreamAdapter::new(new_schema_out, Box::pin(iter) as BoxStream<_>); + Ok(Box::pin(adapted_stream)) +} diff --git a/src/context.rs b/src/context.rs index afc02d4e..1525ef05 100644 --- a/src/context.rs +++ b/src/context.rs @@ -1,9 +1,6 @@ use std::collections::HashMap; -use std::sync::Arc; -use datafusion::arrow::datatypes::DataType; use datafusion::config::ConfigOptions; -use datafusion::logical_expr::{create_udaf, AggregateUDF, Volatility}; use datafusion::prelude::SessionConfig; use exon::config::ExonConfigExtension; use exon::ExonSession; @@ -11,8 +8,6 @@ use log::debug; use pyo3::{pyclass, pymethods, PyResult}; use sequila_core::session_context::SequilaConfig; -use crate::udaf::{base_quality_result_type, QualityScoresStats}; - #[pyclass(name = "BioSessionContext")] // #[derive(Clone)] pub struct PyBioSessionContext { @@ -30,7 +25,6 @@ impl PyBioSessionContext { pub fn new(seed: String, catalog_dir: String) -> PyResult { let ctx = create_context().unwrap(); let session_config: HashMap = HashMap::new(); - ctx.session.register_udaf(make_base_sequence_quality_udaf()); Ok(PyBioSessionContext { ctx, session_config, @@ -92,14 +86,3 @@ fn create_context() -> exon::Result { ExonSession::with_config_exon(config) } - -pub fn make_base_sequence_quality_udaf() -> AggregateUDF { - create_udaf( - "base_sequence_quality", // nazwa funkcji w SQL - vec![DataType::Utf8], // typ wejściowy - Arc::new(base_quality_result_type()), - Volatility::Immutable, - Arc::new(|_| Ok(Box::new(QualityScoresStats::new()))), - Arc::new(vec![]), - ) -} diff --git a/src/lib.rs b/src/lib.rs index d92eb0c4..ac78e9b3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,17 +1,16 @@ +mod base_sequence_quality; mod context; mod operation; mod option; mod query; mod scan; mod streaming; -mod udaf; mod udtf; mod utils; use std::string::ToString; use std::sync::{Arc, Mutex}; -use arrow::array::*; use datafusion::arrow::ffi_stream::ArrowArrayStreamReader; use datafusion::arrow::pyarrow::PyArrowType; use datafusion::datasource::MemTable; @@ -23,8 +22,6 @@ use polars_lazy::prelude::{LazyFrame, ScanArgsAnonymous}; use polars_python::error::PyPolarsErr; use polars_python::lazyframe::PyLazyFrame; use pyo3::prelude::*; -use pyo3::types::{PyDict, PyList}; -use scan::deregister_table; use tokio::runtime::Runtime; use crate::context::PyBioSessionContext; @@ -409,128 +406,65 @@ fn py_from_polars( }) } -fn struct_array_to_pydict(py: Python<'_>, struct_array: &StructArray) -> PyResult { - let warn_array = struct_array - .column_by_name("base_quality_warn") - .and_then(|a| a.as_any().downcast_ref::()) - .unwrap(); - - let base_per_pos_array = struct_array - .column_by_name("base_per_pos_data") - .and_then(|a| a.as_any().downcast_ref::()) - .unwrap(); - - let struct_array = base_per_pos_array - .values() - .as_any() - .downcast_ref::() - .unwrap(); - - let mut base_per_pos_data = Vec::new(); - for i in 0..base_per_pos_array.value_length(0) { - let mut row = std::collections::HashMap::new(); - - let pos = struct_array - .column_by_name("pos") - .and_then(|a| a.as_any().downcast_ref::()) - .unwrap() - .value(i as usize); - let average = struct_array - .column_by_name("average") - .and_then(|a| a.as_any().downcast_ref::()) - .unwrap() - .value(i as usize); - let median = struct_array - .column_by_name("median") - .and_then(|a| a.as_any().downcast_ref::()) - .unwrap() - .value(i as usize); - let q1 = struct_array - .column_by_name("q1") - .and_then(|a| a.as_any().downcast_ref::()) - .unwrap() - .value(i as usize); - let q3 = struct_array - .column_by_name("q3") - .and_then(|a| a.as_any().downcast_ref::()) - .unwrap() - .value(i as usize); - let lower = struct_array - .column_by_name("lower") - .and_then(|a| a.as_any().downcast_ref::()) - .unwrap() - .value(i as usize); - let upper = struct_array - .column_by_name("upper") - .and_then(|a| a.as_any().downcast_ref::()) - .unwrap() - .value(i as usize); - - row.insert("pos", pos.into_py(py)); - row.insert("average", average.into_py(py)); - row.insert("median", median.into_py(py)); - row.insert("q1", q1.into_py(py)); - row.insert("q3", q3.into_py(py)); - row.insert("lower", lower.into_py(py)); - row.insert("upper", upper.into_py(py)); - - base_per_pos_data.push(row.into_py(py).to_object(py)); - } - - let result_dict = PyDict::new_bound(py); - result_dict.set_item("base_quality_warn", warn_array.value(0))?; - result_dict.set_item( - "base_per_pos_data", - PyList::new_bound(py, base_per_pos_data), - )?; - - Ok(result_dict.to_object(py)) -} - fn handle_base_sequence_quality<'a, F>( - py: Python<'a>, + _py: Python<'a>, py_ctx: &PyBioSessionContext, table_name: &str, + column: &str, register_fn: F, -) -> PyResult +) -> PyResult where F: FnOnce(&PyBioSessionContext, &str, &Runtime), { let ctx = &py_ctx.ctx; let rt = Runtime::new().unwrap(); register_fn(py_ctx, table_name, &rt); - let result_opt = rt.block_on(do_base_sequence_quality(ctx, &table_name.to_string())); - deregister_table(ctx, table_name); - if let Some(struct_array) = result_opt { - struct_array_to_pydict(py, &struct_array) - } else { - Ok(py.None()) - } + let data_frame = rt.block_on(do_base_sequence_quality( + ctx, + table_name.to_string(), + column.to_string(), + )); + // deregister_table(ctx, table_name); + Ok(PyDataFrame::new(data_frame)) } #[pyfunction] -#[pyo3(signature = (py_ctx, path))] +#[pyo3(signature = (py_ctx, path, column))] fn base_sequance_quality_scan( py: Python<'_>, py_ctx: &PyBioSessionContext, path: String, -) -> PyResult { - handle_base_sequence_quality(py, py_ctx, DEFAULT_TABLE_NAME, |py_ctx, table_name, rt| { - let ctx = &py_ctx.ctx; - maybe_register_table(path, &table_name.to_string(), None, ctx, rt); - }) + column: String, +) -> PyResult { + handle_base_sequence_quality( + py, + py_ctx, + DEFAULT_TABLE_NAME, + &column, + |py_ctx, table_name, rt| { + let ctx = &py_ctx.ctx; + maybe_register_table(path, &table_name.to_string(), None, ctx, rt); + }, + ) } #[pyfunction] -#[pyo3(signature = (py_ctx, df))] +#[pyo3(signature = (py_ctx, df, column))] fn base_sequance_quality_frame( py: Python<'_>, py_ctx: &PyBioSessionContext, df: PyArrowType, -) -> PyResult { - handle_base_sequence_quality(py, py_ctx, DEFAULT_TABLE_NAME, |py_ctx, table_name, _rt| { - register_frame(py_ctx, df, table_name.to_string()); - }) + column: String, +) -> PyResult { + handle_base_sequence_quality( + py, + py_ctx, + DEFAULT_TABLE_NAME, + &column, + |py_ctx, table_name, _rt| { + register_frame(py_ctx, df, table_name.to_string()); + }, + ) } #[pymodule] diff --git a/src/operation.rs b/src/operation.rs index 808c55a9..d4481184 100644 --- a/src/operation.rs +++ b/src/operation.rs @@ -1,12 +1,12 @@ use std::sync::Arc; -use arrow_array::{Array, StructArray}; use datafusion::catalog_common::TableReference; use exon::ExonSession; use log::{debug, info}; use sequila_core::session_context::{Algorithm, SequilaConfig}; use tokio::runtime::Runtime; +use crate::base_sequence_quality::BaseSequenceQualityProvider; use crate::context::set_option_internal; use crate::option::{FilterOp, RangeOp, RangeOptions}; use crate::query::{count_overlaps_query, nearest_query, overlap_query}; @@ -194,33 +194,20 @@ async fn do_count_overlaps_coverage_naive( pub(crate) async fn do_base_sequence_quality( ctx: &ExonSession, - table: &String, -) -> Option { - let query = format!( - "SELECT base_sequence_quality(quality_scores) as result FROM {}", - table - ); + table: String, + column: String, +) -> datafusion::dataframe::DataFrame { + let session = &ctx.session; + let provider = + BaseSequenceQualityProvider::new(Arc::new(session.clone()), table.clone(), column.clone()); + let table_name = format!("{}_base_sequence_quality", table); + ctx.session.deregister_table(table_name.clone()).ok(); + ctx.session + .register_table(table_name.clone(), Arc::new(provider)) + .unwrap(); + let query = format!("SELECT * FROM {}", table_name); debug!("Query: {}", query); - let batches = ctx.sql(&query).await.unwrap().collect().await.unwrap(); - - if let Some(batch) = batches.get(0) { - let col_idx = batch - .schema() - .fields() - .iter() - .position(|f| f.name() == "result") - .expect("Column 'result' not found"); - let array = batch.column(col_idx); - - if array.len() > 0 && !array.is_null(0) { - if let Some(struct_array) = array.as_any().downcast_ref::() { - return Some(struct_array.clone()); - } else { - panic!("Unsupported result type: {:?}", array.data_type()); - } - } - } - None + ctx.sql(&query).await.unwrap() } async fn get_non_join_columns( diff --git a/src/scan.rs b/src/scan.rs index e7795a99..34412780 100644 --- a/src/scan.rs +++ b/src/scan.rs @@ -156,7 +156,3 @@ pub(crate) fn maybe_register_table( } .to_string() } - -pub(crate) fn deregister_table(ctx: &ExonSession, table_name: &str) { - let _ = ctx.session.deregister_table(table_name); -} diff --git a/src/udaf.rs b/src/udaf.rs deleted file mode 100644 index a26ac237..00000000 --- a/src/udaf.rs +++ /dev/null @@ -1,210 +0,0 @@ -use std::collections::HashMap; -use std::sync::Arc; - -use arrow::buffer::OffsetBuffer; -use arrow_array::{Array, ArrayRef, Float64Array, Int64Array, ListArray, StringArray, StructArray}; -use arrow_schema::{DataType, Field, Fields}; -use datafusion::error::{DataFusionError, Result}; -use datafusion::physical_plan::Accumulator; -use datafusion::scalar::ScalarValue; - -#[derive(Debug)] -pub(crate) struct QualityScoresStats { - values_per_pos: HashMap>, // key: position, value: decoded quality scores -} - -impl QualityScoresStats { - pub fn new() -> Self { - Self { - values_per_pos: HashMap::new(), - } - } - - fn decode_score(c: char) -> Option { - let ascii = c as u8; - if ascii >= 33 { - Some(ascii - 33) - } else { - None - } - } - - fn calc_stats(values: &mut Vec) -> (f64, f64, f64, f64, f64, f64) { - values.sort_unstable(); - let n = values.len(); - let average = values.iter().map(|&v| v as f64).sum::() / n as f64; - let median = if n % 2 == 0 { - (values[n / 2 - 1] as f64 + values[n / 2] as f64) / 2.0 - } else { - values[n / 2] as f64 - }; - let q1 = values[n / 4] as f64; - let q3 = values[(3 * n) / 4] as f64; - let iqr = q3 - q1; - let lower = q1 - 1.5 * iqr; - let upper = q3 + 1.5 * iqr; - (average, median, q1, q3, lower, upper) - } -} - -impl Accumulator for QualityScoresStats { - fn state(&mut self) -> Result> { - Ok(vec![]) - } - - fn evaluate(&mut self) -> Result { - #[derive(Default)] - struct StatColumns { - pos: Vec, - avg: Vec, - median: Vec, - q1: Vec, - q3: Vec, - lower: Vec, - upper: Vec, - } - - let mut cols = StatColumns::default(); - let mut base_quality_warn = "pass"; - - for (&pos, values) in &mut self.values_per_pos { - if values.is_empty() { - continue; - } - - let (avg, median, q1, q3, lower, upper) = Self::calc_stats(values); - - cols.pos.push(pos as i64); - cols.avg.push(avg); - cols.median.push(median); - cols.q1.push(q1); - cols.q3.push(q3); - cols.lower.push(lower); - cols.upper.push(upper); - - base_quality_warn = match (q1 <= 20.0, q1 <= 25.0, base_quality_warn) { - (true, _, _) => "fail", - (false, true, "pass") => "warn", - _ => base_quality_warn, - }; - } - - let result_type = base_quality_result_type(); - - let fields = match result_type { - DataType::Struct(ref fields) => fields.clone(), - _ => { - return Err(DataFusionError::Execution( - "Unexpected result type".to_string(), - )) - }, - }; - - let base_quality_warn_field = fields[0].clone(); - let base_per_pos_data_field = fields[1].clone(); - - let base_per_pos_data_element_field = match base_per_pos_data_field.data_type() { - DataType::List(inner_field) => inner_field.as_ref().clone(), - _ => return Err(DataFusionError::Execution("Expected List type".to_string())), - }; - - let struct_fields = match base_per_pos_data_element_field.data_type() { - DataType::Struct(inner_fields) => inner_fields.clone(), - _ => { - return Err(DataFusionError::Execution( - "Expected Struct type inside list".to_string(), - )) - }, - }; - - let to_array = |vec: Vec| Arc::new(Float64Array::from(vec)) as ArrayRef; - - let struct_array = Arc::new(StructArray::new( - struct_fields.clone(), - vec![ - Arc::new(Int64Array::from(cols.pos)) as ArrayRef, - to_array(cols.avg), - to_array(cols.median), - to_array(cols.q1), - to_array(cols.q3), - to_array(cols.lower), - to_array(cols.upper), - ], - None, - )) as ArrayRef; - - let list_array = Arc::new(ListArray::new( - Arc::new(base_per_pos_data_element_field), - OffsetBuffer::new(vec![0, struct_array.len() as i32].into()), - struct_array, - None, - )); - - Ok(ScalarValue::Struct(Arc::new(StructArray::from(vec![ - ( - base_quality_warn_field, - Arc::new(StringArray::from(vec![base_quality_warn])) as ArrayRef, - ), - (base_per_pos_data_field, list_array), - ])))) - } - - fn update_batch(&mut self, values: &[ArrayRef]) -> Result<()> { - let arr = values[0] - .as_any() - .downcast_ref::() - .ok_or_else(|| { - datafusion::error::DataFusionError::Internal("Expected StringArray".to_string()) - })?; - - for i in 0..arr.len() { - if arr.is_null(i) { - continue; - } - let val = arr.value(i); - - for (j, c) in val.chars().enumerate() { - if let Some(decoded) = Self::decode_score(c) { - self.values_per_pos.entry(j).or_default().push(decoded); - } - } - } - - Ok(()) - } - - fn merge_batch(&mut self, _states: &[ArrayRef]) -> Result<()> { - Ok(()) - } - - fn size(&self) -> usize { - std::mem::size_of_val(self) - } -} - -pub fn base_quality_result_type() -> DataType { - let per_pos_fields = Fields::from(vec![ - Field::new("pos", DataType::Int64, false), - Field::new("average", DataType::Float64, false), - Field::new("median", DataType::Float64, false), - Field::new("q1", DataType::Float64, false), - Field::new("q3", DataType::Float64, false), - Field::new("lower", DataType::Float64, false), - Field::new("upper", DataType::Float64, false), - ]); - - let base_per_pos_element_field = Field::new( - "base_per_pos_data_element", - DataType::Struct(per_pos_fields), - false, - ); - - DataType::Struct(Fields::from(vec![ - Field::new("base_quality_warn", DataType::Utf8, false), - Field::new( - "base_per_pos_data", - DataType::List(Arc::new(base_per_pos_element_field)), - false, - ), - ])) -} From 1bff752c6caa4ea7e01d5a7a54501079c4b8131a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20=C5=9Acise=C5=82?= Date: Thu, 5 Jun 2025 17:58:00 +0200 Subject: [PATCH 06/13] Implement sequence quality histogram and quantile statistics - Added `SequenceQualityHistogramProvider` and `SequenceQualityHistogramExec` to compute quality histograms from sequence data. - Introduced `QuantileStatsTableProvider` and `QuantileStatsExec` for calculating quantile statistics based on histogram data. --- docs/notebooks/base_sequence_quality.ipynb | 267 ++++++++---------- polars_bio/quality_stats.py | 17 +- src/lib.rs | 66 ++--- src/operation.rs | 42 ++- src/quantile_stats.rs | 266 +++++++++++++++++ ...ality.rs => sequence_quality_histogram.rs} | 172 ++++++----- 6 files changed, 544 insertions(+), 286 deletions(-) create mode 100644 src/quantile_stats.rs rename src/{base_sequence_quality.rs => sequence_quality_histogram.rs} (53%) diff --git a/docs/notebooks/base_sequence_quality.ipynb b/docs/notebooks/base_sequence_quality.ipynb index cac9a2ce..ac49dd6f 100644 --- a/docs/notebooks/base_sequence_quality.ipynb +++ b/docs/notebooks/base_sequence_quality.ipynb @@ -37,27 +37,6 @@ "### Usage examples" ] }, - { - "cell_type": "markdown", - "id": "f9aedeb9", - "metadata": {}, - "source": [ - "#### Usage example - calling UDAF directly in SQL" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5f6fccf3", - "metadata": {}, - "outputs": [], - "source": [ - "a_lazyframe = pb.read_fastq(\"./example.fastq\")\n", - "# not implemented yet\n", - "result = pb.sql(\"???\").collect()\n", - "print(result)" - ] - }, { "cell_type": "markdown", "id": "b238193d", @@ -68,7 +47,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 2, "id": "0420c240", "metadata": {}, "outputs": [ @@ -76,25 +55,25 @@ "name": "stdout", "output_type": "stream", "text": [ - " pos score\n", - "0 0 2\n", - "1 1 19\n", - "2 2 33\n", - "3 3 35\n", - "4 4 37\n", - "... ... ...\n", - "20195 96 35\n", - "20196 97 32\n", - "20197 98 35\n", - "20198 99 35\n", - "20199 100 33\n", + " pos avg q1 median q3 lower upper\n", + "0 47 37.665 37.535714 39.921053 41.060185 32.249008 46.346892\n", + "1 38 37.640 37.964286 40.067308 41.024038 33.374657 45.613668\n", + "2 65 35.995 35.190000 37.433333 39.810000 28.260000 46.740000\n", + "3 3 35.690 35.483333 37.208661 37.600394 32.307743 40.775984\n", + "4 41 37.870 37.678571 40.116071 41.004902 32.689076 45.994398\n", + ".. ... ... ... ... ... ... ...\n", + "96 42 37.780 37.583333 40.139344 40.954918 32.525956 46.012295\n", + "97 43 37.775 38.114583 40.126866 40.869403 33.982354 45.001632\n", + "98 15 38.725 38.226190 40.352459 41.168033 33.813427 45.580796\n", + "99 46 37.790 37.479167 39.975000 41.042453 32.134237 46.387382\n", + "100 24 38.265 38.397059 40.095745 41.125000 34.305147 45.216912\n", "\n", - "[20200 rows x 2 columns]\n" + "[101 rows x 7 columns]\n" ] } ], "source": [ - "result = pb.base_sequence_quality(\"example.fastq\", output_type=\"pandas.DataFrame\")\n", + "result = pb.base_sequence_quality(\"example.fastq\", output_type=\"pandas.DataFrame\", target_partitions=2)\n", "print(result)" ] }, @@ -108,7 +87,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 3, "id": "66c3af24", "metadata": {}, "outputs": [ @@ -122,30 +101,30 @@ " white-space: pre-wrap;\n", "}\n", "\n", - "shape: (20_200, 2)
posscore
i64i8
02
119
233
335
437
9635
9732
9835
9935
10033
" + "shape: (101, 7)
posavgq1medianq3lowerupper
u64f64f64f64f64f64f64
4737.66537.53571439.92105341.06018532.24900846.346892
9032.27533.18333334.98684235.6396129.49891839.324026
2637.85538.02884640.07894740.95175433.64448445.336117
735.435.46590936.9062537.48737432.43371240.519571
335.6935.48333337.20866137.60039432.30774340.775984
1938.42538.237540.23846241.00490234.08639745.156005
9430.77532.05769234.65151535.5126.87923140.688462
1738.50538.12540.12745141.0937533.67187545.546875
7932.4631.9687535.20535736.437525.26562543.140625
4137.8737.67857140.11607141.00490232.68907645.994398
" ], "text/plain": [ - "shape: (20_200, 2)\n", - "┌─────┬───────┐\n", - "│ pos ┆ score │\n", - "│ --- ┆ --- │\n", - "│ i64 ┆ i8 │\n", - "╞═════╪═══════╡\n", - "│ 0 ┆ 2 │\n", - "│ 1 ┆ 19 │\n", - "│ 2 ┆ 33 │\n", - "│ 3 ┆ 35 │\n", - "│ 4 ┆ 37 │\n", - "│ … ┆ … │\n", - "│ 96 ┆ 35 │\n", - "│ 97 ┆ 32 │\n", - "│ 98 ┆ 35 │\n", - "│ 99 ┆ 35 │\n", - "│ 100 ┆ 33 │\n", - "└─────┴───────┘" + "shape: (101, 7)\n", + "┌─────┬────────┬───────────┬───────────┬───────────┬───────────┬───────────┐\n", + "│ pos ┆ avg ┆ q1 ┆ median ┆ q3 ┆ lower ┆ upper │\n", + "│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │\n", + "│ u64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 │\n", + "╞═════╪════════╪═══════════╪═══════════╪═══════════╪═══════════╪═══════════╡\n", + "│ 47 ┆ 37.665 ┆ 37.535714 ┆ 39.921053 ┆ 41.060185 ┆ 32.249008 ┆ 46.346892 │\n", + "│ 90 ┆ 32.275 ┆ 33.183333 ┆ 34.986842 ┆ 35.63961 ┆ 29.498918 ┆ 39.324026 │\n", + "│ 26 ┆ 37.855 ┆ 38.028846 ┆ 40.078947 ┆ 40.951754 ┆ 33.644484 ┆ 45.336117 │\n", + "│ 7 ┆ 35.4 ┆ 35.465909 ┆ 36.90625 ┆ 37.487374 ┆ 32.433712 ┆ 40.519571 │\n", + "│ 3 ┆ 35.69 ┆ 35.483333 ┆ 37.208661 ┆ 37.600394 ┆ 32.307743 ┆ 40.775984 │\n", + "│ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … │\n", + "│ 19 ┆ 38.425 ┆ 38.2375 ┆ 40.238462 ┆ 41.004902 ┆ 34.086397 ┆ 45.156005 │\n", + "│ 94 ┆ 30.775 ┆ 32.057692 ┆ 34.651515 ┆ 35.51 ┆ 26.879231 ┆ 40.688462 │\n", + "│ 17 ┆ 38.505 ┆ 38.125 ┆ 40.127451 ┆ 41.09375 ┆ 33.671875 ┆ 45.546875 │\n", + "│ 79 ┆ 32.46 ┆ 31.96875 ┆ 35.205357 ┆ 36.4375 ┆ 25.265625 ┆ 43.140625 │\n", + "│ 41 ┆ 37.87 ┆ 37.678571 ┆ 40.116071 ┆ 41.004902 ┆ 32.689076 ┆ 45.994398 │\n", + "└─────┴────────┴───────────┴───────────┴───────────┴───────────┴───────────┘" ] }, - "execution_count": 4, + "execution_count": 3, "metadata": {}, "output_type": "execute_result" } @@ -164,7 +143,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 4, "id": "a2cb9c97", "metadata": {}, "outputs": [ @@ -178,30 +157,30 @@ " white-space: pre-wrap;\n", "}\n", "\n", - "shape: (20_200, 2)
posscore
i64i8
02
119
233
335
437
9635
9732
9835
9935
10033
" + "shape: (101, 7)
posavgq1medianq3lowerupper
u64f64f64f64f64f64f64
4437.56537.7187540.13392941.02403832.76081745.981971
2738.4438.23437540.2741.20703133.77539145.666016
7233.26533.86111135.687537.92391327.76690844.018116
8631.81533.36538535.13291135.76265829.76947439.358569
9032.27533.18333334.98684235.6396129.49891839.324026
3438.20537.97916740.15957441.16803333.19586745.951332
8432.41533.2535.18243235.8547329.34290539.761824
4937.2136.67857139.64583340.76388930.55059546.891865
6336.2535.21590938.02631640.27527.62727347.863636
8032.6132.62535.28947436.42045526.93181842.113636
" ], "text/plain": [ - "shape: (20_200, 2)\n", - "┌─────┬───────┐\n", - "│ pos ┆ score │\n", - "│ --- ┆ --- │\n", - "│ i64 ┆ i8 │\n", - "╞═════╪═══════╡\n", - "│ 0 ┆ 2 │\n", - "│ 1 ┆ 19 │\n", - "│ 2 ┆ 33 │\n", - "│ 3 ┆ 35 │\n", - "│ 4 ┆ 37 │\n", - "│ … ┆ … │\n", - "│ 96 ┆ 35 │\n", - "│ 97 ┆ 32 │\n", - "│ 98 ┆ 35 │\n", - "│ 99 ┆ 35 │\n", - "│ 100 ┆ 33 │\n", - "└─────┴───────┘" + "shape: (101, 7)\n", + "┌─────┬────────┬───────────┬───────────┬───────────┬───────────┬───────────┐\n", + "│ pos ┆ avg ┆ q1 ┆ median ┆ q3 ┆ lower ┆ upper │\n", + "│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │\n", + "│ u64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 │\n", + "╞═════╪════════╪═══════════╪═══════════╪═══════════╪═══════════╪═══════════╡\n", + "│ 44 ┆ 37.565 ┆ 37.71875 ┆ 40.133929 ┆ 41.024038 ┆ 32.760817 ┆ 45.981971 │\n", + "│ 27 ┆ 38.44 ┆ 38.234375 ┆ 40.27 ┆ 41.207031 ┆ 33.775391 ┆ 45.666016 │\n", + "│ 72 ┆ 33.265 ┆ 33.861111 ┆ 35.6875 ┆ 37.923913 ┆ 27.766908 ┆ 44.018116 │\n", + "│ 86 ┆ 31.815 ┆ 33.365385 ┆ 35.132911 ┆ 35.762658 ┆ 29.769474 ┆ 39.358569 │\n", + "│ 90 ┆ 32.275 ┆ 33.183333 ┆ 34.986842 ┆ 35.63961 ┆ 29.498918 ┆ 39.324026 │\n", + "│ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … │\n", + "│ 34 ┆ 38.205 ┆ 37.979167 ┆ 40.159574 ┆ 41.168033 ┆ 33.195867 ┆ 45.951332 │\n", + "│ 84 ┆ 32.415 ┆ 33.25 ┆ 35.182432 ┆ 35.85473 ┆ 29.342905 ┆ 39.761824 │\n", + "│ 49 ┆ 37.21 ┆ 36.678571 ┆ 39.645833 ┆ 40.763889 ┆ 30.550595 ┆ 46.891865 │\n", + "│ 63 ┆ 36.25 ┆ 35.215909 ┆ 38.026316 ┆ 40.275 ┆ 27.627273 ┆ 47.863636 │\n", + "│ 80 ┆ 32.61 ┆ 32.625 ┆ 35.289474 ┆ 36.420455 ┆ 26.931818 ┆ 42.113636 │\n", + "└─────┴────────┴───────────┴───────────┴───────────┴───────────┴───────────┘" ] }, - "execution_count": 5, + "execution_count": 4, "metadata": {}, "output_type": "execute_result" } @@ -220,7 +199,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 5, "id": "1899ca01", "metadata": {}, "outputs": [ @@ -242,7 +221,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "200rows [00:00, 85580.58rows/s]\n" + "200rows [00:00, 62156.25rows/s]\n" ] }, { @@ -255,30 +234,30 @@ " white-space: pre-wrap;\n", "}\n", "\n", - "shape: (20_200, 2)
posscore
i64i8
02
119
233
335
437
9635
9732
9835
9935
10033
" + "shape: (101, 7)
posavgq1medianq3lowerupper
u64f64f64f64f64f64f64
6436.09535.06481537.740.14583327.44328747.767361
435.6835.55288537.20866137.60039432.48162140.671657
6835.9134.94047636.93181839.53947428.0419846.43797
7233.26533.86111135.687537.92391327.76690844.018116
5836.7735.33823538.9062540.71710527.2699348.78541
2637.85538.02884640.07894740.95175433.64448445.336117
937.3637.3437539.01470639.50245134.10569942.740502
7133.00533.79166735.85135138.58333326.60416745.770833
1137.7137.78448339.09459539.54279335.14701842.180258
2438.26538.39705940.09574541.12534.30514745.216912
" ], "text/plain": [ - "shape: (20_200, 2)\n", - "┌─────┬───────┐\n", - "│ pos ┆ score │\n", - "│ --- ┆ --- │\n", - "│ i64 ┆ i8 │\n", - "╞═════╪═══════╡\n", - "│ 0 ┆ 2 │\n", - "│ 1 ┆ 19 │\n", - "│ 2 ┆ 33 │\n", - "│ 3 ┆ 35 │\n", - "│ 4 ┆ 37 │\n", - "│ … ┆ … │\n", - "│ 96 ┆ 35 │\n", - "│ 97 ┆ 32 │\n", - "│ 98 ┆ 35 │\n", - "│ 99 ┆ 35 │\n", - "│ 100 ┆ 33 │\n", - "└─────┴───────┘" + "shape: (101, 7)\n", + "┌─────┬────────┬───────────┬───────────┬───────────┬───────────┬───────────┐\n", + "│ pos ┆ avg ┆ q1 ┆ median ┆ q3 ┆ lower ┆ upper │\n", + "│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │\n", + "│ u64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 │\n", + "╞═════╪════════╪═══════════╪═══════════╪═══════════╪═══════════╪═══════════╡\n", + "│ 64 ┆ 36.095 ┆ 35.064815 ┆ 37.7 ┆ 40.145833 ┆ 27.443287 ┆ 47.767361 │\n", + "│ 4 ┆ 35.68 ┆ 35.552885 ┆ 37.208661 ┆ 37.600394 ┆ 32.481621 ┆ 40.671657 │\n", + "│ 68 ┆ 35.91 ┆ 34.940476 ┆ 36.931818 ┆ 39.539474 ┆ 28.04198 ┆ 46.43797 │\n", + "│ 72 ┆ 33.265 ┆ 33.861111 ┆ 35.6875 ┆ 37.923913 ┆ 27.766908 ┆ 44.018116 │\n", + "│ 58 ┆ 36.77 ┆ 35.338235 ┆ 38.90625 ┆ 40.717105 ┆ 27.26993 ┆ 48.78541 │\n", + "│ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … │\n", + "│ 26 ┆ 37.855 ┆ 38.028846 ┆ 40.078947 ┆ 40.951754 ┆ 33.644484 ┆ 45.336117 │\n", + "│ 9 ┆ 37.36 ┆ 37.34375 ┆ 39.014706 ┆ 39.502451 ┆ 34.105699 ┆ 42.740502 │\n", + "│ 71 ┆ 33.005 ┆ 33.791667 ┆ 35.851351 ┆ 38.583333 ┆ 26.604167 ┆ 45.770833 │\n", + "│ 11 ┆ 37.71 ┆ 37.784483 ┆ 39.094595 ┆ 39.542793 ┆ 35.147018 ┆ 42.180258 │\n", + "│ 24 ┆ 38.265 ┆ 38.397059 ┆ 40.095745 ┆ 41.125 ┆ 34.305147 ┆ 45.216912 │\n", + "└─────┴────────┴───────────┴───────────┴───────────┴───────────┴───────────┘" ] }, - "execution_count": 6, + "execution_count": 5, "metadata": {}, "output_type": "execute_result" } @@ -299,7 +278,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 6, "id": "7830b8aa", "metadata": {}, "outputs": [ @@ -308,7 +287,7 @@ "output_type": "stream", "text": [ "INFO:polars_bio:Table: example registered for path: ./example.fastq\n", - "200rows [00:00, 99332.24rows/s]" + "200rows [00:00, 66234.57rows/s]" ] }, { @@ -335,30 +314,30 @@ " white-space: pre-wrap;\n", "}\n", "\n", - "shape: (20_200, 2)
posscore
i64i8
02
119
233
335
437
9635
9732
9835
9935
10033
" + "shape: (101, 7)
posavgq1medianq3lowerupper
u64f64f64f64f64f64f64
335.6935.48333337.20866137.60039432.30774340.775984
2938.59538.3540.25833341.0937534.23437545.209375
4437.56537.7187540.13392941.02403832.76081745.981971
7630.26530.91666735.41489437.07352921.68137346.308824
6735.9634.72368436.97222239.8127.09421147.439474
1538.72538.2261940.35245941.16803333.81342745.580796
2637.85538.02884640.07894740.95175433.64448445.336117
3937.89538.02777840.12540.85661833.78451845.099877
9730.6731.57534.89062535.55722925.60165741.530572
5137.5336.7187539.44736841.02403830.26081747.481971
" ], "text/plain": [ - "shape: (20_200, 2)\n", - "┌─────┬───────┐\n", - "│ pos ┆ score │\n", - "│ --- ┆ --- │\n", - "│ i64 ┆ i8 │\n", - "╞═════╪═══════╡\n", - "│ 0 ┆ 2 │\n", - "│ 1 ┆ 19 │\n", - "│ 2 ┆ 33 │\n", - "│ 3 ┆ 35 │\n", - "│ 4 ┆ 37 │\n", - "│ … ┆ … │\n", - "│ 96 ┆ 35 │\n", - "│ 97 ┆ 32 │\n", - "│ 98 ┆ 35 │\n", - "│ 99 ┆ 35 │\n", - "│ 100 ┆ 33 │\n", - "└─────┴───────┘" + "shape: (101, 7)\n", + "┌─────┬────────┬───────────┬───────────┬───────────┬───────────┬───────────┐\n", + "│ pos ┆ avg ┆ q1 ┆ median ┆ q3 ┆ lower ┆ upper │\n", + "│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │\n", + "│ u64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 │\n", + "╞═════╪════════╪═══════════╪═══════════╪═══════════╪═══════════╪═══════════╡\n", + "│ 3 ┆ 35.69 ┆ 35.483333 ┆ 37.208661 ┆ 37.600394 ┆ 32.307743 ┆ 40.775984 │\n", + "│ 29 ┆ 38.595 ┆ 38.35 ┆ 40.258333 ┆ 41.09375 ┆ 34.234375 ┆ 45.209375 │\n", + "│ 44 ┆ 37.565 ┆ 37.71875 ┆ 40.133929 ┆ 41.024038 ┆ 32.760817 ┆ 45.981971 │\n", + "│ 76 ┆ 30.265 ┆ 30.916667 ┆ 35.414894 ┆ 37.073529 ┆ 21.681373 ┆ 46.308824 │\n", + "│ 67 ┆ 35.96 ┆ 34.723684 ┆ 36.972222 ┆ 39.81 ┆ 27.094211 ┆ 47.439474 │\n", + "│ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … │\n", + "│ 15 ┆ 38.725 ┆ 38.22619 ┆ 40.352459 ┆ 41.168033 ┆ 33.813427 ┆ 45.580796 │\n", + "│ 26 ┆ 37.855 ┆ 38.028846 ┆ 40.078947 ┆ 40.951754 ┆ 33.644484 ┆ 45.336117 │\n", + "│ 39 ┆ 37.895 ┆ 38.027778 ┆ 40.125 ┆ 40.856618 ┆ 33.784518 ┆ 45.099877 │\n", + "│ 97 ┆ 30.67 ┆ 31.575 ┆ 34.890625 ┆ 35.557229 ┆ 25.601657 ┆ 41.530572 │\n", + "│ 51 ┆ 37.53 ┆ 36.71875 ┆ 39.447368 ┆ 41.024038 ┆ 30.260817 ┆ 47.481971 │\n", + "└─────┴────────┴───────────┴───────────┴───────────┴───────────┴───────────┘" ] }, - "execution_count": 7, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } @@ -380,7 +359,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 7, "id": "56817174", "metadata": {}, "outputs": [ @@ -389,7 +368,7 @@ "output_type": "stream", "text": [ "INFO:polars_bio:Table: example registered for path: ./example.fastq\n", - "200rows [00:00, 91638.72rows/s]" + "200rows [00:00, 91799.17rows/s]" ] }, { @@ -416,30 +395,30 @@ " white-space: pre-wrap;\n", "}\n", "\n", - "shape: (20_200, 2)
posscore
i64i8
02
119
233
335
437
9635
9732
9835
9935
10033
" + "shape: (101, 7)
posavgq1medianq3lowerupper
u64f64f64f64f64f64f64
7133.00533.79166735.85135138.58333326.60416745.770833
7430.8332.7535.53260937.48529425.64705944.588235
4537.4536.5937540.07142941.07727329.86846647.802557
4937.2136.67857139.64583340.76388930.55059546.891865
7531.0630.95833335.41836737.28333321.47083346.770833
5037.42535.97539.77083341.06018528.34722248.687963
335.6935.48333337.20866137.60039432.30774340.775984
030.13531.21363633.72222234.48214326.31087739.384903
3738.038.21527840.08035740.9687534.08506945.098958
6535.99535.1937.43333339.8128.2646.74
" ], "text/plain": [ - "shape: (20_200, 2)\n", - "┌─────┬───────┐\n", - "│ pos ┆ score │\n", - "│ --- ┆ --- │\n", - "│ i64 ┆ i8 │\n", - "╞═════╪═══════╡\n", - "│ 0 ┆ 2 │\n", - "│ 1 ┆ 19 │\n", - "│ 2 ┆ 33 │\n", - "│ 3 ┆ 35 │\n", - "│ 4 ┆ 37 │\n", - "│ … ┆ … │\n", - "│ 96 ┆ 35 │\n", - "│ 97 ┆ 32 │\n", - "│ 98 ┆ 35 │\n", - "│ 99 ┆ 35 │\n", - "│ 100 ┆ 33 │\n", - "└─────┴───────┘" + "shape: (101, 7)\n", + "┌─────┬────────┬───────────┬───────────┬───────────┬───────────┬───────────┐\n", + "│ pos ┆ avg ┆ q1 ┆ median ┆ q3 ┆ lower ┆ upper │\n", + "│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │\n", + "│ u64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 │\n", + "╞═════╪════════╪═══════════╪═══════════╪═══════════╪═══════════╪═══════════╡\n", + "│ 71 ┆ 33.005 ┆ 33.791667 ┆ 35.851351 ┆ 38.583333 ┆ 26.604167 ┆ 45.770833 │\n", + "│ 74 ┆ 30.83 ┆ 32.75 ┆ 35.532609 ┆ 37.485294 ┆ 25.647059 ┆ 44.588235 │\n", + "│ 45 ┆ 37.45 ┆ 36.59375 ┆ 40.071429 ┆ 41.077273 ┆ 29.868466 ┆ 47.802557 │\n", + "│ 49 ┆ 37.21 ┆ 36.678571 ┆ 39.645833 ┆ 40.763889 ┆ 30.550595 ┆ 46.891865 │\n", + "│ 75 ┆ 31.06 ┆ 30.958333 ┆ 35.418367 ┆ 37.283333 ┆ 21.470833 ┆ 46.770833 │\n", + "│ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … │\n", + "│ 50 ┆ 37.425 ┆ 35.975 ┆ 39.770833 ┆ 41.060185 ┆ 28.347222 ┆ 48.687963 │\n", + "│ 3 ┆ 35.69 ┆ 35.483333 ┆ 37.208661 ┆ 37.600394 ┆ 32.307743 ┆ 40.775984 │\n", + "│ 0 ┆ 30.135 ┆ 31.213636 ┆ 33.722222 ┆ 34.482143 ┆ 26.310877 ┆ 39.384903 │\n", + "│ 37 ┆ 38.0 ┆ 38.215278 ┆ 40.080357 ┆ 40.96875 ┆ 34.085069 ┆ 45.098958 │\n", + "│ 65 ┆ 35.995 ┆ 35.19 ┆ 37.433333 ┆ 39.81 ┆ 28.26 ┆ 46.74 │\n", + "└─────┴────────┴───────────┴───────────┴───────────┴───────────┴───────────┘" ] }, - "execution_count": 8, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" } diff --git a/polars_bio/quality_stats.py b/polars_bio/quality_stats.py index d19daec9..501bd44a 100644 --- a/polars_bio/quality_stats.py +++ b/polars_bio/quality_stats.py @@ -15,6 +15,7 @@ def base_sequence_quality( df: Union[str, pl.DataFrame, pl.LazyFrame, pd.DataFrame], quality_scores_column: str = "quality_scores", output_type: str = "polars.DataFrame", + target_partitions: int = 8, ) -> Union[pl.DataFrame, pd.DataFrame]: """ Compute base sequence quality statistics from various dataframe/file types. @@ -27,12 +28,20 @@ def base_sequence_quality( Returns: DataFrame with base sequence quality statistics. """ + ctx.set_option( + "datafusion.execution.target_partitions", str(target_partitions), False + ) + if isinstance(df, str): supported_exts = {".parquet", ".csv", ".bed", ".vcf", ".fastq"} ext = set(Path(df).suffixes) if not (supported_exts & ext or not ext): - raise ValueError("Input file must be a Parquet, CSV, BED, VCF, or FASTQ file.") - result: datafusion.DataFrame = base_sequance_quality_scan(ctx, df, quality_scores_column) + raise ValueError( + "Input file must be a Parquet, CSV, BED, VCF, or FASTQ file." + ) + result: datafusion.DataFrame = base_sequance_quality_scan( + ctx, df, quality_scores_column + ) else: if isinstance(df, pl.LazyFrame): arrow_table = df.collect().to_arrow() @@ -42,7 +51,9 @@ def base_sequence_quality( arrow_table = pa.Table.from_pandas(df) else: raise TypeError("Unsupported dataframe type.") - result: datafusion.DataFrame = base_sequance_quality_frame(ctx, arrow_table, quality_scores_column) + result: datafusion.DataFrame = base_sequance_quality_frame( + ctx, arrow_table, quality_scores_column + ) if output_type == "polars.DataFrame": return result.to_polars() diff --git a/src/lib.rs b/src/lib.rs index ac78e9b3..152b0736 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,8 @@ -mod base_sequence_quality; +mod sequence_quality_histogram; mod context; mod operation; mod option; +mod quantile_stats; mod query; mod scan; mod streaming; @@ -406,28 +407,6 @@ fn py_from_polars( }) } -fn handle_base_sequence_quality<'a, F>( - _py: Python<'a>, - py_ctx: &PyBioSessionContext, - table_name: &str, - column: &str, - register_fn: F, -) -> PyResult -where - F: FnOnce(&PyBioSessionContext, &str, &Runtime), -{ - let ctx = &py_ctx.ctx; - let rt = Runtime::new().unwrap(); - register_fn(py_ctx, table_name, &rt); - let data_frame = rt.block_on(do_base_sequence_quality( - ctx, - table_name.to_string(), - column.to_string(), - )); - // deregister_table(ctx, table_name); - Ok(PyDataFrame::new(data_frame)) -} - #[pyfunction] #[pyo3(signature = (py_ctx, path, column))] fn base_sequance_quality_scan( @@ -436,16 +415,17 @@ fn base_sequance_quality_scan( path: String, column: String, ) -> PyResult { - handle_base_sequence_quality( - py, - py_ctx, - DEFAULT_TABLE_NAME, - &column, - |py_ctx, table_name, rt| { - let ctx = &py_ctx.ctx; - maybe_register_table(path, &table_name.to_string(), None, ctx, rt); - }, - ) + py.allow_threads(|| { + let ctx = &py_ctx.ctx; + let rt = Runtime::new().unwrap(); + maybe_register_table(path, &DEFAULT_TABLE_NAME.to_string(), None, ctx, &rt); + let data_frame = rt.block_on(do_base_sequence_quality( + ctx, + DEFAULT_TABLE_NAME.to_string(), + column.to_string(), + )); + Ok(PyDataFrame::new(data_frame)) + }) } #[pyfunction] @@ -456,15 +436,17 @@ fn base_sequance_quality_frame( df: PyArrowType, column: String, ) -> PyResult { - handle_base_sequence_quality( - py, - py_ctx, - DEFAULT_TABLE_NAME, - &column, - |py_ctx, table_name, _rt| { - register_frame(py_ctx, df, table_name.to_string()); - }, - ) + py.allow_threads(|| { + let ctx = &py_ctx.ctx; + let rt = Runtime::new().unwrap(); + register_frame(py_ctx, df, DEFAULT_TABLE_NAME.to_string()); + let data_frame = rt.block_on(do_base_sequence_quality( + ctx, + DEFAULT_TABLE_NAME.to_string(), + column.to_string(), + )); + Ok(PyDataFrame::new(data_frame)) + }) } #[pymodule] diff --git a/src/operation.rs b/src/operation.rs index d4481184..bd50e182 100644 --- a/src/operation.rs +++ b/src/operation.rs @@ -6,9 +6,10 @@ use log::{debug, info}; use sequila_core::session_context::{Algorithm, SequilaConfig}; use tokio::runtime::Runtime; -use crate::base_sequence_quality::BaseSequenceQualityProvider; +use crate::sequence_quality_histogram::SequenceQualityHistogramProvider; use crate::context::set_option_internal; use crate::option::{FilterOp, RangeOp, RangeOptions}; +use crate::quantile_stats::QuantileStatsTableProvider; use crate::query::{count_overlaps_query, nearest_query, overlap_query}; use crate::udtf::CountOverlapsProvider; use crate::utils::default_cols_to_string; @@ -197,16 +198,37 @@ pub(crate) async fn do_base_sequence_quality( table: String, column: String, ) -> datafusion::dataframe::DataFrame { - let session = &ctx.session; - let provider = - BaseSequenceQualityProvider::new(Arc::new(session.clone()), table.clone(), column.clone()); - let table_name = format!("{}_base_sequence_quality", table); - ctx.session.deregister_table(table_name.clone()).ok(); - ctx.session - .register_table(table_name.clone(), Arc::new(provider)) + let session = Arc::new(ctx.session.clone()); + let base_provider = Arc::new(SequenceQualityHistogramProvider::new( + session.clone(), + table.clone(), + column, + )); + + let base_table_name = format!("{}_decoded", table); + session.deregister_table(base_table_name.clone()).unwrap(); + session + .register_table(&base_table_name, base_provider) .unwrap(); - let query = format!("SELECT * FROM {}", table_name); - debug!("Query: {}", query); + + let query = format!( + "SELECT pos, score, SUM(count) as count FROM {} GROUP BY pos, score", + base_table_name + ); + let base_df = ctx.sql(&query).await.unwrap(); + let base_plan = base_df.create_physical_plan().await.unwrap(); + + let quantile_provider = Arc::new(QuantileStatsTableProvider::new(base_plan)); + + let quantile_table_name = format!("{}_quantiles", table); + session + .deregister_table(quantile_table_name.clone()) + .unwrap(); + session + .register_table(&quantile_table_name, quantile_provider) + .unwrap(); + + let query = format!("SELECT * FROM {}", quantile_table_name); ctx.sql(&query).await.unwrap() } diff --git a/src/quantile_stats.rs b/src/quantile_stats.rs new file mode 100644 index 00000000..36bf01b2 --- /dev/null +++ b/src/quantile_stats.rs @@ -0,0 +1,266 @@ +use std::any::Any; +use std::collections::HashMap; +use std::fmt::{Debug, Formatter}; +use std::sync::Arc; + +use arrow::array::{Array, Float64Builder, UInt64Array, UInt64Builder, UInt8Array}; +use arrow::compute::concat_batches; +use arrow::datatypes::{DataType, Field, Schema, SchemaRef}; +use arrow::record_batch::RecordBatch; +use async_trait::async_trait; +use datafusion::catalog::{Session, TableProvider}; +use datafusion::datasource::TableType; +use datafusion::error::Result; +use datafusion::execution::context::TaskContext; +use datafusion::physical_expr::EquivalenceProperties; +use datafusion::physical_plan::memory::MemoryStream; +use datafusion::physical_plan::{ + collect, DisplayAs, DisplayFormatType, ExecutionMode, ExecutionPlan, Partitioning, + PlanProperties, SendableRecordBatchStream, +}; + +pub struct QuantileStatsTableProvider { + input: Arc, + schema: SchemaRef, +} + +impl QuantileStatsTableProvider { + pub fn new(input: Arc) -> Self { + let schema = Arc::new(Schema::new(vec![ + Field::new("pos", DataType::UInt64, false), + Field::new("avg", DataType::Float64, true), + Field::new("q1", DataType::Float64, true), + Field::new("median", DataType::Float64, true), + Field::new("q3", DataType::Float64, true), + Field::new("lower", DataType::Float64, true), + Field::new("upper", DataType::Float64, true), + ])); + Self { + input, + schema, + } + } +} + +impl Debug for QuantileStatsTableProvider { + fn fmt(&self, _f: &mut Formatter<'_>) -> std::fmt::Result { + Ok(()) + } +} + +#[async_trait] +impl TableProvider for QuantileStatsTableProvider { + fn as_any(&self) -> &dyn std::any::Any { + self + } + + fn schema(&self) -> SchemaRef { + self.schema.clone() + } + + fn table_type(&self) -> TableType { + TableType::Base + } + + async fn scan( + &self, + _state: &dyn Session, + _projection: Option<&Vec>, + _filters: &[datafusion::logical_expr::Expr], + _limit: Option, + ) -> datafusion::error::Result> { + Ok(Arc::new(QuantileStatsExec::new(self.input.clone()))) + } +} + +#[derive(Debug)] +pub struct QuantileStatsExec { + input: Arc, + schema: SchemaRef, + properties: PlanProperties, +} + +impl QuantileStatsExec { + pub fn new(input: Arc) -> Self { + let schema = Arc::new(Schema::new(vec![ + Field::new("pos", DataType::UInt64, false), + Field::new("avg", DataType::Float64, true), + Field::new("q1", DataType::Float64, true), + Field::new("median", DataType::Float64, true), + Field::new("q3", DataType::Float64, true), + Field::new("lower", DataType::Float64, true), + Field::new("upper", DataType::Float64, true), + ])); + + let schema_clone = schema.clone(); + + Self { + input, + schema, + properties: PlanProperties::new( + EquivalenceProperties::new(schema_clone), + Partitioning::UnknownPartitioning(1), + ExecutionMode::Bounded, + ), + } + } +} + +impl ExecutionPlan for QuantileStatsExec { + fn name(&self) -> &str { + "QuantileAggregateExec" + } + + fn as_any(&self) -> &dyn Any { + self + } + + fn schema(&self) -> SchemaRef { + Arc::clone(&self.schema) + } + + fn properties(&self) -> &PlanProperties { + &self.properties + } + + fn children(&self) -> Vec<&Arc> { + vec![&self.input] + } + + fn with_new_children( + self: Arc, + _children: Vec>, + ) -> Result> { + Ok(self) + } + + fn execute( + &self, + _partition: usize, + context: Arc, + ) -> Result { + let input = self.input.clone(); + let schema = self.schema.clone(); + + let batches = futures::executor::block_on(collect(input, context.clone()))?; + let combined = concat_batches(&self.input.schema(), &batches)?; + let pos_array = combined + .column_by_name("pos") + .expect("Column 'pos' not found") + .as_any() + .downcast_ref::() + .expect("Expected UInt64 for pos"); + + let score_array = combined + .column_by_name("score") + .expect("Column 'score' not found") + .as_any() + .downcast_ref::() + .expect("Expected UInt8 for score"); + + let count_array = combined + .column_by_name("count") + .expect("Column 'count' not found") + .as_any() + .downcast_ref::() + .expect("Expected UInt64 for count"); + + let mut groups: HashMap> = HashMap::new(); + for i in 0..combined.num_rows() { + if pos_array.is_valid(i) && score_array.is_valid(i) && count_array.is_valid(i) { + let pos = pos_array.value(i); + let score = score_array.value(i); + let count = count_array.value(i); + let entry = groups.entry(pos).or_insert_with(|| vec![0; 256]); + entry[score as usize] += count; + } + } + + let mut pos_builder = UInt64Builder::with_capacity(groups.len()); + let mut avg_builder = Float64Builder::with_capacity(groups.len()); + let mut q1_builder = Float64Builder::with_capacity(groups.len()); + let mut median_builder = Float64Builder::with_capacity(groups.len()); + let mut q3_builder = Float64Builder::with_capacity(groups.len()); + let mut lower_builder = Float64Builder::with_capacity(groups.len()); + let mut upper_builder = Float64Builder::with_capacity(groups.len()); + + for (pos, hist) in groups { + if let Some((average, q1, median, q3, lower, upper)) = calculate_histogram_stats(&hist) + { + pos_builder.append_value(pos); + avg_builder.append_value(average); + q1_builder.append_value(q1); + median_builder.append_value(median); + q3_builder.append_value(q3); + lower_builder.append_value(lower); + upper_builder.append_value(upper); + } + } + + let result_batch = RecordBatch::try_new( + schema.clone(), + vec![ + Arc::new(pos_builder.finish()), + Arc::new(avg_builder.finish()), + Arc::new(q1_builder.finish()), + Arc::new(median_builder.finish()), + Arc::new(q3_builder.finish()), + Arc::new(lower_builder.finish()), + Arc::new(upper_builder.finish()), + ], + )?; + let mem_stream = MemoryStream::try_new(vec![result_batch], schema, None)?; + Ok(Box::pin(mem_stream)) + } +} + +impl DisplayAs for QuantileStatsExec { + fn fmt_as(&self, _t: DisplayFormatType, _f: &mut Formatter) -> std::fmt::Result { + Ok(()) + } +} + +fn calculate_histogram_stats(hist: &[u64]) -> Option<(f64, f64, f64, f64, f64, f64)> { + let total_count: u64 = hist.iter().sum(); + if total_count == 0 { + return None; + } + + let weighted_sum: u64 = hist + .iter() + .enumerate() + .map(|(score, &count)| score as u64 * count) + .sum(); + let average = weighted_sum as f64 / total_count as f64; + + fn quantile(hist: &[u64], quantile: f64, total: u64) -> f64 { + let target = quantile * (total - 1) as f64; + let mut acc = 0u64; + let mut prev_idx = 0usize; + for (idx, &count) in hist.iter().enumerate() { + if count == 0 { + continue; + } + if (acc as f64) <= target && (acc + count) as f64 > target { + let delta = target - acc as f64; + if count > 1 && delta > 0.0 { + return idx as f64 + delta / count as f64; + } else { + return idx as f64; + } + } + acc += count; + prev_idx = idx; + } + prev_idx as f64 + } + + let q1 = quantile(hist, 0.25, total_count); + let median = quantile(hist, 0.5, total_count); + let q3 = quantile(hist, 0.75, total_count); + let iqr = q3 - q1; + let lower = q1 - 1.5 * iqr; + let upper = q3 + 1.5 * iqr; + + Some((average, q1, median, q3, lower, upper)) +} diff --git a/src/base_sequence_quality.rs b/src/sequence_quality_histogram.rs similarity index 53% rename from src/base_sequence_quality.rs rename to src/sequence_quality_histogram.rs index 1ca4d1e4..38c922aa 100644 --- a/src/base_sequence_quality.rs +++ b/src/sequence_quality_histogram.rs @@ -1,3 +1,5 @@ +use std::any::Any; +use std::collections::HashMap; use std::fmt::{Debug, Formatter}; use std::sync::Arc; @@ -6,6 +8,7 @@ use async_trait::async_trait; use datafusion::arrow::datatypes::{DataType, Field, Schema, SchemaRef}; use datafusion::arrow::record_batch::RecordBatch; use datafusion::catalog::{Session, TableProvider}; +use datafusion::datasource::TableType; use datafusion::error::{DataFusionError, Result}; use datafusion::execution::context::TaskContext; use datafusion::physical_expr::EquivalenceProperties; @@ -15,22 +18,22 @@ use datafusion::physical_plan::{ DisplayAs, DisplayFormatType, ExecutionMode, ExecutionPlan, Partitioning, PlanProperties, SendableRecordBatchStream, }; -use datafusion::prelude::SessionContext; +use datafusion::prelude::{col, SessionContext}; use futures::stream::BoxStream; use futures::{StreamExt, TryStreamExt}; - -pub struct BaseSequenceQualityProvider { +pub struct SequenceQualityHistogramProvider { session: Arc, table_name: String, column_name: String, schema: SchemaRef, } -impl BaseSequenceQualityProvider { +impl SequenceQualityHistogramProvider { pub fn new(session: Arc, table_name: String, column_name: String) -> Self { let schema = Arc::new(Schema::new(vec![ - Field::new("pos", DataType::Int64, false), - Field::new("score", DataType::Int8, false), + Field::new("pos", DataType::UInt64, false), + Field::new("score", DataType::UInt8, false), + Field::new("count", DataType::UInt64, false), ])); Self { session, @@ -41,14 +44,14 @@ impl BaseSequenceQualityProvider { } } -impl Debug for BaseSequenceQualityProvider { +impl Debug for SequenceQualityHistogramProvider { fn fmt(&self, _f: &mut Formatter<'_>) -> std::fmt::Result { Ok(()) } } #[async_trait] -impl TableProvider for BaseSequenceQualityProvider { +impl TableProvider for SequenceQualityHistogramProvider { fn as_any(&self) -> &dyn std::any::Any { self } @@ -57,8 +60,8 @@ impl TableProvider for BaseSequenceQualityProvider { self.schema.clone() } - fn table_type(&self) -> datafusion::datasource::TableType { - datafusion::datasource::TableType::Base + fn table_type(&self) -> TableType { + todo!() } async fn scan( @@ -69,13 +72,12 @@ impl TableProvider for BaseSequenceQualityProvider { _limit: Option, ) -> Result> { let target_partitions = self.session.state().config().target_partitions(); - - Ok(Arc::new(BaseSequenceQualityExec { + Ok(Arc::new(SequenceQualityHistogramExec { schema: self.schema.clone(), - session: Arc::clone(&self.session), + session: self.session.clone(), table_name: self.table_name.clone(), column_name: self.column_name.clone(), - cache: PlanProperties::new( + properties: PlanProperties::new( EquivalenceProperties::new(self.schema.clone()), Partitioning::UnknownPartitioning(target_partitions), ExecutionMode::Bounded, @@ -84,32 +86,32 @@ impl TableProvider for BaseSequenceQualityProvider { } } -pub struct BaseSequenceQualityExec { +pub struct SequenceQualityHistogramExec { schema: SchemaRef, session: Arc, table_name: String, column_name: String, - cache: PlanProperties, + properties: PlanProperties, } -impl Debug for BaseSequenceQualityExec { +impl Debug for SequenceQualityHistogramExec { fn fmt(&self, _f: &mut Formatter<'_>) -> std::fmt::Result { Ok(()) } } -impl DisplayAs for BaseSequenceQualityExec { +impl DisplayAs for SequenceQualityHistogramExec { fn fmt_as(&self, _t: DisplayFormatType, _f: &mut Formatter) -> std::fmt::Result { Ok(()) } } -impl ExecutionPlan for BaseSequenceQualityExec { +impl ExecutionPlan for SequenceQualityHistogramExec { fn name(&self) -> &str { "BaseSequenceQualityExec" } - fn as_any(&self) -> &dyn std::any::Any { + fn as_any(&self) -> &dyn Any { self } @@ -118,7 +120,7 @@ impl ExecutionPlan for BaseSequenceQualityExec { } fn properties(&self) -> &PlanProperties { - &self.cache + &self.properties } fn children(&self) -> Vec<&Arc> { @@ -138,10 +140,10 @@ impl ExecutionPlan for BaseSequenceQualityExec { context: Arc, ) -> Result { let fut = get_stream( - Arc::clone(&self.session), + self.session.clone(), self.table_name.clone(), self.column_name.clone(), - self.cache.partitioning.partition_count(), + self.properties.partitioning.partition_count(), partition, context, self.schema.clone(), @@ -161,23 +163,6 @@ fn decode_score(c: char) -> Option { } } -fn calc_stats(values: &mut Vec) -> (f64, f64, f64, f64, f64, f64) { - values.sort_unstable(); - let n = values.len(); - let average = values.iter().map(|&v| v as f64).sum::() / n as f64; - let median = if n % 2 == 0 { - (values[n / 2 - 1] as f64 + values[n / 2] as f64) / 2.0 - } else { - values[n / 2] as f64 - }; - let q1 = values[n / 4] as f64; - let q3 = values[(3 * n) / 4] as f64; - let iqr = q3 - q1; - let lower = q1 - 1.5 * iqr; - let upper = q3 + 1.5 * iqr; - (average, median, q1, q3, lower, upper) -} - async fn get_stream( session: Arc, table_name: String, @@ -187,61 +172,74 @@ async fn get_stream( context: Arc, new_schema: SchemaRef, ) -> Result { - let table_stream = session.table(table_name).await?; - let plan = table_stream.create_physical_plan().await?; + let df = session + .table(table_name.clone()) + .await? + .select(vec![col(&column_name)])?; + + let plan = df.create_physical_plan().await?; + let repartition_stream = RepartitionExec::try_new(plan, Partitioning::RoundRobinBatch(target_partitions))?; - let partition_stream = repartition_stream.execute(partition, context)?; - let new_schema_out = new_schema.clone(); - let iter = partition_stream.map(move |batch| match batch { - Ok(batch) => { - let index = match batch.schema().index_of(&column_name) { - Ok(idx) => idx, - Err(_) => { - return Err(DataFusionError::Internal(format!( - "Column '{}' not found in schema", - column_name - ))) - }, - }; - let col = batch.column(index); - - // Try to cast to StringArray if possible - let col = arrow::compute::cast(col, &DataType::Utf8) - .map_err(|e| DataFusionError::Internal(format!("Cast error: {e}")))?; - - let col = col - .as_any() - .downcast_ref::() - .ok_or_else(|| DataFusionError::Internal("Expected StringArray".into()))?; - - let mut positions = Vec::new(); - let mut scores = Vec::new(); - - for row in 0..col.len() { - if col.is_null(row) { - continue; - } - let s = col.value(row); - for (pos, byte) in s.bytes().enumerate() { - if let Some(score) = decode_score(byte as char) { - positions.push(pos as i64); - scores.push(score as i8); + + let mut partition_stream = repartition_stream.execute(partition, context)?; + + let mut pos_map: HashMap> = HashMap::new(); + + while let Some(batch_result) = partition_stream.next().await { + let batch = batch_result?; + let col = batch.column(0); // tylko jedna kolumna + + let col = arrow::compute::cast(col, &DataType::Utf8) + .map_err(|e| DataFusionError::Internal(format!("Cast error: {e}")))?; + + let col = col + .as_any() + .downcast_ref::() + .ok_or_else(|| DataFusionError::Internal("Expected StringArray".into()))?; + + for row in 0..col.len() { + if col.is_null(row) { + continue; + } + let s = col.value(row); + for (pos, byte) in s.bytes().enumerate() { + if let Some(score) = decode_score(byte as char) { + let entry = pos_map.entry(pos).or_insert_with(|| vec![0u64; 94]); + if (score as usize) < entry.len() { + entry[score as usize] += 1; } } } + } + } - let pos_array = Arc::new(arrow_array::Int64Array::from(positions)); - let score_array = Arc::new(arrow_array::Int8Array::from(scores)); - let new_batch = - RecordBatch::try_new(new_schema.clone(), vec![pos_array, score_array]).unwrap(); + let mut positions = Vec::new(); + let mut scores = Vec::new(); + let mut counts = Vec::new(); - Ok(new_batch) - }, - Err(e) => Err(e), - }); + for (pos, counts_vec) in pos_map { + for (score, &count) in counts_vec.iter().enumerate() { + if count > 0 { + positions.push(pos as u64); + scores.push(score as u8); + counts.push(count as u64); + } + } + } + let pos_array = Arc::new(arrow_array::UInt64Array::from(positions)); + let score_array = Arc::new(arrow_array::UInt8Array::from(scores)); + let count_array = Arc::new(arrow_array::UInt64Array::from(counts)); + let new_batch = RecordBatch::try_new( + new_schema.clone(), + vec![pos_array, score_array, count_array], + ) + .unwrap(); + + let iter = futures::stream::once(async move { Ok(new_batch) }); let adapted_stream = - RecordBatchStreamAdapter::new(new_schema_out, Box::pin(iter) as BoxStream<_>); + RecordBatchStreamAdapter::new(new_schema.clone(), Box::pin(iter) as BoxStream<_>); + Ok(Box::pin(adapted_stream)) } From 90caa36ced8f53cf7ecc91960ff939a6b727c5f6 Mon Sep 17 00:00:00 2001 From: Jakub Winter <117023023+jwinter3@users.noreply.github.com> Date: Thu, 5 Jun 2025 23:32:26 +0200 Subject: [PATCH 07/13] small refactor --- src/sequence_quality_histogram.rs | 41 ++++++++++++++----------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/src/sequence_quality_histogram.rs b/src/sequence_quality_histogram.rs index 38c922aa..9ea963ed 100644 --- a/src/sequence_quality_histogram.rs +++ b/src/sequence_quality_histogram.rs @@ -20,7 +20,7 @@ use datafusion::physical_plan::{ }; use datafusion::prelude::{col, SessionContext}; use futures::stream::BoxStream; -use futures::{StreamExt, TryStreamExt}; +use futures::TryStreamExt; pub struct SequenceQualityHistogramProvider { session: Arc, table_name: String, @@ -171,7 +171,7 @@ async fn get_stream( partition: usize, context: Arc, new_schema: SchemaRef, -) -> Result { +) -> Result { let df = session .table(table_name.clone()) .await? @@ -182,12 +182,9 @@ async fn get_stream( let repartition_stream = RepartitionExec::try_new(plan, Partitioning::RoundRobinBatch(target_partitions))?; - let mut partition_stream = repartition_stream.execute(partition, context)?; + let partition_stream = repartition_stream.execute(partition, context)?; - let mut pos_map: HashMap> = HashMap::new(); - - while let Some(batch_result) = partition_stream.next().await { - let batch = batch_result?; + let final_pos_map = partition_stream.try_fold(HashMap::new(), |mut pos_map, batch| async move { let col = batch.column(0); // tylko jedna kolumna let col = arrow::compute::cast(col, &DataType::Utf8) @@ -198,27 +195,27 @@ async fn get_stream( .downcast_ref::() .ok_or_else(|| DataFusionError::Internal("Expected StringArray".into()))?; - for row in 0..col.len() { - if col.is_null(row) { - continue; - } - let s = col.value(row); - for (pos, byte) in s.bytes().enumerate() { - if let Some(score) = decode_score(byte as char) { - let entry = pos_map.entry(pos).or_insert_with(|| vec![0u64; 94]); - if (score as usize) < entry.len() { - entry[score as usize] += 1; + col.iter().for_each(|s_opt| { + if let Some(s) = s_opt { + s.bytes().enumerate().for_each(|(pos, byte)| { + if let Some(score) = decode_score(byte as char) { + let entry = pos_map.entry(pos).or_insert_with(|| vec![0u64; 94]); + if (score as usize) < entry.len() { + entry[score as usize] += 1; + } } - } + }); } - } - } + }); + + Ok(pos_map) + }).await?; let mut positions = Vec::new(); let mut scores = Vec::new(); let mut counts = Vec::new(); - for (pos, counts_vec) in pos_map { + for (pos, counts_vec) in final_pos_map { for (score, &count) in counts_vec.iter().enumerate() { if count > 0 { positions.push(pos as u64); @@ -234,7 +231,7 @@ async fn get_stream( new_schema.clone(), vec![pos_array, score_array, count_array], ) - .unwrap(); + .map_err(|e| DataFusionError::Internal(format!("Error creating RecordBatch: {e}")))?; let iter = futures::stream::once(async move { Ok(new_batch) }); From a12b313086a6e86123cf0b80c43ce2e61e559245 Mon Sep 17 00:00:00 2001 From: Jakub Winter <117023023+jwinter3@users.noreply.github.com> Date: Wed, 11 Jun 2025 23:53:24 +0200 Subject: [PATCH 08/13] Add visualization --- docs/notebooks/base_sequence_quality.ipynb | 193 +++++++++++++-------- 1 file changed, 124 insertions(+), 69 deletions(-) diff --git a/docs/notebooks/base_sequence_quality.ipynb b/docs/notebooks/base_sequence_quality.ipynb index ac49dd6f..6c665ef6 100644 --- a/docs/notebooks/base_sequence_quality.ipynb +++ b/docs/notebooks/base_sequence_quality.ipynb @@ -10,21 +10,13 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 27, "id": "58b40aa6", "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/user/.pyenv/versions/3.12.9/lib/python3.12/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", - " from .autonotebook import tqdm as notebook_tqdm\n", - "INFO:polars_bio:Creating BioSessionContext\n" - ] - } - ], + "outputs": [], "source": [ + "import matplotlib.pyplot as plt\n", + "\n", "import polars_bio as pb\n", "import pandas as pd" ] @@ -47,7 +39,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 29, "id": "0420c240", "metadata": {}, "outputs": [ @@ -55,28 +47,91 @@ "name": "stdout", "output_type": "stream", "text": [ - " pos avg q1 median q3 lower upper\n", - "0 47 37.665 37.535714 39.921053 41.060185 32.249008 46.346892\n", - "1 38 37.640 37.964286 40.067308 41.024038 33.374657 45.613668\n", - "2 65 35.995 35.190000 37.433333 39.810000 28.260000 46.740000\n", - "3 3 35.690 35.483333 37.208661 37.600394 32.307743 40.775984\n", - "4 41 37.870 37.678571 40.116071 41.004902 32.689076 45.994398\n", - ".. ... ... ... ... ... ... ...\n", - "96 42 37.780 37.583333 40.139344 40.954918 32.525956 46.012295\n", - "97 43 37.775 38.114583 40.126866 40.869403 33.982354 45.001632\n", - "98 15 38.725 38.226190 40.352459 41.168033 33.813427 45.580796\n", - "99 46 37.790 37.479167 39.975000 41.042453 32.134237 46.387382\n", - "100 24 38.265 38.397059 40.095745 41.125000 34.305147 45.216912\n", + " pos avg q1 median q3 lower upper\n", + "77 0 30.135 31.213636 33.722222 34.482143 26.310877 39.384903\n", + "94 1 31.210 31.275000 34.086364 34.538636 26.379545 39.434091\n", + "51 2 32.015 31.356383 34.094595 34.542793 26.576768 39.322408\n", + "22 3 35.690 35.483333 37.208661 37.600394 32.307743 40.775984\n", + "48 4 35.680 35.552885 37.208661 37.600394 32.481621 40.671657\n", + ".. ... ... ... ... ... ... ...\n", + "67 96 31.315 32.795455 34.824324 35.508824 28.725401 39.578877\n", + "57 97 30.670 31.575000 34.890625 35.557229 25.601657 41.530572\n", + "2 98 31.550 32.107143 34.890625 35.537791 26.961171 40.683762\n", + "45 99 31.250 32.093750 34.712500 35.455357 27.051339 40.497768\n", + "27 100 31.105 31.250000 34.154762 35.250000 25.250000 41.250000\n", "\n", "[101 rows x 7 columns]\n" ] } ], "source": [ - "result = pb.base_sequence_quality(\"example.fastq\", output_type=\"pandas.DataFrame\", target_partitions=2)\n", + "result = pb.base_sequence_quality(\"example.fastq\", output_type=\"pandas.DataFrame\", target_partitions=2).sort_values(by=\"pos\")\n", "print(result)" ] }, + { + "cell_type": "markdown", + "id": "d8eb42e4", + "metadata": {}, + "source": [ + "##### Results visualization\n" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "7322aae3", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABM8AAAHRCAYAAAB9856CAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjMsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvZiW1igAAAAlwSFlzAAAPYQAAD2EBqD+naQAA1SBJREFUeJzs3Xlc1NX+x/HXsA07KKCgoriDu2CaaWlpaZZlebPNysyWW7bZ/ru39VbWLctWszK10DbTbmVlWi5JruCuKC64griB7Ov8/hiZRBb5AgMDvJ+Phw/lO2fOnPnODM6853POMVksFgsiIiIiIiIiIiJSilNdD0BERERERERERMRRKTwTEREREREREREph8IzERERERERERGRcig8ExERERERERERKYfCMxERERERERERkXIoPBMRERERERERESmHwjMREREREREREZFyKDwTEREREREREREph8IzERERERERERGRcig8ExERkTrzwgsvYDKZOH78eF0PRRoxk8nECy+8YPt51qxZmEwmEhMT62xMIiIi4jgUnomIiIiInMeHH37IrFmz6noYIiIiUgcUnomIiIiInOW2224jOzubNm3a2I4pPBMREWm8XOp6ACIiIiIijsTZ2RlnZ+e6HoaIiIg4CFWeiYiISJ07fvw4Y8aMwdfXl4CAAB5++GFycnJKtJk5cyaXXXYZzZo1w2w206VLF6ZNm1aqr/Xr1zNs2DACAwPx8PCgbdu2jB8/vkSboqIipk6dSteuXXF3d6d58+bce++9nDp16rxjTU5O5s4776RVq1aYzWZCQkK49tprS62P9csvv3DxxRfj5eWFj48PV111Fdu2bSvV3/fff0+3bt1wd3enW7duLFiwgHHjxhEWFmZrs2zZMkwmE8uWLStx3cTEREwmU6mKqPj4eP7xj3/QtGlT3N3d6dOnDz/88EOJNsXresXExDBp0iSCgoLw8vLiuuuu49ixY6XG+csvvzBo0CB8fHzw9fXlggsuYO7cuSXarFmzhuHDh+Pn54enpyeDBg0iJibmvOcU4NChQ4waNQovLy+aNWvGo48+yqJFi0rd77CwMMaNG1fq+oMHD2bw4MG2n/Py8njuueeIiorCz88PLy8vLr74YpYuXXresZy75llYWBjbtm1j+fLlmEwmTCYTgwcPZu/evZhMJt5+++1Sffz111+YTCa+/PLLSt1/ERERcVyqPBMREZE6N2bMGMLCwpg8eTKrV6/m3Xff5dSpU3z++ee2NtOmTaNr165cc801uLi48OOPP3L//fdTVFTEAw88AEBKSgpXXHEFQUFBPP300/j7+5OYmMj8+fNL3N69997LrFmzuPPOO3nooYfYt28f77//Phs2bCAmJgZXV9dyxzp69Gi2bdvGgw8+SFhYGCkpKSxevJgDBw7YAq8vvviCO+64g2HDhvH666+TlZXFtGnTGDhwIBs2bLC1++233xg9ejRdunRh8uTJnDhxwhbMVdW2bdsYMGAALVu25Omnn8bLy4tvvvmGUaNG8d1333HdddeVaP/ggw/SpEkTnn/+eRITE5k6dSoTJ07k66+/trWZNWsW48ePp2vXrjzzzDP4+/uzYcMGfv31V2655RYA/vjjD6688kqioqJ4/vnncXJysgWef/75J3379i13zNnZ2QwZMoQDBw7w0EMP0aJFC7744gv++OOPKp+H06dP8+mnn3LzzTdz9913k56ezowZMxg2bBhr166lV69ele5r6tSpPPjgg3h7e/Ovf/0LgObNm9OuXTsGDBjAnDlzePTRR0tcZ86cOfj4+HDttddW+T6IiIiIg7CIiIiI1JHnn3/eAliuueaaEsfvv/9+C2DZtGmT7VhWVlap6w8bNszSrl07288LFiywAJZ169aVe5t//vmnBbDMmTOnxPFff/21zONnO3XqlAWwvPHGG+W2SU9Pt/j7+1vuvvvuEseTk5Mtfn5+JY736tXLEhISYklNTbUd++233yyApU2bNrZjS5cutQCWpUuXluhz3759FsAyc+ZM27EhQ4ZYunfvbsnJybEdKyoqslx00UWWjh072o7NnDnTAliGDh1qKSoqsh1/9NFHLc7OzrYxpaamWnx8fCz9+vWzZGdnl7j94usVFRVZOnbsaBk2bFiJvrKysixt27a1XH755eWeL4vFYpk6daoFsHzzzTe2Y5mZmZYOHTqUut9t2rSx3HHHHaX6GDRokGXQoEG2nwsKCiy5ubkl2pw6dcrSvHlzy/jx40scByzPP/98qXOzb98+27GuXbuW6L/Y9OnTLYBlx44dtmN5eXmWwMDAMscpIiIi9Y+mbYqIiEidK64cK/bggw8C8PPPP9uOeXh42P6dlpbG8ePHGTRoEHv37iUtLQ0Af39/AH766Sfy8/PL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7rvvth0vKCjAz8+v3HHWJIVnIiIiIg3cuWGOpu3VX0aCOU9PzxKX67EXqX9MJpOhqZN1ZcaMGRQUFNCiRQvbMYvFgtls5v3338fPz49bb72VQYMGkZKSwuLFi/Hw8GD48OEAtnXCFi5cSMuWLUv0fe4i+2eHVQCPP/44ixcv5s0336RDhw54eHjwj3/8w9CC+RkZGYSEhLBs2bJSlxVXj9W1c8Mok8lUKuA699xkZGQQFRVVYmpnsaCgoCqPZcKECQwbNoyFCxfy22+/MXnyZKZMmcKDDz6Ih4dHlfs929n3pfj58cknn5QI+gCcnSsf8laH478KRUREREQaKK1LJiL1XUFBAZ9//jlTpkzhiiuuKHHZqFGj+PLLL7nvvvu46KKLCA0N5euvv+aXX37hhhtusAVCXbp0wWw2c+DAgRJTNCsjJiaGcePG2dZOy8jIKLEgfufOnSkoKGDDhg22qey7d+/m1KlTtjaRkZEkJyfj4uJCWFhYpW43IiKCWbNmkZmZaQt6YmJicHJysi3Wb8Tq1atta7SdOnWKXbt22b4sqarIyEi+/vprmjVrhq+vb5ltQkJCWLNmDZdccglgfTwrM8U/NDSU++67j/vuu49nnnmGTz75hAcffJAePXowe/Zs8vPzSwV+vr6+tGjRgpiYmBKPc0xMDH379i33tpo3b06LFi3Yu3cvt956a2Xvfo1SeCYiIiIiUkccaV0yI5sRiIgU++mnnzh16hR33XVXqSl0o0ePZsaMGdx3332AddfNjz76iF27drF06VJbOx8fHx5//HEeffRRioqKGDhwIGlpacTExODr61vhmlYdO3Zk/vz5jBw5EpPJxLPPPktRUZHt8vDwcIYOHco999zDtGnTcHV15bHHHsPDw8O2DtjQoUPp378/o0aN4r///S+dOnXiyJEjLFy4kOuuu67UVFGAW2+9leeff5477riDF154gWPHjvHggw9y2223GZ6yCda13AICAmjevDn/+te/CAwMZNSoUYb7OXeMb7zxBtdee61th8v9+/czf/58nnzySVq1asXDDz/Ma6+9RseOHQkPD+ett94iNTW1wn4feeQRrrzySjp16sSpU6dYunSpLeibOHEi7733HjfddBPPPPMMfn5+rF69mr59+9K5c2eeeOIJnn/+edq3b0+vXr2YOXMmGzduLLM67mwvvvgiDz30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RDtXV9cSP5tMJoqKiqp8uzWtMuPz8vKy/dte5zM0NJSdO3eyZMkSFi9ezP33388bb7zB8uXLa2yjhrPvB1jvy8iRI8usiAsJCamR26wqhWciIiIi9YymEVbfububKnh0HPW1srK+jtuedE4ap+HDh5OXl4fJZLItAn+2Ll26YDabOXDgQLmVSxERESUWygdYvXp1hbcbExPDuHHjuO666wBrEHO+RfHPp3379rY1udq0aQNAfn4+69at45FHHjHc37n3YfXq1bb/i6rKXucTrDuajhw5kpEjR/LAAw8QHh7Oli1b6N69O0VFRSxfvtw2bfPc2/vuu++wWCy26rOYmBh8fHwq3JE0MjKS7777jrCwMIfbQdSxRiMiIiIi56VphNKQGa2sNLJ+nT2pIrQ0nZPGydnZ2Tal0dnZudTlPj4+PP744zz66KMUFRUxcOBA0tLSiImJwdfXlzvuuIP77ruPKVOm8MQTTzBhwgRiY2PL3cWyWMeOHZk/fz4jR47EZDLx7LPPVruizMvLi3/+85888cQTNG3alNatW/Pf//6XrKws7rrrLsP9xcTE8N///pdRo0axePFivv32WxYuXFitMdrrfM6aNYvCwkL69euHp6cn0dHReHh40KZNGwICArjjjjsYP3487777Lj179mT//v2kpKQwZswY7r//fqZOncqDDz7IxIkT2blzJ88//zyTJk2yrXdWlgceeIBPPvmEm2++mSeffJKmTZuye/duvvrqKz799NMyn0+1ReGZiIiIiFTZucGFqkqkuoxWVhpZv86eVBFams5J4+Xr61vh5f/5z38ICgpi8uTJ7N27F39/fyIjI/m///s/AFq3bs13333Ho48+ynvvvUffvn159dVXGT9+fLl9vvXWW4wfP56LLrqIwMBAnnrqKU6fPl3t+/Laa69RVFTEbbfdRnp6On369GHRokU0adLEcF+PPfYY69ev58UXX8TX15e33nqrzOo8o+xxPv39/XnttdeYNGkShYWFdO/enR9//JGAgAAApk2bxv/93/9x//33c+LECVq3bm27vZYtW/Lzzz/zxBNP0LNnT5o2bcpdd93Fv//97wrvR4sWLYiJieGpp57iiiuuIDc3lzZt2jB8+PAKQ7faoPBMRERERKrs3OBCVSVSXUYrKx1l/TpVhJamc9J4nK+K6fvvvy/xs8lk4uGHH+bh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yMPDQz4+PmrXrp1efvll5eXlXfbYUVFRSk5OVnBwsCTrBtaWLVv08MMPX/bXszN69Gj98ssvFfo13GHZsmU6ceKExowZU67jdu7cWf369dNf//rXch0XAABUXzTPAABAtTVs2DAlJydr3759mjJliqZPn67XXnvtssf18fFRaGioPDw8bHMNGzaUv7//ZX89O35+fmrUqFG5jpmfn6+CgoJyHbOs/v73v+u+++6Tp2f5P1297777NHv27HJppAIAgOqP5hkAAKi2fH19FRoaqquuukqPPfaYhgwZomXLlkmSzp49q3HjxqlevXry9/fX8OHDtW/fPsfnHjp0SCNGjFC9evUUEBCgLl266Ouvv5ZU/LTNVatW6b777lNaWppjp9v06dMllTxt8/Dhwxo5cqQCAwMVFBSkO+64QydOnHB8fPr06erZs6c++OADtWrVSsHBwRozZowyMjIsv0fnXW+XM8ayZcvUuXNn+fr66vDhw8rOztbUqVPVrFkzBQQEqG/fvlq1apXj806fPq0777xTzZo1k7+/v7p166ZFixYVG/v8+fMaN26cAgMD1aRJE73++uuW8yhy6tQp/fDDDxoxYkSJjyUnJ2v48OHy8/NTmzZt9Mknnzg+lpSUJA8PDy1evFhRUVGqXbu2unbtqtWrVxcb49prr9WZM2dKvB8AAMAMzTMAAFBj+Pn5KScnR1LhaZ0///yzli1bpg0bNsgwDF1//fXKzc2VJE2YMEHZ2dlas2aNdu7cqVdeeUWBgYElxoyKitIbb7yhoKAgJScnKzk5WVOnTi2RKygo0MiRIx1Nm++++06//vqrRo8eXSx34MABff7551q+fLmWL1+u1atXa9asWWX6Pi9ljMzMTL3yyiv617/+pd27d6tRo0aaOHGiNmzYoMWLF2vHjh26/fbbNWzYMEeT8cKFC4qIiNBXX32lXbt26eGHH9Y999yjzZs3O8Z9+umntXr1an3xxRf69ttvtWrVKsXHx9vOZe3atfL391enTp1KfOzFF1/UqFGjtH37dt19990aM2aMEhISimWefvppTZkyRVu3blVkZKRGjBih06dPOz7u4+Ojnj176qeffnL5swQAAKjl7gkAAABUNMMwtHLlSq1YsUKTJk3Svn37tGzZMq1bt05RUVGSpI8++kgtWrTQ559/rttvv12HDx/WqFGj1K1bN0lSmzZtTMf28fFRcHCwPDw8FBoaajmHlStXaufOnTp48KBatGghSVqwYIG6dOmiLVu2qHfv3pIKm2zz5s1TnTp1JEn33HOPVq5cqRkzZpT6+72UMXJzc/Xuu++qR48ekgp3yc2dO1eHDx9W06ZNJUlTp07VN998o7lz5+ovf/mLmjVrVqxROGnSJK1YsUIff/yx+vTpo3PnzmnOnDn68MMPNXjwYEnS/Pnz1bx5c9v5Hzp0SI0bNzY9ZfP222/Xgw8+KEn605/+pO+++05vvfWW3n33XUdm4sSJGjVqlCRp9uzZ+uabbzRnzhz98Y9/dGSaNm2qQ4cO2c4DAABAonkGAACqseXLlyswMFC5ubkqKCjQXXfdpenTp2vlypWqVauW+vbt68iGhISoY8eOjl1Mf/jDH/TYY4/p22+/1ZAhQzRq1Ch17979kueSkJCgFi1aOBpnUuHF6+vWrauEhARH86xVq1aOppckNWnSRCdPnizT17qUMXx8fIp9fzt37lR+fr46dOhQLJedna2QkBBJhddG+8tf/qKPP/5Yx44dU05OjrKzsx3XeTtw4IBycnKK/Zzr16+vjh072s4lKytLtWvXNv1YZGRkibe3bdtmmalVq5auvvrqErvT/Pz8lJmZaTsPAAAAieYZAACoxgYNGqTZs2fLx8dHTZs2Va1apX/q8+CDD2ro0KH66quv9O2332rmzJl6/fXXNWnSpAqcseTt7V3sbQ8PjzJfvP9SxvDz8yt2A4Rz587Jy8tLcXFx8vLyKpYtOn31tdde05tvvqk33nhD3bp1U0BAgCZPnuw4NfZSNWjQQGfPnr2sMVw5c+aM2rZtW6FfAwAAVA9c8wwAAFRbAQEBateunVq2bFmscdapUyfl5eVp06ZNjvedPn1ae/fuVefOnR3va9GihR599FEtXbpUU6ZM0T//+U/Tr+Pj46P8/HzbuXTq1ElHjhzRkSNHHO/bs2ePUlNTi33NyqJXr17Kz8/XyZMn1a5du2L/FZ2eum7dOo0cOVJjx45Vjx491KZNG/3yyy+OMdq2bStvb+9iP+ezZ88Wy1h97ZSUFNMG2saNG0u87XxttIszeXl5iouLK5HZtWuXevXq5eKnAAAAQPMMAADUQO3bt9fIkSP10EMPae3atdq+fbvGjh2rZs2aaeTIkZKkyZMna8WKFTp48KDi4+P1448/ml7AXio8TfLcuXNauXKlfvvtN9PTAYcMGaJu3brp7rvvVnx8vDZv3qxx48Zp4MCBuvrqqyv0+70UHTp00N13361x48Zp6dKlOnjwoDZv3qyZM2fqq6++klT4c/zuu++0fv16JSQk6JFHHil299DAwEA98MADevrpp/XDDz9o165dGj9+vOm1zC7Wq1cvNWjQQOvWrSvxsSVLluj999/XL7/8omnTpmnz5s2aOHFiscw777yjzz77TImJiZowYYLOnj2r+++/3/HxpKQkHTt2TEOGDLmcHxEAAKghaJ4BAIAaae7cuYqIiNCNN96oyMhIGYahr7/+2nHKY35+viZMmKBOnTpp2LBh6tChQ7GL0l8sKipKjz76qEaPHq2GDRvq1VdfLZHx8PDQF198oXr16mnAgAEaMmSI2rRpo3//+98V+n1ejrlz52rcuHGaMmWKOnbsqJtvvllbtmxRy5YtJUkvvPCCwsPDNXToUMXGxio0NFQ333xzsTFee+019e/fXyNGjNCQIUMUExOjiIgI26/r5eWl++67Tx999FGJj7300ktavHixunfvrgULFmjRokUldu7NmjVLs2bNUo8ePbR27VotW7ZMDRo0cHx80aJFuu6663TVVVdd4k8GAADUJB6GYRjungQAAABwsZSUFHXp0kXx8fGlbnIlJSWpdevW2rp1q3r27GmaycnJUfv27bVw4UJFR0eX44wBAEB1xc4zAAAAVDqhoaGaM2eODh8+XK7jHj58WM8//zyNMwAAUGrcbRMAAACVkvMpoOWh6KYHAAAApcVpmwAAAAAAAIAFTtsEAAAAAAAALNA8AwAAAAAAACzQPAMAAAAAAAAs0DwDAAAAAAAALNA8AwAAAAAAACzQPAMAAAAAAAAs0DwDAAAAAAAALNA8AwAAAAAAACz8f2NzusDY9TvPAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "boxes = [\n", + " {\n", + " \"label\": int(row[\"pos\"]),\n", + " \"whislo\": row[\"lower\"],\n", + " \"q1\": row[\"q1\"],\n", + " \"med\": row[\"median\"],\n", + " \"q3\": row[\"q3\"],\n", + " \"whishi\": row[\"upper\"],\n", + " }\n", + " for _, row in result.iterrows()\n", + "]\n", + "\n", + "\n", + "fig, ax = plt.subplots()\n", + "fig.set_size_inches(15, 5)\n", + "\n", + "\n", + "plot = ax.plot(result[\"pos\"] + 1, result[\"avg\"])\n", + "box_plot = ax.bxp(boxes, showfliers=False)\n", + "\n", + "ax.set_title(\"base sequence quality\")\n", + "ax.set_ylabel(\"Phred score\")\n", + "ax.set_xlabel(\"Position in read (bp)\")\n", + "\n", + "ax.legend(\n", + " [plot[0], box_plot[\"medians\"][0]],\n", + " [\"Average of phred score\", \"Median of phred score\"],\n", + ")\n", + "\n", + "\n", + "for label in ax.get_xticklabels():\n", + " label.set_fontsize(6)\n", + "\n", + "\n", + "plt.show()" + ] + }, { "cell_type": "markdown", "id": "9886c394", @@ -143,7 +198,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 20, "id": "a2cb9c97", "metadata": {}, "outputs": [ @@ -157,7 +212,7 @@ " white-space: pre-wrap;\n", "}\n", "\n", - "shape: (101, 7)
posavgq1medianq3lowerupper
u64f64f64f64f64f64f64
4437.56537.7187540.13392941.02403832.76081745.981971
2738.4438.23437540.2741.20703133.77539145.666016
7233.26533.86111135.687537.92391327.76690844.018116
8631.81533.36538535.13291135.76265829.76947439.358569
9032.27533.18333334.98684235.6396129.49891839.324026
3438.20537.97916740.15957441.16803333.19586745.951332
8432.41533.2535.18243235.8547329.34290539.761824
4937.2136.67857139.64583340.76388930.55059546.891865
6336.2535.21590938.02631640.27527.62727347.863636
8032.6132.62535.28947436.42045526.93181842.113636
" + "shape: (101, 7)
posavgq1medianq3lowerupper
u64f64f64f64f64f64f64
8832.06533.06818235.0687535.69062529.13451739.62429
4337.77538.11458340.12686640.86940333.98235445.001632
4937.2136.67857139.64583340.76388930.55059546.891865
6735.9634.72368436.97222239.8127.09421147.439474
3638.1138.17857140.2540.96071434.00535745.133929
7430.8332.7535.53260937.48529425.64705944.588235
8332.0333.2535.2848135.91455729.25316539.911392
8132.7633.51470635.29710136.07352929.67647139.911765
3738.038.21527840.08035740.9687534.08506945.098958
937.3637.3437539.01470639.50245134.10569942.740502
" ], "text/plain": [ "shape: (101, 7)\n", @@ -166,21 +221,21 @@ "│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │\n", "│ u64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 │\n", "╞═════╪════════╪═══════════╪═══════════╪═══════════╪═══════════╪═══════════╡\n", - "│ 44 ┆ 37.565 ┆ 37.71875 ┆ 40.133929 ┆ 41.024038 ┆ 32.760817 ┆ 45.981971 │\n", - "│ 27 ┆ 38.44 ┆ 38.234375 ┆ 40.27 ┆ 41.207031 ┆ 33.775391 ┆ 45.666016 │\n", - "│ 72 ┆ 33.265 ┆ 33.861111 ┆ 35.6875 ┆ 37.923913 ┆ 27.766908 ┆ 44.018116 │\n", - "│ 86 ┆ 31.815 ┆ 33.365385 ┆ 35.132911 ┆ 35.762658 ┆ 29.769474 ┆ 39.358569 │\n", - "│ 90 ┆ 32.275 ┆ 33.183333 ┆ 34.986842 ┆ 35.63961 ┆ 29.498918 ┆ 39.324026 │\n", - "│ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … │\n", - "│ 34 ┆ 38.205 ┆ 37.979167 ┆ 40.159574 ┆ 41.168033 ┆ 33.195867 ┆ 45.951332 │\n", - "│ 84 ┆ 32.415 ┆ 33.25 ┆ 35.182432 ┆ 35.85473 ┆ 29.342905 ┆ 39.761824 │\n", + "│ 88 ┆ 32.065 ┆ 33.068182 ┆ 35.06875 ┆ 35.690625 ┆ 29.134517 ┆ 39.62429 │\n", + "│ 43 ┆ 37.775 ┆ 38.114583 ┆ 40.126866 ┆ 40.869403 ┆ 33.982354 ┆ 45.001632 │\n", "│ 49 ┆ 37.21 ┆ 36.678571 ┆ 39.645833 ┆ 40.763889 ┆ 30.550595 ┆ 46.891865 │\n", - "│ 63 ┆ 36.25 ┆ 35.215909 ┆ 38.026316 ┆ 40.275 ┆ 27.627273 ┆ 47.863636 │\n", - "│ 80 ┆ 32.61 ┆ 32.625 ┆ 35.289474 ┆ 36.420455 ┆ 26.931818 ┆ 42.113636 │\n", + "│ 67 ┆ 35.96 ┆ 34.723684 ┆ 36.972222 ┆ 39.81 ┆ 27.094211 ┆ 47.439474 │\n", + "│ 36 ┆ 38.11 ┆ 38.178571 ┆ 40.25 ┆ 40.960714 ┆ 34.005357 ┆ 45.133929 │\n", + "│ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … │\n", + "│ 74 ┆ 30.83 ┆ 32.75 ┆ 35.532609 ┆ 37.485294 ┆ 25.647059 ┆ 44.588235 │\n", + "│ 83 ┆ 32.03 ┆ 33.25 ┆ 35.28481 ┆ 35.914557 ┆ 29.253165 ┆ 39.911392 │\n", + "│ 81 ┆ 32.76 ┆ 33.514706 ┆ 35.297101 ┆ 36.073529 ┆ 29.676471 ┆ 39.911765 │\n", + "│ 37 ┆ 38.0 ┆ 38.215278 ┆ 40.080357 ┆ 40.96875 ┆ 34.085069 ┆ 45.098958 │\n", + "│ 9 ┆ 37.36 ┆ 37.34375 ┆ 39.014706 ┆ 39.502451 ┆ 34.105699 ┆ 42.740502 │\n", "└─────┴────────┴───────────┴───────────┴───────────┴───────────┴───────────┘" ] }, - "execution_count": 4, + "execution_count": 20, "metadata": {}, "output_type": "execute_result" } @@ -199,7 +254,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 23, "id": "1899ca01", "metadata": {}, "outputs": [ @@ -221,7 +276,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "200rows [00:00, 62156.25rows/s]\n" + "200rows [00:00, 63535.62rows/s]\n" ] }, { @@ -234,7 +289,7 @@ " white-space: pre-wrap;\n", "}\n", "\n", - "shape: (101, 7)
posavgq1medianq3lowerupper
u64f64f64f64f64f64f64
6436.09535.06481537.740.14583327.44328747.767361
435.6835.55288537.20866137.60039432.48162140.671657
6835.9134.94047636.93181839.53947428.0419846.43797
7233.26533.86111135.687537.92391327.76690844.018116
5836.7735.33823538.9062540.71710527.2699348.78541
2637.85538.02884640.07894740.95175433.64448445.336117
937.3637.3437539.01470639.50245134.10569942.740502
7133.00533.79166735.85135138.58333326.60416745.770833
1137.7137.78448339.09459539.54279335.14701842.180258
2438.26538.39705940.09574541.12534.30514745.216912
" + "shape: (101, 7)
posavgq1medianq3lowerupper
u64f64f64f64f64f64f64
5637.5936.82692339.39655240.89583330.72355846.999199
1638.4838.19791740.32456141.18145233.72261445.656754
8332.0333.2535.2848135.91455729.25316539.911392
9231.83532.22916735.00588235.59117627.18615240.634191
2637.85538.02884640.07894740.95175433.64448445.336117
9730.6731.57534.89062535.55722925.60165741.530572
4637.7937.47916739.97541.04245332.13423746.387382
8731.91532.5535.08783835.76013527.73479740.575338
7932.4631.9687535.20535736.437525.26562543.140625
9531.42532.19444434.89393935.53779127.17942540.55281
" ], "text/plain": [ "shape: (101, 7)\n", @@ -243,21 +298,21 @@ "│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │\n", "│ u64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 │\n", "╞═════╪════════╪═══════════╪═══════════╪═══════════╪═══════════╪═══════════╡\n", - "│ 64 ┆ 36.095 ┆ 35.064815 ┆ 37.7 ┆ 40.145833 ┆ 27.443287 ┆ 47.767361 │\n", - "│ 4 ┆ 35.68 ┆ 35.552885 ┆ 37.208661 ┆ 37.600394 ┆ 32.481621 ┆ 40.671657 │\n", - "│ 68 ┆ 35.91 ┆ 34.940476 ┆ 36.931818 ┆ 39.539474 ┆ 28.04198 ┆ 46.43797 │\n", - "│ 72 ┆ 33.265 ┆ 33.861111 ┆ 35.6875 ┆ 37.923913 ┆ 27.766908 ┆ 44.018116 │\n", - "│ 58 ┆ 36.77 ┆ 35.338235 ┆ 38.90625 ┆ 40.717105 ┆ 27.26993 ┆ 48.78541 │\n", - "│ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … │\n", + "│ 56 ┆ 37.59 ┆ 36.826923 ┆ 39.396552 ┆ 40.895833 ┆ 30.723558 ┆ 46.999199 │\n", + "│ 16 ┆ 38.48 ┆ 38.197917 ┆ 40.324561 ┆ 41.181452 ┆ 33.722614 ┆ 45.656754 │\n", + "│ 83 ┆ 32.03 ┆ 33.25 ┆ 35.28481 ┆ 35.914557 ┆ 29.253165 ┆ 39.911392 │\n", + "│ 92 ┆ 31.835 ┆ 32.229167 ┆ 35.005882 ┆ 35.591176 ┆ 27.186152 ┆ 40.634191 │\n", "│ 26 ┆ 37.855 ┆ 38.028846 ┆ 40.078947 ┆ 40.951754 ┆ 33.644484 ┆ 45.336117 │\n", - "│ 9 ┆ 37.36 ┆ 37.34375 ┆ 39.014706 ┆ 39.502451 ┆ 34.105699 ┆ 42.740502 │\n", - "│ 71 ┆ 33.005 ┆ 33.791667 ┆ 35.851351 ┆ 38.583333 ┆ 26.604167 ┆ 45.770833 │\n", - "│ 11 ┆ 37.71 ┆ 37.784483 ┆ 39.094595 ┆ 39.542793 ┆ 35.147018 ┆ 42.180258 │\n", - "│ 24 ┆ 38.265 ┆ 38.397059 ┆ 40.095745 ┆ 41.125 ┆ 34.305147 ┆ 45.216912 │\n", + "│ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … │\n", + "│ 97 ┆ 30.67 ┆ 31.575 ┆ 34.890625 ┆ 35.557229 ┆ 25.601657 ┆ 41.530572 │\n", + "│ 46 ┆ 37.79 ┆ 37.479167 ┆ 39.975 ┆ 41.042453 ┆ 32.134237 ┆ 46.387382 │\n", + "│ 87 ┆ 31.915 ┆ 32.55 ┆ 35.087838 ┆ 35.760135 ┆ 27.734797 ┆ 40.575338 │\n", + "│ 79 ┆ 32.46 ┆ 31.96875 ┆ 35.205357 ┆ 36.4375 ┆ 25.265625 ┆ 43.140625 │\n", + "│ 95 ┆ 31.425 ┆ 32.194444 ┆ 34.893939 ┆ 35.537791 ┆ 27.179425 ┆ 40.55281 │\n", "└─────┴────────┴───────────┴───────────┴───────────┴───────────┴───────────┘" ] }, - "execution_count": 5, + "execution_count": 23, "metadata": {}, "output_type": "execute_result" } @@ -278,7 +333,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 24, "id": "7830b8aa", "metadata": {}, "outputs": [ @@ -287,7 +342,7 @@ "output_type": "stream", "text": [ "INFO:polars_bio:Table: example registered for path: ./example.fastq\n", - "200rows [00:00, 66234.57rows/s]" + "200rows [00:00, 88450.11rows/s]" ] }, { @@ -314,7 +369,7 @@ " white-space: pre-wrap;\n", "}\n", "\n", - "shape: (101, 7)
posavgq1medianq3lowerupper
u64f64f64f64f64f64f64
335.6935.48333337.20866137.60039432.30774340.775984
2938.59538.3540.25833341.0937534.23437545.209375
4437.56537.7187540.13392941.02403832.76081745.981971
7630.26530.91666735.41489437.07352921.68137346.308824
6735.9634.72368436.97222239.8127.09421147.439474
1538.72538.2261940.35245941.16803333.81342745.580796
2637.85538.02884640.07894740.95175433.64448445.336117
3937.89538.02777840.12540.85661833.78451845.099877
9730.6731.57534.89062535.55722925.60165741.530572
5137.5336.7187539.44736841.02403830.26081747.481971
" + "shape: (101, 7)
posavgq1medianq3lowerupper
u64f64f64f64f64f64f64
131.2131.27534.08636434.53863626.37954539.434091
6436.09535.06481537.740.14583327.44328747.767361
4337.77538.11458340.12686640.86940333.98235445.001632
1638.4838.19791740.32456141.18145233.72261445.656754
837.62537.53571439.11842139.55482534.50704942.58349
2138.44538.3706940.13492140.92460334.53981944.755473
7831.4631.687535.26363636.48684224.48848743.685855
3638.1138.17857140.2540.96071434.00535745.133929
7531.0630.95833335.41836737.28333321.47083346.770833
4137.8737.67857140.11607141.00490232.68907645.994398
" ], "text/plain": [ "shape: (101, 7)\n", @@ -323,21 +378,21 @@ "│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │\n", "│ u64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 │\n", "╞═════╪════════╪═══════════╪═══════════╪═══════════╪═══════════╪═══════════╡\n", - "│ 3 ┆ 35.69 ┆ 35.483333 ┆ 37.208661 ┆ 37.600394 ┆ 32.307743 ┆ 40.775984 │\n", - "│ 29 ┆ 38.595 ┆ 38.35 ┆ 40.258333 ┆ 41.09375 ┆ 34.234375 ┆ 45.209375 │\n", - "│ 44 ┆ 37.565 ┆ 37.71875 ┆ 40.133929 ┆ 41.024038 ┆ 32.760817 ┆ 45.981971 │\n", - "│ 76 ┆ 30.265 ┆ 30.916667 ┆ 35.414894 ┆ 37.073529 ┆ 21.681373 ┆ 46.308824 │\n", - "│ 67 ┆ 35.96 ┆ 34.723684 ┆ 36.972222 ┆ 39.81 ┆ 27.094211 ┆ 47.439474 │\n", + "│ 1 ┆ 31.21 ┆ 31.275 ┆ 34.086364 ┆ 34.538636 ┆ 26.379545 ┆ 39.434091 │\n", + "│ 64 ┆ 36.095 ┆ 35.064815 ┆ 37.7 ┆ 40.145833 ┆ 27.443287 ┆ 47.767361 │\n", + "│ 43 ┆ 37.775 ┆ 38.114583 ┆ 40.126866 ┆ 40.869403 ┆ 33.982354 ┆ 45.001632 │\n", + "│ 16 ┆ 38.48 ┆ 38.197917 ┆ 40.324561 ┆ 41.181452 ┆ 33.722614 ┆ 45.656754 │\n", + "│ 8 ┆ 37.625 ┆ 37.535714 ┆ 39.118421 ┆ 39.554825 ┆ 34.507049 ┆ 42.58349 │\n", "│ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … │\n", - "│ 15 ┆ 38.725 ┆ 38.22619 ┆ 40.352459 ┆ 41.168033 ┆ 33.813427 ┆ 45.580796 │\n", - "│ 26 ┆ 37.855 ┆ 38.028846 ┆ 40.078947 ┆ 40.951754 ┆ 33.644484 ┆ 45.336117 │\n", - "│ 39 ┆ 37.895 ┆ 38.027778 ┆ 40.125 ┆ 40.856618 ┆ 33.784518 ┆ 45.099877 │\n", - "│ 97 ┆ 30.67 ┆ 31.575 ┆ 34.890625 ┆ 35.557229 ┆ 25.601657 ┆ 41.530572 │\n", - "│ 51 ┆ 37.53 ┆ 36.71875 ┆ 39.447368 ┆ 41.024038 ┆ 30.260817 ┆ 47.481971 │\n", + "│ 21 ┆ 38.445 ┆ 38.37069 ┆ 40.134921 ┆ 40.924603 ┆ 34.539819 ┆ 44.755473 │\n", + "│ 78 ┆ 31.46 ┆ 31.6875 ┆ 35.263636 ┆ 36.486842 ┆ 24.488487 ┆ 43.685855 │\n", + "│ 36 ┆ 38.11 ┆ 38.178571 ┆ 40.25 ┆ 40.960714 ┆ 34.005357 ┆ 45.133929 │\n", + "│ 75 ┆ 31.06 ┆ 30.958333 ┆ 35.418367 ┆ 37.283333 ┆ 21.470833 ┆ 46.770833 │\n", + "│ 41 ┆ 37.87 ┆ 37.678571 ┆ 40.116071 ┆ 41.004902 ┆ 32.689076 ┆ 45.994398 │\n", "└─────┴────────┴───────────┴───────────┴───────────┴───────────┴───────────┘" ] }, - "execution_count": 6, + "execution_count": 24, "metadata": {}, "output_type": "execute_result" } @@ -433,7 +488,7 @@ ], "metadata": { "kernelspec": { - "display_name": "3.12.9", + "display_name": "venv", "language": "python", "name": "python3" }, @@ -447,7 +502,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.9" + "version": "3.12.10" } }, "nbformat": 4, From 4925f72dffbc254a29feca7d9424f328e3113d53 Mon Sep 17 00:00:00 2001 From: Jakub Winter <117023023+jwinter3@users.noreply.github.com> Date: Thu, 12 Jun 2025 21:23:17 +0200 Subject: [PATCH 09/13] Move plot to function in polars_bio lib --- docs/notebooks/base_sequence_quality.ipynb | 79 ++++++++-------------- polars_bio/__init__.py | 2 + polars_bio/base_sequnce_quality_vis.py | 51 ++++++++++++++ 3 files changed, 80 insertions(+), 52 deletions(-) create mode 100644 polars_bio/base_sequnce_quality_vis.py diff --git a/docs/notebooks/base_sequence_quality.ipynb b/docs/notebooks/base_sequence_quality.ipynb index 6c665ef6..f7ae29e8 100644 --- a/docs/notebooks/base_sequence_quality.ipynb +++ b/docs/notebooks/base_sequence_quality.ipynb @@ -10,15 +10,24 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 1, "id": "58b40aa6", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/jwinter/TBD/proj2/polars-bio/venv/lib/python3.12/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", + " from .autonotebook import tqdm as notebook_tqdm\n", + "INFO:polars_bio:Creating BioSessionContext\n" + ] + } + ], "source": [ - "import matplotlib.pyplot as plt\n", + "import pandas as pd\n", "\n", - "import polars_bio as pb\n", - "import pandas as pd" + "import polars_bio as pb" ] }, { @@ -39,7 +48,7 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 2, "id": "0420c240", "metadata": {}, "outputs": [ @@ -48,17 +57,17 @@ "output_type": "stream", "text": [ " pos avg q1 median q3 lower upper\n", - "77 0 30.135 31.213636 33.722222 34.482143 26.310877 39.384903\n", - "94 1 31.210 31.275000 34.086364 34.538636 26.379545 39.434091\n", - "51 2 32.015 31.356383 34.094595 34.542793 26.576768 39.322408\n", - "22 3 35.690 35.483333 37.208661 37.600394 32.307743 40.775984\n", - "48 4 35.680 35.552885 37.208661 37.600394 32.481621 40.671657\n", + "60 0 30.135 31.213636 33.722222 34.482143 26.310877 39.384903\n", + "48 1 31.210 31.275000 34.086364 34.538636 26.379545 39.434091\n", + "99 2 32.015 31.356383 34.094595 34.542793 26.576768 39.322408\n", + "21 3 35.690 35.483333 37.208661 37.600394 32.307743 40.775984\n", + "2 4 35.680 35.552885 37.208661 37.600394 32.481621 40.671657\n", ".. ... ... ... ... ... ... ...\n", - "67 96 31.315 32.795455 34.824324 35.508824 28.725401 39.578877\n", - "57 97 30.670 31.575000 34.890625 35.557229 25.601657 41.530572\n", - "2 98 31.550 32.107143 34.890625 35.537791 26.961171 40.683762\n", - "45 99 31.250 32.093750 34.712500 35.455357 27.051339 40.497768\n", - "27 100 31.105 31.250000 34.154762 35.250000 25.250000 41.250000\n", + "25 96 31.315 32.795455 34.824324 35.508824 28.725401 39.578877\n", + "83 97 30.670 31.575000 34.890625 35.557229 25.601657 41.530572\n", + "75 98 31.550 32.107143 34.890625 35.537791 26.961171 40.683762\n", + "86 99 31.250 32.093750 34.712500 35.455357 27.051339 40.497768\n", + "41 100 31.105 31.250000 34.154762 35.250000 25.250000 41.250000\n", "\n", "[101 rows x 7 columns]\n" ] @@ -79,7 +88,7 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 3, "id": "7322aae3", "metadata": {}, "outputs": [ @@ -95,41 +104,7 @@ } ], "source": [ - "boxes = [\n", - " {\n", - " \"label\": int(row[\"pos\"]),\n", - " \"whislo\": row[\"lower\"],\n", - " \"q1\": row[\"q1\"],\n", - " \"med\": row[\"median\"],\n", - " \"q3\": row[\"q3\"],\n", - " \"whishi\": row[\"upper\"],\n", - " }\n", - " for _, row in result.iterrows()\n", - "]\n", - "\n", - "\n", - "fig, ax = plt.subplots()\n", - "fig.set_size_inches(15, 5)\n", - "\n", - "\n", - "plot = ax.plot(result[\"pos\"] + 1, result[\"avg\"])\n", - "box_plot = ax.bxp(boxes, showfliers=False)\n", - "\n", - "ax.set_title(\"base sequence quality\")\n", - "ax.set_ylabel(\"Phred score\")\n", - "ax.set_xlabel(\"Position in read (bp)\")\n", - "\n", - "ax.legend(\n", - " [plot[0], box_plot[\"medians\"][0]],\n", - " [\"Average of phred score\", \"Median of phred score\"],\n", - ")\n", - "\n", - "\n", - "for label in ax.get_xticklabels():\n", - " label.set_fontsize(6)\n", - "\n", - "\n", - "plt.show()" + "pb.visualize_base_sequence_quality(result)" ] }, { diff --git a/polars_bio/__init__.py b/polars_bio/__init__.py index 91eb9b0b..ffe5dce6 100644 --- a/polars_bio/__init__.py +++ b/polars_bio/__init__.py @@ -1,5 +1,6 @@ from polars_bio.polars_bio import InputFormat, ReadOptions, VcfReadOptions +from .base_sequnce_quality_vis import visualize_base_sequence_quality from .context import ctx, set_option from .io import ( describe_vcf, @@ -30,6 +31,7 @@ "coverage", "ctx", "FilterOp", + "visualize_base_sequence_quality", "visualize_intervals", "read_bam", "read_vcf", diff --git a/polars_bio/base_sequnce_quality_vis.py b/polars_bio/base_sequnce_quality_vis.py new file mode 100644 index 00000000..fd6cd51b --- /dev/null +++ b/polars_bio/base_sequnce_quality_vis.py @@ -0,0 +1,51 @@ +from typing import Union + +import pandas as pd +import polars as pl +from matplotlib import pyplot as plt + + +def visualize_base_sequence_quality(df: Union[pd.DataFrame, pl.DataFrame]) -> None: + """ + Visualize the overlapping intervals. + + Parameters: + df: Pandas DataFrame or Polars DataFrame. The DataFrame containing the base sequence quality results + """ + assert isinstance( + df, (pd.DataFrame, pl.DataFrame) + ), "df must be a Pandas or Polars DataFrame" + df = df if isinstance(df, pd.DataFrame) else df.to_pandas() + df = df.sort_values(by="pos") + + boxes = [ + { + "label": int(row["pos"]), + "whislo": row["lower"], + "q1": row["q1"], + "med": row["median"], + "q3": row["q3"], + "whishi": row["upper"], + } + for _, row in df.iterrows() + ] + + fig, ax = plt.subplots() + fig.set_size_inches(15, 5) + + plot = ax.plot(df["pos"] + 1, df["avg"]) + box_plot = ax.bxp(boxes, showfliers=False) + + ax.set_title("base sequence quality") + ax.set_ylabel("Phred score") + ax.set_xlabel("Position in read (bp)") + + ax.legend( + [plot[0], box_plot["medians"][0]], + ["Average of phred score", "Median of phred score"], + ) + + for label in ax.get_xticklabels(): + label.set_fontsize(6) + + plt.show() From 01260df59465b8e5b3450be98791c64aaf32b303 Mon Sep 17 00:00:00 2001 From: Jakub Winter <117023023+jwinter3@users.noreply.github.com> Date: Fri, 13 Jun 2025 00:27:04 +0200 Subject: [PATCH 10/13] Add unit tests --- polars_bio/quality_stats.py | 5 +- src/quantile_stats.rs | 30 ++-- tests/test_base_sequence_quality.py | 215 ++++++++++++++++++++++++++++ 3 files changed, 234 insertions(+), 16 deletions(-) create mode 100644 tests/test_base_sequence_quality.py diff --git a/polars_bio/quality_stats.py b/polars_bio/quality_stats.py index 501bd44a..6c23b6d9 100644 --- a/polars_bio/quality_stats.py +++ b/polars_bio/quality_stats.py @@ -12,7 +12,7 @@ def base_sequence_quality( - df: Union[str, pl.DataFrame, pl.LazyFrame, pd.DataFrame], + df: Union[str, Path, pl.DataFrame, pl.LazyFrame, pd.DataFrame], quality_scores_column: str = "quality_scores", output_type: str = "polars.DataFrame", target_partitions: int = 8, @@ -32,7 +32,8 @@ def base_sequence_quality( "datafusion.execution.target_partitions", str(target_partitions), False ) - if isinstance(df, str): + if isinstance(df, (str, Path)): + df = str(df) supported_exts = {".parquet", ".csv", ".bed", ".vcf", ".fastq"} ext = set(Path(df).suffixes) if not (supported_exts & ext or not ext): diff --git a/src/quantile_stats.rs b/src/quantile_stats.rs index 36bf01b2..43645027 100644 --- a/src/quantile_stats.rs +++ b/src/quantile_stats.rs @@ -235,24 +235,26 @@ fn calculate_histogram_stats(hist: &[u64]) -> Option<(f64, f64, f64, f64, f64, f fn quantile(hist: &[u64], quantile: f64, total: u64) -> f64 { let target = quantile * (total - 1) as f64; + let target_ = target.floor(); + let delta = target - target_; + let n = target_ as u64 + 1; + let mut lo = None; let mut acc = 0u64; - let mut prev_idx = 0usize; - for (idx, &count) in hist.iter().enumerate() { - if count == 0 { - continue; - } - if (acc as f64) <= target && (acc + count) as f64 > target { - let delta = target - acc as f64; - if count > 1 && delta > 0.0 { - return idx as f64 + delta / count as f64; - } else { - return idx as f64; - } + for (hi, &count) in hist.iter().enumerate().filter(|(_, &count)| count > 0) { + if acc == n && lo.is_some() { + let lo = lo.unwrap() as f64; + return (lo + (hi as f64 - lo) * delta) as f64; + } else if acc + count > n { + return hi as f64; } acc += count; - prev_idx = idx; + lo = Some(hi); } - prev_idx as f64 + + hist.iter().enumerate().fold( + 0_usize, + |acc, (value, &count)| if count > 0 { value } else { acc }, + ) as f64 } let q1 = quantile(hist, 0.25, total_count); diff --git a/tests/test_base_sequence_quality.py b/tests/test_base_sequence_quality.py new file mode 100644 index 00000000..f7b278bd --- /dev/null +++ b/tests/test_base_sequence_quality.py @@ -0,0 +1,215 @@ +from pathlib import Path +import polars as pl +import pandas as pd + +import pytest + +import polars_bio as pb + + +class TestBaseSequenceQuality: + def record_header(self, len: int): + return f"@test\n{'N'*len}\n+\n" + + def simple_test_data(self): + data = self.record_header(1) + chr(5 + 33) + "\n" + result = pl.DataFrame( + { + "pos": [0], + "avg": [5.0], + "q1": [5.0], + "median": [5.0], + "q3": [5.0], + "lower": [5.0], + "upper": [5.0], + } + ) + + return data, result + + @pytest.mark.usefixtures("tmp_path") + def test_result_from_empty_fastq_should_be_empty_df_polars(self, tmp_path: Path): + fastq_file = tmp_path / "test.fastq" + fastq_file.write_text("", encoding="ascii") + + result = pb.base_sequence_quality(fastq_file) + assert isinstance(result, pl.DataFrame) + assert pb.base_sequence_quality(fastq_file).is_empty() + + @pytest.mark.usefixtures("tmp_path") + def test_result_from_empty_fastq_should_be_empty_df_pandas(self, tmp_path: Path): + fastq_file = tmp_path / "test.fastq" + fastq_file.write_text("", encoding="ascii") + + result = pb.base_sequence_quality(fastq_file, output_type="pandas.DataFrame") + assert isinstance(result, pd.DataFrame) + assert pb.base_sequence_quality(fastq_file).is_empty() + + @pytest.mark.usefixtures("tmp_path") + def test_one_record_one_length(self, tmp_path: Path): + data, expected_result = self.simple_test_data() + fastq_file = tmp_path / "test.fastq" + fastq_file.write_text(data, encoding="ascii") + + result = pb.base_sequence_quality(fastq_file) + assert result.equals(expected_result) + + @pytest.mark.usefixtures("tmp_path") + def test_one_record_one_length_lazyframe(self, tmp_path: Path): + data, expected_result = self.simple_test_data() + fastq_file = tmp_path / "test.fastq" + fastq_file.write_text(data, encoding="ascii") + + lf = pb.read_fastq(str(fastq_file)) + result = pb.base_sequence_quality(lf) + + assert result.equals(expected_result) + + @pytest.mark.usefixtures("tmp_path") + def test_one_record_one_length_polars(self, tmp_path: Path): + data, expected_result = self.simple_test_data() + fastq_file = tmp_path / "test.fastq" + fastq_file.write_text(data, encoding="ascii") + + lf = pb.read_fastq(str(fastq_file)) + polars_df = lf.collect() + result = pb.base_sequence_quality(polars_df) + + assert result.equals(expected_result) + + @pytest.mark.usefixtures("tmp_path") + def test_one_record_one_length_pandas(self, tmp_path: Path): + data, expected_result = self.simple_test_data() + fastq_file = tmp_path / "test.fastq" + fastq_file.write_text(data, encoding="ascii") + + lf = pb.read_fastq(str(fastq_file)) + pandas_df = lf.collect().to_pandas() + result = pb.base_sequence_quality(pandas_df) + + assert result.equals(expected_result) + + @pytest.mark.usefixtures("tmp_path") + def test_one_record_two_length(self, tmp_path: Path): + fastq_file = tmp_path / "test.fastq" + fastq_file.write_text( + self.record_header(1) + chr(5 + 33) + chr(6 + 33) + "\n", + encoding="ascii", + ) + + result = pb.base_sequence_quality(fastq_file).sort(by="pos") + assert result.equals( + pl.DataFrame( + { + "pos": [0, 1], + "avg": [5.0, 6.0], + "q1": [5.0, 6.0], + "median": [5.0, 6.0], + "q3": [5.0, 6.0], + "lower": [5.0, 6.0], + "upper": [5.0, 6.0], + } + ) + ) + + @pytest.mark.usefixtures("tmp_path") + def test_two_record_one_length(self, tmp_path: Path): + fastq_file = tmp_path / "test.fastq" + + file_content = "" + for read in [0, 2]: + file_content += self.record_header(2) + chr(read + 33) + "\n" + + fastq_file.write_text(file_content, encoding="ascii") + + result = pb.base_sequence_quality(fastq_file) + assert result.equals( + pl.DataFrame( + { + "pos": [0], + "avg": [1.0], + "q1": [0.5], + "median": [1.0], + "q3": [1.5], + "lower": [-1.0], + "upper": [3.0], + } + ) + ) + + @pytest.mark.usefixtures("tmp_path") + def test_three_record_one_length(self, tmp_path: Path): + fastq_file = tmp_path / "test.fastq" + + file_content = "" + for read in [0, 2, 4]: + file_content += self.record_header(3) + chr(read + 33) + "\n" + + fastq_file.write_text(file_content, encoding="ascii") + + result = pb.base_sequence_quality(fastq_file) + assert result.equals( + pl.DataFrame( + { + "pos": [0], + "avg": [2.0], + "q1": [1.0], + "median": [2.0], + "q3": [3.0], + "lower": [-2.0], + "upper": [6.0], + } + ) + ) + + @pytest.mark.usefixtures("tmp_path") + def test_four_record_one_length(self, tmp_path: Path): + fastq_file = tmp_path / "test.fastq" + + file_content = "" + for read in [0, 2, 4, 9]: + file_content += self.record_header(3) + chr(read + 33) + "\n" + + fastq_file.write_text(file_content, encoding="ascii") + + result = pb.base_sequence_quality(fastq_file) + assert result.equals( + pl.DataFrame( + { + "pos": [0], + "avg": [3.75], + "q1": [1.5], + "median": [3.0], + "q3": [5.25], + "lower": [-4.125], + "upper": [10.875], + } + ) + ) + + @pytest.mark.usefixtures("tmp_path") + def test_four_record_two_length(self, tmp_path: Path): + fastq_file = tmp_path / "test.fastq" + + file_content = "" + for read1, read2 in zip([0, 2, 4, 9], [1, 3, 5, 10]): + file_content += ( + self.record_header(3) + chr(read1 + 33) + chr(read2 + 33) + "\n" + ) + + fastq_file.write_text(file_content, encoding="ascii") + + result = pb.base_sequence_quality(fastq_file).sort(by="pos") + assert result.equals( + pl.DataFrame( + { + "pos": [0, 1], + "avg": [3.75, 4.75], + "q1": [1.5, 2.5], + "median": [3.0, 4.0], + "q3": [5.25, 6.25], + "lower": [-4.125, -3.125], + "upper": [10.875, 11.875], + } + ) + ) From 51139681db66d4b699d7a181140b1c254c06a716 Mon Sep 17 00:00:00 2001 From: Jakub Winter <117023023+jwinter3@users.noreply.github.com> Date: Sun, 15 Jun 2025 21:19:43 +0200 Subject: [PATCH 11/13] Update notebooks --- .gitignore | 3 +- docs/notebooks/base_sequence_quality.ipynb | 278 +++++++++++---------- docs/notebooks/example.csv | 201 +++++++++++++++ 3 files changed, 346 insertions(+), 136 deletions(-) create mode 100644 docs/notebooks/example.csv diff --git a/.gitignore b/.gitignore index d08bdd88..1c30809a 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,5 @@ benchmark/bin/env.sh benchmark/src/results benchmark/src/results/overlap mprofile*dat -*csv \ No newline at end of file +*csv +!docs/notebooks/example.csv \ No newline at end of file diff --git a/docs/notebooks/base_sequence_quality.ipynb b/docs/notebooks/base_sequence_quality.ipynb index f7ae29e8..c88a6a58 100644 --- a/docs/notebooks/base_sequence_quality.ipynb +++ b/docs/notebooks/base_sequence_quality.ipynb @@ -10,20 +10,10 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 17, "id": "58b40aa6", "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/jwinter/TBD/proj2/polars-bio/venv/lib/python3.12/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", - " from .autonotebook import tqdm as notebook_tqdm\n", - "INFO:polars_bio:Creating BioSessionContext\n" - ] - } - ], + "outputs": [], "source": [ "import pandas as pd\n", "\n", @@ -48,7 +38,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 18, "id": "0420c240", "metadata": {}, "outputs": [ @@ -56,18 +46,18 @@ "name": "stdout", "output_type": "stream", "text": [ - " pos avg q1 median q3 lower upper\n", - "60 0 30.135 31.213636 33.722222 34.482143 26.310877 39.384903\n", - "48 1 31.210 31.275000 34.086364 34.538636 26.379545 39.434091\n", - "99 2 32.015 31.356383 34.094595 34.542793 26.576768 39.322408\n", - "21 3 35.690 35.483333 37.208661 37.600394 32.307743 40.775984\n", - "2 4 35.680 35.552885 37.208661 37.600394 32.481621 40.671657\n", - ".. ... ... ... ... ... ... ...\n", - "25 96 31.315 32.795455 34.824324 35.508824 28.725401 39.578877\n", - "83 97 30.670 31.575000 34.890625 35.557229 25.601657 41.530572\n", - "75 98 31.550 32.107143 34.890625 35.537791 26.961171 40.683762\n", - "86 99 31.250 32.093750 34.712500 35.455357 27.051339 40.497768\n", - "41 100 31.105 31.250000 34.154762 35.250000 25.250000 41.250000\n", + " pos avg q1 median q3 lower upper\n", + "87 0 30.135 31.0 33.0 34.0 26.5 38.5\n", + "66 1 31.210 31.0 34.0 34.0 26.5 38.5\n", + "69 2 32.015 31.0 34.0 34.0 26.5 38.5\n", + "45 3 35.690 35.0 37.0 37.0 32.0 40.0\n", + "14 4 35.680 35.0 37.0 37.0 32.0 40.0\n", + ".. ... ... ... ... ... ... ...\n", + "40 96 31.315 32.0 34.0 35.0 27.5 39.5\n", + "23 97 30.670 31.0 34.0 35.0 25.0 41.0\n", + "37 98 31.550 32.0 34.0 35.0 27.5 39.5\n", + "6 99 31.250 32.0 34.0 35.0 27.5 39.5\n", + "4 100 31.105 31.0 34.0 35.0 25.0 41.0\n", "\n", "[101 rows x 7 columns]\n" ] @@ -88,13 +78,13 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 19, "id": "7322aae3", "metadata": {}, "outputs": [ { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAABM8AAAHRCAYAAAB9856CAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjMsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvZiW1igAAAAlwSFlzAAAPYQAAD2EBqD+naQAA1SBJREFUeJzs3Xlc1NX+x/HXsA07KKCgoriDu2CaaWlpaZZlebPNysyWW7bZ/ru39VbWLctWszK10DbTbmVlWi5JruCuKC64griB7Ov8/hiZRBb5AgMDvJ+Phw/lO2fOnPnODM6853POMVksFgsiIiIiIiIiIiJSilNdD0BERERERERERMRRKTwTEREREREREREph8IzERERERERERGRcig8ExERERERERERKYfCMxERERERERERkXIoPBMRERERERERESmHwjMREREREREREZFyKDwTEREREREREREph8IzERERERERERGRcig8ExERkTrzwgsvYDKZOH78eF0PRRoxk8nECy+8YPt51qxZmEwmEhMT62xMIiIi4jgUnomIiIiInMeHH37IrFmz6noYIiIiUgcUnomIiIiInOW2224jOzubNm3a2I4pPBMREWm8XOp6ACIiIiIijsTZ2RlnZ+e6HoaIiIg4CFWeiYiISJ07fvw4Y8aMwdfXl4CAAB5++GFycnJKtJk5cyaXXXYZzZo1w2w206VLF6ZNm1aqr/Xr1zNs2DACAwPx8PCgbdu2jB8/vkSboqIipk6dSteuXXF3d6d58+bce++9nDp16rxjTU5O5s4776RVq1aYzWZCQkK49tprS62P9csvv3DxxRfj5eWFj48PV111Fdu2bSvV3/fff0+3bt1wd3enW7duLFiwgHHjxhEWFmZrs2zZMkwmE8uWLStx3cTEREwmU6mKqPj4eP7xj3/QtGlT3N3d6dOnDz/88EOJNsXresXExDBp0iSCgoLw8vLiuuuu49ixY6XG+csvvzBo0CB8fHzw9fXlggsuYO7cuSXarFmzhuHDh+Pn54enpyeDBg0iJibmvOcU4NChQ4waNQovLy+aNWvGo48+yqJFi0rd77CwMMaNG1fq+oMHD2bw4MG2n/Py8njuueeIiorCz88PLy8vLr74YpYuXXresZy75llYWBjbtm1j+fLlmEwmTCYTgwcPZu/evZhMJt5+++1Sffz111+YTCa+/PLLSt1/ERERcVyqPBMREZE6N2bMGMLCwpg8eTKrV6/m3Xff5dSpU3z++ee2NtOmTaNr165cc801uLi48OOPP3L//fdTVFTEAw88AEBKSgpXXHEFQUFBPP300/j7+5OYmMj8+fNL3N69997LrFmzuPPOO3nooYfYt28f77//Phs2bCAmJgZXV9dyxzp69Gi2bdvGgw8+SFhYGCkpKSxevJgDBw7YAq8vvviCO+64g2HDhvH666+TlZXFtGnTGDhwIBs2bLC1++233xg9ejRdunRh8uTJnDhxwhbMVdW2bdsYMGAALVu25Omnn8bLy4tvvvmGUaNG8d1333HdddeVaP/ggw/SpEkTnn/+eRITE5k6dSoTJ07k66+/trWZNWsW48ePp2vXrjzzzDP4+/uzYcMGfv31V2655RYA/vjjD6688kqioqJ4/vnncXJysgWef/75J3379i13zNnZ2QwZMoQDBw7w0EMP0aJFC7744gv++OOPKp+H06dP8+mnn3LzzTdz9913k56ezowZMxg2bBhr166lV69ele5r6tSpPPjgg3h7e/Ovf/0LgObNm9OuXTsGDBjAnDlzePTRR0tcZ86cOfj4+HDttddW+T6IiIiIg7CIiIiI1JHnn3/eAliuueaaEsfvv/9+C2DZtGmT7VhWVlap6w8bNszSrl07288LFiywAJZ169aVe5t//vmnBbDMmTOnxPFff/21zONnO3XqlAWwvPHGG+W2SU9Pt/j7+1vuvvvuEseTk5Mtfn5+JY736tXLEhISYklNTbUd++233yyApU2bNrZjS5cutQCWpUuXluhz3759FsAyc+ZM27EhQ4ZYunfvbsnJybEdKyoqslx00UWWjh072o7NnDnTAliGDh1qKSoqsh1/9NFHLc7OzrYxpaamWnx8fCz9+vWzZGdnl7j94usVFRVZOnbsaBk2bFiJvrKysixt27a1XH755eWeL4vFYpk6daoFsHzzzTe2Y5mZmZYOHTqUut9t2rSx3HHHHaX6GDRokGXQoEG2nwsKCiy5ubkl2pw6dcrSvHlzy/jx40scByzPP/98qXOzb98+27GuXbuW6L/Y9OnTLYBlx44dtmN5eXmWwMDAMscpIiIi9Y+mbYqIiEidK64cK/bggw8C8PPPP9uOeXh42P6dlpbG8ePHGTRoEHv37iUtLQ0Af39/AH766Sfy8/PL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7rvvth0vKCjAz8+v3HHWJIVnIiIiIg3cuWGOpu3VX0aCOU9PzxKX67EXqX9MJpOhqZN1ZcaMGRQUFNCiRQvbMYvFgtls5v3338fPz49bb72VQYMGkZKSwuLFi/Hw8GD48OEAtnXCFi5cSMuWLUv0fe4i+2eHVQCPP/44ixcv5s0336RDhw54eHjwj3/8w9CC+RkZGYSEhLBs2bJSlxVXj9W1c8Mok8lUKuA699xkZGQQFRVVYmpnsaCgoCqPZcKECQwbNoyFCxfy22+/MXnyZKZMmcKDDz6Ih4dHlfs929n3pfj58cknn5QI+gCcnSsf8laH478KRUREREQaKK1LJiL1XUFBAZ9//jlTpkzhiiuuKHHZqFGj+PLLL7nvvvu46KKLCA0N5euvv+aXX37hhhtusAVCXbp0wWw2c+DAgRJTNCsjJiaGcePG2dZOy8jIKLEgfufOnSkoKGDDhg22qey7d+/m1KlTtjaRkZEkJyfj4uJCWFhYpW43IiKCWbNmkZmZaQt6YmJicHJysi3Wb8Tq1atta7SdOnWKXbt22b4sqarIyEi+/vprmjVrhq+vb5ltQkJCWLNmDZdccglgfTwrM8U/NDSU++67j/vuu49nnnmGTz75hAcffJAePXowe/Zs8vPzSwV+vr6+tGjRgpiYmBKPc0xMDH379i33tpo3b06LFi3Yu3cvt956a2Xvfo1SeCYiIiIiUkccaV0yI5sRiIgU++mnnzh16hR33XVXqSl0o0ePZsaMGdx3332AddfNjz76iF27drF06VJbOx8fHx5//HEeffRRioqKGDhwIGlpacTExODr61vhmlYdO3Zk/vz5jBw5EpPJxLPPPktRUZHt8vDwcIYOHco999zDtGnTcHV15bHHHsPDw8O2DtjQoUPp378/o0aN4r///S+dOnXiyJEjLFy4kOuuu67UVFGAW2+9leeff5477riDF154gWPHjvHggw9y2223GZ6yCda13AICAmjevDn/+te/CAwMZNSoUYb7OXeMb7zxBtdee61th8v9+/czf/58nnzySVq1asXDDz/Ma6+9RseOHQkPD+ett94iNTW1wn4feeQRrrzySjp16sSpU6dYunSpLeibOHEi7733HjfddBPPPPMMfn5+rF69mr59+9K5c2eeeOIJnn/+edq3b0+vXr2YOXMmGzduLLM67mwvvvgiDz30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RDtXV9cSP5tMJoqKiqp8uzWtMuPz8vKy/dte5zM0NJSdO3eyZMkSFi9ezP33388bb7zB8uXLa2yjhrPvB1jvy8iRI8usiAsJCamR26wqhWciIiIi9YymEVbfububKnh0HPW1srK+jtuedE4ap+HDh5OXl4fJZLItAn+2Ll26YDabOXDgQLmVSxERESUWygdYvXp1hbcbExPDuHHjuO666wBrEHO+RfHPp3379rY1udq0aQNAfn4+69at45FHHjHc37n3YfXq1bb/i6rKXucTrDuajhw5kpEjR/LAAw8QHh7Oli1b6N69O0VFRSxfvtw2bfPc2/vuu++wWCy26rOYmBh8fHwq3JE0MjKS7777jrCwMIfbQdSxRiMiIiIi56VphNKQGa2sNLJ+nT2pIrQ0nZPGydnZ2Tal0dnZudTlPj4+PP744zz66KMUFRUxcOBA0tLSiImJwdfXlzvuuIP77ruPKVOm8MQTTzBhwgRiY2PL3cWyWMeOHZk/fz4jR47EZDLx7LPPVruizMvLi3/+85888cQTNG3alNatW/Pf//6XrKws7rrrLsP9xcTE8N///pdRo0axePFivv32WxYuXFitMdrrfM6aNYvCwkL69euHp6cn0dHReHh40KZNGwICArjjjjsYP3487777Lj179mT//v2kpKQwZswY7r//fqZOncqDDz7IxIkT2blzJ88//zyTJk2yrXdWlgceeIBPPvmEm2++mSeffJKmTZuye/duvvrqKz799NMyn0+1ReGZiIiIiFTZucGFqkqkuoxWVhpZv86eVBFams5J4+Xr61vh5f/5z38ICgpi8uTJ7N27F39/fyIjI/m///s/AFq3bs13333Ho48+ynvvvUffvn159dVXGT9+fLl9vvXWW4wfP56LLrqIwMBAnnrqKU6fPl3t+/Laa69RVFTEbbfdRnp6On369GHRokU0adLEcF+PPfYY69ev58UXX8TX15e33nqrzOo8o+xxPv39/XnttdeYNGkShYWFdO/enR9//JGAgAAApk2bxv/93/9x//33c+LECVq3bm27vZYtW/Lzzz/zxBNP0LNnT5o2bcpdd93Fv//97wrvR4sWLYiJieGpp57iiiuuIDc3lzZt2jB8+PAKQ7faoPBMRERERKrs3OBCVSVSXUYrKx1l/TpVhJamc9J4nK+K6fvvvy/xs8lk4uGHH+bh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yMPDQz4+PmrXrp1efvll5eXlXfbYUVFRSk5OVnBwsCTrBtaWLVv08MMPX/bXszN69Gj98ssvFfo13GHZsmU6ceKExowZU67jdu7cWf369dNf//rXch0XAABUXzTPAABAtTVs2DAlJydr3759mjJliqZPn67XXnvtssf18fFRaGioPDw8bHMNGzaUv7//ZX89O35+fmrUqFG5jpmfn6+CgoJyHbOs/v73v+u+++6Tp2f5P1297777NHv27HJppAIAgOqP5hkAAKi2fH19FRoaqquuukqPPfaYhgwZomXLlkmSzp49q3HjxqlevXry9/fX8OHDtW/fPsfnHjp0SCNGjFC9evUUEBCgLl266Ouvv5ZU/LTNVatW6b777lNaWppjp9v06dMllTxt8/Dhwxo5cqQCAwMVFBSkO+64QydOnHB8fPr06erZs6c++OADtWrVSsHBwRozZowyMjIsv0fnXW+XM8ayZcvUuXNn+fr66vDhw8rOztbUqVPVrFkzBQQEqG/fvlq1apXj806fPq0777xTzZo1k7+/v7p166ZFixYVG/v8+fMaN26cAgMD1aRJE73++uuW8yhy6tQp/fDDDxoxYkSJjyUnJ2v48OHy8/NTmzZt9Mknnzg+lpSUJA8PDy1evFhRUVGqXbu2unbtqtWrVxcb49prr9WZM2dKvB8AAMAMzTMAAFBj+Pn5KScnR1LhaZ0///yzli1bpg0bNsgwDF1//fXKzc2VJE2YMEHZ2dlas2aNdu7cqVdeeUWBgYElxoyKitIbb7yhoKAgJScnKzk5WVOnTi2RKygo0MiRIx1Nm++++06//vqrRo8eXSx34MABff7551q+fLmWL1+u1atXa9asWWX6Pi9ljMzMTL3yyiv617/+pd27d6tRo0aaOHGiNmzYoMWLF2vHjh26/fbbNWzYMEeT8cKFC4qIiNBXX32lXbt26eGHH9Y999yjzZs3O8Z9+umntXr1an3xxRf69ttvtWrVKsXHx9vOZe3atfL391enTp1KfOzFF1/UqFGjtH37dt19990aM2aMEhISimWefvppTZkyRVu3blVkZKRGjBih06dPOz7u4+Ojnj176qeffnL5swQAAKjl7gkAAABUNMMwtHLlSq1YsUKTJk3Svn37tGzZMq1bt05RUVGSpI8++kgtWrTQ559/rttvv12HDx/WqFGj1K1bN0lSmzZtTMf28fFRcHCwPDw8FBoaajmHlStXaufOnTp48KBatGghSVqwYIG6dOmiLVu2qHfv3pIKm2zz5s1TnTp1JEn33HOPVq5cqRkzZpT6+72UMXJzc/Xuu++qR48ekgp3yc2dO1eHDx9W06ZNJUlTp07VN998o7lz5+ovf/mLmjVrVqxROGnSJK1YsUIff/yx+vTpo3PnzmnOnDn68MMPNXjwYEnS/Pnz1bx5c9v5Hzp0SI0bNzY9ZfP222/Xgw8+KEn605/+pO+++05vvfWW3n33XUdm4sSJGjVqlCRp9uzZ+uabbzRnzhz98Y9/dGSaNm2qQ4cO2c4DAABAonkGAACqseXLlyswMFC5ubkqKCjQXXfdpenTp2vlypWqVauW+vbt68iGhISoY8eOjl1Mf/jDH/TYY4/p22+/1ZAhQzRq1Ch17979kueSkJCgFi1aOBpnUuHF6+vWrauEhARH86xVq1aOppckNWnSRCdPnizT17qUMXx8fIp9fzt37lR+fr46dOhQLJedna2QkBBJhddG+8tf/qKPP/5Yx44dU05OjrKzsx3XeTtw4IBycnKK/Zzr16+vjh072s4lKytLtWvXNv1YZGRkibe3bdtmmalVq5auvvrqErvT/Pz8lJmZaTsPAAAAieYZAACoxgYNGqTZs2fLx8dHTZs2Va1apX/q8+CDD2ro0KH66quv9O2332rmzJl6/fXXNWnSpAqcseTt7V3sbQ8PjzJfvP9SxvDz8yt2A4Rz587Jy8tLcXFx8vLyKpYtOn31tdde05tvvqk33nhD3bp1U0BAgCZPnuw4NfZSNWjQQGfPnr2sMVw5c+aM2rZtW6FfAwAAVA9c8wwAAFRbAQEBateunVq2bFmscdapUyfl5eVp06ZNjvedPn1ae/fuVefOnR3va9GihR599FEtXbpUU6ZM0T//+U/Tr+Pj46P8/HzbuXTq1ElHjhzRkSNHHO/bs2ePUlNTi33NyqJXr17Kz8/XyZMn1a5du2L/FZ2eum7dOo0cOVJjx45Vjx491KZNG/3yyy+OMdq2bStvb+9iP+ezZ88Wy1h97ZSUFNMG2saNG0u87XxttIszeXl5iouLK5HZtWuXevXq5eKnAAAAQPMMAADUQO3bt9fIkSP10EMPae3atdq+fbvGjh2rZs2aaeTIkZKkyZMna8WKFTp48KDi4+P1448/ml7AXio8TfLcuXNauXKlfvvtN9PTAYcMGaJu3brp7rvvVnx8vDZv3qxx48Zp4MCBuvrqqyv0+70UHTp00N13361x48Zp6dKlOnjwoDZv3qyZM2fqq6++klT4c/zuu++0fv16JSQk6JFHHil299DAwEA98MADevrpp/XDDz9o165dGj9+vOm1zC7Wq1cvNWjQQOvWrSvxsSVLluj999/XL7/8omnTpmnz5s2aOHFiscw777yjzz77TImJiZowYYLOnj2r+++/3/HxpKQkHTt2TEOGDLmcHxEAAKghaJ4BAIAaae7cuYqIiNCNN96oyMhIGYahr7/+2nHKY35+viZMmKBOnTpp2LBh6tChQ7GL0l8sKipKjz76qEaPHq2GDRvq1VdfLZHx8PDQF198oXr16mnAgAEaMmSI2rRpo3//+98V+n1ejrlz52rcuHGaMmWKOnbsqJtvvllbtmxRy5YtJUkvvPCCwsPDNXToUMXGxio0NFQ333xzsTFee+019e/fXyNGjNCQIUMUExOjiIgI26/r5eWl++67Tx999FGJj7300ktavHixunfvrgULFmjRokUldu7NmjVLs2bNUo8ePbR27VotW7ZMDRo0cHx80aJFuu6663TVVVdd4k8GAADUJB6GYRjungQAAABwsZSUFHXp0kXx8fGlbnIlJSWpdevW2rp1q3r27GmaycnJUfv27bVw4UJFR0eX44wBAEB1xc4zAAAAVDqhoaGaM2eODh8+XK7jHj58WM8//zyNMwAAUGrcbRMAAACVkvMpoOWh6KYHAAAApcVpmwAAAAAAAIAFTtsEAAAAAAAALNA8AwAAAAAAACzQPAMAAAAAAAAs0DwDAAAAAAAALNA8AwAAAAAAACzQPAMAAAAAAAAs0DwDAAAAAAAALNA8AwAAAAAAACz8f2NzusDY9TvPAAAAAElFTkSuQmCC", + "image/png": "iVBORw0KGgoAAAANSUhEUgAABM8AAAHRCAYAAAB9856CAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjMsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvZiW1igAAAAlwSFlzAAAPYQAAD2EBqD+naQAA115JREFUeJzs3XlY1OX6x/H3sA3D7gqiKC7ojDtgmmlpWWmaZVlWSmUurbbZ6jmVtpys38nylGWeMrXQdu20m5ZmmqYB7qCIoCjiCgiyw/z+GBlFQB0FGeTzui4vnO88c3/veWYYZu55FoPVarUiIiIiIiIiIiIiFbjUdgIiIiIiIiIiIiLOSsUzERERERERERGRKqh4JiIiIiIiIiIiUgUVz0RERERERERERKqg4pmIiIiIiIiIiEgVVDwTERERERERERGpgopnIiIiIiIiIiIiVVDxTEREREREREREpAoqnomIiIiIiIiIiFRBxTMRERGpNVOmTMFgMHDo0KHaTkXqMYPBwJQpU+yX586di8FgICUlpdZyEhEREeeh4pmIiIiIyBm89957zJ07t7bTEBERkVqg4pmIiIiIyEnuvPNO8vLyaNWqlf2YimciIiL1l1ttJyAiIiIi4kxcXV1xdXWt7TRERETESWjkmYiIiNS6Q4cOMWLECPz8/GjUqBGPPvoo+fn55drMmTOHq666iqZNm2I0GunYsSMzZ86sEOvvv/9m4MCBNG7cGJPJROvWrRkzZky5NqWlpUyfPp1OnTrh6elJYGAg9913HxkZGWfMNT09nXvuuYcWLVpgNBpp1qwZN954Y4X1sX766Scuv/xyvL298fX1ZciQIWzZsqVCvG+++YbOnTvj6elJ586dWbRoEaNHjyY0NNTeZvny5RgMBpYvX17utikpKRgMhgojohISErjlllto2LAhnp6e9OjRg2+//bZcm7J1vVatWsXEiRNp0qQJ3t7e3HTTTRw8eLBCnj/99BP9+vXD19cXPz8/LrnkEhYsWFCuzV9//cWgQYPw9/fHy8uLfv36sWrVqjP2KcCePXsYNmwY3t7eNG3alMcff5zFixdXuN+hoaGMHj26wu379+9P//797ZcLCwt54YUXiIyMxN/fH29vby6//HKWLVt2xlxOXfMsNDSULVu28Pvvv2MwGDAYDPTv35+dO3diMBh46623KsT4888/MRgMfPrpp2d1/0VERMR5aeSZiIiI1LoRI0YQGhrK1KlTWbNmDW+//TYZGRl8/PHH9jYzZ86kU6dO3HDDDbi5ufHdd9/x4IMPUlpaykMPPQTAgQMHuPbaa2nSpAnPPvssAQEBpKSksHDhwnLnu++++5g7dy733HMPjzzyCMnJycyYMYO4uDhWrVqFu7t7lbkOHz6cLVu28PDDDxMaGsqBAwdYsmQJu3fvthe8PvnkE+6++24GDhzI66+/Tm5uLjNnzqRv377ExcXZ2/3yyy8MHz6cjh07MnXqVA4fPmwvzJ2rLVu20KdPH5o3b86zzz6Lt7c3X3zxBcOGDePrr7/mpptuKtf+4YcfpkGDBkyePJmUlBSmT5/OhAkT+Pzzz+1t5s6dy5gxY+jUqROTJk0iICCAuLg4fv75Z0aOHAnAb7/9xnXXXUdkZCSTJ0/GxcXFXvD8448/6NmzZ5U55+XlMWDAAHbv3s0jjzxCcHAwn3zyCb/99ts598PRo0f58MMPueOOOxg/fjzZ2dnMnj2bgQMHsnbtWrp3737WsaZPn87DDz+Mj48P//znPwEIDAykTZs29OnTh/nz5/P444+Xu838+fPx9fXlxhtvPOf7ICIiIk7CKiIiIlJLJk+ebAWsN9xwQ7njDz74oBWwbtiwwX4sNze3wu0HDhxobdOmjf3yokWLrIB13bp1VZ7zjz/+sALW+fPnlzv+888/V3r8ZBkZGVbA+u9//7vKNtnZ2daAgADr+PHjyx1PT0+3+vv7lzvevXt3a7NmzayZmZn2Y7/88osVsLZq1cp+bNmyZVbAumzZsnIxk5OTrYB1zpw59mMDBgywdunSxZqfn28/Vlpaar3sssusYWFh9mNz5syxAtarr77aWlpaaj/++OOPW11dXe05ZWZmWn19fa29evWy5uXllTt/2e1KS0utYWFh1oEDB5aLlZuba23durX1mmuuqbK/rFardfr06VbA+sUXX9iPHTt2zNquXbsK97tVq1bWu+++u0KMfv36Wfv162e/XFxcbC0oKCjXJiMjwxoYGGgdM2ZMueOAdfLkyRX6Jjk52X6sU6dO5eKXmTVrlhWwxsfH248VFhZaGzduXGmeIiIiUvdo2qaIiIjUurKRY2UefvhhAH788Uf7MZPJZP9/VlYWhw4dol+/fuzcuZOsrCwAAgICAPj+++8pKiqq9Fxffvkl/v7+XHPNNRw6dMj+LzIyEh8fn9NO6zOZTHh4eLB8+fIqp3guWbKEzMxM7rjjjnLxXV1d6dWrlz3+vn37WL9+PXfffTf+/v72219zzTV07NixyhxO58iRI/z222+MGDGC7Oxs+7kPHz7MwIEDSUxMZO/eveVuc++992IwGOyXL7/8ckpKSti1a5f9/mRnZ/Pss8/i6elZ7rZlt1u/fj2JiYmMHDmSw4cP28977NgxBgwYwIoVKygtLa0y7x9//JFmzZpxyy232I95eXlx7733nlM/gG3dMg8PD8A2TffIkSMUFxfTo0cPYmNjzznuqUaMGIGnpyfz58+3H1u8eDGHDh0iKiqq2s4jIiIitUfTNkVERKTWhYWFlbvctm1bXFxcyq0jtmrVKiZPnszq1avJzc0t1z4rKwt/f3/69evH8OHDefHFF3nrrbfo378/w4YNY+TIkRiNRgASExPJysqiadOmleZy4MCBKvM0Go28/vrrPPHEEwQGBnLppZdy/fXXc9dddxEUFGSPD3DVVVdVGsPPzw/AXpw69b4DdOjQ4ZwKPDt27MBqtfL888/z/PPPV9rmwIEDNG/e3H65ZcuW5a5v0KABgL04mJSUBEDnzp2rPG/Zfb777rurbJOVlWWPfapdu3bRrl27ckU8sPXD+Zg3bx7Tpk0jISGhXDG1devW5xX3ZAEBAQwdOpQFCxbw8ssvA7Ypm82bN6/yOSAiIiJ1i4pnIiIi4nROLaIkJSUxYMAAzGYzb775JiEhIXh4ePDjjz/y1ltv2Uc1GQwGvvrqK9asWcN3333H4sWLGTNmDNOmTWPNmjX4+PhQWlpK06ZNy40UOlmTJk1Om9tjjz3G0KFD+eabb1i8eDHPP/88U6dO5bfffiM8PNyeyyeffGIvqJ3Mzc3xt1+n9keZkpKScpfLzv3kk08ycODASm/Trl27cper2lXSarWedX5l5/33v/9d5VpiPj4+Zx3vdE7XFyffl+joaEaPHs2wYcN46qmnaNq0Ka6urkydOtVeEKwud911F19++SV//vknXbp04dtvv+XBBx/ExUWTPERERC4GKp6JiIhIrUtMTCw3GmjHjh2UlpbaF9b/7rvvKCgo4Ntvvy03UqqqKZaXXnopl156Kf/6179YsGABo0aN4rPPPmPcuHG0bduWpUuX0qdPn3JTQR3Rtm1bnnjiCZ544gkSExPp3r0706ZNIzo6mrZt2wLQtGlTrr766ipjtGrVyn7fT7Vt27Zyl8tGbGVmZpY7XjZ6rUybNm0AcHd3P+25HVF2fzZv3lyh8HZqGz8/v3M6b6tWrdi8eTNWq7VccezUfgBbX5zaD2Dri7L7D/DVV1/Rpk0bFi5cWC7m5MmTHc4Pqi7aAQwaNIgmTZowf/58evXqRW5uLnfeeec5nUdEREScj74OExERkVr37rvvlrv8zjvvAHDdddcBJ0ZHnTwaKisrizlz5pS7XUZGRoURU2UjoQoKCgDbGlUlJSX2KXYnKy4urrQwUyY3N5f8/Pxyx9q2bYuvr689/sCBA/Hz8+PVV1+tdN21gwcPAtCsWTO6d+/OvHnz7Gu2gW2Nsa1bt5a7TatWrXB1dWXFihXljr/33nvlLjdt2pT+/fsza9Ys9u3bV+W5HXHttdfi6+vL1KlTK9z3sr6OjIykbdu2vPHGG+Tk5Dh83sGDB5OWlsZXX31lP5abm8t///vfCm3btm3LmjVrKCwstB/7/vvvSU1NLdeusufMX3/9xerVq0+bS1W8vb2rfG64ublxxx138MUXXzB37ly6dOlC165dz+k8IiIi4nw08kxERERqXXJyMjfccAODBg1i9erVREdHM3LkSLp16wbYCjgeHh4MHTqU++67j5ycHD744AOaNm1arkg0b9483nvvPW666Sbatm1LdnY2H3zwAX5+fgwePBiAfv36cd999zF16lTWr1/Ptddei7u7O4mJiXz55Zf85z//Kbdw/cm2b9/OgAEDGDFiBB07dsTNzY1Fixaxf/9+br/9dsA2+mrmzJnceeedREREcPvtt9OkSRN2797NDz/8QJ8+fZgxYwYAU6dOZciQIfTt25cxY8Zw5MgR3nnnHTp16lSuCOXv78+tt97KO++8g8FgoG3btnz//feVrs/27rvv0rdvX7p06cL48eNp06YN+/fvZ/Xq1ezZs4cNGzY49Nj4+fnx1ltvMW7cOC655BJGjhxJgwYN2LBhA7m5ucybNw8XFxc+/PBDrrvuOjp16sQ999xD8+bN2bt3L8uWLcPPz4/vvvuuynOMHz+eGTNmcNdddxETE0OzZs345JNP8PLyqtB23LhxfPXVVwwaNIgRI0aQlJRUbsRfmeuvv56FCxdy0003MWTIEJKTk3n//ffp2LFjpQW+M4mMjGTmzJm88sortGvXjqZNm5Zb0+yuu+7i7bffZtmyZbz++usOxxcREREnVos7fYqIiEg9N3nyZCtg3bp1q/WWW26x+vr6Whs0aGCdMGGCNS8vr1zbb7/91tq1a1erp6enNTQ01Pr6669bP/roIytgTU5OtlqtVmtsbKz1jjvusLZs2dJqNBqtTZs2tV5//fXWv//+u8K5//vf/1ojIyOtJpPJ6uvra+3SpYv16aeftqalpVWZ76FDh6wPPfSQ1Ww2W729va3+/v7WXr16Wb/44osKbZctW2YdOHCg1d/f3+rp6Wlt27atdfTo0RVy+frrr60Wi8VqNBqtHTt2tC5cuNB69913W1u1alWu3cGDB63Dhw+3enl5WRs0aGC97777rJs3b7YC1jlz5pRrm5SUZL3rrrusQUFBVnd3d2vz5s2t119/vfWrr76yt5kzZ44VsK5bt65C3oB12bJlFfr/sssus5pMJqufn5+1Z8+e1k8//bRcm7i4OOvNN99sbdSokdVoNFpbtWplHTFihPXXX3+tsk/L7Nq1y3rDDTdYvby8rI0bN7Y++uij1p9//rnSXKZNm2Zt3ry51Wg0Wvv06WP9+++/rf369bP269fP3qa0tNT66quvWlu1amU1Go3W8PBw6/fff19p3wLWyZMnV+ibsueV1Wq1pqenW4cMGWL19fW1AuXOVaZTp05WFxcX6549e854f0VERKTuMFitDqwGKyIiIiI1bvTo0SxfvrzcbqP10fLly7nyyitZtmwZ/fv3r+10zig8PJyGDRvy66+/1nYqIiIiUo205pmIiIiIyHn6+++/Wb9+PXfddVdtpyIiIiLVTGueiYiIiIico82bNxMTE8O0adNo1qwZt912W22nJCIiItVMI89ERERERM7RV199xT333ENRURGffvopnp6etZ2SiIiIVDOteSYiIiIiIiIiIlIFjTwTERERERERERGpgopnIiIiIiIiIiIiVajVDQOmTJnCiy++WO5Yhw4dSEhIACA/P58nnniCzz77jIKCAgYOHMh7771HYGDgWZ+jtLSUtLQ0fH19MRgM1Zq/iIiIiIiIiIjUHVarlezsbIKDg3FxObsxZbW+22anTp1YunSp/bKb24mUHn/8cX744Qe+/PJL/P39mTBhAjfffDOrVq066/hpaWmEhIRUa84iIiIiIiIiIlJ3paam0qJFi7NqW+vFMzc3N4KCgiocz8rKYvbs2SxYsICrrroKgDlz5mCxWFizZg2XXnrpWcX39fUFbJ3i5+dXfYmLiIiIiIiIiEidcvToUUJCQuz1orNR68WzxMREgoOD8fT0pHfv3kydOpWWLVsSExNDUVERV199tb2t2WymZcuWrF69usriWUFBAQUFBfbL2dnZAPj5+al4JiIiIiIiIiIiDi3tVasbBvTq1Yu5c+fy888/M3PmTJKTk7n88svJzs4mPT0dDw8PAgICyt0mMDCQ9PT0KmNOnToVf39/+z9N2RQRERERERERkXNVqyPPrrvuOvv/u3btSq9evWjVqhVffPEFJpPpnGJOmjSJiRMn2i+XDccTERERERERERFxVK2OPDtVQEAA7du3Z8eOHQQFBVFYWEhmZma5Nvv37690jbQyRqPRPkVTUzVFREREREREROR81PqaZyfLyckhKSmJO++8k8jISNzd3fn1118ZPnw4ANu2bWP37t307t27ljMVERERERERqRklJSUUFRXVdhoidZa7uzuurq7VFq9Wi2dPPvkkQ4cOpVWrVqSlpTF58mRcXV2544478Pf3Z+zYsUycOJGGDRvi5+fHww8/TO/evc96p00RERERERGRuiQnJ4c9e/ZgtVprOxWROstgMNCiRQt8fHyqJV6tFs/27NnDHXfcweHDh2nSpAl9+/ZlzZo1NGnSBIC33noLFxcXhg8fTkFBAQMHDuS9996rzZRFREREREREakRJSQl79uzBy8uLJk2aOLQboIjYWK1WDh48yJ49ewgLC6uWEWgG60Vezj569Cj+/v5kZWVp/TMRERERERFxWvn5+SQnJxMaGnrOm+iJCOTl5ZGSkkLr1q3x9PQsd9251ImcasMAERERERERkfpOI85Ezk91/w6peCYiIiIiIiIiIlIFFc9ERERERERERESqoOKZiIiIiIiIiEgNmDJlCoGBgRgMBr755ptzijF37lwCAgKqNa/TGT16NMOGDbtg56sLVDwTERERERERkfO2evVqXF1dGTJkSG2n4hTi4+N58cUXmTVrFvv27eO6666r7ZTkHKl4JiIiIiIiIiLnbfbs2Tz88MOsWLGCtLS0Gj2X1WqluLi4Rs9xvpKSkgC48cYbCQoKwmg0XrBzFxYWXrBz1bSioqLaTkHFMxEREZGLXW5uLqtWrWL+/PmsWrWK3Nzc2k5JRETOgtVqJbewuFb+Wa1Wh3LNycnh888/54EHHmDIkCHMnTvXft3IkSO57bbbyrUvKiqicePGfPzxxwCUlpYydepUWrdujclkolu3bnz11Vf29suXL8dgMPDTTz8RGRmJ0Whk5cqVJCUlceONNxIYGIiPjw+XXHIJS5cuLXeuffv2MWTIEEwmE61bt2bBggWEhoYyffp0e5vMzEzGjRtHkyZN8PPz46qrrmLDhg2nvc+bNm3iqquuwmQy0ahRI+69915ycnIA23TNoUOHAuDi4lLl7o9l9+uHH36ga9eueHp6cumll7J58+YKbRcvXozFYsHHx4dBgwaxb98++3VlUy3/9a9/ERwcTIcOHQBITU1lxIgRBAQE0LBhQ2688UZSUlLstyspKWHixIkEBATQqFEjnn766TM+9rt27WLo0KE0aNAAb29vOnXqxI8//mi/fsuWLVx//fX4+fnh6+vL5Zdfbi8klpaW8tJLL9GiRQuMRiPdu3fn559/tt82JSUFg8HA559/Tr9+/fD09GT+/PkAfPjhh1gsFjw9PTGbzbz33nunzbM6uV2wM4mIiIhIrUhISKBv3772yzExMURERNRiRiIicjbyikro+MLiWjn31pcG4uVx9iWDL774ArPZTIcOHYiKiuKxxx5j0qRJGAwGRo0axa233kpOTg4+Pj6ArRCUm5vLTTfdBMDUqVOJjo7m/fffJywsjBUrVhAVFUWTJk3o16+f/TzPPvssb7zxBm3atKFBgwakpqYyePBg/vWvf2E0Gvn4448ZOnQo27Zto2XLlgDcddddHDp0iOXLl+Pu7s7EiRM5cOBAufxvvfVWTCYTP/30E/7+/syaNYsBAwawfft2GjZsWOH+Hjt2jIEDB9K7d2/WrVvHgQMHGDduHBMmTGDu3Lk8+eSThIaGcs8995QrclXlqaee4j//+Q9BQUH84x//YOjQoWzfvh13d3fA9kXYG2+8wSeffIKLiwtRUVE8+eST9sISwK+//oqfnx9LliwBbAXKshz/+OMP3NzceOWVVxg0aBAbN27Ew8ODadOmMXfuXD766CMsFgvTpk1j0aJFXHXVVVXm+tBDD1FYWMiKFSvw9vZm69at9sd17969XHHFFfTv35/ffvsNPz8/Vq1aZR8l+J///Idp06Yxa9YswsPD+eijj7jhhhvYsmULYWFh5R7nadOmER4ebi+gvfDCC8yYMYPw8HDi4uIYP3483t7e3H333Wfs3/Ol4pmIiIjIRc5sNhMdHU1UVBTR0dGYzebaTklERC4ys2fPJioqCoBBgwaRlZXF77//Tv/+/Rk4cCDe3t4sWrSIO++8E4AFCxZwww034OvrS0FBAa+++ipLly6ld+/eALRp04aVK1cya9ascsWzl156iWuuucZ+uWHDhnTr1s1++eWXX2bRokV8++23TJgwgYSEBJYuXcq6devo0aMHYBvBdHKhZuXKlaxdu5YDBw7Yp1a+8cYbfPPNN3z11Vfce++9Fe7vggULyM/P5+OPP8bb2xuAGTNmMHToUF5//XUCAwPti/wHBQWdsf8mT55sv1/z5s2jRYsWLFq0iBEjRgC2Qtj7779P27ZtAZgwYQIvvfRSuRje3t58+OGHeHh4ABAdHU1paSkffvihfeTbnDlzCAgIYPny5Vx77bVMnz6dSZMmcfPNNwPw/vvvs3jx6Qu2u3fvZvjw4XTp0gWwPVZl3n33Xfz9/fnss8/shb/27dvbr3/jjTd45plnuP322wF4/fXXWbZsGdOnT+fdd9+1t3vsscfsOZX1z7Rp0+zHWrduzdatW5k1a5aKZyIiIiJy/ry8vLBYLABYLBa8vLxqOSMRETkbJndXtr40sNbOfba2bdvG2rVrWbRoEQBubm7cdtttzJ49m/79++Pm5saIESOYP38+d955J8eOHeN///sfn332GQA7duwgNze3XFEMbOt2hYeHlztWVgArk5OTw5QpU/jhhx/Yt28fxcXF5OXlsXv3bntubm5u5UZct2vXjgYNGtgvb9iwgZycHBo1alQudl5enn264ani4+Pp1q2bvXAG0KdPH0pLS9m2bRuBgYFn1XdlyoqGYCsIdujQgfj4ePsxLy8ve+EMoFmzZhVGz3Xp0sVeOCu7Xzt27MDX17dcu/z8fJKSksjKymLfvn306tXLfp2bmxs9evQ47dTNRx55hAceeIBffvmFq6++muHDh9O1a1cA1q9fz+WXX24vnJ3s6NGjpKWl0adPn3LH+/TpU2GK7MmP87Fjx0hKSmLs2LGMHz/efry4uBh/f/8q86xOKp6JiIiIiIiIOCGDweDQ1MnaMnv2bIqLiwkODrYfs1qtGI1GZsyYgb+/P6NGjaJfv34cOHCAJUuWYDKZGDRoEIB9nbAffviB5s2bl4t96iL7JxerAJ588kmWLFnCG2+8Qbt27TCZTNxyyy0OLZifk5NDs2bNWL58eYXrykaP1bZTi1EGg6FCgevUvsnJySEyMrLc1M4yTZo0Oedcxo0bx8CBA/nhhx/45ZdfmDp1KtOmTePhhx/GZDKdc9yTnXxfyp4fH3zwQblCH4Cr69kXec+H8/8WioiIiNSQ3Nxc4uLiSElJITQ0FJPJhNlsrpWRWafmEh4eXmt5JCQkkJeX5xS5OMvjIyIilSsuLubjjz9m2rRpXHvtteWuGzZsGJ9++in3338/l112GSEhIXz++ef89NNP3HrrrfaCUMeOHTEajezevbvcFM2zsWrVKkaPHm1fOy0nJ6fcgvgdOnSguLiYuLg4IiMjAdtIt4yMDHubiIgI0tPTcXNzIzQ09KzOa7FYmDt3LseOHbMXelatWoWLi4t9sX5HrFmzxr5GW0ZGBtu3b7ePGj9XERERfP755zRt2hQ/P79K2zRr1oy//vqLK664ArA9nmezNmpISAj3338/999/P5MmTeKDDz7g4YcfpmvXrsybN4+ioqIKBT8/Pz+Cg4NZtWpVucd51apV9OzZs8pzBQYGEhwczM6dOxk1atTZ3v1qpeKZiIiI1FunLqQPtbeYvrMs6p+QkGD/cOEMuTjL4yMiIpX7/vvvycjIYOzYsRWm0A0fPpzZs2dz//33A7ZdN99//322b9/OsmXL7O18fX158sknefzxxyktLaVv375kZWWxatUq/Pz8TrumVVhYGAsXLmTo0KEYDAaef/55SktL7debzWauvvpq7r33XmbOnIm7uztPPPEEJpPJvg7Y1VdfTe/evRk2bBj/93//R/v27UlLS+OHH37gpptuqjBVFGDUqFFMnjyZu+++mylTpnDw4EEefvhh7rzzToenbIJtLbdGjRoRGBjIP//5Txo3bsywYcMcjnNqjv/+97+58cYb7Ttc7tq1i4ULF/L000/TokULHn30UV577TXCwsIwm828+eabZGZmnjbuY489xnXXXUf79u3JyMhg2bJl9kLfhAkTeOedd7j99tuZNGkS/v7+rFmzhp49e9KhQweeeuopJk+eTNu2benevTtz5sxh/fr1lY6OO9mLL77II488gr+/P4MGDaKgoIC///6bjIwMJk6ceF79dDZcavwMIiIiIk6qbCF9sC2qGxMTU2uL6Z+aS23mERMT4zS5OMvjIyIilZs9ezZXX311pWtPDR8+nL///puNGzcCtmLO1q1bad68eYV1r15++WWef/55pk6disViYdCgQfzwww+0bt36tOd/8803adCgAZdddhlDhw5l4MCBFb5k+fjjjwkMDOSKK67gpptuYvz48fj6+uLp6QnYpkD++OOPXHHFFdxzzz20b9+e22+/nV27dlVZCPPy8mLx4sUcOXKESy65hFtuuYUBAwYwY8aMs+67k7322ms8+uijREZGkp6eznfffVdu/bJz4eXlxYoVK2jZsiU333wzFouFsWPHkp+fbx+J9sQTT3DnnXdy991307t3b3x9fe2j+KpSUlLCQw89ZH+c2rdvz3vvvQdAo0aN+O2338jJyaFfv35ERkbywQcf2EehPfLII0ycOJEnnniCLl268PPPP/Ptt9+W28ChMuPGjePDDz9kzpw5dOnShX79+jF37twzPj+qi8F6ulXgLgJHjx7F39+frKysKocpioiISP0VGxtLZGSkU4xoqslcHI3tLP3iLHmIiFwI+fn5JCcn07p1a3thR6rfnj17CAkJYenSpQwYMKBWc1m+fDlXXnklGRkZTrO+2sXgdL9L51In0rRNEREREREREblolY2E6tKlC/v27ePpp58mNDTUvs6XyJmoeCYiIiIiIiIiF62ioiL+8Y9/sHPnTnx9fbnsssuYP39+hQXtRaqi4pmIiIiIiIiIXLQGDhzIwIEDazuNSvXv35+LfDWti4I2DBAREREREREREamCRp6JiIiIiFyEcnNzSUhIIC8vj5SUFEJDQwkPD8fLy6vK9nFxcfa2JpMJs9lcZXsREZH6QsUzEREREZGLUEJCApGRkeWOnW7X0oSEBPr27XvW7UVEROoLTdsUEREREbkImc1mYmJiiI6OBiA6Ohqz2Xza9ie3jYmJOW17ERGR+kIjz0RERERELkJeXl7lRo1ZLJbTTsH08vLCYrHY22rEmYiIiI2KZyIiIiIi1ciRtcPq6rpkdTVvERGRc6HimYiIiIhINXJk7bC6ui5ZXc1bROqu5cuXc+WVV5KRkUFAQABz587lscceIzMzs7ZTY9WqVdx///0kJCQwZMgQvvnmm3OKYzAYWLRoEcOGDavW/Cpzan/K6WnNMxERERGRauTI2mF1dV2yupq3iNSM0aNHYzAYuP/++ytc99BDD2EwGBg9enS1nvO2225j+/bt1RrzXE2cOJHu3buTnJzM3LlzazsdqQEqnomIiIiIVKPK1g6ranpi2bpkJ7d3dF2y2pj6WFfzFpGaExISwmeffUZeXp79WH5+PgsWLKBly5bVfj6TyUTTpk2rPe65SEpK4qqrrqJFixYXdBSX1WqluLj4gp2vJhUWFtZ2Cqel4pmIiIiIiIiInJeIiAhCQkJYuHCh/djChQtp2bIl4eHh5dqWlpYydepUWrdujclkolu3bnz11Vfl2vz444+0b98ek8nElVdeSUpKSrnr586dW65QlZSUxI033khgYCA+Pj5ccsklLF26tNxtQkNDefXVVxkzZgy+vr60bNmS//73v6e9XwUFBTzyyCM0bdoUT09P+vbty7p16wBISUnBYDBw+PBhxowZg8FgqHLkWWhoKC+//DJ33HEH3t7eNG/enHfffbdCu0OHDnHTTTfh5eVFWFgY3377rf265cuXYzAY+Omnn4iMjMRoNLJy5cpq6c9TWa1WpkyZQsuWLTEajQQHB/PII4+U65dnnnmGkJAQjEYj7dq1Y/bs2fbrf//9d3r27InRaKRZs2Y8++yz5Qp9/fv3Z8KECTz22GM0btyYgQMHArB582auu+46fHx8CAwM5M477+TQoUOnzfVCUPFMRERERERExJllp0Pa+gv3Lzv9nNIcM2YMc+bMsV/+6KOPuOeeeyq0mzp1Kh9//DHvv/8+W7Zs4fHHHycqKorff/8dgNTUVG6++WaGDh3K+vXrGTduHM8+++xpz52Tk8PgwYP59ddfiYuLY9CgQQwdOpTdu3eXazdt2jR69OhBXFwcDz74IA888ADbtm2rMu7TTz/N119/zbx584iNjaVdu3YMHDiQI0eOEBISwr59+/Dz82P69Ons27eP2267rcpY//73v+nWrRtxcXE8++yzPProoyxZsqRcmxdffJERI0awceNGBg8ezKhRozhy5Ei5Ns8++yyvvfYa8fHxdO3atUb68+uvv+att95i1qxZJCYm8s0339ClSxf79XfddReffvopb7/9NvHx8cyaNQsfHx8A9u7dy+DBg7nkkkvYsGEDM2fOZPbs2bzyyivlzjFv3jw8PDxYtWoV77//PpmZmVx11VWEh4fz999/8/PPP7N//35GjBhx2lwvBG0YICIiIiIiIuLM/p4Dv7924c7X71m4cpLDN4uKimLSpEns2rULsC2k/9lnn7F8+XJ7m4KCAl599VWWLl1K7969AWjTpg0rV65k1qxZ9OvXj5kzZ9K2bVumTZsGQIcOHdi0aROvv/56lefu1q0b3bp1s19++eWXWbRoEd9++y0TJkywHx88eDAPPvggAM888wxvvfUWy5Yto0OHDhViHjt2jJkzZzJ37lyuu+46AD744AOWLFnC7NmzeeqppwgKCsJgMODv709QUNBp+6dPnz72olX79u1ZtWoVb731Ftdcc429zejRo7njjjsAePXVV3n77bdZu3YtgwYNsrd56aWX7Lepqf7cvXs3QUFBXH311bi7u9OyZUt69uwJwPbt2/niiy9YsmQJV199tf2cZd577z1CQkKYMWMGBoMBs9lMWloazzzzDC+88AIuLrZxXGFhYfzf//2f/XavvPIK4eHhvPrqq/ZjH330ESEhIWzfvp327duftn9rkopnIiIict5yc3OJi4sjJSWF0NBQTCYTZrO5VtY0OjWX8PDwasvDkdjO1CciIlLH9bgHOlx34c7ne/oiUFWaNGnCkCFDmDt3LlarlSFDhtC4ceNybXbs2EFubm65ghHY1rwqm94ZHx9Pr169yl1fVhiqSk5ODlOmTOGHH35g3759FBcXk5eXV2HkWdeuXe3/NxgMBAUFceDAgUpjJiUlUVRURJ8+fezH3N3d6dmzJ/Hx8afNpzKn3ofevXszffr0KvPz9vbGz8+vQn49evSw/7+m+vPWW29l+vTptGnThkGDBjF48GCGDh2Km5sb69evx9XVlX79+lV62/j4eHr37o3BYLAf69OnDzk5OezZs8e+Bt6puzZv2LCBZcuW2UewnSwpKUnFMxEREanbEhIS6Nu3b7ljMTExRERE1Hou1ZmHI7GdqU9ERKSO8w0654LWhTZmzBj7SK/K1vTKyckB4IcffqB58+blrjMajed83ieffJIlS5bwxhtv0K5dO0wmE7fcckuFhejd3d3LXTYYDJSWlp7zeavb2eTn7e1t/39N9WdISAjbtm1j6dKlLFmyhAcffJB///vf/P7775hMpnOOe7KT7wfY7svQoUMrHRHXrFmzajnnudKaZyIiInLezGYz0dHRAERHRxMTE4PZbHaKXKozD0diO1OfiIiIXCiDBg2isLCQoqIi+yLwJ+vYsSNGo5Hdu3fTrl27cv9CQkIA2668a9euLXe7NWvWnPa8q1atYvTo0dx000106dKFoKCgMy6KfyZt27a1r8lVpqioiHXr1tGxY0eH4516H9asWWPfifhc1VR/gm1H06FDh/L222+zfPlyVq9ezaZNm+jSpQulpaX2NdVOZbFYWL16NVar1X5s1apV+Pr60qJFiyrPFxERwZYtWwgNDa1wX04ttF1oKp6JiIjIefPy8rK/+bNYLERERNTa9MRTc6nOPByJ7Ux9IiIicqG4uroSHx/P1q1bcXV1rXC9r68vTz75JI8//jjz5s0jKSmJ2NhY3nnnHebNmwfA/fffT2JiIk899RTbtm1jwYIFVe5iWSYsLIyFCxeyfv16NmzYwMiRI897RJm3tzcPPPAATz31FD///DNbt25l/Pjx5ObmMnbsWIfjrVq1iv/7v/9j+/btvPvuu3z55Zc8+uij55VjTfXn3LlzmT17Nps3b2bnzp1ER0djMplo1aoVoaGh3H333YwZM4ZvvvmG5ORkli9fzhdffAHAgw8+SGpqKg8//DAJCQn873//Y/LkyUycONG+3lllHnroIY4cOcIdd9zBunXrSEpKYvHixdxzzz2UlJScVz+dLxXPRERERERERKTa+Pn54efnV+X1L7/8Ms8//zxTp07FYrEwaNAgfvjhB1q3bg1Ay5Yt+frrr/nmm2/o1q0b77//frlF5Cvz5ptv0qBBAy677DKGDh3KwIEDq2WphNdee43hw4dz5513EhERwY4dO1i8eDENGjRwONYTTzzB33//TXh4OK+88gpvvvlmpaPzHFUT/RkQEMAHH3xAnz596Nq1K0uXLuW7776jUaNGAMycOZNbbrmFBx98ELPZzPjx4zl27BgAzZs358cff2Tt2rV069aN+++/n7Fjx/Lcc8+d9pzBwcGsWrWKkpISrr32Wrp06cJjjz1GQEDAaYtuF4LWPBMRERERERGRc3amUUzffPNNucsGg4FHH330tKOurr/+eq6//vpyx+655x77/0ePHs3o0aPtl0NDQ/ntt9/KtX/ooYfKXa5sGuf69etPm7unpydvv/02b7/9dpVtMjMzTxujjJ+fn310VmVOnuZYWez+/ftX2qY6+vNUw4YNY9iwYVVe7+npyZtvvsmbb75Z6fX9+vWrMFX0ZCfvwHqyshGEzkbFMxERERERqRdyc3NJSEggLy+v2nfNdTS2iIjUHSqeiYiIiIhI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bxGR2uLI66b+douInJlGnomIiIiIiIiIiFRBxTMREREREREREZEqqHgmIiIiIiIiIiJSBRXPREREREREREREqqANA0RERERERESOy83NJSEhgby8PFJSUggNDSU8PFwbKYjUYyqeiYiIiIiIiByXkJBAZGRkuWMxMTHa7VmkHtO0TREREREREZHjzGYzMTExREdHAxAdHY3ZbK7lrESkNmnkmYiIiIiIiMhxXl5e5UaZWSwWTdkUqec08kxERERERERERKQKGnkmNcrRxTZzc3OJi4uztzWZTJjN5krbO1NsERERERGpnxz5nCEidZOKZ1KjHF1sMyEhgb59+55Ve2eKLSIiIiIi9ZMjnzNEpG7StE2pUY4utmk2m8u1jYmJqbK9M8UWEREREZH6yZHPGSJSN2nkmdQoRxfb9PLywmKx2Nue7tsaZ4otIiIiIiL1kyOfM0SkbtLIMxERERERERERkSqoeCYiIiIiIiIiIlIFFc9ERERERERERESqoOKZiIiIiIiIiIhIFVQ8ExERERERERERqYKKZyIiIiIiIiIiIlVQ8UxERERERERERKQKKp6JiIiIiIiIiIhUwa22ExCp6xITE8nOziY+Ph7A/tPX15ewsLDzaq/Ylbd3hLPk7Sz3UXlXz3MwMTGxRvrEUTX5+JxLLs6SR009ls4U2xHV8ftQFx5LERERqX25ubnExcWRkpJCaGgo4eHheHl51UoeCQkJ5OXlVUsuKp6JnIfExETat29f7lhUVJT9/9u3by/3Bt+R9opdeXtHOEveznIflff5x66sfXX1iaNq8vE531ycJY8z5eJI3s4U2xHV+fvgzI+liIiIOIeEhAT69u1rvxwTE0NERESt5BEZGVnu2PnkouKZyHnIzs4GIDo6mtDQUHtFOyUlhaioKPv159JesStv7whnydtZ7qPyrp7nYNnl2bNnYzQaq61PHFWTj8+55lLX+sSRvJ0p9oXok5PbFxQUMHbsWKd+LEVERMQ5mM1moqOjiYqKIjo6GrPZXGt5xMTEEB8fXy25qHgmUg0sFgsRERH06dMHAJPJVG3tFfv8OUveznIfHW1fX/J2tH337t3t31xVZ584qiYfH0fV1T5xJG9niu2I8/l9iI2NrbY8HOVMz28RERE5My8vLywWC2D7O14bUzbL8jh5lNn55qINA0RERERERERERKqg4pmI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nF7/bEQ1DdRjV0Rr+shO+nJLut5Zs0drMsqe4L9p/wn5Ff938YWmjXwVEeKvyFB/RYS2UeTYvooIDVD2/u2687MX9OkT49WnT5zVS3mEqta+00Ut9ePcv+mGWQv1+ZfS26lFunhgE93eu+05t12eL697ZbI10XZVWfXFbCKspra1qqj05JlhGJo4caL8/P67POupU6d0zz33qFGj/85oL126tHp76ME27T+hO+at05GThWoe5KcMST2iGtd2twAAAADgnIT4++iOhHZ6adkOvbxsh67oFqEGdWTlzf3H8/TXj7ZKkjpHBOt/E2Pl+/vzqj3h9jBJenJ0V6XsPa5fD53UC98ckFR2Tv711gw995VDvx0um/xrF9ZIj46K1uVdW8jLq/br4+/TUNf2bq1re7fW++2LNX5+2cqlCQP6KjLUXy1C/OXvY361WIpXpiTVmd8zV4G+3vrr1V30+dOSYUhPf7ZNaUdz9deru5z1wgQ4fyo9eXbbbbed8bny513VR2t3H9VLH2Yqv6hEXSJD9EDvnrrstdruFQAAAABUjzsS2umtpN3afihHX2/N0BXdI2u7S+fs6MkCTXhzrY7klj2YfOborgr0/e9psSfcHiZJAb4N9drNsRr9apLW7zshSXrsg83aUVr2aKBmjXx1/8hOuqlfm7NeCKCmdQwvm2gcHh2u2PbNark3nqF8kuyOhLZ6d5f09po92nssT6/eHKsgv0pPz9QpxSWlSk3Pqu1uuFXp6sydO7cm+3HBeeazbfJp0VFDLm6u12+J1a9bN9V2lwAAAACg2oQG+uj2hLZ6eflOvbRshy7vemFffXayoFi3z1un347kOu8cCgnwqZDxhNvDynVqEaynx3TT/a/+KknacjBLIa1baNLgdrpnaAcF+/u4aQGealxclAYNiNT09zZoxfbD+sOcH/XWxL5q2djqCXd106miEt27IFlfrSybT3nms226VeEaEdNCoQGe9fvtmVPUHqq01ND8H3eX/b8h3dCntd68rU+9nSEGAAAAULfdMaidgvy85cjI0TfbDtV2d87avuN5Gv/GGm3an6UmgT56Zmy32u5SpVwf11qjukVIkkbGtNCKR4bpkcujmTirA67oHqn37o5XWJCfHBk5Gvvaam3ef36uwDpZUKx5v89tvJm0W/N/TNN32w5p28FsZeWfn+fa5xYU64556/T9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R40apRUrVujPf/6zunfv7vy66/7mlVdesd0uq7J/MsvabZeu+WnTpllul67Za6+91na7dM3fd999ltula/bRRx+13S6t3hOzWrpmp0+fbrtdmrVttV26HgtcddVVtrWsyrGDWdaulq75Dh06WNbSNXvppZfa1tKsL1a1dM12797dtpZW74lZLV2zvXr1sq2lWdtWtXQ9TuvSpYvtGFuV4zqzrN0Ya5a3GmNdsxEREbZjrFnbVmOsWdZujLV6T8xqaZa1G2PN8lZjbLnTj6UDAwNt61mV426zvF09XbNWtTTLOxwO23q6tm1VS6u8XT3N3hO741jXvF09XbN2tXQ9z8nJybGsZVXOiazyVrU0y9rV0jV/4sQJy1qatW1XS7O8VS2t3hOrWprlrWpplrWrpet56PTp0y33mVU9ZzXLW+0zXbPXXHON7fmla753796W+0yzftidX5rlrfaZVu+JVS1d89dee63lPtOsbav95emszi0jIyO1a9cu5eTk6NixY7aPlaqg0k9Hq0MefvhhY9CgQcbNN99cqQfkX3HFFUZkZKQxYMAAY+7cubbZt99+22jatKkxdOhQY+jQocbixYstsz///LMxePBgY9iwYcaoUaOMgwcPVqr/dg/1K/fFF18YsbGxxqBBg4xbb73VKCoqcvs9r776qjF48GBjyJAhxs6dO922P23atEr1t6ioyLjhhhuMIUOGGP379zdWr15tmU1PTzeGDRtmXHLJJcasWbMsc641Wbx4sREfH28MHz7c2Lt3r9v8Y489ZnTp0sXo3LmzMX36dMvs008/bTRs2NBZz8cee8y27Tlz5jizgwYNMlatWmXbj3JWC1Kcnn/22WeN2NhYY/DgwcbIkSPP+Dld2169erUxaNAgo1+/fqYPcHXNnzhxwvJ3yzX73HPPGf379zf69u1rzJkzx21+/PjxxvDhw42JEycaubm5zpzZ9mJXS7O8VS1ds/PmzbOtpVneqpZ227lZLc3yVrU0y9rV0ixvVUuzrF0tzfJWtTQbz1auXGnEx8cbAwcONDZs2FChbbP8iy++aMTGxhpt2rRxPuDVLLt//37Dx8fHGDhwoDF06NAzHiZr1vaYMWOMoUOHGvHx8cYHH3xgmy335JNPnvF+m+Xj4uKMQYMGGYMGDTI2btxom3U4HMawYcOM/v37G//617/ctl1SUmJ07dr1jDHcLPv2228bffv2NQYMGGD85S9/cZu///77jeHDhxvjxo0zDh8+fMbvi2H8d3/jbox1zduNsadn9+7d63aMPT2fn59vO8a69qOcu0V/4uLijIyMDNsx1rVtd2Osa95ujHXNuhtjXfNW26XZsYBdLc3yVrV0zbqrpWs+JyfHspZ2xzBmtXTN29XSrG27WprlrWpplrWrpVneqpaGceZxmt0Ya5a3GmPNsnZjrFneaow1y5YzG2PN8lZjrFnWbow1y1uNsWZZuzHWLO9ujHU9lrarp2vWrpau+eLiYtt6urZtV0uzfDmzerpm7Wpplrerp2vWrpZmebt6umbtaml2nmNVS7OsXS1d80lJSZa1NGvbrpZ252eutTTL2tXSLG9VS7OsXS3N8la1NMva1dLsPNRqn2mWtTv2cc3b7TNds+6OfezOn133ma5Zd8c+Zm1b7TPNsnbHPmZ5q32mWdZqf1mZeYKtW7cagwYNMuLj441vvvnGtH9mvAzDzSUjAAAAAAAAQD1V727bBAAAAAAAACqLyTMAAAAAAADAApNnAAAAAAAAgAUmzwAAAAAAAAALTJ4BAAAAAAAAFpg8AwAAAAAAACwweQYAAAAAAABYYPIMAACgilasWCEvLy+dOHHCNte2bVu9+OKLNdqXefPmqXHjxjX6GtVt2LBhmj59utvckCFDtHDhQufHXl5e+uijj87ptbdt26bWrVsrNzf3nNoBAAD1B5NnAACgTpo4caK8vLzk5eUlX19fdezYUU8//bSKi4vPue2BAwcqPT1doaGhkqwnsNatW6e77rrrnF/Pzvjx4/Xrr7/W6GvUhk8++USHDh3SjTfeWK3tdunSRQMGDND//M//VGu7AACg7mLyDAAA1FmjRo1Senq6duzYoYceekgzZ87U888/f87t+vr6KiIiQl5eXra55s2bKzAw8Jxfz05AQIDCw8Ortc2SkhKVlpZWa5tV9fLLL+v2229XgwbVf7h6++23a86cOdUykQoAAOo+Js8AAECd5efnp4iICF100UW69957NXLkSH3yySeSpOPHj2vChAlq0qSJAgMDdcUVV2jHjh3O792zZ49Gjx6tJk2aqFGjRuratau++OILSRVv21yxYoVuv/12ZWVlOa90mzlzpqQzb9vcu3evxowZo6CgIIWEhOiGG27QoUOHnF+fOXOmevXqpXfeeUdt27ZVaGiobrzxRuXk5Fj+jK5XvZ1LG5988om6dOkiPz8/7d27VwUFBXr44YfVqlUrNWrUSP3799eKFSuc33f06FHddNNNatWqlQIDA9W9e3ctWrSoQtu5ubmaMGGCgoKCFBkZqRdeeMGyH+UOHz6s5cuXa/To0Wd8LT09XVdccYUCAgLUvn17/ec//3F+LS0tTV5eXlq8eLEGDhwof39/devWTStXrqzQxqWXXqpjx46d8XkAAAAzTJ4BAIB6IyAgQIWFhZLKbuv85Zdf9Mknn2jNmjUyDENXXnmlioqKJElTpkxRQUGBVq1apc2bN+u5555TUFDQGW0OHDhQL774okJCQpSenq709HQ9/PDDZ+RKS0s1ZswY56TNt99+q99++03jx4+vkNu1a5c++ugjffbZZ/rss8+0cuVKPfvss1X6Oc+mjby8PD333HP697//ra1btyo8PFxTp07VmjVrtHjxYm3atEnXX3+9Ro0a5ZxkPHXqlOLi4vT5559ry5Ytuuuuu3Trrbdq7dq1znYfeeQRrVy5Uh9//LG++eYbrVixQikpKbZ9SUpKUmBgoGJiYs742l/+8heNGzdOGzdu1C233KIbb7xRqampFTKPPPKIHnroIa1fv17x8fEaPXq0jh496vy6r6+vevXqpR9++MHtewkAAOBd2x0AAACoaYZhaNmyZfr66681bdo07dixQ5988olWr16tgQMHSpLeffddRUVF6aOPPtL111+vvXv3aty4cerevbskqX379qZt+/r6KjQ0VF5eXoqIiLDsw7Jly7R582bt3r1bUVFRkqS3335bXbt21bp169S3b19JZZNs8+bNU3BwsCTp1ltv1bJlyzRr1qxK/7xn00ZRUZFef/119ezZU1LZVXJz587V3r171bJlS0nSww8/rK+++kpz587V3//+d7Vq1arCROG0adP09ddf6/3331e/fv108uRJvfnmm1qwYIFGjBghSZo/f75at25t2/89e/aoRYsWprdsXn/99Zo0aZIk6ZlnntG3336rV155Ra+//rozM3XqVI0bN06SNGfOHH311Vd688039ac//cmZadmypfbs2WPbDwAAAInJMwAAUId99tlnCgoKUlFRkUpLS3XzzTdr5syZWrZsmby9vdW/f39ntlmzZurcubPzKqY//vGPuvfee/XNN99o5MiRGjdunHr06HHWfUlNTVVUVJRz4kwqe3h948aNlZqa6pw8a9u2rXPSS5IiIyOVmZlZpdc6mzZ8fX0r/HybN29WSUmJLr744gq5goICNWvWTFLZs9H+/ve/6/3339eBAwdUWFiogoIC53Pedu3apcLCwgrvc9OmTdW5c2fbvuTn58vf39/0a/Hx8Wd8vGHDBsuMt7e3+vTpc8bVaQEBAcrLy7PtBwAAgMTkGQAAqMOGDx+uOXPmyNfXVy1btpS3d+UPfSZNmqTLL79cn3/+ub755hvNnj1bL7zwgqZNm1aDPZZ8fHwqfOzl5VXlh/efTRsBAQEVFkA4efKkGjZsqOTkZDVs2LBCtvz21eeff14vvfSSXnzxRXXv3l2NGjXS9OnTnbfGnq2wsDAdP378nNpw59ixY+rQoUONvgYAAKgbeOYZAACosxo1aqSOHTuqTZs2FSbOYmJiVFxcrJ9//tn5uaNHj2r79u3q0qWL83NRUVG65557tHTpUj300EP6v//7P9PX8fX1VUlJiW1fYmJitG/fPu3bt8/5uW3btunEiRMVXtNT9O7dWyUlJcrMzFTHjh0r/Cu/PXX16tUaM2aMEhMT1bNnT7Vv316//vqrs40OHTrIx8enwvt8/PjxChmr187IyDCdQPvpp5/O+Nj12WinZ4qLi5WcnHxGZsuWLerdu7ebdwEAAIDJMwAAUA916tRJY8aM0eTJk5WUlKSNGzcqMTFRrVq10pgxYyRJ06dP19dff63du3crJSVF33//vekD7KWy2yRPnjypZcuW6ciRI6a3A44cOVLdu3fXLbfcopSUFK1du1YTJkzQ0KFD1adPnxr9ec/GxRdfrFtuuUUTJkzQ0qVLtXv3bq1du1azZ8/W559/Lqnsffz222/1448/KjU1VXfffXeF1UODgoJ055136pFHHtHy5cu1ZcsWTZw40fRZZqfr3bu3wsLCtHr16jO+tmTJEr311lv69ddf9eSTT2rt2rWaOnVqhcxrr72mDz/8UA6HQ1OmTNHx48d1xx13OL+elpamAwcOaOTIkefyFgEAgHqCyTMAAFAvzZ07V3Fxcbr66qsVHx8vwzD0xRdfOG95LCkp0ZQpUxQTE6NRo0bp4osvrvBQ+tMNHDhQ99xzj8aPH6/mzZvrH//4xxkZLy8vffzxx2rSpImGDBmikSNHqn379nrvvfdq9Oc8F3PnztWECRP00EMPqXPnzho7dqzWrVunNm3aSJKeeOIJxcbG6vLLL9ewYcMUERGhsWPHVmjj+eef1+DBgzV69GiNHDlSgwYNUlxcnO3rNmzYULfffrvefffdM7721FNPafHixerRo4fefvttLVq06Iwr95599lk9++yz6tmzp5KSkvTJJ58oLCzM+fVFixbpsssu00UXXXSW7wwAAKhPvAzDMGq7EwAAAMDpMjIy1LVrV6WkpFR6kistLU3t2rXT+vXr1atXL9NMYWGhOnXqpIULFyohIaEaewwAAOoqrjwDAACAx4mIiNCbb76pvXv3Vmu7e/fu1eOPP87EGQAAqDRW2wQAAIBHcr0FtDqUL3oAAABQWdy2CQAAAAAAAFjgtk0AAAAAAADAApNnAAAAAAAAgAUmzwAAAAAAAAALTJ4BAAAAAAAAFpg8AwAAAAAAACwweQYAAAAAAABYYPIMAAAAAAAAsMDkGQAAAAAAAGDh/wNdEhNCmlP/BgAAAABJRU5ErkJggg==", "text/plain": [ "
" ] @@ -107,6 +97,24 @@ "pb.visualize_base_sequence_quality(result)" ] }, + { + "cell_type": "markdown", + "id": "5126c39b", + "metadata": {}, + "source": [ + "##### Performance Benchmarking\n", + "| Implementation | Target Partitions | Time |\n", + "| -------------- | ----------------- | ----- |\n", + "| fastqc-rs | - | 22.9s |\n", + "| polars_bio | 1 | 9.0s |\n", + "| polars_bio | 2 | 8.5s |\n", + "| polars_bio | 4 | 15.6s |\n", + "| polars_bio | 8 | 7.8s |\n", + "\n", + "- The measured execution time is for the algorithm to run on file ftp://ftp.sra.ebi.ac.uk/vol1/fastq/ERR194/ERR194147/ERR194147.fastq.gz, which contains about 8,240,000 records.\n", + "- The `fastqc-rs` execution time applies only to the base sequence quality task (pieces of code relating to other tasks have been removed for the purpose of this comparison).\n" + ] + }, { "cell_type": "markdown", "id": "9886c394", @@ -117,7 +125,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 20, "id": "66c3af24", "metadata": {}, "outputs": [ @@ -131,36 +139,36 @@ " white-space: pre-wrap;\n", "}\n", "\n", - "shape: (101, 7)
posavgq1medianq3lowerupper
u64f64f64f64f64f64f64
4737.66537.53571439.92105341.06018532.24900846.346892
9032.27533.18333334.98684235.6396129.49891839.324026
2637.85538.02884640.07894740.95175433.64448445.336117
735.435.46590936.9062537.48737432.43371240.519571
335.6935.48333337.20866137.60039432.30774340.775984
1938.42538.237540.23846241.00490234.08639745.156005
9430.77532.05769234.65151535.5126.87923140.688462
1738.50538.12540.12745141.0937533.67187545.546875
7932.4631.9687535.20535736.437525.26562543.140625
4137.8737.67857140.11607141.00490232.68907645.994398
" + "shape: (101, 7)
posavgq1medianq3lowerupper
u64f64f64f64f64f64f64
030.13531.033.034.026.538.5
131.2131.034.034.026.538.5
232.01531.034.034.026.538.5
335.6935.037.037.032.040.0
435.6835.037.037.032.040.0
9631.31532.034.035.027.539.5
9730.6731.034.035.025.041.0
9831.5532.034.035.027.539.5
9931.2532.034.035.027.539.5
10031.10531.034.035.025.041.0
" ], "text/plain": [ "shape: (101, 7)\n", - "┌─────┬────────┬───────────┬───────────┬───────────┬───────────┬───────────┐\n", - "│ pos ┆ avg ┆ q1 ┆ median ┆ q3 ┆ lower ┆ upper │\n", - "│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │\n", - "│ u64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 │\n", - "╞═════╪════════╪═══════════╪═══════════╪═══════════╪═══════════╪═══════════╡\n", - "│ 47 ┆ 37.665 ┆ 37.535714 ┆ 39.921053 ┆ 41.060185 ┆ 32.249008 ┆ 46.346892 │\n", - "│ 90 ┆ 32.275 ┆ 33.183333 ┆ 34.986842 ┆ 35.63961 ┆ 29.498918 ┆ 39.324026 │\n", - "│ 26 ┆ 37.855 ┆ 38.028846 ┆ 40.078947 ┆ 40.951754 ┆ 33.644484 ┆ 45.336117 │\n", - "│ 7 ┆ 35.4 ┆ 35.465909 ┆ 36.90625 ┆ 37.487374 ┆ 32.433712 ┆ 40.519571 │\n", - "│ 3 ┆ 35.69 ┆ 35.483333 ┆ 37.208661 ┆ 37.600394 ┆ 32.307743 ┆ 40.775984 │\n", - "│ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … │\n", - "│ 19 ┆ 38.425 ┆ 38.2375 ┆ 40.238462 ┆ 41.004902 ┆ 34.086397 ┆ 45.156005 │\n", - "│ 94 ┆ 30.775 ┆ 32.057692 ┆ 34.651515 ┆ 35.51 ┆ 26.879231 ┆ 40.688462 │\n", - "│ 17 ┆ 38.505 ┆ 38.125 ┆ 40.127451 ┆ 41.09375 ┆ 33.671875 ┆ 45.546875 │\n", - "│ 79 ┆ 32.46 ┆ 31.96875 ┆ 35.205357 ┆ 36.4375 ┆ 25.265625 ┆ 43.140625 │\n", - "│ 41 ┆ 37.87 ┆ 37.678571 ┆ 40.116071 ┆ 41.004902 ┆ 32.689076 ┆ 45.994398 │\n", - "└─────┴────────┴───────────┴───────────┴───────────┴───────────┴───────────┘" + "┌─────┬────────┬──────┬────────┬──────┬───────┬───────┐\n", + "│ pos ┆ avg ┆ q1 ┆ median ┆ q3 ┆ lower ┆ upper │\n", + "│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │\n", + "│ u64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 │\n", + "╞═════╪════════╪══════╪════════╪══════╪═══════╪═══════╡\n", + "│ 0 ┆ 30.135 ┆ 31.0 ┆ 33.0 ┆ 34.0 ┆ 26.5 ┆ 38.5 │\n", + "│ 1 ┆ 31.21 ┆ 31.0 ┆ 34.0 ┆ 34.0 ┆ 26.5 ┆ 38.5 │\n", + "│ 2 ┆ 32.015 ┆ 31.0 ┆ 34.0 ┆ 34.0 ┆ 26.5 ┆ 38.5 │\n", + "│ 3 ┆ 35.69 ┆ 35.0 ┆ 37.0 ┆ 37.0 ┆ 32.0 ┆ 40.0 │\n", + "│ 4 ┆ 35.68 ┆ 35.0 ┆ 37.0 ┆ 37.0 ┆ 32.0 ┆ 40.0 │\n", + "│ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … │\n", + "│ 96 ┆ 31.315 ┆ 32.0 ┆ 34.0 ┆ 35.0 ┆ 27.5 ┆ 39.5 │\n", + "│ 97 ┆ 30.67 ┆ 31.0 ┆ 34.0 ┆ 35.0 ┆ 25.0 ┆ 41.0 │\n", + "│ 98 ┆ 31.55 ┆ 32.0 ┆ 34.0 ┆ 35.0 ┆ 27.5 ┆ 39.5 │\n", + "│ 99 ┆ 31.25 ┆ 32.0 ┆ 34.0 ┆ 35.0 ┆ 27.5 ┆ 39.5 │\n", + "│ 100 ┆ 31.105 ┆ 31.0 ┆ 34.0 ┆ 35.0 ┆ 25.0 ┆ 41.0 │\n", + "└─────┴────────┴──────┴────────┴──────┴───────┴───────┘" ] }, - "execution_count": 3, + "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "pb.base_sequence_quality(\"example.csv\")" + "pb.base_sequence_quality(\"example.csv\").sort(by=\"pos\")" ] }, { @@ -173,7 +181,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 21, "id": "a2cb9c97", "metadata": {}, "outputs": [ @@ -187,36 +195,36 @@ " white-space: pre-wrap;\n", "}\n", "\n", - "shape: (101, 7)
posavgq1medianq3lowerupper
u64f64f64f64f64f64f64
8832.06533.06818235.0687535.69062529.13451739.62429
4337.77538.11458340.12686640.86940333.98235445.001632
4937.2136.67857139.64583340.76388930.55059546.891865
6735.9634.72368436.97222239.8127.09421147.439474
3638.1138.17857140.2540.96071434.00535745.133929
7430.8332.7535.53260937.48529425.64705944.588235
8332.0333.2535.2848135.91455729.25316539.911392
8132.7633.51470635.29710136.07352929.67647139.911765
3738.038.21527840.08035740.9687534.08506945.098958
937.3637.3437539.01470639.50245134.10569942.740502
" + "shape: (101, 7)
posavgq1medianq3lowerupper
u64f64f64f64f64f64f64
030.13531.033.034.026.538.5
131.2131.034.034.026.538.5
232.01531.034.034.026.538.5
335.6935.037.037.032.040.0
435.6835.037.037.032.040.0
9631.31532.034.035.027.539.5
9730.6731.034.035.025.041.0
9831.5532.034.035.027.539.5
9931.2532.034.035.027.539.5
10031.10531.034.035.025.041.0
" ], "text/plain": [ "shape: (101, 7)\n", - "┌─────┬────────┬───────────┬───────────┬───────────┬───────────┬───────────┐\n", - "│ pos ┆ avg ┆ q1 ┆ median ┆ q3 ┆ lower ┆ upper │\n", - "│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │\n", - "│ u64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 │\n", - "╞═════╪════════╪═══════════╪═══════════╪═══════════╪═══════════╪═══════════╡\n", - "│ 88 ┆ 32.065 ┆ 33.068182 ┆ 35.06875 ┆ 35.690625 ┆ 29.134517 ┆ 39.62429 │\n", - "│ 43 ┆ 37.775 ┆ 38.114583 ┆ 40.126866 ┆ 40.869403 ┆ 33.982354 ┆ 45.001632 │\n", - "│ 49 ┆ 37.21 ┆ 36.678571 ┆ 39.645833 ┆ 40.763889 ┆ 30.550595 ┆ 46.891865 │\n", - "│ 67 ┆ 35.96 ┆ 34.723684 ┆ 36.972222 ┆ 39.81 ┆ 27.094211 ┆ 47.439474 │\n", - "│ 36 ┆ 38.11 ┆ 38.178571 ┆ 40.25 ┆ 40.960714 ┆ 34.005357 ┆ 45.133929 │\n", - "│ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … │\n", - "│ 74 ┆ 30.83 ┆ 32.75 ┆ 35.532609 ┆ 37.485294 ┆ 25.647059 ┆ 44.588235 │\n", - "│ 83 ┆ 32.03 ┆ 33.25 ┆ 35.28481 ┆ 35.914557 ┆ 29.253165 ┆ 39.911392 │\n", - "│ 81 ┆ 32.76 ┆ 33.514706 ┆ 35.297101 ┆ 36.073529 ┆ 29.676471 ┆ 39.911765 │\n", - "│ 37 ┆ 38.0 ┆ 38.215278 ┆ 40.080357 ┆ 40.96875 ┆ 34.085069 ┆ 45.098958 │\n", - "│ 9 ┆ 37.36 ┆ 37.34375 ┆ 39.014706 ┆ 39.502451 ┆ 34.105699 ┆ 42.740502 │\n", - "└─────┴────────┴───────────┴───────────┴───────────┴───────────┴───────────┘" + "┌─────┬────────┬──────┬────────┬──────┬───────┬───────┐\n", + "│ pos ┆ avg ┆ q1 ┆ median ┆ q3 ┆ lower ┆ upper │\n", + "│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │\n", + "│ u64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 │\n", + "╞═════╪════════╪══════╪════════╪══════╪═══════╪═══════╡\n", + "│ 0 ┆ 30.135 ┆ 31.0 ┆ 33.0 ┆ 34.0 ┆ 26.5 ┆ 38.5 │\n", + "│ 1 ┆ 31.21 ┆ 31.0 ┆ 34.0 ┆ 34.0 ┆ 26.5 ┆ 38.5 │\n", + "│ 2 ┆ 32.015 ┆ 31.0 ┆ 34.0 ┆ 34.0 ┆ 26.5 ┆ 38.5 │\n", + "│ 3 ┆ 35.69 ┆ 35.0 ┆ 37.0 ┆ 37.0 ┆ 32.0 ┆ 40.0 │\n", + "│ 4 ┆ 35.68 ┆ 35.0 ┆ 37.0 ┆ 37.0 ┆ 32.0 ┆ 40.0 │\n", + "│ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … │\n", + "│ 96 ┆ 31.315 ┆ 32.0 ┆ 34.0 ┆ 35.0 ┆ 27.5 ┆ 39.5 │\n", + "│ 97 ┆ 30.67 ┆ 31.0 ┆ 34.0 ┆ 35.0 ┆ 25.0 ┆ 41.0 │\n", + "│ 98 ┆ 31.55 ┆ 32.0 ┆ 34.0 ┆ 35.0 ┆ 27.5 ┆ 39.5 │\n", + "│ 99 ┆ 31.25 ┆ 32.0 ┆ 34.0 ┆ 35.0 ┆ 27.5 ┆ 39.5 │\n", + "│ 100 ┆ 31.105 ┆ 31.0 ┆ 34.0 ┆ 35.0 ┆ 25.0 ┆ 41.0 │\n", + "└─────┴────────┴──────┴────────┴──────┴───────┴───────┘" ] }, - "execution_count": 20, + "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "pb.base_sequence_quality(\"example.parquet\")" + "pb.base_sequence_quality(\"example.parquet\").sort(by=\"pos\")" ] }, { @@ -229,7 +237,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 22, "id": "1899ca01", "metadata": {}, "outputs": [ @@ -251,7 +259,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "200rows [00:00, 63535.62rows/s]\n" + "200rows [00:00, 211459.74rows/s]\n" ] }, { @@ -264,30 +272,30 @@ " white-space: pre-wrap;\n", "}\n", "\n", - "shape: (101, 7)
posavgq1medianq3lowerupper
u64f64f64f64f64f64f64
5637.5936.82692339.39655240.89583330.72355846.999199
1638.4838.19791740.32456141.18145233.72261445.656754
8332.0333.2535.2848135.91455729.25316539.911392
9231.83532.22916735.00588235.59117627.18615240.634191
2637.85538.02884640.07894740.95175433.64448445.336117
9730.6731.57534.89062535.55722925.60165741.530572
4637.7937.47916739.97541.04245332.13423746.387382
8731.91532.5535.08783835.76013527.73479740.575338
7932.4631.9687535.20535736.437525.26562543.140625
9531.42532.19444434.89393935.53779127.17942540.55281
" + "shape: (101, 7)
posavgq1medianq3lowerupper
u64f64f64f64f64f64f64
030.13531.033.034.026.538.5
131.2131.034.034.026.538.5
232.01531.034.034.026.538.5
335.6935.037.037.032.040.0
435.6835.037.037.032.040.0
9631.31532.034.035.027.539.5
9730.6731.034.035.025.041.0
9831.5532.034.035.027.539.5
9931.2532.034.035.027.539.5
10031.10531.034.035.025.041.0
" ], "text/plain": [ "shape: (101, 7)\n", - "┌─────┬────────┬───────────┬───────────┬───────────┬───────────┬───────────┐\n", - "│ pos ┆ avg ┆ q1 ┆ median ┆ q3 ┆ lower ┆ upper │\n", - "│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │\n", - "│ u64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 │\n", - "╞═════╪════════╪═══════════╪═══════════╪═══════════╪═══════════╪═══════════╡\n", - "│ 56 ┆ 37.59 ┆ 36.826923 ┆ 39.396552 ┆ 40.895833 ┆ 30.723558 ┆ 46.999199 │\n", - "│ 16 ┆ 38.48 ┆ 38.197917 ┆ 40.324561 ┆ 41.181452 ┆ 33.722614 ┆ 45.656754 │\n", - "│ 83 ┆ 32.03 ┆ 33.25 ┆ 35.28481 ┆ 35.914557 ┆ 29.253165 ┆ 39.911392 │\n", - "│ 92 ┆ 31.835 ┆ 32.229167 ┆ 35.005882 ┆ 35.591176 ┆ 27.186152 ┆ 40.634191 │\n", - "│ 26 ┆ 37.855 ┆ 38.028846 ┆ 40.078947 ┆ 40.951754 ┆ 33.644484 ┆ 45.336117 │\n", - "│ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … │\n", - "│ 97 ┆ 30.67 ┆ 31.575 ┆ 34.890625 ┆ 35.557229 ┆ 25.601657 ┆ 41.530572 │\n", - "│ 46 ┆ 37.79 ┆ 37.479167 ┆ 39.975 ┆ 41.042453 ┆ 32.134237 ┆ 46.387382 │\n", - "│ 87 ┆ 31.915 ┆ 32.55 ┆ 35.087838 ┆ 35.760135 ┆ 27.734797 ┆ 40.575338 │\n", - "│ 79 ┆ 32.46 ┆ 31.96875 ┆ 35.205357 ┆ 36.4375 ┆ 25.265625 ┆ 43.140625 │\n", - "│ 95 ┆ 31.425 ┆ 32.194444 ┆ 34.893939 ┆ 35.537791 ┆ 27.179425 ┆ 40.55281 │\n", - "└─────┴────────┴───────────┴───────────┴───────────┴───────────┴───────────┘" + "┌─────┬────────┬──────┬────────┬──────┬───────┬───────┐\n", + "│ pos ┆ avg ┆ q1 ┆ median ┆ q3 ┆ lower ┆ upper │\n", + "│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │\n", + "│ u64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 │\n", + "╞═════╪════════╪══════╪════════╪══════╪═══════╪═══════╡\n", + "│ 0 ┆ 30.135 ┆ 31.0 ┆ 33.0 ┆ 34.0 ┆ 26.5 ┆ 38.5 │\n", + "│ 1 ┆ 31.21 ┆ 31.0 ┆ 34.0 ┆ 34.0 ┆ 26.5 ┆ 38.5 │\n", + "│ 2 ┆ 32.015 ┆ 31.0 ┆ 34.0 ┆ 34.0 ┆ 26.5 ┆ 38.5 │\n", + "│ 3 ┆ 35.69 ┆ 35.0 ┆ 37.0 ┆ 37.0 ┆ 32.0 ┆ 40.0 │\n", + "│ 4 ┆ 35.68 ┆ 35.0 ┆ 37.0 ┆ 37.0 ┆ 32.0 ┆ 40.0 │\n", + "│ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … │\n", + "│ 96 ┆ 31.315 ┆ 32.0 ┆ 34.0 ┆ 35.0 ┆ 27.5 ┆ 39.5 │\n", + "│ 97 ┆ 30.67 ┆ 31.0 ┆ 34.0 ┆ 35.0 ┆ 25.0 ┆ 41.0 │\n", + "│ 98 ┆ 31.55 ┆ 32.0 ┆ 34.0 ┆ 35.0 ┆ 27.5 ┆ 39.5 │\n", + "│ 99 ┆ 31.25 ┆ 32.0 ┆ 34.0 ┆ 35.0 ┆ 27.5 ┆ 39.5 │\n", + "│ 100 ┆ 31.105 ┆ 31.0 ┆ 34.0 ┆ 35.0 ┆ 25.0 ┆ 41.0 │\n", + "└─────┴────────┴──────┴────────┴──────┴───────┴───────┘" ] }, - "execution_count": 23, + "execution_count": 22, "metadata": {}, "output_type": "execute_result" } @@ -295,7 +303,7 @@ "source": [ "a_lazyframe = pb.read_fastq(\"./example.fastq\")\n", "print(type(a_lazyframe))\n", - "pb.base_sequence_quality(a_lazyframe)" + "pb.base_sequence_quality(a_lazyframe).sort(by=\"pos\")" ] }, { @@ -308,7 +316,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 23, "id": "7830b8aa", "metadata": {}, "outputs": [ @@ -317,7 +325,7 @@ "output_type": "stream", "text": [ "INFO:polars_bio:Table: example registered for path: ./example.fastq\n", - "200rows [00:00, 88450.11rows/s]" + "200rows [00:00, 182877.87rows/s]" ] }, { @@ -344,30 +352,30 @@ " white-space: pre-wrap;\n", "}\n", "\n", - "shape: (101, 7)
posavgq1medianq3lowerupper
u64f64f64f64f64f64f64
131.2131.27534.08636434.53863626.37954539.434091
6436.09535.06481537.740.14583327.44328747.767361
4337.77538.11458340.12686640.86940333.98235445.001632
1638.4838.19791740.32456141.18145233.72261445.656754
837.62537.53571439.11842139.55482534.50704942.58349
2138.44538.3706940.13492140.92460334.53981944.755473
7831.4631.687535.26363636.48684224.48848743.685855
3638.1138.17857140.2540.96071434.00535745.133929
7531.0630.95833335.41836737.28333321.47083346.770833
4137.8737.67857140.11607141.00490232.68907645.994398
" + "shape: (101, 7)
posavgq1medianq3lowerupper
u64f64f64f64f64f64f64
030.13531.033.034.026.538.5
131.2131.034.034.026.538.5
232.01531.034.034.026.538.5
335.6935.037.037.032.040.0
435.6835.037.037.032.040.0
9631.31532.034.035.027.539.5
9730.6731.034.035.025.041.0
9831.5532.034.035.027.539.5
9931.2532.034.035.027.539.5
10031.10531.034.035.025.041.0
" ], "text/plain": [ "shape: (101, 7)\n", - "┌─────┬────────┬───────────┬───────────┬───────────┬───────────┬───────────┐\n", - "│ pos ┆ avg ┆ q1 ┆ median ┆ q3 ┆ lower ┆ upper │\n", - "│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │\n", - "│ u64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 │\n", - "╞═════╪════════╪═══════════╪═══════════╪═══════════╪═══════════╪═══════════╡\n", - "│ 1 ┆ 31.21 ┆ 31.275 ┆ 34.086364 ┆ 34.538636 ┆ 26.379545 ┆ 39.434091 │\n", - "│ 64 ┆ 36.095 ┆ 35.064815 ┆ 37.7 ┆ 40.145833 ┆ 27.443287 ┆ 47.767361 │\n", - "│ 43 ┆ 37.775 ┆ 38.114583 ┆ 40.126866 ┆ 40.869403 ┆ 33.982354 ┆ 45.001632 │\n", - "│ 16 ┆ 38.48 ┆ 38.197917 ┆ 40.324561 ┆ 41.181452 ┆ 33.722614 ┆ 45.656754 │\n", - "│ 8 ┆ 37.625 ┆ 37.535714 ┆ 39.118421 ┆ 39.554825 ┆ 34.507049 ┆ 42.58349 │\n", - "│ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … │\n", - "│ 21 ┆ 38.445 ┆ 38.37069 ┆ 40.134921 ┆ 40.924603 ┆ 34.539819 ┆ 44.755473 │\n", - "│ 78 ┆ 31.46 ┆ 31.6875 ┆ 35.263636 ┆ 36.486842 ┆ 24.488487 ┆ 43.685855 │\n", - "│ 36 ┆ 38.11 ┆ 38.178571 ┆ 40.25 ┆ 40.960714 ┆ 34.005357 ┆ 45.133929 │\n", - "│ 75 ┆ 31.06 ┆ 30.958333 ┆ 35.418367 ┆ 37.283333 ┆ 21.470833 ┆ 46.770833 │\n", - "│ 41 ┆ 37.87 ┆ 37.678571 ┆ 40.116071 ┆ 41.004902 ┆ 32.689076 ┆ 45.994398 │\n", - "└─────┴────────┴───────────┴───────────┴───────────┴───────────┴───────────┘" + "┌─────┬────────┬──────┬────────┬──────┬───────┬───────┐\n", + "│ pos ┆ avg ┆ q1 ┆ median ┆ q3 ┆ lower ┆ upper │\n", + "│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │\n", + "│ u64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 │\n", + "╞═════╪════════╪══════╪════════╪══════╪═══════╪═══════╡\n", + "│ 0 ┆ 30.135 ┆ 31.0 ┆ 33.0 ┆ 34.0 ┆ 26.5 ┆ 38.5 │\n", + "│ 1 ┆ 31.21 ┆ 31.0 ┆ 34.0 ┆ 34.0 ┆ 26.5 ┆ 38.5 │\n", + "│ 2 ┆ 32.015 ┆ 31.0 ┆ 34.0 ┆ 34.0 ┆ 26.5 ┆ 38.5 │\n", + "│ 3 ┆ 35.69 ┆ 35.0 ┆ 37.0 ┆ 37.0 ┆ 32.0 ┆ 40.0 │\n", + "│ 4 ┆ 35.68 ┆ 35.0 ┆ 37.0 ┆ 37.0 ┆ 32.0 ┆ 40.0 │\n", + "│ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … │\n", + "│ 96 ┆ 31.315 ┆ 32.0 ┆ 34.0 ┆ 35.0 ┆ 27.5 ┆ 39.5 │\n", + "│ 97 ┆ 30.67 ┆ 31.0 ┆ 34.0 ┆ 35.0 ┆ 25.0 ┆ 41.0 │\n", + "│ 98 ┆ 31.55 ┆ 32.0 ┆ 34.0 ┆ 35.0 ┆ 27.5 ┆ 39.5 │\n", + "│ 99 ┆ 31.25 ┆ 32.0 ┆ 34.0 ┆ 35.0 ┆ 27.5 ┆ 39.5 │\n", + "│ 100 ┆ 31.105 ┆ 31.0 ┆ 34.0 ┆ 35.0 ┆ 25.0 ┆ 41.0 │\n", + "└─────┴────────┴──────┴────────┴──────┴───────┴───────┘" ] }, - "execution_count": 24, + "execution_count": 23, "metadata": {}, "output_type": "execute_result" } @@ -376,7 +384,7 @@ "a_lazyframe = pb.read_fastq(\"./example.fastq\")\n", "a_dataframe = a_lazyframe.collect()\n", "print(type(a_dataframe))\n", - "pb.base_sequence_quality(a_dataframe)" + "pb.base_sequence_quality(a_dataframe).sort(by=\"pos\")" ] }, { @@ -389,7 +397,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 24, "id": "56817174", "metadata": {}, "outputs": [ @@ -398,7 +406,7 @@ "output_type": "stream", "text": [ "INFO:polars_bio:Table: example registered for path: ./example.fastq\n", - "200rows [00:00, 91799.17rows/s]" + "200rows [00:00, 193508.84rows/s]" ] }, { @@ -425,30 +433,30 @@ " white-space: pre-wrap;\n", "}\n", "\n", - "shape: (101, 7)
posavgq1medianq3lowerupper
u64f64f64f64f64f64f64
7133.00533.79166735.85135138.58333326.60416745.770833
7430.8332.7535.53260937.48529425.64705944.588235
4537.4536.5937540.07142941.07727329.86846647.802557
4937.2136.67857139.64583340.76388930.55059546.891865
7531.0630.95833335.41836737.28333321.47083346.770833
5037.42535.97539.77083341.06018528.34722248.687963
335.6935.48333337.20866137.60039432.30774340.775984
030.13531.21363633.72222234.48214326.31087739.384903
3738.038.21527840.08035740.9687534.08506945.098958
6535.99535.1937.43333339.8128.2646.74
" + "shape: (101, 7)
posavgq1medianq3lowerupper
u64f64f64f64f64f64f64
030.13531.033.034.026.538.5
131.2131.034.034.026.538.5
232.01531.034.034.026.538.5
335.6935.037.037.032.040.0
435.6835.037.037.032.040.0
9631.31532.034.035.027.539.5
9730.6731.034.035.025.041.0
9831.5532.034.035.027.539.5
9931.2532.034.035.027.539.5
10031.10531.034.035.025.041.0
" ], "text/plain": [ "shape: (101, 7)\n", - "┌─────┬────────┬───────────┬───────────┬───────────┬───────────┬───────────┐\n", - "│ pos ┆ avg ┆ q1 ┆ median ┆ q3 ┆ lower ┆ upper │\n", - "│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │\n", - "│ u64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 │\n", - "╞═════╪════════╪═══════════╪═══════════╪═══════════╪═══════════╪═══════════╡\n", - "│ 71 ┆ 33.005 ┆ 33.791667 ┆ 35.851351 ┆ 38.583333 ┆ 26.604167 ┆ 45.770833 │\n", - "│ 74 ┆ 30.83 ┆ 32.75 ┆ 35.532609 ┆ 37.485294 ┆ 25.647059 ┆ 44.588235 │\n", - "│ 45 ┆ 37.45 ┆ 36.59375 ┆ 40.071429 ┆ 41.077273 ┆ 29.868466 ┆ 47.802557 │\n", - "│ 49 ┆ 37.21 ┆ 36.678571 ┆ 39.645833 ┆ 40.763889 ┆ 30.550595 ┆ 46.891865 │\n", - "│ 75 ┆ 31.06 ┆ 30.958333 ┆ 35.418367 ┆ 37.283333 ┆ 21.470833 ┆ 46.770833 │\n", - "│ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … │\n", - "│ 50 ┆ 37.425 ┆ 35.975 ┆ 39.770833 ┆ 41.060185 ┆ 28.347222 ┆ 48.687963 │\n", - "│ 3 ┆ 35.69 ┆ 35.483333 ┆ 37.208661 ┆ 37.600394 ┆ 32.307743 ┆ 40.775984 │\n", - "│ 0 ┆ 30.135 ┆ 31.213636 ┆ 33.722222 ┆ 34.482143 ┆ 26.310877 ┆ 39.384903 │\n", - "│ 37 ┆ 38.0 ┆ 38.215278 ┆ 40.080357 ┆ 40.96875 ┆ 34.085069 ┆ 45.098958 │\n", - "│ 65 ┆ 35.995 ┆ 35.19 ┆ 37.433333 ┆ 39.81 ┆ 28.26 ┆ 46.74 │\n", - "└─────┴────────┴───────────┴───────────┴───────────┴───────────┴───────────┘" + "┌─────┬────────┬──────┬────────┬──────┬───────┬───────┐\n", + "│ pos ┆ avg ┆ q1 ┆ median ┆ q3 ┆ lower ┆ upper │\n", + "│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │\n", + "│ u64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 │\n", + "╞═════╪════════╪══════╪════════╪══════╪═══════╪═══════╡\n", + "│ 0 ┆ 30.135 ┆ 31.0 ┆ 33.0 ┆ 34.0 ┆ 26.5 ┆ 38.5 │\n", + "│ 1 ┆ 31.21 ┆ 31.0 ┆ 34.0 ┆ 34.0 ┆ 26.5 ┆ 38.5 │\n", + "│ 2 ┆ 32.015 ┆ 31.0 ┆ 34.0 ┆ 34.0 ┆ 26.5 ┆ 38.5 │\n", + "│ 3 ┆ 35.69 ┆ 35.0 ┆ 37.0 ┆ 37.0 ┆ 32.0 ┆ 40.0 │\n", + "│ 4 ┆ 35.68 ┆ 35.0 ┆ 37.0 ┆ 37.0 ┆ 32.0 ┆ 40.0 │\n", + "│ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … │\n", + "│ 96 ┆ 31.315 ┆ 32.0 ┆ 34.0 ┆ 35.0 ┆ 27.5 ┆ 39.5 │\n", + "│ 97 ┆ 30.67 ┆ 31.0 ┆ 34.0 ┆ 35.0 ┆ 25.0 ┆ 41.0 │\n", + "│ 98 ┆ 31.55 ┆ 32.0 ┆ 34.0 ┆ 35.0 ┆ 27.5 ┆ 39.5 │\n", + "│ 99 ┆ 31.25 ┆ 32.0 ┆ 34.0 ┆ 35.0 ┆ 27.5 ┆ 39.5 │\n", + "│ 100 ┆ 31.105 ┆ 31.0 ┆ 34.0 ┆ 35.0 ┆ 25.0 ┆ 41.0 │\n", + "└─────┴────────┴──────┴────────┴──────┴───────┴───────┘" ] }, - "execution_count": 7, + "execution_count": 24, "metadata": {}, "output_type": "execute_result" } @@ -457,7 +465,7 @@ "a_lazyframe = pb.read_fastq(\"./example.fastq\")\n", "a_pandas_dataframe = a_lazyframe.collect().to_pandas()\n", "print(type(a_pandas_dataframe))\n", - "pb.base_sequence_quality(a_pandas_dataframe)" + "pb.base_sequence_quality(a_pandas_dataframe).sort(by=\"pos\")" ] } ], diff --git a/docs/notebooks/example.csv b/docs/notebooks/example.csv new file mode 100644 index 00000000..852077c0 --- /dev/null +++ b/docs/notebooks/example.csv @@ -0,0 +1,201 @@ +name,description,sequence,quality_scores +SRR9130495.1,D00236:723:HG32CBCX2:1:1108:1330:1935/1,NCAATACAAAAGCAATATGGGAGAAGCTACCTACCATGCTTAAAAACGCCAATGAGCAGNGATTTGTCANCNNNNNNNNCNNNNNNNNTNNTANNANNCTC,"#4BDFDFFHGHGGJJJHIIIIGGIIJGJJGIIIIBHIJJJIIJIJJIJDHIGGGIJJJI#-@AEHGEFF#,########,########+##++##+##+2<" +SRR9130495.2,D00236:723:HG32CBCX2:1:1108:1472:1938/1,NGTCAAAGATAAGATCAAAAGGCACTGGCTTACCTGATTAAGAAATTGTGTAGTCCAACATCAAAATACNTNTNNNNNAGAGNCANGNCAAGCNNANNAAT,"#1=DDDDD>DHFH@EFHHGHGGFGIIIGIGGGGIIGIIDDCHIIIIIID@FEGGGIIIIICHIIIIIIG#-#-#####,,;;#,5#,#,,85@A:AB@8>@:@A@9(:((+(834" +SRR9130495.6,D00236:723:HG32CBCX2:1:1108:2392:1965/1,CGATAAAGGACTTTCAGTCAACCAACTAGATAATGACCACTGGGCACCCATTCATTATGCATGCTGGTAAATAAATTATTCTGTTCAGGAACATTGAACTC,CC@DDDBDFFHHHJJIJJIIJIJJJIIIHGIGGHCGGIGHHAACC??A<" +SRR9130495.11,D00236:723:HG32CBCX2:1:1108:4089:1977/1,CATTCCAACCAGCCGCTTAAAGTTTCTAAAAGAAGCTGGTCATGGAACCCAGAAGGAGGAGATACCTGAGGAGGAATTAGCAGAGGATGTTGAAGAGATTG,CCCFFFDFHHHHHJIJJJJIIJJJJJJJJJJJIIGJJJIGHGIJJIJJIJJIIFHGHIJJGHEHHFCEFFDEDDBDDDDDDDDDDDBACDDDDDDDDDDDD +SRR9130495.12,D00236:723:HG32CBCX2:1:1108:6197:1936/1,NCTTAAAGGCAAGGTGCTCGGCTTCCGCTATCAAGACCTCCGACAGAAAATCCGGCCTGNGGCTAAAGANCNNNNNNNNANNNNNNNNCNNGGNNCNNGGC,"#1BDFDEFGHHHHIJJJJJJIJJJJJJJJJJIJJIGIJJIJJJIJJJJHIJJHHHFFDC#,;?BBDDDD#,########+########+##++##+##++8" +SRR9130495.13,D00236:723:HG32CBCX2:1:1108:6415:1939/1,NTGTGTATGGGGATGAGGAAGGATATTAATATGTTCTATTTGAGATTTAGGGATTACATTTGTTTTTGCNCNCNNNNNTTTTNTCNTCATTTGNNGTNAAT,"#1:ADDDFHGGHFGGBHIGGIIJJEIIIJJIJIJJJFGJIIHGHGDGHJGHIHIIIIJJIIHFHIIJJJ#-#-#####,,;?#,;#,8?DDEE##,+#+2<" +SRR9130495.14,D00236:723:HG32CBCX2:1:1108:6361:1952/1,TCAGATCTTATTTTAATAGTTGACTTTACCTCTTCTTTGACTTCCTCTTCCTCGGTCTCAGTAGATATAGATGGTACCTTGGGCTTATGCCATGAGATCTG,CCCFFFFFHHHHDHIIIIJJJJJJJJJJHIIIJJJJJJJIHJHJII>GHIEGHIIIIJJJIJJIHHIJJJIJIGHIJJGJJHFHHFFDCFFEDCEDCCDEC +SRR9130495.15,D00236:723:HG32CBCX2:1:1108:6263:1960/1,CAATATCTGACTGAATGGGCCCATTTTCATAATATTCTGAAACTGTTCATACATGTCTCGCAATGTAAACTGACCTGAAATGCAATACAAAAAAATTCAGA,CCCFFFFFHHGHGGGIIIIJJIJIJJIIIIIIIIEIHGGIEGGHGIJJIJJJCECGHIIIJJJJJIFGHIIHGIIJJHHGEFHDFFFFFCCCDDBBCCDCA +SRR9130495.16,D00236:723:HG32CBCX2:1:1108:6338:1988/1,AGACACTAAAATGCCATGTATGAGACTACATAGACATACCAATTTACAACACAAACACATGAAATATACATGAGAAAACATTAACTTACTTCCAGTTGGGA,C@CFFDDDHGHHHIIIIHJJIIHIHGIJJJJJIJJJIJIIHEHIIJJJJJJIJJIIIIIJJDHIJIJGIJIJJIJJHHGGHFFFFFFFEEEDCCC@ACCBA +SRR9130495.17,D00236:723:HG32CBCX2:1:1108:6742:1944/1,NGAAACACTCTTTTTCTGGAATTTGCAAGTGGAGATTTCAGCCGCTTTGTGGTCAATGGTAGAAAAGGAAATATNTNCATATAAAAACTAGACAGAATGAT,"#1BDFDFFHGHGHJJJJJJJJHIJHHIJIIJJIJJGIJJIJIIJJGIJIHIJJJIIJJJHIEIIJJJJIHDEFH#,#,5=ADEEEDCDDDDDDDCDD5@CD" +SRR9130495.18,D00236:723:HG32CBCX2:1:1108:7076:1942/1,NGTCTAAGAATGAAGTGCTTATGGTCAACATAGGCTCCCTGTCGACAGGAGGAAGAGTTAGTGCAGTCAAGGCTNANTTGGGCAAAATTGTTTNNACCAAT,"#1:B:BDDHHFFHIEGGIGIDEHGEEGIGHIIIFACHIGIGCFGEHIGGHHGHGH@DCGGIDEIIIIFFHHAEE#,#,5=@BBC@BCCCCCCC##,+8?BC" +SRR9130495.19,D00236:723:HG32CBCX2:1:1108:7440:1957/1,CACCTGATGTCCCACAGTCCTCATAGACACTAGCACTGACTGCTGGCCATCGTCTCAGCCAGATGATGTTGACCTGCTAGCTTTTCAATTAAATTATTAAA,+=144=DD>D4CCD?E@AECFFIIIIEI?E+??;3EBDECEIBEECDIEIIADDDDEIDCDCA;=A@CECE7ACD=(;;A@DA@A@A:ADAAAD>AADBB> +SRR9130495.20,D00236:723:HG32CBCX2:1:1108:7363:1977/1,ACTCATAGAGTTGAAGATTCCCTTTCATAGAGCAGGTTTGAAACACTCTTTCTGGAGTATCTGGATGTGGACATTTGGAGCGCTTTGATGCCTACGGTGGA,CCCFFDDDFHHHHJJJIJJJJHHIIHGIJIJJJIGGHGIJIJJIIIJJJJJIJIGBFDHIIJIJGIJIGGCHGGIJHIIHHHFECDECEEDCDDCBD9?B? +SRR9130495.21,D00236:723:HG32CBCX2:1:1108:7298:1979/1,AACCGTCGCCAGGTACCATCCCAGAGAACTCTGTCTTCCTTACTTATAGCCAAGTTGCCGGCAGATCACAGCTGCATGCTTATCGGTCCATCCGTCATCGC,BCCDDDFFGGFGFJIBBHHIJJIIHHIIIGJIIHIIJJJIIEIGHJIIJJJJIIHHGIJFGHGFDDCEECDDDDDDDDDDEDDDDDDDBDEDDDCCC +SRR9130495.23,D00236:723:HG32CBCX2:1:1108:7307:1995/1,TAATTTGGTATATGTCTTTTTAAAGGCATTTTTATTAGATATTTCCTTAATTTACATTTCAAATGTTATCCCCAAAGCCCCCTATAATCTACCCCTGCCTT,;?7DD?;DBFHHFIA;A@AABBB@B?2<58+:?<<9<@: +SRR9130495.25,D00236:723:HG32CBCX2:1:1108:7870:1955/1,CTATCCCGTCGGGTGACTGTTTCCTGCTTTGCAGTTATTCAGTGGCAGAGCGTGGCGCTCTAATTTCTGCTTTCCTCTTTCCTGCAGATTGTGTGCTACAT,CCCFFFDFFHHFHBHGJIIIHGIIIJJIJIIIIJHIIIIEIJJIIJJJJIJIJIJDFEDDDCEEEEEEDDDDDDDDCDDDCDDDDDDDCDDDCDDDDDDDD +SRR9130495.26,D00236:723:HG32CBCX2:1:1108:8157:1994/1,GAAGTGCTCTTCGTTACTACTTAAATCCCCCTGGGCATGTTTCATTATTTTACAATTTGTGCAGAACCCTATCCAAACACACATGGAGTACAAATGACTTC,CCCFFDDDDHHDHHIGIIBIHHHJJJ@FGGA?@CCCCCC@CCCDD +SRR9130495.27,D00236:723:HG32CBCX2:1:1108:8703:1937/1,NATAAAAAAATAACATCCTTTCCTCCTAATAGCTTAATTATTTGAAAAAAAATATTTTCNAATCACATGNANNNNNNNNTNNNNNNNNTCTTTNNTNNCCT,"#1=DFDDDHHHHHIIJJJJJFIJJJIGIEGIIJJJHHIJJJJJIIJIIIIIJEHEHHHA#,;??AEDDC#,########,########++8??##+##(+2" +SRR9130495.28,D00236:723:HG32CBCX2:1:1108:8702:1991/1,CTCAGAGATTAAAAATGAATAACGCCTGCCGGCCAATGAGCGGACTCACAGTCCCTGTTTGTTTGTAAGCTAGGTGATTTTCAATCCACAGGGCAGGCTGA,@@@DFDFFGGDHFGIIBGEHJIIIBGIIIJJIIJIJIIFGGEGIJJJHGGHHHDCFFDDDEDEDDDDDCDDDCBDDACDEDEDDDDCCCCDGII@GIFGFE???BFBBEHIGGIEEHIHIGGHHGIHA3?CH;?@CB@DCCEDEDD3 +SRR9130495.34,D00236:723:HG32CBCX2:1:1108:10535:1962/1,AATACAGAAAAGTTAAGAGCCAGCCCCAGGCGGATTGGATGAATAGGTTGCATCTCTTTCTTGCTTATATCAAATGCCTCTTGGCAGGCTCCTTGGGAATT,???BD:A:3=?B:;?;;CA;;;A3-5>5-5:(::@8/2?8?9>>3(83(+ +SRR9130495.35,D00236:723:HG32CBCX2:1:1108:11147:1968/1,GCTGCCTTCTCCCCTCAAGGATGCAGTGGAAGTGTCAACCTGGAGAAGATGCTACACGATGCAGGAGGTGAACTCGGCCCTCAGTAAAATCCAGCTGGTGG,CCCFFFDFHHHGHJFEGIHEGHIGIIGCCGGGIIJJIJJGGGGHCGIF>DGHIIIEHHGIIJJDBGHFHFCCFFFDDCDDDDBDDDCCDEDA:CACD@CDD +SRR9130495.36,D00236:723:HG32CBCX2:1:1108:11124:1986/1,GACAGGGTTTCACCATGTTAGCCAGGACGGTCTTGATCTCCTGACCTCGTGATCCGCCTGTCTCGGCCTCCCAAAGTCCTGGGATTACAGGCGTGAGCCAC,CCCFFFFBFFFHGGHGHIHIIGIJFJJJIJHIIIFGHGGIIGEGHIH@@FGGIJIIGGIHIEEHEEFFDDCCCCBDDACCDCDBAACCDDDBDDDDBDDCC +SRR9130495.37,D00236:723:HG32CBCX2:1:1108:11773:1947/1,TACCTGCCTCTGCCTCTCGAGTGCTGGGATGAAAGATGTGCACACCCCCACCACCACCACCACCACTGCCTGGCNCNGTTTTTGATTTCTTATTCTCCAGA,"CCCFFFFFHGHHHJIJIJIIEHIJJIJJIJJIHIHJJIGFIIIIJBHHGFF>HGIJIEHHHFGDEEEEEECC?B#,#,,5?@HF1CGBGHCDDFF7=DEG.?AAC?3@EED;6@;>(-;@AC?31(,5?(4::A>AC" +SRR9130495.46,D00236:723:HG32CBCX2:1:1108:14226:1948/1,AACCTGCACCCAGAATGGCAGGAGGTCCTGGTGGCCCAGGGGGTCCTGGTGGTCCAGGAACACCAGGTCTCCCANANCCAGGTGGCCCAGGCAGGCCTGGA,??1D1BDDHFHHBBHGGGAFG)AF1:?CEGD@BGAFDGIGGB'5;CE77?=???>>CC3#+#++228>>28((2(>ACC?CCDDCCD@ +SRR9130495.48,D00236:723:HG32CBCX2:1:1108:15049:1993/1,TGACCAAGAACTCACAGAGATCCCCCCCCCCAGGGCTAAGATTAAAGGCATGTGCCACTGCCACTGGATAGATATTATCTTTTATTTTACCTGACTGGTTG,@CCFFDDDHDFHGJJJJIJGIHHHIIJJIJFE=(5;?@>@A@;@C>CAB=@<:@C@CA:>CC3:>CB<@@?344>>@@A>CDC>ACDD:>4>>>ACD?CC( +SRR9130495.49,D00236:723:HG32CBCX2:1:1108:15487:1951/1,ACGGAGGGTGGGGCTGGGTGATTGTGGTTGTCTCCTTCTTCACCCAGTTCCTCTCTTACGGATCCCCGTTAGCTNTNGGGGTCTTGTATGTAGAATGGCTG,BCCFD@DFDFHHGDGIIICGHIIJJIJGHIIJIIJJJIJIJIJEHIGHHHHHHHFFFFFFDDCDDCD@DDDDD:#+#+2<@8GHIIIEHGACFHIIGGIBHIIHHC??BDC@BBCECDCE63>@@CACCDD@ +SRR9130495.51,D00236:723:HG32CBCX2:1:1108:15923:1957/1,CCGCAACTGCCATGGAGCCACAGCCTGGTCCGTAATAGATGCAAAGCTTCTCAATAGTCAGGGGCGTGGTTTCGCGCAGCTTGGAGGCCAGCAACAGGCAG,CCCFFFFFHFHHHIIFIIIGIIFIIGJIIJJIFHGHIIIIIJIIFIJIIIJJJJJJJGGIGJFFH@?BBBDBCDDDDDDDDDDDDDDDDDDDDDDDDDDD? +SRR9130495.52,D00236:723:HG32CBCX2:1:1108:15793:1968/1,GTTTTTCCACAGACCTCTGATCTCTTACATTCGAAAGTTCTACTACTATGATCCTCAGGAAGAGGTGTACCTGTCCCTAAAGGAAGCGCAGCTCATTTCCA,BB@FFFFFFFHGDGFHJJJJIFIIGGG@FIIIGIBGGDHIIIJCHIIJJDHIIJJJIIIGIIJJFHHIJCHGDHIIHHHHHFFFFFDDDDDDCDDDDEDDE +SRR9130495.53,D00236:723:HG32CBCX2:1:1108:16082:1968/1,GAAACTTGTTTGTGACGTGTGTATTCAACTAACAGAGTTGAACCTTTCTTTTTACAGAGCAGCTTTGAAACACGCTTTTTGTAGAATCAGATCGGAAGAGC,@<@ADDDECBFFHIFEGDG;EEHHB@FHGHIIGGEHGGHGGEGEGICGCEFFDB@D>AE>ADC@CBBFGIIJJJJIHHIJJGH?DGGHCFHHIJJEEIIJAHIJJFG=FGGGIFHHIIDHGEHIHHHHGHGEB;?CDCECEEDD +SRR9130495.55,D00236:723:HG32CBCX2:1:1108:16048:2000/1,AGGACAGGAAGGACGCTTTGAGATATGATTTCACAGGCGACAGTGAGAGAAAACCAATGTCTTTAATGCATTTCTCTGCAGCATGTGACAAACTTTCAACA,CCCFFFFDFHGHHIIJJJJIFGGIJJIIIIJIJIHJIIJIHGIJJIJGGIIJIJJHHHHEDCDFFFEEEDDEDEEDDDDDDDDDDCDEDDCDDDDDDCCD@ +SRR9130495.56,D00236:723:HG32CBCX2:1:1108:16580:1970/1,GCCTGTACTCCCAGCTACTTGGGAGGCTGAGACAGGAGAATCACTTGAACCCAGGAGGTGGAGGTTGCAGTGAGCCAAGACCGGGCTATTGCACTAGATCG,@@@FFD?DBFFHHIIEHCIJIFIJHEDCH@GGEBFHHIJJIIIIIJJJJJIFHFHF@G-6@AAEDFFF>AEC@@A?;=?BCD6/<@>BAAC>:@C:CDDA? +SRR9130495.57,D00236:723:HG32CBCX2:1:1108:16594:1971/1,TCCTCTGACTTTGACACTAGTGTTGACCTTGCATGAGGAGATGTTCTCCATTTGGACTAACCTGATGTACACAGACGTTACACTTATCACAGAATACCATA,CCCFFDDFFHFHFHIJIJJIHIIIJJJJJIJJJJIIIIHIGIIJJJIGIIJJIIJEHIIJIJJJIGIJJJEIHJJIIHHEFFFFFFCCEEEEDCDDDDDDC +SRR9130495.58,D00236:723:HG32CBCX2:1:1108:16808:1998/1,ACCAATTTTCCCCTCCCCTTCCTCCCTCCCTCCCAGCCCCCTTCCTCTCTCTACCTCCTGTTATTGTTTTGTTCCTTGTTCTATGTAGGATTGAAGCATCT,@@@FFDDFHDFHGIJJJJIIGGDFHI>DGC;DHI9??FHIJIIHG>>3>;ACCCC9:@>@:>AA +SRR9130495.59,D00236:723:HG32CBCX2:1:1108:17428:1967/1,TGCATGGTGCTGAAAGCTTTGTTGCAGCTTTTCTTGGGATTGCTTAGCTGCTCCGGGTCGATCCACTTGCAGATGAGCTCTTGCTTGATGCACTGCTGCCG,?<A3>A>>AAAA?3 +SRR9130495.60,D00236:723:HG32CBCX2:1:1108:17508:1988/1,TTGTTCAGAAAAAAGTATCTTGAAACCAAAAGAACTGGGATCTTGTTAAATGCAGATTCTGTTCATTAGGTATAGGTATGCAGTCTTACAAAATGAGGTAG,CCCFFEFFHHHHHJJJJJJJJJJJJJJJJJGIJJJJJJJIIJJJJJJJJIJJIJJJJJJJJJJJIJJIIIEHHBHGHHEFFFFFEEEEDEEDDCDCDDCDC +SRR9130495.61,D00236:723:HG32CBCX2:1:1108:18425:1951/1,CCACTTAATAAATCACCTATCAAGTTGAATTATTTGTGCAAAGGCACTAGGCTGAATAGAGACCACTCAGTAGCNTNTTTTTAATCTTGCTAAGAAAGAAT,CCCFFDDFHFHHGJIIJJJJJJHGHEHHHIIJIJJIJGJIHIJHEFDHGHIFIJJGHIJJJFIGGIHIIIJIII#-#-5@DFFEEEDEEEDEDDACDCCBC +SRR9130495.62,D00236:723:HG32CBCX2:1:1108:18468:1964/1,CTATTGACTTTTATTAGAAAGGGTCTTGTTGCATAGGTAGGTCTTTAACAACCATCTCTTAAAGGGCTGGGATTGCCAGAGTAGGCCAACACGCCCAGCTA,CCCFFFFFGGHHGIGIJIJJIIIJJJJIJJIJJJJIIJDGEHGIIJJJIJJJHIJJIGFHGIJGEGIJJJIIHHHHHHFFFFFEDEEDDDDDDDBDDBBD@ +SRR9130495.63,D00236:723:HG32CBCX2:1:1108:18615:1941/1,NAGCCGAGAGGCGCCGGCTCACCTGCCTGGGTCCCGGCCTTTCTCCTGCAGTGCCAGGGATTCACCTGANGNCNNNNNNTCTNCTAGGCAAGCNNATNCTT,#1:DDFDDHHHHHIIJIIFGJJIEFHHIHHIIIJJIEHFFEEEEEEE?DFF;5:AAB9>29(#+#++8++4>>:@>AA:@1<@@A(:4? +SRR9130495.72,D00236:723:HG32CBCX2:1:1108:1440:2047/1,GCTGGTGCAGGACACCAGAATCCGCTCGATCATGCTCCCTAGAGAGGAGGGGCACAGTGAGTACACATAAGCACATGTACACACACACCCAGGACCCAAAG,CCCFFFDEHHGHHHIIIIIIIIJJIJJJGEGHIJIJJJJIIJGHIIJJJIDFEDFFFFEEEEDEDDDDDDDDDDDDDEEEEDDDDDDDDDDDDDDDDDDDA +SRR9130495.73,D00236:723:HG32CBCX2:1:1108:1468:2080/1,ACTGTCTTTTTTTTAAAACAGGTGATTGCCCGTTGATTGTTCAGTTTGCTGCTAATGATGCAAGACTTTTATCTGATGCTGCCCTGCTAGTCTGTCCCTAT,CCCFFDDEHFFDHIEIIJHGCGFHCIIHIIIHH@FGGIHIGHIJJIJGIIIJBHIGEIHGHHGGHFFFFFFEEEEDEDDDDDDDDDDDCDDDEDDDDDDDD +SRR9130495.74,D00236:723:HG32CBCX2:1:1108:1333:2084/1,ATGAGCACACAAGGGATGATCAGATTGATGGTGTAGAAGAGTGGCTTGCGCTTGATGATGAAGTCATAGGTCACGTCCACATAGCTGGGGTCCTGTGGGTT,CCCFFFFFHHHHHJIJHDIIHHHIIJIIJJJJJIJJIIJIJJJIBDGIJJJJIJJJJGIIIJIAHEEHEFFFFF>EDCDDDDDCDDCDDDDDDDDDCDDDD +SRR9130495.75,D00236:723:HG32CBCX2:1:1108:1447:2137/1,TCCACTTGTACAAAAAATTACAAAAATTAGCTGGGCATGGTGGCACACACCTGTAGTCCCAGCTACTCGGGAGGCTGAAGTGGCAGGATCACTTGAGGCAG,CCCFFEFFHFHGHJJJJIJJJJIIDIEHJIIJJJIGJJJHGJIIDHIDGIJIJJIGHIJJJJJHHHFEEBDCDBBDDDDDDDDDDDDDDDDDDDDDCDDD@ +SRR9130495.76,D00236:723:HG32CBCX2:1:1108:1499:2151/1,GAGAAAAAGCATCCCTTTAATAAGGCCGCCCCGGTTCCAAATCAATCCTGGCATTGCAGGAGGCAAGGGGGAAACACAGCCACGAAATTGGATTAGCTCTT,CCCFFFFFGGHHHJIIJHIEIJJIIIIJIIGJJIHJIJJIGIJJJIIJJHHHHHFFFFFFDCDBDDDDDDDDDDDCDDDBDBDDBBDDDDDCDDDDCDDCD +SRR9130495.77,D00236:723:HG32CBCX2:1:1108:1280:2166/1,GCCTTCTTCCCAGCAGCAATATGGCTCTTTCTTCAGCTCTTATCAGTCACATCCATCAACGAGTGGCTTTTAAAAGGGTATGTTTAAACCTTTTGACGGGA,CCCFFDEFHHHGGJIJJIJIJEIJJJJJIFGIIIIIIIJIIGIJJGIIBHIJJJJIJIEH>CG;CHCHGHICHFFFFFFDDC;@CCEEDDCDDCCDDDDDB +SRR9130495.78,D00236:723:HG32CBCX2:1:1108:1458:2216/1,TTTCTTTCCACACATCCCACCTAACACCCAAACTAAGCACTCAGTGCTTGGAATCTCCCCACCCATTCCCTCACCCCTGCTCTTCCATCATTTCCTCCAGC,CCCFFFFFHHHHHIDHIIJJJJHIIJFHIJIJIGIJHGIIIIGJEHIGIIJCGEEHJJJJJJJDHEHHGFFFFFDCDDDDDDDDDDDECCDDEEEDDDDDD +SRR9130495.79,D00236:723:HG32CBCX2:1:1108:1634:2001/1,TGTGCATTTCTCATTTTTCACGATTTTCAGTGATTTCGTCATTTTTCAAGTCGTCAAGTGGATGTTTATGATTTTCCATGATTTTCAGTTTTCTTGCCATA,CCCFFFFFHHHHGJJJJJJJJIJHGIJJJJIIIIJJIGIIJJJIJJJIIFIIJJJJJIJJJIJIIIIIIJIJGJJJJFHHGGHGFFFFCEFFDEEDEEDDD +SRR9130495.80,D00236:723:HG32CBCX2:1:1108:1566:2120/1,GGACGAAGTAAGGGAGGAGCAACTGACAACATTCATCTTGTCTGTCTCCTCCACGTCCCGAGGTACAAGGCGGATGTCATTCTTACTAATTTTTTTCTTCT,CCCFFFFFHHHHHIIJJJJIJJJIJJJJJJJIFIJJJIJIJIJIIJJIJIJJJJIJJIIJHHFFEEEEEDDDDDDDCDEDEDEEDDDEDDEECDDDDDDDD +SRR9130495.81,D00236:723:HG32CBCX2:1:1108:1863:2047/1,AAATTCGGACCCCTTGGGTGGAATATTCCTTACGAATTCAATGAGACAGATCTAAGAATCAGTGTGCAGCAACTCCACATGTTCCTGGACCAGTATGAGGT,@BCFFFFFHHFHHHIJIJGIIIJIJJJJIIJJIIIIJJJJGIJJJIJJIEGIIGIJIJJJEGHHHGEEHFFFFDEEEDDDDEEEDDDDDDDBBCDDCCCCC +SRR9130495.82,D00236:723:HG32CBCX2:1:1108:1844:2145/1,TAACTCTCTGCCTGCGATGTCCCTACCTTCCAGAATGGTGCCATGACAACGGTGTCAACTACAAGATCGGAGAGAAGTGGGATCGGCAGGGAGAAAATGGC,@CCFFFFFHHGHHJJJJJJJIJJJJJIJIIIHIIIJIIJJJJIJIIJIJJJJJJJJJIJJIIJEHHGHHFDFDDDDDCDCDDDDDDDDDDD?>BDDDDDDD +SRR9130495.83,D00236:723:HG32CBCX2:1:1108:1772:2188/1,GAGGTAGGGGTGTGTGTGAATGGGTGAGTGTGTGCCTATGCTTGTATGCCATATGAGAGAAAATGCAGCATTTAAAATCAGTGGTTAACGGCCAGCACAGT,B@BFDFDDHHDDHHGIGIJIJGIJ:CFHHIGGIJJIEHGIIIJIIIFHGIJBHIJJJJJJCHHIHHHHHGFDFFFFEEEECEEDDDDDDDDDDBDDDDDCA +SRR9130495.84,D00236:723:HG32CBCX2:1:1108:2103:2085/1,TACAAATGTGCCAGGCACTCTTCTAAGTCCTCACATGCATGAAGTTATACAACTCTACAACAAACCTAGGAATATAAACTGAGGGCAGGGACCCCCAGCAA,CCCFFFFFHHHHHJIJIJJJJJJJJJJJJIJJJJJJIJJJIJJJFHIJJJJIIJJJJJIJIIHIICHHIJJJIIIJJHHHFHHFDDDDDBDDDDDBDDDDD +SRR9130495.85,D00236:723:HG32CBCX2:1:1108:2067:2091/1,ACCAGCCCTGCTGCCACCCAGCCCACGTCCCGCGCGCCACCCATGCTGCTGCCTCGGAGCTGCAGGGAGCCGGGGAGCCAGGGCCACACGCAGGTGCAGCT,?@@D?A:BF8DDFFFFFFFFAECBF@GFECAEFIIIIIIFBE?DBBD;@CCCCBBBBBB@B::AABBBBBB7>BBB>@BB?B>B>BB?/?A?BCCCBDDDD>@ +SRR9130495.87,D00236:723:HG32CBCX2:1:1108:2387:2038/1,GGCTAACCACTGCCTTGTCAAGTTGTGTAGAGTGAGATTCAGGGGTGTTGAAGTAATGTCCTTGTTACTTGCTGTAGGGCATCTGTTTTCTGTGTATCCCA,CCCFFDDDDHGHGJEIGHHIJIHGGIIHGIIIIIEGBEHGGHIGGAFHIJJJJJJJJIDGHIIGIJJJIIHGFHEHFDFEDCEECDCDDACCCAACDFCCC +SRR9130495.88,D00236:723:HG32CBCX2:1:1108:2285:2075/1,CTGAAAGCTGAGCGTGAGCGTGGTATCACTATTGACATCTCCCTGTGGAAATTCGAGACCAGCAAATACTATGTGACCATCATTGATGCCCCAGGACACAG,?;@DDBDDDFFD>ACGED@D8@):E*::??FFC@;FEF>E;CC=CC=@DDD>?;>A>A>A;AB3;A(;@:??DFBCB4<CCD@=BB@-(4812>>> +SRR9130495.93,D00236:723:HG32CBCX2:1:1108:2748:2098/1,CATCATCTTTTTTTTTTTTTTCTCCTGAAAACTGTCTAGTAGTTTGATATATTTTGTCCGAGGTTATTTCAAGTGTTTTTTTTTTTTTTTTTAAAACGGTG,@@@DDDDDHHHHHIIFEHIIH8))7)7CEF9).)7;;>B@>9BD;;(6(55>DDDCBCC@/8-084@CC>C(((+4>?CBBBBBBBBBBB>&23:A(5?(( +SRR9130495.94,D00236:723:HG32CBCX2:1:1108:2733:2156/1,GACTGAGAAGAACAGAAAGGGAGAGAGAGGCCAATGGAAATACATGAGAAGGGAGAGAGGGAGAGAGAGGGAGGGAGGGAGGGAAGGAGGGGGAGAGGGAG,CCCFFFEFGHHHHJJGIIIJJHIIHHIIJJJJJIJIIHGJJJGIJJJJJJJJJHGGHHIHHHFDFCDCDDD>BDDBDDDDDDD>BDD?BDDDDBDBDBD@D?ABD@BD?BBDDDC +SRR9130495.96,D00236:723:HG32CBCX2:1:1108:2818:2076/1,ACACTTCATGGCAACCTGGCTTAGATTCTTCAAAATTTCTGATCCTATACCAAAGCCTCTGTAATCACTCATCACGAAGAAGTCTTCAAGATACAGTAACT,CCCFFFDDHGHHHJJJJIIJIIHIJHGCHIFEGGJJJJIJIGIIJJJIIJCEHIIIIJIBGHGGIIJIIBFGGGGHHGHFFFFDEEDECEDDDDCD>CCDE +SRR9130495.97,D00236:723:HG32CBCX2:1:1108:2848:2112/1,AACCTCTTCTCTTTGTCTTTCTCTTTATCCTTCTCCCTCTTGCCAGGACTGGACTCGCTGGTGATGGTGACGACGCTGGTGGGTAAGGTCTGCGCCCGACT,@@BFFFFEHGHHGIJDEHIJIIIIIIJIFHIIIJEIDHIIIIJJIIIGIEIIJJIIIJFEHFHIIIGIIJIFBEDDBD>=?BB@CACCCAACDDBDBB5;6@;ACBCCCC?@AA>C>?<<<9)?FHFCAG=GFFG>FGGEGHIEEBEDEFC>C@::=BB@BCACCC@CA3:(8@C<8?CC +SRR9130495.100,D00236:723:HG32CBCX2:1:1108:3014:2117/1,CCCTCCTGAAAAGGTCCAGCTCCAAAGCCTGACCCGTAGCTGCAGAGAAGAAAGCTTTTCCTCTAAAGGCTGAGGAAAAGATGAAAAATCACTGCTAGAAC,CCCFFFFFHHHHGIJIJJJJJJJJJJJJJJJIJJJIJJIJJJJIJGIDHHIIIJJIJJJJJIJJJHHHHHFFFFDEEEEDDDDDDDDDDDDDDDDDDDDDD +SRR9130495.101,D00236:723:HG32CBCX2:1:1108:3316:2011/1,GCAGAGCTGAATGGGCAAGCCCAGGACCCTTTTCAGACATTCTGCTGGCCTTTGGAAAGTGTACTCCTGTTGTATTTGATTACTTTTAGAGGACAGTACAT,CCCFFDDFHHHGHJJJJIJFGIGHJGIJIIIIIHIIGIIJIIIIJJJIIIIJIIIGIJGIJJJJIIJJJEEEE?ECFFFFFFCCEDEEEDDDDDDDDEDCD +SRR9130495.102,D00236:723:HG32CBCX2:1:1108:3264:2036/1,GGGTGCTGGAGATAGCCCACGTACACTCCTTCTTGCTGGGGTACTTGTCAGGCCAGTTGGGGCTGGTGATGGTGCCACTGGTGGATGTCACCTTGTGTTCA,"=@<=B+AD>BFDFIIDEDGEIGFIIIIIICDFGFFGIII;D?F>?*/9BF>DAF;CFFGI>/:=?>7@BAA:;@5=A5>@=,98?:>@(;:4>ABAB?ABD" +SRR9130495.103,D00236:723:HG32CBCX2:1:1108:3400:2065/1,TCTGTCTGTCACCAGGTTGGAGTGCAGTGGTAGGATCATGGCTCACTGCAGCCTCGTCCTCTTGGGTTCAAGCAATCCTCCTGCCTCAGCCTCCCAGGTAG,@@BDFFFFHHHGHIJJFHEG@GHHIIAFD@HGGGEHIJJJGIJJGGGIHFDAHHHHJFCGGGHGJI;CHFCEDDFFFCEDEEDDDDDDDD<C +SRR9130495.104,D00236:723:HG32CBCX2:1:1108:3468:2219/1,TGCACTTCGTTCTCTTAATGAAACCCTTTGACTTAACCATGACTCCGCTCTGCTCTTGAGTTTGCAAGTGTGTGCGAGTGCCCGAGAGACAGTTTTTTTTT,CCCFFEFFHHHHHJIJIIJJIIJJJIIJJIHIHJJJJJFHFHIIJIJJJJIJIJJJJJGGIIJJJGDIJJJIHHHGFFDDEEEDDDDDDDCCDCEDDDDDD +SRR9130495.105,D00236:723:HG32CBCX2:1:1108:3722:2006/1,TCCATAGTTTCGCAGAAGACTTGGAAGGATGTTGATGTATATGCAGGTCCATTATCAGTTTTTAAATTAGATGGTTTTCCCCAAGCTGCCCATGCGTCTAA,CCCFFFDDHHHHHJJIJJIIHGHIGIIDFHHIIIHHIJJIJJIJIJJJJJJIIJJIJG=DHHJJIJIIIJJJJJIGHGHHFFBFDDEEEDDDDDDBBDDDD +SRR9130495.106,D00236:723:HG32CBCX2:1:1108:3517:2148/1,CTCTGTTCTGTTCCATTGATCTATATCTCTGTTTTGGTACCAGTACCATGCTGTTTTGGTTACTGTAGCCTTGTAGTATAGTTTGAAGTCAGGTAACGTGA,CCCFFEBFHHHHFGGGIEEHIIJIJJIJJIIJIJJHIIJIIJJIIFHGIIIIJJJJJJFIJIJJJJGIIJIJCHIJIJHGJIJHHHHHHFFFFFFEEDECA +SRR9130495.107,D00236:723:HG32CBCX2:1:1108:3927:2234/1,CTGTGCTCTATGTACACGCCCATCTGTTTGCCTGACTACCACAAGCCGCTACCACCGTGCCGTTCCGTGTGCGAGCGCGCCAAGGCCGGCTGCTCGCCGCT,@C@FFFFFHHHHHJJJJGIIJIJJIJEHIIGHGJJIJJJJJJIIGHHIJIJIGHJIIJIHHGFFDEDE?BBDDBDCDDDBDDDDBDD>BDBDDDDBDDDB< +SRR9130495.108,D00236:723:HG32CBCX2:1:1108:4124:2011/1,GACTCAGAGCCAGGGCCCGGGAACAGAGATGACTCGAAGGCTAGGGCTCCAGCCAGACTTACCGGCACACGTACACCTCTAGGGGTGGCAGGGTGCTGGGT,CCCFFDDEGGGHHIJIIIJIIIIJIHHJJIJIIJIJIGGIIGIIHIGGIGHBHGHFEFFEECEDDDDDDDDBDDDDDCBACCDDDDDDBDDDDDDDDCD?9 +SRR9130495.109,D00236:723:HG32CBCX2:1:1108:4130:2090/1,TTCTATTTCTATAAACTGGCCTATTTTGGGTATTTCATATATATGGAAATATATAATTTGATTTTTTTGTTCTCTTAGCTGTATGTTTTCAGGATTCTTTC,@BBFDFFFHHGHHIJJJJJJJIIIJJJJIJJJIJJJJIJJIIIJJJIJJJJIJIIJJJJJJJJJIHJIJJHHHHHHFFFFFFEEEDECEEDDDDDCDDEDD +SRR9130495.110,D00236:723:HG32CBCX2:1:1108:4176:2091/1,AAATTGAAAGTAAATGTATACTGTAGTCCCACGCACGAGTGAATAAAGGGGTGTCTAAAAGGAGTGTGTTCTCTTCCAGGCTGCATCTCTCGGTACTCAGC,;8;ABD?+AA=ADBHIGBHE?ACCCCC +SRR9130495.111,D00236:723:HG32CBCX2:1:1108:4108:2121/1,ATGCGGAAGTAGGCAAAAATGATGTGCTAGACTACAAGAATTCCTTTTACAGAAAGTAACAAATACAGAGCCAAGAAAGTTTTTGTTAATTATCACGGTGT,@@@ADADA@AD>FIIBBBFGIBGHJDCIGEGGGHHHIJIIJJJJGHIIEHHEGHJIHGGGIFAGGGGIIG>=CHHFD?@;CCEDDDDCDD>>ACDCB@8<5 +SRR9130495.112,D00236:723:HG32CBCX2:1:1108:4384:2110/1,ACACAGGCAGCAATGATGTCTTTACTTCTTTATTTTTTTCGACTTCATCTACAGAGCTTAGCACAGCCATTGGAACAAAATTGGAGCTCAGTGCACAGTTA,@@@FDEFDDFF3CCF?FHCH@DEEGEFHIIFGBGGGDGIHAFBGDDHHIBAGGDGHE@CHAHBFFFFBDD +SRR9130495.115,D00236:723:HG32CBCX2:1:1108:4445:2247/1,TCTGTATTCTGTGTCATCTGCCATTCCTTGACTCCCTGCGCCCTTCAGCCCACAGGAAACGTGTGGATGACACACGAGGAGATGGAGTCTCTGACGGCAGC,CCCFFDDDHHHHGJJJJIJJJJBHHJJIIGIIJJJIIGIFIJJIIIIGIJJIIIJIJCHIIJJJIHHFHEFFFFDDDDDBDDCDDCDCDDDDCCCDBBDDB +SRR9130495.116,D00236:723:HG32CBCX2:1:1108:4698:2005/1,GAGGGAAGGAGGGAGGGAAAGAAGAAGGGAGAGAGGGAGGAAGGCAGGACTGTCGATGCAAGTACCTCGCTTCCTTGTTCTTAACTCATTTGATTCTTGCT,C@BFFFFFGHHGHIIIJJIBGGDHC@FEGDHIIIHGEHHEGCGIHHHFFFFDEEDDDEDDDDCDCCCDDDDDDDDDDDDDEDCCCDDDCDDDED:CCDDDD +SRR9130495.117,D00236:723:HG32CBCX2:1:1108:4588:2182/1,CTGGGGTGCAGTGGTGCAATCATAGCTCACTGCAGCCTCAATTTCCTAGGCTTAAGCATTTCTTCCACCTCAACTTCCCAAGTAGCCAGGATTACAAGCAC,CCCFFADDFFHHGGHHGIIJIJJJJJJHIIJIJJIFIJJEIIJIJIGIJIJJJJJJIJJJIIHIIJHIIFFHGHHFFFFFEDEECCCCBDBDDDDDDCDBC +SRR9130495.118,D00236:723:HG32CBCX2:1:1108:4964:2029/1,CCCCGTCTCTACTGAAACACACACACACACACACACACACACACACACACAATTAGCCAGGCGTGGCAGCGTCTGCCTGTAGTCCCAGCTACTCAGGAGGC,;8=:DDDDFFFAFIIFFBEIIEFIFIFIEFFFIIBEGEF?BF<4;A@EE/?;AB>7;7;>@?>B?''5<@;@?;0((4:@>34@@>:4<@>BAB@(948&+ +SRR9130495.119,D00236:723:HG32CBCX2:1:1108:4831:2078/1,GCGAAGAAAACTGAAAAAGGTGGAAAATTTAGAAATGTCCACTGTAGGACGTGGAATATGGCAAGAAAACTGAAAATCATGGAAAATGAGAAACATCCACT,CCCFFFFFGFHHFFHGIHDICFHIGGIDHIIJJJJIIIIIGIGHGIJJJJJJJJJJJIJJJIJJIHHHHHFFFFFEEEEEEEDDDDDDDDDDDDDDDDCDD +SRR9130495.120,D00236:723:HG32CBCX2:1:1108:4877:2117/1,GCATAATGTTGCCACTGCACTCCAGCTGGGACGACAAAGACTGTCTCTAAAAAAGTAATAAATAAATAAAAGTTTGAAATGCATTGTCCTAGGTTTTAGTC,CCCFFDEFHHHHHIIJJJJJIJIIIGIJJJJJJIIJIJJJIJJJJJJJJJJJJJIIHHGHHHHHFDFFFFFEEEEEEDDDDDCEEDEEDDDDDCDDDDDDD +SRR9130495.121,D00236:723:HG32CBCX2:1:1108:4918:2158/1,AAACATGTCAATGGCCAAAAAAAACAGACAATCAAAAAATGGACAAATATATGAACAGACATTTCTCACAAGAGGACATACAAATGGCCAGCAAATATATA,CCCFFFFDHHGHHIIJIJJJIIIJJJJJJJIJJIJJJIIJJJJIJJIJJIHGFHHHHFFFFFEFEEEEEDDDDDDDDCDDDDDDDCCBCDDDDDDDDEEEE +SRR9130495.122,D00236:723:HG32CBCX2:1:1108:4939:2211/1,CCTGGTCTCAGCATTCCTCACACGTCATAGCGAGGCCCATGGCTGTAGAAATCCCACCATTCTCTTCTCCCCAGGCCTGGCATCCGTAGAAGCCTACAGCT,@CCFFFFFHHHHDHIDIHIJIJJJJJIGGEGIJIIGIIIJJJGGIJJJJIGGHGIIIJJGHHHHHFFFFEFDEDDDDDDBDDDDDDDDD?CDDDDDDDDAC +SRR9130495.123,D00236:723:HG32CBCX2:1:1108:5169:2188/1,TCTGACCCCATGTCCTCAGGCCAGAACCCGGGAGCCTGTCAGAAAAGGTCTCTCACCTAGAGTCCATGCTCTGGAAGCTCCAGGAGGACCTGCAGAGGGTG,??@DD?DFHDFHFIIIIGFHEGGDFFHIBHGIAFIGGIIIFI@CHE@FGH@CDGGIFHEEFCCED@DEEEECCCCCCCCCCCCCCBB8ABC?ACAAABBBB +SRR9130495.124,D00236:723:HG32CBCX2:1:1108:5192:2231/1,ACTCTCCTGGCCCACGAGAGAGTCCACACAGGAGAGAAACCTTACCAGTGTCATGAGTGCGGCAAGAACTTTAGTCAGAAATCCTACCTTCAAAGCCATCA,CCCFFFFFHFHHGJJGEFGHGIIEIIFJJJIHGIJIIJIIIJIIGIEHHIGIHIJIIJIIBDFDDDDDDDDDCDDDCCDDDDDDDCDDCDDDDDCDDDDDA +SRR9130495.125,D00236:723:HG32CBCX2:1:1108:5408:2041/1,TGTGTGCATCCTCATGTGTCCTTGATAAGTGGTGTGATAAATGAAGGCTTTGCCACATTCCTTACACATGTAGGGCTTCTCTCCAGTGTGAGTCCTCTCAT,@@@DDDEBFHHHHIIIHIFHIDHIIIJHHJIHEGFIIHIJJIIJJEIJGHHIEIEGIIJIJJJGIGHGJJIIGIGIHJEHHHHHFFEFFFCC@CEEDDDDE +SRR9130495.126,D00236:723:HG32CBCX2:1:1108:5351:2057/1,CTCTATATATTTTAACAAATGCATAATGTCATGTGTTTACCATTACAGTAGGATAAAGAACAGTCTCATTGCCTTAAAAAGTTCCCTAACATTTTAATTGT,CCCFFDEDFHHHHJIJIIJJJIJJJHJJJJIJIIIHHIJIJIJJJJIIHIJJIIJJJJJIJJJJJJIJIJIJIIJJJJJJJGGIGHHFHFFFFFFFEEEEE +SRR9130495.127,D00236:723:HG32CBCX2:1:1108:5475:2108/1,AGCCCAGAAGGCTGGACACACCTCCCCCTCACCCCATCCCGCTCCCCAATCAACCCAGTCCTCAAGAAGCACACTGTGGCTGCTTGCTCTCTTGCCCCCCT,CCCFFDFFHGHGHJJIJJJIGIIIHIGIIJIIJJJIJJJHGIJIJIIIJHHGHHFFEDEEEECCDDDDDDDDDDDDDDDDDDDDDDDDDDCCDCDDDDDDB +SRR9130495.128,D00236:723:HG32CBCX2:1:1108:5542:2138/1,TGGCTAGCTACTGCTGCTGCTGCATCAAAGCCCAAATATTCACTGGCATCAGCTGTTTTGTTCTTTAGCATATTAGTAAAGTGCTCATTTAGAGACATCTT,@CCFFFFFHHHHGJIJJIJJJIJJJJJJJJJJJJJJIGGIJJJJJHJJJJJJJJJHIEIIJJJIIJJJIJIIJJJJHHHHHHHF@DFFFFEDEEEEDDCDD +SRR9130495.129,D00236:723:HG32CBCX2:1:1108:5707:2147/1,CCAGCATCACTCATGGAACCGGAGGCACTAAGGCCCCTCGGGAGACGCTGAGCAGGTGGGTAGAGGCATACTTCTGGGAGATGGCATCAAGAGCCAGTCAA,CC@FFDDFFDHG>FFFHGGIJIEIIIHIGIGHBHCEHGGGFH@FHGIHHFBFDEEDDEDDDDBDC?BBDCDDDDDC:?A?BDDDCCDC>ACDDDBDDACCC +SRR9130495.130,D00236:723:HG32CBCX2:1:1108:5614:2168/1,AAACCATGTCTCTACTAAAACTACAAAAATTAGCTGGGCAACATGGTGGGTGCCTGTATCCCAGCTACCTGGGAGGGTGAGGCACGAGAATCACTTGAACC,CCCFFFFFHHHHHIJJJJIJGJIJJJIJJJJIJJJJJIJJJJIJJHIIHJIJJJJJJJJJJJJJJJJGHFHHF@DDDDDDDDDDDDDDDBDDDDDDDDDDD +SRR9130495.131,D00236:723:HG32CBCX2:1:1108:5985:2027/1,GCGGCAGCGGCCGCGATGGAAGAACTTACGGCGTTCGTCTCCAAGTCTTTTGACCAGAAAGTGAAGGAGAAGAAGGAGGCCATCACGTACCGGGAGGTGCT,CCCFFFDDHHDGHFIJFHFFHHBFGHGEIJJJFFDDDDDDDDDDD@CCDCDDDDDAAACACDC@CCDBBBDBD@ +SRR9130495.132,D00236:723:HG32CBCX2:1:1108:5816:2071/1,TTTACATATAAGAACCTGATGACCTTTTGTTTTTGTCCAGGAGAGTCCTTCTTGTCTACGAAATGCAGCTATCACAGCAGCTGGACTTGTTTCCTGAATGC,C@CFFDDAFFFHHHHHHGFIHJIJFHHHCAAEHIGHJGCCGHIHEHJJJEHGIIIFIGBBAEHGIJIGIIHHEHHHFFFFEECCABCDCCCCACDDACDA: +SRR9130495.133,D00236:723:HG32CBCX2:1:1108:5835:2081/1,CCAGGGCTCCAAGGGGCTGGTTACGAAGTGTCTCCTGCTGCATGAGGTCCCCACGGGAGAGATTGTGGTCCGCCTTGACCTGCAGTTGTTTGATGAGCCGT,@CCDDDFFHHHGHGJGJFHIEHIGCGHIGJGIIIJJJJJJJJJIIIEIJFGIJJIJGCCDDBDDCDDDBDDDDCDDDDDDDD>BACDDDEDDCBD +SRR9130495.134,D00236:723:HG32CBCX2:1:1108:5841:2101/1,GGGCATGGTGGCATGCGCCTGTAGTCCCAGCTATTCGGGAAGCTGAGGCAGGAAAATCTCTTGAACCCAGGAGGCGGAGGTTGCAGTGAGCCAAGCTTGCA,@CCF?BDDHFHGHIIIIIIIIIGHGHHIIIFIIIIIGGFGGIIIIEFGGEGHCD>CGGFHHHGGHFFFCDDADDDDDDDBDBCDCCCCA@CCCCBDDDDDD +SRR9130495.135,D00236:723:HG32CBCX2:1:1108:6165:2044/1,TTTATACCATTTTTTTTTTTAGCATATATCCTTGTACTTTATAGGAATTATTTGCTTTATTCTCTTGTGACTTGTAAATTGATGTACTTAATTAAATCTTT,"@@CBAB;DHFFHHIGIIGGHGFF@?BGB@8=FHEGHIGD=@CGHIA;@EHFHGHBFFFCBD;>(>@A@C>>;>CA;;35>@3;>5>,;3>:;(:@:>:@@C" +SRR9130495.136,D00236:723:HG32CBCX2:1:1108:6059:2069/1,CTATGACCGCTATGTTGCCATCTGTAGCCCACTGCTTTATAACACTGTAATGTCCCACAAGGTCTGTTCCATAATGATGGCTGTGGTATACTCACTGGGCT,CCBFFDBEHHHHFEGIIGHGIIIJIIHIJIFIJJJJJJJJJJIIJJIJJJJIIHHIJIIIFIHIJFIGIIIHGGHHHHFFFFDEEEEEDEFEDDDCDDDBC +SRR9130495.137,D00236:723:HG32CBCX2:1:1108:6161:2181/1,ATGAAGCAACAACCTTATAGGCATTTTAACTCATAGGTTTTAAAACTTAAGGTTATTTTCATAGGAGTCCCTTTTAGCAGAAATGCTCACCACAGGACCAG,@@CGGDD@4???BDHCH@GH<=FHGEGGGIGCEG@E7ACH@:77?C@A@CBAA???2FFFIGIIGIIIIFDADBDDDDDDDBBBBBBCDD@CDDDD?BDDDDDDCDDBDDDBDDDCCCCCBBCCCDCCCCDDAC>ABDDDCDDDDA@C +SRR9130495.144,D00236:723:HG32CBCX2:1:1108:6837:2146/1,CCTGTTATTTTAGTTGTTAAAGGTGGCATTCTGTTCTTGTGGCTGTCTTCTTTTAGGTTTGTTGAGGGATTACCTTCTTGTTTTTTCTAGGGCATTGTTCC,BCCFDDFDHFDHFGIIIIJIGIIJJIDGHIJIIJJJJJJGFIIIHFHHIJJJIGDGIGHGHIJICHGGEHGCHGFEHFHHFDDDDDDDDDDDC?CDDDDCC +SRR9130495.145,D00236:723:HG32CBCX2:1:1108:6804:2189/1,TGAATCTCTCTTGGCCTCCTCCCCTCTCATGTCCCCTCCTCCCTCCTCTCCACTTACTCCTCCTCCTCCCCTCCCTCCTCCCAGATGGTTCTGTGTCTTTT,CCCFFEFFHHGHHJJJIJJIJJJJIJJJJJIJIFIJIGIIGGJIJJIIIIIGIIJIJIJGIIIJIJJHHHFDFFDCDCCDDDCDBCCDCDDD@ACCCDDDD +SRR9130495.146,D00236:723:HG32CBCX2:1:1108:6940:2229/1,CTTAATGCCACTATCACCACTTCCTTCAAGAGTGAGGGAGAGGAAGAGGAGGAAGAGGAGGAGGAAGAAGAGGAGGAGGAGGAAGAGGAGGGTGAAGGGGA,@@@DBDDEFHHHHGIJIEGGIGECHIFIIJGFHHACCF?D:DFF;?FHH9DFCGGHFG@CA?AB?DD>?A@BDDBB=?B5@BBFCAA@A;;5?BB9;=>;BB?1>A?ABDCC +SRR9130495.149,D00236:723:HG32CBCX2:1:1108:7167:2101/1,TTTCATGTTTTAGGTCTTGTAAGCAAGATTTTTCCTGTTGAAAAACTGGTTGAAGAAGCCATCCAATGTGCAGAAAAAATTGCCAGCAATTCTAAAATCGT,?@?DB?DDHHGDHIHHGBIECFDHHE>C7?BB7;@A(5==;88323>CDC9B +SRR9130495.152,D00236:723:HG32CBCX2:1:1108:7449:2110/1,GGCTTCAGGAGCTTCAGAAGTTAAGAGCTGCAAAAAAGAAGAAAAAGGATCGGCCAAGTAAAGACTGTTCCAAGTTGGACATGCTTGCTAGAAATTTCCAG,CCCFFDFEHGHHGJIIBEEHHIIIHHIGGJIIJIIGIIGGHIIIJIGGGGGGGIIJJHHFHHGFFFFFEEEEEEEDDDDDDDCDDEDDDDDDDDDDDDEDC +SRR9130495.153,D00236:723:HG32CBCX2:1:1108:7499:2197/1,TTCTCATAGTTCAGCTTCCACTTGCGGTAGCTTGTTCCACTTGCGGAACATGTGGTGTTTGGTTTTTTGTACCTGCACTAGTTTGCTGAGAAAGATCGGAA,@@@DDDDEHHFFHABECCAFHHHFDGIHJIIEFGHIIGIGEHEBGG0AEDHGFFFGIDG@EH=ADEBADDE@CCCBCACDDDEEDDCCCBCCC@CC>AB@@ +SRR9130495.154,D00236:723:HG32CBCX2:1:1108:7309:2205/1,GGAGGCTGAGGCAGGAGAATCGCTTGGACCCGGGAGGTGTAGGTTGCAGTGAGCCAAGATTGCGCCACTGCACTCCAGCCTGGGTGACAAAGTGAGATATT,BC@FFFDFDHHGFIGIIIJIJJJJJIJJJIIJJJIIIHHIJIJJJIJHHHHGHFFFEBAEECEDDB:@CDDDDCDDDDDDDDDBCBDCDCDDDCDBDCC?ACDD34>C@BD<>>:CB<>@BA8 +SRR9130495.156,D00236:723:HG32CBCX2:1:1108:7518:2119/1,TTATCAAAGAGGCCCAAGAGAAACCACTTGTCTGACTTCTACCATATGAGTTTAGAATAAGATGATGGCTGCCTATGAGGAAGCAGGCCCTCAACAGATAC,@@@DDBD4CFFAAHII=G9FDHG;?F@;EEBEFCF>BGBGDBECC@BBBBBBBCCABC@CC +SRR9130495.157,D00236:723:HG32CBCX2:1:1108:7577:2169/1,AGTTACTTAATATACCTTAGCCGAAACTTCTGCACTGATTTCCTCCTGTGTTTCAGCCAGCCGCTTTTTGGCAAGTTCGGTTCTCCGATCACACTCTGCAA,@@@DDDFFFFHGHIICGHFH@FGGHGHHJGIHJIJIJGIIIBDHCBGGHEHIJJIGIIIBGIEIGGHHCEBDFEDECD?@DDDDDDDDDDBCCDDDDDDC> +SRR9130495.158,D00236:723:HG32CBCX2:1:1108:7659:2196/1,TTCTGATTTTTGCTGCAGCTTCTGCTTATAATCATATGGCCAGTTGTGCTTGTCAGAGTAATGGTGAAGTCCACAAAACAAATTTCCACATCGGCAGTCAA,CCCFDDDDHDFHFGIFCHIII9FHHIGGHHIJJJJIJJEHGEGIIJJJJJJJJDHGI:DFGIIGHGJGCGHGIJJGIIHGHGFFECB@CEC@B@BDD?CCD +SRR9130495.159,D00236:723:HG32CBCX2:1:1108:7733:2213/1,GGCCAGATGTTTCTGTAAAGATTGAATTAGATCCCCAGGGAGAGGCAGCACAAAGTGCAAATGAATCAAAAACTGAGTAGAATATTGTAGAGTGCCAATTA,@<@DDA+AFFHHHIIFBHC@@F>@>CC: +SRR9130495.160,D00236:723:HG32CBCX2:1:1108:7590:2217/1,GGGGCTGGGCCCACCTGGGACAGAGGGCCACATGTAGAGGCAGCGCTCCCCCGTCTTGAGCTGATCTTTGCAGTCGAATAGCATGAGGTTGGCCCAAGCGA,CC@FFDDDGHHDHIJDGIIACBDDBBBDDD@ +SRR9130495.161,D00236:723:HG32CBCX2:1:1108:7735:2228/1,GCAGCACTGTCTGAGTATGGGAGCAAAGCCTAATCTGGCTTGCCCGGCCTCTCACCTCTGTGGCGCTCTGCATCATGGTGCTTCTTGTCATCTTTTATTGC,?@;DDDDDFCFFHIHHGBHIBH?FHIBDEHB@GEIHIEHGHAFFHGEEH<@CC@C@CCA +SRR9130495.162,D00236:723:HG32CBCX2:1:1108:7898:2065/1,GTTGGCTTCCCCCTCCCCTCTCCCGTGAGCTGAAAAGCAACAAGGGCTCCACCAGCCTGCAAAATAAGACTTGGGGGGGGGGGGGCAGGGATTGCTTTTTT,@@@FDDDDHHFHFIJIFHIIJJJDHFGIGIGJAFHIDG>@GGFHGGHJIGCHIIGEEHFGF@CFEECC>;>CCABBD<99B@BD99&)&&+9(3(4>(+:0 +SRR9130495.163,D00236:723:HG32CBCX2:1:1108:7872:2066/1,CACGCTGGATGAGTTCCTGTTCAGCGACCTGCAGGCGCTGGAAGTGCTGTTGCTCTACAATAACCACATTGTGGTGGTGGACCGGAATGCCTTTGAGGACA,CCCFFFFFGHGGHJJJJJJJJJJIJJJJJJHJJJJJIJJIJJJIGIJJIJJJJIHHHHHHFFDFFEDDEEEEDDDDBDDDDDDDDDDDDDDDDDDDDDDDD +SRR9130495.164,D00236:723:HG32CBCX2:1:1108:7826:2191/1,ATCTCTGGACCCAAACTGGAGGGTGACATTAAAGTTCCCAGGGTGGATTTGAAGGGCCCAGAAGTGGACATTTCTGCTCCCAAGGTCAATATTGATGGGAA,CCCFFEFFGHHGHIHHIIJIIIJJIJIGIIJIHIGIJJJJIJJBFGGIJJIJJJJJIJIHFHHFFF@EEDEEFEEDDDDDDDDDBACDDF@CDEDEDDBDD +SRR9130495.165,D00236:723:HG32CBCX2:1:1108:7791:2195/1,GGAGAACAGCGTGTAGAGCACTCACAGTCTGCTGCCTTCAGGTGTGGGAGGCACTGCTCACACTGATCTTCTTCCCGGTGTGTGTGGTGTTTGCCTGGATG,CCCFFDEFFGHHHJDIIJJIFJJJJJIJJJGIJJIIJIIIJIJIIGEGHHJJJJJIIFIJJJHHHHFHFFDDFFEDC>9;?BBDDD?CDDDDDDDCC?BDC +SRR9130495.166,D00236:723:HG32CBCX2:1:1108:7767:2199/1,GACTAGCCTGGCCAACATGGCAAAACCCAGTCTCTATTAAAAATACAAAAATTAGCTGGGCATGGTGGTGCACGCCTGTAGTCCCAGCTATTCAAGAGGCT,@@@DDDFFFHHFBHBHBDEHHGGGHIIJIIHIHJIEEEIGHEIHIIGHIIHHGJIEHGI?G@CDHI=CA?BDFFACDCCDFCC32??A +SRR9130495.167,D00236:723:HG32CBCX2:1:1108:7824:2210/1,GCACCACCGTGCCTGGCTAATTTTTATATATTTAGTAGAGATTGGGTTTCACTGTGTTGGCCAGGCTGATCTTGAACTCTGGACCTCAGGTGATCCTCCCG,@@@FFDDFDFAHHJJIJIIGHHHHHIIJIIDGG>GHHIGGCGHGIEHGGH>FFHJJJHDGBGHJCGGGHFEHHHHFFFFFECDECEDDDCDDDDCCDDCDD +SRR9130495.168,D00236:723:HG32CBCX2:1:1108:8205:2084/1,CTTAGCCGCTGGTGATGCTAAGGGCATGGTCAAAGTGTGGCAGCTGAGCACAGCCTTCACAGAACAAGGGCCCCGGGAGGTGGAGGACTTGGATCAGCTAG,CCCFFDEDFFHHHJEGIDHHIIIIJJJIJGIJJJGHJIJIJJJIIIJIGGIIGIJJIGHIIJGEFHGBEFDDDBDDD;>B2<@BBDBBCCCCDDDDDDDDD +SRR9130495.169,D00236:723:HG32CBCX2:1:1108:8202:2124/1,GAGACTCTTGCACACATACCGGGGAGCTGGCTCACCCTGGCCCCTCCATCCTGTCAGACTGAAGAGAACAAGTGTCTTAATTTGGGTTTTTCTTATTATTA,CCCFFEFDHFHGHGJIIIJJIJJJIIIGIJJJJFIJJHGIJGHIIJJEEEHFGFFEFECCEEEEDDDDCCAD>CCDDDDCCD?@@A=?8=?=BA93>CA??B@A????8CD(8&8?()(+224@?@>35 +SRR9130495.179,D00236:723:HG32CBCX2:1:1108:8868:2131/1,GTACATTGTATCTTTGTTCTCATTAGTTTCAGAGAAATTATTGATTTCTGCCTTTATTTCATTATTTACCCAAGAGTGATTTGGAAGCAGGTTGTTCAGTT,<;;B?D>DFC:DBF@AEDHHAHHGH:A:AC4?BFFEDA?ABD@ACCD:> +SRR9130495.183,D00236:723:HG32CBCX2:1:1108:9106:2031/1,CTAGAAATCCTGGATTTTCAGCACAATAACTTAGCCAGGCTCTGGAAACGCGCAAACCCCGGTGGTCCCGTTAATTTCCTGAAGGGGCTGTCTCACCTCCA,C@CFFDFFGGHHFJHIIJGIHCCEHHIGIFIIHIJJFIGJIGIJJIIJHIFGIJIJFFHHFDAD@BCCBDDDDBCC@CDDCCDDAEFC'8;&+)+((&28&&&+((&)&&++((++8((2(((25(&&&(++(0&&&(+((+4(+ +SRR9130495.186,D00236:723:HG32CBCX2:1:1108:9230:2213/1,ACTTAGTGCAGTACCCACTATTCCCGCTCAGGCTCCGAATAGTAGATAGAGGGTTCCGATATCTTTGTGATTGGTTGAGAATAATCAACGATTAATGAACA,CCCFFFFEHGFFHFIICIIFIJHHGBHHGIGJJIJGGHIGFHIGIIJJJIIGJCFIJI@EFDFEDFFCCEEEEDDDBDDDDDDDECCDD@BDDDCDDDCDC +SRR9130495.187,D00236:723:HG32CBCX2:1:1108:9264:2024/1,AACATAAGGTTTCTCATAAAACAAAGAAAAATGTCAATTCAGTTGTGAATTCATATTGATACCTGGAACTCTCCTGCTAGACCACCTCTAAAGGCCCAGGG,CCCFFFFFHHHGHIJJIDJIJJJDHIIJJJJIJJJJJJJIJJGCHIIJJJJJJJJJJIHJJJJJJGIJJIJIJIIIIJJHHHHGFFFFFECEEDDDDBBBB +SRR9130495.188,D00236:723:HG32CBCX2:1:1108:9293:2034/1,GTGGGGAGGTTTGGGAGTGAGCAGCACACCCCAGTTAGACTCCTGTTGGGTTTCATAGGAGCTGGCTGCTGAATGTAAGAGTGCAGGCTACCCCGGGACTT,@@@FDA;1DAFHFIIFBGIGHGADHIGIIIIIIIIHBFEHIIIIIIIIHIACEEEHHBD@CDECECCBBCCACCCCEECCCCCCCCBBBCCCB?9>>>>BC +SRR9130495.189,D00236:723:HG32CBCX2:1:1108:9484:2048/1,ATGTAGAGAGAGGGAAAAAAGGAGAGAGAGAAGGATAAAGAGAAGGATGCACAAGAAGACCAAAATACCTGATCATGTAGGGGAGAGCCTCTGGGAGAAGG,@@@DFDDDCDDFHICFHHDGIIHHCHCFFDGHHDCGIJIH@FFHFHGIIGIJIGIGF@CEBDFF@EECDCCCCCCDDEEEDDDDDDDDDDCDDCD<@BDCB +SRR9130495.190,D00236:723:HG32CBCX2:1:1108:9388:2219/1,AGCTGCTGCGAGATGGTGGCTTGCATCTCCTTGGACGGCCGCTTGTTCTCCTTGAAGATGGCAATCAGCGTGCGGCGCTGCAGGTCTGTGAACACGAGGCG,"B?>3=?>;@DF@>CACC>;>@A>',,88>>-09599(+8>C95>>>00" +SRR9130495.191,D00236:723:HG32CBCX2:1:1108:9404:2245/1,TCCGGCTGGTACCTTCATAACTACAGTAATAGAAGACATTGAGTGCCTCCACCGCAGCTGGCCCTCTCTGTTTGTAGCCAAAGATCAGATCTATCCATTCA,CCCFFFFFHHHHHJJIJIIJEIIJJJJJIJJJIJJJIJIIIIIJJJIJJIIJJJJEIJJIHIGHHHFFFFFFDEEEEEDDDDDDDDDDDDDEDCDDDCDCC +SRR9130495.192,D00236:723:HG32CBCX2:1:1108:9632:2134/1,ATAGTGGCTGCTGATGGATGTGCTCTATGCAAGGGAGGTGCTCACTATTTCTGTTCGTCAATTTGTAACCCACGGGAGGAAAGGGAACAAAGAGTGAACAA,CCCFFFFFHHHGAEFFHIICHGIJHGFIIIHIJDGIJJIIIEGIJJIIFHEGHGIICHIIFIJJJJIIJJHHHFFDBDD?BDDDDBDBDDBCDD:@CCCCD +SRR9130495.193,D00236:723:HG32CBCX2:1:1108:9647:2175/1,AATACCAGCCCAAGACTTTGGGAGAAGGGAAGAAAACAAAGTAAAATAACTTACCACTTTGGCCCAGTCCGAGAACAAGTGAAAATACCCAGGCTGCCCCA,CCCFFFDFGHHFHIIJJGIIIJDIIJIJJJJIIHIIIIJJJHCFHHFHIJJJJJJGIHJJJIJJHGHHHFFFDDDDDCD>CCDDDDDDCDDDBDDDDDDDD +SRR9130495.194,D00236:723:HG32CBCX2:1:1108:9552:2194/1,CCATGCCGACACAGGTAGATGGTACGGGGCTGCACGTGGATGTTCATCAGGTAGTATACAATTCGGCTCTGGATGTGGTCCTGCACTCTGTTCACCAAGAA,@@CFFFFFGHGHHJJJIJJJJIJJJIGHFEGGIFIJIJIIIIIJJIIJJIHHHHHHHFFFFFFFDCDDDC@@ACDDCDDDDDDDDDDDDCDDD@CCDDDDD +SRR9130495.195,D00236:723:HG32CBCX2:1:1108:9620:2235/1,CCAATGATGGCCAACTAGGCCATCTTCTACTATGTACGCAGCTAGAGGCACGAGCGCTGGGGGTACCGATTAGTTCATATTGGTGTTCCACCTATAGGGTT,"===BD?DBAABD8AC3?F?D9C6'5;:>7<<>8:(',&22>(((:>3>+:(+28(43>@B(>:>A((32" +SRR9130495.196,D00236:723:HG32CBCX2:1:1108:9908:2124/1,TCTTGTGAAGAAGATGCTGTTGGAAGCCTCTAAGAAGCCCGAACTGAATGCTCTTATAAACAATACCAGAGGAATTATTTTTTACAGTGTCCCTCACCATG,CCCFFFFFHGDFGIIJJIJJIGGJJIIJJIIJHIIIIJJJJI>HHIFIJIJIJJIIHIHIJJJJIHIHHHGFDEFFEEEEEEDDDDDFDEDCCDCDDDDDD +SRR9130495.197,D00236:723:HG32CBCX2:1:1108:9923:2206/1,TGGGGCTGTGAACCGAAGTCTGCTCCTTTGCGTGAGCCACCCCTGCAGCCCCTCCCACAGTTCCTGAGGAGCCTTTAGTCCTCGTCCTTTCTCAGCTGTAT,@BCFFDAFHHHHHIIIIHIIJIIJIIJJJIIIJJIGGIIIJJFGGGGGEIIIGFHHEFFFEECCCC@CB@BDDDCDDCCDCCDDABBBCDDCC@CCDCCCD +SRR9130495.198,D00236:723:HG32CBCX2:1:1108:10131:2036/1,ATGTGCTCAAAGGCTGGGTGGACCTTACCTCCAGTAAACCCCACGTTGTGAAGAAATCCATCAAGTACCTGGAACAAGGAACTCAAGACACCAAAGATGTG,@CCFFFDDFFBHDHIIIBFEGFGHGHGDFHFGIJJIIHDGEGHIJHFHIIIIJJJJJIIIFHHHFHFFFFFFBAEAACBBCADDDDDDDDADBABCCC>AA +SRR9130495.199,D00236:723:HG32CBCX2:1:1108:10246:2089/1,GCCCTGGGATTGTCCCTCTGGGCACAGGGAGTCCTGGGGTTGTCCCTCTGAGTAGTTCTGTTGGGAGAGGAGGCCCTGGGATTGTCCCTCTGGGTACAGGG,CCCFFBDDHHHFHJIIIJJJJIIIIIFIIEHGIGJIJDHJIJIIJJFJIJ@FFCHJJJBEGEHHHDFDCD@DBB;=?A?@BDDDCACDDDDD@?CCCCDCB +SRR9130495.200,D00236:723:HG32CBCX2:1:1108:10051:2156/1,ATGGAGGATGGCACCCTGCAGGCTGGCCCAGGAGGTGCCAGTGGGCCTCGTGCCCTGGAAATAAATAAAATGATTTCTTTTTGGAGGAATGCTCATAAACG,@@CDFFDFGFHFFIJGGIICCDDADDB From 66d97e035441602db85e938581ede35532882c66 Mon Sep 17 00:00:00 2001 From: Jakub Winter <117023023+jwinter3@users.noreply.github.com> Date: Sun, 15 Jun 2025 21:47:37 +0200 Subject: [PATCH 12/13] Move target partition outside base sequence quality function --- docs/notebooks/base_sequence_quality.ipynb | 58 +++++++++++++++------- polars_bio/quality_stats.py | 5 -- 2 files changed, 39 insertions(+), 24 deletions(-) diff --git a/docs/notebooks/base_sequence_quality.ipynb b/docs/notebooks/base_sequence_quality.ipynb index c88a6a58..355fde79 100644 --- a/docs/notebooks/base_sequence_quality.ipynb +++ b/docs/notebooks/base_sequence_quality.ipynb @@ -10,10 +10,20 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 1, "id": "58b40aa6", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/jwinter/TBD/proj2/polars-bio/venv/lib/python3.12/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", + " from .autonotebook import tqdm as notebook_tqdm\n", + "INFO:polars_bio:Creating BioSessionContext\n" + ] + } + ], "source": [ "import pandas as pd\n", "\n", @@ -28,6 +38,16 @@ "### Usage examples" ] }, + { + "cell_type": "code", + "execution_count": 14, + "id": "b0d81403", + "metadata": {}, + "outputs": [], + "source": [ + "pb.set_option(\"datafusion.execution.target_partitions\", \"2\")" + ] + }, { "cell_type": "markdown", "id": "b238193d", @@ -38,7 +58,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": null, "id": "0420c240", "metadata": {}, "outputs": [ @@ -46,25 +66,25 @@ "name": "stdout", "output_type": "stream", "text": [ - " pos avg q1 median q3 lower upper\n", - "87 0 30.135 31.0 33.0 34.0 26.5 38.5\n", - "66 1 31.210 31.0 34.0 34.0 26.5 38.5\n", - "69 2 32.015 31.0 34.0 34.0 26.5 38.5\n", - "45 3 35.690 35.0 37.0 37.0 32.0 40.0\n", - "14 4 35.680 35.0 37.0 37.0 32.0 40.0\n", - ".. ... ... ... ... ... ... ...\n", - "40 96 31.315 32.0 34.0 35.0 27.5 39.5\n", - "23 97 30.670 31.0 34.0 35.0 25.0 41.0\n", - "37 98 31.550 32.0 34.0 35.0 27.5 39.5\n", - "6 99 31.250 32.0 34.0 35.0 27.5 39.5\n", - "4 100 31.105 31.0 34.0 35.0 25.0 41.0\n", + " pos avg q1 median q3 lower upper\n", + "88 0 32.548723 31.0 34.0 34.0 26.5 38.5\n", + "46 1 32.719772 31.0 34.0 34.0 26.5 38.5\n", + "99 2 32.789697 31.0 34.0 34.0 26.5 38.5\n", + "75 3 36.162011 37.0 37.0 37.0 37.0 37.0\n", + "84 4 36.122733 37.0 37.0 37.0 37.0 37.0\n", + ".. ... ... ... ... ... ... ...\n", + "19 96 32.998462 34.0 35.0 35.0 32.5 36.5\n", + "64 97 32.922582 33.0 35.0 35.0 30.0 38.0\n", + "70 98 32.883908 33.0 35.0 35.0 30.0 38.0\n", + "80 99 32.836223 33.0 35.0 35.0 30.0 38.0\n", + "51 100 31.190304 30.0 34.0 35.0 22.5 42.5\n", "\n", "[101 rows x 7 columns]\n" ] } ], "source": [ - "result = pb.base_sequence_quality(\"example.fastq\", output_type=\"pandas.DataFrame\", target_partitions=2).sort_values(by=\"pos\")\n", + "result = pb.base_sequence_quality(\"example.fastq\", output_type=\"pandas.DataFrame\").sort_values(by=\"pos\")\n", "print(result)" ] }, @@ -107,9 +127,9 @@ "| -------------- | ----------------- | ----- |\n", "| fastqc-rs | - | 22.9s |\n", "| polars_bio | 1 | 9.0s |\n", - "| polars_bio | 2 | 8.5s |\n", - "| polars_bio | 4 | 15.6s |\n", - "| polars_bio | 8 | 7.8s |\n", + "| polars_bio | 2 | 7.8s |\n", + "| polars_bio | 4 | 14.9s |\n", + "| polars_bio | 8 | 7.4s |\n", "\n", "- The measured execution time is for the algorithm to run on file ftp://ftp.sra.ebi.ac.uk/vol1/fastq/ERR194/ERR194147/ERR194147.fastq.gz, which contains about 8,240,000 records.\n", "- The `fastqc-rs` execution time applies only to the base sequence quality task (pieces of code relating to other tasks have been removed for the purpose of this comparison).\n" diff --git a/polars_bio/quality_stats.py b/polars_bio/quality_stats.py index 6c23b6d9..cc1a1be2 100644 --- a/polars_bio/quality_stats.py +++ b/polars_bio/quality_stats.py @@ -15,7 +15,6 @@ def base_sequence_quality( df: Union[str, Path, pl.DataFrame, pl.LazyFrame, pd.DataFrame], quality_scores_column: str = "quality_scores", output_type: str = "polars.DataFrame", - target_partitions: int = 8, ) -> Union[pl.DataFrame, pd.DataFrame]: """ Compute base sequence quality statistics from various dataframe/file types. @@ -28,10 +27,6 @@ def base_sequence_quality( Returns: DataFrame with base sequence quality statistics. """ - ctx.set_option( - "datafusion.execution.target_partitions", str(target_partitions), False - ) - if isinstance(df, (str, Path)): df = str(df) supported_exts = {".parquet", ".csv", ".bed", ".vcf", ".fastq"} From ffaa6facae81561f3a8ad56f00eccd622b39215a Mon Sep 17 00:00:00 2001 From: Jakub Winter <117023023+jwinter3@users.noreply.github.com> Date: Sun, 15 Jun 2025 22:25:24 +0200 Subject: [PATCH 13/13] Update notebook --- docs/notebooks/base_sequence_quality.ipynb | 81 +++++++++++----------- 1 file changed, 41 insertions(+), 40 deletions(-) diff --git a/docs/notebooks/base_sequence_quality.ipynb b/docs/notebooks/base_sequence_quality.ipynb index 355fde79..1e484745 100644 --- a/docs/notebooks/base_sequence_quality.ipynb +++ b/docs/notebooks/base_sequence_quality.ipynb @@ -1,5 +1,16 @@ { "cells": [ + { + "cell_type": "markdown", + "id": "76af9b7e", + "metadata": {}, + "source": [ + "# Team Z6\n", + "- Mariusz Paluch\n", + "- Bartłomiej Ściseł\n", + "- Jakub Winter" + ] + }, { "cell_type": "markdown", "id": "83d7ccd7", @@ -10,20 +21,10 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 14, "id": "58b40aa6", "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/jwinter/TBD/proj2/polars-bio/venv/lib/python3.12/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", - " from .autonotebook import tqdm as notebook_tqdm\n", - "INFO:polars_bio:Creating BioSessionContext\n" - ] - } - ], + "outputs": [], "source": [ "import pandas as pd\n", "\n", @@ -40,7 +41,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 15, "id": "b0d81403", "metadata": {}, "outputs": [], @@ -58,7 +59,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 16, "id": "0420c240", "metadata": {}, "outputs": [ @@ -66,18 +67,18 @@ "name": "stdout", "output_type": "stream", "text": [ - " pos avg q1 median q3 lower upper\n", - "88 0 32.548723 31.0 34.0 34.0 26.5 38.5\n", - "46 1 32.719772 31.0 34.0 34.0 26.5 38.5\n", - "99 2 32.789697 31.0 34.0 34.0 26.5 38.5\n", - "75 3 36.162011 37.0 37.0 37.0 37.0 37.0\n", - "84 4 36.122733 37.0 37.0 37.0 37.0 37.0\n", - ".. ... ... ... ... ... ... ...\n", - "19 96 32.998462 34.0 35.0 35.0 32.5 36.5\n", - "64 97 32.922582 33.0 35.0 35.0 30.0 38.0\n", - "70 98 32.883908 33.0 35.0 35.0 30.0 38.0\n", - "80 99 32.836223 33.0 35.0 35.0 30.0 38.0\n", - "51 100 31.190304 30.0 34.0 35.0 22.5 42.5\n", + " pos avg q1 median q3 lower upper\n", + "46 0 30.135 31.0 33.0 34.0 26.5 38.5\n", + "14 1 31.210 31.0 34.0 34.0 26.5 38.5\n", + "54 2 32.015 31.0 34.0 34.0 26.5 38.5\n", + "99 3 35.690 35.0 37.0 37.0 32.0 40.0\n", + "7 4 35.680 35.0 37.0 37.0 32.0 40.0\n", + ".. ... ... ... ... ... ... ...\n", + "95 96 31.315 32.0 34.0 35.0 27.5 39.5\n", + "62 97 30.670 31.0 34.0 35.0 25.0 41.0\n", + "67 98 31.550 32.0 34.0 35.0 27.5 39.5\n", + "53 99 31.250 32.0 34.0 35.0 27.5 39.5\n", + "55 100 31.105 31.0 34.0 35.0 25.0 41.0\n", "\n", "[101 rows x 7 columns]\n" ] @@ -98,7 +99,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 17, "id": "7322aae3", "metadata": {}, "outputs": [ @@ -145,7 +146,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 18, "id": "66c3af24", "metadata": {}, "outputs": [ @@ -182,7 +183,7 @@ "└─────┴────────┴──────┴────────┴──────┴───────┴───────┘" ] }, - "execution_count": 20, + "execution_count": 18, "metadata": {}, "output_type": "execute_result" } @@ -201,7 +202,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 19, "id": "a2cb9c97", "metadata": {}, "outputs": [ @@ -238,7 +239,7 @@ "└─────┴────────┴──────┴────────┴──────┴───────┴───────┘" ] }, - "execution_count": 21, + "execution_count": 19, "metadata": {}, "output_type": "execute_result" } @@ -257,7 +258,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 20, "id": "1899ca01", "metadata": {}, "outputs": [ @@ -279,7 +280,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "200rows [00:00, 211459.74rows/s]\n" + "200rows [00:00, 212477.41rows/s]\n" ] }, { @@ -315,7 +316,7 @@ "└─────┴────────┴──────┴────────┴──────┴───────┴───────┘" ] }, - "execution_count": 22, + "execution_count": 20, "metadata": {}, "output_type": "execute_result" } @@ -336,7 +337,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 21, "id": "7830b8aa", "metadata": {}, "outputs": [ @@ -345,7 +346,7 @@ "output_type": "stream", "text": [ "INFO:polars_bio:Table: example registered for path: ./example.fastq\n", - "200rows [00:00, 182877.87rows/s]" + "200rows [00:00, 177236.59rows/s]" ] }, { @@ -395,7 +396,7 @@ "└─────┴────────┴──────┴────────┴──────┴───────┴───────┘" ] }, - "execution_count": 23, + "execution_count": 21, "metadata": {}, "output_type": "execute_result" } @@ -417,7 +418,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 22, "id": "56817174", "metadata": {}, "outputs": [ @@ -426,7 +427,7 @@ "output_type": "stream", "text": [ "INFO:polars_bio:Table: example registered for path: ./example.fastq\n", - "200rows [00:00, 193508.84rows/s]" + "200rows [00:00, 74651.67rows/s]" ] }, { @@ -476,7 +477,7 @@ "└─────┴────────┴──────┴────────┴──────┴───────┴───────┘" ] }, - "execution_count": 24, + "execution_count": 22, "metadata": {}, "output_type": "execute_result" }