diff --git a/CHANGELOG.md b/CHANGELOG.md index 9dd2389c..6bd21a1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,13 +20,17 @@ based on a provided sequence IDs or region coordinates file (PR #85). * `agat`: - - `agat_convert_sp_gff2gtf`: convert any GTF/GFF file into a proper GTF file (PR #76). - - `/agat_convert_bed2gff`: convert bed file to gff format (PR #97). + - `agat/agat_convert_sp_gff2gtf`: convert any GTF/GFF file into a proper GTF file (PR #76). + - `agat/agat_convert_bed2gff`: convert bed file to gff format (PR #97). + - `agat/agat_convert_embl2gff`: convert an EMBL file into GFF format (PR #99). + - `agat/agat_convert_sp_gff2tsv`: convert gtf/gff file into tabulated file (PR #102). + - `agat/agat_convert_sp_gxf2gxf`: fixes and/or standardizes any GTF/GFF file into full sorted GTF/GFF file (PR #103). * `bedtools`: - `bedtools/bedtools_intersect`: Allows one to screen for overlaps between two sets of genomic features (PR #94). - `bedtools/bedtools_sort`: Sorts a feature file (bed/gff/vcf) by chromosome and other criteria (PR #98). - + - `bedtools/bedtools_bamtofastq`: Convert BAM alignments to FASTQ files (PR #101). + - `bedtools/bedtools_bedtobam`: Converts genomic feature records (bed/gff/vcf) to BAM format (PR #111). ## MINOR CHANGES @@ -34,6 +38,10 @@ * Update CI to reusable workflow in `viash-io/viash-actions` (PR #86). +* Update several components in order to avoid duplicate code when using `unset` on boolean arguments (PR #133). + +* Bump viash to `0.9.0-RC7` (PR #134) + ## DOCUMENTATION * Extend the contributing guidelines (PR #82): diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cee4249a..a32b680c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -320,6 +320,31 @@ Notes: * If your tool allows for multiple inputs using a separator other than `;` (which is the default Viash multiple separator), you can substitute these values with a command like: `par_disable_filters=$(echo $par_disable_filters | tr ';' ',')`. +* If you have a lot of boolean variables that you would like to unset when the value is `false`, you can avoid duplicate code by using the following syntax: + +```bash +unset_if_false=( + par_argument_1 + par_argument_2 + par_argument_3 + par_argument_4 +) + +for par in ${unset_if_false[@]}; do + test_val="${!par}" + [[ "$test_val" == "false" ]] && unset $par +done +``` + +this code is equivalent to + +```bash +[[ "$par_argument_1" == "false" ]] && unset par_argument_1 +[[ "$par_argument_2" == "false" ]] && unset par_argument_2 +[[ "$par_argument_3" == "false" ]] && unset par_argument_3 +[[ "$par_argument_4" == "false" ]] && unset par_argument_4 +``` + ### Step 12: Create test script diff --git a/_viash.yaml b/_viash.yaml index 9a240c24..ab4f3828 100644 --- a/_viash.yaml +++ b/_viash.yaml @@ -7,7 +7,7 @@ links: issue_tracker: https://github.com/viash-hub/biobox/issues repository: https://github.com/viash-hub/biobox -viash_version: 0.9.0-RC6 +viash_version: 0.9.0-RC7 config_mods: | .requirements.commands := ['ps'] diff --git a/src/agat/agat_convert_embl2gff/config.vsh.yaml b/src/agat/agat_convert_embl2gff/config.vsh.yaml new file mode 100644 index 00000000..99ceec46 --- /dev/null +++ b/src/agat/agat_convert_embl2gff/config.vsh.yaml @@ -0,0 +1,84 @@ +name: agat_convert_embl2gff +namespace: agat +description: | + The script takes an EMBL file as input, and will translate it in gff format. +keywords: [gene annotations, GFF conversion] +links: + homepage: https://github.com/NBISweden/AGAT + documentation: https://agat.readthedocs.io/en/latest/tools/agat_convert_embl2gff.html + issue_tracker: https://github.com/NBISweden/AGAT/issues + repository: https://github.com/NBISweden/AGAT +references: + doi: 10.5281/zenodo.3552717 +license: GPL-3.0 +authors: + - __merge__: /src/_authors/leila_paquay.yaml + roles: [ author, maintainer ] + +argument_groups: + - name: Inputs + arguments: + - name: --embl + description: Input EMBL file that will be read. + type: file + required: true + direction: input + example: input.embl + - name: Outputs + arguments: + - name: --output + alternatives: [-o, --out, --outfile, --gff] + description: Output GFF file. If no output file is specified, the output will be written to STDOUT. + type: file + direction: output + required: false + example: output.gff + - name: Arguments + arguments: + - name: --emblmygff3 + description: | + Means that the EMBL flat file comes from the EMBLmyGFF3 software. This is an EMBL format dedicated for submission and contains particularity to deal with. This parameter is needed to get a proper sequence id in the GFF3 from an embl made with EMBLmyGFF3. + type: boolean_true + - name: --primary_tag + alternatives: [--pt, -t] + description: | + List of "primary tag". Useful to discard or keep specific features. Multiple tags must be comma-separated. + type: string + multiple: true + required: false + example: [tag1, tag2] + - name: --discard + alternatives: [-d] + description: | + Means that primary tags provided by the option "primary_tag" will be discarded. + type: boolean_true + - name: --keep + alternatives: [-k] + description: | + Means that only primary tags provided by the option "primary_tag" will be kept. + type: boolean_true + - name: --config + alternatives: [-c] + description: | + Input agat config file. By default AGAT takes as input agat_config.yaml file from the working directory if any, otherwise it takes the original agat_config.yaml shipped with AGAT. To get the agat_config.yaml locally type: "agat config --expose". The --config option gives you the possibility to use your own AGAT config file (located elsewhere or named differently). + type: file + required: false + example: custom_agat_config.yaml +resources: + - type: bash_script + path: script.sh +test_resources: + - type: bash_script + path: test.sh + - type: file + path: test_data +engines: + - type: docker + image: quay.io/biocontainers/agat:1.4.0--pl5321hdfd78af_0 + setup: + - type: docker + run: | + agat --version | sed 's/AGAT\s\(.*\)/agat: "\1"/' > /var/software_versions.txt +runners: + - type: executable + - type: nextflow \ No newline at end of file diff --git a/src/agat/agat_convert_embl2gff/help.txt b/src/agat/agat_convert_embl2gff/help.txt new file mode 100644 index 00000000..5fce4939 --- /dev/null +++ b/src/agat/agat_convert_embl2gff/help.txt @@ -0,0 +1,78 @@ + ```sh +agat_convert_embl2gff.pl --help +``` + + ------------------------------------------------------------------------------ +| Another GFF Analysis Toolkit (AGAT) - Version: v1.4.0 | +| https://github.com/NBISweden/AGAT | +| National Bioinformatics Infrastructure Sweden (NBIS) - www.nbis.se | + ------------------------------------------------------------------------------ + + +Name: + agat_converter_embl2gff.pl + +Description: + The script takes an EMBL file as input, and will translate it in gff + format. + +Usage: + agat_converter_embl2gff.pl --embl infile.embl [ -o outfile ] + +Options: + --embl Input EMBL file that will be read + + --emblmygff3 + Bolean - Means that the EMBL flat file comes from the EMBLmyGFF3 + software. This is an EMBL format dedicated for submission and + contains particularity to deal with. This parameter is needed to + get a proper sequence id in the GFF3 from an embl made with + EMBLmyGFF3. + + --primary_tag, --pt, -t + List of "primary tag". Useful to discard or keep specific + features. Multiple tags must be coma-separated. + + -d Bolean - Means that primary tags provided by the option + "primary_tag" will be discarded. + + -k Bolean - Means that only primary tags provided by the option + "primary_tag" will be kept. + + -o, --output, --out, --outfile or --gff + Output GFF file. If no output file is specified, the output will + be written to STDOUT. + + -c or --config + String - Input agat config file. By default AGAT takes as input + agat_config.yaml file from the working directory if any, + otherwise it takes the orignal agat_config.yaml shipped with + AGAT. To get the agat_config.yaml locally type: "agat config + --expose". The --config option gives you the possibility to use + your own AGAT config file (located elsewhere or named + differently). + + -h or --help + Display this helpful text. + +Feedback: + Did you find a bug?: + Do not hesitate to report bugs to help us keep track of the bugs and + their resolution. Please use the GitHub issue tracking system available + at this address: + + https://github.com/NBISweden/AGAT/issues + + Ensure that the bug was not already reported by searching under Issues. + If you're unable to find an (open) issue addressing the problem, open a new one. + Try as much as possible to include in the issue when relevant: + - a clear description, + - as much relevant information as possible, + - the command used, + - a data sample, + - an explanation of the expected behaviour that is not occurring. + + Do you want to contribute?: + You are very welcome, visit this address for the Contributing + guidelines: + https://github.com/NBISweden/AGAT/blob/master/CONTRIBUTING.md diff --git a/src/agat/agat_convert_embl2gff/script.sh b/src/agat/agat_convert_embl2gff/script.sh new file mode 100644 index 00000000..63ab8df0 --- /dev/null +++ b/src/agat/agat_convert_embl2gff/script.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +## VIASH START +## VIASH END + + +# unset flags +[[ "$par_emblmygff3" == "false" ]] && unset par_emblmygff3 +[[ "$par_discard" == "false" ]] && unset par_discard +[[ "$par_keep" == "false" ]] && unset par_keep + +# replace ';' with ',' +par_primary_tag=$(echo $par_primary_tag | tr ';' ',') + +# run agat_convert_embl2gff +agat_convert_embl2gff.pl \ + --embl "$par_embl" \ + -o "$par_output" \ + ${par_emblmygff3:+--emblmygff3} \ + ${par_primary_tag:+--primary_tag "${par_primary_tag}"} \ + ${par_discard:+-d} \ + ${par_keep:+-k} \ + ${par_config:+--config "${par_config}"} diff --git a/src/agat/agat_convert_embl2gff/test.sh b/src/agat/agat_convert_embl2gff/test.sh new file mode 100644 index 00000000..81d24aaa --- /dev/null +++ b/src/agat/agat_convert_embl2gff/test.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +## VIASH START +## VIASH END + +test_dir="${meta_resources_dir}/test_data" +out_dir="${meta_resources_dir}/out_data" + +echo "> Run $meta_name with test data and --emblmygff3" +"$meta_executable" \ + --embl "$test_dir/agat_convert_embl2gff_1.embl" \ + --output "$out_dir/output.gff" \ + --emblmygff3 + +echo ">> Checking output" +[ ! -f "$out_dir/output.gff" ] && echo "Output file output.gff does not exist" && exit 1 + +echo ">> Check if output is empty" +[ ! -s "$out_dir/output.gff" ] && echo "Output file output.gff is empty" && exit 1 + +echo ">> Check if output matches expected output" +diff "$out_dir/output.gff" "$test_dir/agat_convert_embl2gff_1.gff" +if [ $? -ne 0 ]; then + echo "Output file output.gff does not match expected output" + exit 1 +fi + +echo "> Test successful" \ No newline at end of file diff --git a/src/agat/agat_convert_embl2gff/test_data/agat_convert_embl2gff_1.embl b/src/agat/agat_convert_embl2gff/test_data/agat_convert_embl2gff_1.embl new file mode 100644 index 00000000..aa4f50aa --- /dev/null +++ b/src/agat/agat_convert_embl2gff/test_data/agat_convert_embl2gff_1.embl @@ -0,0 +1,51 @@ +ID patatrac; SV 1; circular; genomic DNA; XXX; PRO; 317941 BP. +XX +AC XXX; +XX +AC * _ERS324955|SC|contig000001 +XX +PR Project:PRJEBNNNN; +XX +DE XXX +XX +RN [1] +RP 1-2149 +RA XXX; +RT ; +RL Submitted {(DD-MMM-YYYY)} to the INSDC. +XX +FH Key Location/Qualifiers +FH +FT source 1..588788 +FT /organism={"scientific organism name"} +FT /mol_type={"in vivo molecule type of sequence"} +XX +SQ Sequence 588788 BP; 101836 A; 193561 C; 192752 G; 100639 T; 0 other; + tgcgtactcg aagagacgcg cccagattat ataagggcgt cgtctcgagg ccgacggcgc 60 + gccggcgagt acgcgtgatc cacaacccga agcgaccgtc gggagaccga gggtcgtcga 120 + gggtggatac gttcctgcct tcgtgccggg aaacggccga agggaacgtg gcgacctgcg 180 +// +ID fdssf; SV 1; circular; genomic DNA; XXX; PRO; 317941 BP. +XX +AC XXX; +XX +AC * _ERS344554 +XX +PR Project:PRJEBNNNN; +XX +DE XXX +XX +RN [1] +RP 1-2149 +RA XXX; +RT ; +RL Submitted {(DD-MMM-YYYY)} to the INSDC. +XX +FH Key Location/Qualifiers +FH +FT source 1..588788 +FT /organism={"scientific organism name"} +FT /mol_type={"in vivo molecule type of sequence"} +XX +SQ Sequence 588788 BP; 101836 A; 193561 C; 192752 G; 100639 T; 0 other; + TTTTTTTTTT aagagacgcg cccagattat ataagggcgt cgtctcgagg ccgacggcgc 60 diff --git a/src/agat/agat_convert_embl2gff/test_data/agat_convert_embl2gff_1.gff b/src/agat/agat_convert_embl2gff/test_data/agat_convert_embl2gff_1.gff new file mode 100644 index 00000000..f6893022 --- /dev/null +++ b/src/agat/agat_convert_embl2gff/test_data/agat_convert_embl2gff_1.gff @@ -0,0 +1,10 @@ +##gff-version 3 +ERS324955|SC|contig000001 EMBL/GenBank/SwissProt source 1 588788 . + 1 mol_type={"in vivo molecule type of sequence"};organism={"scientific organism name"} +ERS344554 EMBL/GenBank/SwissProt source 1 588788 . + 1 mol_type={"in vivo molecule type of sequence"};organism={"scientific organism name"} +##FASTA +>ERS324955|SC|contig000001 XXX +TGCGTACTCGAAGAGACGCGCCCAGATTATATAAGGGCGTCGTCTCGAGGCCGACGGCGCGCCGGCGAGTACGCGTGATC +CACAACCCGAAGCGACCGTCGGGAGACCGAGGGTCGTCGAGGGTGGATACGTTCCTGCCTTCGTGCCGGGAAACGGCCGA +AGGGAACGTGGCGACCTGCG +>ERS344554 XXX +TTTTTTTTTTAAGAGACGCGCCCAGATTATATAAGGGCGTCGTCTCGAGGCCGACGGCGC diff --git a/src/agat/agat_convert_embl2gff/test_data/script.sh b/src/agat/agat_convert_embl2gff/test_data/script.sh new file mode 100755 index 00000000..7ddbce5b --- /dev/null +++ b/src/agat/agat_convert_embl2gff/test_data/script.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +# clone repo +if [ ! -d /tmp/agat_source ]; then + git clone --depth 1 --single-branch --branch master https://github.com/NBISweden/AGAT /tmp/agat_source +fi + +# copy test data +cp -r /tmp/agat_source/t/scripts_output/in/agat_convert_embl2gff_1.embl src/agat/agat_convert_embl2gff/test_data/agat_convert_embl2gff_1.embl +cp -r /tmp/agat_source/t/scripts_output/out/agat_convert_embl2gff_1.gff src/agat/agat_convert_embl2gff/test_data/agat_convert_embl2gff_1.gff \ No newline at end of file diff --git a/src/agat/agat_convert_sp_gff2tsv/config.vsh.yaml b/src/agat/agat_convert_sp_gff2tsv/config.vsh.yaml new file mode 100644 index 00000000..f1c78590 --- /dev/null +++ b/src/agat/agat_convert_sp_gff2tsv/config.vsh.yaml @@ -0,0 +1,70 @@ +name: agat_convert_sp_gff2tsv +namespace: agat +description: | + The script aims to convert gtf/gff file into tabulated file. Attribute's + tags from the 9th column become column titles. +keywords: [gene annotations, GFF conversion] +links: + homepage: https://github.com/NBISweden/AGAT + documentation: https://agat.readthedocs.io/en/latest/tools/agat_convert_sp_gff2tsv.html + issue_tracker: https://github.com/NBISweden/AGAT/issues + repository: https://github.com/NBISweden/AGAT +references: + doi: 10.5281/zenodo.3552717 +license: GPL-3.0 +authors: + - __merge__: /src/_authors/leila_paquay.yaml + roles: [ author, maintainer ] + +argument_groups: + - name: Inputs + arguments: + - name: --gff + alternatives: [-f] + description: Input GTF/GFF file. + type: file + required: true + direction: input + example: input.gff + - name: Outputs + arguments: + - name: --output + alternatives: [-o, --out, --outfile] + description: Output GFF file. If no output file is specified, the output will be written to STDOUT. + type: file + direction: output + required: true + example: output.gff + - name: Arguments + arguments: + - name: --config + alternatives: [-c] + description: | + String - Input agat config file. By default AGAT takes as input + agat_config.yaml file from the working directory if any, + otherwise it takes the orignal agat_config.yaml shipped with + AGAT. To get the agat_config.yaml locally type: "agat config + --expose". The --config option gives you the possibility to use + your own AGAT config file (located elsewhere or named + differently). + type: file + required: false + example: custom_agat_config.yaml +resources: + - type: bash_script + path: script.sh +test_resources: + - type: bash_script + path: test.sh + - type: file + path: test_data +engines: + - type: docker + image: quay.io/biocontainers/agat:1.4.0--pl5321hdfd78af_0 + setup: + - type: docker + run: | + agat --version | sed 's/AGAT\s\(.*\)/agat: "\1"/' > /var/software_versions.txt +runners: + - type: executable + - type: nextflow \ No newline at end of file diff --git a/src/agat/agat_convert_sp_gff2tsv/help.txt b/src/agat/agat_convert_sp_gff2tsv/help.txt new file mode 100644 index 00000000..afbf85f8 --- /dev/null +++ b/src/agat/agat_convert_sp_gff2tsv/help.txt @@ -0,0 +1,63 @@ +```sh +agat_convert_sp_gff2tsv.pl --help +``` + + ------------------------------------------------------------------------------ +| Another GFF Analysis Toolkit (AGAT) - Version: v1.4.0 | +| https://github.com/NBISweden/AGAT | +| National Bioinformatics Infrastructure Sweden (NBIS) - www.nbis.se | + ------------------------------------------------------------------------------ + + +Name: + agat_convert_sp_gff2tsv.pl + +Description: + The script aims to convert gtf/gff file into tabulated file. Attribute's + tags from the 9th column become column titles. + +Usage: + agat_convert_sp_gff2tsv.pl -gff file.gff [ -o outfile ] + agat_convert_sp_gff2tsv.pl --help + +Options: + --gff or -f + Input GTF/GFF file. + + -o , --output , --out or --outfile + Output GFF file. If no output file is specified, the output will + be written to STDOUT. + + -c or --config + String - Input agat config file. By default AGAT takes as input + agat_config.yaml file from the working directory if any, + otherwise it takes the orignal agat_config.yaml shipped with + AGAT. To get the agat_config.yaml locally type: "agat config + --expose". The --config option gives you the possibility to use + your own AGAT config file (located elsewhere or named + differently). + + -h or --help + Display this helpful text. + +Feedback: + Did you find a bug?: + Do not hesitate to report bugs to help us keep track of the bugs and + their resolution. Please use the GitHub issue tracking system available + at this address: + + https://github.com/NBISweden/AGAT/issues + + Ensure that the bug was not already reported by searching under Issues. + If you're unable to find an (open) issue addressing the problem, open a new one. + Try as much as possible to include in the issue when relevant: + - a clear description, + - as much relevant information as possible, + - the command used, + - a data sample, + - an explanation of the expected behaviour that is not occurring. + + Do you want to contribute?: + You are very welcome, visit this address for the Contributing + guidelines: + https://github.com/NBISweden/AGAT/blob/master/CONTRIBUTING.md \ No newline at end of file diff --git a/src/agat/agat_convert_sp_gff2tsv/script.sh b/src/agat/agat_convert_sp_gff2tsv/script.sh new file mode 100644 index 00000000..6393303c --- /dev/null +++ b/src/agat/agat_convert_sp_gff2tsv/script.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +## VIASH START +## VIASH END + +agat_convert_sp_gff2tsv.pl \ + -f "$par_gff" \ + -o "$par_output" \ + ${par_config:+--config "${par_config}"} diff --git a/src/agat/agat_convert_sp_gff2tsv/test.sh b/src/agat/agat_convert_sp_gff2tsv/test.sh new file mode 100644 index 00000000..fabe46b9 --- /dev/null +++ b/src/agat/agat_convert_sp_gff2tsv/test.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +## VIASH START +## VIASH END + +test_dir="${meta_resources_dir}/test_data" +out_dir="${meta_resources_dir}/out_data" + +echo "> Run $meta_name with test data" +"$meta_executable" \ + --gff "$test_dir/1.gff" \ + --output "$out_dir/output.gff" + +echo ">> Checking output" +[ ! -f "$out_dir/output.gff" ] && echo "Output file output.gff does not exist" && exit 1 + +echo ">> Check if output is empty" +[ ! -s "$out_dir/output.gff" ] && echo "Output file output.gff is empty" && exit 1 + +echo ">> Check if output matches expected output" +diff "$out_dir/output.gff" "$test_dir/agat_convert_sp_gff2tsv_1.tsv" +if [ $? -ne 0 ]; then + echo "Output file output.gff does not match expected output" + exit 1 +fi + +echo "> Test successful" \ No newline at end of file diff --git a/src/agat/agat_convert_sp_gff2tsv/test_data/1.gff b/src/agat/agat_convert_sp_gff2tsv/test_data/1.gff new file mode 100644 index 00000000..40a06c78 --- /dev/null +++ b/src/agat/agat_convert_sp_gff2tsv/test_data/1.gff @@ -0,0 +1,942 @@ +##gff-version 3 +##sequence-region 1 1 43270923 +#!genome-build RAP-DB IRGSP-1.0 +#!genome-version IRGSP-1.0 +#!genome-date 2015-10 +#!genome-build-accession GCA_001433935.1 +1 RAP-DB chromosome 1 43270923 . . . ID=chromosome:1;Alias=Chr1,AP014957.1,NC_029256.1 +### +1 irgsp repeat_region 2000 2100 . + . ID=fakeRepeat1 +### +1 irgsp gene 2983 10815 . + . ID=gene:Os01g0100100;biotype=protein_coding;description=RabGAP/TBC domain containing protein. (Os01t0100100-01);gene_id=Os01g0100100;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 2983 10815 . + . ID=transcript:Os01t0100100-01;Parent=gene:Os01g0100100;biotype=protein_coding;transcript_id=Os01t0100100-01 +1 irgsp exon 2983 3268 . + . Parent=transcript:Os01t0100100-01;Name=Os01t0100100-01.exon1;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0100100-01.exon1;rank=1 +1 irgsp five_prime_UTR 2983 3268 . + . Parent=transcript:Os01t0100100-01 +1 irgsp five_prime_UTR 3354 3448 . + . Parent=transcript:Os01t0100100-01 +1 irgsp exon 3354 3616 . + . Parent=transcript:Os01t0100100-01;Name=Os01t0100100-01.exon2;constitutive=1;ensembl_end_phase=0;ensembl_phase=-1;exon_id=Os01t0100100-01.exon2;rank=2 +1 irgsp CDS 3449 3616 . + 0 ID=CDS:Os01t0100100-01;Parent=transcript:Os01t0100100-01;protein_id=Os01t0100100-01 +1 irgsp exon 4357 4455 . + . Parent=transcript:Os01t0100100-01;Name=Os01t0100100-01.exon3;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0100100-01.exon3;rank=3 +1 irgsp CDS 4357 4455 . + 0 ID=CDS:Os01t0100100-01;Parent=transcript:Os01t0100100-01;protein_id=Os01t0100100-01 +1 irgsp exon 5457 5560 . + . Parent=transcript:Os01t0100100-01;Name=Os01t0100100-01.exon4;constitutive=1;ensembl_end_phase=2;ensembl_phase=0;exon_id=Os01t0100100-01.exon4;rank=4 +1 irgsp CDS 5457 5560 . + 0 ID=CDS:Os01t0100100-01;Parent=transcript:Os01t0100100-01;protein_id=Os01t0100100-01 +1 irgsp exon 7136 7944 . + . Parent=transcript:Os01t0100100-01;Name=Os01t0100100-01.exon5;constitutive=1;ensembl_end_phase=1;ensembl_phase=2;exon_id=Os01t0100100-01.exon5;rank=5 +1 irgsp CDS 7136 7944 . + 1 ID=CDS:Os01t0100100-01;Parent=transcript:Os01t0100100-01;protein_id=Os01t0100100-01 +1 irgsp exon 8028 8150 . + . Parent=transcript:Os01t0100100-01;Name=Os01t0100100-01.exon6;constitutive=1;ensembl_end_phase=1;ensembl_phase=1;exon_id=Os01t0100100-01.exon6;rank=6 +1 irgsp CDS 8028 8150 . + 2 ID=CDS:Os01t0100100-01;Parent=transcript:Os01t0100100-01;protein_id=Os01t0100100-01 +1 irgsp exon 8232 8320 . + . Parent=transcript:Os01t0100100-01;Name=Os01t0100100-01.exon7;constitutive=1;ensembl_end_phase=0;ensembl_phase=1;exon_id=Os01t0100100-01.exon7;rank=7 +1 irgsp CDS 8232 8320 . + 2 ID=CDS:Os01t0100100-01;Parent=transcript:Os01t0100100-01;protein_id=Os01t0100100-01 +1 irgsp exon 8408 8608 . + . Parent=transcript:Os01t0100100-01;Name=Os01t0100100-01.exon8;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0100100-01.exon8;rank=8 +1 irgsp CDS 8408 8608 . + 0 ID=CDS:Os01t0100100-01;Parent=transcript:Os01t0100100-01;protein_id=Os01t0100100-01 +1 irgsp exon 9210 9615 . + . Parent=transcript:Os01t0100100-01;Name=Os01t0100100-01.exon9;constitutive=1;ensembl_end_phase=1;ensembl_phase=0;exon_id=Os01t0100100-01.exon9;rank=9 +1 irgsp CDS 9210 9615 . + 0 ID=CDS:Os01t0100100-01;Parent=transcript:Os01t0100100-01;protein_id=Os01t0100100-01 +1 irgsp exon 10102 10187 . + . Parent=transcript:Os01t0100100-01;Name=Os01t0100100-01.exon10;constitutive=1;ensembl_end_phase=0;ensembl_phase=1;exon_id=Os01t0100100-01.exon10;rank=10 +1 irgsp CDS 10102 10187 . + 2 ID=CDS:Os01t0100100-01;Parent=transcript:Os01t0100100-01;protein_id=Os01t0100100-01 +1 irgsp CDS 10274 10297 . + 0 ID=CDS:Os01t0100100-01;Parent=transcript:Os01t0100100-01;protein_id=Os01t0100100-01 +1 irgsp exon 10274 10430 . + . Parent=transcript:Os01t0100100-01;Name=Os01t0100100-01.exon11;constitutive=1;ensembl_end_phase=-1;ensembl_phase=0;exon_id=Os01t0100100-01.exon11;rank=11 +1 irgsp three_prime_UTR 10298 10430 . + . Parent=transcript:Os01t0100100-01 +1 irgsp exon 10504 10815 . + . Parent=transcript:Os01t0100100-01;Name=Os01t0100100-01.exon12;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0100100-01.exon12;rank=12 +1 irgsp three_prime_UTR 10504 10815 . + . Parent=transcript:Os01t0100100-01 +### +1 irgsp gene 11218 12435 . + . ID=gene:Os01g0100200;biotype=protein_coding;description=Conserved hypothetical protein. (Os01t0100200-01);gene_id=Os01g0100200;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 11218 12435 . + . ID=transcript:Os01t0100200-01;Parent=gene:Os01g0100200;biotype=protein_coding;transcript_id=Os01t0100200-01 +1 irgsp five_prime_UTR 11218 11797 . + . Parent=transcript:Os01t0100200-01 +1 irgsp exon 11218 12060 . + . Parent=transcript:Os01t0100200-01;Name=Os01t0100200-01.exon1;constitutive=1;ensembl_end_phase=2;ensembl_phase=-1;exon_id=Os01t0100200-01.exon1;rank=1 +1 irgsp CDS 11798 12060 . + 0 ID=CDS:Os01t0100200-01;Parent=transcript:Os01t0100200-01;protein_id=Os01t0100200-01 +1 irgsp CDS 12152 12317 . + 1 ID=CDS:Os01t0100200-01;Parent=transcript:Os01t0100200-01;protein_id=Os01t0100200-01 +1 irgsp exon 12152 12435 . + . Parent=transcript:Os01t0100200-01;Name=Os01t0100200-01.exon2;constitutive=1;ensembl_end_phase=-1;ensembl_phase=2;exon_id=Os01t0100200-01.exon2;rank=2 +1 irgsp three_prime_UTR 12318 12435 . + . Parent=transcript:Os01t0100200-01 +### +1 irgsp gene 11372 12284 . - . ID=gene:Os01g0100300;biotype=protein_coding;description=Cytochrome P450 domain containing protein. (Os01t0100300-00);gene_id=Os01g0100300;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 11372 12284 . - . ID=transcript:Os01t0100300-00;Parent=gene:Os01g0100300;biotype=protein_coding;transcript_id=Os01t0100300-00 +1 irgsp exon 11372 12042 . - . Parent=transcript:Os01t0100300-00;Name=Os01t0100300-00.exon2;constitutive=1;ensembl_end_phase=0;ensembl_phase=1;exon_id=Os01t0100300-00.exon2;rank=2 +1 irgsp CDS 11372 12042 . - 2 ID=CDS:Os01t0100300-00;Parent=transcript:Os01t0100300-00;protein_id=Os01t0100300-00 +1 irgsp exon 12146 12284 . - . Parent=transcript:Os01t0100300-00;Name=Os01t0100300-00.exon1;constitutive=1;ensembl_end_phase=1;ensembl_phase=0;exon_id=Os01t0100300-00.exon1;rank=1 +1 irgsp CDS 12146 12284 . - 0 ID=CDS:Os01t0100300-00;Parent=transcript:Os01t0100300-00;protein_id=Os01t0100300-00 +### +1 irgsp gene 12721 15685 . + . ID=gene:Os01g0100400;biotype=protein_coding;description=Similar to Pectinesterase-like protein. (Os01t0100400-01);gene_id=Os01g0100400;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 12721 15685 . + . ID=transcript:Os01t0100400-01;Parent=gene:Os01g0100400;biotype=protein_coding;transcript_id=Os01t0100400-01 +1 irgsp five_prime_UTR 12721 12773 . + . Parent=transcript:Os01t0100400-01 +1 irgsp exon 12721 13813 . + . Parent=transcript:Os01t0100400-01;Name=Os01t0100400-01.exon1;constitutive=1;ensembl_end_phase=2;ensembl_phase=-1;exon_id=Os01t0100400-01.exon1;rank=1 +1 irgsp CDS 12774 13813 . + 0 ID=CDS:Os01t0100400-01;Parent=transcript:Os01t0100400-01;protein_id=Os01t0100400-01 +1 irgsp exon 13906 14271 . + . Parent=transcript:Os01t0100400-01;Name=Os01t0100400-01.exon2;constitutive=1;ensembl_end_phase=2;ensembl_phase=2;exon_id=Os01t0100400-01.exon2;rank=2 +1 irgsp CDS 13906 14271 . + 1 ID=CDS:Os01t0100400-01;Parent=transcript:Os01t0100400-01;protein_id=Os01t0100400-01 +1 irgsp exon 14359 14437 . + . Parent=transcript:Os01t0100400-01;Name=Os01t0100400-01.exon3;constitutive=1;ensembl_end_phase=0;ensembl_phase=2;exon_id=Os01t0100400-01.exon3;rank=3 +1 irgsp CDS 14359 14437 . + 1 ID=CDS:Os01t0100400-01;Parent=transcript:Os01t0100400-01;protein_id=Os01t0100400-01 +1 irgsp exon 14969 15171 . + . Parent=transcript:Os01t0100400-01;Name=Os01t0100400-01.exon4;constitutive=1;ensembl_end_phase=2;ensembl_phase=0;exon_id=Os01t0100400-01.exon4;rank=4 +1 irgsp CDS 14969 15171 . + 0 ID=CDS:Os01t0100400-01;Parent=transcript:Os01t0100400-01;protein_id=Os01t0100400-01 +1 irgsp CDS 15266 15359 . + 1 ID=CDS:Os01t0100400-01;Parent=transcript:Os01t0100400-01;protein_id=Os01t0100400-01 +1 irgsp exon 15266 15685 . + . Parent=transcript:Os01t0100400-01;Name=Os01t0100400-01.exon5;constitutive=1;ensembl_end_phase=-1;ensembl_phase=2;exon_id=Os01t0100400-01.exon5;rank=5 +1 irgsp three_prime_UTR 15360 15685 . + . Parent=transcript:Os01t0100400-01 +### +1 irgsp gene 12808 13978 . - . ID=gene:Os01g0100466;biotype=protein_coding;description=Hypothetical protein. (Os01t0100466-00);gene_id=Os01g0100466;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 12808 13978 . - . ID=transcript:Os01t0100466-00;Parent=gene:Os01g0100466;biotype=protein_coding;transcript_id=Os01t0100466-00 +1 irgsp three_prime_UTR 12808 12868 . - . Parent=transcript:Os01t0100466-00 +1 irgsp exon 12808 13782 . - . Parent=transcript:Os01t0100466-00;Name=Os01t0100466-00.exon2;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0100466-00.exon2;rank=2 +1 irgsp CDS 12869 13102 . - 0 ID=CDS:Os01t0100466-00;Parent=transcript:Os01t0100466-00;protein_id=Os01t0100466-00 +1 irgsp five_prime_UTR 13103 13782 . - . Parent=transcript:Os01t0100466-00 +1 irgsp exon 13880 13978 . - . Parent=transcript:Os01t0100466-00;Name=Os01t0100466-00.exon1;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0100466-00.exon1;rank=1 +1 irgsp five_prime_UTR 13880 13978 . - . Parent=transcript:Os01t0100466-00 +### +1 irgsp gene 16399 20144 . + . ID=gene:Os01g0100500;biotype=protein_coding;description=Immunoglobulin-like domain containing protein. (Os01t0100500-01);gene_id=Os01g0100500;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 16399 20144 . + . ID=transcript:Os01t0100500-01;Parent=gene:Os01g0100500;biotype=protein_coding;transcript_id=Os01t0100500-01 +1 irgsp five_prime_UTR 16399 16598 . + . Parent=transcript:Os01t0100500-01 +1 irgsp exon 16399 16976 . + . Parent=transcript:Os01t0100500-01;Name=Os01t0100500-01.exon1;constitutive=1;ensembl_end_phase=0;ensembl_phase=-1;exon_id=Os01t0100500-01.exon1;rank=1 +1 irgsp CDS 16599 16976 . + 0 ID=CDS:Os01t0100500-01;Parent=transcript:Os01t0100500-01;protein_id=Os01t0100500-01 +1 irgsp exon 17383 17474 . + . Parent=transcript:Os01t0100500-01;Name=Os01t0100500-01.exon2;constitutive=1;ensembl_end_phase=2;ensembl_phase=0;exon_id=Os01t0100500-01.exon2;rank=2 +1 irgsp CDS 17383 17474 . + 0 ID=CDS:Os01t0100500-01;Parent=transcript:Os01t0100500-01;protein_id=Os01t0100500-01 +1 irgsp exon 17558 18258 . + . Parent=transcript:Os01t0100500-01;Name=Os01t0100500-01.exon3;constitutive=1;ensembl_end_phase=1;ensembl_phase=2;exon_id=Os01t0100500-01.exon3;rank=3 +1 irgsp CDS 17558 18258 . + 1 ID=CDS:Os01t0100500-01;Parent=transcript:Os01t0100500-01;protein_id=Os01t0100500-01 +1 irgsp exon 18501 18571 . + . Parent=transcript:Os01t0100500-01;Name=Os01t0100500-01.exon4;constitutive=1;ensembl_end_phase=0;ensembl_phase=1;exon_id=Os01t0100500-01.exon4;rank=4 +1 irgsp CDS 18501 18571 . + 2 ID=CDS:Os01t0100500-01;Parent=transcript:Os01t0100500-01;protein_id=Os01t0100500-01 +1 irgsp exon 18968 19057 . + . Parent=transcript:Os01t0100500-01;Name=Os01t0100500-01.exon5;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0100500-01.exon5;rank=5 +1 irgsp CDS 18968 19057 . + 0 ID=CDS:Os01t0100500-01;Parent=transcript:Os01t0100500-01;protein_id=Os01t0100500-01 +1 irgsp exon 19142 19321 . + . Parent=transcript:Os01t0100500-01;Name=Os01t0100500-01.exon6;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0100500-01.exon6;rank=6 +1 irgsp CDS 19142 19321 . + 0 ID=CDS:Os01t0100500-01;Parent=transcript:Os01t0100500-01;protein_id=Os01t0100500-01 +1 irgsp CDS 19531 19593 . + 0 ID=CDS:Os01t0100500-01;Parent=transcript:Os01t0100500-01;protein_id=Os01t0100500-01 +1 irgsp exon 19531 19629 . + . Parent=transcript:Os01t0100500-01;Name=Os01t0100500-01.exon7;constitutive=1;ensembl_end_phase=-1;ensembl_phase=0;exon_id=Os01t0100500-01.exon7;rank=7 +1 irgsp three_prime_UTR 19594 19629 . + . Parent=transcript:Os01t0100500-01 +1 irgsp exon 19734 20144 . + . Parent=transcript:Os01t0100500-01;Name=Os01t0100500-01.exon8;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0100500-01.exon8;rank=8 +1 irgsp three_prime_UTR 19734 20144 . + . Parent=transcript:Os01t0100500-01 +### +1 irgsp gene 22841 26892 . + . ID=gene:Os01g0100600;biotype=protein_coding;description=Single-stranded nucleic acid binding R3H domain containing protein. (Os01t0100600-01);gene_id=Os01g0100600;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 22841 26892 . + . ID=transcript:Os01t0100600-01;Parent=gene:Os01g0100600;biotype=protein_coding;transcript_id=Os01t0100600-01 +1 irgsp five_prime_UTR 22841 23231 . + . Parent=transcript:Os01t0100600-01 +1 irgsp exon 22841 23281 . + . Parent=transcript:Os01t0100600-01;Name=Os01t0100600-01.exon1;constitutive=1;ensembl_end_phase=2;ensembl_phase=-1;exon_id=Os01t0100600-01.exon1;rank=1 +1 irgsp CDS 23232 23281 . + 0 ID=CDS:Os01t0100600-01;Parent=transcript:Os01t0100600-01;protein_id=Os01t0100600-01 +1 irgsp exon 23572 23847 . + . Parent=transcript:Os01t0100600-01;Name=Os01t0100600-01.exon2;constitutive=1;ensembl_end_phase=2;ensembl_phase=2;exon_id=Os01t0100600-01.exon2;rank=2 +1 irgsp CDS 23572 23847 . + 1 ID=CDS:Os01t0100600-01;Parent=transcript:Os01t0100600-01;protein_id=Os01t0100600-01 +1 irgsp exon 23962 24033 . + . Parent=transcript:Os01t0100600-01;Name=Os01t0100600-01.exon3;constitutive=1;ensembl_end_phase=2;ensembl_phase=2;exon_id=Os01t0100600-01.exon3;rank=3 +1 irgsp CDS 23962 24033 . + 1 ID=CDS:Os01t0100600-01;Parent=transcript:Os01t0100600-01;protein_id=Os01t0100600-01 +1 irgsp exon 24492 24577 . + . Parent=transcript:Os01t0100600-01;Name=Os01t0100600-01.exon4;constitutive=1;ensembl_end_phase=1;ensembl_phase=2;exon_id=Os01t0100600-01.exon4;rank=4 +1 irgsp CDS 24492 24577 . + 1 ID=CDS:Os01t0100600-01;Parent=transcript:Os01t0100600-01;protein_id=Os01t0100600-01 +1 irgsp exon 25445 25519 . + . Parent=transcript:Os01t0100600-01;Name=Os01t0100600-01.exon5;constitutive=1;ensembl_end_phase=1;ensembl_phase=1;exon_id=Os01t0100600-01.exon5;rank=5 +1 irgsp CDS 25445 25519 . + 2 ID=CDS:Os01t0100600-01;Parent=transcript:Os01t0100600-01;protein_id=Os01t0100600-01 +1 irgsp CDS 25883 26391 . + 2 ID=CDS:Os01t0100600-01;Parent=transcript:Os01t0100600-01;protein_id=Os01t0100600-01 +1 irgsp exon 25883 26892 . + . Parent=transcript:Os01t0100600-01;Name=Os01t0100600-01.exon6;constitutive=1;ensembl_end_phase=-1;ensembl_phase=1;exon_id=Os01t0100600-01.exon6;rank=6 +1 irgsp three_prime_UTR 26392 26892 . + . Parent=transcript:Os01t0100600-01 +### +1 irgsp gene 25861 26424 . - . ID=gene:Os01g0100650;biotype=protein_coding;description=Hypothetical gene. (Os01t0100650-00);gene_id=Os01g0100650;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 25861 26424 . - . ID=transcript:Os01t0100650-00;Parent=gene:Os01g0100650;biotype=protein_coding;transcript_id=Os01t0100650-00 +1 irgsp three_prime_UTR 25861 26039 . - . Parent=transcript:Os01t0100650-00 +1 irgsp exon 25861 26424 . - . Parent=transcript:Os01t0100650-00;Name=Os01t0100650-00.exon1;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0100650-00.exon1;rank=1 +1 irgsp CDS 26040 26423 . - 0 ID=CDS:Os01t0100650-00;Parent=transcript:Os01t0100650-00;protein_id=Os01t0100650-00 +1 irgsp five_prime_UTR 26424 26424 . - . Parent=transcript:Os01t0100650-00 +### +1 irgsp gene 27143 28644 . + . ID=gene:Os01g0100700;biotype=protein_coding;description=Similar to 40S ribosomal protein S5-1. (Os01t0100700-01);gene_id=Os01g0100700;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 27143 28644 . + . ID=transcript:Os01t0100700-01;Parent=gene:Os01g0100700;biotype=protein_coding;transcript_id=Os01t0100700-01 +1 irgsp five_prime_UTR 27143 27220 . + . Parent=transcript:Os01t0100700-01 +1 irgsp exon 27143 27292 . + . Parent=transcript:Os01t0100700-01;Name=Os01t0100700-01.exon1;constitutive=1;ensembl_end_phase=0;ensembl_phase=-1;exon_id=Os01t0100700-01.exon1;rank=1 +1 irgsp CDS 27221 27292 . + 0 ID=CDS:Os01t0100700-01;Parent=transcript:Os01t0100700-01;protein_id=Os01t0100700-01 +1 irgsp exon 27370 27641 . + . Parent=transcript:Os01t0100700-01;Name=Os01t0100700-01.exon2;constitutive=1;ensembl_end_phase=2;ensembl_phase=0;exon_id=Os01t0100700-01.exon2;rank=2 +1 irgsp CDS 27370 27641 . + 0 ID=CDS:Os01t0100700-01;Parent=transcript:Os01t0100700-01;protein_id=Os01t0100700-01 +1 irgsp exon 28090 28293 . + . Parent=transcript:Os01t0100700-01;Name=Os01t0100700-01.exon3;constitutive=1;ensembl_end_phase=2;ensembl_phase=2;exon_id=Os01t0100700-01.exon3;rank=3 +1 irgsp CDS 28090 28293 . + 1 ID=CDS:Os01t0100700-01;Parent=transcript:Os01t0100700-01;protein_id=Os01t0100700-01 +1 irgsp CDS 28365 28419 . + 1 ID=CDS:Os01t0100700-01;Parent=transcript:Os01t0100700-01;protein_id=Os01t0100700-01 +1 irgsp exon 28365 28644 . + . Parent=transcript:Os01t0100700-01;Name=Os01t0100700-01.exon4;constitutive=1;ensembl_end_phase=-1;ensembl_phase=2;exon_id=Os01t0100700-01.exon4;rank=4 +1 irgsp three_prime_UTR 28420 28644 . + . Parent=transcript:Os01t0100700-01 +### +1 irgsp gene 29818 34453 . + . ID=gene:Os01g0100800;biotype=protein_coding;description=Protein of unknown function DUF1664 family protein. (Os01t0100800-01);gene_id=Os01g0100800;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 29818 34453 . + . ID=transcript:Os01t0100800-01;Parent=gene:Os01g0100800;biotype=protein_coding;transcript_id=Os01t0100800-01 +1 irgsp five_prime_UTR 29818 29939 . + . Parent=transcript:Os01t0100800-01 +1 irgsp exon 29818 29976 . + . Parent=transcript:Os01t0100800-01;Name=Os01t0100800-01.exon1;constitutive=1;ensembl_end_phase=1;ensembl_phase=-1;exon_id=Os01t0100800-01.exon1;rank=1 +1 irgsp CDS 29940 29976 . + 0 ID=CDS:Os01t0100800-01;Parent=transcript:Os01t0100800-01;protein_id=Os01t0100800-01 +1 irgsp exon 30146 30228 . + . Parent=transcript:Os01t0100800-01;Name=Os01t0100800-01.exon2;constitutive=1;ensembl_end_phase=0;ensembl_phase=1;exon_id=Os01t0100800-01.exon2;rank=2 +1 irgsp CDS 30146 30228 . + 2 ID=CDS:Os01t0100800-01;Parent=transcript:Os01t0100800-01;protein_id=Os01t0100800-01 +1 irgsp exon 30735 30806 . + . Parent=transcript:Os01t0100800-01;Name=Os01t0100800-01.exon3;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0100800-01.exon3;rank=3 +1 irgsp CDS 30735 30806 . + 0 ID=CDS:Os01t0100800-01;Parent=transcript:Os01t0100800-01;protein_id=Os01t0100800-01 +1 irgsp exon 30885 30963 . + . Parent=transcript:Os01t0100800-01;Name=Os01t0100800-01.exon4;constitutive=1;ensembl_end_phase=1;ensembl_phase=0;exon_id=Os01t0100800-01.exon4;rank=4 +1 irgsp CDS 30885 30963 . + 0 ID=CDS:Os01t0100800-01;Parent=transcript:Os01t0100800-01;protein_id=Os01t0100800-01 +1 irgsp exon 31258 31325 . + . Parent=transcript:Os01t0100800-01;Name=Os01t0100800-01.exon5;constitutive=1;ensembl_end_phase=0;ensembl_phase=1;exon_id=Os01t0100800-01.exon5;rank=5 +1 irgsp CDS 31258 31325 . + 2 ID=CDS:Os01t0100800-01;Parent=transcript:Os01t0100800-01;protein_id=Os01t0100800-01 +1 irgsp exon 31505 31606 . + . Parent=transcript:Os01t0100800-01;Name=Os01t0100800-01.exon6;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0100800-01.exon6;rank=6 +1 irgsp CDS 31505 31606 . + 0 ID=CDS:Os01t0100800-01;Parent=transcript:Os01t0100800-01;protein_id=Os01t0100800-01 +1 irgsp exon 32377 32466 . + . Parent=transcript:Os01t0100800-01;Name=Os01t0100800-01.exon7;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0100800-01.exon7;rank=7 +1 irgsp CDS 32377 32466 . + 0 ID=CDS:Os01t0100800-01;Parent=transcript:Os01t0100800-01;protein_id=Os01t0100800-01 +1 irgsp exon 32542 32616 . + . Parent=transcript:Os01t0100800-01;Name=Os01t0100800-01.exon8;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0100800-01.exon8;rank=8 +1 irgsp CDS 32542 32616 . + 0 ID=CDS:Os01t0100800-01;Parent=transcript:Os01t0100800-01;protein_id=Os01t0100800-01 +1 irgsp exon 32712 32744 . + . Parent=transcript:Os01t0100800-01;Name=Os01t0100800-01.exon9;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0100800-01.exon9;rank=9 +1 irgsp CDS 32712 32744 . + 0 ID=CDS:Os01t0100800-01;Parent=transcript:Os01t0100800-01;protein_id=Os01t0100800-01 +1 irgsp exon 32828 32905 . + . Parent=transcript:Os01t0100800-01;Name=Os01t0100800-01.exon10;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0100800-01.exon10;rank=10 +1 irgsp CDS 32828 32905 . + 0 ID=CDS:Os01t0100800-01;Parent=transcript:Os01t0100800-01;protein_id=Os01t0100800-01 +1 irgsp exon 33274 33330 . + . Parent=transcript:Os01t0100800-01;Name=Os01t0100800-01.exon11;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0100800-01.exon11;rank=11 +1 irgsp CDS 33274 33330 . + 0 ID=CDS:Os01t0100800-01;Parent=transcript:Os01t0100800-01;protein_id=Os01t0100800-01 +1 irgsp exon 33400 33471 . + . Parent=transcript:Os01t0100800-01;Name=Os01t0100800-01.exon12;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0100800-01.exon12;rank=12 +1 irgsp CDS 33400 33471 . + 0 ID=CDS:Os01t0100800-01;Parent=transcript:Os01t0100800-01;protein_id=Os01t0100800-01 +1 irgsp exon 33543 33617 . + . Parent=transcript:Os01t0100800-01;Name=Os01t0100800-01.exon13;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0100800-01.exon13;rank=13 +1 irgsp CDS 33543 33617 . + 0 ID=CDS:Os01t0100800-01;Parent=transcript:Os01t0100800-01;protein_id=Os01t0100800-01 +1 irgsp CDS 33975 34124 . + 0 ID=CDS:Os01t0100800-01;Parent=transcript:Os01t0100800-01;protein_id=Os01t0100800-01 +1 irgsp exon 33975 34453 . + . Parent=transcript:Os01t0100800-01;Name=Os01t0100800-01.exon14;constitutive=1;ensembl_end_phase=-1;ensembl_phase=0;exon_id=Os01t0100800-01.exon14;rank=14 +1 irgsp three_prime_UTR 34125 34453 . + . Parent=transcript:Os01t0100800-01 +### +1 irgsp gene 35623 41136 . + . ID=gene:Os01g0100900;Name=SPHINGOSINE-1-PHOSPHATE LYASE 1%2C Sphingosine-1-Phoshpate Lyase 1;biotype=protein_coding;description=Sphingosine-1-phosphate lyase%2C Disease resistance response (Os01t0100900-01);gene_id=Os01g0100900;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 35623 41136 . + . ID=transcript:Os01t0100900-01;Parent=gene:Os01g0100900;biotype=protein_coding;transcript_id=Os01t0100900-01 +1 irgsp five_prime_UTR 35623 35742 . + . Parent=transcript:Os01t0100900-01 +1 irgsp exon 35623 35939 . + . Parent=transcript:Os01t0100900-01;Name=Os01t0100900-01.exon1;constitutive=1;ensembl_end_phase=2;ensembl_phase=-1;exon_id=Os01t0100900-01.exon1;rank=1 +1 irgsp CDS 35743 35939 . + 0 ID=CDS:Os01t0100900-01;Parent=transcript:Os01t0100900-01;protein_id=Os01t0100900-01 +1 irgsp exon 36027 36072 . + . Parent=transcript:Os01t0100900-01;Name=Os01t0100900-01.exon2;constitutive=1;ensembl_end_phase=0;ensembl_phase=2;exon_id=Os01t0100900-01.exon2;rank=2 +1 irgsp CDS 36027 36072 . + 1 ID=CDS:Os01t0100900-01;Parent=transcript:Os01t0100900-01;protein_id=Os01t0100900-01 +1 irgsp exon 36517 36668 . + . Parent=transcript:Os01t0100900-01;Name=Os01t0100900-01.exon3;constitutive=1;ensembl_end_phase=2;ensembl_phase=0;exon_id=Os01t0100900-01.exon3;rank=3 +1 irgsp CDS 36517 36668 . + 0 ID=CDS:Os01t0100900-01;Parent=transcript:Os01t0100900-01;protein_id=Os01t0100900-01 +1 irgsp exon 36818 36877 . + . Parent=transcript:Os01t0100900-01;Name=Os01t0100900-01.exon4;constitutive=1;ensembl_end_phase=2;ensembl_phase=2;exon_id=Os01t0100900-01.exon4;rank=4 +1 irgsp CDS 36818 36877 . + 1 ID=CDS:Os01t0100900-01;Parent=transcript:Os01t0100900-01;protein_id=Os01t0100900-01 +1 irgsp exon 37594 37818 . + . Parent=transcript:Os01t0100900-01;Name=Os01t0100900-01.exon5;constitutive=1;ensembl_end_phase=2;ensembl_phase=2;exon_id=Os01t0100900-01.exon5;rank=5 +1 irgsp CDS 37594 37818 . + 1 ID=CDS:Os01t0100900-01;Parent=transcript:Os01t0100900-01;protein_id=Os01t0100900-01 +1 irgsp exon 37892 38033 . + . Parent=transcript:Os01t0100900-01;Name=Os01t0100900-01.exon6;constitutive=1;ensembl_end_phase=0;ensembl_phase=2;exon_id=Os01t0100900-01.exon6;rank=6 +1 irgsp CDS 37892 38033 . + 1 ID=CDS:Os01t0100900-01;Parent=transcript:Os01t0100900-01;protein_id=Os01t0100900-01 +1 irgsp exon 38276 38326 . + . Parent=transcript:Os01t0100900-01;Name=Os01t0100900-01.exon7;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0100900-01.exon7;rank=7 +1 irgsp CDS 38276 38326 . + 0 ID=CDS:Os01t0100900-01;Parent=transcript:Os01t0100900-01;protein_id=Os01t0100900-01 +1 irgsp exon 38434 38525 . + . Parent=transcript:Os01t0100900-01;Name=Os01t0100900-01.exon8;constitutive=1;ensembl_end_phase=2;ensembl_phase=0;exon_id=Os01t0100900-01.exon8;rank=8 +1 irgsp CDS 38434 38525 . + 0 ID=CDS:Os01t0100900-01;Parent=transcript:Os01t0100900-01;protein_id=Os01t0100900-01 +1 irgsp exon 39319 39445 . + . Parent=transcript:Os01t0100900-01;Name=Os01t0100900-01.exon9;constitutive=1;ensembl_end_phase=0;ensembl_phase=2;exon_id=Os01t0100900-01.exon9;rank=9 +1 irgsp CDS 39319 39445 . + 1 ID=CDS:Os01t0100900-01;Parent=transcript:Os01t0100900-01;protein_id=Os01t0100900-01 +1 irgsp exon 39553 39568 . + . Parent=transcript:Os01t0100900-01;Name=Os01t0100900-01.exon10;constitutive=1;ensembl_end_phase=1;ensembl_phase=0;exon_id=Os01t0100900-01.exon10;rank=10 +1 irgsp CDS 39553 39568 . + 0 ID=CDS:Os01t0100900-01;Parent=transcript:Os01t0100900-01;protein_id=Os01t0100900-01 +1 irgsp exon 39939 40046 . + . Parent=transcript:Os01t0100900-01;Name=Os01t0100900-01.exon11;constitutive=1;ensembl_end_phase=1;ensembl_phase=1;exon_id=Os01t0100900-01.exon11;rank=11 +1 irgsp CDS 39939 40046 . + 2 ID=CDS:Os01t0100900-01;Parent=transcript:Os01t0100900-01;protein_id=Os01t0100900-01 +1 irgsp exon 40135 40189 . + . Parent=transcript:Os01t0100900-01;Name=Os01t0100900-01.exon12;constitutive=1;ensembl_end_phase=2;ensembl_phase=1;exon_id=Os01t0100900-01.exon12;rank=12 +1 irgsp CDS 40135 40189 . + 2 ID=CDS:Os01t0100900-01;Parent=transcript:Os01t0100900-01;protein_id=Os01t0100900-01 +1 irgsp exon 40456 40602 . + . Parent=transcript:Os01t0100900-01;Name=Os01t0100900-01.exon13;constitutive=1;ensembl_end_phase=2;ensembl_phase=2;exon_id=Os01t0100900-01.exon13;rank=13 +1 irgsp CDS 40456 40602 . + 1 ID=CDS:Os01t0100900-01;Parent=transcript:Os01t0100900-01;protein_id=Os01t0100900-01 +1 irgsp exon 40703 40781 . + . Parent=transcript:Os01t0100900-01;Name=Os01t0100900-01.exon14;constitutive=1;ensembl_end_phase=0;ensembl_phase=2;exon_id=Os01t0100900-01.exon14;rank=14 +1 irgsp CDS 40703 40781 . + 1 ID=CDS:Os01t0100900-01;Parent=transcript:Os01t0100900-01;protein_id=Os01t0100900-01 +1 irgsp CDS 40885 41007 . + 0 ID=CDS:Os01t0100900-01;Parent=transcript:Os01t0100900-01;protein_id=Os01t0100900-01 +1 irgsp exon 40885 41136 . + . Parent=transcript:Os01t0100900-01;Name=Os01t0100900-01.exon15;constitutive=1;ensembl_end_phase=-1;ensembl_phase=0;exon_id=Os01t0100900-01.exon15;rank=15 +1 irgsp three_prime_UTR 41008 41136 . + . Parent=transcript:Os01t0100900-01 +### +1 irgsp gene 58658 61090 . + . ID=gene:Os01g0101150;biotype=protein_coding;description=Hypothetical conserved gene. (Os01t0101150-00);gene_id=Os01g0101150;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 58658 61090 . + . ID=transcript:Os01t0101150-00;Parent=gene:Os01g0101150;biotype=protein_coding;transcript_id=Os01t0101150-00 +1 irgsp exon 58658 61090 . + . Parent=transcript:Os01t0101150-00;Name=Os01t0101150-00.exon1;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0101150-00.exon1;rank=1 +1 irgsp CDS 58658 61090 . + 0 ID=CDS:Os01t0101150-00;Parent=transcript:Os01t0101150-00;protein_id=Os01t0101150-00 +### +1 irgsp gene 62060 65537 . + . ID=gene:Os01g0101200;biotype=protein_coding;description=2%2C3-diketo-5-methylthio-1-phosphopentane phosphatase domain containing protein. (Os01t0101200-01)%3B2%2C3-diketo-5-methylthio-1-phosphopentane phosphatase domain containing protein. (Os01t0101200-02);gene_id=Os01g0101200;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 62060 63576 . + . ID=transcript:Os01t0101200-01;Parent=gene:Os01g0101200;biotype=protein_coding;transcript_id=Os01t0101200-01 +1 irgsp five_prime_UTR 62060 62103 . + . Parent=transcript:Os01t0101200-01 +1 irgsp exon 62060 62295 . + . Parent=transcript:Os01t0101200-01;Name=Os01t0101200-01.exon1;constitutive=0;ensembl_end_phase=0;ensembl_phase=-1;exon_id=Os01t0101200-01.exon1;rank=1 +1 irgsp CDS 62104 62295 . + 0 ID=CDS:Os01t0101200-01;Parent=transcript:Os01t0101200-01;protein_id=Os01t0101200-01 +1 irgsp exon 62385 62905 . + . Parent=transcript:Os01t0101200-01;Name=Os01t0101200-02.exon2;constitutive=1;ensembl_end_phase=2;ensembl_phase=0;exon_id=Os01t0101200-02.exon2;rank=2 +1 irgsp CDS 62385 62905 . + 0 ID=CDS:Os01t0101200-01;Parent=transcript:Os01t0101200-01;protein_id=Os01t0101200-01 +1 irgsp exon 62996 63114 . + . Parent=transcript:Os01t0101200-01;Name=Os01t0101200-02.exon3;constitutive=1;ensembl_end_phase=1;ensembl_phase=2;exon_id=Os01t0101200-02.exon3;rank=3 +1 irgsp CDS 62996 63114 . + 1 ID=CDS:Os01t0101200-01;Parent=transcript:Os01t0101200-01;protein_id=Os01t0101200-01 +1 irgsp CDS 63248 63345 . + 2 ID=CDS:Os01t0101200-01;Parent=transcript:Os01t0101200-01;protein_id=Os01t0101200-01 +1 irgsp exon 63248 63576 . + . Parent=transcript:Os01t0101200-01;Name=Os01t0101200-01.exon4;constitutive=0;ensembl_end_phase=-1;ensembl_phase=1;exon_id=Os01t0101200-01.exon4;rank=4 +1 irgsp three_prime_UTR 63346 63576 . + . Parent=transcript:Os01t0101200-01 +1 irgsp mRNA 62112 65537 . + . ID=transcript:Os01t0101200-02;Parent=gene:Os01g0101200;biotype=protein_coding;transcript_id=Os01t0101200-02 +1 irgsp five_prime_UTR 62112 62112 . + . Parent=transcript:Os01t0101200-02 +1 irgsp exon 62112 62295 . + . Parent=transcript:Os01t0101200-02;Name=Os01t0101200-02.exon1;constitutive=0;ensembl_end_phase=0;ensembl_phase=-1;exon_id=Os01t0101200-02.exon1;rank=1 +1 irgsp CDS 62113 62295 . + 0 ID=CDS:Os01t0101200-02;Parent=transcript:Os01t0101200-02;protein_id=Os01t0101200-02 +1 irgsp exon 62385 62905 . + . Parent=transcript:Os01t0101200-02;Name=Os01t0101200-02.exon2;constitutive=1;ensembl_end_phase=2;ensembl_phase=0;exon_id=Os01t0101200-02.exon2;rank=2 +1 irgsp CDS 62385 62905 . + 0 ID=CDS:Os01t0101200-02;Parent=transcript:Os01t0101200-02;protein_id=Os01t0101200-02 +1 irgsp exon 62996 63114 . + . Parent=transcript:Os01t0101200-02;Name=Os01t0101200-02.exon3;constitutive=1;ensembl_end_phase=1;ensembl_phase=2;exon_id=Os01t0101200-02.exon3;rank=3 +1 irgsp CDS 62996 63114 . + 1 ID=CDS:Os01t0101200-02;Parent=transcript:Os01t0101200-02;protein_id=Os01t0101200-02 +1 irgsp CDS 63248 63345 . + 2 ID=CDS:Os01t0101200-02;Parent=transcript:Os01t0101200-02;protein_id=Os01t0101200-02 +1 irgsp exon 63248 65537 . + . Parent=transcript:Os01t0101200-02;Name=Os01t0101200-02.exon4;constitutive=0;ensembl_end_phase=-1;ensembl_phase=1;exon_id=Os01t0101200-02.exon4;rank=4 +1 irgsp three_prime_UTR 63346 65537 . + . Parent=transcript:Os01t0101200-02 +### +1 irgsp gene 63350 66302 . - . ID=gene:Os01g0101300;biotype=protein_coding;description=Similar to MRNA%2C partial cds%2C clone: RAFL22-26-L17. (Fragment). (Os01t0101300-01);gene_id=Os01g0101300;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 63350 66302 . - . ID=transcript:Os01t0101300-01;Parent=gene:Os01g0101300;biotype=protein_coding;transcript_id=Os01t0101300-01 +1 irgsp three_prime_UTR 63350 63669 . - . Parent=transcript:Os01t0101300-01 +1 irgsp exon 63350 63783 . - . Parent=transcript:Os01t0101300-01;Name=Os01t0101300-01.exon7;constitutive=1;ensembl_end_phase=-1;ensembl_phase=0;exon_id=Os01t0101300-01.exon7;rank=7 +1 irgsp CDS 63670 63783 . - 0 ID=CDS:Os01t0101300-01;Parent=transcript:Os01t0101300-01;protein_id=Os01t0101300-01 +1 irgsp exon 63877 64020 . - . Parent=transcript:Os01t0101300-01;Name=Os01t0101300-01.exon6;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0101300-01.exon6;rank=6 +1 irgsp CDS 63877 64020 . - 0 ID=CDS:Os01t0101300-01;Parent=transcript:Os01t0101300-01;protein_id=Os01t0101300-01 +1 irgsp exon 64339 64431 . - . Parent=transcript:Os01t0101300-01;Name=Os01t0101300-01.exon5;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0101300-01.exon5;rank=5 +1 irgsp CDS 64339 64431 . - 0 ID=CDS:Os01t0101300-01;Parent=transcript:Os01t0101300-01;protein_id=Os01t0101300-01 +1 irgsp exon 64665 64779 . - . Parent=transcript:Os01t0101300-01;Name=Os01t0101300-01.exon4;constitutive=1;ensembl_end_phase=0;ensembl_phase=2;exon_id=Os01t0101300-01.exon4;rank=4 +1 irgsp CDS 64665 64779 . - 1 ID=CDS:Os01t0101300-01;Parent=transcript:Os01t0101300-01;protein_id=Os01t0101300-01 +1 irgsp exon 64902 65152 . - . Parent=transcript:Os01t0101300-01;Name=Os01t0101300-01.exon3;constitutive=1;ensembl_end_phase=2;ensembl_phase=0;exon_id=Os01t0101300-01.exon3;rank=3 +1 irgsp CDS 64902 65152 . - 0 ID=CDS:Os01t0101300-01;Parent=transcript:Os01t0101300-01;protein_id=Os01t0101300-01 +1 irgsp exon 65248 65431 . - . Parent=transcript:Os01t0101300-01;Name=Os01t0101300-01.exon2;constitutive=1;ensembl_end_phase=0;ensembl_phase=2;exon_id=Os01t0101300-01.exon2;rank=2 +1 irgsp CDS 65248 65431 . - 1 ID=CDS:Os01t0101300-01;Parent=transcript:Os01t0101300-01;protein_id=Os01t0101300-01 +1 irgsp CDS 65628 65950 . - 0 ID=CDS:Os01t0101300-01;Parent=transcript:Os01t0101300-01;protein_id=Os01t0101300-01 +1 irgsp exon 65628 66302 . - . Parent=transcript:Os01t0101300-01;Name=Os01t0101300-01.exon1;constitutive=1;ensembl_end_phase=2;ensembl_phase=-1;exon_id=Os01t0101300-01.exon1;rank=1 +1 irgsp five_prime_UTR 65951 66302 . - . Parent=transcript:Os01t0101300-01 +### +1 irgsp gene 72816 78349 . + . ID=gene:Os01g0101600;biotype=protein_coding;description=Immunoglobulin-like fold domain containing protein. (Os01t0101600-01)%3BImmunoglobulin-like fold domain containing protein. (Os01t0101600-02)%3BHypothetical conserved gene. (Os01t0101600-03);gene_id=Os01g0101600;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 72816 78349 . + . ID=transcript:Os01t0101600-01;Parent=gene:Os01g0101600;biotype=protein_coding;transcript_id=Os01t0101600-01 +1 irgsp five_prime_UTR 72816 72902 . + . Parent=transcript:Os01t0101600-01 +1 irgsp exon 72816 73935 . + . Parent=transcript:Os01t0101600-01;Name=Os01t0101600-01.exon1;constitutive=0;ensembl_end_phase=1;ensembl_phase=-1;exon_id=Os01t0101600-01.exon1;rank=1 +1 irgsp CDS 72903 73935 . + 0 ID=CDS:Os01t0101600-01;Parent=transcript:Os01t0101600-01;protein_id=Os01t0101600-01 +1 irgsp exon 74468 74981 . + . Parent=transcript:Os01t0101600-01;Name=Os01t0101600-02.exon2;constitutive=0;ensembl_end_phase=2;ensembl_phase=1;exon_id=Os01t0101600-02.exon2;rank=2 +1 irgsp CDS 74468 74981 . + 2 ID=CDS:Os01t0101600-01;Parent=transcript:Os01t0101600-01;protein_id=Os01t0101600-01 +1 irgsp CDS 75619 77008 . + 1 ID=CDS:Os01t0101600-01;Parent=transcript:Os01t0101600-01;protein_id=Os01t0101600-01 +1 irgsp exon 75619 77205 . + . Parent=transcript:Os01t0101600-01;Name=Os01t0101600-01.exon3;constitutive=0;ensembl_end_phase=-1;ensembl_phase=2;exon_id=Os01t0101600-01.exon3;rank=3 +1 irgsp three_prime_UTR 77009 77205 . + . Parent=transcript:Os01t0101600-01 +1 irgsp exon 77333 78349 . + . Parent=transcript:Os01t0101600-01;Name=Os01t0101600-01.exon4;constitutive=0;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0101600-01.exon4;rank=4 +1 irgsp three_prime_UTR 77333 78349 . + . Parent=transcript:Os01t0101600-01 +1 irgsp mRNA 72823 77699 . + . ID=transcript:Os01t0101600-02;Parent=gene:Os01g0101600;biotype=protein_coding;transcript_id=Os01t0101600-02 +1 irgsp five_prime_UTR 72823 72902 . + . Parent=transcript:Os01t0101600-02 +1 irgsp exon 72823 73935 . + . Parent=transcript:Os01t0101600-02;Name=Os01t0101600-02.exon1;constitutive=0;ensembl_end_phase=1;ensembl_phase=-1;exon_id=Os01t0101600-02.exon1;rank=1 +1 irgsp CDS 72903 73935 . + 0 ID=CDS:Os01t0101600-02;Parent=transcript:Os01t0101600-02;protein_id=Os01t0101600-02 +1 irgsp exon 74468 74981 . + . Parent=transcript:Os01t0101600-02;Name=Os01t0101600-02.exon2;constitutive=0;ensembl_end_phase=2;ensembl_phase=1;exon_id=Os01t0101600-02.exon2;rank=2 +1 irgsp CDS 74468 74981 . + 2 ID=CDS:Os01t0101600-02;Parent=transcript:Os01t0101600-02;protein_id=Os01t0101600-02 +1 irgsp CDS 75619 77008 . + 1 ID=CDS:Os01t0101600-02;Parent=transcript:Os01t0101600-02;protein_id=Os01t0101600-02 +1 irgsp exon 75619 77699 . + . Parent=transcript:Os01t0101600-02;Name=Os01t0101600-02.exon3;constitutive=0;ensembl_end_phase=-1;ensembl_phase=2;exon_id=Os01t0101600-02.exon3;rank=3 +1 irgsp three_prime_UTR 77009 77699 . + . Parent=transcript:Os01t0101600-02 +1 irgsp mRNA 75942 77699 . + . ID=transcript:Os01t0101600-03;Parent=gene:Os01g0101600;biotype=protein_coding;transcript_id=Os01t0101600-03 +1 irgsp five_prime_UTR 75942 75943 . + . Parent=transcript:Os01t0101600-03 +1 irgsp exon 75942 77699 . + . Parent=transcript:Os01t0101600-03;Name=Os01t0101600-03.exon1;constitutive=0;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0101600-03.exon1;rank=1 +1 irgsp CDS 75944 77008 . + 0 ID=CDS:Os01t0101600-03;Parent=transcript:Os01t0101600-03;protein_id=Os01t0101600-03 +1 irgsp three_prime_UTR 77009 77699 . + . Parent=transcript:Os01t0101600-03 +### +1 irgsp gene 82426 84095 . + . ID=gene:Os01g0101700;Name=DnaJ domain protein C1%2C rice DJC26 homolog;biotype=protein_coding;description=Similar to chaperone protein dnaJ 20. (Os01t0101700-00);gene_id=Os01g0101700;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 82426 84095 . + . ID=transcript:Os01t0101700-00;Parent=gene:Os01g0101700;biotype=protein_coding;transcript_id=Os01t0101700-00 +1 irgsp five_prime_UTR 82426 82506 . + . Parent=transcript:Os01t0101700-00 +1 irgsp exon 82426 82932 . + . Parent=transcript:Os01t0101700-00;Name=Os01t0101700-00.exon1;constitutive=1;ensembl_end_phase=0;ensembl_phase=-1;exon_id=Os01t0101700-00.exon1;rank=1 +1 irgsp CDS 82507 82932 . + 0 ID=CDS:Os01t0101700-00;Parent=transcript:Os01t0101700-00;protein_id=Os01t0101700-00 +1 irgsp CDS 83724 83864 . + 0 ID=CDS:Os01t0101700-00;Parent=transcript:Os01t0101700-00;protein_id=Os01t0101700-00 +1 irgsp exon 83724 84095 . + . Parent=transcript:Os01t0101700-00;Name=Os01t0101700-00.exon2;constitutive=1;ensembl_end_phase=-1;ensembl_phase=0;exon_id=Os01t0101700-00.exon2;rank=2 +1 irgsp three_prime_UTR 83865 84095 . + . Parent=transcript:Os01t0101700-00 +### +1 irgsp gene 85337 88844 . + . ID=gene:Os01g0101800;biotype=protein_coding;description=Conserved hypothetical protein. (Os01t0101800-01);gene_id=Os01g0101800;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 85337 88844 . + . ID=transcript:Os01t0101800-01;Parent=gene:Os01g0101800;biotype=protein_coding;transcript_id=Os01t0101800-01 +1 irgsp five_prime_UTR 85337 85378 . + . Parent=transcript:Os01t0101800-01 +1 irgsp exon 85337 85600 . + . Parent=transcript:Os01t0101800-01;Name=Os01t0101800-01.exon1;constitutive=1;ensembl_end_phase=0;ensembl_phase=-1;exon_id=Os01t0101800-01.exon1;rank=1 +1 irgsp CDS 85379 85600 . + 0 ID=CDS:Os01t0101800-01;Parent=transcript:Os01t0101800-01;protein_id=Os01t0101800-01 +1 irgsp exon 85737 85830 . + . Parent=transcript:Os01t0101800-01;Name=Os01t0101800-01.exon2;constitutive=1;ensembl_end_phase=1;ensembl_phase=0;exon_id=Os01t0101800-01.exon2;rank=2 +1 irgsp CDS 85737 85830 . + 0 ID=CDS:Os01t0101800-01;Parent=transcript:Os01t0101800-01;protein_id=Os01t0101800-01 +1 irgsp exon 85935 86086 . + . Parent=transcript:Os01t0101800-01;Name=Os01t0101800-01.exon3;constitutive=1;ensembl_end_phase=0;ensembl_phase=1;exon_id=Os01t0101800-01.exon3;rank=3 +1 irgsp CDS 85935 86086 . + 2 ID=CDS:Os01t0101800-01;Parent=transcript:Os01t0101800-01;protein_id=Os01t0101800-01 +1 irgsp exon 86212 86299 . + . Parent=transcript:Os01t0101800-01;Name=Os01t0101800-01.exon4;constitutive=1;ensembl_end_phase=1;ensembl_phase=0;exon_id=Os01t0101800-01.exon4;rank=4 +1 irgsp CDS 86212 86299 . + 0 ID=CDS:Os01t0101800-01;Parent=transcript:Os01t0101800-01;protein_id=Os01t0101800-01 +1 irgsp exon 86399 87681 . + . Parent=transcript:Os01t0101800-01;Name=Os01t0101800-01.exon5;constitutive=1;ensembl_end_phase=0;ensembl_phase=1;exon_id=Os01t0101800-01.exon5;rank=5 +1 irgsp CDS 86399 87681 . + 2 ID=CDS:Os01t0101800-01;Parent=transcript:Os01t0101800-01;protein_id=Os01t0101800-01 +1 irgsp exon 88291 88398 . + . Parent=transcript:Os01t0101800-01;Name=Os01t0101800-01.exon6;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0101800-01.exon6;rank=6 +1 irgsp CDS 88291 88398 . + 0 ID=CDS:Os01t0101800-01;Parent=transcript:Os01t0101800-01;protein_id=Os01t0101800-01 +1 irgsp CDS 88500 88583 . + 0 ID=CDS:Os01t0101800-01;Parent=transcript:Os01t0101800-01;protein_id=Os01t0101800-01 +1 irgsp exon 88500 88844 . + . Parent=transcript:Os01t0101800-01;Name=Os01t0101800-01.exon7;constitutive=1;ensembl_end_phase=-1;ensembl_phase=0;exon_id=Os01t0101800-01.exon7;rank=7 +1 irgsp three_prime_UTR 88584 88844 . + . Parent=transcript:Os01t0101800-01 +### +1 irgsp gene 86211 88583 . - . ID=gene:Os01g0101850;biotype=protein_coding;description=Hypothetical protein. (Os01t0101850-00);gene_id=Os01g0101850;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 86211 88583 . - . ID=transcript:Os01t0101850-00;Parent=gene:Os01g0101850;biotype=protein_coding;transcript_id=Os01t0101850-00 +1 irgsp exon 86211 86277 . - . Parent=transcript:Os01t0101850-00;Name=Os01t0101850-00.exon4;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0101850-00.exon4;rank=4 +1 irgsp three_prime_UTR 86211 86277 . - . Parent=transcript:Os01t0101850-00 +1 irgsp three_prime_UTR 86384 87326 . - . Parent=transcript:Os01t0101850-00 +1 irgsp exon 86384 87694 . - . Parent=transcript:Os01t0101850-00;Name=Os01t0101850-00.exon3;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0101850-00.exon3;rank=3 +1 irgsp CDS 87327 87662 . - 0 ID=CDS:Os01t0101850-00;Parent=transcript:Os01t0101850-00;protein_id=Os01t0101850-00 +1 irgsp five_prime_UTR 87663 87694 . - . Parent=transcript:Os01t0101850-00 +1 irgsp exon 88308 88396 . - . Parent=transcript:Os01t0101850-00;Name=Os01t0101850-00.exon2;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0101850-00.exon2;rank=2 +1 irgsp five_prime_UTR 88308 88396 . - . Parent=transcript:Os01t0101850-00 +1 irgsp exon 88496 88583 . - . Parent=transcript:Os01t0101850-00;Name=Os01t0101850-00.exon1;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0101850-00.exon1;rank=1 +1 irgsp five_prime_UTR 88496 88583 . - . Parent=transcript:Os01t0101850-00 +### +1 irgsp gene 88883 89228 . - . ID=gene:Os01g0101900;biotype=protein_coding;description=Similar to OSIGBa0075F02.3 protein. (Os01t0101900-00);gene_id=Os01g0101900;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 88883 89228 . - . ID=transcript:Os01t0101900-00;Parent=gene:Os01g0101900;biotype=protein_coding;transcript_id=Os01t0101900-00 +1 irgsp three_prime_UTR 88883 88985 . - . Parent=transcript:Os01t0101900-00 +1 irgsp exon 88883 89228 . - . Parent=transcript:Os01t0101900-00;Name=Os01t0101900-00.exon1;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0101900-00.exon1;rank=1 +1 irgsp CDS 88986 89204 . - 0 ID=CDS:Os01t0101900-00;Parent=transcript:Os01t0101900-00;protein_id=Os01t0101900-00 +1 irgsp five_prime_UTR 89205 89228 . - . Parent=transcript:Os01t0101900-00 +### +1 irgsp gene 89763 91465 . - . ID=gene:Os01g0102000;Name=NON-SPECIFIC PHOSPHOLIPASE C5;biotype=protein_coding;description=Phosphoesterase family protein. (Os01t0102000-01);gene_id=Os01g0102000;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 89763 91465 . - . ID=transcript:Os01t0102000-01;Parent=gene:Os01g0102000;biotype=protein_coding;transcript_id=Os01t0102000-01 +1 irgsp three_prime_UTR 89763 89824 . - . Parent=transcript:Os01t0102000-01 +1 irgsp exon 89763 91465 . - . Parent=transcript:Os01t0102000-01;Name=Os01t0102000-01.exon1;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0102000-01.exon1;rank=1 +1 irgsp CDS 89825 91411 . - 0 ID=CDS:Os01t0102000-01;Parent=transcript:Os01t0102000-01;protein_id=Os01t0102000-01 +1 irgsp five_prime_UTR 91412 91465 . - . Parent=transcript:Os01t0102000-01 +### +1 irgsp gene 134300 135439 . + . ID=gene:Os01g0102300;Name=OsTLP27;biotype=protein_coding;description=Thylakoid lumen protein%2C Photosynthesis and chloroplast development (Os01t0102300-01);gene_id=Os01g0102300;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 134300 135439 . + . ID=transcript:Os01t0102300-01;Parent=gene:Os01g0102300;biotype=protein_coding;transcript_id=Os01t0102300-01 +1 irgsp five_prime_UTR 134300 134310 . + . Parent=transcript:Os01t0102300-01 +1 irgsp exon 134300 134615 . + . Parent=transcript:Os01t0102300-01;Name=Os01t0102300-01.exon1;constitutive=1;ensembl_end_phase=2;ensembl_phase=-1;exon_id=Os01t0102300-01.exon1;rank=1 +1 irgsp CDS 134311 134615 . + 0 ID=CDS:Os01t0102300-01;Parent=transcript:Os01t0102300-01;protein_id=Os01t0102300-01 +1 irgsp exon 134698 134824 . + . Parent=transcript:Os01t0102300-01;Name=Os01t0102300-01.exon2;constitutive=1;ensembl_end_phase=0;ensembl_phase=2;exon_id=Os01t0102300-01.exon2;rank=2 +1 irgsp CDS 134698 134824 . + 1 ID=CDS:Os01t0102300-01;Parent=transcript:Os01t0102300-01;protein_id=Os01t0102300-01 +1 irgsp CDS 134912 135253 . + 0 ID=CDS:Os01t0102300-01;Parent=transcript:Os01t0102300-01;protein_id=Os01t0102300-01 +1 irgsp exon 134912 135439 . + . Parent=transcript:Os01t0102300-01;Name=Os01t0102300-01.exon3;constitutive=1;ensembl_end_phase=-1;ensembl_phase=0;exon_id=Os01t0102300-01.exon3;rank=3 +1 irgsp three_prime_UTR 135254 135439 . + . Parent=transcript:Os01t0102300-01 +### +1 irgsp gene 139826 141555 . + . ID=gene:Os01g0102400;Name=HAP5H SUBUNIT OF CCAAT-BOX BINDING COMPLEX;biotype=protein_coding;description=Histone-fold domain containing protein. (Os01t0102400-01);gene_id=Os01g0102400;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 139826 141555 . + . ID=transcript:Os01t0102400-01;Parent=gene:Os01g0102400;biotype=protein_coding;transcript_id=Os01t0102400-01 +1 irgsp exon 139826 139906 . + . Parent=transcript:Os01t0102400-01;Name=Os01t0102400-01.exon1;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0102400-01.exon1;rank=1 +1 irgsp five_prime_UTR 139826 139906 . + . Parent=transcript:Os01t0102400-01 +1 irgsp five_prime_UTR 140120 140149 . + . Parent=transcript:Os01t0102400-01 +1 irgsp exon 140120 141555 . + . Parent=transcript:Os01t0102400-01;Name=Os01t0102400-01.exon2;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0102400-01.exon2;rank=2 +1 irgsp CDS 140150 141415 . + 0 ID=CDS:Os01t0102400-01;Parent=transcript:Os01t0102400-01;protein_id=Os01t0102400-01 +1 irgsp three_prime_UTR 141416 141555 . + . Parent=transcript:Os01t0102400-01 +### +1 irgsp gene 141959 144554 . + . ID=gene:Os01g0102500;biotype=protein_coding;description=Conserved hypothetical protein. (Os01t0102500-01);gene_id=Os01g0102500;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 141959 144554 . + . ID=transcript:Os01t0102500-01;Parent=gene:Os01g0102500;biotype=protein_coding;transcript_id=Os01t0102500-01 +1 irgsp five_prime_UTR 141959 142083 . + . Parent=transcript:Os01t0102500-01 +1 irgsp exon 141959 142631 . + . Parent=transcript:Os01t0102500-01;Name=Os01t0102500-01.exon1;constitutive=1;ensembl_end_phase=2;ensembl_phase=-1;exon_id=Os01t0102500-01.exon1;rank=1 +1 irgsp CDS 142084 142631 . + 0 ID=CDS:Os01t0102500-01;Parent=transcript:Os01t0102500-01;protein_id=Os01t0102500-01 +1 irgsp exon 143191 143431 . + . Parent=transcript:Os01t0102500-01;Name=Os01t0102500-01.exon2;constitutive=1;ensembl_end_phase=0;ensembl_phase=2;exon_id=Os01t0102500-01.exon2;rank=2 +1 irgsp CDS 143191 143431 . + 1 ID=CDS:Os01t0102500-01;Parent=transcript:Os01t0102500-01;protein_id=Os01t0102500-01 +1 irgsp exon 143563 143680 . + . Parent=transcript:Os01t0102500-01;Name=Os01t0102500-01.exon3;constitutive=1;ensembl_end_phase=1;ensembl_phase=0;exon_id=Os01t0102500-01.exon3;rank=3 +1 irgsp CDS 143563 143680 . + 0 ID=CDS:Os01t0102500-01;Parent=transcript:Os01t0102500-01;protein_id=Os01t0102500-01 +1 irgsp CDS 143817 143908 . + 2 ID=CDS:Os01t0102500-01;Parent=transcript:Os01t0102500-01;protein_id=Os01t0102500-01 +1 irgsp exon 143817 144554 . + . Parent=transcript:Os01t0102500-01;Name=Os01t0102500-01.exon4;constitutive=1;ensembl_end_phase=-1;ensembl_phase=1;exon_id=Os01t0102500-01.exon4;rank=4 +1 irgsp three_prime_UTR 143909 144554 . + . Parent=transcript:Os01t0102500-01 +### +1 irgsp gene 145603 147847 . + . ID=gene:Os01g0102600;Name=Shikimate kinase 4;biotype=protein_coding;description=Shikimate kinase domain containing protein. (Os01t0102600-01)%3BSimilar to shikimate kinase family protein. (Os01t0102600-02);gene_id=Os01g0102600;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 145603 147847 . + . ID=transcript:Os01t0102600-01;Parent=gene:Os01g0102600;biotype=protein_coding;transcript_id=Os01t0102600-01 +1 irgsp five_prime_UTR 145603 145644 . + . Parent=transcript:Os01t0102600-01 +1 irgsp exon 145603 145786 . + . Parent=transcript:Os01t0102600-01;Name=Os01t0102600-01.exon1;constitutive=0;ensembl_end_phase=1;ensembl_phase=-1;exon_id=Os01t0102600-01.exon1;rank=1 +1 irgsp CDS 145645 145786 . + 0 ID=CDS:Os01t0102600-01;Parent=transcript:Os01t0102600-01;protein_id=Os01t0102600-01 +1 irgsp exon 145905 145951 . + . Parent=transcript:Os01t0102600-01;Name=Os01t0102600-01.exon2;constitutive=0;ensembl_end_phase=0;ensembl_phase=1;exon_id=Os01t0102600-01.exon2;rank=2 +1 irgsp CDS 145905 145951 . + 2 ID=CDS:Os01t0102600-01;Parent=transcript:Os01t0102600-01;protein_id=Os01t0102600-01 +1 irgsp exon 146028 146082 . + . Parent=transcript:Os01t0102600-01;Name=Os01t0102600-01.exon3;constitutive=0;ensembl_end_phase=1;ensembl_phase=0;exon_id=Os01t0102600-01.exon3;rank=3 +1 irgsp CDS 146028 146082 . + 0 ID=CDS:Os01t0102600-01;Parent=transcript:Os01t0102600-01;protein_id=Os01t0102600-01 +1 irgsp exon 146179 146339 . + . Parent=transcript:Os01t0102600-01;Name=Os01t0102600-01.exon4;constitutive=0;ensembl_end_phase=0;ensembl_phase=1;exon_id=Os01t0102600-01.exon4;rank=4 +1 irgsp CDS 146179 146339 . + 2 ID=CDS:Os01t0102600-01;Parent=transcript:Os01t0102600-01;protein_id=Os01t0102600-01 +1 irgsp exon 146450 146532 . + . Parent=transcript:Os01t0102600-01;Name=Os01t0102600-01.exon5;constitutive=0;ensembl_end_phase=2;ensembl_phase=0;exon_id=Os01t0102600-01.exon5;rank=5 +1 irgsp CDS 146450 146532 . + 0 ID=CDS:Os01t0102600-01;Parent=transcript:Os01t0102600-01;protein_id=Os01t0102600-01 +1 irgsp exon 146611 146719 . + . Parent=transcript:Os01t0102600-01;Name=Os01t0102600-01.exon6;constitutive=0;ensembl_end_phase=0;ensembl_phase=2;exon_id=Os01t0102600-01.exon6;rank=6 +1 irgsp CDS 146611 146719 . + 1 ID=CDS:Os01t0102600-01;Parent=transcript:Os01t0102600-01;protein_id=Os01t0102600-01 +1 irgsp exon 147106 147184 . + . Parent=transcript:Os01t0102600-01;Name=Os01t0102600-01.exon7;constitutive=0;ensembl_end_phase=1;ensembl_phase=0;exon_id=Os01t0102600-01.exon7;rank=7 +1 irgsp CDS 147106 147184 . + 0 ID=CDS:Os01t0102600-01;Parent=transcript:Os01t0102600-01;protein_id=Os01t0102600-01 +1 irgsp exon 147311 147375 . + . Parent=transcript:Os01t0102600-01;Name=Os01t0102600-02.exon2;constitutive=1;ensembl_end_phase=0;ensembl_phase=1;exon_id=Os01t0102600-02.exon2;rank=8 +1 irgsp CDS 147311 147375 . + 2 ID=CDS:Os01t0102600-01;Parent=transcript:Os01t0102600-01;protein_id=Os01t0102600-01 +1 irgsp CDS 147507 147575 . + 0 ID=CDS:Os01t0102600-01;Parent=transcript:Os01t0102600-01;protein_id=Os01t0102600-01 +1 irgsp exon 147507 147847 . + . Parent=transcript:Os01t0102600-01;Name=Os01t0102600-01.exon9;constitutive=0;ensembl_end_phase=-1;ensembl_phase=0;exon_id=Os01t0102600-01.exon9;rank=9 +1 irgsp three_prime_UTR 147576 147847 . + . Parent=transcript:Os01t0102600-01 +1 irgsp mRNA 147104 147805 . + . ID=transcript:Os01t0102600-02;Parent=gene:Os01g0102600;biotype=protein_coding;transcript_id=Os01t0102600-02 +1 irgsp five_prime_UTR 147104 147105 . + . Parent=transcript:Os01t0102600-02 +1 irgsp exon 147104 147184 . + . Parent=transcript:Os01t0102600-02;Name=Os01t0102600-02.exon1;constitutive=0;ensembl_end_phase=1;ensembl_phase=-1;exon_id=Os01t0102600-02.exon1;rank=1 +1 irgsp CDS 147106 147184 . + 0 ID=CDS:Os01t0102600-02;Parent=transcript:Os01t0102600-02;protein_id=Os01t0102600-02 +1 irgsp exon 147311 147375 . + . Parent=transcript:Os01t0102600-02;Name=Os01t0102600-02.exon2;constitutive=1;ensembl_end_phase=0;ensembl_phase=1;exon_id=Os01t0102600-02.exon2;rank=2 +1 irgsp CDS 147311 147375 . + 2 ID=CDS:Os01t0102600-02;Parent=transcript:Os01t0102600-02;protein_id=Os01t0102600-02 +1 irgsp CDS 147507 147575 . + 0 ID=CDS:Os01t0102600-02;Parent=transcript:Os01t0102600-02;protein_id=Os01t0102600-02 +1 irgsp exon 147507 147805 . + . Parent=transcript:Os01t0102600-02;Name=Os01t0102600-02.exon3;constitutive=0;ensembl_end_phase=-1;ensembl_phase=0;exon_id=Os01t0102600-02.exon3;rank=3 +1 irgsp three_prime_UTR 147576 147805 . + . Parent=transcript:Os01t0102600-02 +### +1 irgsp gene 148085 150568 . + . ID=gene:Os01g0102700;biotype=protein_coding;description=Translocon-associated beta family protein. (Os01t0102700-01);gene_id=Os01g0102700;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 148085 150568 . + . ID=transcript:Os01t0102700-01;Parent=gene:Os01g0102700;biotype=protein_coding;transcript_id=Os01t0102700-01 +1 irgsp five_prime_UTR 148085 148146 . + . Parent=transcript:Os01t0102700-01 +1 irgsp exon 148085 148313 . + . Parent=transcript:Os01t0102700-01;Name=Os01t0102700-01.exon1;constitutive=1;ensembl_end_phase=2;ensembl_phase=-1;exon_id=Os01t0102700-01.exon1;rank=1 +1 irgsp CDS 148147 148313 . + 0 ID=CDS:Os01t0102700-01;Parent=transcript:Os01t0102700-01;protein_id=Os01t0102700-01 +1 irgsp exon 149450 149548 . + . Parent=transcript:Os01t0102700-01;Name=Os01t0102700-01.exon2;constitutive=1;ensembl_end_phase=2;ensembl_phase=2;exon_id=Os01t0102700-01.exon2;rank=2 +1 irgsp CDS 149450 149548 . + 1 ID=CDS:Os01t0102700-01;Parent=transcript:Os01t0102700-01;protein_id=Os01t0102700-01 +1 irgsp exon 149634 149742 . + . Parent=transcript:Os01t0102700-01;Name=Os01t0102700-01.exon3;constitutive=1;ensembl_end_phase=0;ensembl_phase=2;exon_id=Os01t0102700-01.exon3;rank=3 +1 irgsp CDS 149634 149742 . + 1 ID=CDS:Os01t0102700-01;Parent=transcript:Os01t0102700-01;protein_id=Os01t0102700-01 +1 irgsp exon 149856 149931 . + . Parent=transcript:Os01t0102700-01;Name=Os01t0102700-01.exon4;constitutive=1;ensembl_end_phase=1;ensembl_phase=0;exon_id=Os01t0102700-01.exon4;rank=4 +1 irgsp CDS 149856 149931 . + 0 ID=CDS:Os01t0102700-01;Parent=transcript:Os01t0102700-01;protein_id=Os01t0102700-01 +1 irgsp CDS 150152 150318 . + 2 ID=CDS:Os01t0102700-01;Parent=transcript:Os01t0102700-01;protein_id=Os01t0102700-01 +1 irgsp exon 150152 150568 . + . Parent=transcript:Os01t0102700-01;Name=Os01t0102700-01.exon5;constitutive=1;ensembl_end_phase=-1;ensembl_phase=1;exon_id=Os01t0102700-01.exon5;rank=5 +1 irgsp three_prime_UTR 150319 150568 . + . Parent=transcript:Os01t0102700-01 +### +1 irgsp gene 152853 156449 . + . ID=gene:Os01g0102800;Name=Cockayne syndrome WD-repeat protein;biotype=protein_coding;description=Similar to chromatin remodeling complex subunit. (Os01t0102800-01);gene_id=Os01g0102800;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 152853 156449 . + . ID=transcript:Os01t0102800-01;Parent=gene:Os01g0102800;biotype=protein_coding;transcript_id=Os01t0102800-01 +1 irgsp five_prime_UTR 152853 152853 . + . Parent=transcript:Os01t0102800-01 +1 irgsp exon 152853 153025 . + . Parent=transcript:Os01t0102800-01;Name=Os01t0102800-01.exon1;constitutive=1;ensembl_end_phase=1;ensembl_phase=-1;exon_id=Os01t0102800-01.exon1;rank=1 +1 irgsp CDS 152854 153025 . + 0 ID=CDS:Os01t0102800-01;Parent=transcript:Os01t0102800-01;protein_id=Os01t0102800-01 +1 irgsp exon 153178 154646 . + . Parent=transcript:Os01t0102800-01;Name=Os01t0102800-01.exon2;constitutive=1;ensembl_end_phase=0;ensembl_phase=1;exon_id=Os01t0102800-01.exon2;rank=2 +1 irgsp CDS 153178 154646 . + 2 ID=CDS:Os01t0102800-01;Parent=transcript:Os01t0102800-01;protein_id=Os01t0102800-01 +1 irgsp exon 155010 155450 . + . Parent=transcript:Os01t0102800-01;Name=Os01t0102800-01.exon3;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0102800-01.exon3;rank=3 +1 irgsp CDS 155010 155450 . + 0 ID=CDS:Os01t0102800-01;Parent=transcript:Os01t0102800-01;protein_id=Os01t0102800-01 +1 irgsp CDS 155543 156214 . + 0 ID=CDS:Os01t0102800-01;Parent=transcript:Os01t0102800-01;protein_id=Os01t0102800-01 +1 irgsp exon 155543 156449 . + . Parent=transcript:Os01t0102800-01;Name=Os01t0102800-01.exon4;constitutive=1;ensembl_end_phase=-1;ensembl_phase=0;exon_id=Os01t0102800-01.exon4;rank=4 +1 irgsp three_prime_UTR 156215 156449 . + . Parent=transcript:Os01t0102800-01 +### +1 irgsp gene 164577 168921 . + . ID=gene:Os01g0102850;biotype=protein_coding;description=Similar to nitrilase 2. (Os01t0102850-00);gene_id=Os01g0102850;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 164577 168921 . + . ID=transcript:Os01t0102850-00;Parent=gene:Os01g0102850;biotype=protein_coding;transcript_id=Os01t0102850-00 +1 irgsp exon 164577 164905 . + . Parent=transcript:Os01t0102850-00;Name=Os01t0102850-00.exon1;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0102850-00.exon1;rank=1 +1 irgsp five_prime_UTR 164577 164905 . + . Parent=transcript:Os01t0102850-00 +1 irgsp five_prime_UTR 168499 168804 . + . Parent=transcript:Os01t0102850-00 +1 irgsp exon 168499 168921 . + . Parent=transcript:Os01t0102850-00;Name=Os01t0102850-00.exon2;constitutive=1;ensembl_end_phase=0;ensembl_phase=-1;exon_id=Os01t0102850-00.exon2;rank=2 +1 irgsp CDS 168805 168921 . + 0 ID=CDS:Os01t0102850-00;Parent=transcript:Os01t0102850-00;protein_id=Os01t0102850-00 +### +1 irgsp gene 169390 170316 . - . ID=gene:Os01g0102900;Name=LIGHT-REGULATED GENE 1;biotype=protein_coding;description=Light-regulated protein%2C Regulation of light-dependent attachment of LEAF-TYPE FERREDOXIN-NADP+ OXIDOREDUCTASE (LFNR) to the thylakoid membrane (Os01t0102900-01);gene_id=Os01g0102900;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 169390 170316 . - . ID=transcript:Os01t0102900-01;Parent=gene:Os01g0102900;biotype=protein_coding;transcript_id=Os01t0102900-01 +1 irgsp three_prime_UTR 169390 169598 . - . Parent=transcript:Os01t0102900-01 +1 irgsp exon 169390 169656 . - . Parent=transcript:Os01t0102900-01;Name=Os01t0102900-01.exon3;constitutive=1;ensembl_end_phase=-1;ensembl_phase=2;exon_id=Os01t0102900-01.exon3;rank=3 +1 irgsp CDS 169599 169656 . - 1 ID=CDS:Os01t0102900-01;Parent=transcript:Os01t0102900-01;protein_id=Os01t0102900-01 +1 irgsp exon 169751 169909 . - . Parent=transcript:Os01t0102900-01;Name=Os01t0102900-01.exon2;constitutive=1;ensembl_end_phase=2;ensembl_phase=2;exon_id=Os01t0102900-01.exon2;rank=2 +1 irgsp CDS 169751 169909 . - 1 ID=CDS:Os01t0102900-01;Parent=transcript:Os01t0102900-01;protein_id=Os01t0102900-01 +1 irgsp CDS 170091 170260 . - 0 ID=CDS:Os01t0102900-01;Parent=transcript:Os01t0102900-01;protein_id=Os01t0102900-01 +1 irgsp exon 170091 170316 . - . Parent=transcript:Os01t0102900-01;Name=Os01t0102900-01.exon1;constitutive=1;ensembl_end_phase=2;ensembl_phase=-1;exon_id=Os01t0102900-01.exon1;rank=1 +1 irgsp five_prime_UTR 170261 170316 . - . Parent=transcript:Os01t0102900-01 +### +1 irgsp gene 170798 173144 . - . ID=gene:Os01g0103000;biotype=protein_coding;description=Snf7 family protein. (Os01t0103000-01);gene_id=Os01g0103000;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 170798 173144 . - . ID=transcript:Os01t0103000-01;Parent=gene:Os01g0103000;biotype=protein_coding;transcript_id=Os01t0103000-01 +1 irgsp three_prime_UTR 170798 171044 . - . Parent=transcript:Os01t0103000-01 +1 irgsp exon 170798 171095 . - . Parent=transcript:Os01t0103000-01;Name=Os01t0103000-01.exon7;constitutive=1;ensembl_end_phase=-1;ensembl_phase=0;exon_id=Os01t0103000-01.exon7;rank=7 +1 irgsp CDS 171045 171095 . - 0 ID=CDS:Os01t0103000-01;Parent=transcript:Os01t0103000-01;protein_id=Os01t0103000-01 +1 irgsp exon 171406 171554 . - . Parent=transcript:Os01t0103000-01;Name=Os01t0103000-01.exon6;constitutive=1;ensembl_end_phase=0;ensembl_phase=1;exon_id=Os01t0103000-01.exon6;rank=6 +1 irgsp CDS 171406 171554 . - 2 ID=CDS:Os01t0103000-01;Parent=transcript:Os01t0103000-01;protein_id=Os01t0103000-01 +1 irgsp exon 171764 171875 . - . Parent=transcript:Os01t0103000-01;Name=Os01t0103000-01.exon5;constitutive=1;ensembl_end_phase=1;ensembl_phase=0;exon_id=Os01t0103000-01.exon5;rank=5 +1 irgsp CDS 171764 171875 . - 0 ID=CDS:Os01t0103000-01;Parent=transcript:Os01t0103000-01;protein_id=Os01t0103000-01 +1 irgsp exon 172398 172469 . - . Parent=transcript:Os01t0103000-01;Name=Os01t0103000-01.exon4;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0103000-01.exon4;rank=4 +1 irgsp CDS 172398 172469 . - 0 ID=CDS:Os01t0103000-01;Parent=transcript:Os01t0103000-01;protein_id=Os01t0103000-01 +1 irgsp exon 172578 172671 . - . Parent=transcript:Os01t0103000-01;Name=Os01t0103000-01.exon3;constitutive=1;ensembl_end_phase=0;ensembl_phase=2;exon_id=Os01t0103000-01.exon3;rank=3 +1 irgsp CDS 172578 172671 . - 1 ID=CDS:Os01t0103000-01;Parent=transcript:Os01t0103000-01;protein_id=Os01t0103000-01 +1 irgsp exon 172770 172921 . - . Parent=transcript:Os01t0103000-01;Name=Os01t0103000-01.exon2;constitutive=1;ensembl_end_phase=2;ensembl_phase=0;exon_id=Os01t0103000-01.exon2;rank=2 +1 irgsp CDS 172770 172921 . - 0 ID=CDS:Os01t0103000-01;Parent=transcript:Os01t0103000-01;protein_id=Os01t0103000-01 +1 irgsp CDS 173004 173072 . - 0 ID=CDS:Os01t0103000-01;Parent=transcript:Os01t0103000-01;protein_id=Os01t0103000-01 +1 irgsp exon 173004 173144 . - . Parent=transcript:Os01t0103000-01;Name=Os01t0103000-01.exon1;constitutive=1;ensembl_end_phase=0;ensembl_phase=-1;exon_id=Os01t0103000-01.exon1;rank=1 +1 irgsp five_prime_UTR 173073 173144 . - . Parent=transcript:Os01t0103000-01 +### +1 irgsp gene 178607 180575 . + . ID=gene:Os01g0103100;biotype=protein_coding;description=TGF-beta receptor%2C type I/II extracellular region family protein. (Os01t0103100-01)%3BSimilar to predicted protein. (Os01t0103100-02);gene_id=Os01g0103100;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 178607 180548 . + . ID=transcript:Os01t0103100-01;Parent=gene:Os01g0103100;biotype=protein_coding;transcript_id=Os01t0103100-01 +1 irgsp five_prime_UTR 178607 178641 . + . Parent=transcript:Os01t0103100-01 +1 irgsp exon 178607 180548 . + . Parent=transcript:Os01t0103100-01;Name=Os01t0103100-01.exon1;constitutive=0;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0103100-01.exon1;rank=1 +1 irgsp CDS 178642 180462 . + 0 ID=CDS:Os01t0103100-01;Parent=transcript:Os01t0103100-01;protein_id=Os01t0103100-01 +1 irgsp three_prime_UTR 180463 180548 . + . Parent=transcript:Os01t0103100-01 +1 irgsp mRNA 178652 180575 . + . ID=transcript:Os01t0103100-02;Parent=gene:Os01g0103100;biotype=protein_coding;transcript_id=Os01t0103100-02 +1 irgsp five_prime_UTR 178652 178677 . + . Parent=transcript:Os01t0103100-02 +1 irgsp exon 178652 180575 . + . Parent=transcript:Os01t0103100-02;Name=Os01t0103100-02.exon1;constitutive=0;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0103100-02.exon1;rank=1 +1 irgsp CDS 178678 180462 . + 0 ID=CDS:Os01t0103100-02;Parent=transcript:Os01t0103100-02;protein_id=Os01t0103100-02 +1 irgsp three_prime_UTR 180463 180575 . + . Parent=transcript:Os01t0103100-02 +### +1 irgsp gene 178815 180433 . - . ID=gene:Os01g0103075;biotype=protein_coding;description=Hypothetical protein. (Os01t0103075-00);gene_id=Os01g0103075;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 178815 180433 . - . ID=transcript:Os01t0103075-00;Parent=gene:Os01g0103075;biotype=protein_coding;transcript_id=Os01t0103075-00 +1 irgsp three_prime_UTR 178815 179511 . - . Parent=transcript:Os01t0103075-00 +1 irgsp exon 178815 180433 . - . Parent=transcript:Os01t0103075-00;Name=Os01t0103075-00.exon1;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0103075-00.exon1;rank=1 +1 irgsp CDS 179512 180054 . - 0 ID=CDS:Os01t0103075-00;Parent=transcript:Os01t0103075-00;protein_id=Os01t0103075-00 +1 irgsp five_prime_UTR 180055 180433 . - . Parent=transcript:Os01t0103075-00 +### +1 Ensembl_Plants ncRNA_gene 182074 182154 . + . ID=gene:ENSRNA049442722;Name=tRNA-Leu;biotype=tRNA;description=tRNA-Leu for anticodon AAG;gene_id=ENSRNA049442722;logic_name=trnascan_gene +1 Ensembl_Plants tRNA 182074 182154 . + . ID=transcript:ENSRNA049442722-T1;Parent=gene:ENSRNA049442722;biotype=tRNA;transcript_id=ENSRNA049442722-T1 +1 Ensembl_Plants exon 182074 182154 . + . Parent=transcript:ENSRNA049442722-T1;Name=ENSRNA049442722-E1;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=ENSRNA049442722-E1;rank=1 +### +1 irgsp gene 185189 185828 . - . ID=gene:Os01g0103400;biotype=protein_coding;description=Hypothetical gene. (Os01t0103400-01);gene_id=Os01g0103400;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 185189 185828 . - . ID=transcript:Os01t0103400-01;Parent=gene:Os01g0103400;biotype=protein_coding;transcript_id=Os01t0103400-01 +1 irgsp three_prime_UTR 185189 185434 . - . Parent=transcript:Os01t0103400-01 +1 irgsp exon 185189 185828 . - . Parent=transcript:Os01t0103400-01;Name=Os01t0103400-01.exon1;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0103400-01.exon1;rank=1 +1 irgsp CDS 185435 185827 . - 0 ID=CDS:Os01t0103400-01;Parent=transcript:Os01t0103400-01;protein_id=Os01t0103400-01 +1 irgsp five_prime_UTR 185828 185828 . - . Parent=transcript:Os01t0103400-01 +### +1 irgsp repeat_region 186000 186100 . + . ID=fakeRepeat2 +### +1 irgsp gene 186250 190904 . - . ID=gene:Os01g0103600;biotype=protein_coding;description=Similar to sterol-8%2C7-isomerase. (Os01t0103600-01)%3BEmopamil-binding family protein. (Os01t0103600-02);gene_id=Os01g0103600;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 186250 190262 . - . ID=transcript:Os01t0103600-02;Parent=gene:Os01g0103600;biotype=protein_coding;transcript_id=Os01t0103600-02 +1 irgsp three_prime_UTR 186250 186515 . - . Parent=transcript:Os01t0103600-02 +1 irgsp exon 186250 186771 . - . Parent=transcript:Os01t0103600-02;Name=Os01t0103600-02.exon4;constitutive=0;ensembl_end_phase=-1;ensembl_phase=2;exon_id=Os01t0103600-02.exon4;rank=4 +1 irgsp CDS 186516 186771 . - 1 ID=CDS:Os01t0103600-02;Parent=transcript:Os01t0103600-02;protein_id=Os01t0103600-02 +1 irgsp exon 189607 189715 . - . Parent=transcript:Os01t0103600-02;Name=Os01t0103600-02.exon3;constitutive=0;ensembl_end_phase=2;ensembl_phase=1;exon_id=Os01t0103600-02.exon3;rank=3 +1 irgsp CDS 189607 189715 . - 2 ID=CDS:Os01t0103600-02;Parent=transcript:Os01t0103600-02;protein_id=Os01t0103600-02 +1 irgsp exon 189841 189990 . - . Parent=transcript:Os01t0103600-02;Name=Os01t0103600-02.exon2;constitutive=1;ensembl_end_phase=1;ensembl_phase=1;exon_id=Os01t0103600-02.exon2;rank=2 +1 irgsp CDS 189841 189990 . - 2 ID=CDS:Os01t0103600-02;Parent=transcript:Os01t0103600-02;protein_id=Os01t0103600-02 +1 irgsp CDS 190087 190231 . - 0 ID=CDS:Os01t0103600-02;Parent=transcript:Os01t0103600-02;protein_id=Os01t0103600-02 +1 irgsp exon 190087 190262 . - . Parent=transcript:Os01t0103600-02;Name=Os01t0103600-02.exon1;constitutive=0;ensembl_end_phase=1;ensembl_phase=-1;exon_id=Os01t0103600-02.exon1;rank=1 +1 irgsp five_prime_UTR 190232 190262 . - . Parent=transcript:Os01t0103600-02 +1 irgsp mRNA 187345 190904 . - . ID=transcript:Os01t0103600-01;Parent=gene:Os01g0103600;biotype=protein_coding;transcript_id=Os01t0103600-01 +1 irgsp three_prime_UTR 187345 189395 . - . Parent=transcript:Os01t0103600-01 +1 irgsp exon 187345 189715 . - . Parent=transcript:Os01t0103600-01;Name=Os01t0103600-01.exon3;constitutive=0;ensembl_end_phase=-1;ensembl_phase=1;exon_id=Os01t0103600-01.exon3;rank=3 +1 irgsp CDS 189396 189715 . - 2 ID=CDS:Os01t0103600-01;Parent=transcript:Os01t0103600-01;protein_id=Os01t0103600-01 +1 irgsp exon 189841 189990 . - . Parent=transcript:Os01t0103600-01;Name=Os01t0103600-02.exon2;constitutive=1;ensembl_end_phase=1;ensembl_phase=1;exon_id=Os01t0103600-02.exon2;rank=2 +1 irgsp CDS 189841 189990 . - 2 ID=CDS:Os01t0103600-01;Parent=transcript:Os01t0103600-01;protein_id=Os01t0103600-01 +1 irgsp CDS 190087 190231 . - 0 ID=CDS:Os01t0103600-01;Parent=transcript:Os01t0103600-01;protein_id=Os01t0103600-01 +1 irgsp exon 190087 190904 . - . Parent=transcript:Os01t0103600-01;Name=Os01t0103600-01.exon1;constitutive=0;ensembl_end_phase=1;ensembl_phase=-1;exon_id=Os01t0103600-01.exon1;rank=1 +1 irgsp five_prime_UTR 190232 190904 . - . Parent=transcript:Os01t0103600-01 +### +1 irgsp gene 187545 188586 . + . ID=gene:Os01g0103650;biotype=protein_coding;description=Hypothetical gene. (Os01t0103650-00);gene_id=Os01g0103650;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 187545 188586 . + . ID=transcript:Os01t0103650-00;Parent=gene:Os01g0103650;biotype=protein_coding;transcript_id=Os01t0103650-00 +1 irgsp five_prime_UTR 187545 187546 . + . Parent=transcript:Os01t0103650-00 +1 irgsp exon 187545 188020 . + . Parent=transcript:Os01t0103650-00;Name=Os01t0103650-00.exon1;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0103650-00.exon1;rank=1 +1 irgsp CDS 187547 187768 . + 0 ID=CDS:Os01t0103650-00;Parent=transcript:Os01t0103650-00;protein_id=Os01t0103650-00 +1 irgsp three_prime_UTR 187769 188020 . + . Parent=transcript:Os01t0103650-00 +1 irgsp exon 188060 188385 . + . Parent=transcript:Os01t0103650-00;Name=Os01t0103650-00.exon2;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0103650-00.exon2;rank=2 +1 irgsp three_prime_UTR 188060 188385 . + . Parent=transcript:Os01t0103650-00 +1 irgsp exon 188455 188586 . + . Parent=transcript:Os01t0103650-00;Name=Os01t0103650-00.exon3;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0103650-00.exon3;rank=3 +1 irgsp three_prime_UTR 188455 188586 . + . Parent=transcript:Os01t0103650-00 +### +1 irgsp gene 191037 196287 . + . ID=gene:Os01g0103700;biotype=protein_coding;description=Conserved hypothetical protein. (Os01t0103700-01);gene_id=Os01g0103700;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 191037 196287 . + . ID=transcript:Os01t0103700-01;Parent=gene:Os01g0103700;biotype=protein_coding;transcript_id=Os01t0103700-01 +1 irgsp exon 191037 191161 . + . Parent=transcript:Os01t0103700-01;Name=Os01t0103700-01.exon1;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0103700-01.exon1;rank=1 +1 irgsp five_prime_UTR 191037 191161 . + . Parent=transcript:Os01t0103700-01 +1 irgsp five_prime_UTR 191625 191693 . + . Parent=transcript:Os01t0103700-01 +1 irgsp exon 191625 191705 . + . Parent=transcript:Os01t0103700-01;Name=Os01t0103700-01.exon2;constitutive=1;ensembl_end_phase=0;ensembl_phase=-1;exon_id=Os01t0103700-01.exon2;rank=2 +1 irgsp CDS 191694 191705 . + 0 ID=CDS:Os01t0103700-01;Parent=transcript:Os01t0103700-01;protein_id=Os01t0103700-01 +1 irgsp exon 192399 192506 . + . Parent=transcript:Os01t0103700-01;Name=Os01t0103700-01.exon3;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0103700-01.exon3;rank=3 +1 irgsp CDS 192399 192506 . + 0 ID=CDS:Os01t0103700-01;Parent=transcript:Os01t0103700-01;protein_id=Os01t0103700-01 +1 irgsp exon 192958 193161 . + . Parent=transcript:Os01t0103700-01;Name=Os01t0103700-01.exon4;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0103700-01.exon4;rank=4 +1 irgsp CDS 192958 193161 . + 0 ID=CDS:Os01t0103700-01;Parent=transcript:Os01t0103700-01;protein_id=Os01t0103700-01 +1 irgsp exon 193248 193356 . + . Parent=transcript:Os01t0103700-01;Name=Os01t0103700-01.exon5;constitutive=1;ensembl_end_phase=1;ensembl_phase=0;exon_id=Os01t0103700-01.exon5;rank=5 +1 irgsp CDS 193248 193356 . + 0 ID=CDS:Os01t0103700-01;Parent=transcript:Os01t0103700-01;protein_id=Os01t0103700-01 +1 irgsp CDS 193434 193507 . + 2 ID=CDS:Os01t0103700-01;Parent=transcript:Os01t0103700-01;protein_id=Os01t0103700-01 +1 irgsp exon 193434 196287 . + . Parent=transcript:Os01t0103700-01;Name=Os01t0103700-01.exon6;constitutive=1;ensembl_end_phase=-1;ensembl_phase=1;exon_id=Os01t0103700-01.exon6;rank=6 +1 irgsp three_prime_UTR 193508 196287 . + . Parent=transcript:Os01t0103700-01 +### +1 irgsp gene 197647 200803 . + . ID=gene:Os01g0103800;Name=OsDW1-01g;biotype=protein_coding;description=Conserved hypothetical protein. (Os01t0103800-01);gene_id=Os01g0103800;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 197647 200803 . + . ID=transcript:Os01t0103800-01;Parent=gene:Os01g0103800;biotype=protein_coding;transcript_id=Os01t0103800-01 +1 irgsp exon 197647 197838 . + . Parent=transcript:Os01t0103800-01;Name=Os01t0103800-01.exon1;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0103800-01.exon1;rank=1 +1 irgsp five_prime_UTR 197647 197838 . + . Parent=transcript:Os01t0103800-01 +1 irgsp five_prime_UTR 198034 198129 . + . Parent=transcript:Os01t0103800-01 +1 irgsp exon 198034 198225 . + . Parent=transcript:Os01t0103800-01;Name=Os01t0103800-01.exon2;constitutive=1;ensembl_end_phase=0;ensembl_phase=-1;exon_id=Os01t0103800-01.exon2;rank=2 +1 irgsp CDS 198130 198225 . + 0 ID=CDS:Os01t0103800-01;Parent=transcript:Os01t0103800-01;protein_id=Os01t0103800-01 +1 irgsp exon 198830 200036 . + . Parent=transcript:Os01t0103800-01;Name=Os01t0103800-01.exon3;constitutive=1;ensembl_end_phase=1;ensembl_phase=0;exon_id=Os01t0103800-01.exon3;rank=3 +1 irgsp CDS 198830 200036 . + 0 ID=CDS:Os01t0103800-01;Parent=transcript:Os01t0103800-01;protein_id=Os01t0103800-01 +1 irgsp CDS 200253 200479 . + 2 ID=CDS:Os01t0103800-01;Parent=transcript:Os01t0103800-01;protein_id=Os01t0103800-01 +1 irgsp exon 200253 200803 . + . Parent=transcript:Os01t0103800-01;Name=Os01t0103800-01.exon4;constitutive=1;ensembl_end_phase=-1;ensembl_phase=1;exon_id=Os01t0103800-01.exon4;rank=4 +1 irgsp three_prime_UTR 200480 200803 . + . Parent=transcript:Os01t0103800-01 +### +1 irgsp gene 201944 206202 . + . ID=gene:Os01g0103900;biotype=protein_coding;description=Polynucleotidyl transferase%2C Ribonuclease H fold domain containing protein. (Os01t0103900-01);gene_id=Os01g0103900;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 201944 206202 . + . ID=transcript:Os01t0103900-01;Parent=gene:Os01g0103900;biotype=protein_coding;transcript_id=Os01t0103900-01 +1 irgsp five_prime_UTR 201944 202041 . + . Parent=transcript:Os01t0103900-01 +1 irgsp exon 201944 202110 . + . Parent=transcript:Os01t0103900-01;Name=Os01t0103900-01.exon1;constitutive=1;ensembl_end_phase=0;ensembl_phase=-1;exon_id=Os01t0103900-01.exon1;rank=1 +1 irgsp CDS 202042 202110 . + 0 ID=CDS:Os01t0103900-01;Parent=transcript:Os01t0103900-01;protein_id=Os01t0103900-01 +1 irgsp exon 202252 202359 . + . Parent=transcript:Os01t0103900-01;Name=Os01t0103900-01.exon2;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0103900-01.exon2;rank=2 +1 irgsp CDS 202252 202359 . + 0 ID=CDS:Os01t0103900-01;Parent=transcript:Os01t0103900-01;protein_id=Os01t0103900-01 +1 irgsp exon 203007 203127 . + . Parent=transcript:Os01t0103900-01;Name=Os01t0103900-01.exon3;constitutive=1;ensembl_end_phase=1;ensembl_phase=0;exon_id=Os01t0103900-01.exon3;rank=3 +1 irgsp CDS 203007 203127 . + 0 ID=CDS:Os01t0103900-01;Parent=transcript:Os01t0103900-01;protein_id=Os01t0103900-01 +1 irgsp exon 203302 203429 . + . Parent=transcript:Os01t0103900-01;Name=Os01t0103900-01.exon4;constitutive=1;ensembl_end_phase=0;ensembl_phase=1;exon_id=Os01t0103900-01.exon4;rank=4 +1 irgsp CDS 203302 203429 . + 2 ID=CDS:Os01t0103900-01;Parent=transcript:Os01t0103900-01;protein_id=Os01t0103900-01 +1 irgsp exon 203511 203658 . + . Parent=transcript:Os01t0103900-01;Name=Os01t0103900-01.exon5;constitutive=1;ensembl_end_phase=1;ensembl_phase=0;exon_id=Os01t0103900-01.exon5;rank=5 +1 irgsp CDS 203511 203658 . + 0 ID=CDS:Os01t0103900-01;Parent=transcript:Os01t0103900-01;protein_id=Os01t0103900-01 +1 irgsp exon 203760 203938 . + . Parent=transcript:Os01t0103900-01;Name=Os01t0103900-01.exon6;constitutive=1;ensembl_end_phase=0;ensembl_phase=1;exon_id=Os01t0103900-01.exon6;rank=6 +1 irgsp CDS 203760 203938 . + 2 ID=CDS:Os01t0103900-01;Parent=transcript:Os01t0103900-01;protein_id=Os01t0103900-01 +1 irgsp exon 204203 204440 . + . Parent=transcript:Os01t0103900-01;Name=Os01t0103900-01.exon7;constitutive=1;ensembl_end_phase=1;ensembl_phase=0;exon_id=Os01t0103900-01.exon7;rank=7 +1 irgsp CDS 204203 204440 . + 0 ID=CDS:Os01t0103900-01;Parent=transcript:Os01t0103900-01;protein_id=Os01t0103900-01 +1 irgsp exon 204543 204635 . + . Parent=transcript:Os01t0103900-01;Name=Os01t0103900-01.exon8;constitutive=1;ensembl_end_phase=1;ensembl_phase=1;exon_id=Os01t0103900-01.exon8;rank=8 +1 irgsp CDS 204543 204635 . + 2 ID=CDS:Os01t0103900-01;Parent=transcript:Os01t0103900-01;protein_id=Os01t0103900-01 +1 irgsp exon 204730 204875 . + . Parent=transcript:Os01t0103900-01;Name=Os01t0103900-01.exon9;constitutive=1;ensembl_end_phase=0;ensembl_phase=1;exon_id=Os01t0103900-01.exon9;rank=9 +1 irgsp CDS 204730 204875 . + 2 ID=CDS:Os01t0103900-01;Parent=transcript:Os01t0103900-01;protein_id=Os01t0103900-01 +1 irgsp exon 205042 205149 . + . Parent=transcript:Os01t0103900-01;Name=Os01t0103900-01.exon10;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0103900-01.exon10;rank=10 +1 irgsp CDS 205042 205149 . + 0 ID=CDS:Os01t0103900-01;Parent=transcript:Os01t0103900-01;protein_id=Os01t0103900-01 +1 irgsp exon 205290 205378 . + . Parent=transcript:Os01t0103900-01;Name=Os01t0103900-01.exon11;constitutive=1;ensembl_end_phase=2;ensembl_phase=0;exon_id=Os01t0103900-01.exon11;rank=11 +1 irgsp CDS 205290 205378 . + 0 ID=CDS:Os01t0103900-01;Parent=transcript:Os01t0103900-01;protein_id=Os01t0103900-01 +1 irgsp CDS 205534 205543 . + 1 ID=CDS:Os01t0103900-01;Parent=transcript:Os01t0103900-01;protein_id=Os01t0103900-01 +1 irgsp exon 205534 206202 . + . Parent=transcript:Os01t0103900-01;Name=Os01t0103900-01.exon12;constitutive=1;ensembl_end_phase=-1;ensembl_phase=2;exon_id=Os01t0103900-01.exon12;rank=12 +1 irgsp three_prime_UTR 205544 206202 . + . Parent=transcript:Os01t0103900-01 +### +1 irgsp gene 206131 209606 . - . ID=gene:Os01g0104000;biotype=protein_coding;description=C-type lectin domain containing protein. (Os01t0104000-01)%3BSimilar to predicted protein. (Os01t0104000-02);gene_id=Os01g0104000;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 206131 209581 . - . ID=transcript:Os01t0104000-02;Parent=gene:Os01g0104000;biotype=protein_coding;transcript_id=Os01t0104000-02 +1 irgsp three_prime_UTR 206131 206449 . - . Parent=transcript:Os01t0104000-02 +1 irgsp exon 206131 207029 . - . Parent=transcript:Os01t0104000-02;Name=Os01t0104000-02.exon4;constitutive=0;ensembl_end_phase=-1;ensembl_phase=2;exon_id=Os01t0104000-02.exon4;rank=4 +1 irgsp CDS 206450 207029 . - 1 ID=CDS:Os01t0104000-02;Parent=transcript:Os01t0104000-02;protein_id=Os01t0104000-02 +1 irgsp exon 207706 208273 . - . Parent=transcript:Os01t0104000-02;Name=Os01t0104000-02.exon3;constitutive=0;ensembl_end_phase=2;ensembl_phase=1;exon_id=Os01t0104000-02.exon3;rank=3 +1 irgsp CDS 207706 208273 . - 2 ID=CDS:Os01t0104000-02;Parent=transcript:Os01t0104000-02;protein_id=Os01t0104000-02 +1 irgsp exon 208408 208836 . - . Parent=transcript:Os01t0104000-02;Name=Os01t0104000-01.exon2;constitutive=1;ensembl_end_phase=1;ensembl_phase=1;exon_id=Os01t0104000-01.exon2;rank=2 +1 irgsp CDS 208408 208836 . - 2 ID=CDS:Os01t0104000-02;Parent=transcript:Os01t0104000-02;protein_id=Os01t0104000-02 +1 irgsp CDS 209438 209525 . - 0 ID=CDS:Os01t0104000-02;Parent=transcript:Os01t0104000-02;protein_id=Os01t0104000-02 +1 irgsp exon 209438 209581 . - . Parent=transcript:Os01t0104000-02;Name=Os01t0104000-02.exon1;constitutive=0;ensembl_end_phase=1;ensembl_phase=-1;exon_id=Os01t0104000-02.exon1;rank=1 +1 irgsp five_prime_UTR 209526 209581 . - . Parent=transcript:Os01t0104000-02 +1 irgsp mRNA 206134 209606 . - . ID=transcript:Os01t0104000-01;Parent=gene:Os01g0104000;biotype=protein_coding;transcript_id=Os01t0104000-01 +1 irgsp three_prime_UTR 206134 206449 . - . Parent=transcript:Os01t0104000-01 +1 irgsp exon 206134 207029 . - . Parent=transcript:Os01t0104000-01;Name=Os01t0104000-01.exon4;constitutive=0;ensembl_end_phase=-1;ensembl_phase=2;exon_id=Os01t0104000-01.exon4;rank=4 +1 irgsp CDS 206450 207029 . - 1 ID=CDS:Os01t0104000-01;Parent=transcript:Os01t0104000-01;protein_id=Os01t0104000-01 +1 irgsp exon 207706 208276 . - . Parent=transcript:Os01t0104000-01;Name=Os01t0104000-01.exon3;constitutive=0;ensembl_end_phase=2;ensembl_phase=1;exon_id=Os01t0104000-01.exon3;rank=3 +1 irgsp CDS 207706 208276 . - 2 ID=CDS:Os01t0104000-01;Parent=transcript:Os01t0104000-01;protein_id=Os01t0104000-01 +1 irgsp exon 208408 208836 . - . Parent=transcript:Os01t0104000-01;Name=Os01t0104000-01.exon2;constitutive=1;ensembl_end_phase=1;ensembl_phase=1;exon_id=Os01t0104000-01.exon2;rank=2 +1 irgsp CDS 208408 208836 . - 2 ID=CDS:Os01t0104000-01;Parent=transcript:Os01t0104000-01;protein_id=Os01t0104000-01 +1 irgsp CDS 209438 209525 . - 0 ID=CDS:Os01t0104000-01;Parent=transcript:Os01t0104000-01;protein_id=Os01t0104000-01 +1 irgsp exon 209438 209606 . - . Parent=transcript:Os01t0104000-01;Name=Os01t0104000-01.exon1;constitutive=0;ensembl_end_phase=1;ensembl_phase=-1;exon_id=Os01t0104000-01.exon1;rank=1 +1 irgsp five_prime_UTR 209526 209606 . - . Parent=transcript:Os01t0104000-01 +### +1 irgsp gene 209771 214173 . + . ID=gene:Os01g0104100;Name=cold-inducible%2C cold-inducible zinc finger protein;biotype=protein_coding;description=Similar to protein binding / zinc ion binding. (Os01t0104100-01)%3BSimilar to protein binding / zinc ion binding. (Os01t0104100-02);gene_id=Os01g0104100;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 209771 214173 . + . ID=transcript:Os01t0104100-01;Parent=gene:Os01g0104100;biotype=protein_coding;transcript_id=Os01t0104100-01 +1 irgsp exon 209771 209896 . + . Parent=transcript:Os01t0104100-01;Name=Os01t0104100-01.exon1;constitutive=0;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0104100-01.exon1;rank=1 +1 irgsp CDS 209771 209896 . + 0 ID=CDS:Os01t0104100-01;Parent=transcript:Os01t0104100-01;protein_id=Os01t0104100-01 +1 irgsp exon 210244 210563 . + . Parent=transcript:Os01t0104100-01;Name=Os01t0104100-01.exon2;constitutive=1;ensembl_end_phase=2;ensembl_phase=0;exon_id=Os01t0104100-01.exon2;rank=2 +1 irgsp CDS 210244 210563 . + 0 ID=CDS:Os01t0104100-01;Parent=transcript:Os01t0104100-01;protein_id=Os01t0104100-01 +1 irgsp exon 210659 210890 . + . Parent=transcript:Os01t0104100-01;Name=Os01t0104100-01.exon3;constitutive=1;ensembl_end_phase=0;ensembl_phase=2;exon_id=Os01t0104100-01.exon3;rank=3 +1 irgsp CDS 210659 210890 . + 1 ID=CDS:Os01t0104100-01;Parent=transcript:Os01t0104100-01;protein_id=Os01t0104100-01 +1 irgsp exon 211015 211160 . + . Parent=transcript:Os01t0104100-01;Name=Os01t0104100-01.exon4;constitutive=1;ensembl_end_phase=2;ensembl_phase=0;exon_id=Os01t0104100-01.exon4;rank=4 +1 irgsp CDS 211015 211160 . + 0 ID=CDS:Os01t0104100-01;Parent=transcript:Os01t0104100-01;protein_id=Os01t0104100-01 +1 irgsp exon 212265 212352 . + . Parent=transcript:Os01t0104100-01;Name=Os01t0104100-01.exon5;constitutive=1;ensembl_end_phase=0;ensembl_phase=2;exon_id=Os01t0104100-01.exon5;rank=5 +1 irgsp CDS 212265 212352 . + 1 ID=CDS:Os01t0104100-01;Parent=transcript:Os01t0104100-01;protein_id=Os01t0104100-01 +1 irgsp exon 212433 212579 . + . Parent=transcript:Os01t0104100-01;Name=Os01t0104100-01.exon6;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0104100-01.exon6;rank=6 +1 irgsp CDS 212433 212579 . + 0 ID=CDS:Os01t0104100-01;Parent=transcript:Os01t0104100-01;protein_id=Os01t0104100-01 +1 irgsp exon 213490 213639 . + . Parent=transcript:Os01t0104100-01;Name=Os01t0104100-01.exon7;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0104100-01.exon7;rank=7 +1 irgsp CDS 213490 213639 . + 0 ID=CDS:Os01t0104100-01;Parent=transcript:Os01t0104100-01;protein_id=Os01t0104100-01 +1 irgsp CDS 213741 213788 . + 0 ID=CDS:Os01t0104100-01;Parent=transcript:Os01t0104100-01;protein_id=Os01t0104100-01 +1 irgsp exon 213741 214173 . + . Parent=transcript:Os01t0104100-01;Name=Os01t0104100-01.exon8;constitutive=0;ensembl_end_phase=-1;ensembl_phase=0;exon_id=Os01t0104100-01.exon8;rank=8 +1 irgsp three_prime_UTR 213789 214173 . + . Parent=transcript:Os01t0104100-01 +1 irgsp mRNA 209794 214147 . + . ID=transcript:Os01t0104100-02;Parent=gene:Os01g0104100;biotype=protein_coding;transcript_id=Os01t0104100-02 +1 irgsp five_prime_UTR 209794 209794 . + . Parent=transcript:Os01t0104100-02 +1 irgsp exon 209794 209896 . + . Parent=transcript:Os01t0104100-02;Name=Os01t0104100-02.exon1;constitutive=0;ensembl_end_phase=0;ensembl_phase=-1;exon_id=Os01t0104100-02.exon1;rank=1 +1 irgsp CDS 209795 209896 . + 0 ID=CDS:Os01t0104100-02;Parent=transcript:Os01t0104100-02;protein_id=Os01t0104100-02 +1 irgsp exon 210244 210563 . + . Parent=transcript:Os01t0104100-02;Name=Os01t0104100-01.exon2;constitutive=1;ensembl_end_phase=2;ensembl_phase=0;exon_id=Os01t0104100-01.exon2;rank=2 +1 irgsp CDS 210244 210563 . + 0 ID=CDS:Os01t0104100-02;Parent=transcript:Os01t0104100-02;protein_id=Os01t0104100-02 +1 irgsp exon 210659 210890 . + . Parent=transcript:Os01t0104100-02;Name=Os01t0104100-01.exon3;constitutive=1;ensembl_end_phase=0;ensembl_phase=2;exon_id=Os01t0104100-01.exon3;rank=3 +1 irgsp CDS 210659 210890 . + 1 ID=CDS:Os01t0104100-02;Parent=transcript:Os01t0104100-02;protein_id=Os01t0104100-02 +1 irgsp exon 211015 211160 . + . Parent=transcript:Os01t0104100-02;Name=Os01t0104100-01.exon4;constitutive=1;ensembl_end_phase=2;ensembl_phase=0;exon_id=Os01t0104100-01.exon4;rank=4 +1 irgsp CDS 211015 211160 . + 0 ID=CDS:Os01t0104100-02;Parent=transcript:Os01t0104100-02;protein_id=Os01t0104100-02 +1 irgsp exon 212265 212352 . + . Parent=transcript:Os01t0104100-02;Name=Os01t0104100-01.exon5;constitutive=1;ensembl_end_phase=0;ensembl_phase=2;exon_id=Os01t0104100-01.exon5;rank=5 +1 irgsp CDS 212265 212352 . + 1 ID=CDS:Os01t0104100-02;Parent=transcript:Os01t0104100-02;protein_id=Os01t0104100-02 +1 irgsp exon 212433 212579 . + . Parent=transcript:Os01t0104100-02;Name=Os01t0104100-01.exon6;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0104100-01.exon6;rank=6 +1 irgsp CDS 212433 212579 . + 0 ID=CDS:Os01t0104100-02;Parent=transcript:Os01t0104100-02;protein_id=Os01t0104100-02 +1 irgsp exon 213490 213639 . + . Parent=transcript:Os01t0104100-02;Name=Os01t0104100-01.exon7;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0104100-01.exon7;rank=7 +1 irgsp CDS 213490 213639 . + 0 ID=CDS:Os01t0104100-02;Parent=transcript:Os01t0104100-02;protein_id=Os01t0104100-02 +1 irgsp CDS 213741 213788 . + 0 ID=CDS:Os01t0104100-02;Parent=transcript:Os01t0104100-02;protein_id=Os01t0104100-02 +1 irgsp exon 213741 214147 . + . Parent=transcript:Os01t0104100-02;Name=Os01t0104100-02.exon8;constitutive=0;ensembl_end_phase=-1;ensembl_phase=0;exon_id=Os01t0104100-02.exon8;rank=8 +1 irgsp three_prime_UTR 213789 214147 . + . Parent=transcript:Os01t0104100-02 +### +1 irgsp gene 216212 217345 . + . ID=gene:Os01g0104200;Name=NAC DOMAIN-CONTAINING PROTEIN 16;biotype=protein_coding;description=No apical meristem (NAM) protein domain containing protein. (Os01t0104200-00);gene_id=Os01g0104200;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 216212 217345 . + . ID=transcript:Os01t0104200-00;Parent=gene:Os01g0104200;biotype=protein_coding;transcript_id=Os01t0104200-00 +1 irgsp exon 216212 216769 . + . Parent=transcript:Os01t0104200-00;Name=Os01t0104200-00.exon1;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0104200-00.exon1;rank=1 +1 irgsp CDS 216212 216769 . + 0 ID=CDS:Os01t0104200-00;Parent=transcript:Os01t0104200-00;protein_id=Os01t0104200-00 +1 irgsp exon 216884 217345 . + . Parent=transcript:Os01t0104200-00;Name=Os01t0104200-00.exon2;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0104200-00.exon2;rank=2 +1 irgsp CDS 216884 217345 . + 0 ID=CDS:Os01t0104200-00;Parent=transcript:Os01t0104200-00;protein_id=Os01t0104200-00 +### +1 irgsp gene 226897 229301 . + . ID=gene:Os01g0104400;biotype=protein_coding;description=Ricin B-related lectin domain containing protein. (Os01t0104400-01)%3BRicin B-related lectin domain containing protein. (Os01t0104400-02)%3BRicin B-related lectin domain containing protein. (Os01t0104400-03);gene_id=Os01g0104400;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 226897 229229 . + . ID=transcript:Os01t0104400-01;Parent=gene:Os01g0104400;biotype=protein_coding;transcript_id=Os01t0104400-01 +1 irgsp five_prime_UTR 226897 227181 . + . Parent=transcript:Os01t0104400-01 +1 irgsp exon 226897 227634 . + . Parent=transcript:Os01t0104400-01;Name=Os01t0104400-01.exon1;constitutive=0;ensembl_end_phase=0;ensembl_phase=-1;exon_id=Os01t0104400-01.exon1;rank=1 +1 irgsp CDS 227182 227634 . + 0 ID=CDS:Os01t0104400-01;Parent=transcript:Os01t0104400-01;protein_id=Os01t0104400-01 +1 irgsp exon 227742 227864 . + . Parent=transcript:Os01t0104400-01;Name=Os01t0104400-03.exon2;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0104400-03.exon2;rank=2 +1 irgsp CDS 227742 227864 . + 0 ID=CDS:Os01t0104400-01;Parent=transcript:Os01t0104400-01;protein_id=Os01t0104400-01 +1 irgsp exon 228557 228785 . + . Parent=transcript:Os01t0104400-01;Name=Os01t0104400-03.exon3;constitutive=1;ensembl_end_phase=1;ensembl_phase=0;exon_id=Os01t0104400-03.exon3;rank=3 +1 irgsp CDS 228557 228785 . + 0 ID=CDS:Os01t0104400-01;Parent=transcript:Os01t0104400-01;protein_id=Os01t0104400-01 +1 irgsp CDS 228930 228931 . + 2 ID=CDS:Os01t0104400-01;Parent=transcript:Os01t0104400-01;protein_id=Os01t0104400-01 +1 irgsp exon 228930 229229 . + . Parent=transcript:Os01t0104400-01;Name=Os01t0104400-01.exon4;constitutive=0;ensembl_end_phase=-1;ensembl_phase=1;exon_id=Os01t0104400-01.exon4;rank=4 +1 irgsp three_prime_UTR 228932 229229 . + . Parent=transcript:Os01t0104400-01 +1 irgsp mRNA 227139 229301 . + . ID=transcript:Os01t0104400-02;Parent=gene:Os01g0104400;biotype=protein_coding;transcript_id=Os01t0104400-02 +1 irgsp five_prime_UTR 227139 227181 . + . Parent=transcript:Os01t0104400-02 +1 irgsp exon 227139 227634 . + . Parent=transcript:Os01t0104400-02;Name=Os01t0104400-02.exon1;constitutive=0;ensembl_end_phase=0;ensembl_phase=-1;exon_id=Os01t0104400-02.exon1;rank=1 +1 irgsp CDS 227182 227634 . + 0 ID=CDS:Os01t0104400-02;Parent=transcript:Os01t0104400-02;protein_id=Os01t0104400-02 +1 irgsp exon 227742 227864 . + . Parent=transcript:Os01t0104400-02;Name=Os01t0104400-03.exon2;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0104400-03.exon2;rank=2 +1 irgsp CDS 227742 227864 . + 0 ID=CDS:Os01t0104400-02;Parent=transcript:Os01t0104400-02;protein_id=Os01t0104400-02 +1 irgsp exon 228557 228785 . + . Parent=transcript:Os01t0104400-02;Name=Os01t0104400-03.exon3;constitutive=1;ensembl_end_phase=1;ensembl_phase=0;exon_id=Os01t0104400-03.exon3;rank=3 +1 irgsp CDS 228557 228785 . + 0 ID=CDS:Os01t0104400-02;Parent=transcript:Os01t0104400-02;protein_id=Os01t0104400-02 +1 irgsp CDS 228930 228931 . + 2 ID=CDS:Os01t0104400-02;Parent=transcript:Os01t0104400-02;protein_id=Os01t0104400-02 +1 irgsp exon 228930 229301 . + . Parent=transcript:Os01t0104400-02;Name=Os01t0104400-02.exon4;constitutive=0;ensembl_end_phase=-1;ensembl_phase=1;exon_id=Os01t0104400-02.exon4;rank=4 +1 irgsp three_prime_UTR 228932 229301 . + . Parent=transcript:Os01t0104400-02 +1 irgsp mRNA 227179 229214 . + . ID=transcript:Os01t0104400-03;Parent=gene:Os01g0104400;biotype=protein_coding;transcript_id=Os01t0104400-03 +1 irgsp five_prime_UTR 227179 227181 . + . Parent=transcript:Os01t0104400-03 +1 irgsp exon 227179 227634 . + . Parent=transcript:Os01t0104400-03;Name=Os01t0104400-03.exon1;constitutive=0;ensembl_end_phase=0;ensembl_phase=-1;exon_id=Os01t0104400-03.exon1;rank=1 +1 irgsp CDS 227182 227634 . + 0 ID=CDS:Os01t0104400-03;Parent=transcript:Os01t0104400-03;protein_id=Os01t0104400-03 +1 irgsp exon 227742 227864 . + . Parent=transcript:Os01t0104400-03;Name=Os01t0104400-03.exon2;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0104400-03.exon2;rank=2 +1 irgsp CDS 227742 227864 . + 0 ID=CDS:Os01t0104400-03;Parent=transcript:Os01t0104400-03;protein_id=Os01t0104400-03 +1 irgsp exon 228557 228785 . + . Parent=transcript:Os01t0104400-03;Name=Os01t0104400-03.exon3;constitutive=1;ensembl_end_phase=1;ensembl_phase=0;exon_id=Os01t0104400-03.exon3;rank=3 +1 irgsp CDS 228557 228785 . + 0 ID=CDS:Os01t0104400-03;Parent=transcript:Os01t0104400-03;protein_id=Os01t0104400-03 +1 irgsp CDS 228930 228931 . + 2 ID=CDS:Os01t0104400-03;Parent=transcript:Os01t0104400-03;protein_id=Os01t0104400-03 +1 irgsp exon 228930 229214 . + . Parent=transcript:Os01t0104400-03;Name=Os01t0104400-03.exon4;constitutive=0;ensembl_end_phase=-1;ensembl_phase=1;exon_id=Os01t0104400-03.exon4;rank=4 +1 irgsp three_prime_UTR 228932 229214 . + . Parent=transcript:Os01t0104400-03 +### +1 irgsp gene 241680 243440 . + . ID=gene:Os01g0104500;Name=NAC DOMAIN-CONTAINING PROTEIN 20;biotype=protein_coding;description=No apical meristem (NAM) protein domain containing protein. (Os01t0104500-01);gene_id=Os01g0104500;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 241680 243440 . + . ID=transcript:Os01t0104500-01;Parent=gene:Os01g0104500;biotype=protein_coding;transcript_id=Os01t0104500-01 +1 irgsp exon 241680 241702 . + . Parent=transcript:Os01t0104500-01;Name=Os01t0104500-01.exon1;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0104500-01.exon1;rank=1 +1 irgsp five_prime_UTR 241680 241702 . + . Parent=transcript:Os01t0104500-01 +1 irgsp five_prime_UTR 241866 241907 . + . Parent=transcript:Os01t0104500-01 +1 irgsp exon 241866 242091 . + . Parent=transcript:Os01t0104500-01;Name=Os01t0104500-01.exon2;constitutive=1;ensembl_end_phase=1;ensembl_phase=-1;exon_id=Os01t0104500-01.exon2;rank=2 +1 irgsp CDS 241908 242091 . + 0 ID=CDS:Os01t0104500-01;Parent=transcript:Os01t0104500-01;protein_id=Os01t0104500-01 +1 irgsp CDS 242199 242977 . + 2 ID=CDS:Os01t0104500-01;Parent=transcript:Os01t0104500-01;protein_id=Os01t0104500-01 +1 irgsp exon 242199 243440 . + . Parent=transcript:Os01t0104500-01;Name=Os01t0104500-01.exon3;constitutive=1;ensembl_end_phase=-1;ensembl_phase=1;exon_id=Os01t0104500-01.exon3;rank=3 +1 irgsp three_prime_UTR 242978 243440 . + . Parent=transcript:Os01t0104500-01 +### +1 irgsp gene 248828 256872 . - . ID=gene:Os01g0104600;Name=DE-ETIOLATED1;biotype=protein_coding;description=Homolog of Arabidopsis DE-ETIOLATED1 (DET1)%2C Modulation of the ABA signaling pathway and ABA biosynthesis%2C Regulation of chlorophyll content (Os01t0104600-01)%3BSimilar to Light-mediated development protein DET1 (Deetiolated1 homolog) (tDET1) (High pigmentation protein 2) (Protein dark green). (Os01t0104600-02);gene_id=Os01g0104600;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 248828 256571 . - . ID=transcript:Os01t0104600-02;Parent=gene:Os01g0104600;biotype=protein_coding;transcript_id=Os01t0104600-02 +1 irgsp three_prime_UTR 248828 248970 . - . Parent=transcript:Os01t0104600-02 +1 irgsp exon 248828 249107 . - . Parent=transcript:Os01t0104600-02;Name=Os01t0104600-01.exon11;constitutive=1;ensembl_end_phase=-1;ensembl_phase=1;exon_id=Os01t0104600-01.exon11;rank=11 +1 irgsp CDS 248971 249107 . - 2 ID=CDS:Os01t0104600-02;Parent=transcript:Os01t0104600-02;protein_id=Os01t0104600-02 +1 irgsp exon 249369 249468 . - . Parent=transcript:Os01t0104600-02;Name=Os01t0104600-01.exon10;constitutive=1;ensembl_end_phase=1;ensembl_phase=0;exon_id=Os01t0104600-01.exon10;rank=10 +1 irgsp CDS 249369 249468 . - 0 ID=CDS:Os01t0104600-02;Parent=transcript:Os01t0104600-02;protein_id=Os01t0104600-02 +1 irgsp exon 249861 249956 . - . Parent=transcript:Os01t0104600-02;Name=Os01t0104600-01.exon9;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0104600-01.exon9;rank=9 +1 irgsp CDS 249861 249956 . - 0 ID=CDS:Os01t0104600-02;Parent=transcript:Os01t0104600-02;protein_id=Os01t0104600-02 +1 irgsp exon 250617 250781 . - . Parent=transcript:Os01t0104600-02;Name=Os01t0104600-01.exon8;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0104600-01.exon8;rank=8 +1 irgsp CDS 250617 250781 . - 0 ID=CDS:Os01t0104600-02;Parent=transcript:Os01t0104600-02;protein_id=Os01t0104600-02 +1 irgsp exon 250860 250940 . - . Parent=transcript:Os01t0104600-02;Name=Os01t0104600-01.exon7;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0104600-01.exon7;rank=7 +1 irgsp CDS 250860 250940 . - 0 ID=CDS:Os01t0104600-02;Parent=transcript:Os01t0104600-02;protein_id=Os01t0104600-02 +1 irgsp exon 251026 251082 . - . Parent=transcript:Os01t0104600-02;Name=Os01t0104600-01.exon6;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0104600-01.exon6;rank=6 +1 irgsp CDS 251026 251082 . - 0 ID=CDS:Os01t0104600-02;Parent=transcript:Os01t0104600-02;protein_id=Os01t0104600-02 +1 irgsp exon 251316 251384 . - . Parent=transcript:Os01t0104600-02;Name=Os01t0104600-01.exon5;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0104600-01.exon5;rank=5 +1 irgsp CDS 251316 251384 . - 0 ID=CDS:Os01t0104600-02;Parent=transcript:Os01t0104600-02;protein_id=Os01t0104600-02 +1 irgsp exon 251695 251790 . - . Parent=transcript:Os01t0104600-02;Name=Os01t0104600-01.exon4;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0104600-01.exon4;rank=4 +1 irgsp CDS 251695 251790 . - 0 ID=CDS:Os01t0104600-02;Parent=transcript:Os01t0104600-02;protein_id=Os01t0104600-02 +1 irgsp exon 255325 255553 . - . Parent=transcript:Os01t0104600-02;Name=Os01t0104600-01.exon3;constitutive=1;ensembl_end_phase=0;ensembl_phase=2;exon_id=Os01t0104600-01.exon3;rank=3 +1 irgsp CDS 255325 255553 . - 1 ID=CDS:Os01t0104600-02;Parent=transcript:Os01t0104600-02;protein_id=Os01t0104600-02 +1 irgsp exon 255674 256098 . - . Parent=transcript:Os01t0104600-02;Name=Os01t0104600-01.exon2;constitutive=1;ensembl_end_phase=2;ensembl_phase=0;exon_id=Os01t0104600-01.exon2;rank=2 +1 irgsp CDS 255674 256098 . - 0 ID=CDS:Os01t0104600-02;Parent=transcript:Os01t0104600-02;protein_id=Os01t0104600-02 +1 irgsp CDS 256361 256441 . - 0 ID=CDS:Os01t0104600-02;Parent=transcript:Os01t0104600-02;protein_id=Os01t0104600-02 +1 irgsp exon 256361 256571 . - . Parent=transcript:Os01t0104600-02;Name=Os01t0104600-02.exon1;constitutive=0;ensembl_end_phase=0;ensembl_phase=-1;exon_id=Os01t0104600-02.exon1;rank=1 +1 irgsp five_prime_UTR 256442 256571 . - . Parent=transcript:Os01t0104600-02 +1 irgsp mRNA 248828 256872 . - . ID=transcript:Os01t0104600-01;Parent=gene:Os01g0104600;biotype=protein_coding;transcript_id=Os01t0104600-01 +1 irgsp three_prime_UTR 248828 248970 . - . Parent=transcript:Os01t0104600-01 +1 irgsp exon 248828 249107 . - . Parent=transcript:Os01t0104600-01;Name=Os01t0104600-01.exon11;constitutive=1;ensembl_end_phase=-1;ensembl_phase=1;exon_id=Os01t0104600-01.exon11;rank=11 +1 irgsp CDS 248971 249107 . - 2 ID=CDS:Os01t0104600-01;Parent=transcript:Os01t0104600-01;protein_id=Os01t0104600-01 +1 irgsp exon 249369 249468 . - . Parent=transcript:Os01t0104600-01;Name=Os01t0104600-01.exon10;constitutive=1;ensembl_end_phase=1;ensembl_phase=0;exon_id=Os01t0104600-01.exon10;rank=10 +1 irgsp CDS 249369 249468 . - 0 ID=CDS:Os01t0104600-01;Parent=transcript:Os01t0104600-01;protein_id=Os01t0104600-01 +1 irgsp exon 249861 249956 . - . Parent=transcript:Os01t0104600-01;Name=Os01t0104600-01.exon9;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0104600-01.exon9;rank=9 +1 irgsp CDS 249861 249956 . - 0 ID=CDS:Os01t0104600-01;Parent=transcript:Os01t0104600-01;protein_id=Os01t0104600-01 +1 irgsp exon 250617 250781 . - . Parent=transcript:Os01t0104600-01;Name=Os01t0104600-01.exon8;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0104600-01.exon8;rank=8 +1 irgsp CDS 250617 250781 . - 0 ID=CDS:Os01t0104600-01;Parent=transcript:Os01t0104600-01;protein_id=Os01t0104600-01 +1 irgsp exon 250860 250940 . - . Parent=transcript:Os01t0104600-01;Name=Os01t0104600-01.exon7;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0104600-01.exon7;rank=7 +1 irgsp CDS 250860 250940 . - 0 ID=CDS:Os01t0104600-01;Parent=transcript:Os01t0104600-01;protein_id=Os01t0104600-01 +1 irgsp exon 251026 251082 . - . Parent=transcript:Os01t0104600-01;Name=Os01t0104600-01.exon6;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0104600-01.exon6;rank=6 +1 irgsp CDS 251026 251082 . - 0 ID=CDS:Os01t0104600-01;Parent=transcript:Os01t0104600-01;protein_id=Os01t0104600-01 +1 irgsp exon 251316 251384 . - . Parent=transcript:Os01t0104600-01;Name=Os01t0104600-01.exon5;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0104600-01.exon5;rank=5 +1 irgsp CDS 251316 251384 . - 0 ID=CDS:Os01t0104600-01;Parent=transcript:Os01t0104600-01;protein_id=Os01t0104600-01 +1 irgsp exon 251695 251790 . - . Parent=transcript:Os01t0104600-01;Name=Os01t0104600-01.exon4;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0104600-01.exon4;rank=4 +1 irgsp CDS 251695 251790 . - 0 ID=CDS:Os01t0104600-01;Parent=transcript:Os01t0104600-01;protein_id=Os01t0104600-01 +1 irgsp exon 255325 255553 . - . Parent=transcript:Os01t0104600-01;Name=Os01t0104600-01.exon3;constitutive=1;ensembl_end_phase=0;ensembl_phase=2;exon_id=Os01t0104600-01.exon3;rank=3 +1 irgsp CDS 255325 255553 . - 1 ID=CDS:Os01t0104600-01;Parent=transcript:Os01t0104600-01;protein_id=Os01t0104600-01 +1 irgsp exon 255674 256098 . - . Parent=transcript:Os01t0104600-01;Name=Os01t0104600-01.exon2;constitutive=1;ensembl_end_phase=2;ensembl_phase=0;exon_id=Os01t0104600-01.exon2;rank=2 +1 irgsp CDS 255674 256098 . - 0 ID=CDS:Os01t0104600-01;Parent=transcript:Os01t0104600-01;protein_id=Os01t0104600-01 +1 irgsp CDS 256361 256441 . - 0 ID=CDS:Os01t0104600-01;Parent=transcript:Os01t0104600-01;protein_id=Os01t0104600-01 +1 irgsp exon 256361 256872 . - . Parent=transcript:Os01t0104600-01;Name=Os01t0104600-01.exon1;constitutive=0;ensembl_end_phase=0;ensembl_phase=-1;exon_id=Os01t0104600-01.exon1;rank=1 +1 irgsp five_prime_UTR 256442 256872 . - . Parent=transcript:Os01t0104600-01 +### +1 irgsp gene 261530 268145 . + . ID=gene:Os01g0104800;biotype=protein_coding;description=Sas10/Utp3 family protein. (Os01t0104800-01)%3BHypothetical conserved gene. (Os01t0104800-02);gene_id=Os01g0104800;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 261530 268145 . + . ID=transcript:Os01t0104800-01;Parent=gene:Os01g0104800;biotype=protein_coding;transcript_id=Os01t0104800-01 +1 irgsp five_prime_UTR 261530 261561 . + . Parent=transcript:Os01t0104800-01 +1 irgsp exon 261530 261661 . + . Parent=transcript:Os01t0104800-01;Name=Os01t0104800-01.exon1;constitutive=0;ensembl_end_phase=1;ensembl_phase=-1;exon_id=Os01t0104800-01.exon1;rank=1 +1 irgsp CDS 261562 261661 . + 0 ID=CDS:Os01t0104800-01;Parent=transcript:Os01t0104800-01;protein_id=Os01t0104800-01 +1 irgsp exon 261767 261805 . + . Parent=transcript:Os01t0104800-01;Name=Os01t0104800-01.exon2;constitutive=0;ensembl_end_phase=1;ensembl_phase=1;exon_id=Os01t0104800-01.exon2;rank=2 +1 irgsp CDS 261767 261805 . + 2 ID=CDS:Os01t0104800-01;Parent=transcript:Os01t0104800-01;protein_id=Os01t0104800-01 +1 irgsp exon 261895 261941 . + . Parent=transcript:Os01t0104800-01;Name=Os01t0104800-01.exon3;constitutive=0;ensembl_end_phase=0;ensembl_phase=1;exon_id=Os01t0104800-01.exon3;rank=3 +1 irgsp CDS 261895 261941 . + 2 ID=CDS:Os01t0104800-01;Parent=transcript:Os01t0104800-01;protein_id=Os01t0104800-01 +1 irgsp exon 262582 262681 . + . Parent=transcript:Os01t0104800-01;Name=Os01t0104800-01.exon4;constitutive=0;ensembl_end_phase=1;ensembl_phase=0;exon_id=Os01t0104800-01.exon4;rank=4 +1 irgsp CDS 262582 262681 . + 0 ID=CDS:Os01t0104800-01;Parent=transcript:Os01t0104800-01;protein_id=Os01t0104800-01 +1 irgsp exon 262925 263181 . + . Parent=transcript:Os01t0104800-01;Name=Os01t0104800-01.exon5;constitutive=0;ensembl_end_phase=0;ensembl_phase=1;exon_id=Os01t0104800-01.exon5;rank=5 +1 irgsp CDS 262925 263181 . + 2 ID=CDS:Os01t0104800-01;Parent=transcript:Os01t0104800-01;protein_id=Os01t0104800-01 +1 irgsp exon 263525 263640 . + . Parent=transcript:Os01t0104800-01;Name=Os01t0104800-01.exon6;constitutive=0;ensembl_end_phase=2;ensembl_phase=0;exon_id=Os01t0104800-01.exon6;rank=6 +1 irgsp CDS 263525 263640 . + 0 ID=CDS:Os01t0104800-01;Parent=transcript:Os01t0104800-01;protein_id=Os01t0104800-01 +1 irgsp exon 264014 264098 . + . Parent=transcript:Os01t0104800-01;Name=Os01t0104800-01.exon7;constitutive=1;ensembl_end_phase=0;ensembl_phase=2;exon_id=Os01t0104800-01.exon7;rank=7 +1 irgsp CDS 264014 264098 . + 1 ID=CDS:Os01t0104800-01;Parent=transcript:Os01t0104800-01;protein_id=Os01t0104800-01 +1 irgsp exon 265236 265415 . + . Parent=transcript:Os01t0104800-01;Name=Os01t0104800-01.exon8;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0104800-01.exon8;rank=8 +1 irgsp CDS 265236 265415 . + 0 ID=CDS:Os01t0104800-01;Parent=transcript:Os01t0104800-01;protein_id=Os01t0104800-01 +1 irgsp exon 265506 265649 . + . Parent=transcript:Os01t0104800-01;Name=Os01t0104800-01.exon9;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0104800-01.exon9;rank=9 +1 irgsp CDS 265506 265649 . + 0 ID=CDS:Os01t0104800-01;Parent=transcript:Os01t0104800-01;protein_id=Os01t0104800-01 +1 irgsp exon 265740 265817 . + . Parent=transcript:Os01t0104800-01;Name=Os01t0104800-01.exon10;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0104800-01.exon10;rank=10 +1 irgsp CDS 265740 265817 . + 0 ID=CDS:Os01t0104800-01;Parent=transcript:Os01t0104800-01;protein_id=Os01t0104800-01 +1 irgsp exon 265909 266045 . + . Parent=transcript:Os01t0104800-01;Name=Os01t0104800-01.exon11;constitutive=1;ensembl_end_phase=2;ensembl_phase=0;exon_id=Os01t0104800-01.exon11;rank=11 +1 irgsp CDS 265909 266045 . + 0 ID=CDS:Os01t0104800-01;Parent=transcript:Os01t0104800-01;protein_id=Os01t0104800-01 +1 irgsp exon 266138 266246 . + . Parent=transcript:Os01t0104800-01;Name=Os01t0104800-01.exon12;constitutive=1;ensembl_end_phase=0;ensembl_phase=2;exon_id=Os01t0104800-01.exon12;rank=12 +1 irgsp CDS 266138 266246 . + 1 ID=CDS:Os01t0104800-01;Parent=transcript:Os01t0104800-01;protein_id=Os01t0104800-01 +1 irgsp exon 267237 267514 . + . Parent=transcript:Os01t0104800-01;Name=Os01t0104800-01.exon13;constitutive=1;ensembl_end_phase=2;ensembl_phase=0;exon_id=Os01t0104800-01.exon13;rank=13 +1 irgsp CDS 267237 267514 . + 0 ID=CDS:Os01t0104800-01;Parent=transcript:Os01t0104800-01;protein_id=Os01t0104800-01 +1 irgsp exon 267591 267657 . + . Parent=transcript:Os01t0104800-01;Name=Os01t0104800-01.exon14;constitutive=1;ensembl_end_phase=0;ensembl_phase=2;exon_id=Os01t0104800-01.exon14;rank=14 +1 irgsp CDS 267591 267657 . + 1 ID=CDS:Os01t0104800-01;Parent=transcript:Os01t0104800-01;protein_id=Os01t0104800-01 +1 irgsp exon 267734 267802 . + . Parent=transcript:Os01t0104800-01;Name=Os01t0104800-01.exon15;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0104800-01.exon15;rank=15 +1 irgsp CDS 267734 267802 . + 0 ID=CDS:Os01t0104800-01;Parent=transcript:Os01t0104800-01;protein_id=Os01t0104800-01 +1 irgsp CDS 267880 268011 . + 0 ID=CDS:Os01t0104800-01;Parent=transcript:Os01t0104800-01;protein_id=Os01t0104800-01 +1 irgsp exon 267880 268145 . + . Parent=transcript:Os01t0104800-01;Name=Os01t0104800-01.exon16;constitutive=0;ensembl_end_phase=-1;ensembl_phase=0;exon_id=Os01t0104800-01.exon16;rank=16 +1 irgsp three_prime_UTR 268012 268145 . + . Parent=transcript:Os01t0104800-01 +1 irgsp mRNA 263523 268120 . + . ID=transcript:Os01t0104800-02;Parent=gene:Os01g0104800;biotype=protein_coding;transcript_id=Os01t0104800-02 +1 irgsp five_prime_UTR 263523 263524 . + . Parent=transcript:Os01t0104800-02 +1 irgsp exon 263523 263640 . + . Parent=transcript:Os01t0104800-02;Name=Os01t0104800-02.exon1;constitutive=0;ensembl_end_phase=2;ensembl_phase=-1;exon_id=Os01t0104800-02.exon1;rank=1 +1 irgsp CDS 263525 263640 . + 0 ID=CDS:Os01t0104800-02;Parent=transcript:Os01t0104800-02;protein_id=Os01t0104800-02 +1 irgsp exon 264014 264098 . + . Parent=transcript:Os01t0104800-02;Name=Os01t0104800-01.exon7;constitutive=1;ensembl_end_phase=0;ensembl_phase=2;exon_id=Os01t0104800-01.exon7;rank=2 +1 irgsp CDS 264014 264098 . + 1 ID=CDS:Os01t0104800-02;Parent=transcript:Os01t0104800-02;protein_id=Os01t0104800-02 +1 irgsp exon 265236 265415 . + . Parent=transcript:Os01t0104800-02;Name=Os01t0104800-01.exon8;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0104800-01.exon8;rank=3 +1 irgsp CDS 265236 265415 . + 0 ID=CDS:Os01t0104800-02;Parent=transcript:Os01t0104800-02;protein_id=Os01t0104800-02 +1 irgsp exon 265506 265649 . + . Parent=transcript:Os01t0104800-02;Name=Os01t0104800-01.exon9;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0104800-01.exon9;rank=4 +1 irgsp CDS 265506 265649 . + 0 ID=CDS:Os01t0104800-02;Parent=transcript:Os01t0104800-02;protein_id=Os01t0104800-02 +1 irgsp exon 265740 265817 . + . Parent=transcript:Os01t0104800-02;Name=Os01t0104800-01.exon10;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0104800-01.exon10;rank=5 +1 irgsp CDS 265740 265817 . + 0 ID=CDS:Os01t0104800-02;Parent=transcript:Os01t0104800-02;protein_id=Os01t0104800-02 +1 irgsp exon 265909 266045 . + . Parent=transcript:Os01t0104800-02;Name=Os01t0104800-01.exon11;constitutive=1;ensembl_end_phase=2;ensembl_phase=0;exon_id=Os01t0104800-01.exon11;rank=6 +1 irgsp CDS 265909 266045 . + 0 ID=CDS:Os01t0104800-02;Parent=transcript:Os01t0104800-02;protein_id=Os01t0104800-02 +1 irgsp exon 266138 266246 . + . Parent=transcript:Os01t0104800-02;Name=Os01t0104800-01.exon12;constitutive=1;ensembl_end_phase=0;ensembl_phase=2;exon_id=Os01t0104800-01.exon12;rank=7 +1 irgsp CDS 266138 266246 . + 1 ID=CDS:Os01t0104800-02;Parent=transcript:Os01t0104800-02;protein_id=Os01t0104800-02 +1 irgsp exon 267237 267514 . + . Parent=transcript:Os01t0104800-02;Name=Os01t0104800-01.exon13;constitutive=1;ensembl_end_phase=2;ensembl_phase=0;exon_id=Os01t0104800-01.exon13;rank=8 +1 irgsp CDS 267237 267514 . + 0 ID=CDS:Os01t0104800-02;Parent=transcript:Os01t0104800-02;protein_id=Os01t0104800-02 +1 irgsp exon 267591 267657 . + . Parent=transcript:Os01t0104800-02;Name=Os01t0104800-01.exon14;constitutive=1;ensembl_end_phase=0;ensembl_phase=2;exon_id=Os01t0104800-01.exon14;rank=9 +1 irgsp CDS 267591 267657 . + 1 ID=CDS:Os01t0104800-02;Parent=transcript:Os01t0104800-02;protein_id=Os01t0104800-02 +1 irgsp exon 267734 267802 . + . Parent=transcript:Os01t0104800-02;Name=Os01t0104800-01.exon15;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0104800-01.exon15;rank=10 +1 irgsp CDS 267734 267802 . + 0 ID=CDS:Os01t0104800-02;Parent=transcript:Os01t0104800-02;protein_id=Os01t0104800-02 +1 irgsp CDS 267880 268011 . + 0 ID=CDS:Os01t0104800-02;Parent=transcript:Os01t0104800-02;protein_id=Os01t0104800-02 +1 irgsp exon 267880 268120 . + . Parent=transcript:Os01t0104800-02;Name=Os01t0104800-02.exon11;constitutive=0;ensembl_end_phase=-1;ensembl_phase=0;exon_id=Os01t0104800-02.exon11;rank=11 +1 irgsp three_prime_UTR 268012 268120 . + . Parent=transcript:Os01t0104800-02 +### +1 irgsp gene 270179 275084 . - . ID=gene:Os01g0104900;biotype=protein_coding;description=Transferase family protein. (Os01t0104900-01)%3BHypothetical conserved gene. (Os01t0104900-02);gene_id=Os01g0104900;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 270179 275084 . - . ID=transcript:Os01t0104900-01;Parent=gene:Os01g0104900;biotype=protein_coding;transcript_id=Os01t0104900-01 +1 irgsp three_prime_UTR 270179 270355 . - . Parent=transcript:Os01t0104900-01 +1 irgsp exon 270179 271333 . - . Parent=transcript:Os01t0104900-01;Name=Os01t0104900-01.exon2;constitutive=0;ensembl_end_phase=-1;ensembl_phase=0;exon_id=Os01t0104900-01.exon2;rank=2 +1 irgsp CDS 270356 271333 . - 0 ID=CDS:Os01t0104900-01;Parent=transcript:Os01t0104900-01;protein_id=Os01t0104900-01 +1 irgsp CDS 274529 274957 . - 0 ID=CDS:Os01t0104900-01;Parent=transcript:Os01t0104900-01;protein_id=Os01t0104900-01 +1 irgsp exon 274529 275084 . - . Parent=transcript:Os01t0104900-01;Name=Os01t0104900-01.exon1;constitutive=0;ensembl_end_phase=0;ensembl_phase=-1;exon_id=Os01t0104900-01.exon1;rank=1 +1 irgsp five_prime_UTR 274958 275084 . - . Parent=transcript:Os01t0104900-01 +1 irgsp mRNA 270250 271518 . - . ID=transcript:Os01t0104900-02;Parent=gene:Os01g0104900;biotype=protein_coding;transcript_id=Os01t0104900-02 +1 irgsp three_prime_UTR 270250 270355 . - . Parent=transcript:Os01t0104900-02 +1 irgsp exon 270250 271333 . - . Parent=transcript:Os01t0104900-02;Name=Os01t0104900-02.exon2;constitutive=0;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0104900-02.exon2;rank=2 +1 irgsp CDS 270356 271309 . - 0 ID=CDS:Os01t0104900-02;Parent=transcript:Os01t0104900-02;protein_id=Os01t0104900-02 +1 irgsp five_prime_UTR 271310 271333 . - . Parent=transcript:Os01t0104900-02 +1 irgsp exon 271457 271518 . - . Parent=transcript:Os01t0104900-02;Name=Os01t0104900-02.exon1;constitutive=0;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0104900-02.exon1;rank=1 +1 irgsp five_prime_UTR 271457 271518 . - . Parent=transcript:Os01t0104900-02 +### +1 irgsp gene 284762 291892 . - . ID=gene:Os01g0105300;biotype=protein_coding;description=Similar to HAT family dimerisation domain containing protein%2C expressed. (Os01t0105300-01);gene_id=Os01g0105300;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 284762 291892 . - . ID=transcript:Os01t0105300-01;Parent=gene:Os01g0105300;biotype=protein_coding;transcript_id=Os01t0105300-01 +1 irgsp three_prime_UTR 284762 284930 . - . Parent=transcript:Os01t0105300-01 +1 irgsp exon 284762 287047 . - . Parent=transcript:Os01t0105300-01;Name=Os01t0105300-01.exon5;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0105300-01.exon5;rank=5 +1 irgsp CDS 284931 285020 . - 0 ID=CDS:Os01t0105300-01;Parent=transcript:Os01t0105300-01;protein_id=Os01t0105300-01 +1 irgsp five_prime_UTR 285021 287047 . - . Parent=transcript:Os01t0105300-01 +1 irgsp exon 291398 291436 . - . Parent=transcript:Os01t0105300-01;Name=Os01t0105300-01.exon4;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0105300-01.exon4;rank=4 +1 irgsp five_prime_UTR 291398 291436 . - . Parent=transcript:Os01t0105300-01 +1 irgsp exon 291520 291534 . - . Parent=transcript:Os01t0105300-01;Name=Os01t0105300-01.exon3;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0105300-01.exon3;rank=3 +1 irgsp five_prime_UTR 291520 291534 . - . Parent=transcript:Os01t0105300-01 +1 irgsp exon 291678 291738 . - . Parent=transcript:Os01t0105300-01;Name=Os01t0105300-01.exon2;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0105300-01.exon2;rank=2 +1 irgsp five_prime_UTR 291678 291738 . - . Parent=transcript:Os01t0105300-01 +1 irgsp exon 291838 291892 . - . Parent=transcript:Os01t0105300-01;Name=Os01t0105300-01.exon1;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0105300-01.exon1;rank=1 +1 irgsp five_prime_UTR 291838 291892 . - . Parent=transcript:Os01t0105300-01 +### +1 irgsp gene 288372 292296 . + . ID=gene:Os01g0105400;biotype=protein_coding;description=Similar to Kinesin heavy chain. (Os01t0105400-01);gene_id=Os01g0105400;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 288372 292296 . + . ID=transcript:Os01t0105400-01;Parent=gene:Os01g0105400;biotype=protein_coding;transcript_id=Os01t0105400-01 +1 irgsp exon 288372 288846 . + . Parent=transcript:Os01t0105400-01;Name=Os01t0105400-01.exon1;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0105400-01.exon1;rank=1 +1 irgsp five_prime_UTR 288372 288846 . + . Parent=transcript:Os01t0105400-01 +1 irgsp exon 288950 289116 . + . Parent=transcript:Os01t0105400-01;Name=Os01t0105400-01.exon2;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0105400-01.exon2;rank=2 +1 irgsp five_prime_UTR 288950 289116 . + . Parent=transcript:Os01t0105400-01 +1 irgsp exon 289202 289572 . + . Parent=transcript:Os01t0105400-01;Name=Os01t0105400-01.exon3;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0105400-01.exon3;rank=3 +1 irgsp five_prime_UTR 289202 289572 . + . Parent=transcript:Os01t0105400-01 +1 irgsp exon 289661 289830 . + . Parent=transcript:Os01t0105400-01;Name=Os01t0105400-01.exon4;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0105400-01.exon4;rank=4 +1 irgsp five_prime_UTR 289661 289830 . + . Parent=transcript:Os01t0105400-01 +1 irgsp five_prime_UTR 290395 290432 . + . Parent=transcript:Os01t0105400-01 +1 irgsp exon 290395 290512 . + . Parent=transcript:Os01t0105400-01;Name=Os01t0105400-01.exon5;constitutive=1;ensembl_end_phase=2;ensembl_phase=-1;exon_id=Os01t0105400-01.exon5;rank=5 +1 irgsp CDS 290433 290512 . + 0 ID=CDS:Os01t0105400-01;Parent=transcript:Os01t0105400-01;protein_id=Os01t0105400-01 +1 irgsp CDS 291372 291558 . + 1 ID=CDS:Os01t0105400-01;Parent=transcript:Os01t0105400-01;protein_id=Os01t0105400-01 +1 irgsp exon 291372 291574 . + . Parent=transcript:Os01t0105400-01;Name=Os01t0105400-01.exon6;constitutive=1;ensembl_end_phase=-1;ensembl_phase=2;exon_id=Os01t0105400-01.exon6;rank=6 +1 irgsp three_prime_UTR 291559 291574 . + . Parent=transcript:Os01t0105400-01 +1 irgsp exon 291648 291779 . + . Parent=transcript:Os01t0105400-01;Name=Os01t0105400-01.exon7;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0105400-01.exon7;rank=7 +1 irgsp three_prime_UTR 291648 291779 . + . Parent=transcript:Os01t0105400-01 +1 irgsp exon 291859 291948 . + . Parent=transcript:Os01t0105400-01;Name=Os01t0105400-01.exon8;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0105400-01.exon8;rank=8 +1 irgsp three_prime_UTR 291859 291948 . + . Parent=transcript:Os01t0105400-01 +1 irgsp exon 292073 292296 . + . Parent=transcript:Os01t0105400-01;Name=Os01t0105400-01.exon9;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0105400-01.exon9;rank=9 +1 irgsp three_prime_UTR 292073 292296 . + . Parent=transcript:Os01t0105400-01 +### +1 irgsp gene 303233 306736 . + . ID=gene:Os01g0105700;Name=basic helix-loop-helix protein 071;biotype=protein_coding;description=Basic helix-loop-helix dimerisation region bHLH domain containing protein. (Os01t0105700-01);gene_id=Os01g0105700;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 303233 306736 . + . ID=transcript:Os01t0105700-01;Parent=gene:Os01g0105700;biotype=protein_coding;transcript_id=Os01t0105700-01 +1 irgsp five_prime_UTR 303233 303328 . + . Parent=transcript:Os01t0105700-01 +1 irgsp exon 303233 303471 . + . Parent=transcript:Os01t0105700-01;Name=Os01t0105700-01.exon1;constitutive=1;ensembl_end_phase=2;ensembl_phase=-1;exon_id=Os01t0105700-01.exon1;rank=1 +1 irgsp CDS 303329 303471 . + 0 ID=CDS:Os01t0105700-01;Parent=transcript:Os01t0105700-01;protein_id=Os01t0105700-01 +1 irgsp exon 303981 304509 . + . Parent=transcript:Os01t0105700-01;Name=Os01t0105700-01.exon2;constitutive=1;ensembl_end_phase=0;ensembl_phase=2;exon_id=Os01t0105700-01.exon2;rank=2 +1 irgsp CDS 303981 304509 . + 1 ID=CDS:Os01t0105700-01;Parent=transcript:Os01t0105700-01;protein_id=Os01t0105700-01 +1 irgsp exon 305572 305718 . + . Parent=transcript:Os01t0105700-01;Name=Os01t0105700-01.exon3;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0105700-01.exon3;rank=3 +1 irgsp CDS 305572 305718 . + 0 ID=CDS:Os01t0105700-01;Parent=transcript:Os01t0105700-01;protein_id=Os01t0105700-01 +1 irgsp exon 305834 305899 . + . Parent=transcript:Os01t0105700-01;Name=Os01t0105700-01.exon4;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0105700-01.exon4;rank=4 +1 irgsp CDS 305834 305899 . + 0 ID=CDS:Os01t0105700-01;Parent=transcript:Os01t0105700-01;protein_id=Os01t0105700-01 +1 irgsp exon 305993 306058 . + . Parent=transcript:Os01t0105700-01;Name=Os01t0105700-01.exon5;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0105700-01.exon5;rank=5 +1 irgsp CDS 305993 306058 . + 0 ID=CDS:Os01t0105700-01;Parent=transcript:Os01t0105700-01;protein_id=Os01t0105700-01 +1 irgsp exon 306171 306245 . + . Parent=transcript:Os01t0105700-01;Name=Os01t0105700-01.exon6;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0105700-01.exon6;rank=6 +1 irgsp CDS 306171 306245 . + 0 ID=CDS:Os01t0105700-01;Parent=transcript:Os01t0105700-01;protein_id=Os01t0105700-01 +1 irgsp CDS 306353 306493 . + 0 ID=CDS:Os01t0105700-01;Parent=transcript:Os01t0105700-01;protein_id=Os01t0105700-01 +1 irgsp exon 306353 306736 . + . Parent=transcript:Os01t0105700-01;Name=Os01t0105700-01.exon7;constitutive=1;ensembl_end_phase=-1;ensembl_phase=0;exon_id=Os01t0105700-01.exon7;rank=7 +1 irgsp three_prime_UTR 306494 306736 . + . Parent=transcript:Os01t0105700-01 +### +1 irgsp gene 306871 308842 . - . ID=gene:Os01g0105800;Name=IRON-SULFUR CLUSTER PROTEIN 9;biotype=protein_coding;description=Similar to Iron sulfur assembly protein 1. (Os01t0105800-01);gene_id=Os01g0105800;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 306871 308842 . - . ID=transcript:Os01t0105800-01;Parent=gene:Os01g0105800;biotype=protein_coding;transcript_id=Os01t0105800-01 +1 irgsp three_prime_UTR 306871 307123 . - . Parent=transcript:Os01t0105800-01 +1 irgsp exon 306871 307217 . - . Parent=transcript:Os01t0105800-01;Name=Os01t0105800-01.exon4;constitutive=1;ensembl_end_phase=-1;ensembl_phase=2;exon_id=Os01t0105800-01.exon4;rank=4 +1 irgsp CDS 307124 307217 . - 1 ID=CDS:Os01t0105800-01;Parent=transcript:Os01t0105800-01;protein_id=Os01t0105800-01 +1 irgsp exon 307296 307413 . - . Parent=transcript:Os01t0105800-01;Name=Os01t0105800-01.exon3;constitutive=1;ensembl_end_phase=2;ensembl_phase=1;exon_id=Os01t0105800-01.exon3;rank=3 +1 irgsp CDS 307296 307413 . - 2 ID=CDS:Os01t0105800-01;Parent=transcript:Os01t0105800-01;protein_id=Os01t0105800-01 +1 irgsp CDS 308397 308601 . - 0 ID=CDS:Os01t0105800-01;Parent=transcript:Os01t0105800-01;protein_id=Os01t0105800-01 +1 irgsp exon 308397 308626 . - . Parent=transcript:Os01t0105800-01;Name=Os01t0105800-01.exon2;constitutive=1;ensembl_end_phase=1;ensembl_phase=-1;exon_id=Os01t0105800-01.exon2;rank=2 +1 irgsp five_prime_UTR 308602 308626 . - . Parent=transcript:Os01t0105800-01 +1 irgsp exon 308703 308842 . - . Parent=transcript:Os01t0105800-01;Name=Os01t0105800-01.exon1;constitutive=1;ensembl_end_phase=-1;ensembl_phase=-1;exon_id=Os01t0105800-01.exon1;rank=1 +1 irgsp five_prime_UTR 308703 308842 . - . Parent=transcript:Os01t0105800-01 +### +1 irgsp gene 309520 313170 . - . ID=gene:Os01g0105900;biotype=protein_coding;description=Carbohydrate/purine kinase domain containing protein. (Os01t0105900-01);gene_id=Os01g0105900;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 309520 313170 . - . ID=transcript:Os01t0105900-01;Parent=gene:Os01g0105900;biotype=protein_coding;transcript_id=Os01t0105900-01 +1 irgsp three_prime_UTR 309520 309821 . - . Parent=transcript:Os01t0105900-01 +1 irgsp exon 309520 310070 . - . Parent=transcript:Os01t0105900-01;Name=Os01t0105900-01.exon8;constitutive=1;ensembl_end_phase=-1;ensembl_phase=0;exon_id=Os01t0105900-01.exon8;rank=8 +1 irgsp CDS 309822 310070 . - 0 ID=CDS:Os01t0105900-01;Parent=transcript:Os01t0105900-01;protein_id=Os01t0105900-01 +1 irgsp exon 310256 310367 . - . Parent=transcript:Os01t0105900-01;Name=Os01t0105900-01.exon7;constitutive=1;ensembl_end_phase=0;ensembl_phase=2;exon_id=Os01t0105900-01.exon7;rank=7 +1 irgsp CDS 310256 310367 . - 1 ID=CDS:Os01t0105900-01;Parent=transcript:Os01t0105900-01;protein_id=Os01t0105900-01 +1 irgsp exon 310455 310552 . - . Parent=transcript:Os01t0105900-01;Name=Os01t0105900-01.exon6;constitutive=1;ensembl_end_phase=2;ensembl_phase=0;exon_id=Os01t0105900-01.exon6;rank=6 +1 irgsp CDS 310455 310552 . - 0 ID=CDS:Os01t0105900-01;Parent=transcript:Os01t0105900-01;protein_id=Os01t0105900-01 +1 irgsp exon 310632 310739 . - . Parent=transcript:Os01t0105900-01;Name=Os01t0105900-01.exon5;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0105900-01.exon5;rank=5 +1 irgsp CDS 310632 310739 . - 0 ID=CDS:Os01t0105900-01;Parent=transcript:Os01t0105900-01;protein_id=Os01t0105900-01 +1 irgsp exon 310880 310918 . - . Parent=transcript:Os01t0105900-01;Name=Os01t0105900-01.exon4;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0105900-01.exon4;rank=4 +1 irgsp CDS 310880 310918 . - 0 ID=CDS:Os01t0105900-01;Parent=transcript:Os01t0105900-01;protein_id=Os01t0105900-01 +1 irgsp exon 311002 311073 . - . Parent=transcript:Os01t0105900-01;Name=Os01t0105900-01.exon3;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0105900-01.exon3;rank=3 +1 irgsp CDS 311002 311073 . - 0 ID=CDS:Os01t0105900-01;Parent=transcript:Os01t0105900-01;protein_id=Os01t0105900-01 +1 irgsp exon 311163 311426 . - . Parent=transcript:Os01t0105900-01;Name=Os01t0105900-01.exon2;constitutive=1;ensembl_end_phase=0;ensembl_phase=0;exon_id=Os01t0105900-01.exon2;rank=2 +1 irgsp CDS 311163 311426 . - 0 ID=CDS:Os01t0105900-01;Parent=transcript:Os01t0105900-01;protein_id=Os01t0105900-01 +1 irgsp CDS 312867 313064 . - 0 ID=CDS:Os01t0105900-01;Parent=transcript:Os01t0105900-01;protein_id=Os01t0105900-01 +1 irgsp exon 312867 313170 . - . Parent=transcript:Os01t0105900-01;Name=Os01t0105900-01.exon1;constitutive=1;ensembl_end_phase=0;ensembl_phase=-1;exon_id=Os01t0105900-01.exon1;rank=1 +1 irgsp five_prime_UTR 313065 313170 . - . Parent=transcript:Os01t0105900-01 +### +1 irgsp gene 319754 322205 . + . ID=gene:Os01g0106200;biotype=protein_coding;description=Similar to RER1A protein (AtRER1A). (Os01t0106200-01);gene_id=Os01g0106200;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 319754 322205 . + . ID=transcript:Os01t0106200-01;Parent=gene:Os01g0106200;biotype=protein_coding;transcript_id=Os01t0106200-01 +1 irgsp five_prime_UTR 319754 319874 . + . Parent=transcript:Os01t0106200-01 +1 irgsp exon 319754 320236 . + . Parent=transcript:Os01t0106200-01;Name=Os01t0106200-01.exon1;constitutive=1;ensembl_end_phase=2;ensembl_phase=-1;exon_id=Os01t0106200-01.exon1;rank=1 +1 irgsp CDS 319875 320236 . + 0 ID=CDS:Os01t0106200-01;Parent=transcript:Os01t0106200-01;protein_id=Os01t0106200-01 +1 irgsp exon 321468 321648 . + . Parent=transcript:Os01t0106200-01;Name=Os01t0106200-01.exon2;constitutive=1;ensembl_end_phase=0;ensembl_phase=2;exon_id=Os01t0106200-01.exon2;rank=2 +1 irgsp CDS 321468 321648 . + 1 ID=CDS:Os01t0106200-01;Parent=transcript:Os01t0106200-01;protein_id=Os01t0106200-01 +1 irgsp CDS 321928 321975 . + 0 ID=CDS:Os01t0106200-01;Parent=transcript:Os01t0106200-01;protein_id=Os01t0106200-01 +1 irgsp exon 321928 322205 . + . Parent=transcript:Os01t0106200-01;Name=Os01t0106200-01.exon3;constitutive=1;ensembl_end_phase=-1;ensembl_phase=0;exon_id=Os01t0106200-01.exon3;rank=3 +1 irgsp three_prime_UTR 321976 322205 . + . Parent=transcript:Os01t0106200-01 +### +1 irgsp gene 322591 323923 . - . ID=gene:Os01g0106300;biotype=protein_coding;description=Similar to Isoflavone reductase homolog IRL (EC 1.3.1.-). (Os01t0106300-01);gene_id=Os01g0106300;logic_name=irgspv1.0-20170804-genes +1 irgsp mRNA 322591 323923 . - . ID=transcript:Os01t0106300-01;Parent=gene:Os01g0106300;biotype=protein_coding;transcript_id=Os01t0106300-01 +1 irgsp three_prime_UTR 322591 322809 . - . Parent=transcript:Os01t0106300-01 +1 irgsp exon 322591 322973 . - . Parent=transcript:Os01t0106300-01;Name=Os01t0106300-01.exon2;constitutive=1;ensembl_end_phase=-1;ensembl_phase=1;exon_id=Os01t0106300-01.exon2;rank=2 diff --git a/src/agat/agat_convert_sp_gff2tsv/test_data/agat_convert_sp_gff2tsv_1.tsv b/src/agat/agat_convert_sp_gff2tsv/test_data/agat_convert_sp_gff2tsv_1.tsv new file mode 100644 index 00000000..b30ae271 --- /dev/null +++ b/src/agat/agat_convert_sp_gff2tsv/test_data/agat_convert_sp_gff2tsv_1.tsv @@ -0,0 +1,881 @@ +seq_id source_tag primary_tag start end score strand frame Alias biotype constitutive description ensembl_end_phase ensembl_phase exon_id gene_id ID logic_name Name Parent protein_id rank transcript_id +1 irgsp repeat_region 2000 2100 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A fakeRepeat1 N/A N/A N/A N/A N/A N/A +1 irgsp gene 2983 10815 . 1 . N/A protein_coding N/A RabGAP/TBC domain containing protein. (Os01t0100100-01) N/A N/A N/A Os01g0100100 gene:Os01g0100100 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 2983 10815 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0100100-01 N/A N/A gene:Os01g0100100 N/A N/A Os01t0100100-01 +1 irgsp exon 2983 3268 . 1 . N/A N/A 1 N/A -1 -1 Os01t0100100-01.exon1 N/A Os01t0100100-01.exon1 N/A Os01t0100100-01.exon1 transcript:Os01t0100100-01 N/A 1 N/A +1 irgsp exon 3354 3616 . 1 . N/A N/A 1 N/A 0 -1 Os01t0100100-01.exon2 N/A Os01t0100100-01.exon2 N/A Os01t0100100-01.exon2 transcript:Os01t0100100-01 N/A 2 N/A +1 irgsp exon 4357 4455 . 1 . N/A N/A 1 N/A 0 0 Os01t0100100-01.exon3 N/A Os01t0100100-01.exon3 N/A Os01t0100100-01.exon3 transcript:Os01t0100100-01 N/A 3 N/A +1 irgsp exon 5457 5560 . 1 . N/A N/A 1 N/A 2 0 Os01t0100100-01.exon4 N/A Os01t0100100-01.exon4 N/A Os01t0100100-01.exon4 transcript:Os01t0100100-01 N/A 4 N/A +1 irgsp exon 7136 7944 . 1 . N/A N/A 1 N/A 1 2 Os01t0100100-01.exon5 N/A Os01t0100100-01.exon5 N/A Os01t0100100-01.exon5 transcript:Os01t0100100-01 N/A 5 N/A +1 irgsp exon 8028 8150 . 1 . N/A N/A 1 N/A 1 1 Os01t0100100-01.exon6 N/A Os01t0100100-01.exon6 N/A Os01t0100100-01.exon6 transcript:Os01t0100100-01 N/A 6 N/A +1 irgsp exon 8232 8320 . 1 . N/A N/A 1 N/A 0 1 Os01t0100100-01.exon7 N/A Os01t0100100-01.exon7 N/A Os01t0100100-01.exon7 transcript:Os01t0100100-01 N/A 7 N/A +1 irgsp exon 8408 8608 . 1 . N/A N/A 1 N/A 0 0 Os01t0100100-01.exon8 N/A Os01t0100100-01.exon8 N/A Os01t0100100-01.exon8 transcript:Os01t0100100-01 N/A 8 N/A +1 irgsp exon 9210 9615 . 1 . N/A N/A 1 N/A 1 0 Os01t0100100-01.exon9 N/A Os01t0100100-01.exon9 N/A Os01t0100100-01.exon9 transcript:Os01t0100100-01 N/A 9 N/A +1 irgsp exon 10102 10187 . 1 . N/A N/A 1 N/A 0 1 Os01t0100100-01.exon10 N/A Os01t0100100-01.exon10 N/A Os01t0100100-01.exon10 transcript:Os01t0100100-01 N/A 10 N/A +1 irgsp exon 10274 10430 . 1 . N/A N/A 1 N/A -1 0 Os01t0100100-01.exon11 N/A Os01t0100100-01.exon11 N/A Os01t0100100-01.exon11 transcript:Os01t0100100-01 N/A 11 N/A +1 irgsp exon 10504 10815 . 1 . N/A N/A 1 N/A -1 -1 Os01t0100100-01.exon12 N/A Os01t0100100-01.exon12 N/A Os01t0100100-01.exon12 transcript:Os01t0100100-01 N/A 12 N/A +1 irgsp CDS 3449 3616 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100100-01 N/A N/A transcript:Os01t0100100-01 Os01t0100100-01 N/A N/A +1 irgsp CDS 4357 4455 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100100-01 N/A N/A transcript:Os01t0100100-01 Os01t0100100-01 N/A N/A +1 irgsp CDS 5457 5560 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100100-01 N/A N/A transcript:Os01t0100100-01 Os01t0100100-01 N/A N/A +1 irgsp CDS 7136 7944 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100100-01 N/A N/A transcript:Os01t0100100-01 Os01t0100100-01 N/A N/A +1 irgsp CDS 8028 8150 . 1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100100-01 N/A N/A transcript:Os01t0100100-01 Os01t0100100-01 N/A N/A +1 irgsp CDS 8232 8320 . 1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100100-01 N/A N/A transcript:Os01t0100100-01 Os01t0100100-01 N/A N/A +1 irgsp CDS 8408 8608 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100100-01 N/A N/A transcript:Os01t0100100-01 Os01t0100100-01 N/A N/A +1 irgsp CDS 9210 9615 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100100-01 N/A N/A transcript:Os01t0100100-01 Os01t0100100-01 N/A N/A +1 irgsp CDS 10102 10187 . 1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100100-01 N/A N/A transcript:Os01t0100100-01 Os01t0100100-01 N/A N/A +1 irgsp CDS 10274 10297 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100100-01 N/A N/A transcript:Os01t0100100-01 Os01t0100100-01 N/A N/A +1 irgsp five_prime_UTR 2983 3268 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-1 N/A N/A transcript:Os01t0100100-01 N/A N/A N/A +1 irgsp five_prime_UTR 3354 3448 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-2 N/A N/A transcript:Os01t0100100-01 N/A N/A N/A +1 irgsp three_prime_UTR 10298 10430 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-1 N/A N/A transcript:Os01t0100100-01 N/A N/A N/A +1 irgsp three_prime_UTR 10504 10815 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-2 N/A N/A transcript:Os01t0100100-01 N/A N/A N/A +1 irgsp gene 11218 12435 . 1 . N/A protein_coding N/A Conserved hypothetical protein. (Os01t0100200-01) N/A N/A N/A Os01g0100200 gene:Os01g0100200 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 11218 12435 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0100200-01 N/A N/A gene:Os01g0100200 N/A N/A Os01t0100200-01 +1 irgsp exon 11218 12060 . 1 . N/A N/A 1 N/A 2 -1 Os01t0100200-01.exon1 N/A Os01t0100200-01.exon1 N/A Os01t0100200-01.exon1 transcript:Os01t0100200-01 N/A 1 N/A +1 irgsp exon 12152 12435 . 1 . N/A N/A 1 N/A -1 2 Os01t0100200-01.exon2 N/A Os01t0100200-01.exon2 N/A Os01t0100200-01.exon2 transcript:Os01t0100200-01 N/A 2 N/A +1 irgsp CDS 11798 12060 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100200-01 N/A N/A transcript:Os01t0100200-01 Os01t0100200-01 N/A N/A +1 irgsp CDS 12152 12317 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100200-01 N/A N/A transcript:Os01t0100200-01 Os01t0100200-01 N/A N/A +1 irgsp five_prime_UTR 11218 11797 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-3 N/A N/A transcript:Os01t0100200-01 N/A N/A N/A +1 irgsp three_prime_UTR 12318 12435 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-3 N/A N/A transcript:Os01t0100200-01 N/A N/A N/A +1 irgsp gene 11372 12284 . -1 . N/A protein_coding N/A Cytochrome P450 domain containing protein. (Os01t0100300-00) N/A N/A N/A Os01g0100300 gene:Os01g0100300 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 11372 12284 . -1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0100300-00 N/A N/A gene:Os01g0100300 N/A N/A Os01t0100300-00 +1 irgsp exon 11372 12042 . -1 . N/A N/A 1 N/A 0 1 Os01t0100300-00.exon2 N/A Os01t0100300-00.exon2 N/A Os01t0100300-00.exon2 transcript:Os01t0100300-00 N/A 2 N/A +1 irgsp exon 12146 12284 . -1 . N/A N/A 1 N/A 1 0 Os01t0100300-00.exon1 N/A Os01t0100300-00.exon1 N/A Os01t0100300-00.exon1 transcript:Os01t0100300-00 N/A 1 N/A +1 irgsp CDS 11372 12042 . -1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100300-00 N/A N/A transcript:Os01t0100300-00 Os01t0100300-00 N/A N/A +1 irgsp CDS 12146 12284 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100300-00 N/A N/A transcript:Os01t0100300-00 Os01t0100300-00 N/A N/A +1 irgsp gene 12721 15685 . 1 . N/A protein_coding N/A Similar to Pectinesterase-like protein. (Os01t0100400-01) N/A N/A N/A Os01g0100400 gene:Os01g0100400 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 12721 15685 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0100400-01 N/A N/A gene:Os01g0100400 N/A N/A Os01t0100400-01 +1 irgsp exon 12721 13813 . 1 . N/A N/A 1 N/A 2 -1 Os01t0100400-01.exon1 N/A Os01t0100400-01.exon1 N/A Os01t0100400-01.exon1 transcript:Os01t0100400-01 N/A 1 N/A +1 irgsp exon 13906 14271 . 1 . N/A N/A 1 N/A 2 2 Os01t0100400-01.exon2 N/A Os01t0100400-01.exon2 N/A Os01t0100400-01.exon2 transcript:Os01t0100400-01 N/A 2 N/A +1 irgsp exon 14359 14437 . 1 . N/A N/A 1 N/A 0 2 Os01t0100400-01.exon3 N/A Os01t0100400-01.exon3 N/A Os01t0100400-01.exon3 transcript:Os01t0100400-01 N/A 3 N/A +1 irgsp exon 14969 15171 . 1 . N/A N/A 1 N/A 2 0 Os01t0100400-01.exon4 N/A Os01t0100400-01.exon4 N/A Os01t0100400-01.exon4 transcript:Os01t0100400-01 N/A 4 N/A +1 irgsp exon 15266 15685 . 1 . N/A N/A 1 N/A -1 2 Os01t0100400-01.exon5 N/A Os01t0100400-01.exon5 N/A Os01t0100400-01.exon5 transcript:Os01t0100400-01 N/A 5 N/A +1 irgsp CDS 12774 13813 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100400-01 N/A N/A transcript:Os01t0100400-01 Os01t0100400-01 N/A N/A +1 irgsp CDS 13906 14271 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100400-01 N/A N/A transcript:Os01t0100400-01 Os01t0100400-01 N/A N/A +1 irgsp CDS 14359 14437 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100400-01 N/A N/A transcript:Os01t0100400-01 Os01t0100400-01 N/A N/A +1 irgsp CDS 14969 15171 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100400-01 N/A N/A transcript:Os01t0100400-01 Os01t0100400-01 N/A N/A +1 irgsp CDS 15266 15359 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100400-01 N/A N/A transcript:Os01t0100400-01 Os01t0100400-01 N/A N/A +1 irgsp five_prime_UTR 12721 12773 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-4 N/A N/A transcript:Os01t0100400-01 N/A N/A N/A +1 irgsp three_prime_UTR 15360 15685 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-4 N/A N/A transcript:Os01t0100400-01 N/A N/A N/A +1 irgsp gene 12808 13978 . -1 . N/A protein_coding N/A Hypothetical protein. (Os01t0100466-00) N/A N/A N/A Os01g0100466 gene:Os01g0100466 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 12808 13978 . -1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0100466-00 N/A N/A gene:Os01g0100466 N/A N/A Os01t0100466-00 +1 irgsp exon 12808 13782 . -1 . N/A N/A 1 N/A -1 -1 Os01t0100466-00.exon2 N/A Os01t0100466-00.exon2 N/A Os01t0100466-00.exon2 transcript:Os01t0100466-00 N/A 2 N/A +1 irgsp exon 13880 13978 . -1 . N/A N/A 1 N/A -1 -1 Os01t0100466-00.exon1 N/A Os01t0100466-00.exon1 N/A Os01t0100466-00.exon1 transcript:Os01t0100466-00 N/A 1 N/A +1 irgsp CDS 12869 13102 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100466-00 N/A N/A transcript:Os01t0100466-00 Os01t0100466-00 N/A N/A +1 irgsp five_prime_UTR 13103 13782 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-5 N/A N/A transcript:Os01t0100466-00 N/A N/A N/A +1 irgsp five_prime_UTR 13880 13978 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-6 N/A N/A transcript:Os01t0100466-00 N/A N/A N/A +1 irgsp three_prime_UTR 12808 12868 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-5 N/A N/A transcript:Os01t0100466-00 N/A N/A N/A +1 irgsp gene 16399 20144 . 1 . N/A protein_coding N/A Immunoglobulin-like domain containing protein. (Os01t0100500-01) N/A N/A N/A Os01g0100500 gene:Os01g0100500 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 16399 20144 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0100500-01 N/A N/A gene:Os01g0100500 N/A N/A Os01t0100500-01 +1 irgsp exon 16399 16976 . 1 . N/A N/A 1 N/A 0 -1 Os01t0100500-01.exon1 N/A Os01t0100500-01.exon1 N/A Os01t0100500-01.exon1 transcript:Os01t0100500-01 N/A 1 N/A +1 irgsp exon 17383 17474 . 1 . N/A N/A 1 N/A 2 0 Os01t0100500-01.exon2 N/A Os01t0100500-01.exon2 N/A Os01t0100500-01.exon2 transcript:Os01t0100500-01 N/A 2 N/A +1 irgsp exon 17558 18258 . 1 . N/A N/A 1 N/A 1 2 Os01t0100500-01.exon3 N/A Os01t0100500-01.exon3 N/A Os01t0100500-01.exon3 transcript:Os01t0100500-01 N/A 3 N/A +1 irgsp exon 18501 18571 . 1 . N/A N/A 1 N/A 0 1 Os01t0100500-01.exon4 N/A Os01t0100500-01.exon4 N/A Os01t0100500-01.exon4 transcript:Os01t0100500-01 N/A 4 N/A +1 irgsp exon 18968 19057 . 1 . N/A N/A 1 N/A 0 0 Os01t0100500-01.exon5 N/A Os01t0100500-01.exon5 N/A Os01t0100500-01.exon5 transcript:Os01t0100500-01 N/A 5 N/A +1 irgsp exon 19142 19321 . 1 . N/A N/A 1 N/A 0 0 Os01t0100500-01.exon6 N/A Os01t0100500-01.exon6 N/A Os01t0100500-01.exon6 transcript:Os01t0100500-01 N/A 6 N/A +1 irgsp exon 19531 19629 . 1 . N/A N/A 1 N/A -1 0 Os01t0100500-01.exon7 N/A Os01t0100500-01.exon7 N/A Os01t0100500-01.exon7 transcript:Os01t0100500-01 N/A 7 N/A +1 irgsp exon 19734 20144 . 1 . N/A N/A 1 N/A -1 -1 Os01t0100500-01.exon8 N/A Os01t0100500-01.exon8 N/A Os01t0100500-01.exon8 transcript:Os01t0100500-01 N/A 8 N/A +1 irgsp CDS 16599 16976 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100500-01 N/A N/A transcript:Os01t0100500-01 Os01t0100500-01 N/A N/A +1 irgsp CDS 17383 17474 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100500-01 N/A N/A transcript:Os01t0100500-01 Os01t0100500-01 N/A N/A +1 irgsp CDS 17558 18258 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100500-01 N/A N/A transcript:Os01t0100500-01 Os01t0100500-01 N/A N/A +1 irgsp CDS 18501 18571 . 1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100500-01 N/A N/A transcript:Os01t0100500-01 Os01t0100500-01 N/A N/A +1 irgsp CDS 18968 19057 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100500-01 N/A N/A transcript:Os01t0100500-01 Os01t0100500-01 N/A N/A +1 irgsp CDS 19142 19321 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100500-01 N/A N/A transcript:Os01t0100500-01 Os01t0100500-01 N/A N/A +1 irgsp CDS 19531 19593 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100500-01 N/A N/A transcript:Os01t0100500-01 Os01t0100500-01 N/A N/A +1 irgsp five_prime_UTR 16399 16598 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-7 N/A N/A transcript:Os01t0100500-01 N/A N/A N/A +1 irgsp three_prime_UTR 19594 19629 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-6 N/A N/A transcript:Os01t0100500-01 N/A N/A N/A +1 irgsp three_prime_UTR 19734 20144 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-7 N/A N/A transcript:Os01t0100500-01 N/A N/A N/A +1 irgsp gene 22841 26892 . 1 . N/A protein_coding N/A Single-stranded nucleic acid binding R3H domain containing protein. (Os01t0100600-01) N/A N/A N/A Os01g0100600 gene:Os01g0100600 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 22841 26892 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0100600-01 N/A N/A gene:Os01g0100600 N/A N/A Os01t0100600-01 +1 irgsp exon 22841 23281 . 1 . N/A N/A 1 N/A 2 -1 Os01t0100600-01.exon1 N/A Os01t0100600-01.exon1 N/A Os01t0100600-01.exon1 transcript:Os01t0100600-01 N/A 1 N/A +1 irgsp exon 23572 23847 . 1 . N/A N/A 1 N/A 2 2 Os01t0100600-01.exon2 N/A Os01t0100600-01.exon2 N/A Os01t0100600-01.exon2 transcript:Os01t0100600-01 N/A 2 N/A +1 irgsp exon 23962 24033 . 1 . N/A N/A 1 N/A 2 2 Os01t0100600-01.exon3 N/A Os01t0100600-01.exon3 N/A Os01t0100600-01.exon3 transcript:Os01t0100600-01 N/A 3 N/A +1 irgsp exon 24492 24577 . 1 . N/A N/A 1 N/A 1 2 Os01t0100600-01.exon4 N/A Os01t0100600-01.exon4 N/A Os01t0100600-01.exon4 transcript:Os01t0100600-01 N/A 4 N/A +1 irgsp exon 25445 25519 . 1 . N/A N/A 1 N/A 1 1 Os01t0100600-01.exon5 N/A Os01t0100600-01.exon5 N/A Os01t0100600-01.exon5 transcript:Os01t0100600-01 N/A 5 N/A +1 irgsp exon 25883 26892 . 1 . N/A N/A 1 N/A -1 1 Os01t0100600-01.exon6 N/A Os01t0100600-01.exon6 N/A Os01t0100600-01.exon6 transcript:Os01t0100600-01 N/A 6 N/A +1 irgsp CDS 23232 23281 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100600-01 N/A N/A transcript:Os01t0100600-01 Os01t0100600-01 N/A N/A +1 irgsp CDS 23572 23847 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100600-01 N/A N/A transcript:Os01t0100600-01 Os01t0100600-01 N/A N/A +1 irgsp CDS 23962 24033 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100600-01 N/A N/A transcript:Os01t0100600-01 Os01t0100600-01 N/A N/A +1 irgsp CDS 24492 24577 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100600-01 N/A N/A transcript:Os01t0100600-01 Os01t0100600-01 N/A N/A +1 irgsp CDS 25445 25519 . 1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100600-01 N/A N/A transcript:Os01t0100600-01 Os01t0100600-01 N/A N/A +1 irgsp CDS 25883 26391 . 1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100600-01 N/A N/A transcript:Os01t0100600-01 Os01t0100600-01 N/A N/A +1 irgsp five_prime_UTR 22841 23231 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-8 N/A N/A transcript:Os01t0100600-01 N/A N/A N/A +1 irgsp three_prime_UTR 26392 26892 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-8 N/A N/A transcript:Os01t0100600-01 N/A N/A N/A +1 irgsp gene 25861 26424 . -1 . N/A protein_coding N/A Hypothetical gene. (Os01t0100650-00) N/A N/A N/A Os01g0100650 gene:Os01g0100650 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 25861 26424 . -1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0100650-00 N/A N/A gene:Os01g0100650 N/A N/A Os01t0100650-00 +1 irgsp exon 25861 26424 . -1 . N/A N/A 1 N/A -1 -1 Os01t0100650-00.exon1 N/A Os01t0100650-00.exon1 N/A Os01t0100650-00.exon1 transcript:Os01t0100650-00 N/A 1 N/A +1 irgsp CDS 26040 26423 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100650-00 N/A N/A transcript:Os01t0100650-00 Os01t0100650-00 N/A N/A +1 irgsp five_prime_UTR 26424 26424 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-9 N/A N/A transcript:Os01t0100650-00 N/A N/A N/A +1 irgsp three_prime_UTR 25861 26039 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-9 N/A N/A transcript:Os01t0100650-00 N/A N/A N/A +1 irgsp gene 27143 28644 . 1 . N/A protein_coding N/A Similar to 40S ribosomal protein S5-1. (Os01t0100700-01) N/A N/A N/A Os01g0100700 gene:Os01g0100700 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 27143 28644 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0100700-01 N/A N/A gene:Os01g0100700 N/A N/A Os01t0100700-01 +1 irgsp exon 27143 27292 . 1 . N/A N/A 1 N/A 0 -1 Os01t0100700-01.exon1 N/A Os01t0100700-01.exon1 N/A Os01t0100700-01.exon1 transcript:Os01t0100700-01 N/A 1 N/A +1 irgsp exon 27370 27641 . 1 . N/A N/A 1 N/A 2 0 Os01t0100700-01.exon2 N/A Os01t0100700-01.exon2 N/A Os01t0100700-01.exon2 transcript:Os01t0100700-01 N/A 2 N/A +1 irgsp exon 28090 28293 . 1 . N/A N/A 1 N/A 2 2 Os01t0100700-01.exon3 N/A Os01t0100700-01.exon3 N/A Os01t0100700-01.exon3 transcript:Os01t0100700-01 N/A 3 N/A +1 irgsp exon 28365 28644 . 1 . N/A N/A 1 N/A -1 2 Os01t0100700-01.exon4 N/A Os01t0100700-01.exon4 N/A Os01t0100700-01.exon4 transcript:Os01t0100700-01 N/A 4 N/A +1 irgsp CDS 27221 27292 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100700-01 N/A N/A transcript:Os01t0100700-01 Os01t0100700-01 N/A N/A +1 irgsp CDS 27370 27641 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100700-01 N/A N/A transcript:Os01t0100700-01 Os01t0100700-01 N/A N/A +1 irgsp CDS 28090 28293 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100700-01 N/A N/A transcript:Os01t0100700-01 Os01t0100700-01 N/A N/A +1 irgsp CDS 28365 28419 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100700-01 N/A N/A transcript:Os01t0100700-01 Os01t0100700-01 N/A N/A +1 irgsp five_prime_UTR 27143 27220 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-10 N/A N/A transcript:Os01t0100700-01 N/A N/A N/A +1 irgsp three_prime_UTR 28420 28644 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-10 N/A N/A transcript:Os01t0100700-01 N/A N/A N/A +1 irgsp gene 29818 34453 . 1 . N/A protein_coding N/A Protein of unknown function DUF1664 family protein. (Os01t0100800-01) N/A N/A N/A Os01g0100800 gene:Os01g0100800 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 29818 34453 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0100800-01 N/A N/A gene:Os01g0100800 N/A N/A Os01t0100800-01 +1 irgsp exon 29818 29976 . 1 . N/A N/A 1 N/A 1 -1 Os01t0100800-01.exon1 N/A Os01t0100800-01.exon1 N/A Os01t0100800-01.exon1 transcript:Os01t0100800-01 N/A 1 N/A +1 irgsp exon 30146 30228 . 1 . N/A N/A 1 N/A 0 1 Os01t0100800-01.exon2 N/A Os01t0100800-01.exon2 N/A Os01t0100800-01.exon2 transcript:Os01t0100800-01 N/A 2 N/A +1 irgsp exon 30735 30806 . 1 . N/A N/A 1 N/A 0 0 Os01t0100800-01.exon3 N/A Os01t0100800-01.exon3 N/A Os01t0100800-01.exon3 transcript:Os01t0100800-01 N/A 3 N/A +1 irgsp exon 30885 30963 . 1 . N/A N/A 1 N/A 1 0 Os01t0100800-01.exon4 N/A Os01t0100800-01.exon4 N/A Os01t0100800-01.exon4 transcript:Os01t0100800-01 N/A 4 N/A +1 irgsp exon 31258 31325 . 1 . N/A N/A 1 N/A 0 1 Os01t0100800-01.exon5 N/A Os01t0100800-01.exon5 N/A Os01t0100800-01.exon5 transcript:Os01t0100800-01 N/A 5 N/A +1 irgsp exon 31505 31606 . 1 . N/A N/A 1 N/A 0 0 Os01t0100800-01.exon6 N/A Os01t0100800-01.exon6 N/A Os01t0100800-01.exon6 transcript:Os01t0100800-01 N/A 6 N/A +1 irgsp exon 32377 32466 . 1 . N/A N/A 1 N/A 0 0 Os01t0100800-01.exon7 N/A Os01t0100800-01.exon7 N/A Os01t0100800-01.exon7 transcript:Os01t0100800-01 N/A 7 N/A +1 irgsp exon 32542 32616 . 1 . N/A N/A 1 N/A 0 0 Os01t0100800-01.exon8 N/A Os01t0100800-01.exon8 N/A Os01t0100800-01.exon8 transcript:Os01t0100800-01 N/A 8 N/A +1 irgsp exon 32712 32744 . 1 . N/A N/A 1 N/A 0 0 Os01t0100800-01.exon9 N/A Os01t0100800-01.exon9 N/A Os01t0100800-01.exon9 transcript:Os01t0100800-01 N/A 9 N/A +1 irgsp exon 32828 32905 . 1 . N/A N/A 1 N/A 0 0 Os01t0100800-01.exon10 N/A Os01t0100800-01.exon10 N/A Os01t0100800-01.exon10 transcript:Os01t0100800-01 N/A 10 N/A +1 irgsp exon 33274 33330 . 1 . N/A N/A 1 N/A 0 0 Os01t0100800-01.exon11 N/A Os01t0100800-01.exon11 N/A Os01t0100800-01.exon11 transcript:Os01t0100800-01 N/A 11 N/A +1 irgsp exon 33400 33471 . 1 . N/A N/A 1 N/A 0 0 Os01t0100800-01.exon12 N/A Os01t0100800-01.exon12 N/A Os01t0100800-01.exon12 transcript:Os01t0100800-01 N/A 12 N/A +1 irgsp exon 33543 33617 . 1 . N/A N/A 1 N/A 0 0 Os01t0100800-01.exon13 N/A Os01t0100800-01.exon13 N/A Os01t0100800-01.exon13 transcript:Os01t0100800-01 N/A 13 N/A +1 irgsp exon 33975 34453 . 1 . N/A N/A 1 N/A -1 0 Os01t0100800-01.exon14 N/A Os01t0100800-01.exon14 N/A Os01t0100800-01.exon14 transcript:Os01t0100800-01 N/A 14 N/A +1 irgsp CDS 29940 29976 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100800-01 N/A N/A transcript:Os01t0100800-01 Os01t0100800-01 N/A N/A +1 irgsp CDS 30146 30228 . 1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100800-01 N/A N/A transcript:Os01t0100800-01 Os01t0100800-01 N/A N/A +1 irgsp CDS 30735 30806 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100800-01 N/A N/A transcript:Os01t0100800-01 Os01t0100800-01 N/A N/A +1 irgsp CDS 30885 30963 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100800-01 N/A N/A transcript:Os01t0100800-01 Os01t0100800-01 N/A N/A +1 irgsp CDS 31258 31325 . 1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100800-01 N/A N/A transcript:Os01t0100800-01 Os01t0100800-01 N/A N/A +1 irgsp CDS 31505 31606 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100800-01 N/A N/A transcript:Os01t0100800-01 Os01t0100800-01 N/A N/A +1 irgsp CDS 32377 32466 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100800-01 N/A N/A transcript:Os01t0100800-01 Os01t0100800-01 N/A N/A +1 irgsp CDS 32542 32616 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100800-01 N/A N/A transcript:Os01t0100800-01 Os01t0100800-01 N/A N/A +1 irgsp CDS 32712 32744 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100800-01 N/A N/A transcript:Os01t0100800-01 Os01t0100800-01 N/A N/A +1 irgsp CDS 32828 32905 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100800-01 N/A N/A transcript:Os01t0100800-01 Os01t0100800-01 N/A N/A +1 irgsp CDS 33274 33330 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100800-01 N/A N/A transcript:Os01t0100800-01 Os01t0100800-01 N/A N/A +1 irgsp CDS 33400 33471 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100800-01 N/A N/A transcript:Os01t0100800-01 Os01t0100800-01 N/A N/A +1 irgsp CDS 33543 33617 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100800-01 N/A N/A transcript:Os01t0100800-01 Os01t0100800-01 N/A N/A +1 irgsp CDS 33975 34124 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100800-01 N/A N/A transcript:Os01t0100800-01 Os01t0100800-01 N/A N/A +1 irgsp five_prime_UTR 29818 29939 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-11 N/A N/A transcript:Os01t0100800-01 N/A N/A N/A +1 irgsp three_prime_UTR 34125 34453 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-11 N/A N/A transcript:Os01t0100800-01 N/A N/A N/A +1 irgsp gene 35623 41136 . 1 . N/A protein_coding N/A Sphingosine-1-phosphate lyase, Disease resistance response (Os01t0100900-01) N/A N/A N/A Os01g0100900 gene:Os01g0100900 irgspv1.0-20170804-genes SPHINGOSINE-1-PHOSPHATE LYASE 1, Sphingosine-1-Phoshpate Lyase 1 N/A N/A N/A N/A +1 irgsp mRNA 35623 41136 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0100900-01 N/A N/A gene:Os01g0100900 N/A N/A Os01t0100900-01 +1 irgsp exon 35623 35939 . 1 . N/A N/A 1 N/A 2 -1 Os01t0100900-01.exon1 N/A Os01t0100900-01.exon1 N/A Os01t0100900-01.exon1 transcript:Os01t0100900-01 N/A 1 N/A +1 irgsp exon 36027 36072 . 1 . N/A N/A 1 N/A 0 2 Os01t0100900-01.exon2 N/A Os01t0100900-01.exon2 N/A Os01t0100900-01.exon2 transcript:Os01t0100900-01 N/A 2 N/A +1 irgsp exon 36517 36668 . 1 . N/A N/A 1 N/A 2 0 Os01t0100900-01.exon3 N/A Os01t0100900-01.exon3 N/A Os01t0100900-01.exon3 transcript:Os01t0100900-01 N/A 3 N/A +1 irgsp exon 36818 36877 . 1 . N/A N/A 1 N/A 2 2 Os01t0100900-01.exon4 N/A Os01t0100900-01.exon4 N/A Os01t0100900-01.exon4 transcript:Os01t0100900-01 N/A 4 N/A +1 irgsp exon 37594 37818 . 1 . N/A N/A 1 N/A 2 2 Os01t0100900-01.exon5 N/A Os01t0100900-01.exon5 N/A Os01t0100900-01.exon5 transcript:Os01t0100900-01 N/A 5 N/A +1 irgsp exon 37892 38033 . 1 . N/A N/A 1 N/A 0 2 Os01t0100900-01.exon6 N/A Os01t0100900-01.exon6 N/A Os01t0100900-01.exon6 transcript:Os01t0100900-01 N/A 6 N/A +1 irgsp exon 38276 38326 . 1 . N/A N/A 1 N/A 0 0 Os01t0100900-01.exon7 N/A Os01t0100900-01.exon7 N/A Os01t0100900-01.exon7 transcript:Os01t0100900-01 N/A 7 N/A +1 irgsp exon 38434 38525 . 1 . N/A N/A 1 N/A 2 0 Os01t0100900-01.exon8 N/A Os01t0100900-01.exon8 N/A Os01t0100900-01.exon8 transcript:Os01t0100900-01 N/A 8 N/A +1 irgsp exon 39319 39445 . 1 . N/A N/A 1 N/A 0 2 Os01t0100900-01.exon9 N/A Os01t0100900-01.exon9 N/A Os01t0100900-01.exon9 transcript:Os01t0100900-01 N/A 9 N/A +1 irgsp exon 39553 39568 . 1 . N/A N/A 1 N/A 1 0 Os01t0100900-01.exon10 N/A Os01t0100900-01.exon10 N/A Os01t0100900-01.exon10 transcript:Os01t0100900-01 N/A 10 N/A +1 irgsp exon 39939 40046 . 1 . N/A N/A 1 N/A 1 1 Os01t0100900-01.exon11 N/A Os01t0100900-01.exon11 N/A Os01t0100900-01.exon11 transcript:Os01t0100900-01 N/A 11 N/A +1 irgsp exon 40135 40189 . 1 . N/A N/A 1 N/A 2 1 Os01t0100900-01.exon12 N/A Os01t0100900-01.exon12 N/A Os01t0100900-01.exon12 transcript:Os01t0100900-01 N/A 12 N/A +1 irgsp exon 40456 40602 . 1 . N/A N/A 1 N/A 2 2 Os01t0100900-01.exon13 N/A Os01t0100900-01.exon13 N/A Os01t0100900-01.exon13 transcript:Os01t0100900-01 N/A 13 N/A +1 irgsp exon 40703 40781 . 1 . N/A N/A 1 N/A 0 2 Os01t0100900-01.exon14 N/A Os01t0100900-01.exon14 N/A Os01t0100900-01.exon14 transcript:Os01t0100900-01 N/A 14 N/A +1 irgsp exon 40885 41136 . 1 . N/A N/A 1 N/A -1 0 Os01t0100900-01.exon15 N/A Os01t0100900-01.exon15 N/A Os01t0100900-01.exon15 transcript:Os01t0100900-01 N/A 15 N/A +1 irgsp CDS 35743 35939 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100900-01 N/A N/A transcript:Os01t0100900-01 Os01t0100900-01 N/A N/A +1 irgsp CDS 36027 36072 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100900-01 N/A N/A transcript:Os01t0100900-01 Os01t0100900-01 N/A N/A +1 irgsp CDS 36517 36668 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100900-01 N/A N/A transcript:Os01t0100900-01 Os01t0100900-01 N/A N/A +1 irgsp CDS 36818 36877 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100900-01 N/A N/A transcript:Os01t0100900-01 Os01t0100900-01 N/A N/A +1 irgsp CDS 37594 37818 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100900-01 N/A N/A transcript:Os01t0100900-01 Os01t0100900-01 N/A N/A +1 irgsp CDS 37892 38033 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100900-01 N/A N/A transcript:Os01t0100900-01 Os01t0100900-01 N/A N/A +1 irgsp CDS 38276 38326 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100900-01 N/A N/A transcript:Os01t0100900-01 Os01t0100900-01 N/A N/A +1 irgsp CDS 38434 38525 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100900-01 N/A N/A transcript:Os01t0100900-01 Os01t0100900-01 N/A N/A +1 irgsp CDS 39319 39445 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100900-01 N/A N/A transcript:Os01t0100900-01 Os01t0100900-01 N/A N/A +1 irgsp CDS 39553 39568 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100900-01 N/A N/A transcript:Os01t0100900-01 Os01t0100900-01 N/A N/A +1 irgsp CDS 39939 40046 . 1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100900-01 N/A N/A transcript:Os01t0100900-01 Os01t0100900-01 N/A N/A +1 irgsp CDS 40135 40189 . 1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100900-01 N/A N/A transcript:Os01t0100900-01 Os01t0100900-01 N/A N/A +1 irgsp CDS 40456 40602 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100900-01 N/A N/A transcript:Os01t0100900-01 Os01t0100900-01 N/A N/A +1 irgsp CDS 40703 40781 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100900-01 N/A N/A transcript:Os01t0100900-01 Os01t0100900-01 N/A N/A +1 irgsp CDS 40885 41007 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0100900-01 N/A N/A transcript:Os01t0100900-01 Os01t0100900-01 N/A N/A +1 irgsp five_prime_UTR 35623 35742 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-12 N/A N/A transcript:Os01t0100900-01 N/A N/A N/A +1 irgsp three_prime_UTR 41008 41136 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-12 N/A N/A transcript:Os01t0100900-01 N/A N/A N/A +1 irgsp gene 58658 61090 . 1 . N/A protein_coding N/A Hypothetical conserved gene. (Os01t0101150-00) N/A N/A N/A Os01g0101150 gene:Os01g0101150 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 58658 61090 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0101150-00 N/A N/A gene:Os01g0101150 N/A N/A Os01t0101150-00 +1 irgsp exon 58658 61090 . 1 . N/A N/A 1 N/A 0 0 Os01t0101150-00.exon1 N/A Os01t0101150-00.exon1 N/A Os01t0101150-00.exon1 transcript:Os01t0101150-00 N/A 1 N/A +1 irgsp CDS 58658 61090 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0101150-00 N/A N/A transcript:Os01t0101150-00 Os01t0101150-00 N/A N/A +1 irgsp gene 62060 65537 . 1 . N/A protein_coding N/A 2,3-diketo-5-methylthio-1-phosphopentane phosphatase domain containing protein. (Os01t0101200-01);2,3-diketo-5-methylthio-1-phosphopentane phosphatase domain containing protein. (Os01t0101200-02) N/A N/A N/A Os01g0101200 gene:Os01g0101200 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 62060 63576 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0101200-01 N/A N/A gene:Os01g0101200 N/A N/A Os01t0101200-01 +1 irgsp exon 62060 62295 . 1 . N/A N/A 0 N/A 0 -1 Os01t0101200-01.exon1 N/A Os01t0101200-01.exon1 N/A Os01t0101200-01.exon1 transcript:Os01t0101200-01 N/A 1 N/A +1 irgsp exon 62385 62905 . 1 . N/A N/A 1 N/A 2 0 Os01t0101200-02.exon2 N/A Os01t0101200-02.exon2 N/A Os01t0101200-02.exon2 transcript:Os01t0101200-01 N/A 2 N/A +1 irgsp exon 62996 63114 . 1 . N/A N/A 1 N/A 1 2 Os01t0101200-02.exon3 N/A Os01t0101200-02.exon3 N/A Os01t0101200-02.exon3 transcript:Os01t0101200-01 N/A 3 N/A +1 irgsp exon 63248 63576 . 1 . N/A N/A 0 N/A -1 1 Os01t0101200-01.exon4 N/A Os01t0101200-01.exon4 N/A Os01t0101200-01.exon4 transcript:Os01t0101200-01 N/A 4 N/A +1 irgsp CDS 62104 62295 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0101200-01 N/A N/A transcript:Os01t0101200-01 Os01t0101200-01 N/A N/A +1 irgsp CDS 62385 62905 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0101200-01 N/A N/A transcript:Os01t0101200-01 Os01t0101200-01 N/A N/A +1 irgsp CDS 62996 63114 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0101200-01 N/A N/A transcript:Os01t0101200-01 Os01t0101200-01 N/A N/A +1 irgsp CDS 63248 63345 . 1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0101200-01 N/A N/A transcript:Os01t0101200-01 Os01t0101200-01 N/A N/A +1 irgsp five_prime_UTR 62060 62103 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-13 N/A N/A transcript:Os01t0101200-01 N/A N/A N/A +1 irgsp three_prime_UTR 63346 63576 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-13 N/A N/A transcript:Os01t0101200-01 N/A N/A N/A +1 irgsp mRNA 62112 65537 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0101200-02 N/A N/A gene:Os01g0101200 N/A N/A Os01t0101200-02 +1 irgsp exon 62112 62295 . 1 . N/A N/A 0 N/A 0 -1 Os01t0101200-02.exon1 N/A Os01t0101200-02.exon1 N/A Os01t0101200-02.exon1 transcript:Os01t0101200-02 N/A 1 N/A +1 irgsp exon 62385 62905 . 1 . N/A N/A 1 N/A 2 0 Os01t0101200-02.exon2 N/A agat-exon-1 N/A Os01t0101200-02.exon2 transcript:Os01t0101200-02 N/A 2 N/A +1 irgsp exon 62996 63114 . 1 . N/A N/A 1 N/A 1 2 Os01t0101200-02.exon3 N/A agat-exon-2 N/A Os01t0101200-02.exon3 transcript:Os01t0101200-02 N/A 3 N/A +1 irgsp exon 63248 65537 . 1 . N/A N/A 0 N/A -1 1 Os01t0101200-02.exon4 N/A Os01t0101200-02.exon4 N/A Os01t0101200-02.exon4 transcript:Os01t0101200-02 N/A 4 N/A +1 irgsp CDS 62113 62295 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0101200-02 N/A N/A transcript:Os01t0101200-02 Os01t0101200-02 N/A N/A +1 irgsp CDS 62385 62905 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0101200-02 N/A N/A transcript:Os01t0101200-02 Os01t0101200-02 N/A N/A +1 irgsp CDS 62996 63114 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0101200-02 N/A N/A transcript:Os01t0101200-02 Os01t0101200-02 N/A N/A +1 irgsp CDS 63248 63345 . 1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0101200-02 N/A N/A transcript:Os01t0101200-02 Os01t0101200-02 N/A N/A +1 irgsp five_prime_UTR 62112 62112 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-14 N/A N/A transcript:Os01t0101200-02 N/A N/A N/A +1 irgsp three_prime_UTR 63346 65537 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-14 N/A N/A transcript:Os01t0101200-02 N/A N/A N/A +1 irgsp gene 63350 66302 . -1 . N/A protein_coding N/A Similar to MRNA, partial cds, clone: RAFL22-26-L17. (Fragment). (Os01t0101300-01) N/A N/A N/A Os01g0101300 gene:Os01g0101300 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 63350 66302 . -1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0101300-01 N/A N/A gene:Os01g0101300 N/A N/A Os01t0101300-01 +1 irgsp exon 63350 63783 . -1 . N/A N/A 1 N/A -1 0 Os01t0101300-01.exon7 N/A Os01t0101300-01.exon7 N/A Os01t0101300-01.exon7 transcript:Os01t0101300-01 N/A 7 N/A +1 irgsp exon 63877 64020 . -1 . N/A N/A 1 N/A 0 0 Os01t0101300-01.exon6 N/A Os01t0101300-01.exon6 N/A Os01t0101300-01.exon6 transcript:Os01t0101300-01 N/A 6 N/A +1 irgsp exon 64339 64431 . -1 . N/A N/A 1 N/A 0 0 Os01t0101300-01.exon5 N/A Os01t0101300-01.exon5 N/A Os01t0101300-01.exon5 transcript:Os01t0101300-01 N/A 5 N/A +1 irgsp exon 64665 64779 . -1 . N/A N/A 1 N/A 0 2 Os01t0101300-01.exon4 N/A Os01t0101300-01.exon4 N/A Os01t0101300-01.exon4 transcript:Os01t0101300-01 N/A 4 N/A +1 irgsp exon 64902 65152 . -1 . N/A N/A 1 N/A 2 0 Os01t0101300-01.exon3 N/A Os01t0101300-01.exon3 N/A Os01t0101300-01.exon3 transcript:Os01t0101300-01 N/A 3 N/A +1 irgsp exon 65248 65431 . -1 . N/A N/A 1 N/A 0 2 Os01t0101300-01.exon2 N/A Os01t0101300-01.exon2 N/A Os01t0101300-01.exon2 transcript:Os01t0101300-01 N/A 2 N/A +1 irgsp exon 65628 66302 . -1 . N/A N/A 1 N/A 2 -1 Os01t0101300-01.exon1 N/A Os01t0101300-01.exon1 N/A Os01t0101300-01.exon1 transcript:Os01t0101300-01 N/A 1 N/A +1 irgsp CDS 63670 63783 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0101300-01 N/A N/A transcript:Os01t0101300-01 Os01t0101300-01 N/A N/A +1 irgsp CDS 63877 64020 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0101300-01 N/A N/A transcript:Os01t0101300-01 Os01t0101300-01 N/A N/A +1 irgsp CDS 64339 64431 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0101300-01 N/A N/A transcript:Os01t0101300-01 Os01t0101300-01 N/A N/A +1 irgsp CDS 64665 64779 . -1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0101300-01 N/A N/A transcript:Os01t0101300-01 Os01t0101300-01 N/A N/A +1 irgsp CDS 64902 65152 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0101300-01 N/A N/A transcript:Os01t0101300-01 Os01t0101300-01 N/A N/A +1 irgsp CDS 65248 65431 . -1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0101300-01 N/A N/A transcript:Os01t0101300-01 Os01t0101300-01 N/A N/A +1 irgsp CDS 65628 65950 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0101300-01 N/A N/A transcript:Os01t0101300-01 Os01t0101300-01 N/A N/A +1 irgsp five_prime_UTR 65951 66302 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-15 N/A N/A transcript:Os01t0101300-01 N/A N/A N/A +1 irgsp three_prime_UTR 63350 63669 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-15 N/A N/A transcript:Os01t0101300-01 N/A N/A N/A +1 irgsp gene 72816 78349 . 1 . N/A protein_coding N/A Immunoglobulin-like fold domain containing protein. (Os01t0101600-01);Immunoglobulin-like fold domain containing protein. (Os01t0101600-02);Hypothetical conserved gene. (Os01t0101600-03) N/A N/A N/A Os01g0101600 gene:Os01g0101600 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 72816 78349 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0101600-01 N/A N/A gene:Os01g0101600 N/A N/A Os01t0101600-01 +1 irgsp exon 72816 73935 . 1 . N/A N/A 0 N/A 1 -1 Os01t0101600-01.exon1 N/A Os01t0101600-01.exon1 N/A Os01t0101600-01.exon1 transcript:Os01t0101600-01 N/A 1 N/A +1 irgsp exon 74468 74981 . 1 . N/A N/A 0 N/A 2 1 Os01t0101600-02.exon2 N/A Os01t0101600-02.exon2 N/A Os01t0101600-02.exon2 transcript:Os01t0101600-01 N/A 2 N/A +1 irgsp exon 75619 77205 . 1 . N/A N/A 0 N/A -1 2 Os01t0101600-01.exon3 N/A Os01t0101600-01.exon3 N/A Os01t0101600-01.exon3 transcript:Os01t0101600-01 N/A 3 N/A +1 irgsp exon 77333 78349 . 1 . N/A N/A 0 N/A -1 -1 Os01t0101600-01.exon4 N/A Os01t0101600-01.exon4 N/A Os01t0101600-01.exon4 transcript:Os01t0101600-01 N/A 4 N/A +1 irgsp CDS 72903 73935 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0101600-01 N/A N/A transcript:Os01t0101600-01 Os01t0101600-01 N/A N/A +1 irgsp CDS 74468 74981 . 1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0101600-01 N/A N/A transcript:Os01t0101600-01 Os01t0101600-01 N/A N/A +1 irgsp CDS 75619 77008 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0101600-01 N/A N/A transcript:Os01t0101600-01 Os01t0101600-01 N/A N/A +1 irgsp five_prime_UTR 72816 72902 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-16 N/A N/A transcript:Os01t0101600-01 N/A N/A N/A +1 irgsp three_prime_UTR 77009 77205 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-16 N/A N/A transcript:Os01t0101600-01 N/A N/A N/A +1 irgsp three_prime_UTR 77333 78349 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-17 N/A N/A transcript:Os01t0101600-01 N/A N/A N/A +1 irgsp mRNA 72823 77699 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0101600-02 N/A N/A gene:Os01g0101600 N/A N/A Os01t0101600-02 +1 irgsp exon 72823 73935 . 1 . N/A N/A 0 N/A 1 -1 Os01t0101600-02.exon1 N/A Os01t0101600-02.exon1 N/A Os01t0101600-02.exon1 transcript:Os01t0101600-02 N/A 1 N/A +1 irgsp exon 74468 74981 . 1 . N/A N/A 0 N/A 2 1 Os01t0101600-02.exon2 N/A agat-exon-3 N/A Os01t0101600-02.exon2 transcript:Os01t0101600-02 N/A 2 N/A +1 irgsp exon 75619 77699 . 1 . N/A N/A 0 N/A -1 2 Os01t0101600-02.exon3 N/A Os01t0101600-02.exon3 N/A Os01t0101600-02.exon3 transcript:Os01t0101600-02 N/A 3 N/A +1 irgsp CDS 72903 73935 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0101600-02 N/A N/A transcript:Os01t0101600-02 Os01t0101600-02 N/A N/A +1 irgsp CDS 74468 74981 . 1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0101600-02 N/A N/A transcript:Os01t0101600-02 Os01t0101600-02 N/A N/A +1 irgsp CDS 75619 77008 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0101600-02 N/A N/A transcript:Os01t0101600-02 Os01t0101600-02 N/A N/A +1 irgsp five_prime_UTR 72823 72902 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-17 N/A N/A transcript:Os01t0101600-02 N/A N/A N/A +1 irgsp three_prime_UTR 77009 77699 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-18 N/A N/A transcript:Os01t0101600-02 N/A N/A N/A +1 irgsp mRNA 75942 77699 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0101600-03 N/A N/A gene:Os01g0101600 N/A N/A Os01t0101600-03 +1 irgsp exon 75942 77699 . 1 . N/A N/A 0 N/A -1 -1 Os01t0101600-03.exon1 N/A Os01t0101600-03.exon1 N/A Os01t0101600-03.exon1 transcript:Os01t0101600-03 N/A 1 N/A +1 irgsp CDS 75944 77008 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0101600-03 N/A N/A transcript:Os01t0101600-03 Os01t0101600-03 N/A N/A +1 irgsp five_prime_UTR 75942 75943 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-18 N/A N/A transcript:Os01t0101600-03 N/A N/A N/A +1 irgsp three_prime_UTR 77009 77699 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-19 N/A N/A transcript:Os01t0101600-03 N/A N/A N/A +1 irgsp gene 82426 84095 . 1 . N/A protein_coding N/A Similar to chaperone protein dnaJ 20. (Os01t0101700-00) N/A N/A N/A Os01g0101700 gene:Os01g0101700 irgspv1.0-20170804-genes DnaJ domain protein C1, rice DJC26 homolog N/A N/A N/A N/A +1 irgsp mRNA 82426 84095 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0101700-00 N/A N/A gene:Os01g0101700 N/A N/A Os01t0101700-00 +1 irgsp exon 82426 82932 . 1 . N/A N/A 1 N/A 0 -1 Os01t0101700-00.exon1 N/A Os01t0101700-00.exon1 N/A Os01t0101700-00.exon1 transcript:Os01t0101700-00 N/A 1 N/A +1 irgsp exon 83724 84095 . 1 . N/A N/A 1 N/A -1 0 Os01t0101700-00.exon2 N/A Os01t0101700-00.exon2 N/A Os01t0101700-00.exon2 transcript:Os01t0101700-00 N/A 2 N/A +1 irgsp CDS 82507 82932 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0101700-00 N/A N/A transcript:Os01t0101700-00 Os01t0101700-00 N/A N/A +1 irgsp CDS 83724 83864 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0101700-00 N/A N/A transcript:Os01t0101700-00 Os01t0101700-00 N/A N/A +1 irgsp five_prime_UTR 82426 82506 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-19 N/A N/A transcript:Os01t0101700-00 N/A N/A N/A +1 irgsp three_prime_UTR 83865 84095 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-20 N/A N/A transcript:Os01t0101700-00 N/A N/A N/A +1 irgsp gene 85337 88844 . 1 . N/A protein_coding N/A Conserved hypothetical protein. (Os01t0101800-01) N/A N/A N/A Os01g0101800 gene:Os01g0101800 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 85337 88844 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0101800-01 N/A N/A gene:Os01g0101800 N/A N/A Os01t0101800-01 +1 irgsp exon 85337 85600 . 1 . N/A N/A 1 N/A 0 -1 Os01t0101800-01.exon1 N/A Os01t0101800-01.exon1 N/A Os01t0101800-01.exon1 transcript:Os01t0101800-01 N/A 1 N/A +1 irgsp exon 85737 85830 . 1 . N/A N/A 1 N/A 1 0 Os01t0101800-01.exon2 N/A Os01t0101800-01.exon2 N/A Os01t0101800-01.exon2 transcript:Os01t0101800-01 N/A 2 N/A +1 irgsp exon 85935 86086 . 1 . N/A N/A 1 N/A 0 1 Os01t0101800-01.exon3 N/A Os01t0101800-01.exon3 N/A Os01t0101800-01.exon3 transcript:Os01t0101800-01 N/A 3 N/A +1 irgsp exon 86212 86299 . 1 . N/A N/A 1 N/A 1 0 Os01t0101800-01.exon4 N/A Os01t0101800-01.exon4 N/A Os01t0101800-01.exon4 transcript:Os01t0101800-01 N/A 4 N/A +1 irgsp exon 86399 87681 . 1 . N/A N/A 1 N/A 0 1 Os01t0101800-01.exon5 N/A Os01t0101800-01.exon5 N/A Os01t0101800-01.exon5 transcript:Os01t0101800-01 N/A 5 N/A +1 irgsp exon 88291 88398 . 1 . N/A N/A 1 N/A 0 0 Os01t0101800-01.exon6 N/A Os01t0101800-01.exon6 N/A Os01t0101800-01.exon6 transcript:Os01t0101800-01 N/A 6 N/A +1 irgsp exon 88500 88844 . 1 . N/A N/A 1 N/A -1 0 Os01t0101800-01.exon7 N/A Os01t0101800-01.exon7 N/A Os01t0101800-01.exon7 transcript:Os01t0101800-01 N/A 7 N/A +1 irgsp CDS 85379 85600 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0101800-01 N/A N/A transcript:Os01t0101800-01 Os01t0101800-01 N/A N/A +1 irgsp CDS 85737 85830 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0101800-01 N/A N/A transcript:Os01t0101800-01 Os01t0101800-01 N/A N/A +1 irgsp CDS 85935 86086 . 1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0101800-01 N/A N/A transcript:Os01t0101800-01 Os01t0101800-01 N/A N/A +1 irgsp CDS 86212 86299 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0101800-01 N/A N/A transcript:Os01t0101800-01 Os01t0101800-01 N/A N/A +1 irgsp CDS 86399 87681 . 1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0101800-01 N/A N/A transcript:Os01t0101800-01 Os01t0101800-01 N/A N/A +1 irgsp CDS 88291 88398 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0101800-01 N/A N/A transcript:Os01t0101800-01 Os01t0101800-01 N/A N/A +1 irgsp CDS 88500 88583 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0101800-01 N/A N/A transcript:Os01t0101800-01 Os01t0101800-01 N/A N/A +1 irgsp five_prime_UTR 85337 85378 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-20 N/A N/A transcript:Os01t0101800-01 N/A N/A N/A +1 irgsp three_prime_UTR 88584 88844 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-21 N/A N/A transcript:Os01t0101800-01 N/A N/A N/A +1 irgsp gene 86211 88583 . -1 . N/A protein_coding N/A Hypothetical protein. (Os01t0101850-00) N/A N/A N/A Os01g0101850 gene:Os01g0101850 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 86211 88583 . -1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0101850-00 N/A N/A gene:Os01g0101850 N/A N/A Os01t0101850-00 +1 irgsp exon 86211 86277 . -1 . N/A N/A 1 N/A -1 -1 Os01t0101850-00.exon4 N/A Os01t0101850-00.exon4 N/A Os01t0101850-00.exon4 transcript:Os01t0101850-00 N/A 4 N/A +1 irgsp exon 86384 87694 . -1 . N/A N/A 1 N/A -1 -1 Os01t0101850-00.exon3 N/A Os01t0101850-00.exon3 N/A Os01t0101850-00.exon3 transcript:Os01t0101850-00 N/A 3 N/A +1 irgsp exon 88308 88396 . -1 . N/A N/A 1 N/A -1 -1 Os01t0101850-00.exon2 N/A Os01t0101850-00.exon2 N/A Os01t0101850-00.exon2 transcript:Os01t0101850-00 N/A 2 N/A +1 irgsp exon 88496 88583 . -1 . N/A N/A 1 N/A -1 -1 Os01t0101850-00.exon1 N/A Os01t0101850-00.exon1 N/A Os01t0101850-00.exon1 transcript:Os01t0101850-00 N/A 1 N/A +1 irgsp CDS 87327 87662 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0101850-00 N/A N/A transcript:Os01t0101850-00 Os01t0101850-00 N/A N/A +1 irgsp five_prime_UTR 87663 87694 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-21 N/A N/A transcript:Os01t0101850-00 N/A N/A N/A +1 irgsp five_prime_UTR 88308 88396 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-22 N/A N/A transcript:Os01t0101850-00 N/A N/A N/A +1 irgsp five_prime_UTR 88496 88583 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-23 N/A N/A transcript:Os01t0101850-00 N/A N/A N/A +1 irgsp three_prime_UTR 86211 86277 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-22 N/A N/A transcript:Os01t0101850-00 N/A N/A N/A +1 irgsp three_prime_UTR 86384 87326 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-23 N/A N/A transcript:Os01t0101850-00 N/A N/A N/A +1 irgsp gene 88883 89228 . -1 . N/A protein_coding N/A Similar to OSIGBa0075F02.3 protein. (Os01t0101900-00) N/A N/A N/A Os01g0101900 gene:Os01g0101900 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 88883 89228 . -1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0101900-00 N/A N/A gene:Os01g0101900 N/A N/A Os01t0101900-00 +1 irgsp exon 88883 89228 . -1 . N/A N/A 1 N/A -1 -1 Os01t0101900-00.exon1 N/A Os01t0101900-00.exon1 N/A Os01t0101900-00.exon1 transcript:Os01t0101900-00 N/A 1 N/A +1 irgsp CDS 88986 89204 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0101900-00 N/A N/A transcript:Os01t0101900-00 Os01t0101900-00 N/A N/A +1 irgsp five_prime_UTR 89205 89228 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-24 N/A N/A transcript:Os01t0101900-00 N/A N/A N/A +1 irgsp three_prime_UTR 88883 88985 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-24 N/A N/A transcript:Os01t0101900-00 N/A N/A N/A +1 irgsp gene 89763 91465 . -1 . N/A protein_coding N/A Phosphoesterase family protein. (Os01t0102000-01) N/A N/A N/A Os01g0102000 gene:Os01g0102000 irgspv1.0-20170804-genes NON-SPECIFIC PHOSPHOLIPASE C5 N/A N/A N/A N/A +1 irgsp mRNA 89763 91465 . -1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0102000-01 N/A N/A gene:Os01g0102000 N/A N/A Os01t0102000-01 +1 irgsp exon 89763 91465 . -1 . N/A N/A 1 N/A -1 -1 Os01t0102000-01.exon1 N/A Os01t0102000-01.exon1 N/A Os01t0102000-01.exon1 transcript:Os01t0102000-01 N/A 1 N/A +1 irgsp CDS 89825 91411 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0102000-01 N/A N/A transcript:Os01t0102000-01 Os01t0102000-01 N/A N/A +1 irgsp five_prime_UTR 91412 91465 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-25 N/A N/A transcript:Os01t0102000-01 N/A N/A N/A +1 irgsp three_prime_UTR 89763 89824 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-25 N/A N/A transcript:Os01t0102000-01 N/A N/A N/A +1 irgsp gene 134300 135439 . 1 . N/A protein_coding N/A Thylakoid lumen protein, Photosynthesis and chloroplast development (Os01t0102300-01) N/A N/A N/A Os01g0102300 gene:Os01g0102300 irgspv1.0-20170804-genes OsTLP27 N/A N/A N/A N/A +1 irgsp mRNA 134300 135439 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0102300-01 N/A N/A gene:Os01g0102300 N/A N/A Os01t0102300-01 +1 irgsp exon 134300 134615 . 1 . N/A N/A 1 N/A 2 -1 Os01t0102300-01.exon1 N/A Os01t0102300-01.exon1 N/A Os01t0102300-01.exon1 transcript:Os01t0102300-01 N/A 1 N/A +1 irgsp exon 134698 134824 . 1 . N/A N/A 1 N/A 0 2 Os01t0102300-01.exon2 N/A Os01t0102300-01.exon2 N/A Os01t0102300-01.exon2 transcript:Os01t0102300-01 N/A 2 N/A +1 irgsp exon 134912 135439 . 1 . N/A N/A 1 N/A -1 0 Os01t0102300-01.exon3 N/A Os01t0102300-01.exon3 N/A Os01t0102300-01.exon3 transcript:Os01t0102300-01 N/A 3 N/A +1 irgsp CDS 134311 134615 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0102300-01 N/A N/A transcript:Os01t0102300-01 Os01t0102300-01 N/A N/A +1 irgsp CDS 134698 134824 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0102300-01 N/A N/A transcript:Os01t0102300-01 Os01t0102300-01 N/A N/A +1 irgsp CDS 134912 135253 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0102300-01 N/A N/A transcript:Os01t0102300-01 Os01t0102300-01 N/A N/A +1 irgsp five_prime_UTR 134300 134310 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-26 N/A N/A transcript:Os01t0102300-01 N/A N/A N/A +1 irgsp three_prime_UTR 135254 135439 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-26 N/A N/A transcript:Os01t0102300-01 N/A N/A N/A +1 irgsp gene 139826 141555 . 1 . N/A protein_coding N/A Histone-fold domain containing protein. (Os01t0102400-01) N/A N/A N/A Os01g0102400 gene:Os01g0102400 irgspv1.0-20170804-genes HAP5H SUBUNIT OF CCAAT-BOX BINDING COMPLEX N/A N/A N/A N/A +1 irgsp mRNA 139826 141555 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0102400-01 N/A N/A gene:Os01g0102400 N/A N/A Os01t0102400-01 +1 irgsp exon 139826 139906 . 1 . N/A N/A 1 N/A -1 -1 Os01t0102400-01.exon1 N/A Os01t0102400-01.exon1 N/A Os01t0102400-01.exon1 transcript:Os01t0102400-01 N/A 1 N/A +1 irgsp exon 140120 141555 . 1 . N/A N/A 1 N/A -1 -1 Os01t0102400-01.exon2 N/A Os01t0102400-01.exon2 N/A Os01t0102400-01.exon2 transcript:Os01t0102400-01 N/A 2 N/A +1 irgsp CDS 140150 141415 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0102400-01 N/A N/A transcript:Os01t0102400-01 Os01t0102400-01 N/A N/A +1 irgsp five_prime_UTR 139826 139906 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-27 N/A N/A transcript:Os01t0102400-01 N/A N/A N/A +1 irgsp five_prime_UTR 140120 140149 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-28 N/A N/A transcript:Os01t0102400-01 N/A N/A N/A +1 irgsp three_prime_UTR 141416 141555 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-27 N/A N/A transcript:Os01t0102400-01 N/A N/A N/A +1 irgsp gene 141959 144554 . 1 . N/A protein_coding N/A Conserved hypothetical protein. (Os01t0102500-01) N/A N/A N/A Os01g0102500 gene:Os01g0102500 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 141959 144554 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0102500-01 N/A N/A gene:Os01g0102500 N/A N/A Os01t0102500-01 +1 irgsp exon 141959 142631 . 1 . N/A N/A 1 N/A 2 -1 Os01t0102500-01.exon1 N/A Os01t0102500-01.exon1 N/A Os01t0102500-01.exon1 transcript:Os01t0102500-01 N/A 1 N/A +1 irgsp exon 143191 143431 . 1 . N/A N/A 1 N/A 0 2 Os01t0102500-01.exon2 N/A Os01t0102500-01.exon2 N/A Os01t0102500-01.exon2 transcript:Os01t0102500-01 N/A 2 N/A +1 irgsp exon 143563 143680 . 1 . N/A N/A 1 N/A 1 0 Os01t0102500-01.exon3 N/A Os01t0102500-01.exon3 N/A Os01t0102500-01.exon3 transcript:Os01t0102500-01 N/A 3 N/A +1 irgsp exon 143817 144554 . 1 . N/A N/A 1 N/A -1 1 Os01t0102500-01.exon4 N/A Os01t0102500-01.exon4 N/A Os01t0102500-01.exon4 transcript:Os01t0102500-01 N/A 4 N/A +1 irgsp CDS 142084 142631 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0102500-01 N/A N/A transcript:Os01t0102500-01 Os01t0102500-01 N/A N/A +1 irgsp CDS 143191 143431 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0102500-01 N/A N/A transcript:Os01t0102500-01 Os01t0102500-01 N/A N/A +1 irgsp CDS 143563 143680 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0102500-01 N/A N/A transcript:Os01t0102500-01 Os01t0102500-01 N/A N/A +1 irgsp CDS 143817 143908 . 1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0102500-01 N/A N/A transcript:Os01t0102500-01 Os01t0102500-01 N/A N/A +1 irgsp five_prime_UTR 141959 142083 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-29 N/A N/A transcript:Os01t0102500-01 N/A N/A N/A +1 irgsp three_prime_UTR 143909 144554 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-28 N/A N/A transcript:Os01t0102500-01 N/A N/A N/A +1 irgsp gene 145603 147847 . 1 . N/A protein_coding N/A Shikimate kinase domain containing protein. (Os01t0102600-01);Similar to shikimate kinase family protein. (Os01t0102600-02) N/A N/A N/A Os01g0102600 gene:Os01g0102600 irgspv1.0-20170804-genes Shikimate kinase 4 N/A N/A N/A N/A +1 irgsp mRNA 145603 147847 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0102600-01 N/A N/A gene:Os01g0102600 N/A N/A Os01t0102600-01 +1 irgsp exon 145603 145786 . 1 . N/A N/A 0 N/A 1 -1 Os01t0102600-01.exon1 N/A Os01t0102600-01.exon1 N/A Os01t0102600-01.exon1 transcript:Os01t0102600-01 N/A 1 N/A +1 irgsp exon 145905 145951 . 1 . N/A N/A 0 N/A 0 1 Os01t0102600-01.exon2 N/A Os01t0102600-01.exon2 N/A Os01t0102600-01.exon2 transcript:Os01t0102600-01 N/A 2 N/A +1 irgsp exon 146028 146082 . 1 . N/A N/A 0 N/A 1 0 Os01t0102600-01.exon3 N/A Os01t0102600-01.exon3 N/A Os01t0102600-01.exon3 transcript:Os01t0102600-01 N/A 3 N/A +1 irgsp exon 146179 146339 . 1 . N/A N/A 0 N/A 0 1 Os01t0102600-01.exon4 N/A Os01t0102600-01.exon4 N/A Os01t0102600-01.exon4 transcript:Os01t0102600-01 N/A 4 N/A +1 irgsp exon 146450 146532 . 1 . N/A N/A 0 N/A 2 0 Os01t0102600-01.exon5 N/A Os01t0102600-01.exon5 N/A Os01t0102600-01.exon5 transcript:Os01t0102600-01 N/A 5 N/A +1 irgsp exon 146611 146719 . 1 . N/A N/A 0 N/A 0 2 Os01t0102600-01.exon6 N/A Os01t0102600-01.exon6 N/A Os01t0102600-01.exon6 transcript:Os01t0102600-01 N/A 6 N/A +1 irgsp exon 147106 147184 . 1 . N/A N/A 0 N/A 1 0 Os01t0102600-01.exon7 N/A Os01t0102600-01.exon7 N/A Os01t0102600-01.exon7 transcript:Os01t0102600-01 N/A 7 N/A +1 irgsp exon 147311 147375 . 1 . N/A N/A 1 N/A 0 1 Os01t0102600-02.exon2 N/A Os01t0102600-02.exon2 N/A Os01t0102600-02.exon2 transcript:Os01t0102600-01 N/A 8 N/A +1 irgsp exon 147507 147847 . 1 . N/A N/A 0 N/A -1 0 Os01t0102600-01.exon9 N/A Os01t0102600-01.exon9 N/A Os01t0102600-01.exon9 transcript:Os01t0102600-01 N/A 9 N/A +1 irgsp CDS 145645 145786 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0102600-01 N/A N/A transcript:Os01t0102600-01 Os01t0102600-01 N/A N/A +1 irgsp CDS 145905 145951 . 1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0102600-01 N/A N/A transcript:Os01t0102600-01 Os01t0102600-01 N/A N/A +1 irgsp CDS 146028 146082 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0102600-01 N/A N/A transcript:Os01t0102600-01 Os01t0102600-01 N/A N/A +1 irgsp CDS 146179 146339 . 1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0102600-01 N/A N/A transcript:Os01t0102600-01 Os01t0102600-01 N/A N/A +1 irgsp CDS 146450 146532 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0102600-01 N/A N/A transcript:Os01t0102600-01 Os01t0102600-01 N/A N/A +1 irgsp CDS 146611 146719 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0102600-01 N/A N/A transcript:Os01t0102600-01 Os01t0102600-01 N/A N/A +1 irgsp CDS 147106 147184 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0102600-01 N/A N/A transcript:Os01t0102600-01 Os01t0102600-01 N/A N/A +1 irgsp CDS 147311 147375 . 1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0102600-01 N/A N/A transcript:Os01t0102600-01 Os01t0102600-01 N/A N/A +1 irgsp CDS 147507 147575 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0102600-01 N/A N/A transcript:Os01t0102600-01 Os01t0102600-01 N/A N/A +1 irgsp five_prime_UTR 145603 145644 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-30 N/A N/A transcript:Os01t0102600-01 N/A N/A N/A +1 irgsp three_prime_UTR 147576 147847 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-29 N/A N/A transcript:Os01t0102600-01 N/A N/A N/A +1 irgsp mRNA 147104 147805 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0102600-02 N/A N/A gene:Os01g0102600 N/A N/A Os01t0102600-02 +1 irgsp exon 147104 147184 . 1 . N/A N/A 0 N/A 1 -1 Os01t0102600-02.exon1 N/A Os01t0102600-02.exon1 N/A Os01t0102600-02.exon1 transcript:Os01t0102600-02 N/A 1 N/A +1 irgsp exon 147311 147375 . 1 . N/A N/A 1 N/A 0 1 Os01t0102600-02.exon2 N/A agat-exon-4 N/A Os01t0102600-02.exon2 transcript:Os01t0102600-02 N/A 2 N/A +1 irgsp exon 147507 147805 . 1 . N/A N/A 0 N/A -1 0 Os01t0102600-02.exon3 N/A Os01t0102600-02.exon3 N/A Os01t0102600-02.exon3 transcript:Os01t0102600-02 N/A 3 N/A +1 irgsp CDS 147106 147184 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0102600-02 N/A N/A transcript:Os01t0102600-02 Os01t0102600-02 N/A N/A +1 irgsp CDS 147311 147375 . 1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0102600-02 N/A N/A transcript:Os01t0102600-02 Os01t0102600-02 N/A N/A +1 irgsp CDS 147507 147575 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0102600-02 N/A N/A transcript:Os01t0102600-02 Os01t0102600-02 N/A N/A +1 irgsp five_prime_UTR 147104 147105 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-31 N/A N/A transcript:Os01t0102600-02 N/A N/A N/A +1 irgsp three_prime_UTR 147576 147805 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-30 N/A N/A transcript:Os01t0102600-02 N/A N/A N/A +1 irgsp gene 148085 150568 . 1 . N/A protein_coding N/A Translocon-associated beta family protein. (Os01t0102700-01) N/A N/A N/A Os01g0102700 gene:Os01g0102700 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 148085 150568 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0102700-01 N/A N/A gene:Os01g0102700 N/A N/A Os01t0102700-01 +1 irgsp exon 148085 148313 . 1 . N/A N/A 1 N/A 2 -1 Os01t0102700-01.exon1 N/A Os01t0102700-01.exon1 N/A Os01t0102700-01.exon1 transcript:Os01t0102700-01 N/A 1 N/A +1 irgsp exon 149450 149548 . 1 . N/A N/A 1 N/A 2 2 Os01t0102700-01.exon2 N/A Os01t0102700-01.exon2 N/A Os01t0102700-01.exon2 transcript:Os01t0102700-01 N/A 2 N/A +1 irgsp exon 149634 149742 . 1 . N/A N/A 1 N/A 0 2 Os01t0102700-01.exon3 N/A Os01t0102700-01.exon3 N/A Os01t0102700-01.exon3 transcript:Os01t0102700-01 N/A 3 N/A +1 irgsp exon 149856 149931 . 1 . N/A N/A 1 N/A 1 0 Os01t0102700-01.exon4 N/A Os01t0102700-01.exon4 N/A Os01t0102700-01.exon4 transcript:Os01t0102700-01 N/A 4 N/A +1 irgsp exon 150152 150568 . 1 . N/A N/A 1 N/A -1 1 Os01t0102700-01.exon5 N/A Os01t0102700-01.exon5 N/A Os01t0102700-01.exon5 transcript:Os01t0102700-01 N/A 5 N/A +1 irgsp CDS 148147 148313 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0102700-01 N/A N/A transcript:Os01t0102700-01 Os01t0102700-01 N/A N/A +1 irgsp CDS 149450 149548 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0102700-01 N/A N/A transcript:Os01t0102700-01 Os01t0102700-01 N/A N/A +1 irgsp CDS 149634 149742 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0102700-01 N/A N/A transcript:Os01t0102700-01 Os01t0102700-01 N/A N/A +1 irgsp CDS 149856 149931 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0102700-01 N/A N/A transcript:Os01t0102700-01 Os01t0102700-01 N/A N/A +1 irgsp CDS 150152 150318 . 1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0102700-01 N/A N/A transcript:Os01t0102700-01 Os01t0102700-01 N/A N/A +1 irgsp five_prime_UTR 148085 148146 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-32 N/A N/A transcript:Os01t0102700-01 N/A N/A N/A +1 irgsp three_prime_UTR 150319 150568 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-31 N/A N/A transcript:Os01t0102700-01 N/A N/A N/A +1 irgsp gene 152853 156449 . 1 . N/A protein_coding N/A Similar to chromatin remodeling complex subunit. (Os01t0102800-01) N/A N/A N/A Os01g0102800 gene:Os01g0102800 irgspv1.0-20170804-genes Cockayne syndrome WD-repeat protein N/A N/A N/A N/A +1 irgsp mRNA 152853 156449 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0102800-01 N/A N/A gene:Os01g0102800 N/A N/A Os01t0102800-01 +1 irgsp exon 152853 153025 . 1 . N/A N/A 1 N/A 1 -1 Os01t0102800-01.exon1 N/A Os01t0102800-01.exon1 N/A Os01t0102800-01.exon1 transcript:Os01t0102800-01 N/A 1 N/A +1 irgsp exon 153178 154646 . 1 . N/A N/A 1 N/A 0 1 Os01t0102800-01.exon2 N/A Os01t0102800-01.exon2 N/A Os01t0102800-01.exon2 transcript:Os01t0102800-01 N/A 2 N/A +1 irgsp exon 155010 155450 . 1 . N/A N/A 1 N/A 0 0 Os01t0102800-01.exon3 N/A Os01t0102800-01.exon3 N/A Os01t0102800-01.exon3 transcript:Os01t0102800-01 N/A 3 N/A +1 irgsp exon 155543 156449 . 1 . N/A N/A 1 N/A -1 0 Os01t0102800-01.exon4 N/A Os01t0102800-01.exon4 N/A Os01t0102800-01.exon4 transcript:Os01t0102800-01 N/A 4 N/A +1 irgsp CDS 152854 153025 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0102800-01 N/A N/A transcript:Os01t0102800-01 Os01t0102800-01 N/A N/A +1 irgsp CDS 153178 154646 . 1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0102800-01 N/A N/A transcript:Os01t0102800-01 Os01t0102800-01 N/A N/A +1 irgsp CDS 155010 155450 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0102800-01 N/A N/A transcript:Os01t0102800-01 Os01t0102800-01 N/A N/A +1 irgsp CDS 155543 156214 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0102800-01 N/A N/A transcript:Os01t0102800-01 Os01t0102800-01 N/A N/A +1 irgsp five_prime_UTR 152853 152853 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-33 N/A N/A transcript:Os01t0102800-01 N/A N/A N/A +1 irgsp three_prime_UTR 156215 156449 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-32 N/A N/A transcript:Os01t0102800-01 N/A N/A N/A +1 irgsp gene 164577 168921 . 1 . N/A protein_coding N/A Similar to nitrilase 2. (Os01t0102850-00) N/A N/A N/A Os01g0102850 gene:Os01g0102850 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 164577 168921 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0102850-00 N/A N/A gene:Os01g0102850 N/A N/A Os01t0102850-00 +1 irgsp exon 164577 164905 . 1 . N/A N/A 1 N/A -1 -1 Os01t0102850-00.exon1 N/A Os01t0102850-00.exon1 N/A Os01t0102850-00.exon1 transcript:Os01t0102850-00 N/A 1 N/A +1 irgsp exon 168499 168921 . 1 . N/A N/A 1 N/A 0 -1 Os01t0102850-00.exon2 N/A Os01t0102850-00.exon2 N/A Os01t0102850-00.exon2 transcript:Os01t0102850-00 N/A 2 N/A +1 irgsp CDS 168805 168921 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0102850-00 N/A N/A transcript:Os01t0102850-00 Os01t0102850-00 N/A N/A +1 irgsp five_prime_UTR 164577 164905 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-34 N/A N/A transcript:Os01t0102850-00 N/A N/A N/A +1 irgsp five_prime_UTR 168499 168804 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-35 N/A N/A transcript:Os01t0102850-00 N/A N/A N/A +1 irgsp gene 169390 170316 . -1 . N/A protein_coding N/A Light-regulated protein, Regulation of light-dependent attachment of LEAF-TYPE FERREDOXIN-NADP+ OXIDOREDUCTASE (LFNR) to the thylakoid membrane (Os01t0102900-01) N/A N/A N/A Os01g0102900 gene:Os01g0102900 irgspv1.0-20170804-genes LIGHT-REGULATED GENE 1 N/A N/A N/A N/A +1 irgsp mRNA 169390 170316 . -1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0102900-01 N/A N/A gene:Os01g0102900 N/A N/A Os01t0102900-01 +1 irgsp exon 169390 169656 . -1 . N/A N/A 1 N/A -1 2 Os01t0102900-01.exon3 N/A Os01t0102900-01.exon3 N/A Os01t0102900-01.exon3 transcript:Os01t0102900-01 N/A 3 N/A +1 irgsp exon 169751 169909 . -1 . N/A N/A 1 N/A 2 2 Os01t0102900-01.exon2 N/A Os01t0102900-01.exon2 N/A Os01t0102900-01.exon2 transcript:Os01t0102900-01 N/A 2 N/A +1 irgsp exon 170091 170316 . -1 . N/A N/A 1 N/A 2 -1 Os01t0102900-01.exon1 N/A Os01t0102900-01.exon1 N/A Os01t0102900-01.exon1 transcript:Os01t0102900-01 N/A 1 N/A +1 irgsp CDS 169599 169656 . -1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0102900-01 N/A N/A transcript:Os01t0102900-01 Os01t0102900-01 N/A N/A +1 irgsp CDS 169751 169909 . -1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0102900-01 N/A N/A transcript:Os01t0102900-01 Os01t0102900-01 N/A N/A +1 irgsp CDS 170091 170260 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0102900-01 N/A N/A transcript:Os01t0102900-01 Os01t0102900-01 N/A N/A +1 irgsp five_prime_UTR 170261 170316 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-36 N/A N/A transcript:Os01t0102900-01 N/A N/A N/A +1 irgsp three_prime_UTR 169390 169598 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-33 N/A N/A transcript:Os01t0102900-01 N/A N/A N/A +1 irgsp gene 170798 173144 . -1 . N/A protein_coding N/A Snf7 family protein. (Os01t0103000-01) N/A N/A N/A Os01g0103000 gene:Os01g0103000 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 170798 173144 . -1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0103000-01 N/A N/A gene:Os01g0103000 N/A N/A Os01t0103000-01 +1 irgsp exon 170798 171095 . -1 . N/A N/A 1 N/A -1 0 Os01t0103000-01.exon7 N/A Os01t0103000-01.exon7 N/A Os01t0103000-01.exon7 transcript:Os01t0103000-01 N/A 7 N/A +1 irgsp exon 171406 171554 . -1 . N/A N/A 1 N/A 0 1 Os01t0103000-01.exon6 N/A Os01t0103000-01.exon6 N/A Os01t0103000-01.exon6 transcript:Os01t0103000-01 N/A 6 N/A +1 irgsp exon 171764 171875 . -1 . N/A N/A 1 N/A 1 0 Os01t0103000-01.exon5 N/A Os01t0103000-01.exon5 N/A Os01t0103000-01.exon5 transcript:Os01t0103000-01 N/A 5 N/A +1 irgsp exon 172398 172469 . -1 . N/A N/A 1 N/A 0 0 Os01t0103000-01.exon4 N/A Os01t0103000-01.exon4 N/A Os01t0103000-01.exon4 transcript:Os01t0103000-01 N/A 4 N/A +1 irgsp exon 172578 172671 . -1 . N/A N/A 1 N/A 0 2 Os01t0103000-01.exon3 N/A Os01t0103000-01.exon3 N/A Os01t0103000-01.exon3 transcript:Os01t0103000-01 N/A 3 N/A +1 irgsp exon 172770 172921 . -1 . N/A N/A 1 N/A 2 0 Os01t0103000-01.exon2 N/A Os01t0103000-01.exon2 N/A Os01t0103000-01.exon2 transcript:Os01t0103000-01 N/A 2 N/A +1 irgsp exon 173004 173144 . -1 . N/A N/A 1 N/A 0 -1 Os01t0103000-01.exon1 N/A Os01t0103000-01.exon1 N/A Os01t0103000-01.exon1 transcript:Os01t0103000-01 N/A 1 N/A +1 irgsp CDS 171045 171095 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103000-01 N/A N/A transcript:Os01t0103000-01 Os01t0103000-01 N/A N/A +1 irgsp CDS 171406 171554 . -1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103000-01 N/A N/A transcript:Os01t0103000-01 Os01t0103000-01 N/A N/A +1 irgsp CDS 171764 171875 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103000-01 N/A N/A transcript:Os01t0103000-01 Os01t0103000-01 N/A N/A +1 irgsp CDS 172398 172469 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103000-01 N/A N/A transcript:Os01t0103000-01 Os01t0103000-01 N/A N/A +1 irgsp CDS 172578 172671 . -1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103000-01 N/A N/A transcript:Os01t0103000-01 Os01t0103000-01 N/A N/A +1 irgsp CDS 172770 172921 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103000-01 N/A N/A transcript:Os01t0103000-01 Os01t0103000-01 N/A N/A +1 irgsp CDS 173004 173072 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103000-01 N/A N/A transcript:Os01t0103000-01 Os01t0103000-01 N/A N/A +1 irgsp five_prime_UTR 173073 173144 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-37 N/A N/A transcript:Os01t0103000-01 N/A N/A N/A +1 irgsp three_prime_UTR 170798 171044 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-34 N/A N/A transcript:Os01t0103000-01 N/A N/A N/A +1 irgsp gene 178607 180575 . 1 . N/A protein_coding N/A TGF-beta receptor, type I/II extracellular region family protein. (Os01t0103100-01);Similar to predicted protein. (Os01t0103100-02) N/A N/A N/A Os01g0103100 gene:Os01g0103100 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 178607 180548 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0103100-01 N/A N/A gene:Os01g0103100 N/A N/A Os01t0103100-01 +1 irgsp exon 178607 180548 . 1 . N/A N/A 0 N/A -1 -1 Os01t0103100-01.exon1 N/A Os01t0103100-01.exon1 N/A Os01t0103100-01.exon1 transcript:Os01t0103100-01 N/A 1 N/A +1 irgsp CDS 178642 180462 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103100-01 N/A N/A transcript:Os01t0103100-01 Os01t0103100-01 N/A N/A +1 irgsp five_prime_UTR 178607 178641 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-38 N/A N/A transcript:Os01t0103100-01 N/A N/A N/A +1 irgsp three_prime_UTR 180463 180548 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-35 N/A N/A transcript:Os01t0103100-01 N/A N/A N/A +1 irgsp mRNA 178652 180575 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0103100-02 N/A N/A gene:Os01g0103100 N/A N/A Os01t0103100-02 +1 irgsp exon 178652 180575 . 1 . N/A N/A 0 N/A -1 -1 Os01t0103100-02.exon1 N/A Os01t0103100-02.exon1 N/A Os01t0103100-02.exon1 transcript:Os01t0103100-02 N/A 1 N/A +1 irgsp CDS 178678 180462 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103100-02 N/A N/A transcript:Os01t0103100-02 Os01t0103100-02 N/A N/A +1 irgsp five_prime_UTR 178652 178677 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-39 N/A N/A transcript:Os01t0103100-02 N/A N/A N/A +1 irgsp three_prime_UTR 180463 180575 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-36 N/A N/A transcript:Os01t0103100-02 N/A N/A N/A +1 irgsp gene 178815 180433 . -1 . N/A protein_coding N/A Hypothetical protein. (Os01t0103075-00) N/A N/A N/A Os01g0103075 gene:Os01g0103075 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 178815 180433 . -1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0103075-00 N/A N/A gene:Os01g0103075 N/A N/A Os01t0103075-00 +1 irgsp exon 178815 180433 . -1 . N/A N/A 1 N/A -1 -1 Os01t0103075-00.exon1 N/A Os01t0103075-00.exon1 N/A Os01t0103075-00.exon1 transcript:Os01t0103075-00 N/A 1 N/A +1 irgsp CDS 179512 180054 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103075-00 N/A N/A transcript:Os01t0103075-00 Os01t0103075-00 N/A N/A +1 irgsp five_prime_UTR 180055 180433 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-40 N/A N/A transcript:Os01t0103075-00 N/A N/A N/A +1 irgsp three_prime_UTR 178815 179511 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-37 N/A N/A transcript:Os01t0103075-00 N/A N/A N/A +1 Ensembl_Plants ncRNA_gene 182074 182154 . 1 . N/A tRNA N/A tRNA-Leu for anticodon AAG N/A N/A N/A ENSRNA049442722 gene:ENSRNA049442722 trnascan_gene tRNA-Leu N/A N/A N/A N/A +1 Ensembl_Plants tRNA 182074 182154 . 1 . N/A tRNA N/A N/A N/A N/A N/A N/A transcript:ENSRNA049442722-T1 N/A N/A gene:ENSRNA049442722 N/A N/A ENSRNA049442722-T1 +1 Ensembl_Plants exon 182074 182154 . 1 . N/A N/A 1 N/A -1 -1 ENSRNA049442722-E1 N/A ENSRNA049442722-E1 N/A ENSRNA049442722-E1 transcript:ENSRNA049442722-T1 N/A 1 N/A +1 irgsp gene 185189 185828 . -1 . N/A protein_coding N/A Hypothetical gene. (Os01t0103400-01) N/A N/A N/A Os01g0103400 gene:Os01g0103400 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 185189 185828 . -1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0103400-01 N/A N/A gene:Os01g0103400 N/A N/A Os01t0103400-01 +1 irgsp exon 185189 185828 . -1 . N/A N/A 1 N/A -1 -1 Os01t0103400-01.exon1 N/A Os01t0103400-01.exon1 N/A Os01t0103400-01.exon1 transcript:Os01t0103400-01 N/A 1 N/A +1 irgsp CDS 185435 185827 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103400-01 N/A N/A transcript:Os01t0103400-01 Os01t0103400-01 N/A N/A +1 irgsp five_prime_UTR 185828 185828 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-41 N/A N/A transcript:Os01t0103400-01 N/A N/A N/A +1 irgsp three_prime_UTR 185189 185434 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-38 N/A N/A transcript:Os01t0103400-01 N/A N/A N/A +1 irgsp repeat_region 186000 186100 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A fakeRepeat2 N/A N/A N/A N/A N/A N/A +1 irgsp gene 186250 190904 . -1 . N/A protein_coding N/A Similar to sterol-8,7-isomerase. (Os01t0103600-01);Emopamil-binding family protein. (Os01t0103600-02) N/A N/A N/A Os01g0103600 gene:Os01g0103600 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 186250 190262 . -1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0103600-02 N/A N/A gene:Os01g0103600 N/A N/A Os01t0103600-02 +1 irgsp exon 186250 186771 . -1 . N/A N/A 0 N/A -1 2 Os01t0103600-02.exon4 N/A Os01t0103600-02.exon4 N/A Os01t0103600-02.exon4 transcript:Os01t0103600-02 N/A 4 N/A +1 irgsp exon 189607 189715 . -1 . N/A N/A 0 N/A 2 1 Os01t0103600-02.exon3 N/A Os01t0103600-02.exon3 N/A Os01t0103600-02.exon3 transcript:Os01t0103600-02 N/A 3 N/A +1 irgsp exon 189841 189990 . -1 . N/A N/A 1 N/A 1 1 Os01t0103600-02.exon2 N/A Os01t0103600-02.exon2 N/A Os01t0103600-02.exon2 transcript:Os01t0103600-02 N/A 2 N/A +1 irgsp exon 190087 190262 . -1 . N/A N/A 0 N/A 1 -1 Os01t0103600-02.exon1 N/A Os01t0103600-02.exon1 N/A Os01t0103600-02.exon1 transcript:Os01t0103600-02 N/A 1 N/A +1 irgsp CDS 186516 186771 . -1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103600-02 N/A N/A transcript:Os01t0103600-02 Os01t0103600-02 N/A N/A +1 irgsp CDS 189607 189715 . -1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103600-02 N/A N/A transcript:Os01t0103600-02 Os01t0103600-02 N/A N/A +1 irgsp CDS 189841 189990 . -1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103600-02 N/A N/A transcript:Os01t0103600-02 Os01t0103600-02 N/A N/A +1 irgsp CDS 190087 190231 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103600-02 N/A N/A transcript:Os01t0103600-02 Os01t0103600-02 N/A N/A +1 irgsp five_prime_UTR 190232 190262 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-42 N/A N/A transcript:Os01t0103600-02 N/A N/A N/A +1 irgsp three_prime_UTR 186250 186515 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-39 N/A N/A transcript:Os01t0103600-02 N/A N/A N/A +1 irgsp mRNA 187345 190904 . -1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0103600-01 N/A N/A gene:Os01g0103600 N/A N/A Os01t0103600-01 +1 irgsp exon 187345 189715 . -1 . N/A N/A 0 N/A -1 1 Os01t0103600-01.exon3 N/A Os01t0103600-01.exon3 N/A Os01t0103600-01.exon3 transcript:Os01t0103600-01 N/A 3 N/A +1 irgsp exon 189841 189990 . -1 . N/A N/A 1 N/A 1 1 Os01t0103600-02.exon2 N/A agat-exon-5 N/A Os01t0103600-02.exon2 transcript:Os01t0103600-01 N/A 2 N/A +1 irgsp exon 190087 190904 . -1 . N/A N/A 0 N/A 1 -1 Os01t0103600-01.exon1 N/A Os01t0103600-01.exon1 N/A Os01t0103600-01.exon1 transcript:Os01t0103600-01 N/A 1 N/A +1 irgsp CDS 189396 189715 . -1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103600-01 N/A N/A transcript:Os01t0103600-01 Os01t0103600-01 N/A N/A +1 irgsp CDS 189841 189990 . -1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103600-01 N/A N/A transcript:Os01t0103600-01 Os01t0103600-01 N/A N/A +1 irgsp CDS 190087 190231 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103600-01 N/A N/A transcript:Os01t0103600-01 Os01t0103600-01 N/A N/A +1 irgsp five_prime_UTR 190232 190904 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-43 N/A N/A transcript:Os01t0103600-01 N/A N/A N/A +1 irgsp three_prime_UTR 187345 189395 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-40 N/A N/A transcript:Os01t0103600-01 N/A N/A N/A +1 irgsp gene 187545 188586 . 1 . N/A protein_coding N/A Hypothetical gene. (Os01t0103650-00) N/A N/A N/A Os01g0103650 gene:Os01g0103650 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 187545 188586 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0103650-00 N/A N/A gene:Os01g0103650 N/A N/A Os01t0103650-00 +1 irgsp exon 187545 188020 . 1 . N/A N/A 1 N/A -1 -1 Os01t0103650-00.exon1 N/A Os01t0103650-00.exon1 N/A Os01t0103650-00.exon1 transcript:Os01t0103650-00 N/A 1 N/A +1 irgsp exon 188060 188385 . 1 . N/A N/A 1 N/A -1 -1 Os01t0103650-00.exon2 N/A Os01t0103650-00.exon2 N/A Os01t0103650-00.exon2 transcript:Os01t0103650-00 N/A 2 N/A +1 irgsp exon 188455 188586 . 1 . N/A N/A 1 N/A -1 -1 Os01t0103650-00.exon3 N/A Os01t0103650-00.exon3 N/A Os01t0103650-00.exon3 transcript:Os01t0103650-00 N/A 3 N/A +1 irgsp CDS 187547 187768 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103650-00 N/A N/A transcript:Os01t0103650-00 Os01t0103650-00 N/A N/A +1 irgsp five_prime_UTR 187545 187546 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-44 N/A N/A transcript:Os01t0103650-00 N/A N/A N/A +1 irgsp three_prime_UTR 187769 188020 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-41 N/A N/A transcript:Os01t0103650-00 N/A N/A N/A +1 irgsp three_prime_UTR 188060 188385 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-42 N/A N/A transcript:Os01t0103650-00 N/A N/A N/A +1 irgsp three_prime_UTR 188455 188586 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-43 N/A N/A transcript:Os01t0103650-00 N/A N/A N/A +1 irgsp gene 191037 196287 . 1 . N/A protein_coding N/A Conserved hypothetical protein. (Os01t0103700-01) N/A N/A N/A Os01g0103700 gene:Os01g0103700 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 191037 196287 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0103700-01 N/A N/A gene:Os01g0103700 N/A N/A Os01t0103700-01 +1 irgsp exon 191037 191161 . 1 . N/A N/A 1 N/A -1 -1 Os01t0103700-01.exon1 N/A Os01t0103700-01.exon1 N/A Os01t0103700-01.exon1 transcript:Os01t0103700-01 N/A 1 N/A +1 irgsp exon 191625 191705 . 1 . N/A N/A 1 N/A 0 -1 Os01t0103700-01.exon2 N/A Os01t0103700-01.exon2 N/A Os01t0103700-01.exon2 transcript:Os01t0103700-01 N/A 2 N/A +1 irgsp exon 192399 192506 . 1 . N/A N/A 1 N/A 0 0 Os01t0103700-01.exon3 N/A Os01t0103700-01.exon3 N/A Os01t0103700-01.exon3 transcript:Os01t0103700-01 N/A 3 N/A +1 irgsp exon 192958 193161 . 1 . N/A N/A 1 N/A 0 0 Os01t0103700-01.exon4 N/A Os01t0103700-01.exon4 N/A Os01t0103700-01.exon4 transcript:Os01t0103700-01 N/A 4 N/A +1 irgsp exon 193248 193356 . 1 . N/A N/A 1 N/A 1 0 Os01t0103700-01.exon5 N/A Os01t0103700-01.exon5 N/A Os01t0103700-01.exon5 transcript:Os01t0103700-01 N/A 5 N/A +1 irgsp exon 193434 196287 . 1 . N/A N/A 1 N/A -1 1 Os01t0103700-01.exon6 N/A Os01t0103700-01.exon6 N/A Os01t0103700-01.exon6 transcript:Os01t0103700-01 N/A 6 N/A +1 irgsp CDS 191694 191705 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103700-01 N/A N/A transcript:Os01t0103700-01 Os01t0103700-01 N/A N/A +1 irgsp CDS 192399 192506 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103700-01 N/A N/A transcript:Os01t0103700-01 Os01t0103700-01 N/A N/A +1 irgsp CDS 192958 193161 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103700-01 N/A N/A transcript:Os01t0103700-01 Os01t0103700-01 N/A N/A +1 irgsp CDS 193248 193356 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103700-01 N/A N/A transcript:Os01t0103700-01 Os01t0103700-01 N/A N/A +1 irgsp CDS 193434 193507 . 1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103700-01 N/A N/A transcript:Os01t0103700-01 Os01t0103700-01 N/A N/A +1 irgsp five_prime_UTR 191037 191161 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-45 N/A N/A transcript:Os01t0103700-01 N/A N/A N/A +1 irgsp five_prime_UTR 191625 191693 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-46 N/A N/A transcript:Os01t0103700-01 N/A N/A N/A +1 irgsp three_prime_UTR 193508 196287 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-44 N/A N/A transcript:Os01t0103700-01 N/A N/A N/A +1 irgsp gene 197647 200803 . 1 . N/A protein_coding N/A Conserved hypothetical protein. (Os01t0103800-01) N/A N/A N/A Os01g0103800 gene:Os01g0103800 irgspv1.0-20170804-genes OsDW1-01g N/A N/A N/A N/A +1 irgsp mRNA 197647 200803 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0103800-01 N/A N/A gene:Os01g0103800 N/A N/A Os01t0103800-01 +1 irgsp exon 197647 197838 . 1 . N/A N/A 1 N/A -1 -1 Os01t0103800-01.exon1 N/A Os01t0103800-01.exon1 N/A Os01t0103800-01.exon1 transcript:Os01t0103800-01 N/A 1 N/A +1 irgsp exon 198034 198225 . 1 . N/A N/A 1 N/A 0 -1 Os01t0103800-01.exon2 N/A Os01t0103800-01.exon2 N/A Os01t0103800-01.exon2 transcript:Os01t0103800-01 N/A 2 N/A +1 irgsp exon 198830 200036 . 1 . N/A N/A 1 N/A 1 0 Os01t0103800-01.exon3 N/A Os01t0103800-01.exon3 N/A Os01t0103800-01.exon3 transcript:Os01t0103800-01 N/A 3 N/A +1 irgsp exon 200253 200803 . 1 . N/A N/A 1 N/A -1 1 Os01t0103800-01.exon4 N/A Os01t0103800-01.exon4 N/A Os01t0103800-01.exon4 transcript:Os01t0103800-01 N/A 4 N/A +1 irgsp CDS 198130 198225 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103800-01 N/A N/A transcript:Os01t0103800-01 Os01t0103800-01 N/A N/A +1 irgsp CDS 198830 200036 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103800-01 N/A N/A transcript:Os01t0103800-01 Os01t0103800-01 N/A N/A +1 irgsp CDS 200253 200479 . 1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103800-01 N/A N/A transcript:Os01t0103800-01 Os01t0103800-01 N/A N/A +1 irgsp five_prime_UTR 197647 197838 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-47 N/A N/A transcript:Os01t0103800-01 N/A N/A N/A +1 irgsp five_prime_UTR 198034 198129 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-48 N/A N/A transcript:Os01t0103800-01 N/A N/A N/A +1 irgsp three_prime_UTR 200480 200803 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-45 N/A N/A transcript:Os01t0103800-01 N/A N/A N/A +1 irgsp gene 201944 206202 . 1 . N/A protein_coding N/A Polynucleotidyl transferase, Ribonuclease H fold domain containing protein. (Os01t0103900-01) N/A N/A N/A Os01g0103900 gene:Os01g0103900 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 201944 206202 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0103900-01 N/A N/A gene:Os01g0103900 N/A N/A Os01t0103900-01 +1 irgsp exon 201944 202110 . 1 . N/A N/A 1 N/A 0 -1 Os01t0103900-01.exon1 N/A Os01t0103900-01.exon1 N/A Os01t0103900-01.exon1 transcript:Os01t0103900-01 N/A 1 N/A +1 irgsp exon 202252 202359 . 1 . N/A N/A 1 N/A 0 0 Os01t0103900-01.exon2 N/A Os01t0103900-01.exon2 N/A Os01t0103900-01.exon2 transcript:Os01t0103900-01 N/A 2 N/A +1 irgsp exon 203007 203127 . 1 . N/A N/A 1 N/A 1 0 Os01t0103900-01.exon3 N/A Os01t0103900-01.exon3 N/A Os01t0103900-01.exon3 transcript:Os01t0103900-01 N/A 3 N/A +1 irgsp exon 203302 203429 . 1 . N/A N/A 1 N/A 0 1 Os01t0103900-01.exon4 N/A Os01t0103900-01.exon4 N/A Os01t0103900-01.exon4 transcript:Os01t0103900-01 N/A 4 N/A +1 irgsp exon 203511 203658 . 1 . N/A N/A 1 N/A 1 0 Os01t0103900-01.exon5 N/A Os01t0103900-01.exon5 N/A Os01t0103900-01.exon5 transcript:Os01t0103900-01 N/A 5 N/A +1 irgsp exon 203760 203938 . 1 . N/A N/A 1 N/A 0 1 Os01t0103900-01.exon6 N/A Os01t0103900-01.exon6 N/A Os01t0103900-01.exon6 transcript:Os01t0103900-01 N/A 6 N/A +1 irgsp exon 204203 204440 . 1 . N/A N/A 1 N/A 1 0 Os01t0103900-01.exon7 N/A Os01t0103900-01.exon7 N/A Os01t0103900-01.exon7 transcript:Os01t0103900-01 N/A 7 N/A +1 irgsp exon 204543 204635 . 1 . N/A N/A 1 N/A 1 1 Os01t0103900-01.exon8 N/A Os01t0103900-01.exon8 N/A Os01t0103900-01.exon8 transcript:Os01t0103900-01 N/A 8 N/A +1 irgsp exon 204730 204875 . 1 . N/A N/A 1 N/A 0 1 Os01t0103900-01.exon9 N/A Os01t0103900-01.exon9 N/A Os01t0103900-01.exon9 transcript:Os01t0103900-01 N/A 9 N/A +1 irgsp exon 205042 205149 . 1 . N/A N/A 1 N/A 0 0 Os01t0103900-01.exon10 N/A Os01t0103900-01.exon10 N/A Os01t0103900-01.exon10 transcript:Os01t0103900-01 N/A 10 N/A +1 irgsp exon 205290 205378 . 1 . N/A N/A 1 N/A 2 0 Os01t0103900-01.exon11 N/A Os01t0103900-01.exon11 N/A Os01t0103900-01.exon11 transcript:Os01t0103900-01 N/A 11 N/A +1 irgsp exon 205534 206202 . 1 . N/A N/A 1 N/A -1 2 Os01t0103900-01.exon12 N/A Os01t0103900-01.exon12 N/A Os01t0103900-01.exon12 transcript:Os01t0103900-01 N/A 12 N/A +1 irgsp CDS 202042 202110 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103900-01 N/A N/A transcript:Os01t0103900-01 Os01t0103900-01 N/A N/A +1 irgsp CDS 202252 202359 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103900-01 N/A N/A transcript:Os01t0103900-01 Os01t0103900-01 N/A N/A +1 irgsp CDS 203007 203127 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103900-01 N/A N/A transcript:Os01t0103900-01 Os01t0103900-01 N/A N/A +1 irgsp CDS 203302 203429 . 1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103900-01 N/A N/A transcript:Os01t0103900-01 Os01t0103900-01 N/A N/A +1 irgsp CDS 203511 203658 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103900-01 N/A N/A transcript:Os01t0103900-01 Os01t0103900-01 N/A N/A +1 irgsp CDS 203760 203938 . 1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103900-01 N/A N/A transcript:Os01t0103900-01 Os01t0103900-01 N/A N/A +1 irgsp CDS 204203 204440 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103900-01 N/A N/A transcript:Os01t0103900-01 Os01t0103900-01 N/A N/A +1 irgsp CDS 204543 204635 . 1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103900-01 N/A N/A transcript:Os01t0103900-01 Os01t0103900-01 N/A N/A +1 irgsp CDS 204730 204875 . 1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103900-01 N/A N/A transcript:Os01t0103900-01 Os01t0103900-01 N/A N/A +1 irgsp CDS 205042 205149 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103900-01 N/A N/A transcript:Os01t0103900-01 Os01t0103900-01 N/A N/A +1 irgsp CDS 205290 205378 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103900-01 N/A N/A transcript:Os01t0103900-01 Os01t0103900-01 N/A N/A +1 irgsp CDS 205534 205543 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0103900-01 N/A N/A transcript:Os01t0103900-01 Os01t0103900-01 N/A N/A +1 irgsp five_prime_UTR 201944 202041 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-49 N/A N/A transcript:Os01t0103900-01 N/A N/A N/A +1 irgsp three_prime_UTR 205544 206202 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-46 N/A N/A transcript:Os01t0103900-01 N/A N/A N/A +1 irgsp gene 206131 209606 . -1 . N/A protein_coding N/A C-type lectin domain containing protein. (Os01t0104000-01);Similar to predicted protein. (Os01t0104000-02) N/A N/A N/A Os01g0104000 gene:Os01g0104000 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 206131 209581 . -1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0104000-02 N/A N/A gene:Os01g0104000 N/A N/A Os01t0104000-02 +1 irgsp exon 206131 207029 . -1 . N/A N/A 0 N/A -1 2 Os01t0104000-02.exon4 N/A Os01t0104000-02.exon4 N/A Os01t0104000-02.exon4 transcript:Os01t0104000-02 N/A 4 N/A +1 irgsp exon 207706 208273 . -1 . N/A N/A 0 N/A 2 1 Os01t0104000-02.exon3 N/A Os01t0104000-02.exon3 N/A Os01t0104000-02.exon3 transcript:Os01t0104000-02 N/A 3 N/A +1 irgsp exon 208408 208836 . -1 . N/A N/A 1 N/A 1 1 Os01t0104000-01.exon2 N/A Os01t0104000-01.exon2 N/A Os01t0104000-01.exon2 transcript:Os01t0104000-02 N/A 2 N/A +1 irgsp exon 209438 209581 . -1 . N/A N/A 0 N/A 1 -1 Os01t0104000-02.exon1 N/A Os01t0104000-02.exon1 N/A Os01t0104000-02.exon1 transcript:Os01t0104000-02 N/A 1 N/A +1 irgsp CDS 206450 207029 . -1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104000-02 N/A N/A transcript:Os01t0104000-02 Os01t0104000-02 N/A N/A +1 irgsp CDS 207706 208273 . -1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104000-02 N/A N/A transcript:Os01t0104000-02 Os01t0104000-02 N/A N/A +1 irgsp CDS 208408 208836 . -1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104000-02 N/A N/A transcript:Os01t0104000-02 Os01t0104000-02 N/A N/A +1 irgsp CDS 209438 209525 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104000-02 N/A N/A transcript:Os01t0104000-02 Os01t0104000-02 N/A N/A +1 irgsp five_prime_UTR 209526 209581 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-50 N/A N/A transcript:Os01t0104000-02 N/A N/A N/A +1 irgsp three_prime_UTR 206131 206449 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-47 N/A N/A transcript:Os01t0104000-02 N/A N/A N/A +1 irgsp mRNA 206134 209606 . -1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0104000-01 N/A N/A gene:Os01g0104000 N/A N/A Os01t0104000-01 +1 irgsp exon 206134 207029 . -1 . N/A N/A 0 N/A -1 2 Os01t0104000-01.exon4 N/A Os01t0104000-01.exon4 N/A Os01t0104000-01.exon4 transcript:Os01t0104000-01 N/A 4 N/A +1 irgsp exon 207706 208276 . -1 . N/A N/A 0 N/A 2 1 Os01t0104000-01.exon3 N/A Os01t0104000-01.exon3 N/A Os01t0104000-01.exon3 transcript:Os01t0104000-01 N/A 3 N/A +1 irgsp exon 208408 208836 . -1 . N/A N/A 1 N/A 1 1 Os01t0104000-01.exon2 N/A agat-exon-6 N/A Os01t0104000-01.exon2 transcript:Os01t0104000-01 N/A 2 N/A +1 irgsp exon 209438 209606 . -1 . N/A N/A 0 N/A 1 -1 Os01t0104000-01.exon1 N/A Os01t0104000-01.exon1 N/A Os01t0104000-01.exon1 transcript:Os01t0104000-01 N/A 1 N/A +1 irgsp CDS 206450 207029 . -1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104000-01 N/A N/A transcript:Os01t0104000-01 Os01t0104000-01 N/A N/A +1 irgsp CDS 207706 208276 . -1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104000-01 N/A N/A transcript:Os01t0104000-01 Os01t0104000-01 N/A N/A +1 irgsp CDS 208408 208836 . -1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104000-01 N/A N/A transcript:Os01t0104000-01 Os01t0104000-01 N/A N/A +1 irgsp CDS 209438 209525 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104000-01 N/A N/A transcript:Os01t0104000-01 Os01t0104000-01 N/A N/A +1 irgsp five_prime_UTR 209526 209606 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-51 N/A N/A transcript:Os01t0104000-01 N/A N/A N/A +1 irgsp three_prime_UTR 206134 206449 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-48 N/A N/A transcript:Os01t0104000-01 N/A N/A N/A +1 irgsp gene 209771 214173 . 1 . N/A protein_coding N/A Similar to protein binding / zinc ion binding. (Os01t0104100-01);Similar to protein binding / zinc ion binding. (Os01t0104100-02) N/A N/A N/A Os01g0104100 gene:Os01g0104100 irgspv1.0-20170804-genes cold-inducible, cold-inducible zinc finger protein N/A N/A N/A N/A +1 irgsp mRNA 209771 214173 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0104100-01 N/A N/A gene:Os01g0104100 N/A N/A Os01t0104100-01 +1 irgsp exon 209771 209896 . 1 . N/A N/A 0 N/A 0 0 Os01t0104100-01.exon1 N/A Os01t0104100-01.exon1 N/A Os01t0104100-01.exon1 transcript:Os01t0104100-01 N/A 1 N/A +1 irgsp exon 210244 210563 . 1 . N/A N/A 1 N/A 2 0 Os01t0104100-01.exon2 N/A Os01t0104100-01.exon2 N/A Os01t0104100-01.exon2 transcript:Os01t0104100-01 N/A 2 N/A +1 irgsp exon 210659 210890 . 1 . N/A N/A 1 N/A 0 2 Os01t0104100-01.exon3 N/A Os01t0104100-01.exon3 N/A Os01t0104100-01.exon3 transcript:Os01t0104100-01 N/A 3 N/A +1 irgsp exon 211015 211160 . 1 . N/A N/A 1 N/A 2 0 Os01t0104100-01.exon4 N/A Os01t0104100-01.exon4 N/A Os01t0104100-01.exon4 transcript:Os01t0104100-01 N/A 4 N/A +1 irgsp exon 212265 212352 . 1 . N/A N/A 1 N/A 0 2 Os01t0104100-01.exon5 N/A Os01t0104100-01.exon5 N/A Os01t0104100-01.exon5 transcript:Os01t0104100-01 N/A 5 N/A +1 irgsp exon 212433 212579 . 1 . N/A N/A 1 N/A 0 0 Os01t0104100-01.exon6 N/A Os01t0104100-01.exon6 N/A Os01t0104100-01.exon6 transcript:Os01t0104100-01 N/A 6 N/A +1 irgsp exon 213490 213639 . 1 . N/A N/A 1 N/A 0 0 Os01t0104100-01.exon7 N/A Os01t0104100-01.exon7 N/A Os01t0104100-01.exon7 transcript:Os01t0104100-01 N/A 7 N/A +1 irgsp exon 213741 214173 . 1 . N/A N/A 0 N/A -1 0 Os01t0104100-01.exon8 N/A Os01t0104100-01.exon8 N/A Os01t0104100-01.exon8 transcript:Os01t0104100-01 N/A 8 N/A +1 irgsp CDS 209771 209896 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104100-01 N/A N/A transcript:Os01t0104100-01 Os01t0104100-01 N/A N/A +1 irgsp CDS 210244 210563 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104100-01 N/A N/A transcript:Os01t0104100-01 Os01t0104100-01 N/A N/A +1 irgsp CDS 210659 210890 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104100-01 N/A N/A transcript:Os01t0104100-01 Os01t0104100-01 N/A N/A +1 irgsp CDS 211015 211160 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104100-01 N/A N/A transcript:Os01t0104100-01 Os01t0104100-01 N/A N/A +1 irgsp CDS 212265 212352 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104100-01 N/A N/A transcript:Os01t0104100-01 Os01t0104100-01 N/A N/A +1 irgsp CDS 212433 212579 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104100-01 N/A N/A transcript:Os01t0104100-01 Os01t0104100-01 N/A N/A +1 irgsp CDS 213490 213639 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104100-01 N/A N/A transcript:Os01t0104100-01 Os01t0104100-01 N/A N/A +1 irgsp CDS 213741 213788 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104100-01 N/A N/A transcript:Os01t0104100-01 Os01t0104100-01 N/A N/A +1 irgsp three_prime_UTR 213789 214173 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-49 N/A N/A transcript:Os01t0104100-01 N/A N/A N/A +1 irgsp mRNA 209794 214147 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0104100-02 N/A N/A gene:Os01g0104100 N/A N/A Os01t0104100-02 +1 irgsp exon 209794 209896 . 1 . N/A N/A 0 N/A 0 -1 Os01t0104100-02.exon1 N/A Os01t0104100-02.exon1 N/A Os01t0104100-02.exon1 transcript:Os01t0104100-02 N/A 1 N/A +1 irgsp exon 210244 210563 . 1 . N/A N/A 1 N/A 2 0 Os01t0104100-01.exon2 N/A agat-exon-7 N/A Os01t0104100-01.exon2 transcript:Os01t0104100-02 N/A 2 N/A +1 irgsp exon 210659 210890 . 1 . N/A N/A 1 N/A 0 2 Os01t0104100-01.exon3 N/A agat-exon-8 N/A Os01t0104100-01.exon3 transcript:Os01t0104100-02 N/A 3 N/A +1 irgsp exon 211015 211160 . 1 . N/A N/A 1 N/A 2 0 Os01t0104100-01.exon4 N/A agat-exon-9 N/A Os01t0104100-01.exon4 transcript:Os01t0104100-02 N/A 4 N/A +1 irgsp exon 212265 212352 . 1 . N/A N/A 1 N/A 0 2 Os01t0104100-01.exon5 N/A agat-exon-10 N/A Os01t0104100-01.exon5 transcript:Os01t0104100-02 N/A 5 N/A +1 irgsp exon 212433 212579 . 1 . N/A N/A 1 N/A 0 0 Os01t0104100-01.exon6 N/A agat-exon-11 N/A Os01t0104100-01.exon6 transcript:Os01t0104100-02 N/A 6 N/A +1 irgsp exon 213490 213639 . 1 . N/A N/A 1 N/A 0 0 Os01t0104100-01.exon7 N/A agat-exon-12 N/A Os01t0104100-01.exon7 transcript:Os01t0104100-02 N/A 7 N/A +1 irgsp exon 213741 214147 . 1 . N/A N/A 0 N/A -1 0 Os01t0104100-02.exon8 N/A Os01t0104100-02.exon8 N/A Os01t0104100-02.exon8 transcript:Os01t0104100-02 N/A 8 N/A +1 irgsp CDS 209795 209896 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104100-02 N/A N/A transcript:Os01t0104100-02 Os01t0104100-02 N/A N/A +1 irgsp CDS 210244 210563 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104100-02 N/A N/A transcript:Os01t0104100-02 Os01t0104100-02 N/A N/A +1 irgsp CDS 210659 210890 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104100-02 N/A N/A transcript:Os01t0104100-02 Os01t0104100-02 N/A N/A +1 irgsp CDS 211015 211160 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104100-02 N/A N/A transcript:Os01t0104100-02 Os01t0104100-02 N/A N/A +1 irgsp CDS 212265 212352 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104100-02 N/A N/A transcript:Os01t0104100-02 Os01t0104100-02 N/A N/A +1 irgsp CDS 212433 212579 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104100-02 N/A N/A transcript:Os01t0104100-02 Os01t0104100-02 N/A N/A +1 irgsp CDS 213490 213639 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104100-02 N/A N/A transcript:Os01t0104100-02 Os01t0104100-02 N/A N/A +1 irgsp CDS 213741 213788 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104100-02 N/A N/A transcript:Os01t0104100-02 Os01t0104100-02 N/A N/A +1 irgsp five_prime_UTR 209794 209794 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-52 N/A N/A transcript:Os01t0104100-02 N/A N/A N/A +1 irgsp three_prime_UTR 213789 214147 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-50 N/A N/A transcript:Os01t0104100-02 N/A N/A N/A +1 irgsp gene 216212 217345 . 1 . N/A protein_coding N/A No apical meristem (NAM) protein domain containing protein. (Os01t0104200-00) N/A N/A N/A Os01g0104200 gene:Os01g0104200 irgspv1.0-20170804-genes NAC DOMAIN-CONTAINING PROTEIN 16 N/A N/A N/A N/A +1 irgsp mRNA 216212 217345 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0104200-00 N/A N/A gene:Os01g0104200 N/A N/A Os01t0104200-00 +1 irgsp exon 216212 216769 . 1 . N/A N/A 1 N/A 0 0 Os01t0104200-00.exon1 N/A Os01t0104200-00.exon1 N/A Os01t0104200-00.exon1 transcript:Os01t0104200-00 N/A 1 N/A +1 irgsp exon 216884 217345 . 1 . N/A N/A 1 N/A 0 0 Os01t0104200-00.exon2 N/A Os01t0104200-00.exon2 N/A Os01t0104200-00.exon2 transcript:Os01t0104200-00 N/A 2 N/A +1 irgsp CDS 216212 216769 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104200-00 N/A N/A transcript:Os01t0104200-00 Os01t0104200-00 N/A N/A +1 irgsp CDS 216884 217345 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104200-00 N/A N/A transcript:Os01t0104200-00 Os01t0104200-00 N/A N/A +1 irgsp gene 226897 229301 . 1 . N/A protein_coding N/A Ricin B-related lectin domain containing protein. (Os01t0104400-01);Ricin B-related lectin domain containing protein. (Os01t0104400-02);Ricin B-related lectin domain containing protein. (Os01t0104400-03) N/A N/A N/A Os01g0104400 gene:Os01g0104400 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 226897 229229 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0104400-01 N/A N/A gene:Os01g0104400 N/A N/A Os01t0104400-01 +1 irgsp exon 226897 227634 . 1 . N/A N/A 0 N/A 0 -1 Os01t0104400-01.exon1 N/A Os01t0104400-01.exon1 N/A Os01t0104400-01.exon1 transcript:Os01t0104400-01 N/A 1 N/A +1 irgsp exon 227742 227864 . 1 . N/A N/A 1 N/A 0 0 Os01t0104400-03.exon2 N/A Os01t0104400-03.exon2 N/A Os01t0104400-03.exon2 transcript:Os01t0104400-01 N/A 2 N/A +1 irgsp exon 228557 228785 . 1 . N/A N/A 1 N/A 1 0 Os01t0104400-03.exon3 N/A Os01t0104400-03.exon3 N/A Os01t0104400-03.exon3 transcript:Os01t0104400-01 N/A 3 N/A +1 irgsp exon 228930 229229 . 1 . N/A N/A 0 N/A -1 1 Os01t0104400-01.exon4 N/A Os01t0104400-01.exon4 N/A Os01t0104400-01.exon4 transcript:Os01t0104400-01 N/A 4 N/A +1 irgsp CDS 227182 227634 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104400-01 N/A N/A transcript:Os01t0104400-01 Os01t0104400-01 N/A N/A +1 irgsp CDS 227742 227864 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104400-01 N/A N/A transcript:Os01t0104400-01 Os01t0104400-01 N/A N/A +1 irgsp CDS 228557 228785 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104400-01 N/A N/A transcript:Os01t0104400-01 Os01t0104400-01 N/A N/A +1 irgsp CDS 228930 228931 . 1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104400-01 N/A N/A transcript:Os01t0104400-01 Os01t0104400-01 N/A N/A +1 irgsp five_prime_UTR 226897 227181 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-53 N/A N/A transcript:Os01t0104400-01 N/A N/A N/A +1 irgsp three_prime_UTR 228932 229229 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-51 N/A N/A transcript:Os01t0104400-01 N/A N/A N/A +1 irgsp mRNA 227139 229301 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0104400-02 N/A N/A gene:Os01g0104400 N/A N/A Os01t0104400-02 +1 irgsp exon 227139 227634 . 1 . N/A N/A 0 N/A 0 -1 Os01t0104400-02.exon1 N/A Os01t0104400-02.exon1 N/A Os01t0104400-02.exon1 transcript:Os01t0104400-02 N/A 1 N/A +1 irgsp exon 227742 227864 . 1 . N/A N/A 1 N/A 0 0 Os01t0104400-03.exon2 N/A agat-exon-13 N/A Os01t0104400-03.exon2 transcript:Os01t0104400-02 N/A 2 N/A +1 irgsp exon 228557 228785 . 1 . N/A N/A 1 N/A 1 0 Os01t0104400-03.exon3 N/A agat-exon-14 N/A Os01t0104400-03.exon3 transcript:Os01t0104400-02 N/A 3 N/A +1 irgsp exon 228930 229301 . 1 . N/A N/A 0 N/A -1 1 Os01t0104400-02.exon4 N/A Os01t0104400-02.exon4 N/A Os01t0104400-02.exon4 transcript:Os01t0104400-02 N/A 4 N/A +1 irgsp CDS 227182 227634 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104400-02 N/A N/A transcript:Os01t0104400-02 Os01t0104400-02 N/A N/A +1 irgsp CDS 227742 227864 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104400-02 N/A N/A transcript:Os01t0104400-02 Os01t0104400-02 N/A N/A +1 irgsp CDS 228557 228785 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104400-02 N/A N/A transcript:Os01t0104400-02 Os01t0104400-02 N/A N/A +1 irgsp CDS 228930 228931 . 1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104400-02 N/A N/A transcript:Os01t0104400-02 Os01t0104400-02 N/A N/A +1 irgsp five_prime_UTR 227139 227181 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-54 N/A N/A transcript:Os01t0104400-02 N/A N/A N/A +1 irgsp three_prime_UTR 228932 229301 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-52 N/A N/A transcript:Os01t0104400-02 N/A N/A N/A +1 irgsp mRNA 227179 229214 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0104400-03 N/A N/A gene:Os01g0104400 N/A N/A Os01t0104400-03 +1 irgsp exon 227179 227634 . 1 . N/A N/A 0 N/A 0 -1 Os01t0104400-03.exon1 N/A Os01t0104400-03.exon1 N/A Os01t0104400-03.exon1 transcript:Os01t0104400-03 N/A 1 N/A +1 irgsp exon 227742 227864 . 1 . N/A N/A 1 N/A 0 0 Os01t0104400-03.exon2 N/A agat-exon-15 N/A Os01t0104400-03.exon2 transcript:Os01t0104400-03 N/A 2 N/A +1 irgsp exon 228557 228785 . 1 . N/A N/A 1 N/A 1 0 Os01t0104400-03.exon3 N/A agat-exon-16 N/A Os01t0104400-03.exon3 transcript:Os01t0104400-03 N/A 3 N/A +1 irgsp exon 228930 229214 . 1 . N/A N/A 0 N/A -1 1 Os01t0104400-03.exon4 N/A Os01t0104400-03.exon4 N/A Os01t0104400-03.exon4 transcript:Os01t0104400-03 N/A 4 N/A +1 irgsp CDS 227182 227634 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104400-03 N/A N/A transcript:Os01t0104400-03 Os01t0104400-03 N/A N/A +1 irgsp CDS 227742 227864 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104400-03 N/A N/A transcript:Os01t0104400-03 Os01t0104400-03 N/A N/A +1 irgsp CDS 228557 228785 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104400-03 N/A N/A transcript:Os01t0104400-03 Os01t0104400-03 N/A N/A +1 irgsp CDS 228930 228931 . 1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104400-03 N/A N/A transcript:Os01t0104400-03 Os01t0104400-03 N/A N/A +1 irgsp five_prime_UTR 227179 227181 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-55 N/A N/A transcript:Os01t0104400-03 N/A N/A N/A +1 irgsp three_prime_UTR 228932 229214 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-53 N/A N/A transcript:Os01t0104400-03 N/A N/A N/A +1 irgsp gene 241680 243440 . 1 . N/A protein_coding N/A No apical meristem (NAM) protein domain containing protein. (Os01t0104500-01) N/A N/A N/A Os01g0104500 gene:Os01g0104500 irgspv1.0-20170804-genes NAC DOMAIN-CONTAINING PROTEIN 20 N/A N/A N/A N/A +1 irgsp mRNA 241680 243440 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0104500-01 N/A N/A gene:Os01g0104500 N/A N/A Os01t0104500-01 +1 irgsp exon 241680 241702 . 1 . N/A N/A 1 N/A -1 -1 Os01t0104500-01.exon1 N/A Os01t0104500-01.exon1 N/A Os01t0104500-01.exon1 transcript:Os01t0104500-01 N/A 1 N/A +1 irgsp exon 241866 242091 . 1 . N/A N/A 1 N/A 1 -1 Os01t0104500-01.exon2 N/A Os01t0104500-01.exon2 N/A Os01t0104500-01.exon2 transcript:Os01t0104500-01 N/A 2 N/A +1 irgsp exon 242199 243440 . 1 . N/A N/A 1 N/A -1 1 Os01t0104500-01.exon3 N/A Os01t0104500-01.exon3 N/A Os01t0104500-01.exon3 transcript:Os01t0104500-01 N/A 3 N/A +1 irgsp CDS 241908 242091 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104500-01 N/A N/A transcript:Os01t0104500-01 Os01t0104500-01 N/A N/A +1 irgsp CDS 242199 242977 . 1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104500-01 N/A N/A transcript:Os01t0104500-01 Os01t0104500-01 N/A N/A +1 irgsp five_prime_UTR 241680 241702 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-56 N/A N/A transcript:Os01t0104500-01 N/A N/A N/A +1 irgsp five_prime_UTR 241866 241907 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-57 N/A N/A transcript:Os01t0104500-01 N/A N/A N/A +1 irgsp three_prime_UTR 242978 243440 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-54 N/A N/A transcript:Os01t0104500-01 N/A N/A N/A +1 irgsp gene 248828 256872 . -1 . N/A protein_coding N/A Homolog of Arabidopsis DE-ETIOLATED1 (DET1), Modulation of the ABA signaling pathway and ABA biosynthesis, Regulation of chlorophyll content (Os01t0104600-01);Similar to Light-mediated development protein DET1 (Deetiolated1 homolog) (tDET1) (High pigmentation protein 2) (Protein dark green). (Os01t0104600-02) N/A N/A N/A Os01g0104600 gene:Os01g0104600 irgspv1.0-20170804-genes DE-ETIOLATED1 N/A N/A N/A N/A +1 irgsp mRNA 248828 256571 . -1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0104600-02 N/A N/A gene:Os01g0104600 N/A N/A Os01t0104600-02 +1 irgsp exon 248828 249107 . -1 . N/A N/A 1 N/A -1 1 Os01t0104600-01.exon11 N/A Os01t0104600-01.exon11 N/A Os01t0104600-01.exon11 transcript:Os01t0104600-02 N/A 11 N/A +1 irgsp exon 249369 249468 . -1 . N/A N/A 1 N/A 1 0 Os01t0104600-01.exon10 N/A Os01t0104600-01.exon10 N/A Os01t0104600-01.exon10 transcript:Os01t0104600-02 N/A 10 N/A +1 irgsp exon 249861 249956 . -1 . N/A N/A 1 N/A 0 0 Os01t0104600-01.exon9 N/A Os01t0104600-01.exon9 N/A Os01t0104600-01.exon9 transcript:Os01t0104600-02 N/A 9 N/A +1 irgsp exon 250617 250781 . -1 . N/A N/A 1 N/A 0 0 Os01t0104600-01.exon8 N/A Os01t0104600-01.exon8 N/A Os01t0104600-01.exon8 transcript:Os01t0104600-02 N/A 8 N/A +1 irgsp exon 250860 250940 . -1 . N/A N/A 1 N/A 0 0 Os01t0104600-01.exon7 N/A Os01t0104600-01.exon7 N/A Os01t0104600-01.exon7 transcript:Os01t0104600-02 N/A 7 N/A +1 irgsp exon 251026 251082 . -1 . N/A N/A 1 N/A 0 0 Os01t0104600-01.exon6 N/A Os01t0104600-01.exon6 N/A Os01t0104600-01.exon6 transcript:Os01t0104600-02 N/A 6 N/A +1 irgsp exon 251316 251384 . -1 . N/A N/A 1 N/A 0 0 Os01t0104600-01.exon5 N/A Os01t0104600-01.exon5 N/A Os01t0104600-01.exon5 transcript:Os01t0104600-02 N/A 5 N/A +1 irgsp exon 251695 251790 . -1 . N/A N/A 1 N/A 0 0 Os01t0104600-01.exon4 N/A Os01t0104600-01.exon4 N/A Os01t0104600-01.exon4 transcript:Os01t0104600-02 N/A 4 N/A +1 irgsp exon 255325 255553 . -1 . N/A N/A 1 N/A 0 2 Os01t0104600-01.exon3 N/A Os01t0104600-01.exon3 N/A Os01t0104600-01.exon3 transcript:Os01t0104600-02 N/A 3 N/A +1 irgsp exon 255674 256098 . -1 . N/A N/A 1 N/A 2 0 Os01t0104600-01.exon2 N/A Os01t0104600-01.exon2 N/A Os01t0104600-01.exon2 transcript:Os01t0104600-02 N/A 2 N/A +1 irgsp exon 256361 256571 . -1 . N/A N/A 0 N/A 0 -1 Os01t0104600-02.exon1 N/A Os01t0104600-02.exon1 N/A Os01t0104600-02.exon1 transcript:Os01t0104600-02 N/A 1 N/A +1 irgsp CDS 248971 249107 . -1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104600-02 N/A N/A transcript:Os01t0104600-02 Os01t0104600-02 N/A N/A +1 irgsp CDS 249369 249468 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104600-02 N/A N/A transcript:Os01t0104600-02 Os01t0104600-02 N/A N/A +1 irgsp CDS 249861 249956 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104600-02 N/A N/A transcript:Os01t0104600-02 Os01t0104600-02 N/A N/A +1 irgsp CDS 250617 250781 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104600-02 N/A N/A transcript:Os01t0104600-02 Os01t0104600-02 N/A N/A +1 irgsp CDS 250860 250940 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104600-02 N/A N/A transcript:Os01t0104600-02 Os01t0104600-02 N/A N/A +1 irgsp CDS 251026 251082 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104600-02 N/A N/A transcript:Os01t0104600-02 Os01t0104600-02 N/A N/A +1 irgsp CDS 251316 251384 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104600-02 N/A N/A transcript:Os01t0104600-02 Os01t0104600-02 N/A N/A +1 irgsp CDS 251695 251790 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104600-02 N/A N/A transcript:Os01t0104600-02 Os01t0104600-02 N/A N/A +1 irgsp CDS 255325 255553 . -1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104600-02 N/A N/A transcript:Os01t0104600-02 Os01t0104600-02 N/A N/A +1 irgsp CDS 255674 256098 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104600-02 N/A N/A transcript:Os01t0104600-02 Os01t0104600-02 N/A N/A +1 irgsp CDS 256361 256441 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104600-02 N/A N/A transcript:Os01t0104600-02 Os01t0104600-02 N/A N/A +1 irgsp five_prime_UTR 256442 256571 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-58 N/A N/A transcript:Os01t0104600-02 N/A N/A N/A +1 irgsp three_prime_UTR 248828 248970 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-55 N/A N/A transcript:Os01t0104600-02 N/A N/A N/A +1 irgsp mRNA 248828 256872 . -1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0104600-01 N/A N/A gene:Os01g0104600 N/A N/A Os01t0104600-01 +1 irgsp exon 248828 249107 . -1 . N/A N/A 1 N/A -1 1 Os01t0104600-01.exon11 N/A agat-exon-17 N/A Os01t0104600-01.exon11 transcript:Os01t0104600-01 N/A 11 N/A +1 irgsp exon 249369 249468 . -1 . N/A N/A 1 N/A 1 0 Os01t0104600-01.exon10 N/A agat-exon-18 N/A Os01t0104600-01.exon10 transcript:Os01t0104600-01 N/A 10 N/A +1 irgsp exon 249861 249956 . -1 . N/A N/A 1 N/A 0 0 Os01t0104600-01.exon9 N/A agat-exon-19 N/A Os01t0104600-01.exon9 transcript:Os01t0104600-01 N/A 9 N/A +1 irgsp exon 250617 250781 . -1 . N/A N/A 1 N/A 0 0 Os01t0104600-01.exon8 N/A agat-exon-20 N/A Os01t0104600-01.exon8 transcript:Os01t0104600-01 N/A 8 N/A +1 irgsp exon 250860 250940 . -1 . N/A N/A 1 N/A 0 0 Os01t0104600-01.exon7 N/A agat-exon-21 N/A Os01t0104600-01.exon7 transcript:Os01t0104600-01 N/A 7 N/A +1 irgsp exon 251026 251082 . -1 . N/A N/A 1 N/A 0 0 Os01t0104600-01.exon6 N/A agat-exon-22 N/A Os01t0104600-01.exon6 transcript:Os01t0104600-01 N/A 6 N/A +1 irgsp exon 251316 251384 . -1 . N/A N/A 1 N/A 0 0 Os01t0104600-01.exon5 N/A agat-exon-23 N/A Os01t0104600-01.exon5 transcript:Os01t0104600-01 N/A 5 N/A +1 irgsp exon 251695 251790 . -1 . N/A N/A 1 N/A 0 0 Os01t0104600-01.exon4 N/A agat-exon-24 N/A Os01t0104600-01.exon4 transcript:Os01t0104600-01 N/A 4 N/A +1 irgsp exon 255325 255553 . -1 . N/A N/A 1 N/A 0 2 Os01t0104600-01.exon3 N/A agat-exon-25 N/A Os01t0104600-01.exon3 transcript:Os01t0104600-01 N/A 3 N/A +1 irgsp exon 255674 256098 . -1 . N/A N/A 1 N/A 2 0 Os01t0104600-01.exon2 N/A agat-exon-26 N/A Os01t0104600-01.exon2 transcript:Os01t0104600-01 N/A 2 N/A +1 irgsp exon 256361 256872 . -1 . N/A N/A 0 N/A 0 -1 Os01t0104600-01.exon1 N/A Os01t0104600-01.exon1 N/A Os01t0104600-01.exon1 transcript:Os01t0104600-01 N/A 1 N/A +1 irgsp CDS 248971 249107 . -1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104600-01 N/A N/A transcript:Os01t0104600-01 Os01t0104600-01 N/A N/A +1 irgsp CDS 249369 249468 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104600-01 N/A N/A transcript:Os01t0104600-01 Os01t0104600-01 N/A N/A +1 irgsp CDS 249861 249956 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104600-01 N/A N/A transcript:Os01t0104600-01 Os01t0104600-01 N/A N/A +1 irgsp CDS 250617 250781 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104600-01 N/A N/A transcript:Os01t0104600-01 Os01t0104600-01 N/A N/A +1 irgsp CDS 250860 250940 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104600-01 N/A N/A transcript:Os01t0104600-01 Os01t0104600-01 N/A N/A +1 irgsp CDS 251026 251082 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104600-01 N/A N/A transcript:Os01t0104600-01 Os01t0104600-01 N/A N/A +1 irgsp CDS 251316 251384 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104600-01 N/A N/A transcript:Os01t0104600-01 Os01t0104600-01 N/A N/A +1 irgsp CDS 251695 251790 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104600-01 N/A N/A transcript:Os01t0104600-01 Os01t0104600-01 N/A N/A +1 irgsp CDS 255325 255553 . -1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104600-01 N/A N/A transcript:Os01t0104600-01 Os01t0104600-01 N/A N/A +1 irgsp CDS 255674 256098 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104600-01 N/A N/A transcript:Os01t0104600-01 Os01t0104600-01 N/A N/A +1 irgsp CDS 256361 256441 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104600-01 N/A N/A transcript:Os01t0104600-01 Os01t0104600-01 N/A N/A +1 irgsp five_prime_UTR 256442 256872 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-59 N/A N/A transcript:Os01t0104600-01 N/A N/A N/A +1 irgsp three_prime_UTR 248828 248970 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-56 N/A N/A transcript:Os01t0104600-01 N/A N/A N/A +1 irgsp gene 261530 268145 . 1 . N/A protein_coding N/A Sas10/Utp3 family protein. (Os01t0104800-01);Hypothetical conserved gene. (Os01t0104800-02) N/A N/A N/A Os01g0104800 gene:Os01g0104800 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 261530 268145 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0104800-01 N/A N/A gene:Os01g0104800 N/A N/A Os01t0104800-01 +1 irgsp exon 261530 261661 . 1 . N/A N/A 0 N/A 1 -1 Os01t0104800-01.exon1 N/A Os01t0104800-01.exon1 N/A Os01t0104800-01.exon1 transcript:Os01t0104800-01 N/A 1 N/A +1 irgsp exon 261767 261805 . 1 . N/A N/A 0 N/A 1 1 Os01t0104800-01.exon2 N/A Os01t0104800-01.exon2 N/A Os01t0104800-01.exon2 transcript:Os01t0104800-01 N/A 2 N/A +1 irgsp exon 261895 261941 . 1 . N/A N/A 0 N/A 0 1 Os01t0104800-01.exon3 N/A Os01t0104800-01.exon3 N/A Os01t0104800-01.exon3 transcript:Os01t0104800-01 N/A 3 N/A +1 irgsp exon 262582 262681 . 1 . N/A N/A 0 N/A 1 0 Os01t0104800-01.exon4 N/A Os01t0104800-01.exon4 N/A Os01t0104800-01.exon4 transcript:Os01t0104800-01 N/A 4 N/A +1 irgsp exon 262925 263181 . 1 . N/A N/A 0 N/A 0 1 Os01t0104800-01.exon5 N/A Os01t0104800-01.exon5 N/A Os01t0104800-01.exon5 transcript:Os01t0104800-01 N/A 5 N/A +1 irgsp exon 263525 263640 . 1 . N/A N/A 0 N/A 2 0 Os01t0104800-01.exon6 N/A Os01t0104800-01.exon6 N/A Os01t0104800-01.exon6 transcript:Os01t0104800-01 N/A 6 N/A +1 irgsp exon 264014 264098 . 1 . N/A N/A 1 N/A 0 2 Os01t0104800-01.exon7 N/A Os01t0104800-01.exon7 N/A Os01t0104800-01.exon7 transcript:Os01t0104800-01 N/A 7 N/A +1 irgsp exon 265236 265415 . 1 . N/A N/A 1 N/A 0 0 Os01t0104800-01.exon8 N/A Os01t0104800-01.exon8 N/A Os01t0104800-01.exon8 transcript:Os01t0104800-01 N/A 8 N/A +1 irgsp exon 265506 265649 . 1 . N/A N/A 1 N/A 0 0 Os01t0104800-01.exon9 N/A Os01t0104800-01.exon9 N/A Os01t0104800-01.exon9 transcript:Os01t0104800-01 N/A 9 N/A +1 irgsp exon 265740 265817 . 1 . N/A N/A 1 N/A 0 0 Os01t0104800-01.exon10 N/A Os01t0104800-01.exon10 N/A Os01t0104800-01.exon10 transcript:Os01t0104800-01 N/A 10 N/A +1 irgsp exon 265909 266045 . 1 . N/A N/A 1 N/A 2 0 Os01t0104800-01.exon11 N/A Os01t0104800-01.exon11 N/A Os01t0104800-01.exon11 transcript:Os01t0104800-01 N/A 11 N/A +1 irgsp exon 266138 266246 . 1 . N/A N/A 1 N/A 0 2 Os01t0104800-01.exon12 N/A Os01t0104800-01.exon12 N/A Os01t0104800-01.exon12 transcript:Os01t0104800-01 N/A 12 N/A +1 irgsp exon 267237 267514 . 1 . N/A N/A 1 N/A 2 0 Os01t0104800-01.exon13 N/A Os01t0104800-01.exon13 N/A Os01t0104800-01.exon13 transcript:Os01t0104800-01 N/A 13 N/A +1 irgsp exon 267591 267657 . 1 . N/A N/A 1 N/A 0 2 Os01t0104800-01.exon14 N/A Os01t0104800-01.exon14 N/A Os01t0104800-01.exon14 transcript:Os01t0104800-01 N/A 14 N/A +1 irgsp exon 267734 267802 . 1 . N/A N/A 1 N/A 0 0 Os01t0104800-01.exon15 N/A Os01t0104800-01.exon15 N/A Os01t0104800-01.exon15 transcript:Os01t0104800-01 N/A 15 N/A +1 irgsp exon 267880 268145 . 1 . N/A N/A 0 N/A -1 0 Os01t0104800-01.exon16 N/A Os01t0104800-01.exon16 N/A Os01t0104800-01.exon16 transcript:Os01t0104800-01 N/A 16 N/A +1 irgsp CDS 261562 261661 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104800-01 N/A N/A transcript:Os01t0104800-01 Os01t0104800-01 N/A N/A +1 irgsp CDS 261767 261805 . 1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104800-01 N/A N/A transcript:Os01t0104800-01 Os01t0104800-01 N/A N/A +1 irgsp CDS 261895 261941 . 1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104800-01 N/A N/A transcript:Os01t0104800-01 Os01t0104800-01 N/A N/A +1 irgsp CDS 262582 262681 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104800-01 N/A N/A transcript:Os01t0104800-01 Os01t0104800-01 N/A N/A +1 irgsp CDS 262925 263181 . 1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104800-01 N/A N/A transcript:Os01t0104800-01 Os01t0104800-01 N/A N/A +1 irgsp CDS 263525 263640 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104800-01 N/A N/A transcript:Os01t0104800-01 Os01t0104800-01 N/A N/A +1 irgsp CDS 264014 264098 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104800-01 N/A N/A transcript:Os01t0104800-01 Os01t0104800-01 N/A N/A +1 irgsp CDS 265236 265415 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104800-01 N/A N/A transcript:Os01t0104800-01 Os01t0104800-01 N/A N/A +1 irgsp CDS 265506 265649 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104800-01 N/A N/A transcript:Os01t0104800-01 Os01t0104800-01 N/A N/A +1 irgsp CDS 265740 265817 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104800-01 N/A N/A transcript:Os01t0104800-01 Os01t0104800-01 N/A N/A +1 irgsp CDS 265909 266045 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104800-01 N/A N/A transcript:Os01t0104800-01 Os01t0104800-01 N/A N/A +1 irgsp CDS 266138 266246 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104800-01 N/A N/A transcript:Os01t0104800-01 Os01t0104800-01 N/A N/A +1 irgsp CDS 267237 267514 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104800-01 N/A N/A transcript:Os01t0104800-01 Os01t0104800-01 N/A N/A +1 irgsp CDS 267591 267657 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104800-01 N/A N/A transcript:Os01t0104800-01 Os01t0104800-01 N/A N/A +1 irgsp CDS 267734 267802 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104800-01 N/A N/A transcript:Os01t0104800-01 Os01t0104800-01 N/A N/A +1 irgsp CDS 267880 268011 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104800-01 N/A N/A transcript:Os01t0104800-01 Os01t0104800-01 N/A N/A +1 irgsp five_prime_UTR 261530 261561 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-60 N/A N/A transcript:Os01t0104800-01 N/A N/A N/A +1 irgsp three_prime_UTR 268012 268145 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-57 N/A N/A transcript:Os01t0104800-01 N/A N/A N/A +1 irgsp mRNA 263523 268120 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0104800-02 N/A N/A gene:Os01g0104800 N/A N/A Os01t0104800-02 +1 irgsp exon 263523 263640 . 1 . N/A N/A 0 N/A 2 -1 Os01t0104800-02.exon1 N/A Os01t0104800-02.exon1 N/A Os01t0104800-02.exon1 transcript:Os01t0104800-02 N/A 1 N/A +1 irgsp exon 264014 264098 . 1 . N/A N/A 1 N/A 0 2 Os01t0104800-01.exon7 N/A agat-exon-27 N/A Os01t0104800-01.exon7 transcript:Os01t0104800-02 N/A 2 N/A +1 irgsp exon 265236 265415 . 1 . N/A N/A 1 N/A 0 0 Os01t0104800-01.exon8 N/A agat-exon-28 N/A Os01t0104800-01.exon8 transcript:Os01t0104800-02 N/A 3 N/A +1 irgsp exon 265506 265649 . 1 . N/A N/A 1 N/A 0 0 Os01t0104800-01.exon9 N/A agat-exon-29 N/A Os01t0104800-01.exon9 transcript:Os01t0104800-02 N/A 4 N/A +1 irgsp exon 265740 265817 . 1 . N/A N/A 1 N/A 0 0 Os01t0104800-01.exon10 N/A agat-exon-30 N/A Os01t0104800-01.exon10 transcript:Os01t0104800-02 N/A 5 N/A +1 irgsp exon 265909 266045 . 1 . N/A N/A 1 N/A 2 0 Os01t0104800-01.exon11 N/A agat-exon-31 N/A Os01t0104800-01.exon11 transcript:Os01t0104800-02 N/A 6 N/A +1 irgsp exon 266138 266246 . 1 . N/A N/A 1 N/A 0 2 Os01t0104800-01.exon12 N/A agat-exon-32 N/A Os01t0104800-01.exon12 transcript:Os01t0104800-02 N/A 7 N/A +1 irgsp exon 267237 267514 . 1 . N/A N/A 1 N/A 2 0 Os01t0104800-01.exon13 N/A agat-exon-33 N/A Os01t0104800-01.exon13 transcript:Os01t0104800-02 N/A 8 N/A +1 irgsp exon 267591 267657 . 1 . N/A N/A 1 N/A 0 2 Os01t0104800-01.exon14 N/A agat-exon-34 N/A Os01t0104800-01.exon14 transcript:Os01t0104800-02 N/A 9 N/A +1 irgsp exon 267734 267802 . 1 . N/A N/A 1 N/A 0 0 Os01t0104800-01.exon15 N/A agat-exon-35 N/A Os01t0104800-01.exon15 transcript:Os01t0104800-02 N/A 10 N/A +1 irgsp exon 267880 268120 . 1 . N/A N/A 0 N/A -1 0 Os01t0104800-02.exon11 N/A Os01t0104800-02.exon11 N/A Os01t0104800-02.exon11 transcript:Os01t0104800-02 N/A 11 N/A +1 irgsp CDS 263525 263640 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104800-02 N/A N/A transcript:Os01t0104800-02 Os01t0104800-02 N/A N/A +1 irgsp CDS 264014 264098 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104800-02 N/A N/A transcript:Os01t0104800-02 Os01t0104800-02 N/A N/A +1 irgsp CDS 265236 265415 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104800-02 N/A N/A transcript:Os01t0104800-02 Os01t0104800-02 N/A N/A +1 irgsp CDS 265506 265649 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104800-02 N/A N/A transcript:Os01t0104800-02 Os01t0104800-02 N/A N/A +1 irgsp CDS 265740 265817 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104800-02 N/A N/A transcript:Os01t0104800-02 Os01t0104800-02 N/A N/A +1 irgsp CDS 265909 266045 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104800-02 N/A N/A transcript:Os01t0104800-02 Os01t0104800-02 N/A N/A +1 irgsp CDS 266138 266246 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104800-02 N/A N/A transcript:Os01t0104800-02 Os01t0104800-02 N/A N/A +1 irgsp CDS 267237 267514 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104800-02 N/A N/A transcript:Os01t0104800-02 Os01t0104800-02 N/A N/A +1 irgsp CDS 267591 267657 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104800-02 N/A N/A transcript:Os01t0104800-02 Os01t0104800-02 N/A N/A +1 irgsp CDS 267734 267802 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104800-02 N/A N/A transcript:Os01t0104800-02 Os01t0104800-02 N/A N/A +1 irgsp CDS 267880 268011 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104800-02 N/A N/A transcript:Os01t0104800-02 Os01t0104800-02 N/A N/A +1 irgsp five_prime_UTR 263523 263524 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-61 N/A N/A transcript:Os01t0104800-02 N/A N/A N/A +1 irgsp three_prime_UTR 268012 268120 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-58 N/A N/A transcript:Os01t0104800-02 N/A N/A N/A +1 irgsp gene 270179 275084 . -1 . N/A protein_coding N/A Transferase family protein. (Os01t0104900-01);Hypothetical conserved gene. (Os01t0104900-02) N/A N/A N/A Os01g0104900 gene:Os01g0104900 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 270179 275084 . -1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0104900-01 N/A N/A gene:Os01g0104900 N/A N/A Os01t0104900-01 +1 irgsp exon 270179 271333 . -1 . N/A N/A 0 N/A -1 0 Os01t0104900-01.exon2 N/A Os01t0104900-01.exon2 N/A Os01t0104900-01.exon2 transcript:Os01t0104900-01 N/A 2 N/A +1 irgsp exon 274529 275084 . -1 . N/A N/A 0 N/A 0 -1 Os01t0104900-01.exon1 N/A Os01t0104900-01.exon1 N/A Os01t0104900-01.exon1 transcript:Os01t0104900-01 N/A 1 N/A +1 irgsp CDS 270356 271333 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104900-01 N/A N/A transcript:Os01t0104900-01 Os01t0104900-01 N/A N/A +1 irgsp CDS 274529 274957 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104900-01 N/A N/A transcript:Os01t0104900-01 Os01t0104900-01 N/A N/A +1 irgsp five_prime_UTR 274958 275084 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-62 N/A N/A transcript:Os01t0104900-01 N/A N/A N/A +1 irgsp three_prime_UTR 270179 270355 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-59 N/A N/A transcript:Os01t0104900-01 N/A N/A N/A +1 irgsp mRNA 270250 271518 . -1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0104900-02 N/A N/A gene:Os01g0104900 N/A N/A Os01t0104900-02 +1 irgsp exon 270250 271333 . -1 . N/A N/A 0 N/A -1 -1 Os01t0104900-02.exon2 N/A Os01t0104900-02.exon2 N/A Os01t0104900-02.exon2 transcript:Os01t0104900-02 N/A 2 N/A +1 irgsp exon 271457 271518 . -1 . N/A N/A 0 N/A -1 -1 Os01t0104900-02.exon1 N/A Os01t0104900-02.exon1 N/A Os01t0104900-02.exon1 transcript:Os01t0104900-02 N/A 1 N/A +1 irgsp CDS 270356 271309 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0104900-02 N/A N/A transcript:Os01t0104900-02 Os01t0104900-02 N/A N/A +1 irgsp five_prime_UTR 271310 271333 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-63 N/A N/A transcript:Os01t0104900-02 N/A N/A N/A +1 irgsp five_prime_UTR 271457 271518 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-64 N/A N/A transcript:Os01t0104900-02 N/A N/A N/A +1 irgsp three_prime_UTR 270250 270355 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-60 N/A N/A transcript:Os01t0104900-02 N/A N/A N/A +1 irgsp gene 284762 291892 . -1 . N/A protein_coding N/A Similar to HAT family dimerisation domain containing protein, expressed. (Os01t0105300-01) N/A N/A N/A Os01g0105300 gene:Os01g0105300 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 284762 291892 . -1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0105300-01 N/A N/A gene:Os01g0105300 N/A N/A Os01t0105300-01 +1 irgsp exon 284762 287047 . -1 . N/A N/A 1 N/A -1 -1 Os01t0105300-01.exon5 N/A Os01t0105300-01.exon5 N/A Os01t0105300-01.exon5 transcript:Os01t0105300-01 N/A 5 N/A +1 irgsp exon 291398 291436 . -1 . N/A N/A 1 N/A -1 -1 Os01t0105300-01.exon4 N/A Os01t0105300-01.exon4 N/A Os01t0105300-01.exon4 transcript:Os01t0105300-01 N/A 4 N/A +1 irgsp exon 291520 291534 . -1 . N/A N/A 1 N/A -1 -1 Os01t0105300-01.exon3 N/A Os01t0105300-01.exon3 N/A Os01t0105300-01.exon3 transcript:Os01t0105300-01 N/A 3 N/A +1 irgsp exon 291678 291738 . -1 . N/A N/A 1 N/A -1 -1 Os01t0105300-01.exon2 N/A Os01t0105300-01.exon2 N/A Os01t0105300-01.exon2 transcript:Os01t0105300-01 N/A 2 N/A +1 irgsp exon 291838 291892 . -1 . N/A N/A 1 N/A -1 -1 Os01t0105300-01.exon1 N/A Os01t0105300-01.exon1 N/A Os01t0105300-01.exon1 transcript:Os01t0105300-01 N/A 1 N/A +1 irgsp CDS 284931 285020 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0105300-01 N/A N/A transcript:Os01t0105300-01 Os01t0105300-01 N/A N/A +1 irgsp five_prime_UTR 285021 287047 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-65 N/A N/A transcript:Os01t0105300-01 N/A N/A N/A +1 irgsp five_prime_UTR 291398 291436 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-66 N/A N/A transcript:Os01t0105300-01 N/A N/A N/A +1 irgsp five_prime_UTR 291520 291534 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-67 N/A N/A transcript:Os01t0105300-01 N/A N/A N/A +1 irgsp five_prime_UTR 291678 291738 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-68 N/A N/A transcript:Os01t0105300-01 N/A N/A N/A +1 irgsp five_prime_UTR 291838 291892 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-69 N/A N/A transcript:Os01t0105300-01 N/A N/A N/A +1 irgsp three_prime_UTR 284762 284930 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-61 N/A N/A transcript:Os01t0105300-01 N/A N/A N/A +1 irgsp gene 288372 292296 . 1 . N/A protein_coding N/A Similar to Kinesin heavy chain. (Os01t0105400-01) N/A N/A N/A Os01g0105400 gene:Os01g0105400 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 288372 292296 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0105400-01 N/A N/A gene:Os01g0105400 N/A N/A Os01t0105400-01 +1 irgsp exon 288372 288846 . 1 . N/A N/A 1 N/A -1 -1 Os01t0105400-01.exon1 N/A Os01t0105400-01.exon1 N/A Os01t0105400-01.exon1 transcript:Os01t0105400-01 N/A 1 N/A +1 irgsp exon 288950 289116 . 1 . N/A N/A 1 N/A -1 -1 Os01t0105400-01.exon2 N/A Os01t0105400-01.exon2 N/A Os01t0105400-01.exon2 transcript:Os01t0105400-01 N/A 2 N/A +1 irgsp exon 289202 289572 . 1 . N/A N/A 1 N/A -1 -1 Os01t0105400-01.exon3 N/A Os01t0105400-01.exon3 N/A Os01t0105400-01.exon3 transcript:Os01t0105400-01 N/A 3 N/A +1 irgsp exon 289661 289830 . 1 . N/A N/A 1 N/A -1 -1 Os01t0105400-01.exon4 N/A Os01t0105400-01.exon4 N/A Os01t0105400-01.exon4 transcript:Os01t0105400-01 N/A 4 N/A +1 irgsp exon 290395 290512 . 1 . N/A N/A 1 N/A 2 -1 Os01t0105400-01.exon5 N/A Os01t0105400-01.exon5 N/A Os01t0105400-01.exon5 transcript:Os01t0105400-01 N/A 5 N/A +1 irgsp exon 291372 291574 . 1 . N/A N/A 1 N/A -1 2 Os01t0105400-01.exon6 N/A Os01t0105400-01.exon6 N/A Os01t0105400-01.exon6 transcript:Os01t0105400-01 N/A 6 N/A +1 irgsp exon 291648 291779 . 1 . N/A N/A 1 N/A -1 -1 Os01t0105400-01.exon7 N/A Os01t0105400-01.exon7 N/A Os01t0105400-01.exon7 transcript:Os01t0105400-01 N/A 7 N/A +1 irgsp exon 291859 291948 . 1 . N/A N/A 1 N/A -1 -1 Os01t0105400-01.exon8 N/A Os01t0105400-01.exon8 N/A Os01t0105400-01.exon8 transcript:Os01t0105400-01 N/A 8 N/A +1 irgsp exon 292073 292296 . 1 . N/A N/A 1 N/A -1 -1 Os01t0105400-01.exon9 N/A Os01t0105400-01.exon9 N/A Os01t0105400-01.exon9 transcript:Os01t0105400-01 N/A 9 N/A +1 irgsp CDS 290433 290512 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0105400-01 N/A N/A transcript:Os01t0105400-01 Os01t0105400-01 N/A N/A +1 irgsp CDS 291372 291558 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0105400-01 N/A N/A transcript:Os01t0105400-01 Os01t0105400-01 N/A N/A +1 irgsp five_prime_UTR 288372 288846 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-70 N/A N/A transcript:Os01t0105400-01 N/A N/A N/A +1 irgsp five_prime_UTR 288950 289116 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-71 N/A N/A transcript:Os01t0105400-01 N/A N/A N/A +1 irgsp five_prime_UTR 289202 289572 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-72 N/A N/A transcript:Os01t0105400-01 N/A N/A N/A +1 irgsp five_prime_UTR 289661 289830 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-73 N/A N/A transcript:Os01t0105400-01 N/A N/A N/A +1 irgsp five_prime_UTR 290395 290432 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-74 N/A N/A transcript:Os01t0105400-01 N/A N/A N/A +1 irgsp three_prime_UTR 291559 291574 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-62 N/A N/A transcript:Os01t0105400-01 N/A N/A N/A +1 irgsp three_prime_UTR 291648 291779 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-63 N/A N/A transcript:Os01t0105400-01 N/A N/A N/A +1 irgsp three_prime_UTR 291859 291948 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-64 N/A N/A transcript:Os01t0105400-01 N/A N/A N/A +1 irgsp three_prime_UTR 292073 292296 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-65 N/A N/A transcript:Os01t0105400-01 N/A N/A N/A +1 irgsp gene 303233 306736 . 1 . N/A protein_coding N/A Basic helix-loop-helix dimerisation region bHLH domain containing protein. (Os01t0105700-01) N/A N/A N/A Os01g0105700 gene:Os01g0105700 irgspv1.0-20170804-genes basic helix-loop-helix protein 071 N/A N/A N/A N/A +1 irgsp mRNA 303233 306736 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0105700-01 N/A N/A gene:Os01g0105700 N/A N/A Os01t0105700-01 +1 irgsp exon 303233 303471 . 1 . N/A N/A 1 N/A 2 -1 Os01t0105700-01.exon1 N/A Os01t0105700-01.exon1 N/A Os01t0105700-01.exon1 transcript:Os01t0105700-01 N/A 1 N/A +1 irgsp exon 303981 304509 . 1 . N/A N/A 1 N/A 0 2 Os01t0105700-01.exon2 N/A Os01t0105700-01.exon2 N/A Os01t0105700-01.exon2 transcript:Os01t0105700-01 N/A 2 N/A +1 irgsp exon 305572 305718 . 1 . N/A N/A 1 N/A 0 0 Os01t0105700-01.exon3 N/A Os01t0105700-01.exon3 N/A Os01t0105700-01.exon3 transcript:Os01t0105700-01 N/A 3 N/A +1 irgsp exon 305834 305899 . 1 . N/A N/A 1 N/A 0 0 Os01t0105700-01.exon4 N/A Os01t0105700-01.exon4 N/A Os01t0105700-01.exon4 transcript:Os01t0105700-01 N/A 4 N/A +1 irgsp exon 305993 306058 . 1 . N/A N/A 1 N/A 0 0 Os01t0105700-01.exon5 N/A Os01t0105700-01.exon5 N/A Os01t0105700-01.exon5 transcript:Os01t0105700-01 N/A 5 N/A +1 irgsp exon 306171 306245 . 1 . N/A N/A 1 N/A 0 0 Os01t0105700-01.exon6 N/A Os01t0105700-01.exon6 N/A Os01t0105700-01.exon6 transcript:Os01t0105700-01 N/A 6 N/A +1 irgsp exon 306353 306736 . 1 . N/A N/A 1 N/A -1 0 Os01t0105700-01.exon7 N/A Os01t0105700-01.exon7 N/A Os01t0105700-01.exon7 transcript:Os01t0105700-01 N/A 7 N/A +1 irgsp CDS 303329 303471 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0105700-01 N/A N/A transcript:Os01t0105700-01 Os01t0105700-01 N/A N/A +1 irgsp CDS 303981 304509 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0105700-01 N/A N/A transcript:Os01t0105700-01 Os01t0105700-01 N/A N/A +1 irgsp CDS 305572 305718 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0105700-01 N/A N/A transcript:Os01t0105700-01 Os01t0105700-01 N/A N/A +1 irgsp CDS 305834 305899 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0105700-01 N/A N/A transcript:Os01t0105700-01 Os01t0105700-01 N/A N/A +1 irgsp CDS 305993 306058 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0105700-01 N/A N/A transcript:Os01t0105700-01 Os01t0105700-01 N/A N/A +1 irgsp CDS 306171 306245 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0105700-01 N/A N/A transcript:Os01t0105700-01 Os01t0105700-01 N/A N/A +1 irgsp CDS 306353 306493 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0105700-01 N/A N/A transcript:Os01t0105700-01 Os01t0105700-01 N/A N/A +1 irgsp five_prime_UTR 303233 303328 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-75 N/A N/A transcript:Os01t0105700-01 N/A N/A N/A +1 irgsp three_prime_UTR 306494 306736 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-66 N/A N/A transcript:Os01t0105700-01 N/A N/A N/A +1 irgsp gene 306871 308842 . -1 . N/A protein_coding N/A Similar to Iron sulfur assembly protein 1. (Os01t0105800-01) N/A N/A N/A Os01g0105800 gene:Os01g0105800 irgspv1.0-20170804-genes IRON-SULFUR CLUSTER PROTEIN 9 N/A N/A N/A N/A +1 irgsp mRNA 306871 308842 . -1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0105800-01 N/A N/A gene:Os01g0105800 N/A N/A Os01t0105800-01 +1 irgsp exon 306871 307217 . -1 . N/A N/A 1 N/A -1 2 Os01t0105800-01.exon4 N/A Os01t0105800-01.exon4 N/A Os01t0105800-01.exon4 transcript:Os01t0105800-01 N/A 4 N/A +1 irgsp exon 307296 307413 . -1 . N/A N/A 1 N/A 2 1 Os01t0105800-01.exon3 N/A Os01t0105800-01.exon3 N/A Os01t0105800-01.exon3 transcript:Os01t0105800-01 N/A 3 N/A +1 irgsp exon 308397 308626 . -1 . N/A N/A 1 N/A 1 -1 Os01t0105800-01.exon2 N/A Os01t0105800-01.exon2 N/A Os01t0105800-01.exon2 transcript:Os01t0105800-01 N/A 2 N/A +1 irgsp exon 308703 308842 . -1 . N/A N/A 1 N/A -1 -1 Os01t0105800-01.exon1 N/A Os01t0105800-01.exon1 N/A Os01t0105800-01.exon1 transcript:Os01t0105800-01 N/A 1 N/A +1 irgsp CDS 307124 307217 . -1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0105800-01 N/A N/A transcript:Os01t0105800-01 Os01t0105800-01 N/A N/A +1 irgsp CDS 307296 307413 . -1 2 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0105800-01 N/A N/A transcript:Os01t0105800-01 Os01t0105800-01 N/A N/A +1 irgsp CDS 308397 308601 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0105800-01 N/A N/A transcript:Os01t0105800-01 Os01t0105800-01 N/A N/A +1 irgsp five_prime_UTR 308602 308626 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-76 N/A N/A transcript:Os01t0105800-01 N/A N/A N/A +1 irgsp five_prime_UTR 308703 308842 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-77 N/A N/A transcript:Os01t0105800-01 N/A N/A N/A +1 irgsp three_prime_UTR 306871 307123 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-67 N/A N/A transcript:Os01t0105800-01 N/A N/A N/A +1 irgsp gene 309520 313170 . -1 . N/A protein_coding N/A Carbohydrate/purine kinase domain containing protein. (Os01t0105900-01) N/A N/A N/A Os01g0105900 gene:Os01g0105900 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 309520 313170 . -1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0105900-01 N/A N/A gene:Os01g0105900 N/A N/A Os01t0105900-01 +1 irgsp exon 309520 310070 . -1 . N/A N/A 1 N/A -1 0 Os01t0105900-01.exon8 N/A Os01t0105900-01.exon8 N/A Os01t0105900-01.exon8 transcript:Os01t0105900-01 N/A 8 N/A +1 irgsp exon 310256 310367 . -1 . N/A N/A 1 N/A 0 2 Os01t0105900-01.exon7 N/A Os01t0105900-01.exon7 N/A Os01t0105900-01.exon7 transcript:Os01t0105900-01 N/A 7 N/A +1 irgsp exon 310455 310552 . -1 . N/A N/A 1 N/A 2 0 Os01t0105900-01.exon6 N/A Os01t0105900-01.exon6 N/A Os01t0105900-01.exon6 transcript:Os01t0105900-01 N/A 6 N/A +1 irgsp exon 310632 310739 . -1 . N/A N/A 1 N/A 0 0 Os01t0105900-01.exon5 N/A Os01t0105900-01.exon5 N/A Os01t0105900-01.exon5 transcript:Os01t0105900-01 N/A 5 N/A +1 irgsp exon 310880 310918 . -1 . N/A N/A 1 N/A 0 0 Os01t0105900-01.exon4 N/A Os01t0105900-01.exon4 N/A Os01t0105900-01.exon4 transcript:Os01t0105900-01 N/A 4 N/A +1 irgsp exon 311002 311073 . -1 . N/A N/A 1 N/A 0 0 Os01t0105900-01.exon3 N/A Os01t0105900-01.exon3 N/A Os01t0105900-01.exon3 transcript:Os01t0105900-01 N/A 3 N/A +1 irgsp exon 311163 311426 . -1 . N/A N/A 1 N/A 0 0 Os01t0105900-01.exon2 N/A Os01t0105900-01.exon2 N/A Os01t0105900-01.exon2 transcript:Os01t0105900-01 N/A 2 N/A +1 irgsp exon 312867 313170 . -1 . N/A N/A 1 N/A 0 -1 Os01t0105900-01.exon1 N/A Os01t0105900-01.exon1 N/A Os01t0105900-01.exon1 transcript:Os01t0105900-01 N/A 1 N/A +1 irgsp CDS 309822 310070 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0105900-01 N/A N/A transcript:Os01t0105900-01 Os01t0105900-01 N/A N/A +1 irgsp CDS 310256 310367 . -1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0105900-01 N/A N/A transcript:Os01t0105900-01 Os01t0105900-01 N/A N/A +1 irgsp CDS 310455 310552 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0105900-01 N/A N/A transcript:Os01t0105900-01 Os01t0105900-01 N/A N/A +1 irgsp CDS 310632 310739 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0105900-01 N/A N/A transcript:Os01t0105900-01 Os01t0105900-01 N/A N/A +1 irgsp CDS 310880 310918 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0105900-01 N/A N/A transcript:Os01t0105900-01 Os01t0105900-01 N/A N/A +1 irgsp CDS 311002 311073 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0105900-01 N/A N/A transcript:Os01t0105900-01 Os01t0105900-01 N/A N/A +1 irgsp CDS 311163 311426 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0105900-01 N/A N/A transcript:Os01t0105900-01 Os01t0105900-01 N/A N/A +1 irgsp CDS 312867 313064 . -1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0105900-01 N/A N/A transcript:Os01t0105900-01 Os01t0105900-01 N/A N/A +1 irgsp five_prime_UTR 313065 313170 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-78 N/A N/A transcript:Os01t0105900-01 N/A N/A N/A +1 irgsp three_prime_UTR 309520 309821 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-68 N/A N/A transcript:Os01t0105900-01 N/A N/A N/A +1 irgsp gene 319754 322205 . 1 . N/A protein_coding N/A Similar to RER1A protein (AtRER1A). (Os01t0106200-01) N/A N/A N/A Os01g0106200 gene:Os01g0106200 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 319754 322205 . 1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0106200-01 N/A N/A gene:Os01g0106200 N/A N/A Os01t0106200-01 +1 irgsp exon 319754 320236 . 1 . N/A N/A 1 N/A 2 -1 Os01t0106200-01.exon1 N/A Os01t0106200-01.exon1 N/A Os01t0106200-01.exon1 transcript:Os01t0106200-01 N/A 1 N/A +1 irgsp exon 321468 321648 . 1 . N/A N/A 1 N/A 0 2 Os01t0106200-01.exon2 N/A Os01t0106200-01.exon2 N/A Os01t0106200-01.exon2 transcript:Os01t0106200-01 N/A 2 N/A +1 irgsp exon 321928 322205 . 1 . N/A N/A 1 N/A -1 0 Os01t0106200-01.exon3 N/A Os01t0106200-01.exon3 N/A Os01t0106200-01.exon3 transcript:Os01t0106200-01 N/A 3 N/A +1 irgsp CDS 319875 320236 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0106200-01 N/A N/A transcript:Os01t0106200-01 Os01t0106200-01 N/A N/A +1 irgsp CDS 321468 321648 . 1 1 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0106200-01 N/A N/A transcript:Os01t0106200-01 Os01t0106200-01 N/A N/A +1 irgsp CDS 321928 321975 . 1 0 N/A N/A N/A N/A N/A N/A N/A N/A CDS:Os01t0106200-01 N/A N/A transcript:Os01t0106200-01 Os01t0106200-01 N/A N/A +1 irgsp five_prime_UTR 319754 319874 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-five_prime_utr-79 N/A N/A transcript:Os01t0106200-01 N/A N/A N/A +1 irgsp three_prime_UTR 321976 322205 . 1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-69 N/A N/A transcript:Os01t0106200-01 N/A N/A N/A +1 irgsp gene 322591 323923 . -1 . N/A protein_coding N/A Similar to Isoflavone reductase homolog IRL (EC 1.3.1.-). (Os01t0106300-01) N/A N/A N/A Os01g0106300 gene:Os01g0106300 irgspv1.0-20170804-genes N/A N/A N/A N/A N/A +1 irgsp mRNA 322591 323923 . -1 . N/A protein_coding N/A N/A N/A N/A N/A N/A transcript:Os01t0106300-01 N/A N/A gene:Os01g0106300 N/A N/A Os01t0106300-01 +1 irgsp exon 322591 323923 . -1 . N/A N/A 1 N/A -1 1 Os01t0106300-01.exon2 N/A Os01t0106300-01.exon2 N/A Os01t0106300-01.exon2 transcript:Os01t0106300-01 N/A 2 N/A +1 irgsp three_prime_UTR 322591 322809 . -1 . N/A N/A N/A N/A N/A N/A N/A N/A agat-three_prime_utr-70 N/A N/A transcript:Os01t0106300-01 N/A N/A N/A diff --git a/src/agat/agat_convert_sp_gff2tsv/test_data/script.sh b/src/agat/agat_convert_sp_gff2tsv/test_data/script.sh new file mode 100755 index 00000000..ba7ba143 --- /dev/null +++ b/src/agat/agat_convert_sp_gff2tsv/test_data/script.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +# clone repo +if [ ! -d /tmp/agat_source ]; then + git clone --depth 1 --single-branch --branch master https://github.com/NBISweden/AGAT /tmp/agat_source +fi + +# copy test data +cp -r /tmp/agat_source/t/scripts_output/out/agat_convert_sp_gff2tsv_1.tsv src/agat/agat_convert_sp_gff2tsv/test_data +cp -r /tmp/agat_source/t/scripts_output/in/1.gff src/agat/agat_convert_sp_gff2tsv/test_data diff --git a/src/agat/agat_convert_sp_gxf2gxf/config.vsh.yaml b/src/agat/agat_convert_sp_gxf2gxf/config.vsh.yaml new file mode 100644 index 00000000..9e77b09d --- /dev/null +++ b/src/agat/agat_convert_sp_gxf2gxf/config.vsh.yaml @@ -0,0 +1,75 @@ +name: agat_convert_sp_gxf2gxf +namespace: agat +description: | + This script fixes and/or standardizes any GTF/GFF file into full sorted + GTF/GFF file. It AGAT parser removes duplicate features, fixes + duplicated IDs, adds missing ID and/or Parent attributes, deflates + factorized attributes (attributes with several parents are duplicated + with uniq ID), add missing features when possible (e.g. add exon if only + CDS described, add UTR if CDS and exon described), fix feature locations + (e.g. check exon is embedded in the parent features mRNA, gene), etc... + + All AGAT's scripts with the _sp_ prefix use the AGAT parser, before to + perform any supplementary task. So, it is not necessary to run this + script prior the use of any other _sp_ script. +keywords: [gene annotations, GFF conversion] +links: + homepage: https://github.com/NBISweden/AGAT + documentation: https://agat.readthedocs.io/en/latest/tools/agat_convert_sp_gxf2gxf.html + issue_tracker: https://github.com/NBISweden/AGAT/issues + repository: https://github.com/NBISweden/AGAT +references: + doi: 10.5281/zenodo.3552717 +license: GPL-3.0 +authors: + - __merge__: /src/_authors/leila_paquay.yaml + roles: [ author, maintainer ] + +argument_groups: + - name: Inputs + arguments: + - name: --gxf + alternatives: [-g, --gtf, --gff] + description: | + String - Input GTF/GFF file. Compressed file with .gz extension is accepted. + type: file + required: true + direction: input + example: input.gff + - name: Outputs + arguments: + - name: --output + alternatives: [-o] + description: | + String - Output GFF file. If no output file is specified, the output will be written to STDOUT. + type: file + direction: output + required: true + example: output.gff + - name: Arguments + arguments: + - name: --config + alternatives: [-c] + description: | + String - Input agat config file. By default AGAT takes as input agat_config.yaml file from the working directory if any, otherwise it takes the original agat_config.yaml shipped with AGAT. To get the agat_config.yaml locally type: "agat config --expose". The --config option gives you the possibility to use your own AGAT config file (located elsewhere or named differently). + type: file + required: false + example: custom_agat_config.yaml +resources: + - type: bash_script + path: script.sh +test_resources: + - type: bash_script + path: test.sh + - type: file + path: test_data +engines: + - type: docker + image: quay.io/biocontainers/agat:1.4.0--pl5321hdfd78af_0 + setup: + - type: docker + run: | + agat --version | sed 's/AGAT\s\(.*\)/agat: "\1"/' > /var/software_versions.txt +runners: + - type: executable + - type: nextflow \ No newline at end of file diff --git a/src/agat/agat_convert_sp_gxf2gxf/help.txt b/src/agat/agat_convert_sp_gxf2gxf/help.txt new file mode 100644 index 00000000..7658c4ed --- /dev/null +++ b/src/agat/agat_convert_sp_gxf2gxf/help.txt @@ -0,0 +1,73 @@ +```sh +agat_convert_sp_gxf2gxf.pl --help +``` + + ------------------------------------------------------------------------------ +| Another GFF Analysis Toolkit (AGAT) - Version: v1.4.0 | +| https://github.com/NBISweden/AGAT | +| National Bioinformatics Infrastructure Sweden (NBIS) - www.nbis.se | + ------------------------------------------------------------------------------ + + +Name: + agat_convert_sp_gxf2gxf.pl + +Description: + This script fixes and/or standardizes any GTF/GFF file into full sorted + GTF/GFF file. It AGAT parser removes duplicate features, fixes + duplicated IDs, adds missing ID and/or Parent attributes, deflates + factorized attributes (attributes with several parents are duplicated + with uniq ID), add missing features when possible (e.g. add exon if only + CDS described, add UTR if CDS and exon described), fix feature locations + (e.g. check exon is embedded in the parent features mRNA, gene), etc... + + All AGAT's scripts with the _sp_ prefix use the AGAT parser, before to + perform any supplementary task. So, it is not necessary to run this + script prior the use of any other _sp_ script. + +Usage: + agat_convert_sp_gxf2gxf.pl -g infile.gff [ -o outfile ] + agat_convert_sp_gxf2gxf.pl --help + +Options: + -g, --gtf, --gff or --gxf + String - Input GTF/GFF file. Compressed file with .gz extension + is accepted. + + -o or --output + String - Output GFF file. If no output file is specified, the + output will be written to STDOUT. + + -c or --config + String - Input agat config file. By default AGAT takes as input + agat_config.yaml file from the working directory if any, + otherwise it takes the orignal agat_config.yaml shipped with + AGAT. To get the agat_config.yaml locally type: "agat config + --expose". The --config option gives you the possibility to use + your own AGAT config file (located elsewhere or named + differently). + + -h or --help + Boolean - Display this helpful text. + +Feedback: + Did you find a bug?: + Do not hesitate to report bugs to help us keep track of the bugs and + their resolution. Please use the GitHub issue tracking system available + at this address: + + https://github.com/NBISweden/AGAT/issues + + Ensure that the bug was not already reported by searching under Issues. + If you're unable to find an (open) issue addressing the problem, open a new one. + Try as much as possible to include in the issue when relevant: + - a clear description, + - as much relevant information as possible, + - the command used, + - a data sample, + - an explanation of the expected behaviour that is not occurring. + + Do you want to contribute?: + You are very welcome, visit this address for the Contributing + guidelines: + https://github.com/NBISweden/AGAT/blob/master/CONTRIBUTING.md \ No newline at end of file diff --git a/src/agat/agat_convert_sp_gxf2gxf/script.sh b/src/agat/agat_convert_sp_gxf2gxf/script.sh new file mode 100644 index 00000000..2d532a41 --- /dev/null +++ b/src/agat/agat_convert_sp_gxf2gxf/script.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +## VIASH START +## VIASH END + +agat_convert_sp_gxf2gxf.pl \ + -g "$par_gxf" \ + -o "$par_output" \ + ${par_config:+--config "${par_config}"} diff --git a/src/agat/agat_convert_sp_gxf2gxf/test.sh b/src/agat/agat_convert_sp_gxf2gxf/test.sh new file mode 100644 index 00000000..99574b5b --- /dev/null +++ b/src/agat/agat_convert_sp_gxf2gxf/test.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +## VIASH START +## VIASH END + +test_dir="${meta_resources_dir}/test_data" +out_dir="${meta_resources_dir}/out_data" + +echo "> Run $meta_name with test data" +"$meta_executable" \ + --gxf "$test_dir/0_test.gff" \ + --output "$out_dir/output.gff" + +echo ">> Checking output" +[ ! -f "$out_dir/output.gff" ] && echo "Output file output.gff does not exist" && exit 1 + +echo ">> Check if output is empty" +[ ! -s "$out_dir/output.gff" ] && echo "Output file output.gff is empty" && exit 1 + + +echo ">> Check if output matches expected output" +diff "$out_dir/output.gff" "$test_dir/0_correct_output.gff" +if [ $? -ne 0 ]; then + echo "Output file output.gff does not match expected output" + exit 1 +fi + +echo "> Test successful" \ No newline at end of file diff --git a/src/agat/agat_convert_sp_gxf2gxf/test_data/0_correct_output.gff b/src/agat/agat_convert_sp_gxf2gxf/test_data/0_correct_output.gff new file mode 100644 index 00000000..fafe86ed --- /dev/null +++ b/src/agat/agat_convert_sp_gxf2gxf/test_data/0_correct_output.gff @@ -0,0 +1,36 @@ +##gff-version 3 +scaffold625 maker gene 337818 343277 . + . ID=CLUHARG00000005458;Name=TUBB3_2 +scaffold625 maker mRNA 337818 343277 . + . ID=CLUHART00000008717;Parent=CLUHARG00000005458 +scaffold625 maker exon 337818 337971 . + . ID=CLUHART00000008717:exon:1404;Parent=CLUHART00000008717 +scaffold625 maker exon 340733 340841 . + . ID=CLUHART00000008717:exon:1405;Parent=CLUHART00000008717 +scaffold625 maker exon 341518 341628 . + . ID=CLUHART00000008717:exon:1406;Parent=CLUHART00000008717 +scaffold625 maker exon 341964 343277 . + . ID=CLUHART00000008717:exon:1407;Parent=CLUHART00000008717 +scaffold625 maker CDS 337915 337971 . + 0 ID=CLUHART00000008717:cds;Parent=CLUHART00000008717 +scaffold625 maker CDS 340733 340841 . + 0 ID=CLUHART00000008717:cds;Parent=CLUHART00000008717 +scaffold625 maker CDS 341518 341628 . + 2 ID=CLUHART00000008717:cds;Parent=CLUHART00000008717 +scaffold625 maker CDS 341964 343033 . + 2 ID=CLUHART00000008717:cds;Parent=CLUHART00000008717 +scaffold625 maker five_prime_UTR 337818 337914 . + . ID=CLUHART00000008717:five_prime_utr;Parent=CLUHART00000008717 +scaffold625 maker three_prime_UTR 343034 343277 . + . ID=CLUHART00000008717:three_prime_utr;Parent=CLUHART00000008717 +scaffold789 maker gene 558184 564780 . + . ID=CLUHARG00000003852;Name=PF11_0240 +scaffold789 maker mRNA 558184 564780 . + . ID=CLUHART00000006146;Parent=CLUHARG00000003852 +scaffold789 maker exon 558184 560123 . + . ID=CLUHART00000006146:exon:995;Parent=CLUHART00000006146 +scaffold789 maker exon 561401 561519 . + . ID=CLUHART00000006146:exon:996;Parent=CLUHART00000006146 +scaffold789 maker exon 564171 564235 . + . ID=CLUHART00000006146:exon:997;Parent=CLUHART00000006146 +scaffold789 maker exon 564372 564780 . + . ID=CLUHART00000006146:exon:998;Parent=CLUHART00000006146 +scaffold789 maker CDS 558191 560123 . + 0 ID=CLUHART00000006146:cds;Parent=CLUHART00000006146 +scaffold789 maker CDS 561401 561519 . + 2 ID=CLUHART00000006146:cds;Parent=CLUHART00000006146 +scaffold789 maker CDS 564171 564235 . + 0 ID=CLUHART00000006146:cds;Parent=CLUHART00000006146 +scaffold789 maker CDS 564372 564588 . + 1 ID=CLUHART00000006146:cds;Parent=CLUHART00000006146 +scaffold789 maker five_prime_UTR 558184 558190 . + . ID=CLUHART00000006146:five_prime_utr;Parent=CLUHART00000006146 +scaffold789 maker three_prime_UTR 564589 564780 . + . ID=CLUHART00000006146:three_prime_utr;Parent=CLUHART00000006146 +scaffold789 maker mRNA 558184 564780 . + . ID=CLUHART00000006147;Parent=CLUHARG00000003852 +scaffold789 maker exon 558184 560123 . + . ID=CLUHART00000006147:exon:997;Parent=CLUHART00000006147 +scaffold789 maker exon 561401 561519 . + . ID=CLUHART00000006147:exon:998;Parent=CLUHART00000006147 +scaffold789 maker exon 562057 562121 . + . ID=CLUHART00000006147:exon:999;Parent=CLUHART00000006147 +scaffold789 maker exon 564372 564780 . + . ID=CLUHART00000006147:exon:1000;Parent=CLUHART00000006147 +scaffold789 maker CDS 558191 560123 . + 0 ID=CLUHART00000006147:cds;Parent=CLUHART00000006147 +scaffold789 maker CDS 561401 561519 . + 2 ID=CLUHART00000006147:cds;Parent=CLUHART00000006147 +scaffold789 maker CDS 562057 562121 . + 0 ID=CLUHART00000006147:cds;Parent=CLUHART00000006147 +scaffold789 maker CDS 564372 564588 . + 1 ID=CLUHART00000006147:cds;Parent=CLUHART00000006147 +scaffold789 maker five_prime_UTR 558184 558190 . + . ID=CLUHART00000006147:five_prime_utr;Parent=CLUHART00000006147 +scaffold789 maker three_prime_UTR 564589 564780 . + . ID=CLUHART00000006147:three_prime_utr;Parent=CLUHART00000006147 diff --git a/src/agat/agat_convert_sp_gxf2gxf/test_data/0_test.gff b/src/agat/agat_convert_sp_gxf2gxf/test_data/0_test.gff new file mode 100644 index 00000000..fafe86ed --- /dev/null +++ b/src/agat/agat_convert_sp_gxf2gxf/test_data/0_test.gff @@ -0,0 +1,36 @@ +##gff-version 3 +scaffold625 maker gene 337818 343277 . + . ID=CLUHARG00000005458;Name=TUBB3_2 +scaffold625 maker mRNA 337818 343277 . + . ID=CLUHART00000008717;Parent=CLUHARG00000005458 +scaffold625 maker exon 337818 337971 . + . ID=CLUHART00000008717:exon:1404;Parent=CLUHART00000008717 +scaffold625 maker exon 340733 340841 . + . ID=CLUHART00000008717:exon:1405;Parent=CLUHART00000008717 +scaffold625 maker exon 341518 341628 . + . ID=CLUHART00000008717:exon:1406;Parent=CLUHART00000008717 +scaffold625 maker exon 341964 343277 . + . ID=CLUHART00000008717:exon:1407;Parent=CLUHART00000008717 +scaffold625 maker CDS 337915 337971 . + 0 ID=CLUHART00000008717:cds;Parent=CLUHART00000008717 +scaffold625 maker CDS 340733 340841 . + 0 ID=CLUHART00000008717:cds;Parent=CLUHART00000008717 +scaffold625 maker CDS 341518 341628 . + 2 ID=CLUHART00000008717:cds;Parent=CLUHART00000008717 +scaffold625 maker CDS 341964 343033 . + 2 ID=CLUHART00000008717:cds;Parent=CLUHART00000008717 +scaffold625 maker five_prime_UTR 337818 337914 . + . ID=CLUHART00000008717:five_prime_utr;Parent=CLUHART00000008717 +scaffold625 maker three_prime_UTR 343034 343277 . + . ID=CLUHART00000008717:three_prime_utr;Parent=CLUHART00000008717 +scaffold789 maker gene 558184 564780 . + . ID=CLUHARG00000003852;Name=PF11_0240 +scaffold789 maker mRNA 558184 564780 . + . ID=CLUHART00000006146;Parent=CLUHARG00000003852 +scaffold789 maker exon 558184 560123 . + . ID=CLUHART00000006146:exon:995;Parent=CLUHART00000006146 +scaffold789 maker exon 561401 561519 . + . ID=CLUHART00000006146:exon:996;Parent=CLUHART00000006146 +scaffold789 maker exon 564171 564235 . + . ID=CLUHART00000006146:exon:997;Parent=CLUHART00000006146 +scaffold789 maker exon 564372 564780 . + . ID=CLUHART00000006146:exon:998;Parent=CLUHART00000006146 +scaffold789 maker CDS 558191 560123 . + 0 ID=CLUHART00000006146:cds;Parent=CLUHART00000006146 +scaffold789 maker CDS 561401 561519 . + 2 ID=CLUHART00000006146:cds;Parent=CLUHART00000006146 +scaffold789 maker CDS 564171 564235 . + 0 ID=CLUHART00000006146:cds;Parent=CLUHART00000006146 +scaffold789 maker CDS 564372 564588 . + 1 ID=CLUHART00000006146:cds;Parent=CLUHART00000006146 +scaffold789 maker five_prime_UTR 558184 558190 . + . ID=CLUHART00000006146:five_prime_utr;Parent=CLUHART00000006146 +scaffold789 maker three_prime_UTR 564589 564780 . + . ID=CLUHART00000006146:three_prime_utr;Parent=CLUHART00000006146 +scaffold789 maker mRNA 558184 564780 . + . ID=CLUHART00000006147;Parent=CLUHARG00000003852 +scaffold789 maker exon 558184 560123 . + . ID=CLUHART00000006147:exon:997;Parent=CLUHART00000006147 +scaffold789 maker exon 561401 561519 . + . ID=CLUHART00000006147:exon:998;Parent=CLUHART00000006147 +scaffold789 maker exon 562057 562121 . + . ID=CLUHART00000006147:exon:999;Parent=CLUHART00000006147 +scaffold789 maker exon 564372 564780 . + . ID=CLUHART00000006147:exon:1000;Parent=CLUHART00000006147 +scaffold789 maker CDS 558191 560123 . + 0 ID=CLUHART00000006147:cds;Parent=CLUHART00000006147 +scaffold789 maker CDS 561401 561519 . + 2 ID=CLUHART00000006147:cds;Parent=CLUHART00000006147 +scaffold789 maker CDS 562057 562121 . + 0 ID=CLUHART00000006147:cds;Parent=CLUHART00000006147 +scaffold789 maker CDS 564372 564588 . + 1 ID=CLUHART00000006147:cds;Parent=CLUHART00000006147 +scaffold789 maker five_prime_UTR 558184 558190 . + . ID=CLUHART00000006147:five_prime_utr;Parent=CLUHART00000006147 +scaffold789 maker three_prime_UTR 564589 564780 . + . ID=CLUHART00000006147:three_prime_utr;Parent=CLUHART00000006147 diff --git a/src/agat/agat_convert_sp_gxf2gxf/test_data/script.sh b/src/agat/agat_convert_sp_gxf2gxf/test_data/script.sh new file mode 100755 index 00000000..831dd963 --- /dev/null +++ b/src/agat/agat_convert_sp_gxf2gxf/test_data/script.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +# clone repo +if [ ! -d /tmp/agat_source ]; then + git clone --depth 1 --single-branch --branch master https://github.com/NBISweden/AGAT /tmp/agat_source +fi + +# copy test data +cp -r /tmp/agat_source/t/gff_syntax/in/0_test.gff src/agat/agat_convert_sp_gxf2gxf/test_data +cp -r /tmp/agat_source/t/gff_syntax/out/0_correct_output.gff src/agat/agat_convert_sp_gxf2gxf/test_data diff --git a/src/bedtools/bedtools_bamtofastq/config.vsh.yaml b/src/bedtools/bedtools_bamtofastq/config.vsh.yaml new file mode 100644 index 00000000..cd30cb71 --- /dev/null +++ b/src/bedtools/bedtools_bamtofastq/config.vsh.yaml @@ -0,0 +1,74 @@ +name: bedtools_bamtofastq +namespace: bedtools +description: | + Conversion tool for extracting FASTQ records from sequence alignments in BAM format. +keywords: [Conversion ,BAM, FASTQ] +links: + documentation: https://bedtools.readthedocs.io/en/latest/content/tools/bamtofastq.html + repository: https://github.com/arq5x/bedtools2 + homepage: https://bedtools.readthedocs.io/en/latest/# + issue_tracker: https://github.com/arq5x/bedtools2/issues +references: + doi: 10.1093/bioinformatics/btq033 +license: MIT +requirements: + commands: [bedtools] +authors: + - __merge__: /src/_authors/theodoro_gasperin.yaml + roles: [ author, maintainer ] + +argument_groups: + - name: Inputs + arguments: + - name: --input + alternatives: -i + type: file + description: Input BAM file to be converted to FASTQ. + required: true + + - name: Outputs + arguments: + - name: --fastq + alternatives: -fq + direction: output + type: file + description: Output FASTQ file. + required: true + + - name: --fastq2 + alternatives: -fq2 + type: file + direction: output + description: | + FASTQ for second end. Used if BAM contains paired-end data. + BAM should be sorted by query name is creating paired FASTQ. + + - name: Options + arguments: + - name: --tags + type: boolean_true + description: | + Create FASTQ based on the mate info in the BAM R2 and Q2 tags. + +resources: + - type: bash_script + path: script.sh + +test_resources: + - type: bash_script + path: test.sh + - path: test_data + +engines: + - type: docker + image: debian:stable-slim + setup: + - type: apt + packages: [bedtools, procps] + - type: docker + run: | + echo "bedtools: \"$(bedtools --version | sed -n 's/^bedtools //p')\"" > /var/software_versions.txt + +runners: + - type: executable + - type: nextflow \ No newline at end of file diff --git a/src/bedtools/bedtools_bamtofastq/help.txt b/src/bedtools/bedtools_bamtofastq/help.txt new file mode 100644 index 00000000..ed2b7468 --- /dev/null +++ b/src/bedtools/bedtools_bamtofastq/help.txt @@ -0,0 +1,25 @@ +```bash +bedtools bamtofastq +``` + +Tool: bedtools bamtofastq (aka bamToFastq) +Version: v2.30.0 +Summary: Convert BAM alignments to FASTQ files. + +Usage: bamToFastq [OPTIONS] -i -fq + +Options: + -fq2 FASTQ for second end. Used if BAM contains paired-end data. + BAM should be sorted by query name is creating paired FASTQ. + + -tags Create FASTQ based on the mate info + in the BAM R2 and Q2 tags. + +Tips: + If you want to create a single, interleaved FASTQ file + for paired-end data, you can just write both to /dev/stdout: + + bedtools bamtofastq -i x.bam -fq /dev/stdout -fq2 /dev/stdout > x.ilv.fq + + Also, the samtools fastq command has more fucntionality and is a useful alternative. + diff --git a/src/bedtools/bedtools_bamtofastq/script.sh b/src/bedtools/bedtools_bamtofastq/script.sh new file mode 100644 index 00000000..4b32f2d7 --- /dev/null +++ b/src/bedtools/bedtools_bamtofastq/script.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +## VIASH START +## VIASH END + +# Exit on error +set -eo pipefail + +# Unset parameters +[[ "$par_tags" == "false" ]] && unset par_tags + +# Execute bedtools bamtofastq with the provided arguments +bedtools bamtofastq \ + ${par_tags:+-tags} \ + ${par_fastq2:+-fq2 "$par_fastq2"} \ + -i "$par_input" \ + -fq "$par_fastq" + + diff --git a/src/bedtools/bedtools_bamtofastq/test.sh b/src/bedtools/bedtools_bamtofastq/test.sh new file mode 100644 index 00000000..6d913d85 --- /dev/null +++ b/src/bedtools/bedtools_bamtofastq/test.sh @@ -0,0 +1,84 @@ +#!/bin/bash + +# exit on error +set -eo pipefail + +test_data="$meta_resources_dir/test_data" + +############################################# +# helper functions +assert_file_exists() { + [ -f "$1" ] || { echo "File '$1' does not exist" && exit 1; } +} +assert_file_not_empty() { + [ -s "$1" ] || { echo "File '$1' is empty but shouldn't be" && exit 1; } +} +assert_file_contains() { + grep -q "$2" "$1" || { echo "File '$1' does not contain '$2'" && exit 1; } +} +assert_identical_content() { + diff -a "$2" "$1" \ + || (echo "Files are not identical!" && exit 1) +} +############################################# + +# Test 1: normal conversion +mkdir test1 +cd test1 + +echo "> Run bedtools bamtofastq on BAM file" +"$meta_executable" \ + --input "$test_data/example.bam" \ + --fastq "output.fastq" + +# checks +assert_file_exists "output.fastq" +assert_file_not_empty "output.fastq" +assert_identical_content "output.fastq" "$test_data/expected.fastq" +echo "- test1 succeeded -" + +cd .. + +# Test 2: with tags +mkdir test2 +cd test2 + +echo "> Run bedtools bamtofastq on BAM file with tags" +"$meta_executable" \ + --input "$test_data/example.bam" \ + --fastq "output.fastq" \ + --tags + +# checks +assert_file_exists "output.fastq" +assert_file_not_empty "output.fastq" +assert_identical_content "output.fastq" "$test_data/expected.fastq" +echo "- test2 succeeded -" + +cd .. + +# Test 3: with option fq2 +mkdir test3 +cd test3 + +echo "> Run bedtools bamtofastq on BAM file with output_fq2" +"$meta_executable" \ + --input "$test_data/example.bam" \ + --fastq "output1.fastq" \ + --fastq2 "output2.fastq" + +# checks +assert_file_exists "output1.fastq" +assert_file_not_empty "output1.fastq" +assert_identical_content "output1.fastq" "$test_data/expected_1.fastq" +assert_file_exists "output2.fastq" +assert_file_not_empty "output2.fastq" +assert_identical_content "output2.fastq" "$test_data/expected_2.fastq" +echo "- test3 succeeded -" + +cd .. + +echo "All tests succeeded" +exit 0 + + diff --git a/src/bedtools/bedtools_bamtofastq/test_data/example.bam b/src/bedtools/bedtools_bamtofastq/test_data/example.bam new file mode 100644 index 00000000..ffc075ab Binary files /dev/null and b/src/bedtools/bedtools_bamtofastq/test_data/example.bam differ diff --git a/src/bedtools/bedtools_bamtofastq/test_data/example.sam b/src/bedtools/bedtools_bamtofastq/test_data/example.sam new file mode 100644 index 00000000..4afb0aef --- /dev/null +++ b/src/bedtools/bedtools_bamtofastq/test_data/example.sam @@ -0,0 +1,3 @@ +@SQ SN:chr2:172936693-172938111 LN:1418 +my_read 99 chr2:172936693-172938111 129 60 100M = 429 400 CTAACTAGCCTGGGAAAAAAGGATAGTGTCTCTCTGTTCTTTCATAGGAAATGTTGAATCAGACCCCTACTGGGAAAAGAAATTTAATGCATATCTCACT * XT:A:U NM:i:0 SM:i:37 AM:i:37 X0:i:1 X1:i:0 XM:i:0 XO:i:0 XG:i:0 MD:Z:100 +my_read 147 chr2:172936693-172938111 429 60 100M = 129 -400 TCGAGCTCTGCATTCATGGCTGTGTCTAAAGGGCATGTCAGCCTTTGATTCTCTCTGAGAGGTAATTATCCTTTTCCTGTCACGGAACAACAAATGATAG * XT:A:U NM:i:0 SM:i:37 AM:i:37 X0:i:1 X1:i:0 XM:i:0 XO:i:0 XG:i:0 MD:Z:100 diff --git a/src/bedtools/bedtools_bamtofastq/test_data/expected.fastq b/src/bedtools/bedtools_bamtofastq/test_data/expected.fastq new file mode 100644 index 00000000..358331d4 --- /dev/null +++ b/src/bedtools/bedtools_bamtofastq/test_data/expected.fastq @@ -0,0 +1,16 @@ +@my_read +CTAACTAGCCTGGGAAAAAAGGATAGTGTCTCTCTGTTCTTTCATAGGAAATGTTGAATCAGACCCCTACTGGGAAAAGAAATTTAATGCATATCTCACT ++ +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@my_read +CTAACTAGCCTGGGAAAAAAGGATAGTGTCTCTCTGTTCTTTCATAGGAAATGTTGAATCAGACCCCTACTGGGAAAAGAAATTTAATGCATATCTCACT ++ +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@my_read +CTATCATTTGTTGTTCCGTGACAGGAAAAGGATAATTACCTCTCAGAGAGAATCAAAGGCTGACATGCCCTTTAGACACAGCCATGAATGCAGAGCTCGA ++ +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@my_read +CTATCATTTGTTGTTCCGTGACAGGAAAAGGATAATTACCTCTCAGAGAGAATCAAAGGCTGACATGCCCTTTAGACACAGCCATGAATGCAGAGCTCGA ++ +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! diff --git a/src/bedtools/bedtools_bamtofastq/test_data/expected_1.fastq b/src/bedtools/bedtools_bamtofastq/test_data/expected_1.fastq new file mode 100644 index 00000000..c5dfe571 --- /dev/null +++ b/src/bedtools/bedtools_bamtofastq/test_data/expected_1.fastq @@ -0,0 +1,4 @@ +@my_read/1 +CTAACTAGCCTGGGAAAAAAGGATAGTGTCTCTCTGTTCTTTCATAGGAAATGTTGAATCAGACCCCTACTGGGAAAAGAAATTTAATGCATATCTCACT ++ +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! diff --git a/src/bedtools/bedtools_bamtofastq/test_data/expected_2.fastq b/src/bedtools/bedtools_bamtofastq/test_data/expected_2.fastq new file mode 100644 index 00000000..50d1bd62 --- /dev/null +++ b/src/bedtools/bedtools_bamtofastq/test_data/expected_2.fastq @@ -0,0 +1,4 @@ +@my_read/2 +CTATCATTTGTTGTTCCGTGACAGGAAAAGGATAATTACCTCTCAGAGAGAATCAAAGGCTGACATGCCCTTTAGACACAGCCATGAATGCAGAGCTCGA ++ +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! diff --git a/src/bedtools/bedtools_bamtofastq/test_data/script.sh b/src/bedtools/bedtools_bamtofastq/test_data/script.sh new file mode 100755 index 00000000..df595510 --- /dev/null +++ b/src/bedtools/bedtools_bamtofastq/test_data/script.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +# create sam file +printf "@SQ\tSN:chr2:172936693-172938111\tLN:1418\n" > example.sam +printf "my_read\t99\tchr2:172936693-172938111\t129\t60\t100M\t=\t429\t400\tCTAACTAGCCTGGGAAAAAAGGATAGTGTCTCTCTGTTCTTTCATAGGAAATGTTGAATCAGACCCCTACTGGGAAAAGAAATTTAATGCATATCTCACT\t*\tXT:A:U\tNM:i:0\tSM:i:37\tAM:i:37\tX0:i:1\tX1:i:0\tXM:i:0\tXO:i:0\tXG:i:0\tMD:Z:100\n" >> example.sam +printf "my_read\t147\tchr2:172936693-172938111\t429\t60\t100M\t=\t129\t-400\tTCGAGCTCTGCATTCATGGCTGTGTCTAAAGGGCATGTCAGCCTTTGATTCTCTCTGAGAGGTAATTATCCTTTTCCTGTCACGGAACAACAAATGATAG\t*\tXT:A:U\tNM:i:0\tSM:i:37\tAM:i:37\tX0:i:1\tX1:i:0\tXM:i:0\tXO:i:0\tXG:i:0\tMD:Z:100\n" >> example.sam + +# create bam file +# samtools view -b example.sam > example.bam + +# create fastq files +# bedtools bamtofastq -i example.bam -fq expected.fastq +# bedtools bamtofastq -i example.bam -fq expected_1.fastq -fq2 expected_2.fastq diff --git a/src/bedtools/bedtools_bedtobam/config.vsh.yaml b/src/bedtools/bedtools_bedtobam/config.vsh.yaml new file mode 100644 index 00000000..bd3c48f5 --- /dev/null +++ b/src/bedtools/bedtools_bedtobam/config.vsh.yaml @@ -0,0 +1,91 @@ +name: bedtools_bedtobam +namespace: bedtools +description: Converts feature records (bed/gff/vcf) to BAM format. +keywords: [Converts, BED, GFF, VCF, BAM] +links: + documentation: https://bedtools.readthedocs.io/en/latest/content/tools/bedtobam.html + repository: https://github.com/arq5x/bedtools2 + homepage: https://bedtools.readthedocs.io/en/latest/# + issue_tracker: https://github.com/arq5x/bedtools2/issues +references: + doi: 10.1093/bioinformatics/btq033 +license: MIT +requirements: + commands: [bedtools] +authors: + - __merge__: /src/_authors/theodoro_gasperin.yaml + roles: [ author, maintainer ] + +argument_groups: + - name: Inputs + arguments: + - name: --input + alternatives: -i + type: file + description: Input file (bed/gff/vcf). + required: true + + - name: --genome + alternatives: -g + type: file + description: | + Input genome file. + NOTE: This is not a fasta file. This is a two-column tab-delimited file + where the first column is the chromosome name and the second their sizes. + required: true + + - name: Outputs + arguments: + - name: --output + alternatives: -o + type: file + direction: output + description: Output BAM file to be written. + + - name: Options + arguments: + - name: --map_quality + alternatives: -mapq + type: integer + description: | + Set the mappinq quality for the BAM records. + min: 0 + max: 255 + default: 255 + + - name: --bed12 + type: boolean_true + description: | + The BED file is in BED12 format. The BAM CIGAR + string will reflect BED "blocks". + + - name: --uncompress_bam + alternatives: -ubam + type: boolean_true + description: | + Write uncompressed BAM output. Default writes compressed BAM. + +resources: + - type: bash_script + path: script.sh + +test_resources: + - type: bash_script + path: test.sh + +engines: + - type: docker + image: debian:stable-slim + setup: + - type: apt + packages: [bedtools, procps] + - type: docker + run: | + echo "bedtools: \"$(bedtools --version | sed -n 's/^bedtools //p')\"" > /var/software_versions.txt + test_setup: + - type: apt + packages: [samtools] + +runners: + - type: executable + - type: nextflow \ No newline at end of file diff --git a/src/bedtools/bedtools_bedtobam/help.txt b/src/bedtools/bedtools_bedtobam/help.txt new file mode 100644 index 00000000..c9fa1c6f --- /dev/null +++ b/src/bedtools/bedtools_bedtobam/help.txt @@ -0,0 +1,21 @@ +```bash +bedtools bedtobam +``` + +Tool: bedtools bedtobam (aka bedToBam) +Version: v2.30.0 +Summary: Converts feature records to BAM format. + +Usage: bedtools bedtobam [OPTIONS] -i -g + +Options: + -mapq Set the mappinq quality for the BAM records. + (INT) Default: 255 + + -bed12 The BED file is in BED12 format. The BAM CIGAR + string will reflect BED "blocks". + + -ubam Write uncompressed BAM output. Default writes compressed BAM. + +Notes: + (1) BED files must be at least BED4 to create BAM (needs name field). diff --git a/src/bedtools/bedtools_bedtobam/script.sh b/src/bedtools/bedtools_bedtobam/script.sh new file mode 100644 index 00000000..ac96ae20 --- /dev/null +++ b/src/bedtools/bedtools_bedtobam/script.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +## VIASH START +## VIASH END + +set -eo pipefail + +# Unset parameters +[[ "$par_bed12" == "false" ]] && unset par_bed12 +[[ "$par_uncompress_bam" == "false" ]] && unset par_uncompress_bam + +# Execute bedtools bed to bam +bedtools bedtobam \ + ${par_bed12:+-bed12} \ + ${par_uncompress_bam:+-ubam} \ + ${par_map_quality:+-mapq "$par_map_quality"} \ + -i "$par_input" \ + -g "$par_genome" \ + > "$par_output" diff --git a/src/bedtools/bedtools_bedtobam/test.sh b/src/bedtools/bedtools_bedtobam/test.sh new file mode 100644 index 00000000..14d04241 --- /dev/null +++ b/src/bedtools/bedtools_bedtobam/test.sh @@ -0,0 +1,188 @@ +#!/bin/bash + +# exit on error +set -eo pipefail + +############################################# +# helper functions +assert_file_exists() { + [ -f "$1" ] || { echo "File '$1' does not exist" && exit 1; } +} +assert_file_not_empty() { + [ -s "$1" ] || { echo "File '$1' is empty but shouldn't be" && exit 1; } +} +assert_file_contains() { + grep -q "$2" "$1" || { echo "File '$1' does not contain '$2'" && exit 1; } +} +assert_identical_content() { + diff -a "$2" "$1" \ + || (echo "Files are not identical!" && exit 1) +} +############################################# + +# Create directories for tests +echo "Creating Test Data..." +TMPDIR=$(mktemp -d "$meta_temp_dir/XXXXXX") +function clean_up { + [[ -d "$TMPDIR" ]] && rm -r "$TMPDIR" +} +trap clean_up EXIT + +# Create and populate input files +printf "chr1\t248956422\nchr3\t242193529\nchr2\t198295559\n" > "$TMPDIR/genome.txt" +printf "chr2:172936693-172938111\t128\t228\tmy_read/1\t37\t+\nchr2:172936693-172938111\t428\t528\tmy_read/2\t37\t-\n" > "$TMPDIR/example.bed" +printf "chr2:172936693-172938111\t128\t228\tmy_read/1\t60\t+\t128\t228\t255,0,0\t1\t100\t0\nchr2:172936693-172938111\t428\t528\tmy_read/2\t60\t-\t428\t528\t255,0,0\t1\t100\t0\n" > "$TMPDIR/example.bed12" +# Create and populate example.gff file +printf "##gff-version 3\n" > "$TMPDIR/example.gff" +printf "chr1\t.\tgene\t1000\t2000\t.\t+\t.\tID=gene1;Name=Gene1\n" >> "$TMPDIR/example.gff" +printf "chr3\t.\tmRNA\t1000\t2000\t.\t+\t.\tID=transcript1;Parent=gene1\n" >> "$TMPDIR/example.gff" +printf "chr1\t.\texon\t1000\t1200\t.\t+\t.\tID=exon1;Parent=transcript1\n" >> "$TMPDIR/example.gff" +printf "chr2\t.\texon\t1500\t1700\t.\t+\t.\tID=exon2;Parent=transcript1\n" >> "$TMPDIR/example.gff" +printf "chr1\t.\tCDS\t1000\t1200\t.\t+\t0\tID=cds1;Parent=transcript1\n" >> "$TMPDIR/example.gff" +printf "chr1\t.\tCDS\t1500\t1700\t.\t+\t2\tID=cds2;Parent=transcript1\n" >> "$TMPDIR/example.gff" + +# Expected output sam files for each test +cat < "$TMPDIR/expected.sam" +@HD VN:1.0 SO:unsorted +@PG ID:BEDTools_bedToBam VN:Vv2.30.0 +@PG ID:samtools PN:samtools PP:BEDTools_bedToBam VN:1.16.1 CL:samtools view -h output.bam +@SQ SN:chr1 AS:../genome.txt LN:248956422 +@SQ SN:chr3 AS:../genome.txt LN:242193529 +@SQ SN:chr2 AS:../genome.txt LN:198295559 +my_read/1 0 chr1 129 255 100M * 0 0 * * +my_read/2 16 chr1 429 255 100M * 0 0 * * +EOF +cat < "$TMPDIR/expected12.sam" +@HD VN:1.0 SO:unsorted +@PG ID:BEDTools_bedToBam VN:Vv2.30.0 +@PG ID:samtools PN:samtools PP:BEDTools_bedToBam VN:1.16.1 CL:samtools view -h output.bam +@SQ SN:chr1 AS:../genome.txt LN:248956422 +@SQ SN:chr3 AS:../genome.txt LN:242193529 +@SQ SN:chr2 AS:../genome.txt LN:198295559 +my_read/1 0 chr1 129 255 100M * 0 0 * * +my_read/2 16 chr1 429 255 100M * 0 0 * * +EOF +cat < "$TMPDIR/expected_mapquality.sam" +@HD VN:1.0 SO:unsorted +@PG ID:BEDTools_bedToBam VN:Vv2.30.0 +@PG ID:samtools PN:samtools PP:BEDTools_bedToBam VN:1.16.1 CL:samtools view -h output.bam +@SQ SN:chr1 AS:../genome.txt LN:248956422 +@SQ SN:chr3 AS:../genome.txt LN:242193529 +@SQ SN:chr2 AS:../genome.txt LN:198295559 +my_read/1 0 chr1 129 10 100M * 0 0 * * +my_read/2 16 chr1 429 10 100M * 0 0 * * +EOF +cat < "$TMPDIR/expected_gff.sam" +@HD VN:1.0 SO:unsorted +@PG ID:BEDTools_bedToBam VN:Vv2.30.0 +@PG ID:samtools PN:samtools PP:BEDTools_bedToBam VN:1.16.1 CL:samtools view -h output.bam +@SQ SN:chr1 AS:../genome.txt LN:248956422 +@SQ SN:chr3 AS:../genome.txt LN:242193529 +@SQ SN:chr2 AS:../genome.txt LN:198295559 +gene 0 chr1 1000 255 1001M * 0 0 * * +mRNA 0 chr3 1000 255 1001M * 0 0 * * +exon 0 chr1 1000 255 201M * 0 0 * * +exon 0 chr2 1500 255 201M * 0 0 * * +CDS 0 chr1 1000 255 201M * 0 0 * * +CDS 0 chr1 1500 255 201M * 0 0 * * +EOF + +# Test 1: Default conversion BED to BAM +mkdir "$TMPDIR/test1" && pushd "$TMPDIR/test1" > /dev/null + +echo "> Run bedtools_bedtobam on BED file" +"$meta_executable" \ + --input "../example.bed" \ + --genome "../genome.txt" \ + --output "output.bam" + +samtools view -h output.bam > output.sam + +# checks +assert_file_exists "output.bam" +assert_file_not_empty "output.bam" +assert_identical_content "output.sam" "../expected.sam" +echo "- test1 succeeded -" + +popd > /dev/null + +# Test 2: BED12 file +mkdir "$TMPDIR/test2" && pushd "$TMPDIR/test2" > /dev/null + +echo "> Run bedtools_bedtobam on BED12 file" +"$meta_executable" \ + --input "../example.bed12" \ + --genome "../genome.txt" \ + --output "output.bam" \ + --bed12 \ + +samtools view -h output.bam > output.sam + +# checks +assert_file_exists "output.bam" +assert_file_not_empty "output.bam" +assert_identical_content "output.sam" "../expected12.sam" +echo "- test2 succeeded -" + +popd > /dev/null + +# Test 3: Uncompressed BAM file +mkdir "$TMPDIR/test3" && pushd "$TMPDIR/test3" > /dev/null + +echo "> Run bedtools_bedtobam on BED file with uncompressed BAM output" +"$meta_executable" \ + --input "../example.bed" \ + --genome "../genome.txt" \ + --output "output.bam" \ + --uncompress_bam + +# checks +assert_file_exists "output.bam" +assert_file_not_empty "output.bam" +# Cannot assert_identical_content because umcompress option does not work on this version of bedtools. + +echo "- test3 succeeded -" + +popd > /dev/null + +# Test 4: Map quality +mkdir "$TMPDIR/test4" && pushd "$TMPDIR/test4" > /dev/null + +echo "> Run bedtools_bedtobam on BED file with map quality" +"$meta_executable" \ + --input "../example.bed" \ + --genome "../genome.txt" \ + --output "output.bam" \ + --map_quality 10 \ + +samtools view -h output.bam > output.sam + +# checks +assert_file_exists "output.bam" +assert_file_not_empty "output.bam" +assert_identical_content "output.sam" "../expected_mapquality.sam" +echo "- test4 succeeded -" + +popd > /dev/null + +# Test 5: gff to bam conversion +mkdir "$TMPDIR/test5" && pushd "$TMPDIR/test5" > /dev/null + +echo "> Run bedtools_bedtobam on GFF file" +"$meta_executable" \ + --input "../example.gff" \ + --genome "../genome.txt" \ + --output "output.bam" + +samtools view -h output.bam > output.sam + +# checks +assert_file_exists "output.bam" +assert_file_not_empty "output.bam" +assert_identical_content "output.sam" "../expected_gff.sam" +echo "- test5 succeeded -" + +popd > /dev/null + +echo "---- All tests succeeded! ----" +exit 0 diff --git a/src/bedtools/bedtools_intersect/script.sh b/src/bedtools/bedtools_intersect/script.sh index 2141859d..3a28ba57 100644 --- a/src/bedtools/bedtools_intersect/script.sh +++ b/src/bedtools/bedtools_intersect/script.sh @@ -3,27 +3,35 @@ ## VIASH START ## VIASH END -[[ "$par_write_a" == "false" ]] && unset par_write_a -[[ "$par_write_b" == "false" ]] && unset par_write_b -[[ "$par_left_outer_join" == "false" ]] && unset par_left_outer_join -[[ "$par_write_overlap" == "false" ]] && unset par_write_overlap -[[ "$par_write_overlap_plus" == "false" ]] && unset par_write_overlap_plus -[[ "$par_report_A_if_no_overlap" == "false" ]] && unset par_report_A_if_no_overlap -[[ "$par_number_of_overlaps_A" == "false" ]] && unset par_number_of_overlaps_A -[[ "$par_report_no_overlaps_A" == "false" ]] && unset par_report_no_overlaps_A -[[ "$par_uncompressed_bam" == "false" ]] && unset par_uncompressed_bam -[[ "$par_same_strand" == "false" ]] && unset par_same_strand -[[ "$par_opposite_strand" == "false" ]] && unset par_opposite_strand -[[ "$par_reciprocal_overlap" == "false" ]] && unset par_reciprocal_overlap -[[ "$par_either_overlap" == "false" ]] && unset par_either_overlap -[[ "$par_split" == "false" ]] && unset par_split -[[ "$par_nonamecheck" == "false" ]] && unset par_nonamecheck -[[ "$par_sorted" == "false" ]] && unset par_sorted -[[ "$par_filenames" == "false" ]] && unset par_filenames -[[ "$par_sortout" == "false" ]] && unset par_sortout -[[ "$par_bed" == "false" ]] && unset par_bed -[[ "$par_header" == "false" ]] && unset par_header -[[ "$par_no_buffer_output" == "false" ]] && unset par_no_buffer_output +unset_if_false=( + par_write_a + par_write_b + par_left_outer_join + par_write_overlap + par_write_overlap_plus + par_report_A_if_no_overlap + par_number_of_overlaps_A + par_report_no_overlaps_A + par_uncompressed_bam + par_same_strand + par_opposite_strand + par_reciprocal_overlap + par_either_overlap + par_split + par_nonamecheck + par_sorted + par_filenames + par_sortout + par_bed + par_no_buffer_output + par_header +) + +for par in ${unset_if_false[@]}; do + test_val="${!par}" + [[ "$test_val" == "false" ]] && unset $par +done + # Create input array IFS=";" read -ra input <<< $par_input_b diff --git a/src/bedtools/bedtools_sort/script.sh b/src/bedtools/bedtools_sort/script.sh index e7f712d7..0d0b9b54 100644 --- a/src/bedtools/bedtools_sort/script.sh +++ b/src/bedtools/bedtools_sort/script.sh @@ -4,13 +4,20 @@ ## VIASH END # Unset parameters -[[ "$par_sizeA" == "false" ]] && unset par_sizeA -[[ "$par_sizeD" == "false" ]] && unset par_sizeD -[[ "$par_chrThenSizeA" == "false" ]] && unset par_chrThenSizeA -[[ "$par_chrThenSizeD" == "false" ]] && unset par_chrThenSizeD -[[ "$par_chrThenScoreA" == "false" ]] && unset par_chrThenScoreA -[[ "$par_chrThenScoreD" == "false" ]] && unset par_chrThenScoreD -[[ "$par_header" == "false" ]] && unset par_header +unset_if_false=( + par_sizeA + par_sizeD + par_chrThenSizeA + par_chrThenSizeD + par_chrThenScoreA + par_chrThenScoreD + par_header +) + +for par in ${unset_if_false[@]}; do + test_val="${!par}" + [[ "$test_val" == "false" ]] && unset $par +done # Execute bedtools sort with the provided arguments bedtools sort \ diff --git a/src/busco/busco_run/script.sh b/src/busco/busco_run/script.sh index a0ef24de..673ccd0b 100644 --- a/src/busco/busco_run/script.sh +++ b/src/busco/busco_run/script.sh @@ -3,18 +3,24 @@ ## VIASH START ## VIASH END +unset_if_false=( + par_tar + par_force + par_quiet + par_restart + par_auto_lineage + par_auto_lineage_euk + par_auto_lineage_prok + par_augustus + par_long + par_scaffold_composition + par_miniprot +) -[[ "$par_tar" == "false" ]] && unset par_tar -[[ "$par_force" == "false" ]] && unset par_force -[[ "$par_quiet" == "false" ]] && unset par_quiet -[[ "$par_restart" == "false" ]] && unset par_restart -[[ "$par_auto_lineage" == "false" ]] && unset par_auto_lineage -[[ "$par_auto_lineage_euk" == "false" ]] && unset par_auto_lineage_euk -[[ "$par_auto_lineage_prok" == "false" ]] && unset par_auto_lineage_prok -[[ "$par_augustus" == "false" ]] && unset par_augustus -[[ "$par_long" == "false" ]] && unset par_long -[[ "$par_scaffold_composition" == "false" ]] && unset par_scaffold_composition -[[ "$par_miniprot" == "false" ]] && unset par_miniprot +for par in ${unset_if_false[@]}; do + test_val="${!par}" + [[ "$test_val" == "false" ]] && unset $par +done tmp_dir=$(mktemp -d -p "$meta_temp_dir" busco_XXXXXXXXX) prefix=$(openssl rand -hex 8) diff --git a/src/fastp/script.sh b/src/fastp/script.sh index 4bb37c87..557f7ac3 100644 --- a/src/fastp/script.sh +++ b/src/fastp/script.sh @@ -4,25 +4,32 @@ ## VIASH END # disable flags -[[ "$par_disable_adapter_trimming" == "false" ]] && unset par_disable_adapter_trimming -[[ "$par_detect_adapter_for_pe" == "false" ]] && unset par_detect_adapter_for_pe -[[ "$par_merge" == "false" ]] && unset par_merge -[[ "$par_include_unmerged" == "false" ]] && unset par_include_unmerged -[[ "$par_interleaved_in" == "false" ]] && unset par_interleaved_in -[[ "$par_fix_mgi_id" == "false" ]] && unset par_fix_mgi_id -[[ "$par_phred64" == "false" ]] && unset par_phred64 -[[ "$par_dont_overwrite" == "false" ]] && unset par_dont_overwrite -[[ "$par_verbose" == "false" ]] && unset par_verbose -[[ "$par_dedup" == "false" ]] && unset par_dedup -[[ "$par_dont_eval_duplication" == "false" ]] && unset par_dont_eval_duplication -[[ "$par_trim_poly_g" == "false" ]] && unset par_trim_poly_g -[[ "$par_disable_trim_poly_g" == "false" ]] && unset par_disable_trim_poly_g -[[ "$par_trim_poly_x" == "false" ]] && unset par_trim_poly_x -[[ "$par_disable_quality_filtering" == "false" ]] && unset par_disable_quality_filtering -[[ "$par_disable_length_filtering" == "false" ]] && unset par_disable_length_filtering -[[ "$par_low_complexity_filter" == "false" ]] && unset par_low_complexity_filter -[[ "$par_umi" == "false" ]] && unset par_umi -[[ "$par_overrepresentation_analysis" == "false" ]] && unset par_overrepresentation_analysis +unset_if_false=( + par_disable_adapter_trimming + par_detect_adapter_for_pe + par_merge + par_include_unmerged + par_interleaved_in + par_fix_mgi_id + par_phred64 + par_dont_overwrite + par_verbose + par_dedup + par_dont_eval_duplication + par_trim_poly_g + par_disable_trim_poly_g + par_trim_poly_x + par_disable_quality_filtering + par_disable_length_filtering + par_low_complexity_filter + par_umi + par_overrepresentation_analysis +) + +for par in ${unset_if_false[@]}; do + test_val="${!par}" + [[ "$test_val" == "false" ]] && unset $par +done # run command fastp \ diff --git a/src/featurecounts/script.sh b/src/featurecounts/script.sh index 2e54feb3..53f8c63f 100644 --- a/src/featurecounts/script.sh +++ b/src/featurecounts/script.sh @@ -19,24 +19,31 @@ par_feature_type=$(echo $par_feature_type | tr ',' ';') par_extra_attributes=$(echo $par_extra_attributes | tr ',' ';') # unset flag variables -[[ "$par_feature_level" == "false" ]] && unset par_feature_level -[[ "$par_overlapping" == "false" ]] && unset par_overlapping -[[ "$par_largest_overlap" == "false" ]] && unset par_largest_overlap -[[ "$par_multi_mapping" == "false" ]] && unset par_multi_mapping -[[ "$par_fraction" == "false" ]] && unset par_fraction -[[ "$par_split_only" == "false" ]] && unset par_split_only -[[ "$par_non_split_only" == "false" ]] && unset par_non_split_only -[[ "$par_primary" == "false" ]] && unset par_primary -[[ "$par_ignore_dup" == "false" ]] && unset par_ignore_dup -[[ "$par_paired" == "false" ]] && unset par_paired -[[ "$par_count_read_pairs" == "false" ]] && unset par_count_read_pairs -[[ "$par_both_aligned" == "false" ]] && unset par_both_aligned -[[ "$par_check_pe_dist" == "false" ]] && unset par_check_pe_dist -[[ "$par_same_strand" == "false" ]] && unset par_same_strand -[[ "$par_donotsort" == "false" ]] && unset par_donotsort -[[ "$par_by_read_group" == "false" ]] && unset par_by_read_group -[[ "$par_long_reads" == "false" ]] && unset par_long_reads -[[ "$par_verbose" == "false" ]] && unset par_verbose +unset_if_false=( + par_feature_level + par_overlapping + par_largest_overlap + par_multi_mapping + par_fraction + par_split_only + par_non_split_only + par_primary + par_ignore_dup + par_paired + par_count_read_pairs + par_both_aligned + par_check_pe_dist + par_same_strand + par_donotsort + par_by_read_group + par_long_reads + par_verbose +) + +for par in ${unset_if_false[@]}; do + test_val="${!par}" + [[ "$test_val" == "false" ]] && unset $par +done IFS=";" read -ra input <<< $par_input diff --git a/src/gffread/script.sh b/src/gffread/script.sh index cd4abf14..fab9e521 100644 --- a/src/gffread/script.sh +++ b/src/gffread/script.sh @@ -4,51 +4,58 @@ ## VIASH END # unset flags -[[ "$par_coding" == "false" ]] && unset par_coding -[[ "$par_strict_range" == "false" ]] && unset par_strict_range -[[ "$par_no_single_exon" == "false" ]] && unset par_no_single_exon -[[ "$par_no_exon_attrs" == "false" ]] && unset par_no_exon_attrs -[[ "$par_nc" == "false" ]] && unset par_nc -[[ "$par_ignore_locus" == "false" ]] && unset par_ignore_locus -[[ "$par_description" == "false" ]] && unset par_description -[[ "$par_sort_alpha" == "false" ]] && unset par_sort_alpha -[[ "$par_keep_genes" == "false" ]] && unset par_keep_genes -[[ "$par_keep_attrs" == "false" ]] && unset par_keep_attrs -[[ "$par_keep_exon_attrs" == "false" ]] && unset par_keep_exon_attrs -[[ "$par_keep_comments" == "false" ]] && unset par_keep_comments -[[ "$par_process_other" == "false" ]] && unset par_process_other -[[ "$par_rm_stop_codons" == "false" ]] && unset par_rm_stop_codons -[[ "$par_adj_cds_start" == "false" ]] && unset par_adj_cds_start -[[ "$par_opposite_strand" == "false" ]] && unset par_opposite_strand -[[ "$par_coding_status" == "false" ]] && unset par_coding_status -[[ "$par_add_hasCDS" == "false" ]] && unset par_add_hasCDS -[[ "$par_adj_stop" == "false" ]] && unset par_adj_stop -[[ "$par_rm_noncanon" == "false" ]] && unset par_rm_noncanon -[[ "$par_complete_cds" == "false" ]] && unset par_complete_cds -[[ "$par_no_pseudo" == "false" ]] && unset par_no_pseudo -[[ "$par_in_bed" == "false" ]] && unset par_in_bed -[[ "$par_in_tlf" == "false" ]] && unset par_in_tlf -[[ "$par_stream" == "false" ]] && unset par_stream -[[ "$par_merge" == "false" ]] && unset par_merge -[[ "$par_rm_redundant" == "false" ]] && unset par_rm_redundant -[[ "$par_no_boundary" == "false" ]] && unset par_no_boundary -[[ "$par_no_overlap" == "false" ]] && unset par_no_overlap -[[ "$par_force_exons" == "false" ]] && unset par_force_exons -[[ "$par_gene2exon" == "false" ]] && unset par_gene2exon -[[ "$par_t_adopt" == "false" ]] && unset par_t_adopt -[[ "$par_decode" == "false" ]] && unset par_decode -[[ "$par_merge_exons" == "false" ]] && unset par_merge_exons -[[ "$par_junctions" == "false" ]] && unset par_junctions -[[ "$par_w_nocds" == "false" ]] && unset par_w_nocds -[[ "$par_tr_cds" == "false" ]] && unset par_tr_cds -[[ "$par_w_coords" == "false" ]] && unset par_w_coords -[[ "$par_stop_dot" == "false" ]] && unset par_stop_dot -[[ "$par_id_version" == "false" ]] && unset par_id_version -[[ "$par_gtf_output" == "false" ]] && unset par_gtf_output -[[ "$par_bed" == "false" ]] && unset par_bed -[[ "$par_tlf" == "false" ]] && unset par_tlf -[[ "$par_expose_dups" == "false" ]] && unset par_expose_dups -[[ "$par_cluster_only" == "false" ]] && unset par_cluster_only +unset_if_false=( + par_coding + par_strict_range + par_no_single_exon + par_no_exon_attrs + par_nc + par_ignore_locus + par_description + par_sort_alpha + par_keep_genes + par_keep_attrs + par_keep_exon_attrs + par_keep_comments + par_process_other + par_rm_stop_codons + par_adj_cds_start + par_opposite_strand + par_coding_status + par_add_hasCDS + par_adj_stop + par_rm_noncanon + par_complete_cds + par_no_pseudo + par_in_bed + par_in_tlf + par_stream + par_merge + par_rm_redundant + par_no_boundary + par_no_overlap + par_force_exons + par_gene2exon + par_t_adopt + par_decode + par_merge_exons + par_junctions + par_w_nocds + par_tr_cds + par_w_coords + par_stop_dot + par_id_version + par_gtf_output + par_bed + par_tlf + par_expose_dups + par_cluster_only +) + +for par in ${unset_if_false[@]}; do + test_val="${!par}" + [[ "$test_val" == "false" ]] && unset $par +done # if par_table is not empty, replace ";" with "," par_table=$(echo "$par_table" | tr ';' ',') diff --git a/src/lofreq/call/script.sh b/src/lofreq/call/script.sh index 863fe986..ca229194 100644 --- a/src/lofreq/call/script.sh +++ b/src/lofreq/call/script.sh @@ -4,21 +4,28 @@ ## VIASH END # Unset all parameters that are set to "false" -[[ "$par_no_baq" == "false" ]] && unset par_no_baq -[[ "$par_no_idaq" == "false" ]] && unset par_no_idaq -[[ "$par_del_baq" == "false" ]] && unset par_del_baq -[[ "$par_no_ext_baq" == "false" ]] && unset par_no_ext_baq -[[ "$par_no_mq" == "false" ]] && unset par_no_mq -[[ "$par_call_indels" == "false" ]] && unset par_call_indels -[[ "$par_only_indels" == "false" ]] && unset par_only_indels -[[ "$par_src_qual" == "false" ]] && unset par_src_qual -[[ "$par_illumina_13" == "false" ]] && unset par_illumina_13 -[[ "$par_use_orphan" == "false" ]] && unset par_use_orphan -[[ "$par_plp_summary_only" == "false" ]] && unset par_plp_summary_only -[[ "$par_no_default_filter" == "false" ]] && unset par_no_default_filter -[[ "$par_force_overwrite" == "false" ]] && unset par_force_overwrite -[[ "$par_verbose" == "false" ]] && unset par_verbose -[[ "$par_debug" == "false" ]] && unset par_debug +unset_if_false=( + par_no_baq + par_no_idaq + par_del_baq + par_no_ext_baq + par_no_mq + par_call_indels + par_only_indels + par_src_qual + par_illumina_13 + par_use_orphan + par_plp_summary_only + par_no_default_filter + par_force_overwrite + par_verbose + par_debug +) + +for par in ${unset_if_false[@]}; do + test_val="${!par}" + [[ "$test_val" == "false" ]] && unset $par +done # Run lofreq call lofreq call \ diff --git a/src/multiqc/script.sh b/src/multiqc/script.sh index ad8c1c0c..5806fa1d 100755 --- a/src/multiqc/script.sh +++ b/src/multiqc/script.sh @@ -1,26 +1,32 @@ #!/bin/bash # disable flags -[[ "$par_ignore_symlinks" == "false" ]] && unset par_ignore_symlinks -[[ "$par_dirs" == "false" ]] && unset par_dirs -[[ "$par_full_names" == "false" ]] && unset par_full_names -[[ "$par_fn_as_s_name" == "false" ]] && unset par_fn_as_s_name -[[ "$par_profile_runtime" == "false" ]] && unset par_profile_runtime -[[ "$par_verbose" == "false" ]] && unset par_verbose -[[ "$par_quiet" == "false" ]] && unset par_quiet -[[ "$par_strict" == "false" ]] && unset par_strict -[[ "$par_development" == "false" ]] && unset par_development -[[ "$par_require_logs" == "false" ]] && unset par_require_logs -[[ "$par_no_megaqc_upload" == "false" ]] && unset par_no_megaqc_upload -[[ "$par_no_ansi" == "false" ]] && unset par_no_ansi -[[ "$par_flat" == "false" ]] && unset par_flat -[[ "$par_interactive" == "false" ]] && unset par_interactive -[[ "$par_static_plot_export" == "false" ]] && unset par_static_plot_export -[[ "$par_data_dir" == "false" ]] && unset par_data_dir -[[ "$par_no_data_dir" == "false" ]] && unset par_no_data_dir -[[ "$par_zip_data_dir" == "false" ]] && unset par_zip_data_dir -[[ "$par_pdf" == "false" ]] && unset par_pdf +unset_if_false=( + par_ignore_symlinks + par_dirs + par_full_names + par_fn_as_s_name + par_profile_runtime + par_verbose + par_quiet + par_strict + par_development + par_require_logs + par_no_megaqc_upload + par_no_ansi + par_flat + par_interactive + par_static_plot_export + par_data_dir + par_no_data_dir + par_zip_data_dir + par_pdf +) +for par in ${unset_if_false[@]}; do + test_val="${!par}" + [[ "$test_val" == "false" ]] && unset $par +done # handle inputs out_dir=$(dirname "$par_output_report") diff --git a/src/salmon/salmon_index/script.sh b/src/salmon/salmon_index/script.sh index c2b9e7a0..5b1c4d76 100644 --- a/src/salmon/salmon_index/script.sh +++ b/src/salmon/salmon_index/script.sh @@ -5,12 +5,19 @@ set -e ## VIASH START ## VIASH END -[[ "$par_gencode" == "false" ]] && unset par_gencode -[[ "$par_features" == "false" ]] && unset par_features -[[ "$par_keep_duplicates" == "false" ]] && unset par_keep_duplicates -[[ "$par_keep_fixed_fasta" == "false" ]] && unset par_keep_fixed_fasta -[[ "$par_sparse" == "false" ]] && unset par_sparse -[[ "$par_no_clip" == "false" ]] && unset par_no_clip +unset_if_false=( + par_gencode + par_features + par_keep_duplicates + par_keep_fixed_fasta + par_sparse + par_no_clip +) + +for par in ${unset_if_false[@]}; do + test_val="${!par}" + [[ "$test_val" == "false" ]] && unset $par +done tmp_dir=$(mktemp -d -p "$meta_temp_dir" "${meta_functionality_name}_XXXXXX") mkdir -p "$tmp_dir/temp" diff --git a/src/salmon/salmon_quant/script.sh b/src/salmon/salmon_quant/script.sh index 4c9f69d5..47cba1b9 100644 --- a/src/salmon/salmon_quant/script.sh +++ b/src/salmon/salmon_quant/script.sh @@ -4,49 +4,55 @@ set -e ## VIASH START ## VIASH END +unset_if_false=( + par_discard_orphans + par_ont + par_seq_bias + par_gc_bias + par_pos_bias + par_meta + par_discard_orphans_quasi + par_disable_chaining_heuristic + par_allow_dovetail + par_recover_orphans + par_mimicBT2 + par_mimic_strictBT2 + par_softclip + par_softclip_overhangs + par_full_length_alignment + par_hard_filter + par_write_mappings + par_write_qualities + par_alternative_init_mode + par_skip_quant + par_dump_eq + par_dump_eq_weights + par_reduce_GC_memory + par_init_uniform + par_no_length_correction + par_no_effective_length_correction + par_no_single_frag_prob + par_no_frag_length_dist + par_no_bias_length_threshold + par_useEM + par_useVBOpt + par_no_Gamma_draw + par_bootstrap_reproject + par_quiet + par_per_transcript_prior + par_per_nucleotide_prior + par_write_orphan_links + par_write_unmapped_names + par_no_error_model + par_sample_out + par_sample_unaligned + par_gencode +) -[[ "$par_discard_orphans" == "false" ]] && unset par_discard_orphans -[[ "$par_ont" == "false" ]] && unset par_ont -[[ "$par_seq_bias" == "false" ]] && unset par_seq_bias -[[ "$par_gc_bias" == "false" ]] && unset par_gc_bias -[[ "$par_pos_bias" == "false" ]] && unset par_pos_bias -[[ "$par_meta" == "false" ]] && unset par_meta -[[ "$par_discard_orphans_quasi" == "false" ]] && unset par_discard_orphans_quasi -[[ "$par_disable_chaining_heuristic" == "false" ]] && unset par_disable_chaining_heuristic -[[ "$par_allow_dovetail" == "false" ]] && unset par_allow_dovetail -[[ "$par_recover_orphans" == "false" ]] && unset par_recover_orphans -[[ "$par_mimicBT2" == "false" ]] && unset par_mimicBT2 -[[ "$par_mimic_strictBT2" == "false" ]] && unset par_mimic_strictBT2 -[[ "$par_softclip" == "false" ]] && unset par_softclip -[[ "$par_softclip_overhangs" == "false" ]] && unset par_softclip_overhangs -[[ "$par_full_length_alignment" == "false" ]] && unset par_full_length_alignment -[[ "$par_hard_filter" == "false" ]] && unset par_hard_filter -[[ "$par_write_mappings" == "false" ]] && unset par_write_mappings -[[ "$par_write_qualities" == "false" ]] && unset par_write_qualities -[[ "$par_alternative_init_mode" == "false" ]] && unset par_alternative_init_mode -[[ "$par_skip_quant" == "false" ]] && unset par_skip_quant -[[ "$par_dump_eq" == "false" ]] && unset par_dump_eq -[[ "$par_dump_eq_weights" == "false" ]] && unset par_dump_eq_weights -[[ "$par_reduce_GC_memory" == "false" ]] && unset par_reduce_GC_memory -[[ "$par_init_uniform" == "false" ]] && unset par_init_uniform -[[ "$par_no_length_correction" == "false" ]] && unset par_no_length_correction -[[ "$par_no_effective_length_correction" == "false" ]] && unset par_no_effective_length_correction -[[ "$par_no_single_frag_prob" == "false" ]] && unset par_no_single_frag_prob -[[ "$par_no_frag_length_dist" == "false" ]] && unset par_no_frag_length_dist -[[ "$par_no_bias_length_threshold" == "false" ]] && unset par_no_bias_length_threshold -[[ "$par_useEM" == "false" ]] && unset par_useEM -[[ "$par_useVBOpt" == "false" ]] && unset par_useVBOpt -[[ "$par_no_Gamma_draw" == "false" ]] && unset par_no_Gamma_draw -[[ "$par_bootstrap_reproject" == "false" ]] && unset par_bootstrap_reproject -[[ "$par_quiet" == "false" ]] && unset par_quiet -[[ "$par_per_transcript_prior" == "false" ]] && unset par_per_transcript_prior -[[ "$par_per_nucleotide_prior" == "false" ]] && unset par_per_nucleotide_prior -[[ "$par_write_orphan_links" == "false" ]] && unset par_write_orphan_links -[[ "$par_write_unmapped_names" == "false" ]] && unset par_write_unmapped_names -[[ "$par_no_error_model" == "false" ]] && unset par_no_error_model -[[ "$par_sample_out" == "false" ]] && unset par_sample_out -[[ "$par_sample_unaligned" == "false" ]] && unset par_sample_unaligned -[[ "$par_gencode" == "false" ]] && unset par_gencode +for par in ${unset_if_false[@]}; do + test_val="${!par}" + [[ "$test_val" == "false" ]] && unset $par +done IFS=";" read -ra unmated_reads <<< $par_unmated_reads IFS=";" read -ra mates1 <<< $par_mates1 diff --git a/src/samtools/samtools_fastq/script.sh b/src/samtools/samtools_fastq/script.sh index 0cad9cfe..e05da9b0 100644 --- a/src/samtools/samtools_fastq/script.sh +++ b/src/samtools/samtools_fastq/script.sh @@ -5,11 +5,18 @@ set -e -[[ "$par_no_suffix" == "false" ]] && unset par_no_suffix -[[ "$par_suffix" == "false" ]] && unset par_suffix -[[ "$par_use_oq" == "false" ]] && unset par_use_oq -[[ "$par_copy_tags" == "false" ]] && unset par_copy_tags -[[ "$par_casava" == "false" ]] && unset par_casava +unset_if_false=( + par_no_suffix + par_suffix + par_use_oq + par_copy_tags + par_casava +) + +for par in ${unset_if_false[@]}; do + test_val="${!par}" + [[ "$test_val" == "false" ]] && unset $par +done if [[ "$meta_name" == "samtools_fasta" ]]; then subcommand=fasta diff --git a/src/samtools/samtools_sort/script.sh b/src/samtools/samtools_sort/script.sh index 94836c18..a8b3ce0f 100644 --- a/src/samtools/samtools_sort/script.sh +++ b/src/samtools/samtools_sort/script.sh @@ -5,15 +5,22 @@ set -e -[[ "$par_uncompressed" == "false" ]] && unset par_uncompressed -[[ "$par_minimiser" == "false" ]] && unset par_minimiser -[[ "$par_not_reverse" == "false" ]] && unset par_not_reverse -[[ "$par_homopolymers" == "false" ]] && unset par_homopolymers -[[ "$par_natural_sort" == "false" ]] && unset par_natural_sort -[[ "$par_ascii_sort" == "false" ]] && unset par_ascii_sort -[[ "$par_template_coordinate" == "false" ]] && unset par_template_coordinate -[[ "$par_write_index" == "false" ]] && unset par_write_index -[[ "$par_no_PG" == "false" ]] && unset par_no_PG +unset_if_false=( + par_uncompressed + par_minimiser + par_not_reverse + par_homopolymers + par_natural_sort + par_ascii_sort + par_template_coordinate + par_write_index + par_no_PG +) + +for par in ${unset_if_false[@]}; do + test_val="${!par}" + [[ "$test_val" == "false" ]] && unset $par +done samtools sort \ diff --git a/src/samtools/samtools_view/script.sh b/src/samtools/samtools_view/script.sh index c3911b48..7608844b 100644 --- a/src/samtools/samtools_view/script.sh +++ b/src/samtools/samtools_view/script.sh @@ -5,21 +5,29 @@ set -e -[[ "$par_bam" == "false" ]] && unset par_bam -[[ "$par_cram" == "false" ]] && unset par_cram -[[ "$par_fast" == "false" ]] && unset par_fast -[[ "$par_uncompressed" == "false" ]] && unset par_uncompressed -[[ "$par_with_header" == "false" ]] && unset par_with_header -[[ "$par_header_only" == "false" ]] && unset par_header_only -[[ "$par_no_header" == "false" ]] && unset par_no_header -[[ "$par_count" == "false" ]] && unset par_count -[[ "$par_unmap" == "false" ]] && unset par_unmap -[[ "$par_use_index" == "false" ]] && unset par_use_index -[[ "$par_fetch_pairs" == "false" ]] && unset par_fetch_pairs -[[ "$par_customized_index" == "false" ]] && unset par_customized_index -[[ "$par_no_PG" == "false" ]] && unset par_no_PG -[[ "$par_write_index" == "false" ]] && unset par_write_index -[[ "$par_remove_B" == "false" ]] && unset par_remove_B +unset_if_false=( + par_bam + par_cram + par_fast + par_uncompressed + par_with_header + par_header_only + par_no_header + par_count + par_unmap + par_use_index + par_fetch_pairs + par_customized_index + par_no_PG + par_write_index + par_remove_B +) + +for par in ${unset_if_false[@]}; do + test_val="${!par}" + [[ "$test_val" == "false" ]] && unset $par +done + samtools view \ ${par_bam:+-b} \ diff --git a/src/umi_tools/umi_tools_dedup/script.sh b/src/umi_tools/umi_tools_dedup/script.sh index d57a5e76..3f3bdc89 100644 --- a/src/umi_tools/umi_tools_dedup/script.sh +++ b/src/umi_tools/umi_tools_dedup/script.sh @@ -7,19 +7,26 @@ set -e test_dir="${metal_executable}/test_data" -[[ "$par_paired" == "false" ]] && unset par_paired -[[ "$par_in_sam" == "false" ]] && unset par_in_sam -[[ "$par_out_sam" == "false" ]] && unset par_out_sam -[[ "$par_spliced_is_unique" == "false" ]] && unset par_spliced_is_unique -[[ "$par_per_gene" == "false" ]] && unset par_per_gene -[[ "$par_per_contig" == "false" ]] && unset par_per_contig -[[ "$par_per_cell" == "false" ]] && unset par_per_cell -[[ "$par_no_sort_output" == "false" ]] && unset par_no_sort_output -[[ "$par_buffer_whole_contig" == "false" ]] && unset par_buffer_whole_contig -[[ "$par_ignore_umi" == "false" ]] && unset par_ignore_umi -[[ "$par_subset" == "false" ]] && unset par_subset -[[ "$par_log2stderr" == "false" ]] && unset par_log2stderr -[[ "$par_read_length" == "false" ]] && unset par_read_length +unset_if_false=( + par_paired + par_in_sam + par_out_sam + par_spliced_is_unique + par_per_gene + par_per_contig + par_per_cell + par_no_sort_output + par_buffer_whole_contig + par_ignore_umi + par_subset + par_log2stderr + par_read_length +) + +for par in ${unset_if_false[@]}; do + test_val="${!par}" + [[ "$test_val" == "false" ]] && unset $par +done umi_tools dedup \ --stdin "$par_input" \ diff --git a/src/umi_tools/umi_tools_extract/script.sh b/src/umi_tools/umi_tools_extract/script.sh index 5e41865d..4514860e 100644 --- a/src/umi_tools/umi_tools_extract/script.sh +++ b/src/umi_tools/umi_tools_extract/script.sh @@ -5,14 +5,19 @@ set -exo pipefail -test_dir="${metal_executable}/test_data" +unset_if_false=( + par_error_correct_cell + par_reconcile_pairs + par_three_prime + par_ignore_read_pair_suffixes + par_timeit_header + par_log2stderr +) -[[ "$par_error_correct_cell" == "false" ]] && unset par_error_correct_cell -[[ "$par_reconcile_pairs" == "false" ]] && unset par_reconcile_pairs -[[ "$par_three_prime" == "false" ]] && unset par_three_prime -[[ "$par_ignore_read_pair_suffixes" == "false" ]] && unset par_ignore_read_pair_suffixes -[[ "$par_timeit_header" == "false" ]] && unset par_timeit_header -[[ "$par_log2stderr" == "false" ]] && unset par_log2stderr +for par in ${unset_if_false[@]}; do + test_val="${!par}" + [[ "$test_val" == "false" ]] && unset $par +done # Check if we have the correct number of input files and patterns for paired-end or single-end reads diff --git a/target/executable/agat/agat_convert_bed2gff/.config.vsh.yaml b/target/executable/agat/agat_convert_bed2gff/.config.vsh.yaml index c762fc7a..1c9be457 100644 --- a/target/executable/agat/agat_convert_bed2gff/.config.vsh.yaml +++ b/target/executable/agat/agat_convert_bed2gff/.config.vsh.yaml @@ -235,7 +235,7 @@ build_info: output: "target/executable/agat/agat_convert_bed2gff" executable: "target/executable/agat/agat_convert_bed2gff/agat_convert_bed2gff" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/agat/agat_convert_bed2gff/agat_convert_bed2gff b/target/executable/agat/agat_convert_bed2gff/agat_convert_bed2gff index ff88139d..ecf1708e 100755 --- a/target/executable/agat/agat_convert_bed2gff/agat_convert_bed2gff +++ b/target/executable/agat/agat_convert_bed2gff/agat_convert_bed2gff @@ -514,9 +514,9 @@ RUN agat --version | sed 's/AGAT\s\(.*\)/agat: "\1"/' > /var/software_versions.t LABEL org.opencontainers.image.authors="Leïla Paquay" LABEL org.opencontainers.image.description="Companion container for running component agat agat_convert_bed2gff" -LABEL org.opencontainers.image.created="2024-07-31T19:27:40Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:52Z" LABEL org.opencontainers.image.source="https://github.com/NBISweden/AGAT" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER diff --git a/target/executable/agat/agat_convert_embl2gff/.config.vsh.yaml b/target/executable/agat/agat_convert_embl2gff/.config.vsh.yaml new file mode 100644 index 00000000..e79ad73e --- /dev/null +++ b/target/executable/agat/agat_convert_embl2gff/.config.vsh.yaml @@ -0,0 +1,251 @@ +name: "agat_convert_embl2gff" +namespace: "agat" +version: "main" +authors: +- name: "Leïla Paquay" + roles: + - "author" + - "maintainer" + info: + links: + email: "leila@data-intuitive.com" + github: "Leila011" + linkedin: "leilapaquay" + organizations: + - name: "Data Intuitive" + href: "https://www.data-intuitive.com" + role: "Software Developer" +argument_groups: +- name: "Inputs" + arguments: + - type: "file" + name: "--embl" + description: "Input EMBL file that will be read." + info: null + example: + - "input.embl" + must_exist: true + create_parent: true + required: true + direction: "input" + multiple: false + multiple_sep: ";" +- name: "Outputs" + arguments: + - type: "file" + name: "--output" + alternatives: + - "-o" + - "--out" + - "--outfile" + - "--gff" + description: "Output GFF file. If no output file is specified, the output will\ + \ be written to STDOUT." + info: null + example: + - "output.gff" + must_exist: true + create_parent: true + required: false + direction: "output" + multiple: false + multiple_sep: ";" +- name: "Arguments" + arguments: + - type: "boolean_true" + name: "--emblmygff3" + description: "Means that the EMBL flat file comes from the EMBLmyGFF3 software.\ + \ This is an EMBL format dedicated for submission and contains particularity\ + \ to deal with. This parameter is needed to get a proper sequence id in the\ + \ GFF3 from an embl made with EMBLmyGFF3.\n" + info: null + direction: "input" + - type: "string" + name: "--primary_tag" + alternatives: + - "--pt" + - "-t" + description: "List of \"primary tag\". Useful to discard or keep specific features.\ + \ Multiple tags must be comma-separated.\n" + info: null + example: + - "tag1" + - "tag2" + required: false + direction: "input" + multiple: true + multiple_sep: ";" + - type: "boolean_true" + name: "--discard" + alternatives: + - "-d" + description: "Means that primary tags provided by the option \"primary_tag\" will\ + \ be discarded.\n" + info: null + direction: "input" + - type: "boolean_true" + name: "--keep" + alternatives: + - "-k" + description: "Means that only primary tags provided by the option \"primary_tag\"\ + \ will be kept.\n" + info: null + direction: "input" + - type: "file" + name: "--config" + alternatives: + - "-c" + description: "Input agat config file. By default AGAT takes as input agat_config.yaml\ + \ file from the working directory if any, otherwise it takes the original agat_config.yaml\ + \ shipped with AGAT. To get the agat_config.yaml locally type: \"agat config\ + \ --expose\". The --config option gives you the possibility to use your own\ + \ AGAT config file (located elsewhere or named differently).\n" + info: null + example: + - "custom_agat_config.yaml" + must_exist: true + create_parent: true + required: false + direction: "input" + multiple: false + multiple_sep: ";" +resources: +- type: "bash_script" + path: "script.sh" + is_executable: true +description: "The script takes an EMBL file as input, and will translate it in gff\ + \ format.\n" +test_resources: +- type: "bash_script" + path: "test.sh" + is_executable: true +- type: "file" + path: "test_data" +info: null +status: "enabled" +requirements: + commands: + - "ps" +keywords: +- "gene annotations" +- "GFF conversion" +license: "GPL-3.0" +references: + doi: + - "10.5281/zenodo.3552717" +links: + repository: "https://github.com/NBISweden/AGAT" + homepage: "https://github.com/NBISweden/AGAT" + documentation: "https://agat.readthedocs.io/en/latest/tools/agat_convert_embl2gff.html" + issue_tracker: "https://github.com/NBISweden/AGAT/issues" +runners: +- type: "executable" + id: "executable" + docker_setup_strategy: "ifneedbepullelsecachedbuild" +- type: "nextflow" + id: "nextflow" + directives: + tag: "$id" + auto: + simplifyInput: true + simplifyOutput: false + transcript: false + publish: false + config: + labels: + mem1gb: "memory = 1000000000.B" + mem2gb: "memory = 2000000000.B" + mem5gb: "memory = 5000000000.B" + mem10gb: "memory = 10000000000.B" + mem20gb: "memory = 20000000000.B" + mem50gb: "memory = 50000000000.B" + mem100gb: "memory = 100000000000.B" + mem200gb: "memory = 200000000000.B" + mem500gb: "memory = 500000000000.B" + mem1tb: "memory = 1000000000000.B" + mem2tb: "memory = 2000000000000.B" + mem5tb: "memory = 5000000000000.B" + mem10tb: "memory = 10000000000000.B" + mem20tb: "memory = 20000000000000.B" + mem50tb: "memory = 50000000000000.B" + mem100tb: "memory = 100000000000000.B" + mem200tb: "memory = 200000000000000.B" + mem500tb: "memory = 500000000000000.B" + mem1gib: "memory = 1073741824.B" + mem2gib: "memory = 2147483648.B" + mem4gib: "memory = 4294967296.B" + mem8gib: "memory = 8589934592.B" + mem16gib: "memory = 17179869184.B" + mem32gib: "memory = 34359738368.B" + mem64gib: "memory = 68719476736.B" + mem128gib: "memory = 137438953472.B" + mem256gib: "memory = 274877906944.B" + mem512gib: "memory = 549755813888.B" + mem1tib: "memory = 1099511627776.B" + mem2tib: "memory = 2199023255552.B" + mem4tib: "memory = 4398046511104.B" + mem8tib: "memory = 8796093022208.B" + mem16tib: "memory = 17592186044416.B" + mem32tib: "memory = 35184372088832.B" + mem64tib: "memory = 70368744177664.B" + mem128tib: "memory = 140737488355328.B" + mem256tib: "memory = 281474976710656.B" + mem512tib: "memory = 562949953421312.B" + cpu1: "cpus = 1" + cpu2: "cpus = 2" + cpu5: "cpus = 5" + cpu10: "cpus = 10" + cpu20: "cpus = 20" + cpu50: "cpus = 50" + cpu100: "cpus = 100" + cpu200: "cpus = 200" + cpu500: "cpus = 500" + cpu1000: "cpus = 1000" + debug: false + container: "docker" +engines: +- type: "docker" + id: "docker" + image: "quay.io/biocontainers/agat:1.4.0--pl5321hdfd78af_0" + target_registry: "images.viash-hub.com" + target_tag: "main" + namespace_separator: "/" + setup: + - type: "docker" + run: + - "agat --version | sed 's/AGAT\\s\\(.*\\)/agat: \"\\1\"/' > /var/software_versions.txt\n" + entrypoint: [] + cmd: null +- type: "native" + id: "native" +build_info: + config: "src/agat/agat_convert_embl2gff/config.vsh.yaml" + runner: "executable" + engine: "docker|native" + output: "target/executable/agat/agat_convert_embl2gff" + executable: "target/executable/agat/agat_convert_embl2gff/agat_convert_embl2gff" + viash_version: "0.9.0-RC6" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" + git_remote: "https://github.com/viash-hub/biobox" +package_config: + name: "biobox" + version: "main" + description: "A collection of bioinformatics tools for working with sequence data.\n" + info: null + viash_version: "0.9.0-RC6" + source: "src" + target: "target" + config_mods: + - ".requirements.commands := ['ps']\n" + - ".engines += { type: \"native\" }" + - ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'" + - ".engines[.type == 'docker'].target_tag := 'main'" + keywords: + - "bioinformatics" + - "modules" + - "sequencing" + license: "MIT" + organization: "vsh" + links: + repository: "https://github.com/viash-hub/biobox" + issue_tracker: "https://github.com/viash-hub/biobox/issues" diff --git a/target/executable/agat/agat_convert_embl2gff/agat_convert_embl2gff b/target/executable/agat/agat_convert_embl2gff/agat_convert_embl2gff new file mode 100755 index 00000000..4dff03cf --- /dev/null +++ b/target/executable/agat/agat_convert_embl2gff/agat_convert_embl2gff @@ -0,0 +1,1245 @@ +#!/usr/bin/env bash + +# agat_convert_embl2gff main +# +# This wrapper script is auto-generated by viash 0.9.0-RC6 and is thus a +# derivative work thereof. This software comes with ABSOLUTELY NO WARRANTY from +# Data Intuitive. +# +# The component may contain files which fall under a different license. The +# authors of this component should specify the license in the header of such +# files, or include a separate license file detailing the licenses of all included +# files. +# +# Component authors: +# * Leïla Paquay (author, maintainer) + +set -e + +if [ -z "$VIASH_TEMP" ]; then + VIASH_TEMP=${VIASH_TEMP:-$VIASH_TMPDIR} + VIASH_TEMP=${VIASH_TEMP:-$VIASH_TEMPDIR} + VIASH_TEMP=${VIASH_TEMP:-$VIASH_TMP} + VIASH_TEMP=${VIASH_TEMP:-$TMPDIR} + VIASH_TEMP=${VIASH_TEMP:-$TMP} + VIASH_TEMP=${VIASH_TEMP:-$TEMPDIR} + VIASH_TEMP=${VIASH_TEMP:-$TEMP} + VIASH_TEMP=${VIASH_TEMP:-/tmp} +fi + +# define helper functions +# ViashQuote: put quotes around non flag values +# $1 : unquoted string +# return : possibly quoted string +# examples: +# ViashQuote --foo # returns --foo +# ViashQuote bar # returns 'bar' +# Viashquote --foo=bar # returns --foo='bar' +function ViashQuote { + if [[ "$1" =~ ^-+[a-zA-Z0-9_\-]+=.+$ ]]; then + echo "$1" | sed "s#=\(.*\)#='\1'#" + elif [[ "$1" =~ ^-+[a-zA-Z0-9_\-]+$ ]]; then + echo "$1" + else + echo "'$1'" + fi +} +# ViashRemoveFlags: Remove leading flag +# $1 : string with a possible leading flag +# return : string without possible leading flag +# examples: +# ViashRemoveFlags --foo=bar # returns bar +function ViashRemoveFlags { + echo "$1" | sed 's/^--*[a-zA-Z0-9_\-]*=//' +} +# ViashSourceDir: return the path of a bash file, following symlinks +# usage : ViashSourceDir ${BASH_SOURCE[0]} +# $1 : Should always be set to ${BASH_SOURCE[0]} +# returns : The absolute path of the bash file +function ViashSourceDir { + SOURCE="$1" + while [ -h "$SOURCE" ]; do + DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )" + SOURCE="$(readlink "$SOURCE")" + [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" + done + cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd +} +# ViashFindTargetDir: return the path of the '.build.yaml' file, following symlinks +# usage : ViashFindTargetDir 'ScriptPath' +# $1 : The location from where to start the upward search +# returns : The absolute path of the '.build.yaml' file +function ViashFindTargetDir { + SOURCE="$1" + while [[ "$SOURCE" != "" && ! -e "$SOURCE/.build.yaml" ]]; do + SOURCE=${SOURCE%/*} + done + echo $SOURCE +} +# see https://en.wikipedia.org/wiki/Syslog#Severity_level +VIASH_LOGCODE_EMERGENCY=0 +VIASH_LOGCODE_ALERT=1 +VIASH_LOGCODE_CRITICAL=2 +VIASH_LOGCODE_ERROR=3 +VIASH_LOGCODE_WARNING=4 +VIASH_LOGCODE_NOTICE=5 +VIASH_LOGCODE_INFO=6 +VIASH_LOGCODE_DEBUG=7 +VIASH_VERBOSITY=$VIASH_LOGCODE_NOTICE + +# ViashLog: Log events depending on the verbosity level +# usage: ViashLog 1 alert Oh no something went wrong! +# $1: required verbosity level +# $2: display tag +# $3+: messages to display +# stdout: Your input, prepended by '[$2] '. +function ViashLog { + local required_level="$1" + local display_tag="$2" + shift 2 + if [ $VIASH_VERBOSITY -ge $required_level ]; then + >&2 echo "[$display_tag]" "$@" + fi +} + +# ViashEmergency: log events when the system is unstable +# usage: ViashEmergency Oh no something went wrong. +# stdout: Your input, prepended by '[emergency] '. +function ViashEmergency { + ViashLog $VIASH_LOGCODE_EMERGENCY emergency "$@" +} + +# ViashAlert: log events when actions must be taken immediately (e.g. corrupted system database) +# usage: ViashAlert Oh no something went wrong. +# stdout: Your input, prepended by '[alert] '. +function ViashAlert { + ViashLog $VIASH_LOGCODE_ALERT alert "$@" +} + +# ViashCritical: log events when a critical condition occurs +# usage: ViashCritical Oh no something went wrong. +# stdout: Your input, prepended by '[critical] '. +function ViashCritical { + ViashLog $VIASH_LOGCODE_CRITICAL critical "$@" +} + +# ViashError: log events when an error condition occurs +# usage: ViashError Oh no something went wrong. +# stdout: Your input, prepended by '[error] '. +function ViashError { + ViashLog $VIASH_LOGCODE_ERROR error "$@" +} + +# ViashWarning: log potentially abnormal events +# usage: ViashWarning Something may have gone wrong. +# stdout: Your input, prepended by '[warning] '. +function ViashWarning { + ViashLog $VIASH_LOGCODE_WARNING warning "$@" +} + +# ViashNotice: log significant but normal events +# usage: ViashNotice This just happened. +# stdout: Your input, prepended by '[notice] '. +function ViashNotice { + ViashLog $VIASH_LOGCODE_NOTICE notice "$@" +} + +# ViashInfo: log normal events +# usage: ViashInfo This just happened. +# stdout: Your input, prepended by '[info] '. +function ViashInfo { + ViashLog $VIASH_LOGCODE_INFO info "$@" +} + +# ViashDebug: log all events, for debugging purposes +# usage: ViashDebug This just happened. +# stdout: Your input, prepended by '[debug] '. +function ViashDebug { + ViashLog $VIASH_LOGCODE_DEBUG debug "$@" +} + +# find source folder of this component +VIASH_META_RESOURCES_DIR=`ViashSourceDir ${BASH_SOURCE[0]}` + +# find the root of the built components & dependencies +VIASH_TARGET_DIR=`ViashFindTargetDir $VIASH_META_RESOURCES_DIR` + +# define meta fields +VIASH_META_NAME="agat_convert_embl2gff" +VIASH_META_FUNCTIONALITY_NAME="agat_convert_embl2gff" +VIASH_META_EXECUTABLE="$VIASH_META_RESOURCES_DIR/$VIASH_META_NAME" +VIASH_META_CONFIG="$VIASH_META_RESOURCES_DIR/.config.vsh.yaml" +VIASH_META_TEMP_DIR="$VIASH_TEMP" + + +# ViashHelp: Display helpful explanation about this executable +function ViashHelp { + echo "agat_convert_embl2gff main" + echo "" + echo "The script takes an EMBL file as input, and will translate it in gff format." + echo "" + echo "Inputs:" + echo " --embl" + echo " type: file, required parameter, file must exist" + echo " example: input.embl" + echo " Input EMBL file that will be read." + echo "" + echo "Outputs:" + echo " -o, --out, --outfile, --gff, --output" + echo " type: file, output, file must exist" + echo " example: output.gff" + echo " Output GFF file. If no output file is specified, the output will be" + echo " written to STDOUT." + echo "" + echo "Arguments:" + echo " --emblmygff3" + echo " type: boolean_true" + echo " Means that the EMBL flat file comes from the EMBLmyGFF3 software. This" + echo " is an EMBL format dedicated for submission and contains particularity to" + echo " deal with. This parameter is needed to get a proper sequence id in the" + echo " GFF3 from an embl made with EMBLmyGFF3." + echo "" + echo " --pt, -t, --primary_tag" + echo " type: string, multiple values allowed" + echo " example: tag1;tag2" + echo " List of \"primary tag\". Useful to discard or keep specific features." + echo " Multiple tags must be comma-separated." + echo "" + echo " -d, --discard" + echo " type: boolean_true" + echo " Means that primary tags provided by the option \"primary_tag\" will be" + echo " discarded." + echo "" + echo " -k, --keep" + echo " type: boolean_true" + echo " Means that only primary tags provided by the option \"primary_tag\" will" + echo " be kept." + echo "" + echo " -c, --config" + echo " type: file, file must exist" + echo " example: custom_agat_config.yaml" + echo " Input agat config file. By default AGAT takes as input agat_config.yaml" + echo " file from the working directory if any, otherwise it takes the original" + echo " agat_config.yaml shipped with AGAT. To get the agat_config.yaml locally" + echo " type: \"agat config --expose\". The --config option gives you the" + echo " possibility to use your own AGAT config file (located elsewhere or named" + echo " differently)." +} + +# initialise variables +VIASH_MODE='run' +VIASH_ENGINE_ID='docker' + +######## Helper functions for setting up Docker images for viash ######## +# expects: ViashDockerBuild + +# ViashDockerInstallationCheck: check whether Docker is installed correctly +# +# examples: +# ViashDockerInstallationCheck +function ViashDockerInstallationCheck { + ViashDebug "Checking whether Docker is installed" + if [ ! command -v docker &> /dev/null ]; then + ViashCritical "Docker doesn't seem to be installed. See 'https://docs.docker.com/get-docker/' for instructions." + exit 1 + fi + + ViashDebug "Checking whether the Docker daemon is running" + save=$-; set +e + docker_version=$(docker version --format '{{.Client.APIVersion}}' 2> /dev/null) + out=$? + [[ $save =~ e ]] && set -e + if [ $out -ne 0 ]; then + ViashCritical "Docker daemon does not seem to be running. Try one of the following:" + ViashCritical "- Try running 'dockerd' in the command line" + ViashCritical "- See https://docs.docker.com/config/daemon/" + exit 1 + fi +} + +# ViashDockerRemoteTagCheck: check whether a Docker image is available +# on a remote. Assumes `docker login` has been performed, if relevant. +# +# $1 : image identifier with format `[registry/]image[:tag]` +# exit code $? : whether or not the image was found +# examples: +# ViashDockerRemoteTagCheck python:latest +# echo $? # returns '0' +# ViashDockerRemoteTagCheck sdaizudceahifu +# echo $? # returns '1' +function ViashDockerRemoteTagCheck { + docker manifest inspect $1 > /dev/null 2> /dev/null +} + +# ViashDockerLocalTagCheck: check whether a Docker image is available locally +# +# $1 : image identifier with format `[registry/]image[:tag]` +# exit code $? : whether or not the image was found +# examples: +# docker pull python:latest +# ViashDockerLocalTagCheck python:latest +# echo $? # returns '0' +# ViashDockerLocalTagCheck sdaizudceahifu +# echo $? # returns '1' +function ViashDockerLocalTagCheck { + [ -n "$(docker images -q $1)" ] +} + +# ViashDockerPull: pull a Docker image +# +# $1 : image identifier with format `[registry/]image[:tag]` +# exit code $? : whether or not the image was found +# examples: +# ViashDockerPull python:latest +# echo $? # returns '0' +# ViashDockerPull sdaizudceahifu +# echo $? # returns '1' +function ViashDockerPull { + ViashNotice "Checking if Docker image is available at '$1'" + if [ $VIASH_VERBOSITY -ge $VIASH_LOGCODE_INFO ]; then + docker pull $1 && return 0 || return 1 + else + save=$-; set +e + docker pull $1 2> /dev/null > /dev/null + out=$? + [[ $save =~ e ]] && set -e + if [ $out -ne 0 ]; then + ViashWarning "Could not pull from '$1'. Docker image doesn't exist or is not accessible." + fi + return $out + fi +} + +# ViashDockerPush: push a Docker image +# +# $1 : image identifier with format `[registry/]image[:tag]` +# exit code $? : whether or not the image was found +# examples: +# ViashDockerPush python:latest +# echo $? # returns '0' +# ViashDockerPush sdaizudceahifu +# echo $? # returns '1' +function ViashDockerPush { + ViashNotice "Pushing image to '$1'" + save=$-; set +e + if [ $VIASH_VERBOSITY -ge $VIASH_LOGCODE_INFO ]; then + docker push $1 + out=$? + else + docker push $1 2> /dev/null > /dev/null + out=$? + fi + [[ $save =~ e ]] && set -e + if [ $out -eq 0 ]; then + ViashNotice "Container '$1' push succeeded." + else + ViashError "Container '$1' push errored. You might not be logged in or have the necessary permissions." + fi + return $out +} + +# ViashDockerPullElseBuild: pull a Docker image, else build it +# +# $1 : image identifier with format `[registry/]image[:tag]` +# ViashDockerBuild : a Bash function which builds a docker image, takes image identifier as argument. +# examples: +# ViashDockerPullElseBuild mynewcomponent +function ViashDockerPullElseBuild { + save=$-; set +e + ViashDockerPull $1 + out=$? + [[ $save =~ e ]] && set -e + if [ $out -ne 0 ]; then + ViashDockerBuild $@ + fi +} + +# ViashDockerSetup: create a Docker image, according to specified docker setup strategy +# +# $1 : image identifier with format `[registry/]image[:tag]` +# $2 : docker setup strategy, see DockerSetupStrategy.scala +# examples: +# ViashDockerSetup mynewcomponent alwaysbuild +function ViashDockerSetup { + local image_id="$1" + local setup_strategy="$2" + if [ "$setup_strategy" == "alwaysbuild" -o "$setup_strategy" == "build" -o "$setup_strategy" == "b" ]; then + ViashDockerBuild $image_id --no-cache $(ViashDockerBuildArgs "$engine_id") + elif [ "$setup_strategy" == "alwayspull" -o "$setup_strategy" == "pull" -o "$setup_strategy" == "p" ]; then + ViashDockerPull $image_id + elif [ "$setup_strategy" == "alwayspullelsebuild" -o "$setup_strategy" == "pullelsebuild" ]; then + ViashDockerPullElseBuild $image_id --no-cache $(ViashDockerBuildArgs "$engine_id") + elif [ "$setup_strategy" == "alwayspullelsecachedbuild" -o "$setup_strategy" == "pullelsecachedbuild" ]; then + ViashDockerPullElseBuild $image_id $(ViashDockerBuildArgs "$engine_id") + elif [ "$setup_strategy" == "alwayscachedbuild" -o "$setup_strategy" == "cachedbuild" -o "$setup_strategy" == "cb" ]; then + ViashDockerBuild $image_id $(ViashDockerBuildArgs "$engine_id") + elif [[ "$setup_strategy" =~ ^ifneedbe ]]; then + local save=$-; set +e + ViashDockerLocalTagCheck $image_id + local outCheck=$? + [[ $save =~ e ]] && set -e + if [ $outCheck -eq 0 ]; then + ViashInfo "Image $image_id already exists" + elif [ "$setup_strategy" == "ifneedbebuild" ]; then + ViashDockerBuild $image_id --no-cache $(ViashDockerBuildArgs "$engine_id") + elif [ "$setup_strategy" == "ifneedbecachedbuild" ]; then + ViashDockerBuild $image_id $(ViashDockerBuildArgs "$engine_id") + elif [ "$setup_strategy" == "ifneedbepull" ]; then + ViashDockerPull $image_id + elif [ "$setup_strategy" == "ifneedbepullelsebuild" ]; then + ViashDockerPullElseBuild $image_id --no-cache $(ViashDockerBuildArgs "$engine_id") + elif [ "$setup_strategy" == "ifneedbepullelsecachedbuild" ]; then + ViashDockerPullElseBuild $image_id $(ViashDockerBuildArgs "$engine_id") + else + ViashError "Unrecognised Docker strategy: $setup_strategy" + exit 1 + fi + elif [ "$setup_strategy" == "push" -o "$setup_strategy" == "forcepush" -o "$setup_strategy" == "alwayspush" ]; then + ViashDockerPush "$image_id" + elif [ "$setup_strategy" == "pushifnotpresent" -o "$setup_strategy" == "gentlepush" -o "$setup_strategy" == "maybepush" ]; then + local save=$-; set +e + ViashDockerRemoteTagCheck $image_id + local outCheck=$? + [[ $save =~ e ]] && set -e + if [ $outCheck -eq 0 ]; then + ViashNotice "Container '$image_id' exists, doing nothing." + else + ViashNotice "Container '$image_id' does not yet exist." + ViashDockerPush "$image_id" + fi + elif [ "$setup_strategy" == "donothing" -o "$setup_strategy" == "meh" ]; then + ViashNotice "Skipping setup." + else + ViashError "Unrecognised Docker strategy: $setup_strategy" + exit 1 + fi +} + +# ViashDockerCheckCommands: Check whether a docker container has the required commands +# +# $1 : image identifier with format `[registry/]image[:tag]` +# $@ : commands to verify being present +# examples: +# ViashDockerCheckCommands bash:4.0 bash ps foo +function ViashDockerCheckCommands { + local image_id="$1" + shift 1 + local commands="$@" + local save=$-; set +e + local missing # mark 'missing' as local in advance, otherwise the exit code of the command will be missing and always be '0' + missing=$(docker run --rm --entrypoint=sh "$image_id" -c "for command in $commands; do command -v \$command >/dev/null 2>&1; if [ \$? -ne 0 ]; then echo \$command; exit 1; fi; done") + local outCheck=$? + [[ $save =~ e ]] && set -e + if [ $outCheck -ne 0 ]; then + ViashError "Docker container '$image_id' does not contain command '$missing'." + exit 1 + fi +} + +# ViashDockerBuild: build a docker image +# $1 : image identifier with format `[registry/]image[:tag]` +# $... : additional arguments to pass to docker build +# $VIASH_META_TEMP_DIR : temporary directory to store dockerfile & optional resources in +# $VIASH_META_NAME : name of the component +# $VIASH_META_RESOURCES_DIR : directory containing the resources +# $VIASH_VERBOSITY : verbosity level +# exit code $? : whether or not the image was built successfully +function ViashDockerBuild { + local image_id="$1" + shift 1 + + # create temporary directory to store dockerfile & optional resources in + local tmpdir=$(mktemp -d "$VIASH_META_TEMP_DIR/dockerbuild-$VIASH_META_NAME-XXXXXX") + local dockerfile="$tmpdir/Dockerfile" + function clean_up { + rm -rf "$tmpdir" + } + trap clean_up EXIT + + # store dockerfile and resources + ViashDockerfile "$VIASH_ENGINE_ID" > "$dockerfile" + + # generate the build command + local docker_build_cmd="docker build -t '$image_id' $@ '$VIASH_META_RESOURCES_DIR' -f '$dockerfile'" + + # build the container + ViashNotice "Building container '$image_id' with Dockerfile" + ViashInfo "$docker_build_cmd" + local save=$-; set +e + if [ $VIASH_VERBOSITY -ge $VIASH_LOGCODE_INFO ]; then + eval $docker_build_cmd + else + eval $docker_build_cmd &> "$tmpdir/docker_build.log" + fi + + # check exit code + local out=$? + [[ $save =~ e ]] && set -e + if [ $out -ne 0 ]; then + ViashError "Error occurred while building container '$image_id'" + if [ $VIASH_VERBOSITY -lt $VIASH_LOGCODE_INFO ]; then + ViashError "Transcript: --------------------------------" + cat "$tmpdir/docker_build.log" + ViashError "End of transcript --------------------------" + fi + exit 1 + fi +} + +######## End of helper functions for setting up Docker images for viash ######## + +# ViashDockerFile: print the dockerfile to stdout +# $1 : engine identifier +# return : dockerfile required to run this component +# examples: +# ViashDockerFile +function ViashDockerfile { + local engine_id="$1" + + if [[ "$engine_id" == "docker" ]]; then + cat << 'VIASHDOCKER' +FROM quay.io/biocontainers/agat:1.4.0--pl5321hdfd78af_0 +ENTRYPOINT [] +RUN agat --version | sed 's/AGAT\s\(.*\)/agat: "\1"/' > /var/software_versions.txt + +LABEL org.opencontainers.image.authors="Leïla Paquay" +LABEL org.opencontainers.image.description="Companion container for running component agat agat_convert_embl2gff" +LABEL org.opencontainers.image.created="2024-08-14T20:58:52Z" +LABEL org.opencontainers.image.source="https://github.com/NBISweden/AGAT" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" +LABEL org.opencontainers.image.version="main" + +VIASHDOCKER + fi +} + +# ViashDockerBuildArgs: return the arguments to pass to docker build +# $1 : engine identifier +# return : arguments to pass to docker build +function ViashDockerBuildArgs { + local engine_id="$1" + + if [[ "$engine_id" == "docker" ]]; then + echo "" + fi +} + +# ViashAbsolutePath: generate absolute path from relative path +# borrowed from https://stackoverflow.com/a/21951256 +# $1 : relative filename +# return : absolute path +# examples: +# ViashAbsolutePath some_file.txt # returns /path/to/some_file.txt +# ViashAbsolutePath /foo/bar/.. # returns /foo +function ViashAbsolutePath { + local thePath + if [[ ! "$1" =~ ^/ ]]; then + thePath="$PWD/$1" + else + thePath="$1" + fi + echo "$thePath" | ( + IFS=/ + read -a parr + declare -a outp + for i in "${parr[@]}"; do + case "$i" in + ''|.) continue ;; + ..) + len=${#outp[@]} + if ((len==0)); then + continue + else + unset outp[$((len-1))] + fi + ;; + *) + len=${#outp[@]} + outp[$len]="$i" + ;; + esac + done + echo /"${outp[*]}" + ) +} +# ViashDockerAutodetectMount: auto configuring docker mounts from parameters +# $1 : The parameter value +# returns : New parameter +# $VIASH_DIRECTORY_MOUNTS : Added another parameter to be passed to docker +# examples: +# ViashDockerAutodetectMount /path/to/bar # returns '/viash_automount/path/to/bar' +# ViashDockerAutodetectMountArg /path/to/bar # returns '--volume="/path/to:/viash_automount/path/to"' +function ViashDockerAutodetectMount { + abs_path=$(ViashAbsolutePath "$1") + if [ -d "$abs_path" ]; then + mount_source="$abs_path" + base_name="" + else + mount_source=`dirname "$abs_path"` + base_name=`basename "$abs_path"` + fi + mount_target="/viash_automount$mount_source" + if [ -z "$base_name" ]; then + echo "$mount_target" + else + echo "$mount_target/$base_name" + fi +} +function ViashDockerAutodetectMountArg { + abs_path=$(ViashAbsolutePath "$1") + if [ -d "$abs_path" ]; then + mount_source="$abs_path" + base_name="" + else + mount_source=`dirname "$abs_path"` + base_name=`basename "$abs_path"` + fi + mount_target="/viash_automount$mount_source" + ViashDebug "ViashDockerAutodetectMountArg $1 -> $mount_source -> $mount_target" + echo "--volume=\"$mount_source:$mount_target\"" +} +function ViashDockerStripAutomount { + abs_path=$(ViashAbsolutePath "$1") + echo "${abs_path#/viash_automount}" +} +# initialise variables +VIASH_DIRECTORY_MOUNTS=() + +# initialise docker variables +VIASH_DOCKER_RUN_ARGS=(-i --rm) + +# initialise array +VIASH_POSITIONAL_ARGS='' + +while [[ $# -gt 0 ]]; do + case "$1" in + -h|--help) + ViashHelp + exit + ;; + ---v|---verbose) + let "VIASH_VERBOSITY=VIASH_VERBOSITY+1" + shift 1 + ;; + ---verbosity) + VIASH_VERBOSITY="$2" + shift 2 + ;; + ---verbosity=*) + VIASH_VERBOSITY="$(ViashRemoveFlags "$1")" + shift 1 + ;; + --version) + echo "agat_convert_embl2gff main" + exit + ;; + --embl) + [ -n "$VIASH_PAR_EMBL" ] && ViashError Bad arguments for option \'--embl\': \'$VIASH_PAR_EMBL\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_EMBL="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to --embl. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --embl=*) + [ -n "$VIASH_PAR_EMBL" ] && ViashError Bad arguments for option \'--embl=*\': \'$VIASH_PAR_EMBL\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_EMBL=$(ViashRemoveFlags "$1") + shift 1 + ;; + --output) + [ -n "$VIASH_PAR_OUTPUT" ] && ViashError Bad arguments for option \'--output\': \'$VIASH_PAR_OUTPUT\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_OUTPUT="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to --output. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --output=*) + [ -n "$VIASH_PAR_OUTPUT" ] && ViashError Bad arguments for option \'--output=*\': \'$VIASH_PAR_OUTPUT\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_OUTPUT=$(ViashRemoveFlags "$1") + shift 1 + ;; + -o) + [ -n "$VIASH_PAR_OUTPUT" ] && ViashError Bad arguments for option \'-o\': \'$VIASH_PAR_OUTPUT\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_OUTPUT="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to -o. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --out) + [ -n "$VIASH_PAR_OUTPUT" ] && ViashError Bad arguments for option \'--out\': \'$VIASH_PAR_OUTPUT\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_OUTPUT="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to --out. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --outfile) + [ -n "$VIASH_PAR_OUTPUT" ] && ViashError Bad arguments for option \'--outfile\': \'$VIASH_PAR_OUTPUT\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_OUTPUT="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to --outfile. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --gff) + [ -n "$VIASH_PAR_OUTPUT" ] && ViashError Bad arguments for option \'--gff\': \'$VIASH_PAR_OUTPUT\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_OUTPUT="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to --gff. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --emblmygff3) + [ -n "$VIASH_PAR_EMBLMYGFF3" ] && ViashError Bad arguments for option \'--emblmygff3\': \'$VIASH_PAR_EMBLMYGFF3\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_EMBLMYGFF3=true + shift 1 + ;; + --primary_tag) + if [ -z "$VIASH_PAR_PRIMARY_TAG" ]; then + VIASH_PAR_PRIMARY_TAG="$2" + else + VIASH_PAR_PRIMARY_TAG="$VIASH_PAR_PRIMARY_TAG;""$2" + fi + [ $# -lt 2 ] && ViashError Not enough arguments passed to --primary_tag. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --primary_tag=*) + if [ -z "$VIASH_PAR_PRIMARY_TAG" ]; then + VIASH_PAR_PRIMARY_TAG=$(ViashRemoveFlags "$1") + else + VIASH_PAR_PRIMARY_TAG="$VIASH_PAR_PRIMARY_TAG;"$(ViashRemoveFlags "$1") + fi + shift 1 + ;; + --pt) + if [ -z "$VIASH_PAR_PRIMARY_TAG" ]; then + VIASH_PAR_PRIMARY_TAG="$2" + else + VIASH_PAR_PRIMARY_TAG="$VIASH_PAR_PRIMARY_TAG;""$2" + fi + [ $# -lt 2 ] && ViashError Not enough arguments passed to --pt. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + -t) + if [ -z "$VIASH_PAR_PRIMARY_TAG" ]; then + VIASH_PAR_PRIMARY_TAG="$2" + else + VIASH_PAR_PRIMARY_TAG="$VIASH_PAR_PRIMARY_TAG;""$2" + fi + [ $# -lt 2 ] && ViashError Not enough arguments passed to -t. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --discard) + [ -n "$VIASH_PAR_DISCARD" ] && ViashError Bad arguments for option \'--discard\': \'$VIASH_PAR_DISCARD\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_DISCARD=true + shift 1 + ;; + -d) + [ -n "$VIASH_PAR_DISCARD" ] && ViashError Bad arguments for option \'-d\': \'$VIASH_PAR_DISCARD\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_DISCARD=true + shift 1 + ;; + --keep) + [ -n "$VIASH_PAR_KEEP" ] && ViashError Bad arguments for option \'--keep\': \'$VIASH_PAR_KEEP\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_KEEP=true + shift 1 + ;; + -k) + [ -n "$VIASH_PAR_KEEP" ] && ViashError Bad arguments for option \'-k\': \'$VIASH_PAR_KEEP\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_KEEP=true + shift 1 + ;; + --config) + [ -n "$VIASH_PAR_CONFIG" ] && ViashError Bad arguments for option \'--config\': \'$VIASH_PAR_CONFIG\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_CONFIG="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to --config. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --config=*) + [ -n "$VIASH_PAR_CONFIG" ] && ViashError Bad arguments for option \'--config=*\': \'$VIASH_PAR_CONFIG\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_CONFIG=$(ViashRemoveFlags "$1") + shift 1 + ;; + -c) + [ -n "$VIASH_PAR_CONFIG" ] && ViashError Bad arguments for option \'-c\': \'$VIASH_PAR_CONFIG\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_CONFIG="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to -c. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + ---engine) + VIASH_ENGINE_ID="$2" + shift 2 + ;; + ---engine=*) + VIASH_ENGINE_ID="$(ViashRemoveFlags "$1")" + shift 1 + ;; + ---setup) + VIASH_MODE='setup' + VIASH_SETUP_STRATEGY="$2" + shift 2 + ;; + ---setup=*) + VIASH_MODE='setup' + VIASH_SETUP_STRATEGY="$(ViashRemoveFlags "$1")" + shift 1 + ;; + ---dockerfile) + VIASH_MODE='dockerfile' + shift 1 + ;; + ---debug) + VIASH_MODE='debug' + shift 1 + ;; + ---cpus) + [ -n "$VIASH_META_CPUS" ] && ViashError Bad arguments for option \'---cpus\': \'$VIASH_META_CPUS\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_META_CPUS="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to ---cpus. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + ---cpus=*) + [ -n "$VIASH_META_CPUS" ] && ViashError Bad arguments for option \'---cpus=*\': \'$VIASH_META_CPUS\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_META_CPUS=$(ViashRemoveFlags "$1") + shift 1 + ;; + ---memory) + [ -n "$VIASH_META_MEMORY" ] && ViashError Bad arguments for option \'---memory\': \'$VIASH_META_MEMORY\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_META_MEMORY="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to ---memory. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + ---memory=*) + [ -n "$VIASH_META_MEMORY" ] && ViashError Bad arguments for option \'---memory=*\': \'$VIASH_META_MEMORY\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_META_MEMORY=$(ViashRemoveFlags "$1") + shift 1 + ;; + *) # positional arg or unknown option + # since the positional args will be eval'd, can we always quote, instead of using ViashQuote + VIASH_POSITIONAL_ARGS="$VIASH_POSITIONAL_ARGS '$1'" + [[ $1 == -* ]] && ViashWarning $1 looks like a parameter but is not a defined parameter and will instead be treated as a positional argument. Use "--help" to get more information on the parameters. + shift # past argument + ;; + esac +done + +# parse positional parameters +eval set -- $VIASH_POSITIONAL_ARGS + + +if [ "$VIASH_ENGINE_ID" == "native" ] ; then + VIASH_ENGINE_TYPE='native' +elif [ "$VIASH_ENGINE_ID" == "docker" ] ; then + VIASH_ENGINE_TYPE='docker' +else + ViashError "Engine '$VIASH_ENGINE_ID' is not recognized. Options are: docker, native." + exit 1 +fi + +if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then + # check if docker is installed properly + ViashDockerInstallationCheck + + # determine docker image id + if [[ "$VIASH_ENGINE_ID" == 'docker' ]]; then + VIASH_DOCKER_IMAGE_ID='images.viash-hub.com/vsh/biobox/agat/agat_convert_embl2gff:main' + fi + + # print dockerfile + if [ "$VIASH_MODE" == "dockerfile" ]; then + ViashDockerfile "$VIASH_ENGINE_ID" + exit 0 + + # enter docker container + elif [[ "$VIASH_MODE" == "debug" ]]; then + VIASH_CMD="docker run --entrypoint=bash ${VIASH_DOCKER_RUN_ARGS[@]} -v '$(pwd)':/pwd --workdir /pwd -t $VIASH_DOCKER_IMAGE_ID" + ViashNotice "+ $VIASH_CMD" + eval $VIASH_CMD + exit + + # build docker image + elif [ "$VIASH_MODE" == "setup" ]; then + ViashDockerSetup "$VIASH_DOCKER_IMAGE_ID" "$VIASH_SETUP_STRATEGY" + ViashDockerCheckCommands "$VIASH_DOCKER_IMAGE_ID" 'ps' 'bash' + exit 0 + fi + + # check if docker image exists + ViashDockerSetup "$VIASH_DOCKER_IMAGE_ID" ifneedbepullelsecachedbuild + ViashDockerCheckCommands "$VIASH_DOCKER_IMAGE_ID" 'ps' 'bash' +fi + +# setting computational defaults + +# helper function for parsing memory strings +function ViashMemoryAsBytes { + local memory=`echo "$1" | tr '[:upper:]' '[:lower:]' | tr -d '[:space:]'` + local memory_regex='^([0-9]+)([kmgtp]i?b?|b)$' + if [[ $memory =~ $memory_regex ]]; then + local number=${memory/[^0-9]*/} + local symbol=${memory/*[0-9]/} + + case $symbol in + b) memory_b=$number ;; + kb|k) memory_b=$(( $number * 1000 )) ;; + mb|m) memory_b=$(( $number * 1000 * 1000 )) ;; + gb|g) memory_b=$(( $number * 1000 * 1000 * 1000 )) ;; + tb|t) memory_b=$(( $number * 1000 * 1000 * 1000 * 1000 )) ;; + pb|p) memory_b=$(( $number * 1000 * 1000 * 1000 * 1000 * 1000 )) ;; + kib|ki) memory_b=$(( $number * 1024 )) ;; + mib|mi) memory_b=$(( $number * 1024 * 1024 )) ;; + gib|gi) memory_b=$(( $number * 1024 * 1024 * 1024 )) ;; + tib|ti) memory_b=$(( $number * 1024 * 1024 * 1024 * 1024 )) ;; + pib|pi) memory_b=$(( $number * 1024 * 1024 * 1024 * 1024 * 1024 )) ;; + esac + echo "$memory_b" + fi +} +# compute memory in different units +if [ ! -z ${VIASH_META_MEMORY+x} ]; then + VIASH_META_MEMORY_B=`ViashMemoryAsBytes $VIASH_META_MEMORY` + # do not define other variables if memory_b is an empty string + if [ ! -z "$VIASH_META_MEMORY_B" ]; then + VIASH_META_MEMORY_KB=$(( ($VIASH_META_MEMORY_B+999) / 1000 )) + VIASH_META_MEMORY_MB=$(( ($VIASH_META_MEMORY_KB+999) / 1000 )) + VIASH_META_MEMORY_GB=$(( ($VIASH_META_MEMORY_MB+999) / 1000 )) + VIASH_META_MEMORY_TB=$(( ($VIASH_META_MEMORY_GB+999) / 1000 )) + VIASH_META_MEMORY_PB=$(( ($VIASH_META_MEMORY_TB+999) / 1000 )) + VIASH_META_MEMORY_KIB=$(( ($VIASH_META_MEMORY_B+1023) / 1024 )) + VIASH_META_MEMORY_MIB=$(( ($VIASH_META_MEMORY_KIB+1023) / 1024 )) + VIASH_META_MEMORY_GIB=$(( ($VIASH_META_MEMORY_MIB+1023) / 1024 )) + VIASH_META_MEMORY_TIB=$(( ($VIASH_META_MEMORY_GIB+1023) / 1024 )) + VIASH_META_MEMORY_PIB=$(( ($VIASH_META_MEMORY_TIB+1023) / 1024 )) + else + # unset memory if string is empty + unset $VIASH_META_MEMORY_B + fi +fi +# unset nproc if string is empty +if [ -z "$VIASH_META_CPUS" ]; then + unset $VIASH_META_CPUS +fi + + +# check whether required parameters exist +if [ -z ${VIASH_PAR_EMBL+x} ]; then + ViashError '--embl' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi +if [ -z ${VIASH_META_NAME+x} ]; then + ViashError 'name' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi +if [ -z ${VIASH_META_FUNCTIONALITY_NAME+x} ]; then + ViashError 'functionality_name' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi +if [ -z ${VIASH_META_RESOURCES_DIR+x} ]; then + ViashError 'resources_dir' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi +if [ -z ${VIASH_META_EXECUTABLE+x} ]; then + ViashError 'executable' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi +if [ -z ${VIASH_META_CONFIG+x} ]; then + ViashError 'config' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi +if [ -z ${VIASH_META_TEMP_DIR+x} ]; then + ViashError 'temp_dir' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi + +# filling in defaults +if [ -z ${VIASH_PAR_EMBLMYGFF3+x} ]; then + VIASH_PAR_EMBLMYGFF3="false" +fi +if [ -z ${VIASH_PAR_DISCARD+x} ]; then + VIASH_PAR_DISCARD="false" +fi +if [ -z ${VIASH_PAR_KEEP+x} ]; then + VIASH_PAR_KEEP="false" +fi + +# check whether required files exist +if [ ! -z "$VIASH_PAR_EMBL" ] && [ ! -e "$VIASH_PAR_EMBL" ]; then + ViashError "Input file '$VIASH_PAR_EMBL' does not exist." + exit 1 +fi +if [ ! -z "$VIASH_PAR_CONFIG" ] && [ ! -e "$VIASH_PAR_CONFIG" ]; then + ViashError "Input file '$VIASH_PAR_CONFIG' does not exist." + exit 1 +fi + +# check whether parameters values are of the right type +if [[ -n "$VIASH_PAR_EMBLMYGFF3" ]]; then + if ! [[ "$VIASH_PAR_EMBLMYGFF3" =~ ^(true|True|TRUE|false|False|FALSE|yes|Yes|YES|no|No|NO)$ ]]; then + ViashError '--emblmygff3' has to be a boolean_true. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_PAR_DISCARD" ]]; then + if ! [[ "$VIASH_PAR_DISCARD" =~ ^(true|True|TRUE|false|False|FALSE|yes|Yes|YES|no|No|NO)$ ]]; then + ViashError '--discard' has to be a boolean_true. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_PAR_KEEP" ]]; then + if ! [[ "$VIASH_PAR_KEEP" =~ ^(true|True|TRUE|false|False|FALSE|yes|Yes|YES|no|No|NO)$ ]]; then + ViashError '--keep' has to be a boolean_true. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_CPUS" ]]; then + if ! [[ "$VIASH_META_CPUS" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'cpus' has to be an integer. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_B" ]]; then + if ! [[ "$VIASH_META_MEMORY_B" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_b' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_KB" ]]; then + if ! [[ "$VIASH_META_MEMORY_KB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_kb' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_MB" ]]; then + if ! [[ "$VIASH_META_MEMORY_MB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_mb' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_GB" ]]; then + if ! [[ "$VIASH_META_MEMORY_GB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_gb' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_TB" ]]; then + if ! [[ "$VIASH_META_MEMORY_TB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_tb' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_PB" ]]; then + if ! [[ "$VIASH_META_MEMORY_PB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_pb' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_KIB" ]]; then + if ! [[ "$VIASH_META_MEMORY_KIB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_kib' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_MIB" ]]; then + if ! [[ "$VIASH_META_MEMORY_MIB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_mib' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_GIB" ]]; then + if ! [[ "$VIASH_META_MEMORY_GIB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_gib' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_TIB" ]]; then + if ! [[ "$VIASH_META_MEMORY_TIB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_tib' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_PIB" ]]; then + if ! [[ "$VIASH_META_MEMORY_PIB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_pib' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi + +# create parent directories of output files, if so desired +if [ ! -z "$VIASH_PAR_OUTPUT" ] && [ ! -d "$(dirname "$VIASH_PAR_OUTPUT")" ]; then + mkdir -p "$(dirname "$VIASH_PAR_OUTPUT")" +fi + +if [ "$VIASH_ENGINE_ID" == "native" ] ; then + if [ "$VIASH_MODE" == "run" ]; then + VIASH_CMD="bash" + else + ViashError "Engine '$VIASH_ENGINE_ID' does not support mode '$VIASH_MODE'." + exit 1 + fi +fi + +if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then + # detect volumes from file arguments + VIASH_CHOWN_VARS=() +if [ ! -z "$VIASH_PAR_EMBL" ]; then + VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_PAR_EMBL")" ) + VIASH_PAR_EMBL=$(ViashDockerAutodetectMount "$VIASH_PAR_EMBL") +fi +if [ ! -z "$VIASH_PAR_OUTPUT" ]; then + VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_PAR_OUTPUT")" ) + VIASH_PAR_OUTPUT=$(ViashDockerAutodetectMount "$VIASH_PAR_OUTPUT") + VIASH_CHOWN_VARS+=( "$VIASH_PAR_OUTPUT" ) +fi +if [ ! -z "$VIASH_PAR_CONFIG" ]; then + VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_PAR_CONFIG")" ) + VIASH_PAR_CONFIG=$(ViashDockerAutodetectMount "$VIASH_PAR_CONFIG") +fi +if [ ! -z "$VIASH_META_RESOURCES_DIR" ]; then + VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_META_RESOURCES_DIR")" ) + VIASH_META_RESOURCES_DIR=$(ViashDockerAutodetectMount "$VIASH_META_RESOURCES_DIR") +fi +if [ ! -z "$VIASH_META_EXECUTABLE" ]; then + VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_META_EXECUTABLE")" ) + VIASH_META_EXECUTABLE=$(ViashDockerAutodetectMount "$VIASH_META_EXECUTABLE") +fi +if [ ! -z "$VIASH_META_CONFIG" ]; then + VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_META_CONFIG")" ) + VIASH_META_CONFIG=$(ViashDockerAutodetectMount "$VIASH_META_CONFIG") +fi +if [ ! -z "$VIASH_META_TEMP_DIR" ]; then + VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_META_TEMP_DIR")" ) + VIASH_META_TEMP_DIR=$(ViashDockerAutodetectMount "$VIASH_META_TEMP_DIR") +fi + + # get unique mounts + VIASH_UNIQUE_MOUNTS=($(for val in "${VIASH_DIRECTORY_MOUNTS[@]}"; do echo "$val"; done | sort -u)) +fi + +if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then + # change file ownership + function ViashPerformChown { + if (( ${#VIASH_CHOWN_VARS[@]} )); then + set +e + VIASH_CMD="docker run --entrypoint=bash --rm ${VIASH_UNIQUE_MOUNTS[@]} $VIASH_DOCKER_IMAGE_ID -c 'chown $(id -u):$(id -g) --silent --recursive ${VIASH_CHOWN_VARS[@]}'" + ViashDebug "+ $VIASH_CMD" + eval $VIASH_CMD + set -e + fi + } + trap ViashPerformChown EXIT +fi + +if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then + # helper function for filling in extra docker args + if [ ! -z "$VIASH_META_MEMORY_B" ]; then + VIASH_DOCKER_RUN_ARGS+=("--memory=${VIASH_META_MEMORY_B}") + fi + if [ ! -z "$VIASH_META_CPUS" ]; then + VIASH_DOCKER_RUN_ARGS+=("--cpus=${VIASH_META_CPUS}") + fi +fi + +if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then + VIASH_CMD="docker run --entrypoint=bash ${VIASH_DOCKER_RUN_ARGS[@]} ${VIASH_UNIQUE_MOUNTS[@]} $VIASH_DOCKER_IMAGE_ID" +fi + + +# set dependency paths + + +ViashDebug "Running command: $(echo $VIASH_CMD)" +cat << VIASHEOF | eval $VIASH_CMD +set -e +tempscript=\$(mktemp "$VIASH_META_TEMP_DIR/viash-run-agat_convert_embl2gff-XXXXXX").sh +function clean_up { + rm "\$tempscript" +} +function interrupt { + echo -e "\nCTRL-C Pressed..." + exit 1 +} +trap clean_up EXIT +trap interrupt INT SIGINT +cat > "\$tempscript" << 'VIASHMAIN' +#!/bin/bash + +## VIASH START +# The following code has been auto-generated by Viash. +$( if [ ! -z ${VIASH_PAR_EMBL+x} ]; then echo "${VIASH_PAR_EMBL}" | sed "s#'#'\"'\"'#g;s#.*#par_embl='&'#" ; else echo "# par_embl="; fi ) +$( if [ ! -z ${VIASH_PAR_OUTPUT+x} ]; then echo "${VIASH_PAR_OUTPUT}" | sed "s#'#'\"'\"'#g;s#.*#par_output='&'#" ; else echo "# par_output="; fi ) +$( if [ ! -z ${VIASH_PAR_EMBLMYGFF3+x} ]; then echo "${VIASH_PAR_EMBLMYGFF3}" | sed "s#'#'\"'\"'#g;s#.*#par_emblmygff3='&'#" ; else echo "# par_emblmygff3="; fi ) +$( if [ ! -z ${VIASH_PAR_PRIMARY_TAG+x} ]; then echo "${VIASH_PAR_PRIMARY_TAG}" | sed "s#'#'\"'\"'#g;s#.*#par_primary_tag='&'#" ; else echo "# par_primary_tag="; fi ) +$( if [ ! -z ${VIASH_PAR_DISCARD+x} ]; then echo "${VIASH_PAR_DISCARD}" | sed "s#'#'\"'\"'#g;s#.*#par_discard='&'#" ; else echo "# par_discard="; fi ) +$( if [ ! -z ${VIASH_PAR_KEEP+x} ]; then echo "${VIASH_PAR_KEEP}" | sed "s#'#'\"'\"'#g;s#.*#par_keep='&'#" ; else echo "# par_keep="; fi ) +$( if [ ! -z ${VIASH_PAR_CONFIG+x} ]; then echo "${VIASH_PAR_CONFIG}" | sed "s#'#'\"'\"'#g;s#.*#par_config='&'#" ; else echo "# par_config="; fi ) +$( if [ ! -z ${VIASH_META_NAME+x} ]; then echo "${VIASH_META_NAME}" | sed "s#'#'\"'\"'#g;s#.*#meta_name='&'#" ; else echo "# meta_name="; fi ) +$( if [ ! -z ${VIASH_META_FUNCTIONALITY_NAME+x} ]; then echo "${VIASH_META_FUNCTIONALITY_NAME}" | sed "s#'#'\"'\"'#g;s#.*#meta_functionality_name='&'#" ; else echo "# meta_functionality_name="; fi ) +$( if [ ! -z ${VIASH_META_RESOURCES_DIR+x} ]; then echo "${VIASH_META_RESOURCES_DIR}" | sed "s#'#'\"'\"'#g;s#.*#meta_resources_dir='&'#" ; else echo "# meta_resources_dir="; fi ) +$( if [ ! -z ${VIASH_META_EXECUTABLE+x} ]; then echo "${VIASH_META_EXECUTABLE}" | sed "s#'#'\"'\"'#g;s#.*#meta_executable='&'#" ; else echo "# meta_executable="; fi ) +$( if [ ! -z ${VIASH_META_CONFIG+x} ]; then echo "${VIASH_META_CONFIG}" | sed "s#'#'\"'\"'#g;s#.*#meta_config='&'#" ; else echo "# meta_config="; fi ) +$( if [ ! -z ${VIASH_META_TEMP_DIR+x} ]; then echo "${VIASH_META_TEMP_DIR}" | sed "s#'#'\"'\"'#g;s#.*#meta_temp_dir='&'#" ; else echo "# meta_temp_dir="; fi ) +$( if [ ! -z ${VIASH_META_CPUS+x} ]; then echo "${VIASH_META_CPUS}" | sed "s#'#'\"'\"'#g;s#.*#meta_cpus='&'#" ; else echo "# meta_cpus="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_B+x} ]; then echo "${VIASH_META_MEMORY_B}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_b='&'#" ; else echo "# meta_memory_b="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_KB+x} ]; then echo "${VIASH_META_MEMORY_KB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_kb='&'#" ; else echo "# meta_memory_kb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_MB+x} ]; then echo "${VIASH_META_MEMORY_MB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_mb='&'#" ; else echo "# meta_memory_mb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_GB+x} ]; then echo "${VIASH_META_MEMORY_GB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_gb='&'#" ; else echo "# meta_memory_gb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_TB+x} ]; then echo "${VIASH_META_MEMORY_TB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_tb='&'#" ; else echo "# meta_memory_tb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_PB+x} ]; then echo "${VIASH_META_MEMORY_PB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_pb='&'#" ; else echo "# meta_memory_pb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_KIB+x} ]; then echo "${VIASH_META_MEMORY_KIB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_kib='&'#" ; else echo "# meta_memory_kib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_MIB+x} ]; then echo "${VIASH_META_MEMORY_MIB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_mib='&'#" ; else echo "# meta_memory_mib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_GIB+x} ]; then echo "${VIASH_META_MEMORY_GIB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_gib='&'#" ; else echo "# meta_memory_gib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_TIB+x} ]; then echo "${VIASH_META_MEMORY_TIB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_tib='&'#" ; else echo "# meta_memory_tib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_pib='&'#" ; else echo "# meta_memory_pib="; fi ) + +## VIASH END + + +# unset flags +[[ "\$par_emblmygff3" == "false" ]] && unset par_emblmygff3 +[[ "\$par_discard" == "false" ]] && unset par_discard +[[ "\$par_keep" == "false" ]] && unset par_keep + +# replace ';' with ',' +par_primary_tag=\$(echo \$par_primary_tag | tr ';' ',') + +# run agat_convert_embl2gff +agat_convert_embl2gff.pl \\ + --embl "\$par_embl" \\ + -o "\$par_output" \\ + \${par_emblmygff3:+--emblmygff3} \\ + \${par_primary_tag:+--primary_tag "\${par_primary_tag}"} \\ + \${par_discard:+-d} \\ + \${par_keep:+-k} \\ + \${par_config:+--config "\${par_config}"} +VIASHMAIN +bash "\$tempscript" & +wait "\$!" + +VIASHEOF + + +if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then + # strip viash automount from file paths + + if [ ! -z "$VIASH_PAR_EMBL" ]; then + VIASH_PAR_EMBL=$(ViashDockerStripAutomount "$VIASH_PAR_EMBL") + fi + if [ ! -z "$VIASH_PAR_OUTPUT" ]; then + VIASH_PAR_OUTPUT=$(ViashDockerStripAutomount "$VIASH_PAR_OUTPUT") + fi + if [ ! -z "$VIASH_PAR_CONFIG" ]; then + VIASH_PAR_CONFIG=$(ViashDockerStripAutomount "$VIASH_PAR_CONFIG") + fi + if [ ! -z "$VIASH_META_RESOURCES_DIR" ]; then + VIASH_META_RESOURCES_DIR=$(ViashDockerStripAutomount "$VIASH_META_RESOURCES_DIR") + fi + if [ ! -z "$VIASH_META_EXECUTABLE" ]; then + VIASH_META_EXECUTABLE=$(ViashDockerStripAutomount "$VIASH_META_EXECUTABLE") + fi + if [ ! -z "$VIASH_META_CONFIG" ]; then + VIASH_META_CONFIG=$(ViashDockerStripAutomount "$VIASH_META_CONFIG") + fi + if [ ! -z "$VIASH_META_TEMP_DIR" ]; then + VIASH_META_TEMP_DIR=$(ViashDockerStripAutomount "$VIASH_META_TEMP_DIR") + fi +fi + + +# check whether required files exist +if [ ! -z "$VIASH_PAR_OUTPUT" ] && [ ! -e "$VIASH_PAR_OUTPUT" ]; then + ViashError "Output file '$VIASH_PAR_OUTPUT' does not exist." + exit 1 +fi + + +exit 0 diff --git a/target/executable/agat/agat_convert_sp_gff2gtf/.config.vsh.yaml b/target/executable/agat/agat_convert_sp_gff2gtf/.config.vsh.yaml index 9a495a00..9450e730 100644 --- a/target/executable/agat/agat_convert_sp_gff2gtf/.config.vsh.yaml +++ b/target/executable/agat/agat_convert_sp_gff2gtf/.config.vsh.yaml @@ -228,7 +228,7 @@ build_info: output: "target/executable/agat/agat_convert_sp_gff2gtf" executable: "target/executable/agat/agat_convert_sp_gff2gtf/agat_convert_sp_gff2gtf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/agat/agat_convert_sp_gff2gtf/agat_convert_sp_gff2gtf b/target/executable/agat/agat_convert_sp_gff2gtf/agat_convert_sp_gff2gtf index d8ddc600..95b2bcd9 100755 --- a/target/executable/agat/agat_convert_sp_gff2gtf/agat_convert_sp_gff2gtf +++ b/target/executable/agat/agat_convert_sp_gff2gtf/agat_convert_sp_gff2gtf @@ -518,9 +518,9 @@ RUN agat --version | sed 's/AGAT\s\(.*\)/agat: "\1"/' > /var/software_versions.t LABEL org.opencontainers.image.authors="Leïla Paquay" LABEL org.opencontainers.image.description="Companion container for running component agat agat_convert_sp_gff2gtf" -LABEL org.opencontainers.image.created="2024-07-31T19:27:40Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:53Z" LABEL org.opencontainers.image.source="https://github.com/NBISweden/AGAT" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER diff --git a/target/executable/agat/agat_convert_sp_gff2tsv/.config.vsh.yaml b/target/executable/agat/agat_convert_sp_gff2tsv/.config.vsh.yaml new file mode 100644 index 00000000..f45d9631 --- /dev/null +++ b/target/executable/agat/agat_convert_sp_gff2tsv/.config.vsh.yaml @@ -0,0 +1,214 @@ +name: "agat_convert_sp_gff2tsv" +namespace: "agat" +version: "main" +authors: +- name: "Leïla Paquay" + roles: + - "author" + - "maintainer" + info: + links: + email: "leila@data-intuitive.com" + github: "Leila011" + linkedin: "leilapaquay" + organizations: + - name: "Data Intuitive" + href: "https://www.data-intuitive.com" + role: "Software Developer" +argument_groups: +- name: "Inputs" + arguments: + - type: "file" + name: "--gff" + alternatives: + - "-f" + description: "Input GTF/GFF file." + info: null + example: + - "input.gff" + must_exist: true + create_parent: true + required: true + direction: "input" + multiple: false + multiple_sep: ";" +- name: "Outputs" + arguments: + - type: "file" + name: "--output" + alternatives: + - "-o" + - "--out" + - "--outfile" + description: "Output GFF file. If no output file is specified, the output will\ + \ be written to STDOUT." + info: null + example: + - "output.gff" + must_exist: true + create_parent: true + required: true + direction: "output" + multiple: false + multiple_sep: ";" +- name: "Arguments" + arguments: + - type: "file" + name: "--config" + alternatives: + - "-c" + description: "String - Input agat config file. By default AGAT takes as input\n\ + agat_config.yaml file from the working directory if any,\notherwise it takes\ + \ the orignal agat_config.yaml shipped with\nAGAT. To get the agat_config.yaml\ + \ locally type: \"agat config\n--expose\". The --config option gives you the\ + \ possibility to use\nyour own AGAT config file (located elsewhere or named\n\ + differently). \n" + info: null + example: + - "custom_agat_config.yaml" + must_exist: true + create_parent: true + required: false + direction: "input" + multiple: false + multiple_sep: ";" +resources: +- type: "bash_script" + path: "script.sh" + is_executable: true +description: "The script aims to convert gtf/gff file into tabulated file. Attribute's\n\ + tags from the 9th column become column titles.\n" +test_resources: +- type: "bash_script" + path: "test.sh" + is_executable: true +- type: "file" + path: "test_data" +info: null +status: "enabled" +requirements: + commands: + - "ps" +keywords: +- "gene annotations" +- "GFF conversion" +license: "GPL-3.0" +references: + doi: + - "10.5281/zenodo.3552717" +links: + repository: "https://github.com/NBISweden/AGAT" + homepage: "https://github.com/NBISweden/AGAT" + documentation: "https://agat.readthedocs.io/en/latest/tools/agat_convert_sp_gff2tsv.html" + issue_tracker: "https://github.com/NBISweden/AGAT/issues" +runners: +- type: "executable" + id: "executable" + docker_setup_strategy: "ifneedbepullelsecachedbuild" +- type: "nextflow" + id: "nextflow" + directives: + tag: "$id" + auto: + simplifyInput: true + simplifyOutput: false + transcript: false + publish: false + config: + labels: + mem1gb: "memory = 1000000000.B" + mem2gb: "memory = 2000000000.B" + mem5gb: "memory = 5000000000.B" + mem10gb: "memory = 10000000000.B" + mem20gb: "memory = 20000000000.B" + mem50gb: "memory = 50000000000.B" + mem100gb: "memory = 100000000000.B" + mem200gb: "memory = 200000000000.B" + mem500gb: "memory = 500000000000.B" + mem1tb: "memory = 1000000000000.B" + mem2tb: "memory = 2000000000000.B" + mem5tb: "memory = 5000000000000.B" + mem10tb: "memory = 10000000000000.B" + mem20tb: "memory = 20000000000000.B" + mem50tb: "memory = 50000000000000.B" + mem100tb: "memory = 100000000000000.B" + mem200tb: "memory = 200000000000000.B" + mem500tb: "memory = 500000000000000.B" + mem1gib: "memory = 1073741824.B" + mem2gib: "memory = 2147483648.B" + mem4gib: "memory = 4294967296.B" + mem8gib: "memory = 8589934592.B" + mem16gib: "memory = 17179869184.B" + mem32gib: "memory = 34359738368.B" + mem64gib: "memory = 68719476736.B" + mem128gib: "memory = 137438953472.B" + mem256gib: "memory = 274877906944.B" + mem512gib: "memory = 549755813888.B" + mem1tib: "memory = 1099511627776.B" + mem2tib: "memory = 2199023255552.B" + mem4tib: "memory = 4398046511104.B" + mem8tib: "memory = 8796093022208.B" + mem16tib: "memory = 17592186044416.B" + mem32tib: "memory = 35184372088832.B" + mem64tib: "memory = 70368744177664.B" + mem128tib: "memory = 140737488355328.B" + mem256tib: "memory = 281474976710656.B" + mem512tib: "memory = 562949953421312.B" + cpu1: "cpus = 1" + cpu2: "cpus = 2" + cpu5: "cpus = 5" + cpu10: "cpus = 10" + cpu20: "cpus = 20" + cpu50: "cpus = 50" + cpu100: "cpus = 100" + cpu200: "cpus = 200" + cpu500: "cpus = 500" + cpu1000: "cpus = 1000" + debug: false + container: "docker" +engines: +- type: "docker" + id: "docker" + image: "quay.io/biocontainers/agat:1.4.0--pl5321hdfd78af_0" + target_registry: "images.viash-hub.com" + target_tag: "main" + namespace_separator: "/" + setup: + - type: "docker" + run: + - "agat --version | sed 's/AGAT\\s\\(.*\\)/agat: \"\\1\"/' > /var/software_versions.txt\n" + entrypoint: [] + cmd: null +- type: "native" + id: "native" +build_info: + config: "src/agat/agat_convert_sp_gff2tsv/config.vsh.yaml" + runner: "executable" + engine: "docker|native" + output: "target/executable/agat/agat_convert_sp_gff2tsv" + executable: "target/executable/agat/agat_convert_sp_gff2tsv/agat_convert_sp_gff2tsv" + viash_version: "0.9.0-RC6" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" + git_remote: "https://github.com/viash-hub/biobox" +package_config: + name: "biobox" + version: "main" + description: "A collection of bioinformatics tools for working with sequence data.\n" + info: null + viash_version: "0.9.0-RC6" + source: "src" + target: "target" + config_mods: + - ".requirements.commands := ['ps']\n" + - ".engines += { type: \"native\" }" + - ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'" + - ".engines[.type == 'docker'].target_tag := 'main'" + keywords: + - "bioinformatics" + - "modules" + - "sequencing" + license: "MIT" + organization: "vsh" + links: + repository: "https://github.com/viash-hub/biobox" + issue_tracker: "https://github.com/viash-hub/biobox/issues" diff --git a/target/executable/agat/agat_convert_sp_gff2tsv/agat_convert_sp_gff2tsv b/target/executable/agat/agat_convert_sp_gff2tsv/agat_convert_sp_gff2tsv new file mode 100755 index 00000000..287f7cb8 --- /dev/null +++ b/target/executable/agat/agat_convert_sp_gff2tsv/agat_convert_sp_gff2tsv @@ -0,0 +1,1121 @@ +#!/usr/bin/env bash + +# agat_convert_sp_gff2tsv main +# +# This wrapper script is auto-generated by viash 0.9.0-RC6 and is thus a +# derivative work thereof. This software comes with ABSOLUTELY NO WARRANTY from +# Data Intuitive. +# +# The component may contain files which fall under a different license. The +# authors of this component should specify the license in the header of such +# files, or include a separate license file detailing the licenses of all included +# files. +# +# Component authors: +# * Leïla Paquay (author, maintainer) + +set -e + +if [ -z "$VIASH_TEMP" ]; then + VIASH_TEMP=${VIASH_TEMP:-$VIASH_TMPDIR} + VIASH_TEMP=${VIASH_TEMP:-$VIASH_TEMPDIR} + VIASH_TEMP=${VIASH_TEMP:-$VIASH_TMP} + VIASH_TEMP=${VIASH_TEMP:-$TMPDIR} + VIASH_TEMP=${VIASH_TEMP:-$TMP} + VIASH_TEMP=${VIASH_TEMP:-$TEMPDIR} + VIASH_TEMP=${VIASH_TEMP:-$TEMP} + VIASH_TEMP=${VIASH_TEMP:-/tmp} +fi + +# define helper functions +# ViashQuote: put quotes around non flag values +# $1 : unquoted string +# return : possibly quoted string +# examples: +# ViashQuote --foo # returns --foo +# ViashQuote bar # returns 'bar' +# Viashquote --foo=bar # returns --foo='bar' +function ViashQuote { + if [[ "$1" =~ ^-+[a-zA-Z0-9_\-]+=.+$ ]]; then + echo "$1" | sed "s#=\(.*\)#='\1'#" + elif [[ "$1" =~ ^-+[a-zA-Z0-9_\-]+$ ]]; then + echo "$1" + else + echo "'$1'" + fi +} +# ViashRemoveFlags: Remove leading flag +# $1 : string with a possible leading flag +# return : string without possible leading flag +# examples: +# ViashRemoveFlags --foo=bar # returns bar +function ViashRemoveFlags { + echo "$1" | sed 's/^--*[a-zA-Z0-9_\-]*=//' +} +# ViashSourceDir: return the path of a bash file, following symlinks +# usage : ViashSourceDir ${BASH_SOURCE[0]} +# $1 : Should always be set to ${BASH_SOURCE[0]} +# returns : The absolute path of the bash file +function ViashSourceDir { + SOURCE="$1" + while [ -h "$SOURCE" ]; do + DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )" + SOURCE="$(readlink "$SOURCE")" + [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" + done + cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd +} +# ViashFindTargetDir: return the path of the '.build.yaml' file, following symlinks +# usage : ViashFindTargetDir 'ScriptPath' +# $1 : The location from where to start the upward search +# returns : The absolute path of the '.build.yaml' file +function ViashFindTargetDir { + SOURCE="$1" + while [[ "$SOURCE" != "" && ! -e "$SOURCE/.build.yaml" ]]; do + SOURCE=${SOURCE%/*} + done + echo $SOURCE +} +# see https://en.wikipedia.org/wiki/Syslog#Severity_level +VIASH_LOGCODE_EMERGENCY=0 +VIASH_LOGCODE_ALERT=1 +VIASH_LOGCODE_CRITICAL=2 +VIASH_LOGCODE_ERROR=3 +VIASH_LOGCODE_WARNING=4 +VIASH_LOGCODE_NOTICE=5 +VIASH_LOGCODE_INFO=6 +VIASH_LOGCODE_DEBUG=7 +VIASH_VERBOSITY=$VIASH_LOGCODE_NOTICE + +# ViashLog: Log events depending on the verbosity level +# usage: ViashLog 1 alert Oh no something went wrong! +# $1: required verbosity level +# $2: display tag +# $3+: messages to display +# stdout: Your input, prepended by '[$2] '. +function ViashLog { + local required_level="$1" + local display_tag="$2" + shift 2 + if [ $VIASH_VERBOSITY -ge $required_level ]; then + >&2 echo "[$display_tag]" "$@" + fi +} + +# ViashEmergency: log events when the system is unstable +# usage: ViashEmergency Oh no something went wrong. +# stdout: Your input, prepended by '[emergency] '. +function ViashEmergency { + ViashLog $VIASH_LOGCODE_EMERGENCY emergency "$@" +} + +# ViashAlert: log events when actions must be taken immediately (e.g. corrupted system database) +# usage: ViashAlert Oh no something went wrong. +# stdout: Your input, prepended by '[alert] '. +function ViashAlert { + ViashLog $VIASH_LOGCODE_ALERT alert "$@" +} + +# ViashCritical: log events when a critical condition occurs +# usage: ViashCritical Oh no something went wrong. +# stdout: Your input, prepended by '[critical] '. +function ViashCritical { + ViashLog $VIASH_LOGCODE_CRITICAL critical "$@" +} + +# ViashError: log events when an error condition occurs +# usage: ViashError Oh no something went wrong. +# stdout: Your input, prepended by '[error] '. +function ViashError { + ViashLog $VIASH_LOGCODE_ERROR error "$@" +} + +# ViashWarning: log potentially abnormal events +# usage: ViashWarning Something may have gone wrong. +# stdout: Your input, prepended by '[warning] '. +function ViashWarning { + ViashLog $VIASH_LOGCODE_WARNING warning "$@" +} + +# ViashNotice: log significant but normal events +# usage: ViashNotice This just happened. +# stdout: Your input, prepended by '[notice] '. +function ViashNotice { + ViashLog $VIASH_LOGCODE_NOTICE notice "$@" +} + +# ViashInfo: log normal events +# usage: ViashInfo This just happened. +# stdout: Your input, prepended by '[info] '. +function ViashInfo { + ViashLog $VIASH_LOGCODE_INFO info "$@" +} + +# ViashDebug: log all events, for debugging purposes +# usage: ViashDebug This just happened. +# stdout: Your input, prepended by '[debug] '. +function ViashDebug { + ViashLog $VIASH_LOGCODE_DEBUG debug "$@" +} + +# find source folder of this component +VIASH_META_RESOURCES_DIR=`ViashSourceDir ${BASH_SOURCE[0]}` + +# find the root of the built components & dependencies +VIASH_TARGET_DIR=`ViashFindTargetDir $VIASH_META_RESOURCES_DIR` + +# define meta fields +VIASH_META_NAME="agat_convert_sp_gff2tsv" +VIASH_META_FUNCTIONALITY_NAME="agat_convert_sp_gff2tsv" +VIASH_META_EXECUTABLE="$VIASH_META_RESOURCES_DIR/$VIASH_META_NAME" +VIASH_META_CONFIG="$VIASH_META_RESOURCES_DIR/.config.vsh.yaml" +VIASH_META_TEMP_DIR="$VIASH_TEMP" + + +# ViashHelp: Display helpful explanation about this executable +function ViashHelp { + echo "agat_convert_sp_gff2tsv main" + echo "" + echo "The script aims to convert gtf/gff file into tabulated file. Attribute's" + echo "tags from the 9th column become column titles." + echo "" + echo "Inputs:" + echo " -f, --gff" + echo " type: file, required parameter, file must exist" + echo " example: input.gff" + echo " Input GTF/GFF file." + echo "" + echo "Outputs:" + echo " -o, --out, --outfile, --output" + echo " type: file, required parameter, output, file must exist" + echo " example: output.gff" + echo " Output GFF file. If no output file is specified, the output will be" + echo " written to STDOUT." + echo "" + echo "Arguments:" + echo " -c, --config" + echo " type: file, file must exist" + echo " example: custom_agat_config.yaml" + echo " String - Input agat config file. By default AGAT takes as input" + echo " agat_config.yaml file from the working directory if any," + echo " otherwise it takes the orignal agat_config.yaml shipped with" + echo " AGAT. To get the agat_config.yaml locally type: \"agat config" + echo " --expose\". The --config option gives you the possibility to use" + echo " your own AGAT config file (located elsewhere or named" + echo " differently)." +} + +# initialise variables +VIASH_MODE='run' +VIASH_ENGINE_ID='docker' + +######## Helper functions for setting up Docker images for viash ######## +# expects: ViashDockerBuild + +# ViashDockerInstallationCheck: check whether Docker is installed correctly +# +# examples: +# ViashDockerInstallationCheck +function ViashDockerInstallationCheck { + ViashDebug "Checking whether Docker is installed" + if [ ! command -v docker &> /dev/null ]; then + ViashCritical "Docker doesn't seem to be installed. See 'https://docs.docker.com/get-docker/' for instructions." + exit 1 + fi + + ViashDebug "Checking whether the Docker daemon is running" + save=$-; set +e + docker_version=$(docker version --format '{{.Client.APIVersion}}' 2> /dev/null) + out=$? + [[ $save =~ e ]] && set -e + if [ $out -ne 0 ]; then + ViashCritical "Docker daemon does not seem to be running. Try one of the following:" + ViashCritical "- Try running 'dockerd' in the command line" + ViashCritical "- See https://docs.docker.com/config/daemon/" + exit 1 + fi +} + +# ViashDockerRemoteTagCheck: check whether a Docker image is available +# on a remote. Assumes `docker login` has been performed, if relevant. +# +# $1 : image identifier with format `[registry/]image[:tag]` +# exit code $? : whether or not the image was found +# examples: +# ViashDockerRemoteTagCheck python:latest +# echo $? # returns '0' +# ViashDockerRemoteTagCheck sdaizudceahifu +# echo $? # returns '1' +function ViashDockerRemoteTagCheck { + docker manifest inspect $1 > /dev/null 2> /dev/null +} + +# ViashDockerLocalTagCheck: check whether a Docker image is available locally +# +# $1 : image identifier with format `[registry/]image[:tag]` +# exit code $? : whether or not the image was found +# examples: +# docker pull python:latest +# ViashDockerLocalTagCheck python:latest +# echo $? # returns '0' +# ViashDockerLocalTagCheck sdaizudceahifu +# echo $? # returns '1' +function ViashDockerLocalTagCheck { + [ -n "$(docker images -q $1)" ] +} + +# ViashDockerPull: pull a Docker image +# +# $1 : image identifier with format `[registry/]image[:tag]` +# exit code $? : whether or not the image was found +# examples: +# ViashDockerPull python:latest +# echo $? # returns '0' +# ViashDockerPull sdaizudceahifu +# echo $? # returns '1' +function ViashDockerPull { + ViashNotice "Checking if Docker image is available at '$1'" + if [ $VIASH_VERBOSITY -ge $VIASH_LOGCODE_INFO ]; then + docker pull $1 && return 0 || return 1 + else + save=$-; set +e + docker pull $1 2> /dev/null > /dev/null + out=$? + [[ $save =~ e ]] && set -e + if [ $out -ne 0 ]; then + ViashWarning "Could not pull from '$1'. Docker image doesn't exist or is not accessible." + fi + return $out + fi +} + +# ViashDockerPush: push a Docker image +# +# $1 : image identifier with format `[registry/]image[:tag]` +# exit code $? : whether or not the image was found +# examples: +# ViashDockerPush python:latest +# echo $? # returns '0' +# ViashDockerPush sdaizudceahifu +# echo $? # returns '1' +function ViashDockerPush { + ViashNotice "Pushing image to '$1'" + save=$-; set +e + if [ $VIASH_VERBOSITY -ge $VIASH_LOGCODE_INFO ]; then + docker push $1 + out=$? + else + docker push $1 2> /dev/null > /dev/null + out=$? + fi + [[ $save =~ e ]] && set -e + if [ $out -eq 0 ]; then + ViashNotice "Container '$1' push succeeded." + else + ViashError "Container '$1' push errored. You might not be logged in or have the necessary permissions." + fi + return $out +} + +# ViashDockerPullElseBuild: pull a Docker image, else build it +# +# $1 : image identifier with format `[registry/]image[:tag]` +# ViashDockerBuild : a Bash function which builds a docker image, takes image identifier as argument. +# examples: +# ViashDockerPullElseBuild mynewcomponent +function ViashDockerPullElseBuild { + save=$-; set +e + ViashDockerPull $1 + out=$? + [[ $save =~ e ]] && set -e + if [ $out -ne 0 ]; then + ViashDockerBuild $@ + fi +} + +# ViashDockerSetup: create a Docker image, according to specified docker setup strategy +# +# $1 : image identifier with format `[registry/]image[:tag]` +# $2 : docker setup strategy, see DockerSetupStrategy.scala +# examples: +# ViashDockerSetup mynewcomponent alwaysbuild +function ViashDockerSetup { + local image_id="$1" + local setup_strategy="$2" + if [ "$setup_strategy" == "alwaysbuild" -o "$setup_strategy" == "build" -o "$setup_strategy" == "b" ]; then + ViashDockerBuild $image_id --no-cache $(ViashDockerBuildArgs "$engine_id") + elif [ "$setup_strategy" == "alwayspull" -o "$setup_strategy" == "pull" -o "$setup_strategy" == "p" ]; then + ViashDockerPull $image_id + elif [ "$setup_strategy" == "alwayspullelsebuild" -o "$setup_strategy" == "pullelsebuild" ]; then + ViashDockerPullElseBuild $image_id --no-cache $(ViashDockerBuildArgs "$engine_id") + elif [ "$setup_strategy" == "alwayspullelsecachedbuild" -o "$setup_strategy" == "pullelsecachedbuild" ]; then + ViashDockerPullElseBuild $image_id $(ViashDockerBuildArgs "$engine_id") + elif [ "$setup_strategy" == "alwayscachedbuild" -o "$setup_strategy" == "cachedbuild" -o "$setup_strategy" == "cb" ]; then + ViashDockerBuild $image_id $(ViashDockerBuildArgs "$engine_id") + elif [[ "$setup_strategy" =~ ^ifneedbe ]]; then + local save=$-; set +e + ViashDockerLocalTagCheck $image_id + local outCheck=$? + [[ $save =~ e ]] && set -e + if [ $outCheck -eq 0 ]; then + ViashInfo "Image $image_id already exists" + elif [ "$setup_strategy" == "ifneedbebuild" ]; then + ViashDockerBuild $image_id --no-cache $(ViashDockerBuildArgs "$engine_id") + elif [ "$setup_strategy" == "ifneedbecachedbuild" ]; then + ViashDockerBuild $image_id $(ViashDockerBuildArgs "$engine_id") + elif [ "$setup_strategy" == "ifneedbepull" ]; then + ViashDockerPull $image_id + elif [ "$setup_strategy" == "ifneedbepullelsebuild" ]; then + ViashDockerPullElseBuild $image_id --no-cache $(ViashDockerBuildArgs "$engine_id") + elif [ "$setup_strategy" == "ifneedbepullelsecachedbuild" ]; then + ViashDockerPullElseBuild $image_id $(ViashDockerBuildArgs "$engine_id") + else + ViashError "Unrecognised Docker strategy: $setup_strategy" + exit 1 + fi + elif [ "$setup_strategy" == "push" -o "$setup_strategy" == "forcepush" -o "$setup_strategy" == "alwayspush" ]; then + ViashDockerPush "$image_id" + elif [ "$setup_strategy" == "pushifnotpresent" -o "$setup_strategy" == "gentlepush" -o "$setup_strategy" == "maybepush" ]; then + local save=$-; set +e + ViashDockerRemoteTagCheck $image_id + local outCheck=$? + [[ $save =~ e ]] && set -e + if [ $outCheck -eq 0 ]; then + ViashNotice "Container '$image_id' exists, doing nothing." + else + ViashNotice "Container '$image_id' does not yet exist." + ViashDockerPush "$image_id" + fi + elif [ "$setup_strategy" == "donothing" -o "$setup_strategy" == "meh" ]; then + ViashNotice "Skipping setup." + else + ViashError "Unrecognised Docker strategy: $setup_strategy" + exit 1 + fi +} + +# ViashDockerCheckCommands: Check whether a docker container has the required commands +# +# $1 : image identifier with format `[registry/]image[:tag]` +# $@ : commands to verify being present +# examples: +# ViashDockerCheckCommands bash:4.0 bash ps foo +function ViashDockerCheckCommands { + local image_id="$1" + shift 1 + local commands="$@" + local save=$-; set +e + local missing # mark 'missing' as local in advance, otherwise the exit code of the command will be missing and always be '0' + missing=$(docker run --rm --entrypoint=sh "$image_id" -c "for command in $commands; do command -v \$command >/dev/null 2>&1; if [ \$? -ne 0 ]; then echo \$command; exit 1; fi; done") + local outCheck=$? + [[ $save =~ e ]] && set -e + if [ $outCheck -ne 0 ]; then + ViashError "Docker container '$image_id' does not contain command '$missing'." + exit 1 + fi +} + +# ViashDockerBuild: build a docker image +# $1 : image identifier with format `[registry/]image[:tag]` +# $... : additional arguments to pass to docker build +# $VIASH_META_TEMP_DIR : temporary directory to store dockerfile & optional resources in +# $VIASH_META_NAME : name of the component +# $VIASH_META_RESOURCES_DIR : directory containing the resources +# $VIASH_VERBOSITY : verbosity level +# exit code $? : whether or not the image was built successfully +function ViashDockerBuild { + local image_id="$1" + shift 1 + + # create temporary directory to store dockerfile & optional resources in + local tmpdir=$(mktemp -d "$VIASH_META_TEMP_DIR/dockerbuild-$VIASH_META_NAME-XXXXXX") + local dockerfile="$tmpdir/Dockerfile" + function clean_up { + rm -rf "$tmpdir" + } + trap clean_up EXIT + + # store dockerfile and resources + ViashDockerfile "$VIASH_ENGINE_ID" > "$dockerfile" + + # generate the build command + local docker_build_cmd="docker build -t '$image_id' $@ '$VIASH_META_RESOURCES_DIR' -f '$dockerfile'" + + # build the container + ViashNotice "Building container '$image_id' with Dockerfile" + ViashInfo "$docker_build_cmd" + local save=$-; set +e + if [ $VIASH_VERBOSITY -ge $VIASH_LOGCODE_INFO ]; then + eval $docker_build_cmd + else + eval $docker_build_cmd &> "$tmpdir/docker_build.log" + fi + + # check exit code + local out=$? + [[ $save =~ e ]] && set -e + if [ $out -ne 0 ]; then + ViashError "Error occurred while building container '$image_id'" + if [ $VIASH_VERBOSITY -lt $VIASH_LOGCODE_INFO ]; then + ViashError "Transcript: --------------------------------" + cat "$tmpdir/docker_build.log" + ViashError "End of transcript --------------------------" + fi + exit 1 + fi +} + +######## End of helper functions for setting up Docker images for viash ######## + +# ViashDockerFile: print the dockerfile to stdout +# $1 : engine identifier +# return : dockerfile required to run this component +# examples: +# ViashDockerFile +function ViashDockerfile { + local engine_id="$1" + + if [[ "$engine_id" == "docker" ]]; then + cat << 'VIASHDOCKER' +FROM quay.io/biocontainers/agat:1.4.0--pl5321hdfd78af_0 +ENTRYPOINT [] +RUN agat --version | sed 's/AGAT\s\(.*\)/agat: "\1"/' > /var/software_versions.txt + +LABEL org.opencontainers.image.authors="Leïla Paquay" +LABEL org.opencontainers.image.description="Companion container for running component agat agat_convert_sp_gff2tsv" +LABEL org.opencontainers.image.created="2024-08-14T20:58:52Z" +LABEL org.opencontainers.image.source="https://github.com/NBISweden/AGAT" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" +LABEL org.opencontainers.image.version="main" + +VIASHDOCKER + fi +} + +# ViashDockerBuildArgs: return the arguments to pass to docker build +# $1 : engine identifier +# return : arguments to pass to docker build +function ViashDockerBuildArgs { + local engine_id="$1" + + if [[ "$engine_id" == "docker" ]]; then + echo "" + fi +} + +# ViashAbsolutePath: generate absolute path from relative path +# borrowed from https://stackoverflow.com/a/21951256 +# $1 : relative filename +# return : absolute path +# examples: +# ViashAbsolutePath some_file.txt # returns /path/to/some_file.txt +# ViashAbsolutePath /foo/bar/.. # returns /foo +function ViashAbsolutePath { + local thePath + if [[ ! "$1" =~ ^/ ]]; then + thePath="$PWD/$1" + else + thePath="$1" + fi + echo "$thePath" | ( + IFS=/ + read -a parr + declare -a outp + for i in "${parr[@]}"; do + case "$i" in + ''|.) continue ;; + ..) + len=${#outp[@]} + if ((len==0)); then + continue + else + unset outp[$((len-1))] + fi + ;; + *) + len=${#outp[@]} + outp[$len]="$i" + ;; + esac + done + echo /"${outp[*]}" + ) +} +# ViashDockerAutodetectMount: auto configuring docker mounts from parameters +# $1 : The parameter value +# returns : New parameter +# $VIASH_DIRECTORY_MOUNTS : Added another parameter to be passed to docker +# examples: +# ViashDockerAutodetectMount /path/to/bar # returns '/viash_automount/path/to/bar' +# ViashDockerAutodetectMountArg /path/to/bar # returns '--volume="/path/to:/viash_automount/path/to"' +function ViashDockerAutodetectMount { + abs_path=$(ViashAbsolutePath "$1") + if [ -d "$abs_path" ]; then + mount_source="$abs_path" + base_name="" + else + mount_source=`dirname "$abs_path"` + base_name=`basename "$abs_path"` + fi + mount_target="/viash_automount$mount_source" + if [ -z "$base_name" ]; then + echo "$mount_target" + else + echo "$mount_target/$base_name" + fi +} +function ViashDockerAutodetectMountArg { + abs_path=$(ViashAbsolutePath "$1") + if [ -d "$abs_path" ]; then + mount_source="$abs_path" + base_name="" + else + mount_source=`dirname "$abs_path"` + base_name=`basename "$abs_path"` + fi + mount_target="/viash_automount$mount_source" + ViashDebug "ViashDockerAutodetectMountArg $1 -> $mount_source -> $mount_target" + echo "--volume=\"$mount_source:$mount_target\"" +} +function ViashDockerStripAutomount { + abs_path=$(ViashAbsolutePath "$1") + echo "${abs_path#/viash_automount}" +} +# initialise variables +VIASH_DIRECTORY_MOUNTS=() + +# initialise docker variables +VIASH_DOCKER_RUN_ARGS=(-i --rm) + +# initialise array +VIASH_POSITIONAL_ARGS='' + +while [[ $# -gt 0 ]]; do + case "$1" in + -h|--help) + ViashHelp + exit + ;; + ---v|---verbose) + let "VIASH_VERBOSITY=VIASH_VERBOSITY+1" + shift 1 + ;; + ---verbosity) + VIASH_VERBOSITY="$2" + shift 2 + ;; + ---verbosity=*) + VIASH_VERBOSITY="$(ViashRemoveFlags "$1")" + shift 1 + ;; + --version) + echo "agat_convert_sp_gff2tsv main" + exit + ;; + --gff) + [ -n "$VIASH_PAR_GFF" ] && ViashError Bad arguments for option \'--gff\': \'$VIASH_PAR_GFF\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_GFF="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to --gff. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --gff=*) + [ -n "$VIASH_PAR_GFF" ] && ViashError Bad arguments for option \'--gff=*\': \'$VIASH_PAR_GFF\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_GFF=$(ViashRemoveFlags "$1") + shift 1 + ;; + -f) + [ -n "$VIASH_PAR_GFF" ] && ViashError Bad arguments for option \'-f\': \'$VIASH_PAR_GFF\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_GFF="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to -f. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --output) + [ -n "$VIASH_PAR_OUTPUT" ] && ViashError Bad arguments for option \'--output\': \'$VIASH_PAR_OUTPUT\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_OUTPUT="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to --output. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --output=*) + [ -n "$VIASH_PAR_OUTPUT" ] && ViashError Bad arguments for option \'--output=*\': \'$VIASH_PAR_OUTPUT\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_OUTPUT=$(ViashRemoveFlags "$1") + shift 1 + ;; + -o) + [ -n "$VIASH_PAR_OUTPUT" ] && ViashError Bad arguments for option \'-o\': \'$VIASH_PAR_OUTPUT\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_OUTPUT="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to -o. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --out) + [ -n "$VIASH_PAR_OUTPUT" ] && ViashError Bad arguments for option \'--out\': \'$VIASH_PAR_OUTPUT\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_OUTPUT="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to --out. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --outfile) + [ -n "$VIASH_PAR_OUTPUT" ] && ViashError Bad arguments for option \'--outfile\': \'$VIASH_PAR_OUTPUT\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_OUTPUT="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to --outfile. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --config) + [ -n "$VIASH_PAR_CONFIG" ] && ViashError Bad arguments for option \'--config\': \'$VIASH_PAR_CONFIG\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_CONFIG="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to --config. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --config=*) + [ -n "$VIASH_PAR_CONFIG" ] && ViashError Bad arguments for option \'--config=*\': \'$VIASH_PAR_CONFIG\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_CONFIG=$(ViashRemoveFlags "$1") + shift 1 + ;; + -c) + [ -n "$VIASH_PAR_CONFIG" ] && ViashError Bad arguments for option \'-c\': \'$VIASH_PAR_CONFIG\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_CONFIG="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to -c. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + ---engine) + VIASH_ENGINE_ID="$2" + shift 2 + ;; + ---engine=*) + VIASH_ENGINE_ID="$(ViashRemoveFlags "$1")" + shift 1 + ;; + ---setup) + VIASH_MODE='setup' + VIASH_SETUP_STRATEGY="$2" + shift 2 + ;; + ---setup=*) + VIASH_MODE='setup' + VIASH_SETUP_STRATEGY="$(ViashRemoveFlags "$1")" + shift 1 + ;; + ---dockerfile) + VIASH_MODE='dockerfile' + shift 1 + ;; + ---debug) + VIASH_MODE='debug' + shift 1 + ;; + ---cpus) + [ -n "$VIASH_META_CPUS" ] && ViashError Bad arguments for option \'---cpus\': \'$VIASH_META_CPUS\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_META_CPUS="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to ---cpus. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + ---cpus=*) + [ -n "$VIASH_META_CPUS" ] && ViashError Bad arguments for option \'---cpus=*\': \'$VIASH_META_CPUS\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_META_CPUS=$(ViashRemoveFlags "$1") + shift 1 + ;; + ---memory) + [ -n "$VIASH_META_MEMORY" ] && ViashError Bad arguments for option \'---memory\': \'$VIASH_META_MEMORY\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_META_MEMORY="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to ---memory. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + ---memory=*) + [ -n "$VIASH_META_MEMORY" ] && ViashError Bad arguments for option \'---memory=*\': \'$VIASH_META_MEMORY\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_META_MEMORY=$(ViashRemoveFlags "$1") + shift 1 + ;; + *) # positional arg or unknown option + # since the positional args will be eval'd, can we always quote, instead of using ViashQuote + VIASH_POSITIONAL_ARGS="$VIASH_POSITIONAL_ARGS '$1'" + [[ $1 == -* ]] && ViashWarning $1 looks like a parameter but is not a defined parameter and will instead be treated as a positional argument. Use "--help" to get more information on the parameters. + shift # past argument + ;; + esac +done + +# parse positional parameters +eval set -- $VIASH_POSITIONAL_ARGS + + +if [ "$VIASH_ENGINE_ID" == "native" ] ; then + VIASH_ENGINE_TYPE='native' +elif [ "$VIASH_ENGINE_ID" == "docker" ] ; then + VIASH_ENGINE_TYPE='docker' +else + ViashError "Engine '$VIASH_ENGINE_ID' is not recognized. Options are: docker, native." + exit 1 +fi + +if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then + # check if docker is installed properly + ViashDockerInstallationCheck + + # determine docker image id + if [[ "$VIASH_ENGINE_ID" == 'docker' ]]; then + VIASH_DOCKER_IMAGE_ID='images.viash-hub.com/vsh/biobox/agat/agat_convert_sp_gff2tsv:main' + fi + + # print dockerfile + if [ "$VIASH_MODE" == "dockerfile" ]; then + ViashDockerfile "$VIASH_ENGINE_ID" + exit 0 + + # enter docker container + elif [[ "$VIASH_MODE" == "debug" ]]; then + VIASH_CMD="docker run --entrypoint=bash ${VIASH_DOCKER_RUN_ARGS[@]} -v '$(pwd)':/pwd --workdir /pwd -t $VIASH_DOCKER_IMAGE_ID" + ViashNotice "+ $VIASH_CMD" + eval $VIASH_CMD + exit + + # build docker image + elif [ "$VIASH_MODE" == "setup" ]; then + ViashDockerSetup "$VIASH_DOCKER_IMAGE_ID" "$VIASH_SETUP_STRATEGY" + ViashDockerCheckCommands "$VIASH_DOCKER_IMAGE_ID" 'ps' 'bash' + exit 0 + fi + + # check if docker image exists + ViashDockerSetup "$VIASH_DOCKER_IMAGE_ID" ifneedbepullelsecachedbuild + ViashDockerCheckCommands "$VIASH_DOCKER_IMAGE_ID" 'ps' 'bash' +fi + +# setting computational defaults + +# helper function for parsing memory strings +function ViashMemoryAsBytes { + local memory=`echo "$1" | tr '[:upper:]' '[:lower:]' | tr -d '[:space:]'` + local memory_regex='^([0-9]+)([kmgtp]i?b?|b)$' + if [[ $memory =~ $memory_regex ]]; then + local number=${memory/[^0-9]*/} + local symbol=${memory/*[0-9]/} + + case $symbol in + b) memory_b=$number ;; + kb|k) memory_b=$(( $number * 1000 )) ;; + mb|m) memory_b=$(( $number * 1000 * 1000 )) ;; + gb|g) memory_b=$(( $number * 1000 * 1000 * 1000 )) ;; + tb|t) memory_b=$(( $number * 1000 * 1000 * 1000 * 1000 )) ;; + pb|p) memory_b=$(( $number * 1000 * 1000 * 1000 * 1000 * 1000 )) ;; + kib|ki) memory_b=$(( $number * 1024 )) ;; + mib|mi) memory_b=$(( $number * 1024 * 1024 )) ;; + gib|gi) memory_b=$(( $number * 1024 * 1024 * 1024 )) ;; + tib|ti) memory_b=$(( $number * 1024 * 1024 * 1024 * 1024 )) ;; + pib|pi) memory_b=$(( $number * 1024 * 1024 * 1024 * 1024 * 1024 )) ;; + esac + echo "$memory_b" + fi +} +# compute memory in different units +if [ ! -z ${VIASH_META_MEMORY+x} ]; then + VIASH_META_MEMORY_B=`ViashMemoryAsBytes $VIASH_META_MEMORY` + # do not define other variables if memory_b is an empty string + if [ ! -z "$VIASH_META_MEMORY_B" ]; then + VIASH_META_MEMORY_KB=$(( ($VIASH_META_MEMORY_B+999) / 1000 )) + VIASH_META_MEMORY_MB=$(( ($VIASH_META_MEMORY_KB+999) / 1000 )) + VIASH_META_MEMORY_GB=$(( ($VIASH_META_MEMORY_MB+999) / 1000 )) + VIASH_META_MEMORY_TB=$(( ($VIASH_META_MEMORY_GB+999) / 1000 )) + VIASH_META_MEMORY_PB=$(( ($VIASH_META_MEMORY_TB+999) / 1000 )) + VIASH_META_MEMORY_KIB=$(( ($VIASH_META_MEMORY_B+1023) / 1024 )) + VIASH_META_MEMORY_MIB=$(( ($VIASH_META_MEMORY_KIB+1023) / 1024 )) + VIASH_META_MEMORY_GIB=$(( ($VIASH_META_MEMORY_MIB+1023) / 1024 )) + VIASH_META_MEMORY_TIB=$(( ($VIASH_META_MEMORY_GIB+1023) / 1024 )) + VIASH_META_MEMORY_PIB=$(( ($VIASH_META_MEMORY_TIB+1023) / 1024 )) + else + # unset memory if string is empty + unset $VIASH_META_MEMORY_B + fi +fi +# unset nproc if string is empty +if [ -z "$VIASH_META_CPUS" ]; then + unset $VIASH_META_CPUS +fi + + +# check whether required parameters exist +if [ -z ${VIASH_PAR_GFF+x} ]; then + ViashError '--gff' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi +if [ -z ${VIASH_PAR_OUTPUT+x} ]; then + ViashError '--output' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi +if [ -z ${VIASH_META_NAME+x} ]; then + ViashError 'name' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi +if [ -z ${VIASH_META_FUNCTIONALITY_NAME+x} ]; then + ViashError 'functionality_name' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi +if [ -z ${VIASH_META_RESOURCES_DIR+x} ]; then + ViashError 'resources_dir' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi +if [ -z ${VIASH_META_EXECUTABLE+x} ]; then + ViashError 'executable' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi +if [ -z ${VIASH_META_CONFIG+x} ]; then + ViashError 'config' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi +if [ -z ${VIASH_META_TEMP_DIR+x} ]; then + ViashError 'temp_dir' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi + +# check whether required files exist +if [ ! -z "$VIASH_PAR_GFF" ] && [ ! -e "$VIASH_PAR_GFF" ]; then + ViashError "Input file '$VIASH_PAR_GFF' does not exist." + exit 1 +fi +if [ ! -z "$VIASH_PAR_CONFIG" ] && [ ! -e "$VIASH_PAR_CONFIG" ]; then + ViashError "Input file '$VIASH_PAR_CONFIG' does not exist." + exit 1 +fi + +# check whether parameters values are of the right type +if [[ -n "$VIASH_META_CPUS" ]]; then + if ! [[ "$VIASH_META_CPUS" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'cpus' has to be an integer. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_B" ]]; then + if ! [[ "$VIASH_META_MEMORY_B" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_b' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_KB" ]]; then + if ! [[ "$VIASH_META_MEMORY_KB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_kb' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_MB" ]]; then + if ! [[ "$VIASH_META_MEMORY_MB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_mb' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_GB" ]]; then + if ! [[ "$VIASH_META_MEMORY_GB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_gb' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_TB" ]]; then + if ! [[ "$VIASH_META_MEMORY_TB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_tb' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_PB" ]]; then + if ! [[ "$VIASH_META_MEMORY_PB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_pb' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_KIB" ]]; then + if ! [[ "$VIASH_META_MEMORY_KIB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_kib' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_MIB" ]]; then + if ! [[ "$VIASH_META_MEMORY_MIB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_mib' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_GIB" ]]; then + if ! [[ "$VIASH_META_MEMORY_GIB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_gib' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_TIB" ]]; then + if ! [[ "$VIASH_META_MEMORY_TIB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_tib' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_PIB" ]]; then + if ! [[ "$VIASH_META_MEMORY_PIB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_pib' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi + +# create parent directories of output files, if so desired +if [ ! -z "$VIASH_PAR_OUTPUT" ] && [ ! -d "$(dirname "$VIASH_PAR_OUTPUT")" ]; then + mkdir -p "$(dirname "$VIASH_PAR_OUTPUT")" +fi + +if [ "$VIASH_ENGINE_ID" == "native" ] ; then + if [ "$VIASH_MODE" == "run" ]; then + VIASH_CMD="bash" + else + ViashError "Engine '$VIASH_ENGINE_ID' does not support mode '$VIASH_MODE'." + exit 1 + fi +fi + +if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then + # detect volumes from file arguments + VIASH_CHOWN_VARS=() +if [ ! -z "$VIASH_PAR_GFF" ]; then + VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_PAR_GFF")" ) + VIASH_PAR_GFF=$(ViashDockerAutodetectMount "$VIASH_PAR_GFF") +fi +if [ ! -z "$VIASH_PAR_OUTPUT" ]; then + VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_PAR_OUTPUT")" ) + VIASH_PAR_OUTPUT=$(ViashDockerAutodetectMount "$VIASH_PAR_OUTPUT") + VIASH_CHOWN_VARS+=( "$VIASH_PAR_OUTPUT" ) +fi +if [ ! -z "$VIASH_PAR_CONFIG" ]; then + VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_PAR_CONFIG")" ) + VIASH_PAR_CONFIG=$(ViashDockerAutodetectMount "$VIASH_PAR_CONFIG") +fi +if [ ! -z "$VIASH_META_RESOURCES_DIR" ]; then + VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_META_RESOURCES_DIR")" ) + VIASH_META_RESOURCES_DIR=$(ViashDockerAutodetectMount "$VIASH_META_RESOURCES_DIR") +fi +if [ ! -z "$VIASH_META_EXECUTABLE" ]; then + VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_META_EXECUTABLE")" ) + VIASH_META_EXECUTABLE=$(ViashDockerAutodetectMount "$VIASH_META_EXECUTABLE") +fi +if [ ! -z "$VIASH_META_CONFIG" ]; then + VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_META_CONFIG")" ) + VIASH_META_CONFIG=$(ViashDockerAutodetectMount "$VIASH_META_CONFIG") +fi +if [ ! -z "$VIASH_META_TEMP_DIR" ]; then + VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_META_TEMP_DIR")" ) + VIASH_META_TEMP_DIR=$(ViashDockerAutodetectMount "$VIASH_META_TEMP_DIR") +fi + + # get unique mounts + VIASH_UNIQUE_MOUNTS=($(for val in "${VIASH_DIRECTORY_MOUNTS[@]}"; do echo "$val"; done | sort -u)) +fi + +if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then + # change file ownership + function ViashPerformChown { + if (( ${#VIASH_CHOWN_VARS[@]} )); then + set +e + VIASH_CMD="docker run --entrypoint=bash --rm ${VIASH_UNIQUE_MOUNTS[@]} $VIASH_DOCKER_IMAGE_ID -c 'chown $(id -u):$(id -g) --silent --recursive ${VIASH_CHOWN_VARS[@]}'" + ViashDebug "+ $VIASH_CMD" + eval $VIASH_CMD + set -e + fi + } + trap ViashPerformChown EXIT +fi + +if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then + # helper function for filling in extra docker args + if [ ! -z "$VIASH_META_MEMORY_B" ]; then + VIASH_DOCKER_RUN_ARGS+=("--memory=${VIASH_META_MEMORY_B}") + fi + if [ ! -z "$VIASH_META_CPUS" ]; then + VIASH_DOCKER_RUN_ARGS+=("--cpus=${VIASH_META_CPUS}") + fi +fi + +if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then + VIASH_CMD="docker run --entrypoint=bash ${VIASH_DOCKER_RUN_ARGS[@]} ${VIASH_UNIQUE_MOUNTS[@]} $VIASH_DOCKER_IMAGE_ID" +fi + + +# set dependency paths + + +ViashDebug "Running command: $(echo $VIASH_CMD)" +cat << VIASHEOF | eval $VIASH_CMD +set -e +tempscript=\$(mktemp "$VIASH_META_TEMP_DIR/viash-run-agat_convert_sp_gff2tsv-XXXXXX").sh +function clean_up { + rm "\$tempscript" +} +function interrupt { + echo -e "\nCTRL-C Pressed..." + exit 1 +} +trap clean_up EXIT +trap interrupt INT SIGINT +cat > "\$tempscript" << 'VIASHMAIN' +#!/bin/bash + +## VIASH START +# The following code has been auto-generated by Viash. +$( if [ ! -z ${VIASH_PAR_GFF+x} ]; then echo "${VIASH_PAR_GFF}" | sed "s#'#'\"'\"'#g;s#.*#par_gff='&'#" ; else echo "# par_gff="; fi ) +$( if [ ! -z ${VIASH_PAR_OUTPUT+x} ]; then echo "${VIASH_PAR_OUTPUT}" | sed "s#'#'\"'\"'#g;s#.*#par_output='&'#" ; else echo "# par_output="; fi ) +$( if [ ! -z ${VIASH_PAR_CONFIG+x} ]; then echo "${VIASH_PAR_CONFIG}" | sed "s#'#'\"'\"'#g;s#.*#par_config='&'#" ; else echo "# par_config="; fi ) +$( if [ ! -z ${VIASH_META_NAME+x} ]; then echo "${VIASH_META_NAME}" | sed "s#'#'\"'\"'#g;s#.*#meta_name='&'#" ; else echo "# meta_name="; fi ) +$( if [ ! -z ${VIASH_META_FUNCTIONALITY_NAME+x} ]; then echo "${VIASH_META_FUNCTIONALITY_NAME}" | sed "s#'#'\"'\"'#g;s#.*#meta_functionality_name='&'#" ; else echo "# meta_functionality_name="; fi ) +$( if [ ! -z ${VIASH_META_RESOURCES_DIR+x} ]; then echo "${VIASH_META_RESOURCES_DIR}" | sed "s#'#'\"'\"'#g;s#.*#meta_resources_dir='&'#" ; else echo "# meta_resources_dir="; fi ) +$( if [ ! -z ${VIASH_META_EXECUTABLE+x} ]; then echo "${VIASH_META_EXECUTABLE}" | sed "s#'#'\"'\"'#g;s#.*#meta_executable='&'#" ; else echo "# meta_executable="; fi ) +$( if [ ! -z ${VIASH_META_CONFIG+x} ]; then echo "${VIASH_META_CONFIG}" | sed "s#'#'\"'\"'#g;s#.*#meta_config='&'#" ; else echo "# meta_config="; fi ) +$( if [ ! -z ${VIASH_META_TEMP_DIR+x} ]; then echo "${VIASH_META_TEMP_DIR}" | sed "s#'#'\"'\"'#g;s#.*#meta_temp_dir='&'#" ; else echo "# meta_temp_dir="; fi ) +$( if [ ! -z ${VIASH_META_CPUS+x} ]; then echo "${VIASH_META_CPUS}" | sed "s#'#'\"'\"'#g;s#.*#meta_cpus='&'#" ; else echo "# meta_cpus="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_B+x} ]; then echo "${VIASH_META_MEMORY_B}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_b='&'#" ; else echo "# meta_memory_b="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_KB+x} ]; then echo "${VIASH_META_MEMORY_KB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_kb='&'#" ; else echo "# meta_memory_kb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_MB+x} ]; then echo "${VIASH_META_MEMORY_MB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_mb='&'#" ; else echo "# meta_memory_mb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_GB+x} ]; then echo "${VIASH_META_MEMORY_GB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_gb='&'#" ; else echo "# meta_memory_gb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_TB+x} ]; then echo "${VIASH_META_MEMORY_TB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_tb='&'#" ; else echo "# meta_memory_tb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_PB+x} ]; then echo "${VIASH_META_MEMORY_PB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_pb='&'#" ; else echo "# meta_memory_pb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_KIB+x} ]; then echo "${VIASH_META_MEMORY_KIB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_kib='&'#" ; else echo "# meta_memory_kib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_MIB+x} ]; then echo "${VIASH_META_MEMORY_MIB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_mib='&'#" ; else echo "# meta_memory_mib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_GIB+x} ]; then echo "${VIASH_META_MEMORY_GIB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_gib='&'#" ; else echo "# meta_memory_gib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_TIB+x} ]; then echo "${VIASH_META_MEMORY_TIB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_tib='&'#" ; else echo "# meta_memory_tib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_pib='&'#" ; else echo "# meta_memory_pib="; fi ) + +## VIASH END + +agat_convert_sp_gff2tsv.pl \\ + -f "\$par_gff" \\ + -o "\$par_output" \\ + \${par_config:+--config "\${par_config}"} +VIASHMAIN +bash "\$tempscript" & +wait "\$!" + +VIASHEOF + + +if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then + # strip viash automount from file paths + + if [ ! -z "$VIASH_PAR_GFF" ]; then + VIASH_PAR_GFF=$(ViashDockerStripAutomount "$VIASH_PAR_GFF") + fi + if [ ! -z "$VIASH_PAR_OUTPUT" ]; then + VIASH_PAR_OUTPUT=$(ViashDockerStripAutomount "$VIASH_PAR_OUTPUT") + fi + if [ ! -z "$VIASH_PAR_CONFIG" ]; then + VIASH_PAR_CONFIG=$(ViashDockerStripAutomount "$VIASH_PAR_CONFIG") + fi + if [ ! -z "$VIASH_META_RESOURCES_DIR" ]; then + VIASH_META_RESOURCES_DIR=$(ViashDockerStripAutomount "$VIASH_META_RESOURCES_DIR") + fi + if [ ! -z "$VIASH_META_EXECUTABLE" ]; then + VIASH_META_EXECUTABLE=$(ViashDockerStripAutomount "$VIASH_META_EXECUTABLE") + fi + if [ ! -z "$VIASH_META_CONFIG" ]; then + VIASH_META_CONFIG=$(ViashDockerStripAutomount "$VIASH_META_CONFIG") + fi + if [ ! -z "$VIASH_META_TEMP_DIR" ]; then + VIASH_META_TEMP_DIR=$(ViashDockerStripAutomount "$VIASH_META_TEMP_DIR") + fi +fi + + +# check whether required files exist +if [ ! -z "$VIASH_PAR_OUTPUT" ] && [ ! -e "$VIASH_PAR_OUTPUT" ]; then + ViashError "Output file '$VIASH_PAR_OUTPUT' does not exist." + exit 1 +fi + + +exit 0 diff --git a/target/executable/agat/agat_convert_sp_gxf2gxf/.config.vsh.yaml b/target/executable/agat/agat_convert_sp_gxf2gxf/.config.vsh.yaml new file mode 100644 index 00000000..ec2b5e9f --- /dev/null +++ b/target/executable/agat/agat_convert_sp_gxf2gxf/.config.vsh.yaml @@ -0,0 +1,221 @@ +name: "agat_convert_sp_gxf2gxf" +namespace: "agat" +version: "main" +authors: +- name: "Leïla Paquay" + roles: + - "author" + - "maintainer" + info: + links: + email: "leila@data-intuitive.com" + github: "Leila011" + linkedin: "leilapaquay" + organizations: + - name: "Data Intuitive" + href: "https://www.data-intuitive.com" + role: "Software Developer" +argument_groups: +- name: "Inputs" + arguments: + - type: "file" + name: "--gxf" + alternatives: + - "-g" + - "--gtf" + - "--gff" + description: "String - Input GTF/GFF file. Compressed file with .gz extension\ + \ is accepted.\n" + info: null + example: + - "input.gff" + must_exist: true + create_parent: true + required: true + direction: "input" + multiple: false + multiple_sep: ";" +- name: "Outputs" + arguments: + - type: "file" + name: "--output" + alternatives: + - "-o" + description: "String - Output GFF file. If no output file is specified, the output\ + \ will be written to STDOUT.\n" + info: null + example: + - "output.gff" + must_exist: true + create_parent: true + required: true + direction: "output" + multiple: false + multiple_sep: ";" +- name: "Arguments" + arguments: + - type: "file" + name: "--config" + alternatives: + - "-c" + description: "String - Input agat config file. By default AGAT takes as input\ + \ agat_config.yaml file from the working directory if any, otherwise it takes\ + \ the original agat_config.yaml shipped with AGAT. To get the agat_config.yaml\ + \ locally type: \"agat config --expose\". The --config option gives you the\ + \ possibility to use your own AGAT config file (located elsewhere or named differently).\n" + info: null + example: + - "custom_agat_config.yaml" + must_exist: true + create_parent: true + required: false + direction: "input" + multiple: false + multiple_sep: ";" +resources: +- type: "bash_script" + path: "script.sh" + is_executable: true +description: "This script fixes and/or standardizes any GTF/GFF file into full sorted\n\ + GTF/GFF file. It AGAT parser removes duplicate features, fixes\nduplicated IDs,\ + \ adds missing ID and/or Parent attributes, deflates\nfactorized attributes (attributes\ + \ with several parents are duplicated\nwith uniq ID), add missing features when\ + \ possible (e.g. add exon if only\nCDS described, add UTR if CDS and exon described),\ + \ fix feature locations\n(e.g. check exon is embedded in the parent features mRNA,\ + \ gene), etc...\n\nAll AGAT's scripts with the _sp_ prefix use the AGAT parser,\ + \ before to\nperform any supplementary task. So, it is not necessary to run this\n\ + script prior the use of any other _sp_ script.\n" +test_resources: +- type: "bash_script" + path: "test.sh" + is_executable: true +- type: "file" + path: "test_data" +info: null +status: "enabled" +requirements: + commands: + - "ps" +keywords: +- "gene annotations" +- "GFF conversion" +license: "GPL-3.0" +references: + doi: + - "10.5281/zenodo.3552717" +links: + repository: "https://github.com/NBISweden/AGAT" + homepage: "https://github.com/NBISweden/AGAT" + documentation: "https://agat.readthedocs.io/en/latest/tools/agat_convert_sp_gxf2gxf.html" + issue_tracker: "https://github.com/NBISweden/AGAT/issues" +runners: +- type: "executable" + id: "executable" + docker_setup_strategy: "ifneedbepullelsecachedbuild" +- type: "nextflow" + id: "nextflow" + directives: + tag: "$id" + auto: + simplifyInput: true + simplifyOutput: false + transcript: false + publish: false + config: + labels: + mem1gb: "memory = 1000000000.B" + mem2gb: "memory = 2000000000.B" + mem5gb: "memory = 5000000000.B" + mem10gb: "memory = 10000000000.B" + mem20gb: "memory = 20000000000.B" + mem50gb: "memory = 50000000000.B" + mem100gb: "memory = 100000000000.B" + mem200gb: "memory = 200000000000.B" + mem500gb: "memory = 500000000000.B" + mem1tb: "memory = 1000000000000.B" + mem2tb: "memory = 2000000000000.B" + mem5tb: "memory = 5000000000000.B" + mem10tb: "memory = 10000000000000.B" + mem20tb: "memory = 20000000000000.B" + mem50tb: "memory = 50000000000000.B" + mem100tb: "memory = 100000000000000.B" + mem200tb: "memory = 200000000000000.B" + mem500tb: "memory = 500000000000000.B" + mem1gib: "memory = 1073741824.B" + mem2gib: "memory = 2147483648.B" + mem4gib: "memory = 4294967296.B" + mem8gib: "memory = 8589934592.B" + mem16gib: "memory = 17179869184.B" + mem32gib: "memory = 34359738368.B" + mem64gib: "memory = 68719476736.B" + mem128gib: "memory = 137438953472.B" + mem256gib: "memory = 274877906944.B" + mem512gib: "memory = 549755813888.B" + mem1tib: "memory = 1099511627776.B" + mem2tib: "memory = 2199023255552.B" + mem4tib: "memory = 4398046511104.B" + mem8tib: "memory = 8796093022208.B" + mem16tib: "memory = 17592186044416.B" + mem32tib: "memory = 35184372088832.B" + mem64tib: "memory = 70368744177664.B" + mem128tib: "memory = 140737488355328.B" + mem256tib: "memory = 281474976710656.B" + mem512tib: "memory = 562949953421312.B" + cpu1: "cpus = 1" + cpu2: "cpus = 2" + cpu5: "cpus = 5" + cpu10: "cpus = 10" + cpu20: "cpus = 20" + cpu50: "cpus = 50" + cpu100: "cpus = 100" + cpu200: "cpus = 200" + cpu500: "cpus = 500" + cpu1000: "cpus = 1000" + debug: false + container: "docker" +engines: +- type: "docker" + id: "docker" + image: "quay.io/biocontainers/agat:1.4.0--pl5321hdfd78af_0" + target_registry: "images.viash-hub.com" + target_tag: "main" + namespace_separator: "/" + setup: + - type: "docker" + run: + - "agat --version | sed 's/AGAT\\s\\(.*\\)/agat: \"\\1\"/' > /var/software_versions.txt\n" + entrypoint: [] + cmd: null +- type: "native" + id: "native" +build_info: + config: "src/agat/agat_convert_sp_gxf2gxf/config.vsh.yaml" + runner: "executable" + engine: "docker|native" + output: "target/executable/agat/agat_convert_sp_gxf2gxf" + executable: "target/executable/agat/agat_convert_sp_gxf2gxf/agat_convert_sp_gxf2gxf" + viash_version: "0.9.0-RC6" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" + git_remote: "https://github.com/viash-hub/biobox" +package_config: + name: "biobox" + version: "main" + description: "A collection of bioinformatics tools for working with sequence data.\n" + info: null + viash_version: "0.9.0-RC6" + source: "src" + target: "target" + config_mods: + - ".requirements.commands := ['ps']\n" + - ".engines += { type: \"native\" }" + - ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'" + - ".engines[.type == 'docker'].target_tag := 'main'" + keywords: + - "bioinformatics" + - "modules" + - "sequencing" + license: "MIT" + organization: "vsh" + links: + repository: "https://github.com/viash-hub/biobox" + issue_tracker: "https://github.com/viash-hub/biobox/issues" diff --git a/target/executable/agat/agat_convert_sp_gxf2gxf/agat_convert_sp_gxf2gxf b/target/executable/agat/agat_convert_sp_gxf2gxf/agat_convert_sp_gxf2gxf new file mode 100755 index 00000000..5beff467 --- /dev/null +++ b/target/executable/agat/agat_convert_sp_gxf2gxf/agat_convert_sp_gxf2gxf @@ -0,0 +1,1130 @@ +#!/usr/bin/env bash + +# agat_convert_sp_gxf2gxf main +# +# This wrapper script is auto-generated by viash 0.9.0-RC6 and is thus a +# derivative work thereof. This software comes with ABSOLUTELY NO WARRANTY from +# Data Intuitive. +# +# The component may contain files which fall under a different license. The +# authors of this component should specify the license in the header of such +# files, or include a separate license file detailing the licenses of all included +# files. +# +# Component authors: +# * Leïla Paquay (author, maintainer) + +set -e + +if [ -z "$VIASH_TEMP" ]; then + VIASH_TEMP=${VIASH_TEMP:-$VIASH_TMPDIR} + VIASH_TEMP=${VIASH_TEMP:-$VIASH_TEMPDIR} + VIASH_TEMP=${VIASH_TEMP:-$VIASH_TMP} + VIASH_TEMP=${VIASH_TEMP:-$TMPDIR} + VIASH_TEMP=${VIASH_TEMP:-$TMP} + VIASH_TEMP=${VIASH_TEMP:-$TEMPDIR} + VIASH_TEMP=${VIASH_TEMP:-$TEMP} + VIASH_TEMP=${VIASH_TEMP:-/tmp} +fi + +# define helper functions +# ViashQuote: put quotes around non flag values +# $1 : unquoted string +# return : possibly quoted string +# examples: +# ViashQuote --foo # returns --foo +# ViashQuote bar # returns 'bar' +# Viashquote --foo=bar # returns --foo='bar' +function ViashQuote { + if [[ "$1" =~ ^-+[a-zA-Z0-9_\-]+=.+$ ]]; then + echo "$1" | sed "s#=\(.*\)#='\1'#" + elif [[ "$1" =~ ^-+[a-zA-Z0-9_\-]+$ ]]; then + echo "$1" + else + echo "'$1'" + fi +} +# ViashRemoveFlags: Remove leading flag +# $1 : string with a possible leading flag +# return : string without possible leading flag +# examples: +# ViashRemoveFlags --foo=bar # returns bar +function ViashRemoveFlags { + echo "$1" | sed 's/^--*[a-zA-Z0-9_\-]*=//' +} +# ViashSourceDir: return the path of a bash file, following symlinks +# usage : ViashSourceDir ${BASH_SOURCE[0]} +# $1 : Should always be set to ${BASH_SOURCE[0]} +# returns : The absolute path of the bash file +function ViashSourceDir { + SOURCE="$1" + while [ -h "$SOURCE" ]; do + DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )" + SOURCE="$(readlink "$SOURCE")" + [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" + done + cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd +} +# ViashFindTargetDir: return the path of the '.build.yaml' file, following symlinks +# usage : ViashFindTargetDir 'ScriptPath' +# $1 : The location from where to start the upward search +# returns : The absolute path of the '.build.yaml' file +function ViashFindTargetDir { + SOURCE="$1" + while [[ "$SOURCE" != "" && ! -e "$SOURCE/.build.yaml" ]]; do + SOURCE=${SOURCE%/*} + done + echo $SOURCE +} +# see https://en.wikipedia.org/wiki/Syslog#Severity_level +VIASH_LOGCODE_EMERGENCY=0 +VIASH_LOGCODE_ALERT=1 +VIASH_LOGCODE_CRITICAL=2 +VIASH_LOGCODE_ERROR=3 +VIASH_LOGCODE_WARNING=4 +VIASH_LOGCODE_NOTICE=5 +VIASH_LOGCODE_INFO=6 +VIASH_LOGCODE_DEBUG=7 +VIASH_VERBOSITY=$VIASH_LOGCODE_NOTICE + +# ViashLog: Log events depending on the verbosity level +# usage: ViashLog 1 alert Oh no something went wrong! +# $1: required verbosity level +# $2: display tag +# $3+: messages to display +# stdout: Your input, prepended by '[$2] '. +function ViashLog { + local required_level="$1" + local display_tag="$2" + shift 2 + if [ $VIASH_VERBOSITY -ge $required_level ]; then + >&2 echo "[$display_tag]" "$@" + fi +} + +# ViashEmergency: log events when the system is unstable +# usage: ViashEmergency Oh no something went wrong. +# stdout: Your input, prepended by '[emergency] '. +function ViashEmergency { + ViashLog $VIASH_LOGCODE_EMERGENCY emergency "$@" +} + +# ViashAlert: log events when actions must be taken immediately (e.g. corrupted system database) +# usage: ViashAlert Oh no something went wrong. +# stdout: Your input, prepended by '[alert] '. +function ViashAlert { + ViashLog $VIASH_LOGCODE_ALERT alert "$@" +} + +# ViashCritical: log events when a critical condition occurs +# usage: ViashCritical Oh no something went wrong. +# stdout: Your input, prepended by '[critical] '. +function ViashCritical { + ViashLog $VIASH_LOGCODE_CRITICAL critical "$@" +} + +# ViashError: log events when an error condition occurs +# usage: ViashError Oh no something went wrong. +# stdout: Your input, prepended by '[error] '. +function ViashError { + ViashLog $VIASH_LOGCODE_ERROR error "$@" +} + +# ViashWarning: log potentially abnormal events +# usage: ViashWarning Something may have gone wrong. +# stdout: Your input, prepended by '[warning] '. +function ViashWarning { + ViashLog $VIASH_LOGCODE_WARNING warning "$@" +} + +# ViashNotice: log significant but normal events +# usage: ViashNotice This just happened. +# stdout: Your input, prepended by '[notice] '. +function ViashNotice { + ViashLog $VIASH_LOGCODE_NOTICE notice "$@" +} + +# ViashInfo: log normal events +# usage: ViashInfo This just happened. +# stdout: Your input, prepended by '[info] '. +function ViashInfo { + ViashLog $VIASH_LOGCODE_INFO info "$@" +} + +# ViashDebug: log all events, for debugging purposes +# usage: ViashDebug This just happened. +# stdout: Your input, prepended by '[debug] '. +function ViashDebug { + ViashLog $VIASH_LOGCODE_DEBUG debug "$@" +} + +# find source folder of this component +VIASH_META_RESOURCES_DIR=`ViashSourceDir ${BASH_SOURCE[0]}` + +# find the root of the built components & dependencies +VIASH_TARGET_DIR=`ViashFindTargetDir $VIASH_META_RESOURCES_DIR` + +# define meta fields +VIASH_META_NAME="agat_convert_sp_gxf2gxf" +VIASH_META_FUNCTIONALITY_NAME="agat_convert_sp_gxf2gxf" +VIASH_META_EXECUTABLE="$VIASH_META_RESOURCES_DIR/$VIASH_META_NAME" +VIASH_META_CONFIG="$VIASH_META_RESOURCES_DIR/.config.vsh.yaml" +VIASH_META_TEMP_DIR="$VIASH_TEMP" + + +# ViashHelp: Display helpful explanation about this executable +function ViashHelp { + echo "agat_convert_sp_gxf2gxf main" + echo "" + echo "This script fixes and/or standardizes any GTF/GFF file into full sorted" + echo "GTF/GFF file. It AGAT parser removes duplicate features, fixes" + echo "duplicated IDs, adds missing ID and/or Parent attributes, deflates" + echo "factorized attributes (attributes with several parents are duplicated" + echo "with uniq ID), add missing features when possible (e.g. add exon if only" + echo "CDS described, add UTR if CDS and exon described), fix feature locations" + echo "(e.g. check exon is embedded in the parent features mRNA, gene), etc..." + echo "" + echo "All AGAT's scripts with the _sp_ prefix use the AGAT parser, before to" + echo "perform any supplementary task. So, it is not necessary to run this" + echo "script prior the use of any other _sp_ script." + echo "" + echo "Inputs:" + echo " -g, --gtf, --gff, --gxf" + echo " type: file, required parameter, file must exist" + echo " example: input.gff" + echo " String - Input GTF/GFF file. Compressed file with .gz extension is" + echo " accepted." + echo "" + echo "Outputs:" + echo " -o, --output" + echo " type: file, required parameter, output, file must exist" + echo " example: output.gff" + echo " String - Output GFF file. If no output file is specified, the output" + echo " will be written to STDOUT." + echo "" + echo "Arguments:" + echo " -c, --config" + echo " type: file, file must exist" + echo " example: custom_agat_config.yaml" + echo " String - Input agat config file. By default AGAT takes as input" + echo " agat_config.yaml file from the working directory if any, otherwise it" + echo " takes the original agat_config.yaml shipped with AGAT. To get the" + echo " agat_config.yaml locally type: \"agat config --expose\". The --config" + echo " option gives you the possibility to use your own AGAT config file" + echo " (located elsewhere or named differently)." +} + +# initialise variables +VIASH_MODE='run' +VIASH_ENGINE_ID='docker' + +######## Helper functions for setting up Docker images for viash ######## +# expects: ViashDockerBuild + +# ViashDockerInstallationCheck: check whether Docker is installed correctly +# +# examples: +# ViashDockerInstallationCheck +function ViashDockerInstallationCheck { + ViashDebug "Checking whether Docker is installed" + if [ ! command -v docker &> /dev/null ]; then + ViashCritical "Docker doesn't seem to be installed. See 'https://docs.docker.com/get-docker/' for instructions." + exit 1 + fi + + ViashDebug "Checking whether the Docker daemon is running" + save=$-; set +e + docker_version=$(docker version --format '{{.Client.APIVersion}}' 2> /dev/null) + out=$? + [[ $save =~ e ]] && set -e + if [ $out -ne 0 ]; then + ViashCritical "Docker daemon does not seem to be running. Try one of the following:" + ViashCritical "- Try running 'dockerd' in the command line" + ViashCritical "- See https://docs.docker.com/config/daemon/" + exit 1 + fi +} + +# ViashDockerRemoteTagCheck: check whether a Docker image is available +# on a remote. Assumes `docker login` has been performed, if relevant. +# +# $1 : image identifier with format `[registry/]image[:tag]` +# exit code $? : whether or not the image was found +# examples: +# ViashDockerRemoteTagCheck python:latest +# echo $? # returns '0' +# ViashDockerRemoteTagCheck sdaizudceahifu +# echo $? # returns '1' +function ViashDockerRemoteTagCheck { + docker manifest inspect $1 > /dev/null 2> /dev/null +} + +# ViashDockerLocalTagCheck: check whether a Docker image is available locally +# +# $1 : image identifier with format `[registry/]image[:tag]` +# exit code $? : whether or not the image was found +# examples: +# docker pull python:latest +# ViashDockerLocalTagCheck python:latest +# echo $? # returns '0' +# ViashDockerLocalTagCheck sdaizudceahifu +# echo $? # returns '1' +function ViashDockerLocalTagCheck { + [ -n "$(docker images -q $1)" ] +} + +# ViashDockerPull: pull a Docker image +# +# $1 : image identifier with format `[registry/]image[:tag]` +# exit code $? : whether or not the image was found +# examples: +# ViashDockerPull python:latest +# echo $? # returns '0' +# ViashDockerPull sdaizudceahifu +# echo $? # returns '1' +function ViashDockerPull { + ViashNotice "Checking if Docker image is available at '$1'" + if [ $VIASH_VERBOSITY -ge $VIASH_LOGCODE_INFO ]; then + docker pull $1 && return 0 || return 1 + else + save=$-; set +e + docker pull $1 2> /dev/null > /dev/null + out=$? + [[ $save =~ e ]] && set -e + if [ $out -ne 0 ]; then + ViashWarning "Could not pull from '$1'. Docker image doesn't exist or is not accessible." + fi + return $out + fi +} + +# ViashDockerPush: push a Docker image +# +# $1 : image identifier with format `[registry/]image[:tag]` +# exit code $? : whether or not the image was found +# examples: +# ViashDockerPush python:latest +# echo $? # returns '0' +# ViashDockerPush sdaizudceahifu +# echo $? # returns '1' +function ViashDockerPush { + ViashNotice "Pushing image to '$1'" + save=$-; set +e + if [ $VIASH_VERBOSITY -ge $VIASH_LOGCODE_INFO ]; then + docker push $1 + out=$? + else + docker push $1 2> /dev/null > /dev/null + out=$? + fi + [[ $save =~ e ]] && set -e + if [ $out -eq 0 ]; then + ViashNotice "Container '$1' push succeeded." + else + ViashError "Container '$1' push errored. You might not be logged in or have the necessary permissions." + fi + return $out +} + +# ViashDockerPullElseBuild: pull a Docker image, else build it +# +# $1 : image identifier with format `[registry/]image[:tag]` +# ViashDockerBuild : a Bash function which builds a docker image, takes image identifier as argument. +# examples: +# ViashDockerPullElseBuild mynewcomponent +function ViashDockerPullElseBuild { + save=$-; set +e + ViashDockerPull $1 + out=$? + [[ $save =~ e ]] && set -e + if [ $out -ne 0 ]; then + ViashDockerBuild $@ + fi +} + +# ViashDockerSetup: create a Docker image, according to specified docker setup strategy +# +# $1 : image identifier with format `[registry/]image[:tag]` +# $2 : docker setup strategy, see DockerSetupStrategy.scala +# examples: +# ViashDockerSetup mynewcomponent alwaysbuild +function ViashDockerSetup { + local image_id="$1" + local setup_strategy="$2" + if [ "$setup_strategy" == "alwaysbuild" -o "$setup_strategy" == "build" -o "$setup_strategy" == "b" ]; then + ViashDockerBuild $image_id --no-cache $(ViashDockerBuildArgs "$engine_id") + elif [ "$setup_strategy" == "alwayspull" -o "$setup_strategy" == "pull" -o "$setup_strategy" == "p" ]; then + ViashDockerPull $image_id + elif [ "$setup_strategy" == "alwayspullelsebuild" -o "$setup_strategy" == "pullelsebuild" ]; then + ViashDockerPullElseBuild $image_id --no-cache $(ViashDockerBuildArgs "$engine_id") + elif [ "$setup_strategy" == "alwayspullelsecachedbuild" -o "$setup_strategy" == "pullelsecachedbuild" ]; then + ViashDockerPullElseBuild $image_id $(ViashDockerBuildArgs "$engine_id") + elif [ "$setup_strategy" == "alwayscachedbuild" -o "$setup_strategy" == "cachedbuild" -o "$setup_strategy" == "cb" ]; then + ViashDockerBuild $image_id $(ViashDockerBuildArgs "$engine_id") + elif [[ "$setup_strategy" =~ ^ifneedbe ]]; then + local save=$-; set +e + ViashDockerLocalTagCheck $image_id + local outCheck=$? + [[ $save =~ e ]] && set -e + if [ $outCheck -eq 0 ]; then + ViashInfo "Image $image_id already exists" + elif [ "$setup_strategy" == "ifneedbebuild" ]; then + ViashDockerBuild $image_id --no-cache $(ViashDockerBuildArgs "$engine_id") + elif [ "$setup_strategy" == "ifneedbecachedbuild" ]; then + ViashDockerBuild $image_id $(ViashDockerBuildArgs "$engine_id") + elif [ "$setup_strategy" == "ifneedbepull" ]; then + ViashDockerPull $image_id + elif [ "$setup_strategy" == "ifneedbepullelsebuild" ]; then + ViashDockerPullElseBuild $image_id --no-cache $(ViashDockerBuildArgs "$engine_id") + elif [ "$setup_strategy" == "ifneedbepullelsecachedbuild" ]; then + ViashDockerPullElseBuild $image_id $(ViashDockerBuildArgs "$engine_id") + else + ViashError "Unrecognised Docker strategy: $setup_strategy" + exit 1 + fi + elif [ "$setup_strategy" == "push" -o "$setup_strategy" == "forcepush" -o "$setup_strategy" == "alwayspush" ]; then + ViashDockerPush "$image_id" + elif [ "$setup_strategy" == "pushifnotpresent" -o "$setup_strategy" == "gentlepush" -o "$setup_strategy" == "maybepush" ]; then + local save=$-; set +e + ViashDockerRemoteTagCheck $image_id + local outCheck=$? + [[ $save =~ e ]] && set -e + if [ $outCheck -eq 0 ]; then + ViashNotice "Container '$image_id' exists, doing nothing." + else + ViashNotice "Container '$image_id' does not yet exist." + ViashDockerPush "$image_id" + fi + elif [ "$setup_strategy" == "donothing" -o "$setup_strategy" == "meh" ]; then + ViashNotice "Skipping setup." + else + ViashError "Unrecognised Docker strategy: $setup_strategy" + exit 1 + fi +} + +# ViashDockerCheckCommands: Check whether a docker container has the required commands +# +# $1 : image identifier with format `[registry/]image[:tag]` +# $@ : commands to verify being present +# examples: +# ViashDockerCheckCommands bash:4.0 bash ps foo +function ViashDockerCheckCommands { + local image_id="$1" + shift 1 + local commands="$@" + local save=$-; set +e + local missing # mark 'missing' as local in advance, otherwise the exit code of the command will be missing and always be '0' + missing=$(docker run --rm --entrypoint=sh "$image_id" -c "for command in $commands; do command -v \$command >/dev/null 2>&1; if [ \$? -ne 0 ]; then echo \$command; exit 1; fi; done") + local outCheck=$? + [[ $save =~ e ]] && set -e + if [ $outCheck -ne 0 ]; then + ViashError "Docker container '$image_id' does not contain command '$missing'." + exit 1 + fi +} + +# ViashDockerBuild: build a docker image +# $1 : image identifier with format `[registry/]image[:tag]` +# $... : additional arguments to pass to docker build +# $VIASH_META_TEMP_DIR : temporary directory to store dockerfile & optional resources in +# $VIASH_META_NAME : name of the component +# $VIASH_META_RESOURCES_DIR : directory containing the resources +# $VIASH_VERBOSITY : verbosity level +# exit code $? : whether or not the image was built successfully +function ViashDockerBuild { + local image_id="$1" + shift 1 + + # create temporary directory to store dockerfile & optional resources in + local tmpdir=$(mktemp -d "$VIASH_META_TEMP_DIR/dockerbuild-$VIASH_META_NAME-XXXXXX") + local dockerfile="$tmpdir/Dockerfile" + function clean_up { + rm -rf "$tmpdir" + } + trap clean_up EXIT + + # store dockerfile and resources + ViashDockerfile "$VIASH_ENGINE_ID" > "$dockerfile" + + # generate the build command + local docker_build_cmd="docker build -t '$image_id' $@ '$VIASH_META_RESOURCES_DIR' -f '$dockerfile'" + + # build the container + ViashNotice "Building container '$image_id' with Dockerfile" + ViashInfo "$docker_build_cmd" + local save=$-; set +e + if [ $VIASH_VERBOSITY -ge $VIASH_LOGCODE_INFO ]; then + eval $docker_build_cmd + else + eval $docker_build_cmd &> "$tmpdir/docker_build.log" + fi + + # check exit code + local out=$? + [[ $save =~ e ]] && set -e + if [ $out -ne 0 ]; then + ViashError "Error occurred while building container '$image_id'" + if [ $VIASH_VERBOSITY -lt $VIASH_LOGCODE_INFO ]; then + ViashError "Transcript: --------------------------------" + cat "$tmpdir/docker_build.log" + ViashError "End of transcript --------------------------" + fi + exit 1 + fi +} + +######## End of helper functions for setting up Docker images for viash ######## + +# ViashDockerFile: print the dockerfile to stdout +# $1 : engine identifier +# return : dockerfile required to run this component +# examples: +# ViashDockerFile +function ViashDockerfile { + local engine_id="$1" + + if [[ "$engine_id" == "docker" ]]; then + cat << 'VIASHDOCKER' +FROM quay.io/biocontainers/agat:1.4.0--pl5321hdfd78af_0 +ENTRYPOINT [] +RUN agat --version | sed 's/AGAT\s\(.*\)/agat: "\1"/' > /var/software_versions.txt + +LABEL org.opencontainers.image.authors="Leïla Paquay" +LABEL org.opencontainers.image.description="Companion container for running component agat agat_convert_sp_gxf2gxf" +LABEL org.opencontainers.image.created="2024-08-14T20:58:51Z" +LABEL org.opencontainers.image.source="https://github.com/NBISweden/AGAT" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" +LABEL org.opencontainers.image.version="main" + +VIASHDOCKER + fi +} + +# ViashDockerBuildArgs: return the arguments to pass to docker build +# $1 : engine identifier +# return : arguments to pass to docker build +function ViashDockerBuildArgs { + local engine_id="$1" + + if [[ "$engine_id" == "docker" ]]; then + echo "" + fi +} + +# ViashAbsolutePath: generate absolute path from relative path +# borrowed from https://stackoverflow.com/a/21951256 +# $1 : relative filename +# return : absolute path +# examples: +# ViashAbsolutePath some_file.txt # returns /path/to/some_file.txt +# ViashAbsolutePath /foo/bar/.. # returns /foo +function ViashAbsolutePath { + local thePath + if [[ ! "$1" =~ ^/ ]]; then + thePath="$PWD/$1" + else + thePath="$1" + fi + echo "$thePath" | ( + IFS=/ + read -a parr + declare -a outp + for i in "${parr[@]}"; do + case "$i" in + ''|.) continue ;; + ..) + len=${#outp[@]} + if ((len==0)); then + continue + else + unset outp[$((len-1))] + fi + ;; + *) + len=${#outp[@]} + outp[$len]="$i" + ;; + esac + done + echo /"${outp[*]}" + ) +} +# ViashDockerAutodetectMount: auto configuring docker mounts from parameters +# $1 : The parameter value +# returns : New parameter +# $VIASH_DIRECTORY_MOUNTS : Added another parameter to be passed to docker +# examples: +# ViashDockerAutodetectMount /path/to/bar # returns '/viash_automount/path/to/bar' +# ViashDockerAutodetectMountArg /path/to/bar # returns '--volume="/path/to:/viash_automount/path/to"' +function ViashDockerAutodetectMount { + abs_path=$(ViashAbsolutePath "$1") + if [ -d "$abs_path" ]; then + mount_source="$abs_path" + base_name="" + else + mount_source=`dirname "$abs_path"` + base_name=`basename "$abs_path"` + fi + mount_target="/viash_automount$mount_source" + if [ -z "$base_name" ]; then + echo "$mount_target" + else + echo "$mount_target/$base_name" + fi +} +function ViashDockerAutodetectMountArg { + abs_path=$(ViashAbsolutePath "$1") + if [ -d "$abs_path" ]; then + mount_source="$abs_path" + base_name="" + else + mount_source=`dirname "$abs_path"` + base_name=`basename "$abs_path"` + fi + mount_target="/viash_automount$mount_source" + ViashDebug "ViashDockerAutodetectMountArg $1 -> $mount_source -> $mount_target" + echo "--volume=\"$mount_source:$mount_target\"" +} +function ViashDockerStripAutomount { + abs_path=$(ViashAbsolutePath "$1") + echo "${abs_path#/viash_automount}" +} +# initialise variables +VIASH_DIRECTORY_MOUNTS=() + +# initialise docker variables +VIASH_DOCKER_RUN_ARGS=(-i --rm) + +# initialise array +VIASH_POSITIONAL_ARGS='' + +while [[ $# -gt 0 ]]; do + case "$1" in + -h|--help) + ViashHelp + exit + ;; + ---v|---verbose) + let "VIASH_VERBOSITY=VIASH_VERBOSITY+1" + shift 1 + ;; + ---verbosity) + VIASH_VERBOSITY="$2" + shift 2 + ;; + ---verbosity=*) + VIASH_VERBOSITY="$(ViashRemoveFlags "$1")" + shift 1 + ;; + --version) + echo "agat_convert_sp_gxf2gxf main" + exit + ;; + --gxf) + [ -n "$VIASH_PAR_GXF" ] && ViashError Bad arguments for option \'--gxf\': \'$VIASH_PAR_GXF\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_GXF="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to --gxf. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --gxf=*) + [ -n "$VIASH_PAR_GXF" ] && ViashError Bad arguments for option \'--gxf=*\': \'$VIASH_PAR_GXF\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_GXF=$(ViashRemoveFlags "$1") + shift 1 + ;; + -g) + [ -n "$VIASH_PAR_GXF" ] && ViashError Bad arguments for option \'-g\': \'$VIASH_PAR_GXF\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_GXF="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to -g. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --gtf) + [ -n "$VIASH_PAR_GXF" ] && ViashError Bad arguments for option \'--gtf\': \'$VIASH_PAR_GXF\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_GXF="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to --gtf. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --gff) + [ -n "$VIASH_PAR_GXF" ] && ViashError Bad arguments for option \'--gff\': \'$VIASH_PAR_GXF\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_GXF="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to --gff. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --output) + [ -n "$VIASH_PAR_OUTPUT" ] && ViashError Bad arguments for option \'--output\': \'$VIASH_PAR_OUTPUT\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_OUTPUT="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to --output. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --output=*) + [ -n "$VIASH_PAR_OUTPUT" ] && ViashError Bad arguments for option \'--output=*\': \'$VIASH_PAR_OUTPUT\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_OUTPUT=$(ViashRemoveFlags "$1") + shift 1 + ;; + -o) + [ -n "$VIASH_PAR_OUTPUT" ] && ViashError Bad arguments for option \'-o\': \'$VIASH_PAR_OUTPUT\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_OUTPUT="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to -o. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --config) + [ -n "$VIASH_PAR_CONFIG" ] && ViashError Bad arguments for option \'--config\': \'$VIASH_PAR_CONFIG\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_CONFIG="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to --config. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --config=*) + [ -n "$VIASH_PAR_CONFIG" ] && ViashError Bad arguments for option \'--config=*\': \'$VIASH_PAR_CONFIG\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_CONFIG=$(ViashRemoveFlags "$1") + shift 1 + ;; + -c) + [ -n "$VIASH_PAR_CONFIG" ] && ViashError Bad arguments for option \'-c\': \'$VIASH_PAR_CONFIG\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_CONFIG="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to -c. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + ---engine) + VIASH_ENGINE_ID="$2" + shift 2 + ;; + ---engine=*) + VIASH_ENGINE_ID="$(ViashRemoveFlags "$1")" + shift 1 + ;; + ---setup) + VIASH_MODE='setup' + VIASH_SETUP_STRATEGY="$2" + shift 2 + ;; + ---setup=*) + VIASH_MODE='setup' + VIASH_SETUP_STRATEGY="$(ViashRemoveFlags "$1")" + shift 1 + ;; + ---dockerfile) + VIASH_MODE='dockerfile' + shift 1 + ;; + ---debug) + VIASH_MODE='debug' + shift 1 + ;; + ---cpus) + [ -n "$VIASH_META_CPUS" ] && ViashError Bad arguments for option \'---cpus\': \'$VIASH_META_CPUS\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_META_CPUS="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to ---cpus. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + ---cpus=*) + [ -n "$VIASH_META_CPUS" ] && ViashError Bad arguments for option \'---cpus=*\': \'$VIASH_META_CPUS\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_META_CPUS=$(ViashRemoveFlags "$1") + shift 1 + ;; + ---memory) + [ -n "$VIASH_META_MEMORY" ] && ViashError Bad arguments for option \'---memory\': \'$VIASH_META_MEMORY\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_META_MEMORY="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to ---memory. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + ---memory=*) + [ -n "$VIASH_META_MEMORY" ] && ViashError Bad arguments for option \'---memory=*\': \'$VIASH_META_MEMORY\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_META_MEMORY=$(ViashRemoveFlags "$1") + shift 1 + ;; + *) # positional arg or unknown option + # since the positional args will be eval'd, can we always quote, instead of using ViashQuote + VIASH_POSITIONAL_ARGS="$VIASH_POSITIONAL_ARGS '$1'" + [[ $1 == -* ]] && ViashWarning $1 looks like a parameter but is not a defined parameter and will instead be treated as a positional argument. Use "--help" to get more information on the parameters. + shift # past argument + ;; + esac +done + +# parse positional parameters +eval set -- $VIASH_POSITIONAL_ARGS + + +if [ "$VIASH_ENGINE_ID" == "native" ] ; then + VIASH_ENGINE_TYPE='native' +elif [ "$VIASH_ENGINE_ID" == "docker" ] ; then + VIASH_ENGINE_TYPE='docker' +else + ViashError "Engine '$VIASH_ENGINE_ID' is not recognized. Options are: docker, native." + exit 1 +fi + +if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then + # check if docker is installed properly + ViashDockerInstallationCheck + + # determine docker image id + if [[ "$VIASH_ENGINE_ID" == 'docker' ]]; then + VIASH_DOCKER_IMAGE_ID='images.viash-hub.com/vsh/biobox/agat/agat_convert_sp_gxf2gxf:main' + fi + + # print dockerfile + if [ "$VIASH_MODE" == "dockerfile" ]; then + ViashDockerfile "$VIASH_ENGINE_ID" + exit 0 + + # enter docker container + elif [[ "$VIASH_MODE" == "debug" ]]; then + VIASH_CMD="docker run --entrypoint=bash ${VIASH_DOCKER_RUN_ARGS[@]} -v '$(pwd)':/pwd --workdir /pwd -t $VIASH_DOCKER_IMAGE_ID" + ViashNotice "+ $VIASH_CMD" + eval $VIASH_CMD + exit + + # build docker image + elif [ "$VIASH_MODE" == "setup" ]; then + ViashDockerSetup "$VIASH_DOCKER_IMAGE_ID" "$VIASH_SETUP_STRATEGY" + ViashDockerCheckCommands "$VIASH_DOCKER_IMAGE_ID" 'ps' 'bash' + exit 0 + fi + + # check if docker image exists + ViashDockerSetup "$VIASH_DOCKER_IMAGE_ID" ifneedbepullelsecachedbuild + ViashDockerCheckCommands "$VIASH_DOCKER_IMAGE_ID" 'ps' 'bash' +fi + +# setting computational defaults + +# helper function for parsing memory strings +function ViashMemoryAsBytes { + local memory=`echo "$1" | tr '[:upper:]' '[:lower:]' | tr -d '[:space:]'` + local memory_regex='^([0-9]+)([kmgtp]i?b?|b)$' + if [[ $memory =~ $memory_regex ]]; then + local number=${memory/[^0-9]*/} + local symbol=${memory/*[0-9]/} + + case $symbol in + b) memory_b=$number ;; + kb|k) memory_b=$(( $number * 1000 )) ;; + mb|m) memory_b=$(( $number * 1000 * 1000 )) ;; + gb|g) memory_b=$(( $number * 1000 * 1000 * 1000 )) ;; + tb|t) memory_b=$(( $number * 1000 * 1000 * 1000 * 1000 )) ;; + pb|p) memory_b=$(( $number * 1000 * 1000 * 1000 * 1000 * 1000 )) ;; + kib|ki) memory_b=$(( $number * 1024 )) ;; + mib|mi) memory_b=$(( $number * 1024 * 1024 )) ;; + gib|gi) memory_b=$(( $number * 1024 * 1024 * 1024 )) ;; + tib|ti) memory_b=$(( $number * 1024 * 1024 * 1024 * 1024 )) ;; + pib|pi) memory_b=$(( $number * 1024 * 1024 * 1024 * 1024 * 1024 )) ;; + esac + echo "$memory_b" + fi +} +# compute memory in different units +if [ ! -z ${VIASH_META_MEMORY+x} ]; then + VIASH_META_MEMORY_B=`ViashMemoryAsBytes $VIASH_META_MEMORY` + # do not define other variables if memory_b is an empty string + if [ ! -z "$VIASH_META_MEMORY_B" ]; then + VIASH_META_MEMORY_KB=$(( ($VIASH_META_MEMORY_B+999) / 1000 )) + VIASH_META_MEMORY_MB=$(( ($VIASH_META_MEMORY_KB+999) / 1000 )) + VIASH_META_MEMORY_GB=$(( ($VIASH_META_MEMORY_MB+999) / 1000 )) + VIASH_META_MEMORY_TB=$(( ($VIASH_META_MEMORY_GB+999) / 1000 )) + VIASH_META_MEMORY_PB=$(( ($VIASH_META_MEMORY_TB+999) / 1000 )) + VIASH_META_MEMORY_KIB=$(( ($VIASH_META_MEMORY_B+1023) / 1024 )) + VIASH_META_MEMORY_MIB=$(( ($VIASH_META_MEMORY_KIB+1023) / 1024 )) + VIASH_META_MEMORY_GIB=$(( ($VIASH_META_MEMORY_MIB+1023) / 1024 )) + VIASH_META_MEMORY_TIB=$(( ($VIASH_META_MEMORY_GIB+1023) / 1024 )) + VIASH_META_MEMORY_PIB=$(( ($VIASH_META_MEMORY_TIB+1023) / 1024 )) + else + # unset memory if string is empty + unset $VIASH_META_MEMORY_B + fi +fi +# unset nproc if string is empty +if [ -z "$VIASH_META_CPUS" ]; then + unset $VIASH_META_CPUS +fi + + +# check whether required parameters exist +if [ -z ${VIASH_PAR_GXF+x} ]; then + ViashError '--gxf' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi +if [ -z ${VIASH_PAR_OUTPUT+x} ]; then + ViashError '--output' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi +if [ -z ${VIASH_META_NAME+x} ]; then + ViashError 'name' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi +if [ -z ${VIASH_META_FUNCTIONALITY_NAME+x} ]; then + ViashError 'functionality_name' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi +if [ -z ${VIASH_META_RESOURCES_DIR+x} ]; then + ViashError 'resources_dir' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi +if [ -z ${VIASH_META_EXECUTABLE+x} ]; then + ViashError 'executable' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi +if [ -z ${VIASH_META_CONFIG+x} ]; then + ViashError 'config' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi +if [ -z ${VIASH_META_TEMP_DIR+x} ]; then + ViashError 'temp_dir' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi + +# check whether required files exist +if [ ! -z "$VIASH_PAR_GXF" ] && [ ! -e "$VIASH_PAR_GXF" ]; then + ViashError "Input file '$VIASH_PAR_GXF' does not exist." + exit 1 +fi +if [ ! -z "$VIASH_PAR_CONFIG" ] && [ ! -e "$VIASH_PAR_CONFIG" ]; then + ViashError "Input file '$VIASH_PAR_CONFIG' does not exist." + exit 1 +fi + +# check whether parameters values are of the right type +if [[ -n "$VIASH_META_CPUS" ]]; then + if ! [[ "$VIASH_META_CPUS" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'cpus' has to be an integer. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_B" ]]; then + if ! [[ "$VIASH_META_MEMORY_B" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_b' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_KB" ]]; then + if ! [[ "$VIASH_META_MEMORY_KB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_kb' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_MB" ]]; then + if ! [[ "$VIASH_META_MEMORY_MB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_mb' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_GB" ]]; then + if ! [[ "$VIASH_META_MEMORY_GB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_gb' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_TB" ]]; then + if ! [[ "$VIASH_META_MEMORY_TB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_tb' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_PB" ]]; then + if ! [[ "$VIASH_META_MEMORY_PB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_pb' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_KIB" ]]; then + if ! [[ "$VIASH_META_MEMORY_KIB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_kib' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_MIB" ]]; then + if ! [[ "$VIASH_META_MEMORY_MIB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_mib' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_GIB" ]]; then + if ! [[ "$VIASH_META_MEMORY_GIB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_gib' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_TIB" ]]; then + if ! [[ "$VIASH_META_MEMORY_TIB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_tib' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_PIB" ]]; then + if ! [[ "$VIASH_META_MEMORY_PIB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_pib' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi + +# create parent directories of output files, if so desired +if [ ! -z "$VIASH_PAR_OUTPUT" ] && [ ! -d "$(dirname "$VIASH_PAR_OUTPUT")" ]; then + mkdir -p "$(dirname "$VIASH_PAR_OUTPUT")" +fi + +if [ "$VIASH_ENGINE_ID" == "native" ] ; then + if [ "$VIASH_MODE" == "run" ]; then + VIASH_CMD="bash" + else + ViashError "Engine '$VIASH_ENGINE_ID' does not support mode '$VIASH_MODE'." + exit 1 + fi +fi + +if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then + # detect volumes from file arguments + VIASH_CHOWN_VARS=() +if [ ! -z "$VIASH_PAR_GXF" ]; then + VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_PAR_GXF")" ) + VIASH_PAR_GXF=$(ViashDockerAutodetectMount "$VIASH_PAR_GXF") +fi +if [ ! -z "$VIASH_PAR_OUTPUT" ]; then + VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_PAR_OUTPUT")" ) + VIASH_PAR_OUTPUT=$(ViashDockerAutodetectMount "$VIASH_PAR_OUTPUT") + VIASH_CHOWN_VARS+=( "$VIASH_PAR_OUTPUT" ) +fi +if [ ! -z "$VIASH_PAR_CONFIG" ]; then + VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_PAR_CONFIG")" ) + VIASH_PAR_CONFIG=$(ViashDockerAutodetectMount "$VIASH_PAR_CONFIG") +fi +if [ ! -z "$VIASH_META_RESOURCES_DIR" ]; then + VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_META_RESOURCES_DIR")" ) + VIASH_META_RESOURCES_DIR=$(ViashDockerAutodetectMount "$VIASH_META_RESOURCES_DIR") +fi +if [ ! -z "$VIASH_META_EXECUTABLE" ]; then + VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_META_EXECUTABLE")" ) + VIASH_META_EXECUTABLE=$(ViashDockerAutodetectMount "$VIASH_META_EXECUTABLE") +fi +if [ ! -z "$VIASH_META_CONFIG" ]; then + VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_META_CONFIG")" ) + VIASH_META_CONFIG=$(ViashDockerAutodetectMount "$VIASH_META_CONFIG") +fi +if [ ! -z "$VIASH_META_TEMP_DIR" ]; then + VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_META_TEMP_DIR")" ) + VIASH_META_TEMP_DIR=$(ViashDockerAutodetectMount "$VIASH_META_TEMP_DIR") +fi + + # get unique mounts + VIASH_UNIQUE_MOUNTS=($(for val in "${VIASH_DIRECTORY_MOUNTS[@]}"; do echo "$val"; done | sort -u)) +fi + +if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then + # change file ownership + function ViashPerformChown { + if (( ${#VIASH_CHOWN_VARS[@]} )); then + set +e + VIASH_CMD="docker run --entrypoint=bash --rm ${VIASH_UNIQUE_MOUNTS[@]} $VIASH_DOCKER_IMAGE_ID -c 'chown $(id -u):$(id -g) --silent --recursive ${VIASH_CHOWN_VARS[@]}'" + ViashDebug "+ $VIASH_CMD" + eval $VIASH_CMD + set -e + fi + } + trap ViashPerformChown EXIT +fi + +if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then + # helper function for filling in extra docker args + if [ ! -z "$VIASH_META_MEMORY_B" ]; then + VIASH_DOCKER_RUN_ARGS+=("--memory=${VIASH_META_MEMORY_B}") + fi + if [ ! -z "$VIASH_META_CPUS" ]; then + VIASH_DOCKER_RUN_ARGS+=("--cpus=${VIASH_META_CPUS}") + fi +fi + +if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then + VIASH_CMD="docker run --entrypoint=bash ${VIASH_DOCKER_RUN_ARGS[@]} ${VIASH_UNIQUE_MOUNTS[@]} $VIASH_DOCKER_IMAGE_ID" +fi + + +# set dependency paths + + +ViashDebug "Running command: $(echo $VIASH_CMD)" +cat << VIASHEOF | eval $VIASH_CMD +set -e +tempscript=\$(mktemp "$VIASH_META_TEMP_DIR/viash-run-agat_convert_sp_gxf2gxf-XXXXXX").sh +function clean_up { + rm "\$tempscript" +} +function interrupt { + echo -e "\nCTRL-C Pressed..." + exit 1 +} +trap clean_up EXIT +trap interrupt INT SIGINT +cat > "\$tempscript" << 'VIASHMAIN' +#!/bin/bash + +## VIASH START +# The following code has been auto-generated by Viash. +$( if [ ! -z ${VIASH_PAR_GXF+x} ]; then echo "${VIASH_PAR_GXF}" | sed "s#'#'\"'\"'#g;s#.*#par_gxf='&'#" ; else echo "# par_gxf="; fi ) +$( if [ ! -z ${VIASH_PAR_OUTPUT+x} ]; then echo "${VIASH_PAR_OUTPUT}" | sed "s#'#'\"'\"'#g;s#.*#par_output='&'#" ; else echo "# par_output="; fi ) +$( if [ ! -z ${VIASH_PAR_CONFIG+x} ]; then echo "${VIASH_PAR_CONFIG}" | sed "s#'#'\"'\"'#g;s#.*#par_config='&'#" ; else echo "# par_config="; fi ) +$( if [ ! -z ${VIASH_META_NAME+x} ]; then echo "${VIASH_META_NAME}" | sed "s#'#'\"'\"'#g;s#.*#meta_name='&'#" ; else echo "# meta_name="; fi ) +$( if [ ! -z ${VIASH_META_FUNCTIONALITY_NAME+x} ]; then echo "${VIASH_META_FUNCTIONALITY_NAME}" | sed "s#'#'\"'\"'#g;s#.*#meta_functionality_name='&'#" ; else echo "# meta_functionality_name="; fi ) +$( if [ ! -z ${VIASH_META_RESOURCES_DIR+x} ]; then echo "${VIASH_META_RESOURCES_DIR}" | sed "s#'#'\"'\"'#g;s#.*#meta_resources_dir='&'#" ; else echo "# meta_resources_dir="; fi ) +$( if [ ! -z ${VIASH_META_EXECUTABLE+x} ]; then echo "${VIASH_META_EXECUTABLE}" | sed "s#'#'\"'\"'#g;s#.*#meta_executable='&'#" ; else echo "# meta_executable="; fi ) +$( if [ ! -z ${VIASH_META_CONFIG+x} ]; then echo "${VIASH_META_CONFIG}" | sed "s#'#'\"'\"'#g;s#.*#meta_config='&'#" ; else echo "# meta_config="; fi ) +$( if [ ! -z ${VIASH_META_TEMP_DIR+x} ]; then echo "${VIASH_META_TEMP_DIR}" | sed "s#'#'\"'\"'#g;s#.*#meta_temp_dir='&'#" ; else echo "# meta_temp_dir="; fi ) +$( if [ ! -z ${VIASH_META_CPUS+x} ]; then echo "${VIASH_META_CPUS}" | sed "s#'#'\"'\"'#g;s#.*#meta_cpus='&'#" ; else echo "# meta_cpus="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_B+x} ]; then echo "${VIASH_META_MEMORY_B}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_b='&'#" ; else echo "# meta_memory_b="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_KB+x} ]; then echo "${VIASH_META_MEMORY_KB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_kb='&'#" ; else echo "# meta_memory_kb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_MB+x} ]; then echo "${VIASH_META_MEMORY_MB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_mb='&'#" ; else echo "# meta_memory_mb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_GB+x} ]; then echo "${VIASH_META_MEMORY_GB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_gb='&'#" ; else echo "# meta_memory_gb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_TB+x} ]; then echo "${VIASH_META_MEMORY_TB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_tb='&'#" ; else echo "# meta_memory_tb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_PB+x} ]; then echo "${VIASH_META_MEMORY_PB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_pb='&'#" ; else echo "# meta_memory_pb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_KIB+x} ]; then echo "${VIASH_META_MEMORY_KIB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_kib='&'#" ; else echo "# meta_memory_kib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_MIB+x} ]; then echo "${VIASH_META_MEMORY_MIB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_mib='&'#" ; else echo "# meta_memory_mib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_GIB+x} ]; then echo "${VIASH_META_MEMORY_GIB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_gib='&'#" ; else echo "# meta_memory_gib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_TIB+x} ]; then echo "${VIASH_META_MEMORY_TIB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_tib='&'#" ; else echo "# meta_memory_tib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_pib='&'#" ; else echo "# meta_memory_pib="; fi ) + +## VIASH END + +agat_convert_sp_gxf2gxf.pl \\ + -g "\$par_gxf" \\ + -o "\$par_output" \\ + \${par_config:+--config "\${par_config}"} +VIASHMAIN +bash "\$tempscript" & +wait "\$!" + +VIASHEOF + + +if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then + # strip viash automount from file paths + + if [ ! -z "$VIASH_PAR_GXF" ]; then + VIASH_PAR_GXF=$(ViashDockerStripAutomount "$VIASH_PAR_GXF") + fi + if [ ! -z "$VIASH_PAR_OUTPUT" ]; then + VIASH_PAR_OUTPUT=$(ViashDockerStripAutomount "$VIASH_PAR_OUTPUT") + fi + if [ ! -z "$VIASH_PAR_CONFIG" ]; then + VIASH_PAR_CONFIG=$(ViashDockerStripAutomount "$VIASH_PAR_CONFIG") + fi + if [ ! -z "$VIASH_META_RESOURCES_DIR" ]; then + VIASH_META_RESOURCES_DIR=$(ViashDockerStripAutomount "$VIASH_META_RESOURCES_DIR") + fi + if [ ! -z "$VIASH_META_EXECUTABLE" ]; then + VIASH_META_EXECUTABLE=$(ViashDockerStripAutomount "$VIASH_META_EXECUTABLE") + fi + if [ ! -z "$VIASH_META_CONFIG" ]; then + VIASH_META_CONFIG=$(ViashDockerStripAutomount "$VIASH_META_CONFIG") + fi + if [ ! -z "$VIASH_META_TEMP_DIR" ]; then + VIASH_META_TEMP_DIR=$(ViashDockerStripAutomount "$VIASH_META_TEMP_DIR") + fi +fi + + +# check whether required files exist +if [ ! -z "$VIASH_PAR_OUTPUT" ] && [ ! -e "$VIASH_PAR_OUTPUT" ]; then + ViashError "Output file '$VIASH_PAR_OUTPUT' does not exist." + exit 1 +fi + + +exit 0 diff --git a/target/executable/arriba/.config.vsh.yaml b/target/executable/arriba/.config.vsh.yaml index a1f95749..1ecee512 100644 --- a/target/executable/arriba/.config.vsh.yaml +++ b/target/executable/arriba/.config.vsh.yaml @@ -706,7 +706,7 @@ build_info: output: "target/executable/arriba" executable: "target/executable/arriba/arriba" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/arriba/arriba b/target/executable/arriba/arriba index f535e9f7..71fdbbaa 100755 --- a/target/executable/arriba/arriba +++ b/target/executable/arriba/arriba @@ -753,9 +753,9 @@ RUN arriba -h | grep 'Version:' 2>&1 | sed 's/Version:\s\(.*\)/arriba: "\1"/' > LABEL org.opencontainers.image.authors="Robrecht Cannoodt" LABEL org.opencontainers.image.description="Companion container for running component arriba" -LABEL org.opencontainers.image.created="2024-07-31T19:27:32Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:44Z" LABEL org.opencontainers.image.source="https://github.com/suhrig/arriba" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER diff --git a/target/executable/bcl_convert/.config.vsh.yaml b/target/executable/bcl_convert/.config.vsh.yaml index 1a32495f..81d67682 100644 --- a/target/executable/bcl_convert/.config.vsh.yaml +++ b/target/executable/bcl_convert/.config.vsh.yaml @@ -418,7 +418,7 @@ build_info: output: "target/executable/bcl_convert" executable: "target/executable/bcl_convert/bcl_convert" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/bcl_convert/bcl_convert b/target/executable/bcl_convert/bcl_convert index 1188bf21..9462c703 100755 --- a/target/executable/bcl_convert/bcl_convert +++ b/target/executable/bcl_convert/bcl_convert @@ -598,9 +598,9 @@ RUN echo "bcl-convert: \"$(bcl-convert -V 2>&1 >/dev/null | sed -n '/Version/ s/ LABEL org.opencontainers.image.authors="Toni Verbeiren, Dorien Roosen" LABEL org.opencontainers.image.description="Companion container for running component bcl_convert" -LABEL org.opencontainers.image.created="2024-07-31T19:27:33Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:45Z" LABEL org.opencontainers.image.source="https://github.com/viash-hub/biobox" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER diff --git a/target/executable/bd_rhapsody/bd_rhapsody_make_reference/.config.vsh.yaml b/target/executable/bd_rhapsody/bd_rhapsody_make_reference/.config.vsh.yaml index f33c93b0..ea4ce3ab 100644 --- a/target/executable/bd_rhapsody/bd_rhapsody_make_reference/.config.vsh.yaml +++ b/target/executable/bd_rhapsody/bd_rhapsody_make_reference/.config.vsh.yaml @@ -270,7 +270,7 @@ build_info: output: "target/executable/bd_rhapsody/bd_rhapsody_make_reference" executable: "target/executable/bd_rhapsody/bd_rhapsody_make_reference/bd_rhapsody_make_reference" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/bd_rhapsody/bd_rhapsody_make_reference/bd_rhapsody_make_reference b/target/executable/bd_rhapsody/bd_rhapsody_make_reference/bd_rhapsody_make_reference index 49537acd..0b614340 100755 --- a/target/executable/bd_rhapsody/bd_rhapsody_make_reference/bd_rhapsody_make_reference +++ b/target/executable/bd_rhapsody/bd_rhapsody_make_reference/bd_rhapsody_make_reference @@ -548,9 +548,9 @@ RUN echo "bdgenomics/rhapsody: 2.2.1" > /var/software_versions.txt LABEL org.opencontainers.image.authors="Robrecht Cannoodt, Weiwei Schultz" LABEL org.opencontainers.image.description="Companion container for running component bd_rhapsody bd_rhapsody_make_reference" -LABEL org.opencontainers.image.created="2024-07-31T19:27:40Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:53Z" LABEL org.opencontainers.image.source="https://bitbucket.org/CRSwDev/cwl/src/master/v2.2.1/Extra_Utilities/" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER diff --git a/target/executable/bedtools/bedtools_bamtofastq/.config.vsh.yaml b/target/executable/bedtools/bedtools_bamtofastq/.config.vsh.yaml new file mode 100644 index 00000000..db836704 --- /dev/null +++ b/target/executable/bedtools/bedtools_bamtofastq/.config.vsh.yaml @@ -0,0 +1,213 @@ +name: "bedtools_bamtofastq" +namespace: "bedtools" +version: "main" +authors: +- name: "Theodoro Gasperin Terra Camargo" + roles: + - "author" + - "maintainer" + info: + links: + email: "theodorogtc@gmail.com" + github: "tgaspe" + linkedin: "theodoro-gasperin-terra-camargo" + organizations: + - name: "Data Intuitive" + href: "https://www.data-intuitive.com" + role: "Bioinformatician" +argument_groups: +- name: "Inputs" + arguments: + - type: "file" + name: "--input" + alternatives: + - "-i" + description: "Input BAM file to be converted to FASTQ." + info: null + must_exist: true + create_parent: true + required: true + direction: "input" + multiple: false + multiple_sep: ";" +- name: "Outputs" + arguments: + - type: "file" + name: "--fastq" + alternatives: + - "-fq" + description: "Output FASTQ file." + info: null + must_exist: true + create_parent: true + required: true + direction: "output" + multiple: false + multiple_sep: ";" + - type: "file" + name: "--fastq2" + alternatives: + - "-fq2" + description: "FASTQ for second end. Used if BAM contains paired-end data.\nBAM\ + \ should be sorted by query name is creating paired FASTQ.\n" + info: null + must_exist: true + create_parent: true + required: false + direction: "output" + multiple: false + multiple_sep: ";" +- name: "Options" + arguments: + - type: "boolean_true" + name: "--tags" + description: "Create FASTQ based on the mate info in the BAM R2 and Q2 tags.\n" + info: null + direction: "input" +resources: +- type: "bash_script" + path: "script.sh" + is_executable: true +description: "Conversion tool for extracting FASTQ records from sequence alignments\ + \ in BAM format.\n" +test_resources: +- type: "bash_script" + path: "test.sh" + is_executable: true +- type: "file" + path: "test_data" +info: null +status: "enabled" +requirements: + commands: + - "ps" +keywords: +- "Conversion" +- "BAM" +- "FASTQ" +license: "MIT" +references: + doi: + - "10.1093/bioinformatics/btq033" +links: + repository: "https://github.com/arq5x/bedtools2" + homepage: "https://bedtools.readthedocs.io/en/latest/#" + documentation: "https://bedtools.readthedocs.io/en/latest/content/tools/bamtofastq.html" + issue_tracker: "https://github.com/arq5x/bedtools2/issues" +runners: +- type: "executable" + id: "executable" + docker_setup_strategy: "ifneedbepullelsecachedbuild" +- type: "nextflow" + id: "nextflow" + directives: + tag: "$id" + auto: + simplifyInput: true + simplifyOutput: false + transcript: false + publish: false + config: + labels: + mem1gb: "memory = 1000000000.B" + mem2gb: "memory = 2000000000.B" + mem5gb: "memory = 5000000000.B" + mem10gb: "memory = 10000000000.B" + mem20gb: "memory = 20000000000.B" + mem50gb: "memory = 50000000000.B" + mem100gb: "memory = 100000000000.B" + mem200gb: "memory = 200000000000.B" + mem500gb: "memory = 500000000000.B" + mem1tb: "memory = 1000000000000.B" + mem2tb: "memory = 2000000000000.B" + mem5tb: "memory = 5000000000000.B" + mem10tb: "memory = 10000000000000.B" + mem20tb: "memory = 20000000000000.B" + mem50tb: "memory = 50000000000000.B" + mem100tb: "memory = 100000000000000.B" + mem200tb: "memory = 200000000000000.B" + mem500tb: "memory = 500000000000000.B" + mem1gib: "memory = 1073741824.B" + mem2gib: "memory = 2147483648.B" + mem4gib: "memory = 4294967296.B" + mem8gib: "memory = 8589934592.B" + mem16gib: "memory = 17179869184.B" + mem32gib: "memory = 34359738368.B" + mem64gib: "memory = 68719476736.B" + mem128gib: "memory = 137438953472.B" + mem256gib: "memory = 274877906944.B" + mem512gib: "memory = 549755813888.B" + mem1tib: "memory = 1099511627776.B" + mem2tib: "memory = 2199023255552.B" + mem4tib: "memory = 4398046511104.B" + mem8tib: "memory = 8796093022208.B" + mem16tib: "memory = 17592186044416.B" + mem32tib: "memory = 35184372088832.B" + mem64tib: "memory = 70368744177664.B" + mem128tib: "memory = 140737488355328.B" + mem256tib: "memory = 281474976710656.B" + mem512tib: "memory = 562949953421312.B" + cpu1: "cpus = 1" + cpu2: "cpus = 2" + cpu5: "cpus = 5" + cpu10: "cpus = 10" + cpu20: "cpus = 20" + cpu50: "cpus = 50" + cpu100: "cpus = 100" + cpu200: "cpus = 200" + cpu500: "cpus = 500" + cpu1000: "cpus = 1000" + debug: false + container: "docker" +engines: +- type: "docker" + id: "docker" + image: "debian:stable-slim" + target_registry: "images.viash-hub.com" + target_tag: "main" + namespace_separator: "/" + setup: + - type: "apt" + packages: + - "bedtools" + - "procps" + interactive: false + - type: "docker" + run: + - "echo \"bedtools: \\\"$(bedtools --version | sed -n 's/^bedtools //p')\\\"\"\ + \ > /var/software_versions.txt\n" + entrypoint: [] + cmd: null +- type: "native" + id: "native" +build_info: + config: "src/bedtools/bedtools_bamtofastq/config.vsh.yaml" + runner: "executable" + engine: "docker|native" + output: "target/executable/bedtools/bedtools_bamtofastq" + executable: "target/executable/bedtools/bedtools_bamtofastq/bedtools_bamtofastq" + viash_version: "0.9.0-RC6" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" + git_remote: "https://github.com/viash-hub/biobox" +package_config: + name: "biobox" + version: "main" + description: "A collection of bioinformatics tools for working with sequence data.\n" + info: null + viash_version: "0.9.0-RC6" + source: "src" + target: "target" + config_mods: + - ".requirements.commands := ['ps']\n" + - ".engines += { type: \"native\" }" + - ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'" + - ".engines[.type == 'docker'].target_tag := 'main'" + keywords: + - "bioinformatics" + - "modules" + - "sequencing" + license: "MIT" + organization: "vsh" + links: + repository: "https://github.com/viash-hub/biobox" + issue_tracker: "https://github.com/viash-hub/biobox/issues" diff --git a/target/executable/bedtools/bedtools_bamtofastq/bedtools_bamtofastq b/target/executable/bedtools/bedtools_bamtofastq/bedtools_bamtofastq new file mode 100755 index 00000000..95624099 --- /dev/null +++ b/target/executable/bedtools/bedtools_bamtofastq/bedtools_bamtofastq @@ -0,0 +1,1138 @@ +#!/usr/bin/env bash + +# bedtools_bamtofastq main +# +# This wrapper script is auto-generated by viash 0.9.0-RC6 and is thus a +# derivative work thereof. This software comes with ABSOLUTELY NO WARRANTY from +# Data Intuitive. +# +# The component may contain files which fall under a different license. The +# authors of this component should specify the license in the header of such +# files, or include a separate license file detailing the licenses of all included +# files. +# +# Component authors: +# * Theodoro Gasperin Terra Camargo (author, maintainer) + +set -e + +if [ -z "$VIASH_TEMP" ]; then + VIASH_TEMP=${VIASH_TEMP:-$VIASH_TMPDIR} + VIASH_TEMP=${VIASH_TEMP:-$VIASH_TEMPDIR} + VIASH_TEMP=${VIASH_TEMP:-$VIASH_TMP} + VIASH_TEMP=${VIASH_TEMP:-$TMPDIR} + VIASH_TEMP=${VIASH_TEMP:-$TMP} + VIASH_TEMP=${VIASH_TEMP:-$TEMPDIR} + VIASH_TEMP=${VIASH_TEMP:-$TEMP} + VIASH_TEMP=${VIASH_TEMP:-/tmp} +fi + +# define helper functions +# ViashQuote: put quotes around non flag values +# $1 : unquoted string +# return : possibly quoted string +# examples: +# ViashQuote --foo # returns --foo +# ViashQuote bar # returns 'bar' +# Viashquote --foo=bar # returns --foo='bar' +function ViashQuote { + if [[ "$1" =~ ^-+[a-zA-Z0-9_\-]+=.+$ ]]; then + echo "$1" | sed "s#=\(.*\)#='\1'#" + elif [[ "$1" =~ ^-+[a-zA-Z0-9_\-]+$ ]]; then + echo "$1" + else + echo "'$1'" + fi +} +# ViashRemoveFlags: Remove leading flag +# $1 : string with a possible leading flag +# return : string without possible leading flag +# examples: +# ViashRemoveFlags --foo=bar # returns bar +function ViashRemoveFlags { + echo "$1" | sed 's/^--*[a-zA-Z0-9_\-]*=//' +} +# ViashSourceDir: return the path of a bash file, following symlinks +# usage : ViashSourceDir ${BASH_SOURCE[0]} +# $1 : Should always be set to ${BASH_SOURCE[0]} +# returns : The absolute path of the bash file +function ViashSourceDir { + SOURCE="$1" + while [ -h "$SOURCE" ]; do + DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )" + SOURCE="$(readlink "$SOURCE")" + [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" + done + cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd +} +# ViashFindTargetDir: return the path of the '.build.yaml' file, following symlinks +# usage : ViashFindTargetDir 'ScriptPath' +# $1 : The location from where to start the upward search +# returns : The absolute path of the '.build.yaml' file +function ViashFindTargetDir { + SOURCE="$1" + while [[ "$SOURCE" != "" && ! -e "$SOURCE/.build.yaml" ]]; do + SOURCE=${SOURCE%/*} + done + echo $SOURCE +} +# see https://en.wikipedia.org/wiki/Syslog#Severity_level +VIASH_LOGCODE_EMERGENCY=0 +VIASH_LOGCODE_ALERT=1 +VIASH_LOGCODE_CRITICAL=2 +VIASH_LOGCODE_ERROR=3 +VIASH_LOGCODE_WARNING=4 +VIASH_LOGCODE_NOTICE=5 +VIASH_LOGCODE_INFO=6 +VIASH_LOGCODE_DEBUG=7 +VIASH_VERBOSITY=$VIASH_LOGCODE_NOTICE + +# ViashLog: Log events depending on the verbosity level +# usage: ViashLog 1 alert Oh no something went wrong! +# $1: required verbosity level +# $2: display tag +# $3+: messages to display +# stdout: Your input, prepended by '[$2] '. +function ViashLog { + local required_level="$1" + local display_tag="$2" + shift 2 + if [ $VIASH_VERBOSITY -ge $required_level ]; then + >&2 echo "[$display_tag]" "$@" + fi +} + +# ViashEmergency: log events when the system is unstable +# usage: ViashEmergency Oh no something went wrong. +# stdout: Your input, prepended by '[emergency] '. +function ViashEmergency { + ViashLog $VIASH_LOGCODE_EMERGENCY emergency "$@" +} + +# ViashAlert: log events when actions must be taken immediately (e.g. corrupted system database) +# usage: ViashAlert Oh no something went wrong. +# stdout: Your input, prepended by '[alert] '. +function ViashAlert { + ViashLog $VIASH_LOGCODE_ALERT alert "$@" +} + +# ViashCritical: log events when a critical condition occurs +# usage: ViashCritical Oh no something went wrong. +# stdout: Your input, prepended by '[critical] '. +function ViashCritical { + ViashLog $VIASH_LOGCODE_CRITICAL critical "$@" +} + +# ViashError: log events when an error condition occurs +# usage: ViashError Oh no something went wrong. +# stdout: Your input, prepended by '[error] '. +function ViashError { + ViashLog $VIASH_LOGCODE_ERROR error "$@" +} + +# ViashWarning: log potentially abnormal events +# usage: ViashWarning Something may have gone wrong. +# stdout: Your input, prepended by '[warning] '. +function ViashWarning { + ViashLog $VIASH_LOGCODE_WARNING warning "$@" +} + +# ViashNotice: log significant but normal events +# usage: ViashNotice This just happened. +# stdout: Your input, prepended by '[notice] '. +function ViashNotice { + ViashLog $VIASH_LOGCODE_NOTICE notice "$@" +} + +# ViashInfo: log normal events +# usage: ViashInfo This just happened. +# stdout: Your input, prepended by '[info] '. +function ViashInfo { + ViashLog $VIASH_LOGCODE_INFO info "$@" +} + +# ViashDebug: log all events, for debugging purposes +# usage: ViashDebug This just happened. +# stdout: Your input, prepended by '[debug] '. +function ViashDebug { + ViashLog $VIASH_LOGCODE_DEBUG debug "$@" +} + +# find source folder of this component +VIASH_META_RESOURCES_DIR=`ViashSourceDir ${BASH_SOURCE[0]}` + +# find the root of the built components & dependencies +VIASH_TARGET_DIR=`ViashFindTargetDir $VIASH_META_RESOURCES_DIR` + +# define meta fields +VIASH_META_NAME="bedtools_bamtofastq" +VIASH_META_FUNCTIONALITY_NAME="bedtools_bamtofastq" +VIASH_META_EXECUTABLE="$VIASH_META_RESOURCES_DIR/$VIASH_META_NAME" +VIASH_META_CONFIG="$VIASH_META_RESOURCES_DIR/.config.vsh.yaml" +VIASH_META_TEMP_DIR="$VIASH_TEMP" + + +# ViashHelp: Display helpful explanation about this executable +function ViashHelp { + echo "bedtools_bamtofastq main" + echo "" + echo "Conversion tool for extracting FASTQ records from sequence alignments in BAM" + echo "format." + echo "" + echo "Inputs:" + echo " -i, --input" + echo " type: file, required parameter, file must exist" + echo " Input BAM file to be converted to FASTQ." + echo "" + echo "Outputs:" + echo " -fq, --fastq" + echo " type: file, required parameter, output, file must exist" + echo " Output FASTQ file." + echo "" + echo " -fq2, --fastq2" + echo " type: file, output, file must exist" + echo " FASTQ for second end. Used if BAM contains paired-end data." + echo " BAM should be sorted by query name is creating paired FASTQ." + echo "" + echo "Options:" + echo " --tags" + echo " type: boolean_true" + echo " Create FASTQ based on the mate info in the BAM R2 and Q2 tags." +} + +# initialise variables +VIASH_MODE='run' +VIASH_ENGINE_ID='docker' + +######## Helper functions for setting up Docker images for viash ######## +# expects: ViashDockerBuild + +# ViashDockerInstallationCheck: check whether Docker is installed correctly +# +# examples: +# ViashDockerInstallationCheck +function ViashDockerInstallationCheck { + ViashDebug "Checking whether Docker is installed" + if [ ! command -v docker &> /dev/null ]; then + ViashCritical "Docker doesn't seem to be installed. See 'https://docs.docker.com/get-docker/' for instructions." + exit 1 + fi + + ViashDebug "Checking whether the Docker daemon is running" + save=$-; set +e + docker_version=$(docker version --format '{{.Client.APIVersion}}' 2> /dev/null) + out=$? + [[ $save =~ e ]] && set -e + if [ $out -ne 0 ]; then + ViashCritical "Docker daemon does not seem to be running. Try one of the following:" + ViashCritical "- Try running 'dockerd' in the command line" + ViashCritical "- See https://docs.docker.com/config/daemon/" + exit 1 + fi +} + +# ViashDockerRemoteTagCheck: check whether a Docker image is available +# on a remote. Assumes `docker login` has been performed, if relevant. +# +# $1 : image identifier with format `[registry/]image[:tag]` +# exit code $? : whether or not the image was found +# examples: +# ViashDockerRemoteTagCheck python:latest +# echo $? # returns '0' +# ViashDockerRemoteTagCheck sdaizudceahifu +# echo $? # returns '1' +function ViashDockerRemoteTagCheck { + docker manifest inspect $1 > /dev/null 2> /dev/null +} + +# ViashDockerLocalTagCheck: check whether a Docker image is available locally +# +# $1 : image identifier with format `[registry/]image[:tag]` +# exit code $? : whether or not the image was found +# examples: +# docker pull python:latest +# ViashDockerLocalTagCheck python:latest +# echo $? # returns '0' +# ViashDockerLocalTagCheck sdaizudceahifu +# echo $? # returns '1' +function ViashDockerLocalTagCheck { + [ -n "$(docker images -q $1)" ] +} + +# ViashDockerPull: pull a Docker image +# +# $1 : image identifier with format `[registry/]image[:tag]` +# exit code $? : whether or not the image was found +# examples: +# ViashDockerPull python:latest +# echo $? # returns '0' +# ViashDockerPull sdaizudceahifu +# echo $? # returns '1' +function ViashDockerPull { + ViashNotice "Checking if Docker image is available at '$1'" + if [ $VIASH_VERBOSITY -ge $VIASH_LOGCODE_INFO ]; then + docker pull $1 && return 0 || return 1 + else + save=$-; set +e + docker pull $1 2> /dev/null > /dev/null + out=$? + [[ $save =~ e ]] && set -e + if [ $out -ne 0 ]; then + ViashWarning "Could not pull from '$1'. Docker image doesn't exist or is not accessible." + fi + return $out + fi +} + +# ViashDockerPush: push a Docker image +# +# $1 : image identifier with format `[registry/]image[:tag]` +# exit code $? : whether or not the image was found +# examples: +# ViashDockerPush python:latest +# echo $? # returns '0' +# ViashDockerPush sdaizudceahifu +# echo $? # returns '1' +function ViashDockerPush { + ViashNotice "Pushing image to '$1'" + save=$-; set +e + if [ $VIASH_VERBOSITY -ge $VIASH_LOGCODE_INFO ]; then + docker push $1 + out=$? + else + docker push $1 2> /dev/null > /dev/null + out=$? + fi + [[ $save =~ e ]] && set -e + if [ $out -eq 0 ]; then + ViashNotice "Container '$1' push succeeded." + else + ViashError "Container '$1' push errored. You might not be logged in or have the necessary permissions." + fi + return $out +} + +# ViashDockerPullElseBuild: pull a Docker image, else build it +# +# $1 : image identifier with format `[registry/]image[:tag]` +# ViashDockerBuild : a Bash function which builds a docker image, takes image identifier as argument. +# examples: +# ViashDockerPullElseBuild mynewcomponent +function ViashDockerPullElseBuild { + save=$-; set +e + ViashDockerPull $1 + out=$? + [[ $save =~ e ]] && set -e + if [ $out -ne 0 ]; then + ViashDockerBuild $@ + fi +} + +# ViashDockerSetup: create a Docker image, according to specified docker setup strategy +# +# $1 : image identifier with format `[registry/]image[:tag]` +# $2 : docker setup strategy, see DockerSetupStrategy.scala +# examples: +# ViashDockerSetup mynewcomponent alwaysbuild +function ViashDockerSetup { + local image_id="$1" + local setup_strategy="$2" + if [ "$setup_strategy" == "alwaysbuild" -o "$setup_strategy" == "build" -o "$setup_strategy" == "b" ]; then + ViashDockerBuild $image_id --no-cache $(ViashDockerBuildArgs "$engine_id") + elif [ "$setup_strategy" == "alwayspull" -o "$setup_strategy" == "pull" -o "$setup_strategy" == "p" ]; then + ViashDockerPull $image_id + elif [ "$setup_strategy" == "alwayspullelsebuild" -o "$setup_strategy" == "pullelsebuild" ]; then + ViashDockerPullElseBuild $image_id --no-cache $(ViashDockerBuildArgs "$engine_id") + elif [ "$setup_strategy" == "alwayspullelsecachedbuild" -o "$setup_strategy" == "pullelsecachedbuild" ]; then + ViashDockerPullElseBuild $image_id $(ViashDockerBuildArgs "$engine_id") + elif [ "$setup_strategy" == "alwayscachedbuild" -o "$setup_strategy" == "cachedbuild" -o "$setup_strategy" == "cb" ]; then + ViashDockerBuild $image_id $(ViashDockerBuildArgs "$engine_id") + elif [[ "$setup_strategy" =~ ^ifneedbe ]]; then + local save=$-; set +e + ViashDockerLocalTagCheck $image_id + local outCheck=$? + [[ $save =~ e ]] && set -e + if [ $outCheck -eq 0 ]; then + ViashInfo "Image $image_id already exists" + elif [ "$setup_strategy" == "ifneedbebuild" ]; then + ViashDockerBuild $image_id --no-cache $(ViashDockerBuildArgs "$engine_id") + elif [ "$setup_strategy" == "ifneedbecachedbuild" ]; then + ViashDockerBuild $image_id $(ViashDockerBuildArgs "$engine_id") + elif [ "$setup_strategy" == "ifneedbepull" ]; then + ViashDockerPull $image_id + elif [ "$setup_strategy" == "ifneedbepullelsebuild" ]; then + ViashDockerPullElseBuild $image_id --no-cache $(ViashDockerBuildArgs "$engine_id") + elif [ "$setup_strategy" == "ifneedbepullelsecachedbuild" ]; then + ViashDockerPullElseBuild $image_id $(ViashDockerBuildArgs "$engine_id") + else + ViashError "Unrecognised Docker strategy: $setup_strategy" + exit 1 + fi + elif [ "$setup_strategy" == "push" -o "$setup_strategy" == "forcepush" -o "$setup_strategy" == "alwayspush" ]; then + ViashDockerPush "$image_id" + elif [ "$setup_strategy" == "pushifnotpresent" -o "$setup_strategy" == "gentlepush" -o "$setup_strategy" == "maybepush" ]; then + local save=$-; set +e + ViashDockerRemoteTagCheck $image_id + local outCheck=$? + [[ $save =~ e ]] && set -e + if [ $outCheck -eq 0 ]; then + ViashNotice "Container '$image_id' exists, doing nothing." + else + ViashNotice "Container '$image_id' does not yet exist." + ViashDockerPush "$image_id" + fi + elif [ "$setup_strategy" == "donothing" -o "$setup_strategy" == "meh" ]; then + ViashNotice "Skipping setup." + else + ViashError "Unrecognised Docker strategy: $setup_strategy" + exit 1 + fi +} + +# ViashDockerCheckCommands: Check whether a docker container has the required commands +# +# $1 : image identifier with format `[registry/]image[:tag]` +# $@ : commands to verify being present +# examples: +# ViashDockerCheckCommands bash:4.0 bash ps foo +function ViashDockerCheckCommands { + local image_id="$1" + shift 1 + local commands="$@" + local save=$-; set +e + local missing # mark 'missing' as local in advance, otherwise the exit code of the command will be missing and always be '0' + missing=$(docker run --rm --entrypoint=sh "$image_id" -c "for command in $commands; do command -v \$command >/dev/null 2>&1; if [ \$? -ne 0 ]; then echo \$command; exit 1; fi; done") + local outCheck=$? + [[ $save =~ e ]] && set -e + if [ $outCheck -ne 0 ]; then + ViashError "Docker container '$image_id' does not contain command '$missing'." + exit 1 + fi +} + +# ViashDockerBuild: build a docker image +# $1 : image identifier with format `[registry/]image[:tag]` +# $... : additional arguments to pass to docker build +# $VIASH_META_TEMP_DIR : temporary directory to store dockerfile & optional resources in +# $VIASH_META_NAME : name of the component +# $VIASH_META_RESOURCES_DIR : directory containing the resources +# $VIASH_VERBOSITY : verbosity level +# exit code $? : whether or not the image was built successfully +function ViashDockerBuild { + local image_id="$1" + shift 1 + + # create temporary directory to store dockerfile & optional resources in + local tmpdir=$(mktemp -d "$VIASH_META_TEMP_DIR/dockerbuild-$VIASH_META_NAME-XXXXXX") + local dockerfile="$tmpdir/Dockerfile" + function clean_up { + rm -rf "$tmpdir" + } + trap clean_up EXIT + + # store dockerfile and resources + ViashDockerfile "$VIASH_ENGINE_ID" > "$dockerfile" + + # generate the build command + local docker_build_cmd="docker build -t '$image_id' $@ '$VIASH_META_RESOURCES_DIR' -f '$dockerfile'" + + # build the container + ViashNotice "Building container '$image_id' with Dockerfile" + ViashInfo "$docker_build_cmd" + local save=$-; set +e + if [ $VIASH_VERBOSITY -ge $VIASH_LOGCODE_INFO ]; then + eval $docker_build_cmd + else + eval $docker_build_cmd &> "$tmpdir/docker_build.log" + fi + + # check exit code + local out=$? + [[ $save =~ e ]] && set -e + if [ $out -ne 0 ]; then + ViashError "Error occurred while building container '$image_id'" + if [ $VIASH_VERBOSITY -lt $VIASH_LOGCODE_INFO ]; then + ViashError "Transcript: --------------------------------" + cat "$tmpdir/docker_build.log" + ViashError "End of transcript --------------------------" + fi + exit 1 + fi +} + +######## End of helper functions for setting up Docker images for viash ######## + +# ViashDockerFile: print the dockerfile to stdout +# $1 : engine identifier +# return : dockerfile required to run this component +# examples: +# ViashDockerFile +function ViashDockerfile { + local engine_id="$1" + + if [[ "$engine_id" == "docker" ]]; then + cat << 'VIASHDOCKER' +FROM debian:stable-slim +ENTRYPOINT [] +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y bedtools procps && \ + rm -rf /var/lib/apt/lists/* + +RUN echo "bedtools: \"$(bedtools --version | sed -n 's/^bedtools //p')\"" > /var/software_versions.txt + +LABEL org.opencontainers.image.authors="Theodoro Gasperin Terra Camargo" +LABEL org.opencontainers.image.description="Companion container for running component bedtools bedtools_bamtofastq" +LABEL org.opencontainers.image.created="2024-08-14T20:58:47Z" +LABEL org.opencontainers.image.source="https://github.com/arq5x/bedtools2" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" +LABEL org.opencontainers.image.version="main" + +VIASHDOCKER + fi +} + +# ViashDockerBuildArgs: return the arguments to pass to docker build +# $1 : engine identifier +# return : arguments to pass to docker build +function ViashDockerBuildArgs { + local engine_id="$1" + + if [[ "$engine_id" == "docker" ]]; then + echo "" + fi +} + +# ViashAbsolutePath: generate absolute path from relative path +# borrowed from https://stackoverflow.com/a/21951256 +# $1 : relative filename +# return : absolute path +# examples: +# ViashAbsolutePath some_file.txt # returns /path/to/some_file.txt +# ViashAbsolutePath /foo/bar/.. # returns /foo +function ViashAbsolutePath { + local thePath + if [[ ! "$1" =~ ^/ ]]; then + thePath="$PWD/$1" + else + thePath="$1" + fi + echo "$thePath" | ( + IFS=/ + read -a parr + declare -a outp + for i in "${parr[@]}"; do + case "$i" in + ''|.) continue ;; + ..) + len=${#outp[@]} + if ((len==0)); then + continue + else + unset outp[$((len-1))] + fi + ;; + *) + len=${#outp[@]} + outp[$len]="$i" + ;; + esac + done + echo /"${outp[*]}" + ) +} +# ViashDockerAutodetectMount: auto configuring docker mounts from parameters +# $1 : The parameter value +# returns : New parameter +# $VIASH_DIRECTORY_MOUNTS : Added another parameter to be passed to docker +# examples: +# ViashDockerAutodetectMount /path/to/bar # returns '/viash_automount/path/to/bar' +# ViashDockerAutodetectMountArg /path/to/bar # returns '--volume="/path/to:/viash_automount/path/to"' +function ViashDockerAutodetectMount { + abs_path=$(ViashAbsolutePath "$1") + if [ -d "$abs_path" ]; then + mount_source="$abs_path" + base_name="" + else + mount_source=`dirname "$abs_path"` + base_name=`basename "$abs_path"` + fi + mount_target="/viash_automount$mount_source" + if [ -z "$base_name" ]; then + echo "$mount_target" + else + echo "$mount_target/$base_name" + fi +} +function ViashDockerAutodetectMountArg { + abs_path=$(ViashAbsolutePath "$1") + if [ -d "$abs_path" ]; then + mount_source="$abs_path" + base_name="" + else + mount_source=`dirname "$abs_path"` + base_name=`basename "$abs_path"` + fi + mount_target="/viash_automount$mount_source" + ViashDebug "ViashDockerAutodetectMountArg $1 -> $mount_source -> $mount_target" + echo "--volume=\"$mount_source:$mount_target\"" +} +function ViashDockerStripAutomount { + abs_path=$(ViashAbsolutePath "$1") + echo "${abs_path#/viash_automount}" +} +# initialise variables +VIASH_DIRECTORY_MOUNTS=() + +# initialise docker variables +VIASH_DOCKER_RUN_ARGS=(-i --rm) + +# initialise array +VIASH_POSITIONAL_ARGS='' + +while [[ $# -gt 0 ]]; do + case "$1" in + -h|--help) + ViashHelp + exit + ;; + ---v|---verbose) + let "VIASH_VERBOSITY=VIASH_VERBOSITY+1" + shift 1 + ;; + ---verbosity) + VIASH_VERBOSITY="$2" + shift 2 + ;; + ---verbosity=*) + VIASH_VERBOSITY="$(ViashRemoveFlags "$1")" + shift 1 + ;; + --version) + echo "bedtools_bamtofastq main" + exit + ;; + --input) + [ -n "$VIASH_PAR_INPUT" ] && ViashError Bad arguments for option \'--input\': \'$VIASH_PAR_INPUT\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_INPUT="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to --input. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --input=*) + [ -n "$VIASH_PAR_INPUT" ] && ViashError Bad arguments for option \'--input=*\': \'$VIASH_PAR_INPUT\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_INPUT=$(ViashRemoveFlags "$1") + shift 1 + ;; + -i) + [ -n "$VIASH_PAR_INPUT" ] && ViashError Bad arguments for option \'-i\': \'$VIASH_PAR_INPUT\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_INPUT="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to -i. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --fastq) + [ -n "$VIASH_PAR_FASTQ" ] && ViashError Bad arguments for option \'--fastq\': \'$VIASH_PAR_FASTQ\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_FASTQ="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to --fastq. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --fastq=*) + [ -n "$VIASH_PAR_FASTQ" ] && ViashError Bad arguments for option \'--fastq=*\': \'$VIASH_PAR_FASTQ\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_FASTQ=$(ViashRemoveFlags "$1") + shift 1 + ;; + -fq) + [ -n "$VIASH_PAR_FASTQ" ] && ViashError Bad arguments for option \'-fq\': \'$VIASH_PAR_FASTQ\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_FASTQ="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to -fq. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --fastq2) + [ -n "$VIASH_PAR_FASTQ2" ] && ViashError Bad arguments for option \'--fastq2\': \'$VIASH_PAR_FASTQ2\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_FASTQ2="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to --fastq2. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --fastq2=*) + [ -n "$VIASH_PAR_FASTQ2" ] && ViashError Bad arguments for option \'--fastq2=*\': \'$VIASH_PAR_FASTQ2\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_FASTQ2=$(ViashRemoveFlags "$1") + shift 1 + ;; + -fq2) + [ -n "$VIASH_PAR_FASTQ2" ] && ViashError Bad arguments for option \'-fq2\': \'$VIASH_PAR_FASTQ2\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_FASTQ2="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to -fq2. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --tags) + [ -n "$VIASH_PAR_TAGS" ] && ViashError Bad arguments for option \'--tags\': \'$VIASH_PAR_TAGS\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_TAGS=true + shift 1 + ;; + ---engine) + VIASH_ENGINE_ID="$2" + shift 2 + ;; + ---engine=*) + VIASH_ENGINE_ID="$(ViashRemoveFlags "$1")" + shift 1 + ;; + ---setup) + VIASH_MODE='setup' + VIASH_SETUP_STRATEGY="$2" + shift 2 + ;; + ---setup=*) + VIASH_MODE='setup' + VIASH_SETUP_STRATEGY="$(ViashRemoveFlags "$1")" + shift 1 + ;; + ---dockerfile) + VIASH_MODE='dockerfile' + shift 1 + ;; + ---debug) + VIASH_MODE='debug' + shift 1 + ;; + ---cpus) + [ -n "$VIASH_META_CPUS" ] && ViashError Bad arguments for option \'---cpus\': \'$VIASH_META_CPUS\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_META_CPUS="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to ---cpus. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + ---cpus=*) + [ -n "$VIASH_META_CPUS" ] && ViashError Bad arguments for option \'---cpus=*\': \'$VIASH_META_CPUS\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_META_CPUS=$(ViashRemoveFlags "$1") + shift 1 + ;; + ---memory) + [ -n "$VIASH_META_MEMORY" ] && ViashError Bad arguments for option \'---memory\': \'$VIASH_META_MEMORY\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_META_MEMORY="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to ---memory. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + ---memory=*) + [ -n "$VIASH_META_MEMORY" ] && ViashError Bad arguments for option \'---memory=*\': \'$VIASH_META_MEMORY\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_META_MEMORY=$(ViashRemoveFlags "$1") + shift 1 + ;; + *) # positional arg or unknown option + # since the positional args will be eval'd, can we always quote, instead of using ViashQuote + VIASH_POSITIONAL_ARGS="$VIASH_POSITIONAL_ARGS '$1'" + [[ $1 == -* ]] && ViashWarning $1 looks like a parameter but is not a defined parameter and will instead be treated as a positional argument. Use "--help" to get more information on the parameters. + shift # past argument + ;; + esac +done + +# parse positional parameters +eval set -- $VIASH_POSITIONAL_ARGS + + +if [ "$VIASH_ENGINE_ID" == "native" ] ; then + VIASH_ENGINE_TYPE='native' +elif [ "$VIASH_ENGINE_ID" == "docker" ] ; then + VIASH_ENGINE_TYPE='docker' +else + ViashError "Engine '$VIASH_ENGINE_ID' is not recognized. Options are: docker, native." + exit 1 +fi + +if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then + # check if docker is installed properly + ViashDockerInstallationCheck + + # determine docker image id + if [[ "$VIASH_ENGINE_ID" == 'docker' ]]; then + VIASH_DOCKER_IMAGE_ID='images.viash-hub.com/vsh/biobox/bedtools/bedtools_bamtofastq:main' + fi + + # print dockerfile + if [ "$VIASH_MODE" == "dockerfile" ]; then + ViashDockerfile "$VIASH_ENGINE_ID" + exit 0 + + # enter docker container + elif [[ "$VIASH_MODE" == "debug" ]]; then + VIASH_CMD="docker run --entrypoint=bash ${VIASH_DOCKER_RUN_ARGS[@]} -v '$(pwd)':/pwd --workdir /pwd -t $VIASH_DOCKER_IMAGE_ID" + ViashNotice "+ $VIASH_CMD" + eval $VIASH_CMD + exit + + # build docker image + elif [ "$VIASH_MODE" == "setup" ]; then + ViashDockerSetup "$VIASH_DOCKER_IMAGE_ID" "$VIASH_SETUP_STRATEGY" + ViashDockerCheckCommands "$VIASH_DOCKER_IMAGE_ID" 'ps' 'bash' + exit 0 + fi + + # check if docker image exists + ViashDockerSetup "$VIASH_DOCKER_IMAGE_ID" ifneedbepullelsecachedbuild + ViashDockerCheckCommands "$VIASH_DOCKER_IMAGE_ID" 'ps' 'bash' +fi + +# setting computational defaults + +# helper function for parsing memory strings +function ViashMemoryAsBytes { + local memory=`echo "$1" | tr '[:upper:]' '[:lower:]' | tr -d '[:space:]'` + local memory_regex='^([0-9]+)([kmgtp]i?b?|b)$' + if [[ $memory =~ $memory_regex ]]; then + local number=${memory/[^0-9]*/} + local symbol=${memory/*[0-9]/} + + case $symbol in + b) memory_b=$number ;; + kb|k) memory_b=$(( $number * 1000 )) ;; + mb|m) memory_b=$(( $number * 1000 * 1000 )) ;; + gb|g) memory_b=$(( $number * 1000 * 1000 * 1000 )) ;; + tb|t) memory_b=$(( $number * 1000 * 1000 * 1000 * 1000 )) ;; + pb|p) memory_b=$(( $number * 1000 * 1000 * 1000 * 1000 * 1000 )) ;; + kib|ki) memory_b=$(( $number * 1024 )) ;; + mib|mi) memory_b=$(( $number * 1024 * 1024 )) ;; + gib|gi) memory_b=$(( $number * 1024 * 1024 * 1024 )) ;; + tib|ti) memory_b=$(( $number * 1024 * 1024 * 1024 * 1024 )) ;; + pib|pi) memory_b=$(( $number * 1024 * 1024 * 1024 * 1024 * 1024 )) ;; + esac + echo "$memory_b" + fi +} +# compute memory in different units +if [ ! -z ${VIASH_META_MEMORY+x} ]; then + VIASH_META_MEMORY_B=`ViashMemoryAsBytes $VIASH_META_MEMORY` + # do not define other variables if memory_b is an empty string + if [ ! -z "$VIASH_META_MEMORY_B" ]; then + VIASH_META_MEMORY_KB=$(( ($VIASH_META_MEMORY_B+999) / 1000 )) + VIASH_META_MEMORY_MB=$(( ($VIASH_META_MEMORY_KB+999) / 1000 )) + VIASH_META_MEMORY_GB=$(( ($VIASH_META_MEMORY_MB+999) / 1000 )) + VIASH_META_MEMORY_TB=$(( ($VIASH_META_MEMORY_GB+999) / 1000 )) + VIASH_META_MEMORY_PB=$(( ($VIASH_META_MEMORY_TB+999) / 1000 )) + VIASH_META_MEMORY_KIB=$(( ($VIASH_META_MEMORY_B+1023) / 1024 )) + VIASH_META_MEMORY_MIB=$(( ($VIASH_META_MEMORY_KIB+1023) / 1024 )) + VIASH_META_MEMORY_GIB=$(( ($VIASH_META_MEMORY_MIB+1023) / 1024 )) + VIASH_META_MEMORY_TIB=$(( ($VIASH_META_MEMORY_GIB+1023) / 1024 )) + VIASH_META_MEMORY_PIB=$(( ($VIASH_META_MEMORY_TIB+1023) / 1024 )) + else + # unset memory if string is empty + unset $VIASH_META_MEMORY_B + fi +fi +# unset nproc if string is empty +if [ -z "$VIASH_META_CPUS" ]; then + unset $VIASH_META_CPUS +fi + + +# check whether required parameters exist +if [ -z ${VIASH_PAR_INPUT+x} ]; then + ViashError '--input' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi +if [ -z ${VIASH_PAR_FASTQ+x} ]; then + ViashError '--fastq' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi +if [ -z ${VIASH_META_NAME+x} ]; then + ViashError 'name' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi +if [ -z ${VIASH_META_FUNCTIONALITY_NAME+x} ]; then + ViashError 'functionality_name' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi +if [ -z ${VIASH_META_RESOURCES_DIR+x} ]; then + ViashError 'resources_dir' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi +if [ -z ${VIASH_META_EXECUTABLE+x} ]; then + ViashError 'executable' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi +if [ -z ${VIASH_META_CONFIG+x} ]; then + ViashError 'config' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi +if [ -z ${VIASH_META_TEMP_DIR+x} ]; then + ViashError 'temp_dir' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi + +# filling in defaults +if [ -z ${VIASH_PAR_TAGS+x} ]; then + VIASH_PAR_TAGS="false" +fi + +# check whether required files exist +if [ ! -z "$VIASH_PAR_INPUT" ] && [ ! -e "$VIASH_PAR_INPUT" ]; then + ViashError "Input file '$VIASH_PAR_INPUT' does not exist." + exit 1 +fi + +# check whether parameters values are of the right type +if [[ -n "$VIASH_PAR_TAGS" ]]; then + if ! [[ "$VIASH_PAR_TAGS" =~ ^(true|True|TRUE|false|False|FALSE|yes|Yes|YES|no|No|NO)$ ]]; then + ViashError '--tags' has to be a boolean_true. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_CPUS" ]]; then + if ! [[ "$VIASH_META_CPUS" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'cpus' has to be an integer. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_B" ]]; then + if ! [[ "$VIASH_META_MEMORY_B" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_b' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_KB" ]]; then + if ! [[ "$VIASH_META_MEMORY_KB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_kb' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_MB" ]]; then + if ! [[ "$VIASH_META_MEMORY_MB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_mb' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_GB" ]]; then + if ! [[ "$VIASH_META_MEMORY_GB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_gb' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_TB" ]]; then + if ! [[ "$VIASH_META_MEMORY_TB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_tb' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_PB" ]]; then + if ! [[ "$VIASH_META_MEMORY_PB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_pb' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_KIB" ]]; then + if ! [[ "$VIASH_META_MEMORY_KIB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_kib' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_MIB" ]]; then + if ! [[ "$VIASH_META_MEMORY_MIB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_mib' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_GIB" ]]; then + if ! [[ "$VIASH_META_MEMORY_GIB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_gib' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_TIB" ]]; then + if ! [[ "$VIASH_META_MEMORY_TIB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_tib' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_PIB" ]]; then + if ! [[ "$VIASH_META_MEMORY_PIB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_pib' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi + +# create parent directories of output files, if so desired +if [ ! -z "$VIASH_PAR_FASTQ" ] && [ ! -d "$(dirname "$VIASH_PAR_FASTQ")" ]; then + mkdir -p "$(dirname "$VIASH_PAR_FASTQ")" +fi +if [ ! -z "$VIASH_PAR_FASTQ2" ] && [ ! -d "$(dirname "$VIASH_PAR_FASTQ2")" ]; then + mkdir -p "$(dirname "$VIASH_PAR_FASTQ2")" +fi + +if [ "$VIASH_ENGINE_ID" == "native" ] ; then + if [ "$VIASH_MODE" == "run" ]; then + VIASH_CMD="bash" + else + ViashError "Engine '$VIASH_ENGINE_ID' does not support mode '$VIASH_MODE'." + exit 1 + fi +fi + +if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then + # detect volumes from file arguments + VIASH_CHOWN_VARS=() +if [ ! -z "$VIASH_PAR_INPUT" ]; then + VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_PAR_INPUT")" ) + VIASH_PAR_INPUT=$(ViashDockerAutodetectMount "$VIASH_PAR_INPUT") +fi +if [ ! -z "$VIASH_PAR_FASTQ" ]; then + VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_PAR_FASTQ")" ) + VIASH_PAR_FASTQ=$(ViashDockerAutodetectMount "$VIASH_PAR_FASTQ") + VIASH_CHOWN_VARS+=( "$VIASH_PAR_FASTQ" ) +fi +if [ ! -z "$VIASH_PAR_FASTQ2" ]; then + VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_PAR_FASTQ2")" ) + VIASH_PAR_FASTQ2=$(ViashDockerAutodetectMount "$VIASH_PAR_FASTQ2") + VIASH_CHOWN_VARS+=( "$VIASH_PAR_FASTQ2" ) +fi +if [ ! -z "$VIASH_META_RESOURCES_DIR" ]; then + VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_META_RESOURCES_DIR")" ) + VIASH_META_RESOURCES_DIR=$(ViashDockerAutodetectMount "$VIASH_META_RESOURCES_DIR") +fi +if [ ! -z "$VIASH_META_EXECUTABLE" ]; then + VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_META_EXECUTABLE")" ) + VIASH_META_EXECUTABLE=$(ViashDockerAutodetectMount "$VIASH_META_EXECUTABLE") +fi +if [ ! -z "$VIASH_META_CONFIG" ]; then + VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_META_CONFIG")" ) + VIASH_META_CONFIG=$(ViashDockerAutodetectMount "$VIASH_META_CONFIG") +fi +if [ ! -z "$VIASH_META_TEMP_DIR" ]; then + VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_META_TEMP_DIR")" ) + VIASH_META_TEMP_DIR=$(ViashDockerAutodetectMount "$VIASH_META_TEMP_DIR") +fi + + # get unique mounts + VIASH_UNIQUE_MOUNTS=($(for val in "${VIASH_DIRECTORY_MOUNTS[@]}"; do echo "$val"; done | sort -u)) +fi + +if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then + # change file ownership + function ViashPerformChown { + if (( ${#VIASH_CHOWN_VARS[@]} )); then + set +e + VIASH_CMD="docker run --entrypoint=bash --rm ${VIASH_UNIQUE_MOUNTS[@]} $VIASH_DOCKER_IMAGE_ID -c 'chown $(id -u):$(id -g) --silent --recursive ${VIASH_CHOWN_VARS[@]}'" + ViashDebug "+ $VIASH_CMD" + eval $VIASH_CMD + set -e + fi + } + trap ViashPerformChown EXIT +fi + +if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then + # helper function for filling in extra docker args + if [ ! -z "$VIASH_META_MEMORY_B" ]; then + VIASH_DOCKER_RUN_ARGS+=("--memory=${VIASH_META_MEMORY_B}") + fi + if [ ! -z "$VIASH_META_CPUS" ]; then + VIASH_DOCKER_RUN_ARGS+=("--cpus=${VIASH_META_CPUS}") + fi +fi + +if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then + VIASH_CMD="docker run --entrypoint=bash ${VIASH_DOCKER_RUN_ARGS[@]} ${VIASH_UNIQUE_MOUNTS[@]} $VIASH_DOCKER_IMAGE_ID" +fi + + +# set dependency paths + + +ViashDebug "Running command: $(echo $VIASH_CMD)" +cat << VIASHEOF | eval $VIASH_CMD +set -e +tempscript=\$(mktemp "$VIASH_META_TEMP_DIR/viash-run-bedtools_bamtofastq-XXXXXX").sh +function clean_up { + rm "\$tempscript" +} +function interrupt { + echo -e "\nCTRL-C Pressed..." + exit 1 +} +trap clean_up EXIT +trap interrupt INT SIGINT +cat > "\$tempscript" << 'VIASHMAIN' +#!/bin/bash + +## VIASH START +# The following code has been auto-generated by Viash. +$( if [ ! -z ${VIASH_PAR_INPUT+x} ]; then echo "${VIASH_PAR_INPUT}" | sed "s#'#'\"'\"'#g;s#.*#par_input='&'#" ; else echo "# par_input="; fi ) +$( if [ ! -z ${VIASH_PAR_FASTQ+x} ]; then echo "${VIASH_PAR_FASTQ}" | sed "s#'#'\"'\"'#g;s#.*#par_fastq='&'#" ; else echo "# par_fastq="; fi ) +$( if [ ! -z ${VIASH_PAR_FASTQ2+x} ]; then echo "${VIASH_PAR_FASTQ2}" | sed "s#'#'\"'\"'#g;s#.*#par_fastq2='&'#" ; else echo "# par_fastq2="; fi ) +$( if [ ! -z ${VIASH_PAR_TAGS+x} ]; then echo "${VIASH_PAR_TAGS}" | sed "s#'#'\"'\"'#g;s#.*#par_tags='&'#" ; else echo "# par_tags="; fi ) +$( if [ ! -z ${VIASH_META_NAME+x} ]; then echo "${VIASH_META_NAME}" | sed "s#'#'\"'\"'#g;s#.*#meta_name='&'#" ; else echo "# meta_name="; fi ) +$( if [ ! -z ${VIASH_META_FUNCTIONALITY_NAME+x} ]; then echo "${VIASH_META_FUNCTIONALITY_NAME}" | sed "s#'#'\"'\"'#g;s#.*#meta_functionality_name='&'#" ; else echo "# meta_functionality_name="; fi ) +$( if [ ! -z ${VIASH_META_RESOURCES_DIR+x} ]; then echo "${VIASH_META_RESOURCES_DIR}" | sed "s#'#'\"'\"'#g;s#.*#meta_resources_dir='&'#" ; else echo "# meta_resources_dir="; fi ) +$( if [ ! -z ${VIASH_META_EXECUTABLE+x} ]; then echo "${VIASH_META_EXECUTABLE}" | sed "s#'#'\"'\"'#g;s#.*#meta_executable='&'#" ; else echo "# meta_executable="; fi ) +$( if [ ! -z ${VIASH_META_CONFIG+x} ]; then echo "${VIASH_META_CONFIG}" | sed "s#'#'\"'\"'#g;s#.*#meta_config='&'#" ; else echo "# meta_config="; fi ) +$( if [ ! -z ${VIASH_META_TEMP_DIR+x} ]; then echo "${VIASH_META_TEMP_DIR}" | sed "s#'#'\"'\"'#g;s#.*#meta_temp_dir='&'#" ; else echo "# meta_temp_dir="; fi ) +$( if [ ! -z ${VIASH_META_CPUS+x} ]; then echo "${VIASH_META_CPUS}" | sed "s#'#'\"'\"'#g;s#.*#meta_cpus='&'#" ; else echo "# meta_cpus="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_B+x} ]; then echo "${VIASH_META_MEMORY_B}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_b='&'#" ; else echo "# meta_memory_b="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_KB+x} ]; then echo "${VIASH_META_MEMORY_KB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_kb='&'#" ; else echo "# meta_memory_kb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_MB+x} ]; then echo "${VIASH_META_MEMORY_MB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_mb='&'#" ; else echo "# meta_memory_mb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_GB+x} ]; then echo "${VIASH_META_MEMORY_GB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_gb='&'#" ; else echo "# meta_memory_gb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_TB+x} ]; then echo "${VIASH_META_MEMORY_TB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_tb='&'#" ; else echo "# meta_memory_tb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_PB+x} ]; then echo "${VIASH_META_MEMORY_PB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_pb='&'#" ; else echo "# meta_memory_pb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_KIB+x} ]; then echo "${VIASH_META_MEMORY_KIB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_kib='&'#" ; else echo "# meta_memory_kib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_MIB+x} ]; then echo "${VIASH_META_MEMORY_MIB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_mib='&'#" ; else echo "# meta_memory_mib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_GIB+x} ]; then echo "${VIASH_META_MEMORY_GIB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_gib='&'#" ; else echo "# meta_memory_gib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_TIB+x} ]; then echo "${VIASH_META_MEMORY_TIB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_tib='&'#" ; else echo "# meta_memory_tib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_pib='&'#" ; else echo "# meta_memory_pib="; fi ) + +## VIASH END + +# Exit on error +set -eo pipefail + +# Unset parameters +[[ "\$par_tags" == "false" ]] && unset par_tags + +# Execute bedtools bamtofastq with the provided arguments +bedtools bamtofastq \\ + \${par_tags:+-tags} \\ + \${par_fastq2:+-fq2 "\$par_fastq2"} \\ + -i "\$par_input" \\ + -fq "\$par_fastq" + +VIASHMAIN +bash "\$tempscript" & +wait "\$!" + +VIASHEOF + + +if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then + # strip viash automount from file paths + + if [ ! -z "$VIASH_PAR_INPUT" ]; then + VIASH_PAR_INPUT=$(ViashDockerStripAutomount "$VIASH_PAR_INPUT") + fi + if [ ! -z "$VIASH_PAR_FASTQ" ]; then + VIASH_PAR_FASTQ=$(ViashDockerStripAutomount "$VIASH_PAR_FASTQ") + fi + if [ ! -z "$VIASH_PAR_FASTQ2" ]; then + VIASH_PAR_FASTQ2=$(ViashDockerStripAutomount "$VIASH_PAR_FASTQ2") + fi + if [ ! -z "$VIASH_META_RESOURCES_DIR" ]; then + VIASH_META_RESOURCES_DIR=$(ViashDockerStripAutomount "$VIASH_META_RESOURCES_DIR") + fi + if [ ! -z "$VIASH_META_EXECUTABLE" ]; then + VIASH_META_EXECUTABLE=$(ViashDockerStripAutomount "$VIASH_META_EXECUTABLE") + fi + if [ ! -z "$VIASH_META_CONFIG" ]; then + VIASH_META_CONFIG=$(ViashDockerStripAutomount "$VIASH_META_CONFIG") + fi + if [ ! -z "$VIASH_META_TEMP_DIR" ]; then + VIASH_META_TEMP_DIR=$(ViashDockerStripAutomount "$VIASH_META_TEMP_DIR") + fi +fi + + +# check whether required files exist +if [ ! -z "$VIASH_PAR_FASTQ" ] && [ ! -e "$VIASH_PAR_FASTQ" ]; then + ViashError "Output file '$VIASH_PAR_FASTQ' does not exist." + exit 1 +fi +if [ ! -z "$VIASH_PAR_FASTQ2" ] && [ ! -e "$VIASH_PAR_FASTQ2" ]; then + ViashError "Output file '$VIASH_PAR_FASTQ2' does not exist." + exit 1 +fi + + +exit 0 diff --git a/target/executable/bedtools/bedtools_bedtobam/.config.vsh.yaml b/target/executable/bedtools/bedtools_bedtobam/.config.vsh.yaml new file mode 100644 index 00000000..ea2dbff5 --- /dev/null +++ b/target/executable/bedtools/bedtools_bedtobam/.config.vsh.yaml @@ -0,0 +1,240 @@ +name: "bedtools_bedtobam" +namespace: "bedtools" +version: "main" +authors: +- name: "Theodoro Gasperin Terra Camargo" + roles: + - "author" + - "maintainer" + info: + links: + email: "theodorogtc@gmail.com" + github: "tgaspe" + linkedin: "theodoro-gasperin-terra-camargo" + organizations: + - name: "Data Intuitive" + href: "https://www.data-intuitive.com" + role: "Bioinformatician" +argument_groups: +- name: "Inputs" + arguments: + - type: "file" + name: "--input" + alternatives: + - "-i" + description: "Input file (bed/gff/vcf)." + info: null + must_exist: true + create_parent: true + required: true + direction: "input" + multiple: false + multiple_sep: ";" + - type: "file" + name: "--genome" + alternatives: + - "-g" + description: "Input genome file.\nNOTE: This is not a fasta file. This is a two-column\ + \ tab-delimited file\nwhere the first column is the chromosome name and the\ + \ second their sizes.\n" + info: null + must_exist: true + create_parent: true + required: true + direction: "input" + multiple: false + multiple_sep: ";" +- name: "Outputs" + arguments: + - type: "file" + name: "--output" + alternatives: + - "-o" + description: "Output BAM file to be written." + info: null + must_exist: true + create_parent: true + required: false + direction: "output" + multiple: false + multiple_sep: ";" +- name: "Options" + arguments: + - type: "integer" + name: "--map_quality" + alternatives: + - "-mapq" + description: "Set the mappinq quality for the BAM records.\n" + info: null + default: + - 255 + required: false + min: 0 + max: 255 + direction: "input" + multiple: false + multiple_sep: ";" + - type: "boolean_true" + name: "--bed12" + description: "The BED file is in BED12 format. The BAM CIGAR\nstring will reflect\ + \ BED \"blocks\".\n" + info: null + direction: "input" + - type: "boolean_true" + name: "--uncompress_bam" + alternatives: + - "-ubam" + description: "Write uncompressed BAM output. Default writes compressed BAM.\n" + info: null + direction: "input" +resources: +- type: "bash_script" + path: "script.sh" + is_executable: true +description: "Converts feature records (bed/gff/vcf) to BAM format." +test_resources: +- type: "bash_script" + path: "test.sh" + is_executable: true +info: null +status: "enabled" +requirements: + commands: + - "ps" +keywords: +- "Converts" +- "BED" +- "GFF" +- "VCF" +- "BAM" +license: "MIT" +references: + doi: + - "10.1093/bioinformatics/btq033" +links: + repository: "https://github.com/arq5x/bedtools2" + homepage: "https://bedtools.readthedocs.io/en/latest/#" + documentation: "https://bedtools.readthedocs.io/en/latest/content/tools/bedtobam.html" + issue_tracker: "https://github.com/arq5x/bedtools2/issues" +runners: +- type: "executable" + id: "executable" + docker_setup_strategy: "ifneedbepullelsecachedbuild" +- type: "nextflow" + id: "nextflow" + directives: + tag: "$id" + auto: + simplifyInput: true + simplifyOutput: false + transcript: false + publish: false + config: + labels: + mem1gb: "memory = 1000000000.B" + mem2gb: "memory = 2000000000.B" + mem5gb: "memory = 5000000000.B" + mem10gb: "memory = 10000000000.B" + mem20gb: "memory = 20000000000.B" + mem50gb: "memory = 50000000000.B" + mem100gb: "memory = 100000000000.B" + mem200gb: "memory = 200000000000.B" + mem500gb: "memory = 500000000000.B" + mem1tb: "memory = 1000000000000.B" + mem2tb: "memory = 2000000000000.B" + mem5tb: "memory = 5000000000000.B" + mem10tb: "memory = 10000000000000.B" + mem20tb: "memory = 20000000000000.B" + mem50tb: "memory = 50000000000000.B" + mem100tb: "memory = 100000000000000.B" + mem200tb: "memory = 200000000000000.B" + mem500tb: "memory = 500000000000000.B" + mem1gib: "memory = 1073741824.B" + mem2gib: "memory = 2147483648.B" + mem4gib: "memory = 4294967296.B" + mem8gib: "memory = 8589934592.B" + mem16gib: "memory = 17179869184.B" + mem32gib: "memory = 34359738368.B" + mem64gib: "memory = 68719476736.B" + mem128gib: "memory = 137438953472.B" + mem256gib: "memory = 274877906944.B" + mem512gib: "memory = 549755813888.B" + mem1tib: "memory = 1099511627776.B" + mem2tib: "memory = 2199023255552.B" + mem4tib: "memory = 4398046511104.B" + mem8tib: "memory = 8796093022208.B" + mem16tib: "memory = 17592186044416.B" + mem32tib: "memory = 35184372088832.B" + mem64tib: "memory = 70368744177664.B" + mem128tib: "memory = 140737488355328.B" + mem256tib: "memory = 281474976710656.B" + mem512tib: "memory = 562949953421312.B" + cpu1: "cpus = 1" + cpu2: "cpus = 2" + cpu5: "cpus = 5" + cpu10: "cpus = 10" + cpu20: "cpus = 20" + cpu50: "cpus = 50" + cpu100: "cpus = 100" + cpu200: "cpus = 200" + cpu500: "cpus = 500" + cpu1000: "cpus = 1000" + debug: false + container: "docker" +engines: +- type: "docker" + id: "docker" + image: "debian:stable-slim" + target_registry: "images.viash-hub.com" + target_tag: "main" + namespace_separator: "/" + setup: + - type: "apt" + packages: + - "bedtools" + - "procps" + interactive: false + - type: "docker" + run: + - "echo \"bedtools: \\\"$(bedtools --version | sed -n 's/^bedtools //p')\\\"\"\ + \ > /var/software_versions.txt\n" + test_setup: + - type: "apt" + packages: + - "samtools" + interactive: false + entrypoint: [] + cmd: null +- type: "native" + id: "native" +build_info: + config: "src/bedtools/bedtools_bedtobam/config.vsh.yaml" + runner: "executable" + engine: "docker|native" + output: "target/executable/bedtools/bedtools_bedtobam" + executable: "target/executable/bedtools/bedtools_bedtobam/bedtools_bedtobam" + viash_version: "0.9.0-RC6" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" + git_remote: "https://github.com/viash-hub/biobox" +package_config: + name: "biobox" + version: "main" + description: "A collection of bioinformatics tools for working with sequence data.\n" + info: null + viash_version: "0.9.0-RC6" + source: "src" + target: "target" + config_mods: + - ".requirements.commands := ['ps']\n" + - ".engines += { type: \"native\" }" + - ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'" + - ".engines[.type == 'docker'].target_tag := 'main'" + keywords: + - "bioinformatics" + - "modules" + - "sequencing" + license: "MIT" + organization: "vsh" + links: + repository: "https://github.com/viash-hub/biobox" + issue_tracker: "https://github.com/viash-hub/biobox/issues" diff --git a/target/executable/bedtools/bedtools_bedtobam/bedtools_bedtobam b/target/executable/bedtools/bedtools_bedtobam/bedtools_bedtobam new file mode 100755 index 00000000..5e1b0955 --- /dev/null +++ b/target/executable/bedtools/bedtools_bedtobam/bedtools_bedtobam @@ -0,0 +1,1203 @@ +#!/usr/bin/env bash + +# bedtools_bedtobam main +# +# This wrapper script is auto-generated by viash 0.9.0-RC6 and is thus a +# derivative work thereof. This software comes with ABSOLUTELY NO WARRANTY from +# Data Intuitive. +# +# The component may contain files which fall under a different license. The +# authors of this component should specify the license in the header of such +# files, or include a separate license file detailing the licenses of all included +# files. +# +# Component authors: +# * Theodoro Gasperin Terra Camargo (author, maintainer) + +set -e + +if [ -z "$VIASH_TEMP" ]; then + VIASH_TEMP=${VIASH_TEMP:-$VIASH_TMPDIR} + VIASH_TEMP=${VIASH_TEMP:-$VIASH_TEMPDIR} + VIASH_TEMP=${VIASH_TEMP:-$VIASH_TMP} + VIASH_TEMP=${VIASH_TEMP:-$TMPDIR} + VIASH_TEMP=${VIASH_TEMP:-$TMP} + VIASH_TEMP=${VIASH_TEMP:-$TEMPDIR} + VIASH_TEMP=${VIASH_TEMP:-$TEMP} + VIASH_TEMP=${VIASH_TEMP:-/tmp} +fi + +# define helper functions +# ViashQuote: put quotes around non flag values +# $1 : unquoted string +# return : possibly quoted string +# examples: +# ViashQuote --foo # returns --foo +# ViashQuote bar # returns 'bar' +# Viashquote --foo=bar # returns --foo='bar' +function ViashQuote { + if [[ "$1" =~ ^-+[a-zA-Z0-9_\-]+=.+$ ]]; then + echo "$1" | sed "s#=\(.*\)#='\1'#" + elif [[ "$1" =~ ^-+[a-zA-Z0-9_\-]+$ ]]; then + echo "$1" + else + echo "'$1'" + fi +} +# ViashRemoveFlags: Remove leading flag +# $1 : string with a possible leading flag +# return : string without possible leading flag +# examples: +# ViashRemoveFlags --foo=bar # returns bar +function ViashRemoveFlags { + echo "$1" | sed 's/^--*[a-zA-Z0-9_\-]*=//' +} +# ViashSourceDir: return the path of a bash file, following symlinks +# usage : ViashSourceDir ${BASH_SOURCE[0]} +# $1 : Should always be set to ${BASH_SOURCE[0]} +# returns : The absolute path of the bash file +function ViashSourceDir { + SOURCE="$1" + while [ -h "$SOURCE" ]; do + DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )" + SOURCE="$(readlink "$SOURCE")" + [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" + done + cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd +} +# ViashFindTargetDir: return the path of the '.build.yaml' file, following symlinks +# usage : ViashFindTargetDir 'ScriptPath' +# $1 : The location from where to start the upward search +# returns : The absolute path of the '.build.yaml' file +function ViashFindTargetDir { + SOURCE="$1" + while [[ "$SOURCE" != "" && ! -e "$SOURCE/.build.yaml" ]]; do + SOURCE=${SOURCE%/*} + done + echo $SOURCE +} +# see https://en.wikipedia.org/wiki/Syslog#Severity_level +VIASH_LOGCODE_EMERGENCY=0 +VIASH_LOGCODE_ALERT=1 +VIASH_LOGCODE_CRITICAL=2 +VIASH_LOGCODE_ERROR=3 +VIASH_LOGCODE_WARNING=4 +VIASH_LOGCODE_NOTICE=5 +VIASH_LOGCODE_INFO=6 +VIASH_LOGCODE_DEBUG=7 +VIASH_VERBOSITY=$VIASH_LOGCODE_NOTICE + +# ViashLog: Log events depending on the verbosity level +# usage: ViashLog 1 alert Oh no something went wrong! +# $1: required verbosity level +# $2: display tag +# $3+: messages to display +# stdout: Your input, prepended by '[$2] '. +function ViashLog { + local required_level="$1" + local display_tag="$2" + shift 2 + if [ $VIASH_VERBOSITY -ge $required_level ]; then + >&2 echo "[$display_tag]" "$@" + fi +} + +# ViashEmergency: log events when the system is unstable +# usage: ViashEmergency Oh no something went wrong. +# stdout: Your input, prepended by '[emergency] '. +function ViashEmergency { + ViashLog $VIASH_LOGCODE_EMERGENCY emergency "$@" +} + +# ViashAlert: log events when actions must be taken immediately (e.g. corrupted system database) +# usage: ViashAlert Oh no something went wrong. +# stdout: Your input, prepended by '[alert] '. +function ViashAlert { + ViashLog $VIASH_LOGCODE_ALERT alert "$@" +} + +# ViashCritical: log events when a critical condition occurs +# usage: ViashCritical Oh no something went wrong. +# stdout: Your input, prepended by '[critical] '. +function ViashCritical { + ViashLog $VIASH_LOGCODE_CRITICAL critical "$@" +} + +# ViashError: log events when an error condition occurs +# usage: ViashError Oh no something went wrong. +# stdout: Your input, prepended by '[error] '. +function ViashError { + ViashLog $VIASH_LOGCODE_ERROR error "$@" +} + +# ViashWarning: log potentially abnormal events +# usage: ViashWarning Something may have gone wrong. +# stdout: Your input, prepended by '[warning] '. +function ViashWarning { + ViashLog $VIASH_LOGCODE_WARNING warning "$@" +} + +# ViashNotice: log significant but normal events +# usage: ViashNotice This just happened. +# stdout: Your input, prepended by '[notice] '. +function ViashNotice { + ViashLog $VIASH_LOGCODE_NOTICE notice "$@" +} + +# ViashInfo: log normal events +# usage: ViashInfo This just happened. +# stdout: Your input, prepended by '[info] '. +function ViashInfo { + ViashLog $VIASH_LOGCODE_INFO info "$@" +} + +# ViashDebug: log all events, for debugging purposes +# usage: ViashDebug This just happened. +# stdout: Your input, prepended by '[debug] '. +function ViashDebug { + ViashLog $VIASH_LOGCODE_DEBUG debug "$@" +} + +# find source folder of this component +VIASH_META_RESOURCES_DIR=`ViashSourceDir ${BASH_SOURCE[0]}` + +# find the root of the built components & dependencies +VIASH_TARGET_DIR=`ViashFindTargetDir $VIASH_META_RESOURCES_DIR` + +# define meta fields +VIASH_META_NAME="bedtools_bedtobam" +VIASH_META_FUNCTIONALITY_NAME="bedtools_bedtobam" +VIASH_META_EXECUTABLE="$VIASH_META_RESOURCES_DIR/$VIASH_META_NAME" +VIASH_META_CONFIG="$VIASH_META_RESOURCES_DIR/.config.vsh.yaml" +VIASH_META_TEMP_DIR="$VIASH_TEMP" + + +# ViashHelp: Display helpful explanation about this executable +function ViashHelp { + echo "bedtools_bedtobam main" + echo "" + echo "Converts feature records (bed/gff/vcf) to BAM format." + echo "" + echo "Inputs:" + echo " -i, --input" + echo " type: file, required parameter, file must exist" + echo " Input file (bed/gff/vcf)." + echo "" + echo " -g, --genome" + echo " type: file, required parameter, file must exist" + echo " Input genome file." + echo " NOTE: This is not a fasta file. This is a two-column tab-delimited file" + echo " where the first column is the chromosome name and the second their" + echo " sizes." + echo "" + echo "Outputs:" + echo " -o, --output" + echo " type: file, output, file must exist" + echo " Output BAM file to be written." + echo "" + echo "Options:" + echo " -mapq, --map_quality" + echo " type: integer" + echo " default: 255" + echo " min: 0" + echo " max: 255" + echo " Set the mappinq quality for the BAM records." + echo "" + echo " --bed12" + echo " type: boolean_true" + echo " The BED file is in BED12 format. The BAM CIGAR" + echo " string will reflect BED \"blocks\"." + echo "" + echo " -ubam, --uncompress_bam" + echo " type: boolean_true" + echo " Write uncompressed BAM output. Default writes compressed BAM." +} + +# initialise variables +VIASH_MODE='run' +VIASH_ENGINE_ID='docker' + +######## Helper functions for setting up Docker images for viash ######## +# expects: ViashDockerBuild + +# ViashDockerInstallationCheck: check whether Docker is installed correctly +# +# examples: +# ViashDockerInstallationCheck +function ViashDockerInstallationCheck { + ViashDebug "Checking whether Docker is installed" + if [ ! command -v docker &> /dev/null ]; then + ViashCritical "Docker doesn't seem to be installed. See 'https://docs.docker.com/get-docker/' for instructions." + exit 1 + fi + + ViashDebug "Checking whether the Docker daemon is running" + save=$-; set +e + docker_version=$(docker version --format '{{.Client.APIVersion}}' 2> /dev/null) + out=$? + [[ $save =~ e ]] && set -e + if [ $out -ne 0 ]; then + ViashCritical "Docker daemon does not seem to be running. Try one of the following:" + ViashCritical "- Try running 'dockerd' in the command line" + ViashCritical "- See https://docs.docker.com/config/daemon/" + exit 1 + fi +} + +# ViashDockerRemoteTagCheck: check whether a Docker image is available +# on a remote. Assumes `docker login` has been performed, if relevant. +# +# $1 : image identifier with format `[registry/]image[:tag]` +# exit code $? : whether or not the image was found +# examples: +# ViashDockerRemoteTagCheck python:latest +# echo $? # returns '0' +# ViashDockerRemoteTagCheck sdaizudceahifu +# echo $? # returns '1' +function ViashDockerRemoteTagCheck { + docker manifest inspect $1 > /dev/null 2> /dev/null +} + +# ViashDockerLocalTagCheck: check whether a Docker image is available locally +# +# $1 : image identifier with format `[registry/]image[:tag]` +# exit code $? : whether or not the image was found +# examples: +# docker pull python:latest +# ViashDockerLocalTagCheck python:latest +# echo $? # returns '0' +# ViashDockerLocalTagCheck sdaizudceahifu +# echo $? # returns '1' +function ViashDockerLocalTagCheck { + [ -n "$(docker images -q $1)" ] +} + +# ViashDockerPull: pull a Docker image +# +# $1 : image identifier with format `[registry/]image[:tag]` +# exit code $? : whether or not the image was found +# examples: +# ViashDockerPull python:latest +# echo $? # returns '0' +# ViashDockerPull sdaizudceahifu +# echo $? # returns '1' +function ViashDockerPull { + ViashNotice "Checking if Docker image is available at '$1'" + if [ $VIASH_VERBOSITY -ge $VIASH_LOGCODE_INFO ]; then + docker pull $1 && return 0 || return 1 + else + save=$-; set +e + docker pull $1 2> /dev/null > /dev/null + out=$? + [[ $save =~ e ]] && set -e + if [ $out -ne 0 ]; then + ViashWarning "Could not pull from '$1'. Docker image doesn't exist or is not accessible." + fi + return $out + fi +} + +# ViashDockerPush: push a Docker image +# +# $1 : image identifier with format `[registry/]image[:tag]` +# exit code $? : whether or not the image was found +# examples: +# ViashDockerPush python:latest +# echo $? # returns '0' +# ViashDockerPush sdaizudceahifu +# echo $? # returns '1' +function ViashDockerPush { + ViashNotice "Pushing image to '$1'" + save=$-; set +e + if [ $VIASH_VERBOSITY -ge $VIASH_LOGCODE_INFO ]; then + docker push $1 + out=$? + else + docker push $1 2> /dev/null > /dev/null + out=$? + fi + [[ $save =~ e ]] && set -e + if [ $out -eq 0 ]; then + ViashNotice "Container '$1' push succeeded." + else + ViashError "Container '$1' push errored. You might not be logged in or have the necessary permissions." + fi + return $out +} + +# ViashDockerPullElseBuild: pull a Docker image, else build it +# +# $1 : image identifier with format `[registry/]image[:tag]` +# ViashDockerBuild : a Bash function which builds a docker image, takes image identifier as argument. +# examples: +# ViashDockerPullElseBuild mynewcomponent +function ViashDockerPullElseBuild { + save=$-; set +e + ViashDockerPull $1 + out=$? + [[ $save =~ e ]] && set -e + if [ $out -ne 0 ]; then + ViashDockerBuild $@ + fi +} + +# ViashDockerSetup: create a Docker image, according to specified docker setup strategy +# +# $1 : image identifier with format `[registry/]image[:tag]` +# $2 : docker setup strategy, see DockerSetupStrategy.scala +# examples: +# ViashDockerSetup mynewcomponent alwaysbuild +function ViashDockerSetup { + local image_id="$1" + local setup_strategy="$2" + if [ "$setup_strategy" == "alwaysbuild" -o "$setup_strategy" == "build" -o "$setup_strategy" == "b" ]; then + ViashDockerBuild $image_id --no-cache $(ViashDockerBuildArgs "$engine_id") + elif [ "$setup_strategy" == "alwayspull" -o "$setup_strategy" == "pull" -o "$setup_strategy" == "p" ]; then + ViashDockerPull $image_id + elif [ "$setup_strategy" == "alwayspullelsebuild" -o "$setup_strategy" == "pullelsebuild" ]; then + ViashDockerPullElseBuild $image_id --no-cache $(ViashDockerBuildArgs "$engine_id") + elif [ "$setup_strategy" == "alwayspullelsecachedbuild" -o "$setup_strategy" == "pullelsecachedbuild" ]; then + ViashDockerPullElseBuild $image_id $(ViashDockerBuildArgs "$engine_id") + elif [ "$setup_strategy" == "alwayscachedbuild" -o "$setup_strategy" == "cachedbuild" -o "$setup_strategy" == "cb" ]; then + ViashDockerBuild $image_id $(ViashDockerBuildArgs "$engine_id") + elif [[ "$setup_strategy" =~ ^ifneedbe ]]; then + local save=$-; set +e + ViashDockerLocalTagCheck $image_id + local outCheck=$? + [[ $save =~ e ]] && set -e + if [ $outCheck -eq 0 ]; then + ViashInfo "Image $image_id already exists" + elif [ "$setup_strategy" == "ifneedbebuild" ]; then + ViashDockerBuild $image_id --no-cache $(ViashDockerBuildArgs "$engine_id") + elif [ "$setup_strategy" == "ifneedbecachedbuild" ]; then + ViashDockerBuild $image_id $(ViashDockerBuildArgs "$engine_id") + elif [ "$setup_strategy" == "ifneedbepull" ]; then + ViashDockerPull $image_id + elif [ "$setup_strategy" == "ifneedbepullelsebuild" ]; then + ViashDockerPullElseBuild $image_id --no-cache $(ViashDockerBuildArgs "$engine_id") + elif [ "$setup_strategy" == "ifneedbepullelsecachedbuild" ]; then + ViashDockerPullElseBuild $image_id $(ViashDockerBuildArgs "$engine_id") + else + ViashError "Unrecognised Docker strategy: $setup_strategy" + exit 1 + fi + elif [ "$setup_strategy" == "push" -o "$setup_strategy" == "forcepush" -o "$setup_strategy" == "alwayspush" ]; then + ViashDockerPush "$image_id" + elif [ "$setup_strategy" == "pushifnotpresent" -o "$setup_strategy" == "gentlepush" -o "$setup_strategy" == "maybepush" ]; then + local save=$-; set +e + ViashDockerRemoteTagCheck $image_id + local outCheck=$? + [[ $save =~ e ]] && set -e + if [ $outCheck -eq 0 ]; then + ViashNotice "Container '$image_id' exists, doing nothing." + else + ViashNotice "Container '$image_id' does not yet exist." + ViashDockerPush "$image_id" + fi + elif [ "$setup_strategy" == "donothing" -o "$setup_strategy" == "meh" ]; then + ViashNotice "Skipping setup." + else + ViashError "Unrecognised Docker strategy: $setup_strategy" + exit 1 + fi +} + +# ViashDockerCheckCommands: Check whether a docker container has the required commands +# +# $1 : image identifier with format `[registry/]image[:tag]` +# $@ : commands to verify being present +# examples: +# ViashDockerCheckCommands bash:4.0 bash ps foo +function ViashDockerCheckCommands { + local image_id="$1" + shift 1 + local commands="$@" + local save=$-; set +e + local missing # mark 'missing' as local in advance, otherwise the exit code of the command will be missing and always be '0' + missing=$(docker run --rm --entrypoint=sh "$image_id" -c "for command in $commands; do command -v \$command >/dev/null 2>&1; if [ \$? -ne 0 ]; then echo \$command; exit 1; fi; done") + local outCheck=$? + [[ $save =~ e ]] && set -e + if [ $outCheck -ne 0 ]; then + ViashError "Docker container '$image_id' does not contain command '$missing'." + exit 1 + fi +} + +# ViashDockerBuild: build a docker image +# $1 : image identifier with format `[registry/]image[:tag]` +# $... : additional arguments to pass to docker build +# $VIASH_META_TEMP_DIR : temporary directory to store dockerfile & optional resources in +# $VIASH_META_NAME : name of the component +# $VIASH_META_RESOURCES_DIR : directory containing the resources +# $VIASH_VERBOSITY : verbosity level +# exit code $? : whether or not the image was built successfully +function ViashDockerBuild { + local image_id="$1" + shift 1 + + # create temporary directory to store dockerfile & optional resources in + local tmpdir=$(mktemp -d "$VIASH_META_TEMP_DIR/dockerbuild-$VIASH_META_NAME-XXXXXX") + local dockerfile="$tmpdir/Dockerfile" + function clean_up { + rm -rf "$tmpdir" + } + trap clean_up EXIT + + # store dockerfile and resources + ViashDockerfile "$VIASH_ENGINE_ID" > "$dockerfile" + + # generate the build command + local docker_build_cmd="docker build -t '$image_id' $@ '$VIASH_META_RESOURCES_DIR' -f '$dockerfile'" + + # build the container + ViashNotice "Building container '$image_id' with Dockerfile" + ViashInfo "$docker_build_cmd" + local save=$-; set +e + if [ $VIASH_VERBOSITY -ge $VIASH_LOGCODE_INFO ]; then + eval $docker_build_cmd + else + eval $docker_build_cmd &> "$tmpdir/docker_build.log" + fi + + # check exit code + local out=$? + [[ $save =~ e ]] && set -e + if [ $out -ne 0 ]; then + ViashError "Error occurred while building container '$image_id'" + if [ $VIASH_VERBOSITY -lt $VIASH_LOGCODE_INFO ]; then + ViashError "Transcript: --------------------------------" + cat "$tmpdir/docker_build.log" + ViashError "End of transcript --------------------------" + fi + exit 1 + fi +} + +######## End of helper functions for setting up Docker images for viash ######## + +# ViashDockerFile: print the dockerfile to stdout +# $1 : engine identifier +# return : dockerfile required to run this component +# examples: +# ViashDockerFile +function ViashDockerfile { + local engine_id="$1" + + if [[ "$engine_id" == "docker" ]]; then + cat << 'VIASHDOCKER' +FROM debian:stable-slim +ENTRYPOINT [] +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y bedtools procps && \ + rm -rf /var/lib/apt/lists/* + +RUN echo "bedtools: \"$(bedtools --version | sed -n 's/^bedtools //p')\"" > /var/software_versions.txt + +LABEL org.opencontainers.image.authors="Theodoro Gasperin Terra Camargo" +LABEL org.opencontainers.image.description="Companion container for running component bedtools bedtools_bedtobam" +LABEL org.opencontainers.image.created="2024-08-14T20:58:47Z" +LABEL org.opencontainers.image.source="https://github.com/arq5x/bedtools2" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" +LABEL org.opencontainers.image.version="main" + +VIASHDOCKER + fi +} + +# ViashDockerBuildArgs: return the arguments to pass to docker build +# $1 : engine identifier +# return : arguments to pass to docker build +function ViashDockerBuildArgs { + local engine_id="$1" + + if [[ "$engine_id" == "docker" ]]; then + echo "" + fi +} + +# ViashAbsolutePath: generate absolute path from relative path +# borrowed from https://stackoverflow.com/a/21951256 +# $1 : relative filename +# return : absolute path +# examples: +# ViashAbsolutePath some_file.txt # returns /path/to/some_file.txt +# ViashAbsolutePath /foo/bar/.. # returns /foo +function ViashAbsolutePath { + local thePath + if [[ ! "$1" =~ ^/ ]]; then + thePath="$PWD/$1" + else + thePath="$1" + fi + echo "$thePath" | ( + IFS=/ + read -a parr + declare -a outp + for i in "${parr[@]}"; do + case "$i" in + ''|.) continue ;; + ..) + len=${#outp[@]} + if ((len==0)); then + continue + else + unset outp[$((len-1))] + fi + ;; + *) + len=${#outp[@]} + outp[$len]="$i" + ;; + esac + done + echo /"${outp[*]}" + ) +} +# ViashDockerAutodetectMount: auto configuring docker mounts from parameters +# $1 : The parameter value +# returns : New parameter +# $VIASH_DIRECTORY_MOUNTS : Added another parameter to be passed to docker +# examples: +# ViashDockerAutodetectMount /path/to/bar # returns '/viash_automount/path/to/bar' +# ViashDockerAutodetectMountArg /path/to/bar # returns '--volume="/path/to:/viash_automount/path/to"' +function ViashDockerAutodetectMount { + abs_path=$(ViashAbsolutePath "$1") + if [ -d "$abs_path" ]; then + mount_source="$abs_path" + base_name="" + else + mount_source=`dirname "$abs_path"` + base_name=`basename "$abs_path"` + fi + mount_target="/viash_automount$mount_source" + if [ -z "$base_name" ]; then + echo "$mount_target" + else + echo "$mount_target/$base_name" + fi +} +function ViashDockerAutodetectMountArg { + abs_path=$(ViashAbsolutePath "$1") + if [ -d "$abs_path" ]; then + mount_source="$abs_path" + base_name="" + else + mount_source=`dirname "$abs_path"` + base_name=`basename "$abs_path"` + fi + mount_target="/viash_automount$mount_source" + ViashDebug "ViashDockerAutodetectMountArg $1 -> $mount_source -> $mount_target" + echo "--volume=\"$mount_source:$mount_target\"" +} +function ViashDockerStripAutomount { + abs_path=$(ViashAbsolutePath "$1") + echo "${abs_path#/viash_automount}" +} +# initialise variables +VIASH_DIRECTORY_MOUNTS=() + +# initialise docker variables +VIASH_DOCKER_RUN_ARGS=(-i --rm) + +# initialise array +VIASH_POSITIONAL_ARGS='' + +while [[ $# -gt 0 ]]; do + case "$1" in + -h|--help) + ViashHelp + exit + ;; + ---v|---verbose) + let "VIASH_VERBOSITY=VIASH_VERBOSITY+1" + shift 1 + ;; + ---verbosity) + VIASH_VERBOSITY="$2" + shift 2 + ;; + ---verbosity=*) + VIASH_VERBOSITY="$(ViashRemoveFlags "$1")" + shift 1 + ;; + --version) + echo "bedtools_bedtobam main" + exit + ;; + --input) + [ -n "$VIASH_PAR_INPUT" ] && ViashError Bad arguments for option \'--input\': \'$VIASH_PAR_INPUT\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_INPUT="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to --input. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --input=*) + [ -n "$VIASH_PAR_INPUT" ] && ViashError Bad arguments for option \'--input=*\': \'$VIASH_PAR_INPUT\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_INPUT=$(ViashRemoveFlags "$1") + shift 1 + ;; + -i) + [ -n "$VIASH_PAR_INPUT" ] && ViashError Bad arguments for option \'-i\': \'$VIASH_PAR_INPUT\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_INPUT="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to -i. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --genome) + [ -n "$VIASH_PAR_GENOME" ] && ViashError Bad arguments for option \'--genome\': \'$VIASH_PAR_GENOME\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_GENOME="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to --genome. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --genome=*) + [ -n "$VIASH_PAR_GENOME" ] && ViashError Bad arguments for option \'--genome=*\': \'$VIASH_PAR_GENOME\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_GENOME=$(ViashRemoveFlags "$1") + shift 1 + ;; + -g) + [ -n "$VIASH_PAR_GENOME" ] && ViashError Bad arguments for option \'-g\': \'$VIASH_PAR_GENOME\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_GENOME="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to -g. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --output) + [ -n "$VIASH_PAR_OUTPUT" ] && ViashError Bad arguments for option \'--output\': \'$VIASH_PAR_OUTPUT\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_OUTPUT="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to --output. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --output=*) + [ -n "$VIASH_PAR_OUTPUT" ] && ViashError Bad arguments for option \'--output=*\': \'$VIASH_PAR_OUTPUT\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_OUTPUT=$(ViashRemoveFlags "$1") + shift 1 + ;; + -o) + [ -n "$VIASH_PAR_OUTPUT" ] && ViashError Bad arguments for option \'-o\': \'$VIASH_PAR_OUTPUT\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_OUTPUT="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to -o. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --map_quality) + [ -n "$VIASH_PAR_MAP_QUALITY" ] && ViashError Bad arguments for option \'--map_quality\': \'$VIASH_PAR_MAP_QUALITY\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_MAP_QUALITY="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to --map_quality. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --map_quality=*) + [ -n "$VIASH_PAR_MAP_QUALITY" ] && ViashError Bad arguments for option \'--map_quality=*\': \'$VIASH_PAR_MAP_QUALITY\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_MAP_QUALITY=$(ViashRemoveFlags "$1") + shift 1 + ;; + -mapq) + [ -n "$VIASH_PAR_MAP_QUALITY" ] && ViashError Bad arguments for option \'-mapq\': \'$VIASH_PAR_MAP_QUALITY\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_MAP_QUALITY="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to -mapq. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + --bed12) + [ -n "$VIASH_PAR_BED12" ] && ViashError Bad arguments for option \'--bed12\': \'$VIASH_PAR_BED12\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_BED12=true + shift 1 + ;; + --uncompress_bam) + [ -n "$VIASH_PAR_UNCOMPRESS_BAM" ] && ViashError Bad arguments for option \'--uncompress_bam\': \'$VIASH_PAR_UNCOMPRESS_BAM\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_UNCOMPRESS_BAM=true + shift 1 + ;; + -ubam) + [ -n "$VIASH_PAR_UNCOMPRESS_BAM" ] && ViashError Bad arguments for option \'-ubam\': \'$VIASH_PAR_UNCOMPRESS_BAM\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_PAR_UNCOMPRESS_BAM=true + shift 1 + ;; + ---engine) + VIASH_ENGINE_ID="$2" + shift 2 + ;; + ---engine=*) + VIASH_ENGINE_ID="$(ViashRemoveFlags "$1")" + shift 1 + ;; + ---setup) + VIASH_MODE='setup' + VIASH_SETUP_STRATEGY="$2" + shift 2 + ;; + ---setup=*) + VIASH_MODE='setup' + VIASH_SETUP_STRATEGY="$(ViashRemoveFlags "$1")" + shift 1 + ;; + ---dockerfile) + VIASH_MODE='dockerfile' + shift 1 + ;; + ---debug) + VIASH_MODE='debug' + shift 1 + ;; + ---cpus) + [ -n "$VIASH_META_CPUS" ] && ViashError Bad arguments for option \'---cpus\': \'$VIASH_META_CPUS\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_META_CPUS="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to ---cpus. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + ---cpus=*) + [ -n "$VIASH_META_CPUS" ] && ViashError Bad arguments for option \'---cpus=*\': \'$VIASH_META_CPUS\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_META_CPUS=$(ViashRemoveFlags "$1") + shift 1 + ;; + ---memory) + [ -n "$VIASH_META_MEMORY" ] && ViashError Bad arguments for option \'---memory\': \'$VIASH_META_MEMORY\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_META_MEMORY="$2" + [ $# -lt 2 ] && ViashError Not enough arguments passed to ---memory. Use "--help" to get more information on the parameters. && exit 1 + shift 2 + ;; + ---memory=*) + [ -n "$VIASH_META_MEMORY" ] && ViashError Bad arguments for option \'---memory=*\': \'$VIASH_META_MEMORY\' \& \'$2\' - you should provide exactly one argument for this option. && exit 1 + VIASH_META_MEMORY=$(ViashRemoveFlags "$1") + shift 1 + ;; + *) # positional arg or unknown option + # since the positional args will be eval'd, can we always quote, instead of using ViashQuote + VIASH_POSITIONAL_ARGS="$VIASH_POSITIONAL_ARGS '$1'" + [[ $1 == -* ]] && ViashWarning $1 looks like a parameter but is not a defined parameter and will instead be treated as a positional argument. Use "--help" to get more information on the parameters. + shift # past argument + ;; + esac +done + +# parse positional parameters +eval set -- $VIASH_POSITIONAL_ARGS + + +if [ "$VIASH_ENGINE_ID" == "native" ] ; then + VIASH_ENGINE_TYPE='native' +elif [ "$VIASH_ENGINE_ID" == "docker" ] ; then + VIASH_ENGINE_TYPE='docker' +else + ViashError "Engine '$VIASH_ENGINE_ID' is not recognized. Options are: docker, native." + exit 1 +fi + +if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then + # check if docker is installed properly + ViashDockerInstallationCheck + + # determine docker image id + if [[ "$VIASH_ENGINE_ID" == 'docker' ]]; then + VIASH_DOCKER_IMAGE_ID='images.viash-hub.com/vsh/biobox/bedtools/bedtools_bedtobam:main' + fi + + # print dockerfile + if [ "$VIASH_MODE" == "dockerfile" ]; then + ViashDockerfile "$VIASH_ENGINE_ID" + exit 0 + + # enter docker container + elif [[ "$VIASH_MODE" == "debug" ]]; then + VIASH_CMD="docker run --entrypoint=bash ${VIASH_DOCKER_RUN_ARGS[@]} -v '$(pwd)':/pwd --workdir /pwd -t $VIASH_DOCKER_IMAGE_ID" + ViashNotice "+ $VIASH_CMD" + eval $VIASH_CMD + exit + + # build docker image + elif [ "$VIASH_MODE" == "setup" ]; then + ViashDockerSetup "$VIASH_DOCKER_IMAGE_ID" "$VIASH_SETUP_STRATEGY" + ViashDockerCheckCommands "$VIASH_DOCKER_IMAGE_ID" 'ps' 'bash' + exit 0 + fi + + # check if docker image exists + ViashDockerSetup "$VIASH_DOCKER_IMAGE_ID" ifneedbepullelsecachedbuild + ViashDockerCheckCommands "$VIASH_DOCKER_IMAGE_ID" 'ps' 'bash' +fi + +# setting computational defaults + +# helper function for parsing memory strings +function ViashMemoryAsBytes { + local memory=`echo "$1" | tr '[:upper:]' '[:lower:]' | tr -d '[:space:]'` + local memory_regex='^([0-9]+)([kmgtp]i?b?|b)$' + if [[ $memory =~ $memory_regex ]]; then + local number=${memory/[^0-9]*/} + local symbol=${memory/*[0-9]/} + + case $symbol in + b) memory_b=$number ;; + kb|k) memory_b=$(( $number * 1000 )) ;; + mb|m) memory_b=$(( $number * 1000 * 1000 )) ;; + gb|g) memory_b=$(( $number * 1000 * 1000 * 1000 )) ;; + tb|t) memory_b=$(( $number * 1000 * 1000 * 1000 * 1000 )) ;; + pb|p) memory_b=$(( $number * 1000 * 1000 * 1000 * 1000 * 1000 )) ;; + kib|ki) memory_b=$(( $number * 1024 )) ;; + mib|mi) memory_b=$(( $number * 1024 * 1024 )) ;; + gib|gi) memory_b=$(( $number * 1024 * 1024 * 1024 )) ;; + tib|ti) memory_b=$(( $number * 1024 * 1024 * 1024 * 1024 )) ;; + pib|pi) memory_b=$(( $number * 1024 * 1024 * 1024 * 1024 * 1024 )) ;; + esac + echo "$memory_b" + fi +} +# compute memory in different units +if [ ! -z ${VIASH_META_MEMORY+x} ]; then + VIASH_META_MEMORY_B=`ViashMemoryAsBytes $VIASH_META_MEMORY` + # do not define other variables if memory_b is an empty string + if [ ! -z "$VIASH_META_MEMORY_B" ]; then + VIASH_META_MEMORY_KB=$(( ($VIASH_META_MEMORY_B+999) / 1000 )) + VIASH_META_MEMORY_MB=$(( ($VIASH_META_MEMORY_KB+999) / 1000 )) + VIASH_META_MEMORY_GB=$(( ($VIASH_META_MEMORY_MB+999) / 1000 )) + VIASH_META_MEMORY_TB=$(( ($VIASH_META_MEMORY_GB+999) / 1000 )) + VIASH_META_MEMORY_PB=$(( ($VIASH_META_MEMORY_TB+999) / 1000 )) + VIASH_META_MEMORY_KIB=$(( ($VIASH_META_MEMORY_B+1023) / 1024 )) + VIASH_META_MEMORY_MIB=$(( ($VIASH_META_MEMORY_KIB+1023) / 1024 )) + VIASH_META_MEMORY_GIB=$(( ($VIASH_META_MEMORY_MIB+1023) / 1024 )) + VIASH_META_MEMORY_TIB=$(( ($VIASH_META_MEMORY_GIB+1023) / 1024 )) + VIASH_META_MEMORY_PIB=$(( ($VIASH_META_MEMORY_TIB+1023) / 1024 )) + else + # unset memory if string is empty + unset $VIASH_META_MEMORY_B + fi +fi +# unset nproc if string is empty +if [ -z "$VIASH_META_CPUS" ]; then + unset $VIASH_META_CPUS +fi + + +# check whether required parameters exist +if [ -z ${VIASH_PAR_INPUT+x} ]; then + ViashError '--input' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi +if [ -z ${VIASH_PAR_GENOME+x} ]; then + ViashError '--genome' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi +if [ -z ${VIASH_META_NAME+x} ]; then + ViashError 'name' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi +if [ -z ${VIASH_META_FUNCTIONALITY_NAME+x} ]; then + ViashError 'functionality_name' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi +if [ -z ${VIASH_META_RESOURCES_DIR+x} ]; then + ViashError 'resources_dir' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi +if [ -z ${VIASH_META_EXECUTABLE+x} ]; then + ViashError 'executable' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi +if [ -z ${VIASH_META_CONFIG+x} ]; then + ViashError 'config' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi +if [ -z ${VIASH_META_TEMP_DIR+x} ]; then + ViashError 'temp_dir' is a required argument. Use "--help" to get more information on the parameters. + exit 1 +fi + +# filling in defaults +if [ -z ${VIASH_PAR_MAP_QUALITY+x} ]; then + VIASH_PAR_MAP_QUALITY="255" +fi +if [ -z ${VIASH_PAR_BED12+x} ]; then + VIASH_PAR_BED12="false" +fi +if [ -z ${VIASH_PAR_UNCOMPRESS_BAM+x} ]; then + VIASH_PAR_UNCOMPRESS_BAM="false" +fi + +# check whether required files exist +if [ ! -z "$VIASH_PAR_INPUT" ] && [ ! -e "$VIASH_PAR_INPUT" ]; then + ViashError "Input file '$VIASH_PAR_INPUT' does not exist." + exit 1 +fi +if [ ! -z "$VIASH_PAR_GENOME" ] && [ ! -e "$VIASH_PAR_GENOME" ]; then + ViashError "Input file '$VIASH_PAR_GENOME' does not exist." + exit 1 +fi + +# check whether parameters values are of the right type +if [[ -n "$VIASH_PAR_MAP_QUALITY" ]]; then + if ! [[ "$VIASH_PAR_MAP_QUALITY" =~ ^[-+]?[0-9]+$ ]]; then + ViashError '--map_quality' has to be an integer. Use "--help" to get more information on the parameters. + exit 1 + fi + if [[ $VIASH_PAR_MAP_QUALITY -lt 0 ]]; then + ViashError '--map_quality' has be more than or equal to 0. Use "--help" to get more information on the parameters. + exit 1 + fi + if [[ $VIASH_PAR_MAP_QUALITY -gt 255 ]]; then + ViashError '--map_quality' has be less than or equal to 255. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_PAR_BED12" ]]; then + if ! [[ "$VIASH_PAR_BED12" =~ ^(true|True|TRUE|false|False|FALSE|yes|Yes|YES|no|No|NO)$ ]]; then + ViashError '--bed12' has to be a boolean_true. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_PAR_UNCOMPRESS_BAM" ]]; then + if ! [[ "$VIASH_PAR_UNCOMPRESS_BAM" =~ ^(true|True|TRUE|false|False|FALSE|yes|Yes|YES|no|No|NO)$ ]]; then + ViashError '--uncompress_bam' has to be a boolean_true. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_CPUS" ]]; then + if ! [[ "$VIASH_META_CPUS" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'cpus' has to be an integer. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_B" ]]; then + if ! [[ "$VIASH_META_MEMORY_B" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_b' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_KB" ]]; then + if ! [[ "$VIASH_META_MEMORY_KB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_kb' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_MB" ]]; then + if ! [[ "$VIASH_META_MEMORY_MB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_mb' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_GB" ]]; then + if ! [[ "$VIASH_META_MEMORY_GB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_gb' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_TB" ]]; then + if ! [[ "$VIASH_META_MEMORY_TB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_tb' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_PB" ]]; then + if ! [[ "$VIASH_META_MEMORY_PB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_pb' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_KIB" ]]; then + if ! [[ "$VIASH_META_MEMORY_KIB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_kib' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_MIB" ]]; then + if ! [[ "$VIASH_META_MEMORY_MIB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_mib' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_GIB" ]]; then + if ! [[ "$VIASH_META_MEMORY_GIB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_gib' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_TIB" ]]; then + if ! [[ "$VIASH_META_MEMORY_TIB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_tib' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi +if [[ -n "$VIASH_META_MEMORY_PIB" ]]; then + if ! [[ "$VIASH_META_MEMORY_PIB" =~ ^[-+]?[0-9]+$ ]]; then + ViashError 'memory_pib' has to be a long. Use "--help" to get more information on the parameters. + exit 1 + fi +fi + +# create parent directories of output files, if so desired +if [ ! -z "$VIASH_PAR_OUTPUT" ] && [ ! -d "$(dirname "$VIASH_PAR_OUTPUT")" ]; then + mkdir -p "$(dirname "$VIASH_PAR_OUTPUT")" +fi + +if [ "$VIASH_ENGINE_ID" == "native" ] ; then + if [ "$VIASH_MODE" == "run" ]; then + VIASH_CMD="bash" + else + ViashError "Engine '$VIASH_ENGINE_ID' does not support mode '$VIASH_MODE'." + exit 1 + fi +fi + +if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then + # detect volumes from file arguments + VIASH_CHOWN_VARS=() +if [ ! -z "$VIASH_PAR_INPUT" ]; then + VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_PAR_INPUT")" ) + VIASH_PAR_INPUT=$(ViashDockerAutodetectMount "$VIASH_PAR_INPUT") +fi +if [ ! -z "$VIASH_PAR_GENOME" ]; then + VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_PAR_GENOME")" ) + VIASH_PAR_GENOME=$(ViashDockerAutodetectMount "$VIASH_PAR_GENOME") +fi +if [ ! -z "$VIASH_PAR_OUTPUT" ]; then + VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_PAR_OUTPUT")" ) + VIASH_PAR_OUTPUT=$(ViashDockerAutodetectMount "$VIASH_PAR_OUTPUT") + VIASH_CHOWN_VARS+=( "$VIASH_PAR_OUTPUT" ) +fi +if [ ! -z "$VIASH_META_RESOURCES_DIR" ]; then + VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_META_RESOURCES_DIR")" ) + VIASH_META_RESOURCES_DIR=$(ViashDockerAutodetectMount "$VIASH_META_RESOURCES_DIR") +fi +if [ ! -z "$VIASH_META_EXECUTABLE" ]; then + VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_META_EXECUTABLE")" ) + VIASH_META_EXECUTABLE=$(ViashDockerAutodetectMount "$VIASH_META_EXECUTABLE") +fi +if [ ! -z "$VIASH_META_CONFIG" ]; then + VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_META_CONFIG")" ) + VIASH_META_CONFIG=$(ViashDockerAutodetectMount "$VIASH_META_CONFIG") +fi +if [ ! -z "$VIASH_META_TEMP_DIR" ]; then + VIASH_DIRECTORY_MOUNTS+=( "$(ViashDockerAutodetectMountArg "$VIASH_META_TEMP_DIR")" ) + VIASH_META_TEMP_DIR=$(ViashDockerAutodetectMount "$VIASH_META_TEMP_DIR") +fi + + # get unique mounts + VIASH_UNIQUE_MOUNTS=($(for val in "${VIASH_DIRECTORY_MOUNTS[@]}"; do echo "$val"; done | sort -u)) +fi + +if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then + # change file ownership + function ViashPerformChown { + if (( ${#VIASH_CHOWN_VARS[@]} )); then + set +e + VIASH_CMD="docker run --entrypoint=bash --rm ${VIASH_UNIQUE_MOUNTS[@]} $VIASH_DOCKER_IMAGE_ID -c 'chown $(id -u):$(id -g) --silent --recursive ${VIASH_CHOWN_VARS[@]}'" + ViashDebug "+ $VIASH_CMD" + eval $VIASH_CMD + set -e + fi + } + trap ViashPerformChown EXIT +fi + +if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then + # helper function for filling in extra docker args + if [ ! -z "$VIASH_META_MEMORY_B" ]; then + VIASH_DOCKER_RUN_ARGS+=("--memory=${VIASH_META_MEMORY_B}") + fi + if [ ! -z "$VIASH_META_CPUS" ]; then + VIASH_DOCKER_RUN_ARGS+=("--cpus=${VIASH_META_CPUS}") + fi +fi + +if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then + VIASH_CMD="docker run --entrypoint=bash ${VIASH_DOCKER_RUN_ARGS[@]} ${VIASH_UNIQUE_MOUNTS[@]} $VIASH_DOCKER_IMAGE_ID" +fi + + +# set dependency paths + + +ViashDebug "Running command: $(echo $VIASH_CMD)" +cat << VIASHEOF | eval $VIASH_CMD +set -e +tempscript=\$(mktemp "$VIASH_META_TEMP_DIR/viash-run-bedtools_bedtobam-XXXXXX").sh +function clean_up { + rm "\$tempscript" +} +function interrupt { + echo -e "\nCTRL-C Pressed..." + exit 1 +} +trap clean_up EXIT +trap interrupt INT SIGINT +cat > "\$tempscript" << 'VIASHMAIN' +#!/bin/bash + +## VIASH START +# The following code has been auto-generated by Viash. +$( if [ ! -z ${VIASH_PAR_INPUT+x} ]; then echo "${VIASH_PAR_INPUT}" | sed "s#'#'\"'\"'#g;s#.*#par_input='&'#" ; else echo "# par_input="; fi ) +$( if [ ! -z ${VIASH_PAR_GENOME+x} ]; then echo "${VIASH_PAR_GENOME}" | sed "s#'#'\"'\"'#g;s#.*#par_genome='&'#" ; else echo "# par_genome="; fi ) +$( if [ ! -z ${VIASH_PAR_OUTPUT+x} ]; then echo "${VIASH_PAR_OUTPUT}" | sed "s#'#'\"'\"'#g;s#.*#par_output='&'#" ; else echo "# par_output="; fi ) +$( if [ ! -z ${VIASH_PAR_MAP_QUALITY+x} ]; then echo "${VIASH_PAR_MAP_QUALITY}" | sed "s#'#'\"'\"'#g;s#.*#par_map_quality='&'#" ; else echo "# par_map_quality="; fi ) +$( if [ ! -z ${VIASH_PAR_BED12+x} ]; then echo "${VIASH_PAR_BED12}" | sed "s#'#'\"'\"'#g;s#.*#par_bed12='&'#" ; else echo "# par_bed12="; fi ) +$( if [ ! -z ${VIASH_PAR_UNCOMPRESS_BAM+x} ]; then echo "${VIASH_PAR_UNCOMPRESS_BAM}" | sed "s#'#'\"'\"'#g;s#.*#par_uncompress_bam='&'#" ; else echo "# par_uncompress_bam="; fi ) +$( if [ ! -z ${VIASH_META_NAME+x} ]; then echo "${VIASH_META_NAME}" | sed "s#'#'\"'\"'#g;s#.*#meta_name='&'#" ; else echo "# meta_name="; fi ) +$( if [ ! -z ${VIASH_META_FUNCTIONALITY_NAME+x} ]; then echo "${VIASH_META_FUNCTIONALITY_NAME}" | sed "s#'#'\"'\"'#g;s#.*#meta_functionality_name='&'#" ; else echo "# meta_functionality_name="; fi ) +$( if [ ! -z ${VIASH_META_RESOURCES_DIR+x} ]; then echo "${VIASH_META_RESOURCES_DIR}" | sed "s#'#'\"'\"'#g;s#.*#meta_resources_dir='&'#" ; else echo "# meta_resources_dir="; fi ) +$( if [ ! -z ${VIASH_META_EXECUTABLE+x} ]; then echo "${VIASH_META_EXECUTABLE}" | sed "s#'#'\"'\"'#g;s#.*#meta_executable='&'#" ; else echo "# meta_executable="; fi ) +$( if [ ! -z ${VIASH_META_CONFIG+x} ]; then echo "${VIASH_META_CONFIG}" | sed "s#'#'\"'\"'#g;s#.*#meta_config='&'#" ; else echo "# meta_config="; fi ) +$( if [ ! -z ${VIASH_META_TEMP_DIR+x} ]; then echo "${VIASH_META_TEMP_DIR}" | sed "s#'#'\"'\"'#g;s#.*#meta_temp_dir='&'#" ; else echo "# meta_temp_dir="; fi ) +$( if [ ! -z ${VIASH_META_CPUS+x} ]; then echo "${VIASH_META_CPUS}" | sed "s#'#'\"'\"'#g;s#.*#meta_cpus='&'#" ; else echo "# meta_cpus="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_B+x} ]; then echo "${VIASH_META_MEMORY_B}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_b='&'#" ; else echo "# meta_memory_b="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_KB+x} ]; then echo "${VIASH_META_MEMORY_KB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_kb='&'#" ; else echo "# meta_memory_kb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_MB+x} ]; then echo "${VIASH_META_MEMORY_MB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_mb='&'#" ; else echo "# meta_memory_mb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_GB+x} ]; then echo "${VIASH_META_MEMORY_GB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_gb='&'#" ; else echo "# meta_memory_gb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_TB+x} ]; then echo "${VIASH_META_MEMORY_TB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_tb='&'#" ; else echo "# meta_memory_tb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_PB+x} ]; then echo "${VIASH_META_MEMORY_PB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_pb='&'#" ; else echo "# meta_memory_pb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_KIB+x} ]; then echo "${VIASH_META_MEMORY_KIB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_kib='&'#" ; else echo "# meta_memory_kib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_MIB+x} ]; then echo "${VIASH_META_MEMORY_MIB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_mib='&'#" ; else echo "# meta_memory_mib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_GIB+x} ]; then echo "${VIASH_META_MEMORY_GIB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_gib='&'#" ; else echo "# meta_memory_gib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_TIB+x} ]; then echo "${VIASH_META_MEMORY_TIB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_tib='&'#" ; else echo "# meta_memory_tib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_pib='&'#" ; else echo "# meta_memory_pib="; fi ) + +## VIASH END + +set -eo pipefail + +# Unset parameters +[[ "\$par_bed12" == "false" ]] && unset par_bed12 +[[ "\$par_uncompress_bam" == "false" ]] && unset par_uncompress_bam + +# Execute bedtools bed to bam +bedtools bedtobam \\ + \${par_bed12:+-bed12} \\ + \${par_uncompress_bam:+-ubam} \\ + \${par_map_quality:+-mapq "\$par_map_quality"} \\ + -i "\$par_input" \\ + -g "\$par_genome" \\ + > "\$par_output" +VIASHMAIN +bash "\$tempscript" & +wait "\$!" + +VIASHEOF + + +if [[ "$VIASH_ENGINE_TYPE" == "docker" ]]; then + # strip viash automount from file paths + + if [ ! -z "$VIASH_PAR_INPUT" ]; then + VIASH_PAR_INPUT=$(ViashDockerStripAutomount "$VIASH_PAR_INPUT") + fi + if [ ! -z "$VIASH_PAR_GENOME" ]; then + VIASH_PAR_GENOME=$(ViashDockerStripAutomount "$VIASH_PAR_GENOME") + fi + if [ ! -z "$VIASH_PAR_OUTPUT" ]; then + VIASH_PAR_OUTPUT=$(ViashDockerStripAutomount "$VIASH_PAR_OUTPUT") + fi + if [ ! -z "$VIASH_META_RESOURCES_DIR" ]; then + VIASH_META_RESOURCES_DIR=$(ViashDockerStripAutomount "$VIASH_META_RESOURCES_DIR") + fi + if [ ! -z "$VIASH_META_EXECUTABLE" ]; then + VIASH_META_EXECUTABLE=$(ViashDockerStripAutomount "$VIASH_META_EXECUTABLE") + fi + if [ ! -z "$VIASH_META_CONFIG" ]; then + VIASH_META_CONFIG=$(ViashDockerStripAutomount "$VIASH_META_CONFIG") + fi + if [ ! -z "$VIASH_META_TEMP_DIR" ]; then + VIASH_META_TEMP_DIR=$(ViashDockerStripAutomount "$VIASH_META_TEMP_DIR") + fi +fi + + +# check whether required files exist +if [ ! -z "$VIASH_PAR_OUTPUT" ] && [ ! -e "$VIASH_PAR_OUTPUT" ]; then + ViashError "Output file '$VIASH_PAR_OUTPUT' does not exist." + exit 1 +fi + + +exit 0 diff --git a/target/executable/bedtools/bedtools_getfasta/.config.vsh.yaml b/target/executable/bedtools/bedtools_getfasta/.config.vsh.yaml index 78bb1efc..11b0f864 100644 --- a/target/executable/bedtools/bedtools_getfasta/.config.vsh.yaml +++ b/target/executable/bedtools/bedtools_getfasta/.config.vsh.yaml @@ -232,7 +232,7 @@ build_info: output: "target/executable/bedtools/bedtools_getfasta" executable: "target/executable/bedtools/bedtools_getfasta/bedtools_getfasta" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/bedtools/bedtools_getfasta/bedtools_getfasta b/target/executable/bedtools/bedtools_getfasta/bedtools_getfasta index da573ed3..cc53425c 100755 --- a/target/executable/bedtools/bedtools_getfasta/bedtools_getfasta +++ b/target/executable/bedtools/bedtools_getfasta/bedtools_getfasta @@ -525,9 +525,9 @@ RUN echo "bedtools: \"$(bedtools --version | sed -n 's/^bedtools //p')\"" > /var LABEL org.opencontainers.image.authors="Dries Schaumont" LABEL org.opencontainers.image.description="Companion container for running component bedtools bedtools_getfasta" -LABEL org.opencontainers.image.created="2024-07-31T19:27:35Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:47Z" LABEL org.opencontainers.image.source="https://github.com/arq5x/bedtools2" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER diff --git a/target/executable/bedtools/bedtools_intersect/.config.vsh.yaml b/target/executable/bedtools/bedtools_intersect/.config.vsh.yaml index eb0a6627..4de12853 100644 --- a/target/executable/bedtools/bedtools_intersect/.config.vsh.yaml +++ b/target/executable/bedtools/bedtools_intersect/.config.vsh.yaml @@ -410,7 +410,7 @@ build_info: output: "target/executable/bedtools/bedtools_intersect" executable: "target/executable/bedtools/bedtools_intersect/bedtools_intersect" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/bedtools/bedtools_intersect/bedtools_intersect b/target/executable/bedtools/bedtools_intersect/bedtools_intersect index 28b887f7..bb865a49 100755 --- a/target/executable/bedtools/bedtools_intersect/bedtools_intersect +++ b/target/executable/bedtools/bedtools_intersect/bedtools_intersect @@ -632,9 +632,9 @@ RUN echo "bedtools: \"$(bedtools --version | sed -n 's/^bedtools //p')\"" > /var LABEL org.opencontainers.image.authors="Theodoro Gasperin Terra Camargo" LABEL org.opencontainers.image.description="Companion container for running component bedtools bedtools_intersect" -LABEL org.opencontainers.image.created="2024-07-31T19:27:35Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:48Z" LABEL org.opencontainers.image.source="https://github.com/arq5x/bedtools2" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER @@ -1729,27 +1729,35 @@ $( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" ## VIASH END -[[ "\$par_write_a" == "false" ]] && unset par_write_a -[[ "\$par_write_b" == "false" ]] && unset par_write_b -[[ "\$par_left_outer_join" == "false" ]] && unset par_left_outer_join -[[ "\$par_write_overlap" == "false" ]] && unset par_write_overlap -[[ "\$par_write_overlap_plus" == "false" ]] && unset par_write_overlap_plus -[[ "\$par_report_A_if_no_overlap" == "false" ]] && unset par_report_A_if_no_overlap -[[ "\$par_number_of_overlaps_A" == "false" ]] && unset par_number_of_overlaps_A -[[ "\$par_report_no_overlaps_A" == "false" ]] && unset par_report_no_overlaps_A -[[ "\$par_uncompressed_bam" == "false" ]] && unset par_uncompressed_bam -[[ "\$par_same_strand" == "false" ]] && unset par_same_strand -[[ "\$par_opposite_strand" == "false" ]] && unset par_opposite_strand -[[ "\$par_reciprocal_overlap" == "false" ]] && unset par_reciprocal_overlap -[[ "\$par_either_overlap" == "false" ]] && unset par_either_overlap -[[ "\$par_split" == "false" ]] && unset par_split -[[ "\$par_nonamecheck" == "false" ]] && unset par_nonamecheck -[[ "\$par_sorted" == "false" ]] && unset par_sorted -[[ "\$par_filenames" == "false" ]] && unset par_filenames -[[ "\$par_sortout" == "false" ]] && unset par_sortout -[[ "\$par_bed" == "false" ]] && unset par_bed -[[ "\$par_header" == "false" ]] && unset par_header -[[ "\$par_no_buffer_output" == "false" ]] && unset par_no_buffer_output +unset_if_false=( + par_write_a + par_write_b + par_left_outer_join + par_write_overlap + par_write_overlap_plus + par_report_A_if_no_overlap + par_number_of_overlaps_A + par_report_no_overlaps_A + par_uncompressed_bam + par_same_strand + par_opposite_strand + par_reciprocal_overlap + par_either_overlap + par_split + par_nonamecheck + par_sorted + par_filenames + par_sortout + par_bed + par_no_buffer_output + par_header +) + +for par in \${unset_if_false[@]}; do + test_val="\${!par}" + [[ "\$test_val" == "false" ]] && unset \$par +done + # Create input array IFS=";" read -ra input <<< \$par_input_b diff --git a/target/executable/bedtools/bedtools_sort/.config.vsh.yaml b/target/executable/bedtools/bedtools_sort/.config.vsh.yaml index c75ffb08..86f9157a 100644 --- a/target/executable/bedtools/bedtools_sort/.config.vsh.yaml +++ b/target/executable/bedtools/bedtools_sort/.config.vsh.yaml @@ -222,7 +222,7 @@ build_info: output: "target/executable/bedtools/bedtools_sort" executable: "target/executable/bedtools/bedtools_sort/bedtools_sort" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/bedtools/bedtools_sort/bedtools_sort b/target/executable/bedtools/bedtools_sort/bedtools_sort index cdb4e006..04fcce83 100755 --- a/target/executable/bedtools/bedtools_sort/bedtools_sort +++ b/target/executable/bedtools/bedtools_sort/bedtools_sort @@ -508,9 +508,9 @@ RUN echo "bedtools: \"$(bedtools --version | sed -n 's/^bedtools //p')\"" > /var LABEL org.opencontainers.image.authors="Theodoro Gasperin Terra Camargo" LABEL org.opencontainers.image.description="Companion container for running component bedtools bedtools_sort" -LABEL org.opencontainers.image.created="2024-07-31T19:27:35Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:46Z" LABEL org.opencontainers.image.source="https://github.com/arq5x/bedtools2" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER @@ -1210,13 +1210,20 @@ $( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" ## VIASH END # Unset parameters -[[ "\$par_sizeA" == "false" ]] && unset par_sizeA -[[ "\$par_sizeD" == "false" ]] && unset par_sizeD -[[ "\$par_chrThenSizeA" == "false" ]] && unset par_chrThenSizeA -[[ "\$par_chrThenSizeD" == "false" ]] && unset par_chrThenSizeD -[[ "\$par_chrThenScoreA" == "false" ]] && unset par_chrThenScoreA -[[ "\$par_chrThenScoreD" == "false" ]] && unset par_chrThenScoreD -[[ "\$par_header" == "false" ]] && unset par_header +unset_if_false=( + par_sizeA + par_sizeD + par_chrThenSizeA + par_chrThenSizeD + par_chrThenScoreA + par_chrThenScoreD + par_header +) + +for par in \${unset_if_false[@]}; do + test_val="\${!par}" + [[ "\$test_val" == "false" ]] && unset \$par +done # Execute bedtools sort with the provided arguments bedtools sort \\ diff --git a/target/executable/busco/busco_download_datasets/.config.vsh.yaml b/target/executable/busco/busco_download_datasets/.config.vsh.yaml index 00184502..4321c877 100644 --- a/target/executable/busco/busco_download_datasets/.config.vsh.yaml +++ b/target/executable/busco/busco_download_datasets/.config.vsh.yaml @@ -158,7 +158,7 @@ build_info: output: "target/executable/busco/busco_download_datasets" executable: "target/executable/busco/busco_download_datasets/busco_download_datasets" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/busco/busco_download_datasets/busco_download_datasets b/target/executable/busco/busco_download_datasets/busco_download_datasets index f80559a5..27312328 100755 --- a/target/executable/busco/busco_download_datasets/busco_download_datasets +++ b/target/executable/busco/busco_download_datasets/busco_download_datasets @@ -474,9 +474,9 @@ RUN busco --version | sed 's/BUSCO\s\(.*\)/busco: "\1"/' > /var/software_version LABEL org.opencontainers.image.authors="Dorien Roosen" LABEL org.opencontainers.image.description="Companion container for running component busco busco_download_datasets" -LABEL org.opencontainers.image.created="2024-07-31T19:27:31Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:43Z" LABEL org.opencontainers.image.source="https://gitlab.com/ezlab/busco" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER diff --git a/target/executable/busco/busco_list_datasets/.config.vsh.yaml b/target/executable/busco/busco_list_datasets/.config.vsh.yaml index 9d7031ea..aa106bfe 100644 --- a/target/executable/busco/busco_list_datasets/.config.vsh.yaml +++ b/target/executable/busco/busco_list_datasets/.config.vsh.yaml @@ -145,7 +145,7 @@ build_info: output: "target/executable/busco/busco_list_datasets" executable: "target/executable/busco/busco_list_datasets/busco_list_datasets" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/busco/busco_list_datasets/busco_list_datasets b/target/executable/busco/busco_list_datasets/busco_list_datasets index 80a897a0..8dfbe802 100755 --- a/target/executable/busco/busco_list_datasets/busco_list_datasets +++ b/target/executable/busco/busco_list_datasets/busco_list_datasets @@ -464,9 +464,9 @@ RUN busco --version | sed 's/BUSCO\s\(.*\)/busco: "\1"/' > /var/software_version LABEL org.opencontainers.image.authors="Dorien Roosen" LABEL org.opencontainers.image.description="Companion container for running component busco busco_list_datasets" -LABEL org.opencontainers.image.created="2024-07-31T19:27:31Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:43Z" LABEL org.opencontainers.image.source="https://gitlab.com/ezlab/busco" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER diff --git a/target/executable/busco/busco_run/.config.vsh.yaml b/target/executable/busco/busco_run/.config.vsh.yaml index 18004155..d2fad983 100644 --- a/target/executable/busco/busco_run/.config.vsh.yaml +++ b/target/executable/busco/busco_run/.config.vsh.yaml @@ -423,7 +423,7 @@ build_info: output: "target/executable/busco/busco_run" executable: "target/executable/busco/busco_run/busco_run" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/busco/busco_run/busco_run b/target/executable/busco/busco_run/busco_run index 6e13b929..1c4aab79 100755 --- a/target/executable/busco/busco_run/busco_run +++ b/target/executable/busco/busco_run/busco_run @@ -631,9 +631,9 @@ RUN busco --version | sed 's/BUSCO\s\(.*\)/busco: "\1"/' > /var/software_version LABEL org.opencontainers.image.authors="Dorien Roosen" LABEL org.opencontainers.image.description="Companion container for running component busco busco_run" -LABEL org.opencontainers.image.created="2024-07-31T19:27:31Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:44Z" LABEL org.opencontainers.image.source="https://gitlab.com/ezlab/busco" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER @@ -1612,18 +1612,24 @@ $( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" ## VIASH END +unset_if_false=( + par_tar + par_force + par_quiet + par_restart + par_auto_lineage + par_auto_lineage_euk + par_auto_lineage_prok + par_augustus + par_long + par_scaffold_composition + par_miniprot +) -[[ "\$par_tar" == "false" ]] && unset par_tar -[[ "\$par_force" == "false" ]] && unset par_force -[[ "\$par_quiet" == "false" ]] && unset par_quiet -[[ "\$par_restart" == "false" ]] && unset par_restart -[[ "\$par_auto_lineage" == "false" ]] && unset par_auto_lineage -[[ "\$par_auto_lineage_euk" == "false" ]] && unset par_auto_lineage_euk -[[ "\$par_auto_lineage_prok" == "false" ]] && unset par_auto_lineage_prok -[[ "\$par_augustus" == "false" ]] && unset par_augustus -[[ "\$par_long" == "false" ]] && unset par_long -[[ "\$par_scaffold_composition" == "false" ]] && unset par_scaffold_composition -[[ "\$par_miniprot" == "false" ]] && unset par_miniprot +for par in \${unset_if_false[@]}; do + test_val="\${!par}" + [[ "\$test_val" == "false" ]] && unset \$par +done tmp_dir=\$(mktemp -d -p "\$meta_temp_dir" busco_XXXXXXXXX) prefix=\$(openssl rand -hex 8) diff --git a/target/executable/cutadapt/.config.vsh.yaml b/target/executable/cutadapt/.config.vsh.yaml index 272d9fbd..697434e4 100644 --- a/target/executable/cutadapt/.config.vsh.yaml +++ b/target/executable/cutadapt/.config.vsh.yaml @@ -740,7 +740,7 @@ build_info: output: "target/executable/cutadapt" executable: "target/executable/cutadapt/cutadapt" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/cutadapt/cutadapt b/target/executable/cutadapt/cutadapt index 58efdbe2..fa087008 100755 --- a/target/executable/cutadapt/cutadapt +++ b/target/executable/cutadapt/cutadapt @@ -830,9 +830,9 @@ RUN cutadapt --version | sed 's/\(.*\)/cutadapt: "\1"/' > /var/software_versions LABEL org.opencontainers.image.authors="Toni Verbeiren" LABEL org.opencontainers.image.description="Companion container for running component cutadapt" -LABEL org.opencontainers.image.created="2024-07-31T19:27:29Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:42Z" LABEL org.opencontainers.image.source="https://github.com/marcelm/cutadapt" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER diff --git a/target/executable/falco/.config.vsh.yaml b/target/executable/falco/.config.vsh.yaml index a3404875..fa2e830b 100644 --- a/target/executable/falco/.config.vsh.yaml +++ b/target/executable/falco/.config.vsh.yaml @@ -317,7 +317,7 @@ build_info: output: "target/executable/falco" executable: "target/executable/falco/falco" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/falco/falco b/target/executable/falco/falco index 3314c41b..7efedcb2 100755 --- a/target/executable/falco/falco +++ b/target/executable/falco/falco @@ -588,9 +588,9 @@ RUN echo "falco: \"$(falco -v | sed -n 's/^falco //p')\"" > /var/software_versio LABEL org.opencontainers.image.authors="Toni Verbeiren" LABEL org.opencontainers.image.description="Companion container for running component falco" -LABEL org.opencontainers.image.created="2024-07-31T19:27:30Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:42Z" LABEL org.opencontainers.image.source="https://github.com/smithlabcode/falco" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER diff --git a/target/executable/fastp/.config.vsh.yaml b/target/executable/fastp/.config.vsh.yaml index 91f630b8..8d8b7ae9 100644 --- a/target/executable/fastp/.config.vsh.yaml +++ b/target/executable/fastp/.config.vsh.yaml @@ -1083,7 +1083,7 @@ build_info: output: "target/executable/fastp" executable: "target/executable/fastp/fastp" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/fastp/fastp b/target/executable/fastp/fastp index 9a78e514..eb34d83a 100755 --- a/target/executable/fastp/fastp +++ b/target/executable/fastp/fastp @@ -1027,9 +1027,9 @@ RUN fastp --version 2>&1 | sed 's# #: "#;s#$#"#' > /var/software_versions.txt LABEL org.opencontainers.image.authors="Robrecht Cannoodt" LABEL org.opencontainers.image.description="Companion container for running component fastp" -LABEL org.opencontainers.image.created="2024-07-31T19:27:36Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:48Z" LABEL org.opencontainers.image.source="https://github.com/OpenGene/fastp" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER @@ -3184,25 +3184,32 @@ $( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" ## VIASH END # disable flags -[[ "\$par_disable_adapter_trimming" == "false" ]] && unset par_disable_adapter_trimming -[[ "\$par_detect_adapter_for_pe" == "false" ]] && unset par_detect_adapter_for_pe -[[ "\$par_merge" == "false" ]] && unset par_merge -[[ "\$par_include_unmerged" == "false" ]] && unset par_include_unmerged -[[ "\$par_interleaved_in" == "false" ]] && unset par_interleaved_in -[[ "\$par_fix_mgi_id" == "false" ]] && unset par_fix_mgi_id -[[ "\$par_phred64" == "false" ]] && unset par_phred64 -[[ "\$par_dont_overwrite" == "false" ]] && unset par_dont_overwrite -[[ "\$par_verbose" == "false" ]] && unset par_verbose -[[ "\$par_dedup" == "false" ]] && unset par_dedup -[[ "\$par_dont_eval_duplication" == "false" ]] && unset par_dont_eval_duplication -[[ "\$par_trim_poly_g" == "false" ]] && unset par_trim_poly_g -[[ "\$par_disable_trim_poly_g" == "false" ]] && unset par_disable_trim_poly_g -[[ "\$par_trim_poly_x" == "false" ]] && unset par_trim_poly_x -[[ "\$par_disable_quality_filtering" == "false" ]] && unset par_disable_quality_filtering -[[ "\$par_disable_length_filtering" == "false" ]] && unset par_disable_length_filtering -[[ "\$par_low_complexity_filter" == "false" ]] && unset par_low_complexity_filter -[[ "\$par_umi" == "false" ]] && unset par_umi -[[ "\$par_overrepresentation_analysis" == "false" ]] && unset par_overrepresentation_analysis +unset_if_false=( + par_disable_adapter_trimming + par_detect_adapter_for_pe + par_merge + par_include_unmerged + par_interleaved_in + par_fix_mgi_id + par_phred64 + par_dont_overwrite + par_verbose + par_dedup + par_dont_eval_duplication + par_trim_poly_g + par_disable_trim_poly_g + par_trim_poly_x + par_disable_quality_filtering + par_disable_length_filtering + par_low_complexity_filter + par_umi + par_overrepresentation_analysis +) + +for par in \${unset_if_false[@]}; do + test_val="\${!par}" + [[ "\$test_val" == "false" ]] && unset \$par +done # run command fastp \\ diff --git a/target/executable/featurecounts/.config.vsh.yaml b/target/executable/featurecounts/.config.vsh.yaml index d08f6adc..8f2d2765 100644 --- a/target/executable/featurecounts/.config.vsh.yaml +++ b/target/executable/featurecounts/.config.vsh.yaml @@ -645,7 +645,7 @@ build_info: output: "target/executable/featurecounts" executable: "target/executable/featurecounts/featurecounts" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/featurecounts/featurecounts b/target/executable/featurecounts/featurecounts index da15c514..36f439e8 100755 --- a/target/executable/featurecounts/featurecounts +++ b/target/executable/featurecounts/featurecounts @@ -753,9 +753,9 @@ RUN featureCounts -v 2>&1 | sed 's/featureCounts v\([0-9.]*\)/featureCounts: \1/ LABEL org.opencontainers.image.authors="Sai Nirmayi Yasa" LABEL org.opencontainers.image.description="Companion container for running component featurecounts" -LABEL org.opencontainers.image.created="2024-07-31T19:27:32Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:44Z" LABEL org.opencontainers.image.source="https://github.com/ShiLab-Bioinformatics/subread" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER @@ -2252,24 +2252,31 @@ par_feature_type=\$(echo \$par_feature_type | tr ',' ';') par_extra_attributes=\$(echo \$par_extra_attributes | tr ',' ';') # unset flag variables -[[ "\$par_feature_level" == "false" ]] && unset par_feature_level -[[ "\$par_overlapping" == "false" ]] && unset par_overlapping -[[ "\$par_largest_overlap" == "false" ]] && unset par_largest_overlap -[[ "\$par_multi_mapping" == "false" ]] && unset par_multi_mapping -[[ "\$par_fraction" == "false" ]] && unset par_fraction -[[ "\$par_split_only" == "false" ]] && unset par_split_only -[[ "\$par_non_split_only" == "false" ]] && unset par_non_split_only -[[ "\$par_primary" == "false" ]] && unset par_primary -[[ "\$par_ignore_dup" == "false" ]] && unset par_ignore_dup -[[ "\$par_paired" == "false" ]] && unset par_paired -[[ "\$par_count_read_pairs" == "false" ]] && unset par_count_read_pairs -[[ "\$par_both_aligned" == "false" ]] && unset par_both_aligned -[[ "\$par_check_pe_dist" == "false" ]] && unset par_check_pe_dist -[[ "\$par_same_strand" == "false" ]] && unset par_same_strand -[[ "\$par_donotsort" == "false" ]] && unset par_donotsort -[[ "\$par_by_read_group" == "false" ]] && unset par_by_read_group -[[ "\$par_long_reads" == "false" ]] && unset par_long_reads -[[ "\$par_verbose" == "false" ]] && unset par_verbose +unset_if_false=( + par_feature_level + par_overlapping + par_largest_overlap + par_multi_mapping + par_fraction + par_split_only + par_non_split_only + par_primary + par_ignore_dup + par_paired + par_count_read_pairs + par_both_aligned + par_check_pe_dist + par_same_strand + par_donotsort + par_by_read_group + par_long_reads + par_verbose +) + +for par in \${unset_if_false[@]}; do + test_val="\${!par}" + [[ "\$test_val" == "false" ]] && unset \$par +done IFS=";" read -ra input <<< \$par_input diff --git a/target/executable/gffread/.config.vsh.yaml b/target/executable/gffread/.config.vsh.yaml index 4e1616c6..67aef5f9 100644 --- a/target/executable/gffread/.config.vsh.yaml +++ b/target/executable/gffread/.config.vsh.yaml @@ -685,7 +685,7 @@ build_info: output: "target/executable/gffread" executable: "target/executable/gffread/gffread" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/gffread/gffread b/target/executable/gffread/gffread index 92b5bcf6..4e64d015 100755 --- a/target/executable/gffread/gffread +++ b/target/executable/gffread/gffread @@ -806,9 +806,9 @@ RUN echo "gffread: \"$(gffread --version 2>&1)\"" > /var/software_versions.txt LABEL org.opencontainers.image.authors="Emma Rousseau" LABEL org.opencontainers.image.description="Companion container for running component gffread" -LABEL org.opencontainers.image.created="2024-07-31T19:27:30Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:42Z" LABEL org.opencontainers.image.source="https://github.com/gpertea/gffread" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER @@ -2523,51 +2523,58 @@ $( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" ## VIASH END # unset flags -[[ "\$par_coding" == "false" ]] && unset par_coding -[[ "\$par_strict_range" == "false" ]] && unset par_strict_range -[[ "\$par_no_single_exon" == "false" ]] && unset par_no_single_exon -[[ "\$par_no_exon_attrs" == "false" ]] && unset par_no_exon_attrs -[[ "\$par_nc" == "false" ]] && unset par_nc -[[ "\$par_ignore_locus" == "false" ]] && unset par_ignore_locus -[[ "\$par_description" == "false" ]] && unset par_description -[[ "\$par_sort_alpha" == "false" ]] && unset par_sort_alpha -[[ "\$par_keep_genes" == "false" ]] && unset par_keep_genes -[[ "\$par_keep_attrs" == "false" ]] && unset par_keep_attrs -[[ "\$par_keep_exon_attrs" == "false" ]] && unset par_keep_exon_attrs -[[ "\$par_keep_comments" == "false" ]] && unset par_keep_comments -[[ "\$par_process_other" == "false" ]] && unset par_process_other -[[ "\$par_rm_stop_codons" == "false" ]] && unset par_rm_stop_codons -[[ "\$par_adj_cds_start" == "false" ]] && unset par_adj_cds_start -[[ "\$par_opposite_strand" == "false" ]] && unset par_opposite_strand -[[ "\$par_coding_status" == "false" ]] && unset par_coding_status -[[ "\$par_add_hasCDS" == "false" ]] && unset par_add_hasCDS -[[ "\$par_adj_stop" == "false" ]] && unset par_adj_stop -[[ "\$par_rm_noncanon" == "false" ]] && unset par_rm_noncanon -[[ "\$par_complete_cds" == "false" ]] && unset par_complete_cds -[[ "\$par_no_pseudo" == "false" ]] && unset par_no_pseudo -[[ "\$par_in_bed" == "false" ]] && unset par_in_bed -[[ "\$par_in_tlf" == "false" ]] && unset par_in_tlf -[[ "\$par_stream" == "false" ]] && unset par_stream -[[ "\$par_merge" == "false" ]] && unset par_merge -[[ "\$par_rm_redundant" == "false" ]] && unset par_rm_redundant -[[ "\$par_no_boundary" == "false" ]] && unset par_no_boundary -[[ "\$par_no_overlap" == "false" ]] && unset par_no_overlap -[[ "\$par_force_exons" == "false" ]] && unset par_force_exons -[[ "\$par_gene2exon" == "false" ]] && unset par_gene2exon -[[ "\$par_t_adopt" == "false" ]] && unset par_t_adopt -[[ "\$par_decode" == "false" ]] && unset par_decode -[[ "\$par_merge_exons" == "false" ]] && unset par_merge_exons -[[ "\$par_junctions" == "false" ]] && unset par_junctions -[[ "\$par_w_nocds" == "false" ]] && unset par_w_nocds -[[ "\$par_tr_cds" == "false" ]] && unset par_tr_cds -[[ "\$par_w_coords" == "false" ]] && unset par_w_coords -[[ "\$par_stop_dot" == "false" ]] && unset par_stop_dot -[[ "\$par_id_version" == "false" ]] && unset par_id_version -[[ "\$par_gtf_output" == "false" ]] && unset par_gtf_output -[[ "\$par_bed" == "false" ]] && unset par_bed -[[ "\$par_tlf" == "false" ]] && unset par_tlf -[[ "\$par_expose_dups" == "false" ]] && unset par_expose_dups -[[ "\$par_cluster_only" == "false" ]] && unset par_cluster_only +unset_if_false=( + par_coding + par_strict_range + par_no_single_exon + par_no_exon_attrs + par_nc + par_ignore_locus + par_description + par_sort_alpha + par_keep_genes + par_keep_attrs + par_keep_exon_attrs + par_keep_comments + par_process_other + par_rm_stop_codons + par_adj_cds_start + par_opposite_strand + par_coding_status + par_add_hasCDS + par_adj_stop + par_rm_noncanon + par_complete_cds + par_no_pseudo + par_in_bed + par_in_tlf + par_stream + par_merge + par_rm_redundant + par_no_boundary + par_no_overlap + par_force_exons + par_gene2exon + par_t_adopt + par_decode + par_merge_exons + par_junctions + par_w_nocds + par_tr_cds + par_w_coords + par_stop_dot + par_id_version + par_gtf_output + par_bed + par_tlf + par_expose_dups + par_cluster_only +) + +for par in \${unset_if_false[@]}; do + test_val="\${!par}" + [[ "\$test_val" == "false" ]] && unset \$par +done # if par_table is not empty, replace ";" with "," par_table=\$(echo "\$par_table" | tr ';' ',') diff --git a/target/executable/lofreq/lofreq_call/.config.vsh.yaml b/target/executable/lofreq/lofreq_call/.config.vsh.yaml index f6755b1d..b8e72d5d 100644 --- a/target/executable/lofreq/lofreq_call/.config.vsh.yaml +++ b/target/executable/lofreq/lofreq_call/.config.vsh.yaml @@ -507,7 +507,7 @@ build_info: output: "target/executable/lofreq/lofreq_call" executable: "target/executable/lofreq/lofreq_call/lofreq_call" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/lofreq/lofreq_call/lofreq_call b/target/executable/lofreq/lofreq_call/lofreq_call index 389e3be1..e0657616 100755 --- a/target/executable/lofreq/lofreq_call/lofreq_call +++ b/target/executable/lofreq/lofreq_call/lofreq_call @@ -655,9 +655,9 @@ echo "lofreq: $version" > /var/software_versions.txt LABEL org.opencontainers.image.authors="Kai Waldrant" LABEL org.opencontainers.image.description="Companion container for running component lofreq lofreq_call" -LABEL org.opencontainers.image.created="2024-07-31T19:27:39Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:51Z" LABEL org.opencontainers.image.source="https://github.com/viash-hub/biobox" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER @@ -1889,21 +1889,28 @@ $( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" ## VIASH END # Unset all parameters that are set to "false" -[[ "\$par_no_baq" == "false" ]] && unset par_no_baq -[[ "\$par_no_idaq" == "false" ]] && unset par_no_idaq -[[ "\$par_del_baq" == "false" ]] && unset par_del_baq -[[ "\$par_no_ext_baq" == "false" ]] && unset par_no_ext_baq -[[ "\$par_no_mq" == "false" ]] && unset par_no_mq -[[ "\$par_call_indels" == "false" ]] && unset par_call_indels -[[ "\$par_only_indels" == "false" ]] && unset par_only_indels -[[ "\$par_src_qual" == "false" ]] && unset par_src_qual -[[ "\$par_illumina_13" == "false" ]] && unset par_illumina_13 -[[ "\$par_use_orphan" == "false" ]] && unset par_use_orphan -[[ "\$par_plp_summary_only" == "false" ]] && unset par_plp_summary_only -[[ "\$par_no_default_filter" == "false" ]] && unset par_no_default_filter -[[ "\$par_force_overwrite" == "false" ]] && unset par_force_overwrite -[[ "\$par_verbose" == "false" ]] && unset par_verbose -[[ "\$par_debug" == "false" ]] && unset par_debug +unset_if_false=( + par_no_baq + par_no_idaq + par_del_baq + par_no_ext_baq + par_no_mq + par_call_indels + par_only_indels + par_src_qual + par_illumina_13 + par_use_orphan + par_plp_summary_only + par_no_default_filter + par_force_overwrite + par_verbose + par_debug +) + +for par in \${unset_if_false[@]}; do + test_val="\${!par}" + [[ "\$test_val" == "false" ]] && unset \$par +done # Run lofreq call lofreq call \\ diff --git a/target/executable/lofreq/lofreq_indelqual/.config.vsh.yaml b/target/executable/lofreq/lofreq_indelqual/.config.vsh.yaml index 495034a7..f14efeb3 100644 --- a/target/executable/lofreq/lofreq_indelqual/.config.vsh.yaml +++ b/target/executable/lofreq/lofreq_indelqual/.config.vsh.yaml @@ -215,7 +215,7 @@ build_info: output: "target/executable/lofreq/lofreq_indelqual" executable: "target/executable/lofreq/lofreq_indelqual/lofreq_indelqual" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/lofreq/lofreq_indelqual/lofreq_indelqual b/target/executable/lofreq/lofreq_indelqual/lofreq_indelqual index 67ee28ff..072ababe 100755 --- a/target/executable/lofreq/lofreq_indelqual/lofreq_indelqual +++ b/target/executable/lofreq/lofreq_indelqual/lofreq_indelqual @@ -500,9 +500,9 @@ echo "lofreq: $version" > /var/software_versions.txt LABEL org.opencontainers.image.authors="Kai Waldrant" LABEL org.opencontainers.image.description="Companion container for running component lofreq lofreq_indelqual" -LABEL org.opencontainers.image.created="2024-07-31T19:27:40Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:51Z" LABEL org.opencontainers.image.source="https://github.com/viash-hub/biobox" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER diff --git a/target/executable/multiqc/.config.vsh.yaml b/target/executable/multiqc/.config.vsh.yaml index 627260dc..f360b783 100644 --- a/target/executable/multiqc/.config.vsh.yaml +++ b/target/executable/multiqc/.config.vsh.yaml @@ -456,7 +456,7 @@ build_info: output: "target/executable/multiqc" executable: "target/executable/multiqc/multiqc" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/multiqc/multiqc b/target/executable/multiqc/multiqc index 899e6726..aa9a74ea 100755 --- a/target/executable/multiqc/multiqc +++ b/target/executable/multiqc/multiqc @@ -636,9 +636,9 @@ RUN multiqc --version | sed 's/multiqc, version\s\(.*\)/multiqc: "\1"/' > /var/s LABEL org.opencontainers.image.authors="Dorien Roosen" LABEL org.opencontainers.image.description="Companion container for running component multiqc" -LABEL org.opencontainers.image.created="2024-07-31T19:27:33Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:45Z" LABEL org.opencontainers.image.source="https://github.com/viash-hub/biobox" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER @@ -1760,26 +1760,32 @@ $( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" #!/bin/bash # disable flags -[[ "\$par_ignore_symlinks" == "false" ]] && unset par_ignore_symlinks -[[ "\$par_dirs" == "false" ]] && unset par_dirs -[[ "\$par_full_names" == "false" ]] && unset par_full_names -[[ "\$par_fn_as_s_name" == "false" ]] && unset par_fn_as_s_name -[[ "\$par_profile_runtime" == "false" ]] && unset par_profile_runtime -[[ "\$par_verbose" == "false" ]] && unset par_verbose -[[ "\$par_quiet" == "false" ]] && unset par_quiet -[[ "\$par_strict" == "false" ]] && unset par_strict -[[ "\$par_development" == "false" ]] && unset par_development -[[ "\$par_require_logs" == "false" ]] && unset par_require_logs -[[ "\$par_no_megaqc_upload" == "false" ]] && unset par_no_megaqc_upload -[[ "\$par_no_ansi" == "false" ]] && unset par_no_ansi -[[ "\$par_flat" == "false" ]] && unset par_flat -[[ "\$par_interactive" == "false" ]] && unset par_interactive -[[ "\$par_static_plot_export" == "false" ]] && unset par_static_plot_export -[[ "\$par_data_dir" == "false" ]] && unset par_data_dir -[[ "\$par_no_data_dir" == "false" ]] && unset par_no_data_dir -[[ "\$par_zip_data_dir" == "false" ]] && unset par_zip_data_dir -[[ "\$par_pdf" == "false" ]] && unset par_pdf +unset_if_false=( + par_ignore_symlinks + par_dirs + par_full_names + par_fn_as_s_name + par_profile_runtime + par_verbose + par_quiet + par_strict + par_development + par_require_logs + par_no_megaqc_upload + par_no_ansi + par_flat + par_interactive + par_static_plot_export + par_data_dir + par_no_data_dir + par_zip_data_dir + par_pdf +) +for par in \${unset_if_false[@]}; do + test_val="\${!par}" + [[ "\$test_val" == "false" ]] && unset \$par +done # handle inputs out_dir=\$(dirname "\$par_output_report") diff --git a/target/executable/pear/.config.vsh.yaml b/target/executable/pear/.config.vsh.yaml index 5db85874..f4c00642 100644 --- a/target/executable/pear/.config.vsh.yaml +++ b/target/executable/pear/.config.vsh.yaml @@ -398,7 +398,7 @@ build_info: output: "target/executable/pear" executable: "target/executable/pear/pear" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/pear/pear b/target/executable/pear/pear index cf70db41..1a8e527a 100755 --- a/target/executable/pear/pear +++ b/target/executable/pear/pear @@ -596,9 +596,9 @@ echo "pear: $version" > /var/software_versions.txt LABEL org.opencontainers.image.authors="Kai Waldrant" LABEL org.opencontainers.image.description="Companion container for running component pear" -LABEL org.opencontainers.image.created="2024-07-31T19:27:39Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:50Z" LABEL org.opencontainers.image.source="https://github.com/tseemann/PEAR" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER diff --git a/target/executable/salmon/salmon_index/.config.vsh.yaml b/target/executable/salmon/salmon_index/.config.vsh.yaml index bac69402..eef91767 100644 --- a/target/executable/salmon/salmon_index/.config.vsh.yaml +++ b/target/executable/salmon/salmon_index/.config.vsh.yaml @@ -277,7 +277,7 @@ build_info: output: "target/executable/salmon/salmon_index" executable: "target/executable/salmon/salmon_index/salmon_index" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/salmon/salmon_index/salmon_index b/target/executable/salmon/salmon_index/salmon_index index f73cdd90..63d92e6a 100755 --- a/target/executable/salmon/salmon_index/salmon_index +++ b/target/executable/salmon/salmon_index/salmon_index @@ -545,9 +545,9 @@ RUN salmon index -v 2>&1 | sed 's/salmon \([0-9.]*\)/salmon: \1/' > /var/softwar LABEL org.opencontainers.image.authors="Sai Nirmayi Yasa" LABEL org.opencontainers.image.description="Companion container for running component salmon salmon_index" -LABEL org.opencontainers.image.created="2024-07-31T19:27:34Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:46Z" LABEL org.opencontainers.image.source="https://github.com/COMBINE-lab/salmon" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER @@ -1303,12 +1303,19 @@ $( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" ## VIASH END -[[ "\$par_gencode" == "false" ]] && unset par_gencode -[[ "\$par_features" == "false" ]] && unset par_features -[[ "\$par_keep_duplicates" == "false" ]] && unset par_keep_duplicates -[[ "\$par_keep_fixed_fasta" == "false" ]] && unset par_keep_fixed_fasta -[[ "\$par_sparse" == "false" ]] && unset par_sparse -[[ "\$par_no_clip" == "false" ]] && unset par_no_clip +unset_if_false=( + par_gencode + par_features + par_keep_duplicates + par_keep_fixed_fasta + par_sparse + par_no_clip +) + +for par in \${unset_if_false[@]}; do + test_val="\${!par}" + [[ "\$test_val" == "false" ]] && unset \$par +done tmp_dir=\$(mktemp -d -p "\$meta_temp_dir" "\${meta_functionality_name}_XXXXXX") mkdir -p "\$tmp_dir/temp" diff --git a/target/executable/salmon/salmon_quant/.config.vsh.yaml b/target/executable/salmon/salmon_quant/.config.vsh.yaml index cd573bab..eb00cb58 100644 --- a/target/executable/salmon/salmon_quant/.config.vsh.yaml +++ b/target/executable/salmon/salmon_quant/.config.vsh.yaml @@ -1173,7 +1173,7 @@ build_info: output: "target/executable/salmon/salmon_quant" executable: "target/executable/salmon/salmon_quant/salmon_quant" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/salmon/salmon_quant/salmon_quant b/target/executable/salmon/salmon_quant/salmon_quant index ee23b11c..50c365e2 100755 --- a/target/executable/salmon/salmon_quant/salmon_quant +++ b/target/executable/salmon/salmon_quant/salmon_quant @@ -1167,9 +1167,9 @@ RUN salmon index -v 2>&1 | sed 's/salmon \([0-9.]*\)/salmon: \1/' > /var/softwar LABEL org.opencontainers.image.authors="Sai Nirmayi Yasa" LABEL org.opencontainers.image.description="Companion container for running component salmon salmon_quant" -LABEL org.opencontainers.image.created="2024-07-31T19:27:34Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:46Z" LABEL org.opencontainers.image.source="https://github.com/COMBINE-lab/salmon" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER @@ -3619,49 +3619,55 @@ $( if [ ! -z ${VIASH_META_MEMORY_TIB+x} ]; then echo "${VIASH_META_MEMORY_TIB}" $( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" | sed "s#'#'\"'\"'#g;s#.*#meta_memory_pib='&'#" ; else echo "# meta_memory_pib="; fi ) ## VIASH END +unset_if_false=( + par_discard_orphans + par_ont + par_seq_bias + par_gc_bias + par_pos_bias + par_meta + par_discard_orphans_quasi + par_disable_chaining_heuristic + par_allow_dovetail + par_recover_orphans + par_mimicBT2 + par_mimic_strictBT2 + par_softclip + par_softclip_overhangs + par_full_length_alignment + par_hard_filter + par_write_mappings + par_write_qualities + par_alternative_init_mode + par_skip_quant + par_dump_eq + par_dump_eq_weights + par_reduce_GC_memory + par_init_uniform + par_no_length_correction + par_no_effective_length_correction + par_no_single_frag_prob + par_no_frag_length_dist + par_no_bias_length_threshold + par_useEM + par_useVBOpt + par_no_Gamma_draw + par_bootstrap_reproject + par_quiet + par_per_transcript_prior + par_per_nucleotide_prior + par_write_orphan_links + par_write_unmapped_names + par_no_error_model + par_sample_out + par_sample_unaligned + par_gencode +) -[[ "\$par_discard_orphans" == "false" ]] && unset par_discard_orphans -[[ "\$par_ont" == "false" ]] && unset par_ont -[[ "\$par_seq_bias" == "false" ]] && unset par_seq_bias -[[ "\$par_gc_bias" == "false" ]] && unset par_gc_bias -[[ "\$par_pos_bias" == "false" ]] && unset par_pos_bias -[[ "\$par_meta" == "false" ]] && unset par_meta -[[ "\$par_discard_orphans_quasi" == "false" ]] && unset par_discard_orphans_quasi -[[ "\$par_disable_chaining_heuristic" == "false" ]] && unset par_disable_chaining_heuristic -[[ "\$par_allow_dovetail" == "false" ]] && unset par_allow_dovetail -[[ "\$par_recover_orphans" == "false" ]] && unset par_recover_orphans -[[ "\$par_mimicBT2" == "false" ]] && unset par_mimicBT2 -[[ "\$par_mimic_strictBT2" == "false" ]] && unset par_mimic_strictBT2 -[[ "\$par_softclip" == "false" ]] && unset par_softclip -[[ "\$par_softclip_overhangs" == "false" ]] && unset par_softclip_overhangs -[[ "\$par_full_length_alignment" == "false" ]] && unset par_full_length_alignment -[[ "\$par_hard_filter" == "false" ]] && unset par_hard_filter -[[ "\$par_write_mappings" == "false" ]] && unset par_write_mappings -[[ "\$par_write_qualities" == "false" ]] && unset par_write_qualities -[[ "\$par_alternative_init_mode" == "false" ]] && unset par_alternative_init_mode -[[ "\$par_skip_quant" == "false" ]] && unset par_skip_quant -[[ "\$par_dump_eq" == "false" ]] && unset par_dump_eq -[[ "\$par_dump_eq_weights" == "false" ]] && unset par_dump_eq_weights -[[ "\$par_reduce_GC_memory" == "false" ]] && unset par_reduce_GC_memory -[[ "\$par_init_uniform" == "false" ]] && unset par_init_uniform -[[ "\$par_no_length_correction" == "false" ]] && unset par_no_length_correction -[[ "\$par_no_effective_length_correction" == "false" ]] && unset par_no_effective_length_correction -[[ "\$par_no_single_frag_prob" == "false" ]] && unset par_no_single_frag_prob -[[ "\$par_no_frag_length_dist" == "false" ]] && unset par_no_frag_length_dist -[[ "\$par_no_bias_length_threshold" == "false" ]] && unset par_no_bias_length_threshold -[[ "\$par_useEM" == "false" ]] && unset par_useEM -[[ "\$par_useVBOpt" == "false" ]] && unset par_useVBOpt -[[ "\$par_no_Gamma_draw" == "false" ]] && unset par_no_Gamma_draw -[[ "\$par_bootstrap_reproject" == "false" ]] && unset par_bootstrap_reproject -[[ "\$par_quiet" == "false" ]] && unset par_quiet -[[ "\$par_per_transcript_prior" == "false" ]] && unset par_per_transcript_prior -[[ "\$par_per_nucleotide_prior" == "false" ]] && unset par_per_nucleotide_prior -[[ "\$par_write_orphan_links" == "false" ]] && unset par_write_orphan_links -[[ "\$par_write_unmapped_names" == "false" ]] && unset par_write_unmapped_names -[[ "\$par_no_error_model" == "false" ]] && unset par_no_error_model -[[ "\$par_sample_out" == "false" ]] && unset par_sample_out -[[ "\$par_sample_unaligned" == "false" ]] && unset par_sample_unaligned -[[ "\$par_gencode" == "false" ]] && unset par_gencode +for par in \${unset_if_false[@]}; do + test_val="\${!par}" + [[ "\$test_val" == "false" ]] && unset \$par +done IFS=";" read -ra unmated_reads <<< \$par_unmated_reads IFS=";" read -ra mates1 <<< \$par_mates1 diff --git a/target/executable/samtools/samtools_collate/.config.vsh.yaml b/target/executable/samtools/samtools_collate/.config.vsh.yaml index d0e772de..84e2e7b1 100644 --- a/target/executable/samtools/samtools_collate/.config.vsh.yaml +++ b/target/executable/samtools/samtools_collate/.config.vsh.yaml @@ -264,7 +264,7 @@ build_info: output: "target/executable/samtools/samtools_collate" executable: "target/executable/samtools/samtools_collate/samtools_collate" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/samtools/samtools_collate/samtools_collate b/target/executable/samtools/samtools_collate/samtools_collate index f7538890..16e351bc 100755 --- a/target/executable/samtools/samtools_collate/samtools_collate +++ b/target/executable/samtools/samtools_collate/samtools_collate @@ -518,9 +518,9 @@ sed 's#Using ##;s# \([0-9\.]*\)$#: \1#' > /var/software_versions.txt LABEL org.opencontainers.image.authors="Emma Rousseau" LABEL org.opencontainers.image.description="Companion container for running component samtools samtools_collate" -LABEL org.opencontainers.image.created="2024-07-31T19:27:43Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:55Z" LABEL org.opencontainers.image.source="https://github.com/samtools/samtools" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER diff --git a/target/executable/samtools/samtools_faidx/.config.vsh.yaml b/target/executable/samtools/samtools_faidx/.config.vsh.yaml index 513999f8..afe0ed61 100644 --- a/target/executable/samtools/samtools_faidx/.config.vsh.yaml +++ b/target/executable/samtools/samtools_faidx/.config.vsh.yaml @@ -243,7 +243,7 @@ build_info: output: "target/executable/samtools/samtools_faidx" executable: "target/executable/samtools/samtools_faidx/samtools_faidx" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/samtools/samtools_faidx/samtools_faidx b/target/executable/samtools/samtools_faidx/samtools_faidx index aee3ba29..ed4ec7c0 100755 --- a/target/executable/samtools/samtools_faidx/samtools_faidx +++ b/target/executable/samtools/samtools_faidx/samtools_faidx @@ -511,9 +511,9 @@ sed 's#Using ##;s# \([0-9\.]*\)$#: \1#' > /var/software_versions.txt LABEL org.opencontainers.image.authors="Emma Rousseau" LABEL org.opencontainers.image.description="Companion container for running component samtools samtools_faidx" -LABEL org.opencontainers.image.created="2024-07-31T19:27:44Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:56Z" LABEL org.opencontainers.image.source="https://github.com/samtools/samtools" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER diff --git a/target/executable/samtools/samtools_fasta/.config.vsh.yaml b/target/executable/samtools/samtools_fasta/.config.vsh.yaml index 8079a750..3d1a5e0b 100644 --- a/target/executable/samtools/samtools_fasta/.config.vsh.yaml +++ b/target/executable/samtools/samtools_fasta/.config.vsh.yaml @@ -433,7 +433,7 @@ build_info: output: "target/executable/samtools/samtools_fasta" executable: "target/executable/samtools/samtools_fasta/samtools_fasta" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/samtools/samtools_fasta/samtools_fasta b/target/executable/samtools/samtools_fasta/samtools_fasta index 7570367f..1aa23b32 100755 --- a/target/executable/samtools/samtools_fasta/samtools_fasta +++ b/target/executable/samtools/samtools_fasta/samtools_fasta @@ -624,9 +624,9 @@ sed 's#Using ##;s# \([0-9\.]*\)$#: \1#' > /var/software_versions.txt LABEL org.opencontainers.image.authors="Emma Rousseau" LABEL org.opencontainers.image.description="Companion container for running component samtools samtools_fasta" -LABEL org.opencontainers.image.created="2024-07-31T19:27:41Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:54Z" LABEL org.opencontainers.image.source="https://github.com/samtools/samtools" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER @@ -1648,11 +1648,18 @@ $( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" set -e -[[ "\$par_no_suffix" == "false" ]] && unset par_no_suffix -[[ "\$par_suffix" == "false" ]] && unset par_suffix -[[ "\$par_use_oq" == "false" ]] && unset par_use_oq -[[ "\$par_copy_tags" == "false" ]] && unset par_copy_tags -[[ "\$par_casava" == "false" ]] && unset par_casava +unset_if_false=( + par_no_suffix + par_suffix + par_use_oq + par_copy_tags + par_casava +) + +for par in \${unset_if_false[@]}; do + test_val="\${!par}" + [[ "\$test_val" == "false" ]] && unset \$par +done if [[ "\$meta_name" == "samtools_fasta" ]]; then subcommand=fasta diff --git a/target/executable/samtools/samtools_fastq/.config.vsh.yaml b/target/executable/samtools/samtools_fastq/.config.vsh.yaml index b5c5a714..e61730de 100644 --- a/target/executable/samtools/samtools_fastq/.config.vsh.yaml +++ b/target/executable/samtools/samtools_fastq/.config.vsh.yaml @@ -433,7 +433,7 @@ build_info: output: "target/executable/samtools/samtools_fastq" executable: "target/executable/samtools/samtools_fastq/samtools_fastq" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/samtools/samtools_fastq/samtools_fastq b/target/executable/samtools/samtools_fastq/samtools_fastq index 56183914..58948be0 100755 --- a/target/executable/samtools/samtools_fastq/samtools_fastq +++ b/target/executable/samtools/samtools_fastq/samtools_fastq @@ -625,9 +625,9 @@ sed 's#Using ##;s# \([0-9\.]*\)$#: \1#' > /var/software_versions.txt LABEL org.opencontainers.image.authors="Emma Rousseau" LABEL org.opencontainers.image.description="Companion container for running component samtools samtools_fastq" -LABEL org.opencontainers.image.created="2024-07-31T19:27:44Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:56Z" LABEL org.opencontainers.image.source="https://github.com/samtools/samtools" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER @@ -1649,11 +1649,18 @@ $( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" set -e -[[ "\$par_no_suffix" == "false" ]] && unset par_no_suffix -[[ "\$par_suffix" == "false" ]] && unset par_suffix -[[ "\$par_use_oq" == "false" ]] && unset par_use_oq -[[ "\$par_copy_tags" == "false" ]] && unset par_copy_tags -[[ "\$par_casava" == "false" ]] && unset par_casava +unset_if_false=( + par_no_suffix + par_suffix + par_use_oq + par_copy_tags + par_casava +) + +for par in \${unset_if_false[@]}; do + test_val="\${!par}" + [[ "\$test_val" == "false" ]] && unset \$par +done if [[ "\$meta_name" == "samtools_fasta" ]]; then subcommand=fasta diff --git a/target/executable/samtools/samtools_flagstat/.config.vsh.yaml b/target/executable/samtools/samtools_flagstat/.config.vsh.yaml index a029aa4e..3e65a348 100644 --- a/target/executable/samtools/samtools_flagstat/.config.vsh.yaml +++ b/target/executable/samtools/samtools_flagstat/.config.vsh.yaml @@ -173,7 +173,7 @@ build_info: output: "target/executable/samtools/samtools_flagstat" executable: "target/executable/samtools/samtools_flagstat/samtools_flagstat" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/samtools/samtools_flagstat/samtools_flagstat b/target/executable/samtools/samtools_flagstat/samtools_flagstat index ec1a658e..0485b374 100755 --- a/target/executable/samtools/samtools_flagstat/samtools_flagstat +++ b/target/executable/samtools/samtools_flagstat/samtools_flagstat @@ -473,9 +473,9 @@ sed 's#Using ##;s# \([0-9\.]*\)$#: \1#' > /var/software_versions.txt LABEL org.opencontainers.image.authors="Emma Rousseau" LABEL org.opencontainers.image.description="Companion container for running component samtools samtools_flagstat" -LABEL org.opencontainers.image.created="2024-07-31T19:27:42Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:54Z" LABEL org.opencontainers.image.source="https://github.com/samtools/samtools" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER diff --git a/target/executable/samtools/samtools_idxstats/.config.vsh.yaml b/target/executable/samtools/samtools_idxstats/.config.vsh.yaml index 4a1733b2..2085d11f 100644 --- a/target/executable/samtools/samtools_idxstats/.config.vsh.yaml +++ b/target/executable/samtools/samtools_idxstats/.config.vsh.yaml @@ -183,7 +183,7 @@ build_info: output: "target/executable/samtools/samtools_idxstats" executable: "target/executable/samtools/samtools_idxstats/samtools_idxstats" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/samtools/samtools_idxstats/samtools_idxstats b/target/executable/samtools/samtools_idxstats/samtools_idxstats index 334d1b92..3391b324 100755 --- a/target/executable/samtools/samtools_idxstats/samtools_idxstats +++ b/target/executable/samtools/samtools_idxstats/samtools_idxstats @@ -477,9 +477,9 @@ sed 's#Using ##;s# \([0-9\.]*\)$#: \1#' > /var/software_versions.txt LABEL org.opencontainers.image.authors="Emma Rousseau" LABEL org.opencontainers.image.description="Companion container for running component samtools samtools_idxstats" -LABEL org.opencontainers.image.created="2024-07-31T19:27:42Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:55Z" LABEL org.opencontainers.image.source="https://github.com/samtools/samtools" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER diff --git a/target/executable/samtools/samtools_index/.config.vsh.yaml b/target/executable/samtools/samtools_index/.config.vsh.yaml index 7e2d2e3c..afc62cf3 100644 --- a/target/executable/samtools/samtools_index/.config.vsh.yaml +++ b/target/executable/samtools/samtools_index/.config.vsh.yaml @@ -189,7 +189,7 @@ build_info: output: "target/executable/samtools/samtools_index" executable: "target/executable/samtools/samtools_index/samtools_index" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/samtools/samtools_index/samtools_index b/target/executable/samtools/samtools_index/samtools_index index 025a9a90..de2505f9 100755 --- a/target/executable/samtools/samtools_index/samtools_index +++ b/target/executable/samtools/samtools_index/samtools_index @@ -484,9 +484,9 @@ sed 's#Using ##;s# \([0-9\.]*\)$#: \1#' > /var/software_versions.txt LABEL org.opencontainers.image.authors="Emma Rousseau" LABEL org.opencontainers.image.description="Companion container for running component samtools samtools_index" -LABEL org.opencontainers.image.created="2024-07-31T19:27:43Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:55Z" LABEL org.opencontainers.image.source="https://github.com/samtools/samtools" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER diff --git a/target/executable/samtools/samtools_sort/.config.vsh.yaml b/target/executable/samtools/samtools_sort/.config.vsh.yaml index 3e356582..7db09619 100644 --- a/target/executable/samtools/samtools_sort/.config.vsh.yaml +++ b/target/executable/samtools/samtools_sort/.config.vsh.yaml @@ -332,7 +332,7 @@ build_info: output: "target/executable/samtools/samtools_sort" executable: "target/executable/samtools/samtools_sort/samtools_sort" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/samtools/samtools_sort/samtools_sort b/target/executable/samtools/samtools_sort/samtools_sort index 28188a19..d9a4e0c9 100755 --- a/target/executable/samtools/samtools_sort/samtools_sort +++ b/target/executable/samtools/samtools_sort/samtools_sort @@ -555,9 +555,9 @@ sed 's#Using ##;s# \([0-9\.]*\)$#: \1#' > /var/software_versions.txt LABEL org.opencontainers.image.authors="Emma Rousseau" LABEL org.opencontainers.image.description="Companion container for running component samtools samtools_sort" -LABEL org.opencontainers.image.created="2024-07-31T19:27:43Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:56Z" LABEL org.opencontainers.image.source="https://github.com/samtools/samtools" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER @@ -1463,15 +1463,22 @@ $( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" set -e -[[ "\$par_uncompressed" == "false" ]] && unset par_uncompressed -[[ "\$par_minimiser" == "false" ]] && unset par_minimiser -[[ "\$par_not_reverse" == "false" ]] && unset par_not_reverse -[[ "\$par_homopolymers" == "false" ]] && unset par_homopolymers -[[ "\$par_natural_sort" == "false" ]] && unset par_natural_sort -[[ "\$par_ascii_sort" == "false" ]] && unset par_ascii_sort -[[ "\$par_template_coordinate" == "false" ]] && unset par_template_coordinate -[[ "\$par_write_index" == "false" ]] && unset par_write_index -[[ "\$par_no_PG" == "false" ]] && unset par_no_PG +unset_if_false=( + par_uncompressed + par_minimiser + par_not_reverse + par_homopolymers + par_natural_sort + par_ascii_sort + par_template_coordinate + par_write_index + par_no_PG +) + +for par in \${unset_if_false[@]}; do + test_val="\${!par}" + [[ "\$test_val" == "false" ]] && unset \$par +done samtools sort \\ diff --git a/target/executable/samtools/samtools_stats/.config.vsh.yaml b/target/executable/samtools/samtools_stats/.config.vsh.yaml index 5b3cb389..8acf3b43 100644 --- a/target/executable/samtools/samtools_stats/.config.vsh.yaml +++ b/target/executable/samtools/samtools_stats/.config.vsh.yaml @@ -401,7 +401,7 @@ build_info: output: "target/executable/samtools/samtools_stats" executable: "target/executable/samtools/samtools_stats/samtools_stats" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/samtools/samtools_stats/samtools_stats b/target/executable/samtools/samtools_stats/samtools_stats index 5133e9f4..b81a8be2 100755 --- a/target/executable/samtools/samtools_stats/samtools_stats +++ b/target/executable/samtools/samtools_stats/samtools_stats @@ -574,9 +574,9 @@ sed 's#Using ##;s# \([0-9\.]*\)$#: \1#' > /var/software_versions.txt LABEL org.opencontainers.image.authors="Emma Rousseau" LABEL org.opencontainers.image.description="Companion container for running component samtools samtools_stats" -LABEL org.opencontainers.image.created="2024-07-31T19:27:42Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:54Z" LABEL org.opencontainers.image.source="https://github.com/samtools/samtools" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER diff --git a/target/executable/samtools/samtools_view/.config.vsh.yaml b/target/executable/samtools/samtools_view/.config.vsh.yaml index 123eeabb..ad58dd84 100644 --- a/target/executable/samtools/samtools_view/.config.vsh.yaml +++ b/target/executable/samtools/samtools_view/.config.vsh.yaml @@ -665,7 +665,7 @@ build_info: output: "target/executable/samtools/samtools_view" executable: "target/executable/samtools/samtools_view/samtools_view" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/samtools/samtools_view/samtools_view b/target/executable/samtools/samtools_view/samtools_view index d404e20f..b830edcf 100755 --- a/target/executable/samtools/samtools_view/samtools_view +++ b/target/executable/samtools/samtools_view/samtools_view @@ -824,9 +824,9 @@ sed 's#Using ##;s# \([0-9\.]*\)$#: \1#' > /var/software_versions.txt LABEL org.opencontainers.image.authors="Emma Rousseau" LABEL org.opencontainers.image.description="Companion container for running component samtools samtools_view" -LABEL org.opencontainers.image.created="2024-07-31T19:27:41Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:53Z" LABEL org.opencontainers.image.source="https://github.com/samtools/samtools" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER @@ -2208,21 +2208,29 @@ $( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" set -e -[[ "\$par_bam" == "false" ]] && unset par_bam -[[ "\$par_cram" == "false" ]] && unset par_cram -[[ "\$par_fast" == "false" ]] && unset par_fast -[[ "\$par_uncompressed" == "false" ]] && unset par_uncompressed -[[ "\$par_with_header" == "false" ]] && unset par_with_header -[[ "\$par_header_only" == "false" ]] && unset par_header_only -[[ "\$par_no_header" == "false" ]] && unset par_no_header -[[ "\$par_count" == "false" ]] && unset par_count -[[ "\$par_unmap" == "false" ]] && unset par_unmap -[[ "\$par_use_index" == "false" ]] && unset par_use_index -[[ "\$par_fetch_pairs" == "false" ]] && unset par_fetch_pairs -[[ "\$par_customized_index" == "false" ]] && unset par_customized_index -[[ "\$par_no_PG" == "false" ]] && unset par_no_PG -[[ "\$par_write_index" == "false" ]] && unset par_write_index -[[ "\$par_remove_B" == "false" ]] && unset par_remove_B +unset_if_false=( + par_bam + par_cram + par_fast + par_uncompressed + par_with_header + par_header_only + par_no_header + par_count + par_unmap + par_use_index + par_fetch_pairs + par_customized_index + par_no_PG + par_write_index + par_remove_B +) + +for par in \${unset_if_false[@]}; do + test_val="\${!par}" + [[ "\$test_val" == "false" ]] && unset \$par +done + samtools view \\ \${par_bam:+-b} \\ diff --git a/target/executable/seqtk/seqtk_sample/.config.vsh.yaml b/target/executable/seqtk/seqtk_sample/.config.vsh.yaml index a133c75e..dc60b87f 100644 --- a/target/executable/seqtk/seqtk_sample/.config.vsh.yaml +++ b/target/executable/seqtk/seqtk_sample/.config.vsh.yaml @@ -173,7 +173,7 @@ build_info: output: "target/executable/seqtk/seqtk_sample" executable: "target/executable/seqtk/seqtk_sample/seqtk_sample" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/seqtk/seqtk_sample/seqtk_sample b/target/executable/seqtk/seqtk_sample/seqtk_sample index f9b0bc60..a6529881 100755 --- a/target/executable/seqtk/seqtk_sample/seqtk_sample +++ b/target/executable/seqtk/seqtk_sample/seqtk_sample @@ -480,9 +480,9 @@ FROM quay.io/biocontainers/seqtk:1.4--he4a0461_2 ENTRYPOINT [] LABEL org.opencontainers.image.authors="Jakub Majercik" LABEL org.opencontainers.image.description="Companion container for running component seqtk seqtk_sample" -LABEL org.opencontainers.image.created="2024-07-31T19:27:37Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:49Z" LABEL org.opencontainers.image.source="https://github.com/lh3/seqtk/tree/v1.4" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER diff --git a/target/executable/seqtk/seqtk_subseq/.config.vsh.yaml b/target/executable/seqtk/seqtk_subseq/.config.vsh.yaml index 59a43f16..bc14a41a 100644 --- a/target/executable/seqtk/seqtk_subseq/.config.vsh.yaml +++ b/target/executable/seqtk/seqtk_subseq/.config.vsh.yaml @@ -196,7 +196,7 @@ build_info: output: "target/executable/seqtk/seqtk_subseq" executable: "target/executable/seqtk/seqtk_subseq/seqtk_subseq" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/seqtk/seqtk_subseq/seqtk_subseq b/target/executable/seqtk/seqtk_subseq/seqtk_subseq index 7eb4c0a7..6e79c144 100755 --- a/target/executable/seqtk/seqtk_subseq/seqtk_subseq +++ b/target/executable/seqtk/seqtk_subseq/seqtk_subseq @@ -490,9 +490,9 @@ RUN echo $(echo $(seqtk 2>&1) | sed -n 's/.*\(Version: [^ ]*\).*/\1/p') > /var/s LABEL org.opencontainers.image.authors="Theodoro Gasperin Terra Camargo" LABEL org.opencontainers.image.description="Companion container for running component seqtk seqtk_subseq" -LABEL org.opencontainers.image.created="2024-07-31T19:27:36Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:49Z" LABEL org.opencontainers.image.source="https://github.com/lh3/seqtk/tree/v1.4" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER diff --git a/target/executable/star/star_align_reads/.config.vsh.yaml b/target/executable/star/star_align_reads/.config.vsh.yaml index f09a5a82..85958512 100644 --- a/target/executable/star/star_align_reads/.config.vsh.yaml +++ b/target/executable/star/star_align_reads/.config.vsh.yaml @@ -2663,7 +2663,7 @@ build_info: output: "target/executable/star/star_align_reads" executable: "target/executable/star/star_align_reads/star_align_reads" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/star/star_align_reads/star_align_reads b/target/executable/star/star_align_reads/star_align_reads index 6e4393bf..6c8ab379 100755 --- a/target/executable/star/star_align_reads/star_align_reads +++ b/target/executable/star/star_align_reads/star_align_reads @@ -1919,9 +1919,9 @@ RUN STAR --version | sed 's#\(.*\)#star: "\1"#' > /var/software_versions.txt LABEL org.opencontainers.image.authors="Angela Oliveira Pisco, Robrecht Cannoodt" LABEL org.opencontainers.image.description="Companion container for running component star star_align_reads" -LABEL org.opencontainers.image.created="2024-07-31T19:27:38Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:50Z" LABEL org.opencontainers.image.source="https://github.com/alexdobin/STAR" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER diff --git a/target/executable/star/star_genome_generate/.config.vsh.yaml b/target/executable/star/star_genome_generate/.config.vsh.yaml index 5cd61329..75d57b52 100644 --- a/target/executable/star/star_genome_generate/.config.vsh.yaml +++ b/target/executable/star/star_genome_generate/.config.vsh.yaml @@ -333,7 +333,7 @@ build_info: output: "target/executable/star/star_genome_generate" executable: "target/executable/star/star_genome_generate/star_genome_generate" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/star/star_genome_generate/star_genome_generate b/target/executable/star/star_genome_generate/star_genome_generate index 11cec698..a731ee64 100755 --- a/target/executable/star/star_genome_generate/star_genome_generate +++ b/target/executable/star/star_genome_generate/star_genome_generate @@ -576,9 +576,9 @@ RUN STAR --version | sed 's#\(.*\)#star: "\1"#' > /var/software_versions.txt LABEL org.opencontainers.image.authors="Sai Nirmayi Yasa" LABEL org.opencontainers.image.description="Companion container for running component star star_genome_generate" -LABEL org.opencontainers.image.created="2024-07-31T19:27:37Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:49Z" LABEL org.opencontainers.image.source="https://github.com/alexdobin/STAR" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER diff --git a/target/executable/umi_tools/umi_tools_dedup/.config.vsh.yaml b/target/executable/umi_tools/umi_tools_dedup/.config.vsh.yaml index f073ded3..86088dae 100644 --- a/target/executable/umi_tools/umi_tools_dedup/.config.vsh.yaml +++ b/target/executable/umi_tools/umi_tools_dedup/.config.vsh.yaml @@ -611,7 +611,7 @@ build_info: output: "target/executable/umi_tools/umi_tools_dedup" executable: "target/executable/umi_tools/umi_tools_dedup/umi_tools_dedup" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/umi_tools/umi_tools_dedup/umi_tools_dedup b/target/executable/umi_tools/umi_tools_dedup/umi_tools_dedup index 58694739..397a78e7 100755 --- a/target/executable/umi_tools/umi_tools_dedup/umi_tools_dedup +++ b/target/executable/umi_tools/umi_tools_dedup/umi_tools_dedup @@ -769,9 +769,9 @@ RUN umi_tools -v | sed 's/ version//g' > /var/software_versions.txt LABEL org.opencontainers.image.authors="Emma Rousseau" LABEL org.opencontainers.image.description="Companion container for running component umi_tools umi_tools_dedup" -LABEL org.opencontainers.image.created="2024-07-31T19:27:44Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:57Z" LABEL org.opencontainers.image.source="https://github.com/CGATOxford/UMI-tools" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER @@ -2052,19 +2052,26 @@ set -e test_dir="\${metal_executable}/test_data" -[[ "\$par_paired" == "false" ]] && unset par_paired -[[ "\$par_in_sam" == "false" ]] && unset par_in_sam -[[ "\$par_out_sam" == "false" ]] && unset par_out_sam -[[ "\$par_spliced_is_unique" == "false" ]] && unset par_spliced_is_unique -[[ "\$par_per_gene" == "false" ]] && unset par_per_gene -[[ "\$par_per_contig" == "false" ]] && unset par_per_contig -[[ "\$par_per_cell" == "false" ]] && unset par_per_cell -[[ "\$par_no_sort_output" == "false" ]] && unset par_no_sort_output -[[ "\$par_buffer_whole_contig" == "false" ]] && unset par_buffer_whole_contig -[[ "\$par_ignore_umi" == "false" ]] && unset par_ignore_umi -[[ "\$par_subset" == "false" ]] && unset par_subset -[[ "\$par_log2stderr" == "false" ]] && unset par_log2stderr -[[ "\$par_read_length" == "false" ]] && unset par_read_length +unset_if_false=( + par_paired + par_in_sam + par_out_sam + par_spliced_is_unique + par_per_gene + par_per_contig + par_per_cell + par_no_sort_output + par_buffer_whole_contig + par_ignore_umi + par_subset + par_log2stderr + par_read_length +) + +for par in \${unset_if_false[@]}; do + test_val="\${!par}" + [[ "\$test_val" == "false" ]] && unset \$par +done umi_tools dedup \\ --stdin "\$par_input" \\ diff --git a/target/executable/umi_tools/umi_tools_extract/.config.vsh.yaml b/target/executable/umi_tools/umi_tools_extract/.config.vsh.yaml index 69e8ba4d..f6e16c07 100644 --- a/target/executable/umi_tools/umi_tools_extract/.config.vsh.yaml +++ b/target/executable/umi_tools/umi_tools_extract/.config.vsh.yaml @@ -449,7 +449,7 @@ build_info: output: "target/executable/umi_tools/umi_tools_extract" executable: "target/executable/umi_tools/umi_tools_extract/umi_tools_extract" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/executable/umi_tools/umi_tools_extract/umi_tools_extract b/target/executable/umi_tools/umi_tools_extract/umi_tools_extract index ceee21df..edf03d9d 100755 --- a/target/executable/umi_tools/umi_tools_extract/umi_tools_extract +++ b/target/executable/umi_tools/umi_tools_extract/umi_tools_extract @@ -636,9 +636,9 @@ ENTRYPOINT [] RUN umi_tools -v | sed 's/ version//g' > /var/software_versions.txt LABEL org.opencontainers.image.description="Companion container for running component umi_tools umi_tools_extract" -LABEL org.opencontainers.image.created="2024-07-31T19:27:45Z" +LABEL org.opencontainers.image.created="2024-08-14T20:58:57Z" LABEL org.opencontainers.image.source="https://github.com/CGATOxford/UMI-tools" -LABEL org.opencontainers.image.revision="4aa0a893d2f8be5f0d03797afc15a04c53664367" +LABEL org.opencontainers.image.revision="923a6da3898a832df96a0e17c8a3b74c2806d939" LABEL org.opencontainers.image.version="main" VIASHDOCKER @@ -1714,14 +1714,19 @@ $( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" set -exo pipefail -test_dir="\${metal_executable}/test_data" +unset_if_false=( + par_error_correct_cell + par_reconcile_pairs + par_three_prime + par_ignore_read_pair_suffixes + par_timeit_header + par_log2stderr +) -[[ "\$par_error_correct_cell" == "false" ]] && unset par_error_correct_cell -[[ "\$par_reconcile_pairs" == "false" ]] && unset par_reconcile_pairs -[[ "\$par_three_prime" == "false" ]] && unset par_three_prime -[[ "\$par_ignore_read_pair_suffixes" == "false" ]] && unset par_ignore_read_pair_suffixes -[[ "\$par_timeit_header" == "false" ]] && unset par_timeit_header -[[ "\$par_log2stderr" == "false" ]] && unset par_log2stderr +for par in \${unset_if_false[@]}; do + test_val="\${!par}" + [[ "\$test_val" == "false" ]] && unset \$par +done # Check if we have the correct number of input files and patterns for paired-end or single-end reads diff --git a/target/nextflow/agat/agat_convert_bed2gff/.config.vsh.yaml b/target/nextflow/agat/agat_convert_bed2gff/.config.vsh.yaml index c4b049c2..35e7df8b 100644 --- a/target/nextflow/agat/agat_convert_bed2gff/.config.vsh.yaml +++ b/target/nextflow/agat/agat_convert_bed2gff/.config.vsh.yaml @@ -235,7 +235,7 @@ build_info: output: "target/nextflow/agat/agat_convert_bed2gff" executable: "target/nextflow/agat/agat_convert_bed2gff/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/agat/agat_convert_bed2gff/main.nf b/target/nextflow/agat/agat_convert_bed2gff/main.nf index fa8e92c1..18863948 100644 --- a/target/nextflow/agat/agat_convert_bed2gff/main.nf +++ b/target/nextflow/agat/agat_convert_bed2gff/main.nf @@ -3066,7 +3066,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/agat/agat_convert_bed2gff", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { diff --git a/target/nextflow/agat/agat_convert_embl2gff/.config.vsh.yaml b/target/nextflow/agat/agat_convert_embl2gff/.config.vsh.yaml new file mode 100644 index 00000000..d4019792 --- /dev/null +++ b/target/nextflow/agat/agat_convert_embl2gff/.config.vsh.yaml @@ -0,0 +1,251 @@ +name: "agat_convert_embl2gff" +namespace: "agat" +version: "main" +authors: +- name: "Leïla Paquay" + roles: + - "author" + - "maintainer" + info: + links: + email: "leila@data-intuitive.com" + github: "Leila011" + linkedin: "leilapaquay" + organizations: + - name: "Data Intuitive" + href: "https://www.data-intuitive.com" + role: "Software Developer" +argument_groups: +- name: "Inputs" + arguments: + - type: "file" + name: "--embl" + description: "Input EMBL file that will be read." + info: null + example: + - "input.embl" + must_exist: true + create_parent: true + required: true + direction: "input" + multiple: false + multiple_sep: ";" +- name: "Outputs" + arguments: + - type: "file" + name: "--output" + alternatives: + - "-o" + - "--out" + - "--outfile" + - "--gff" + description: "Output GFF file. If no output file is specified, the output will\ + \ be written to STDOUT." + info: null + example: + - "output.gff" + must_exist: true + create_parent: true + required: false + direction: "output" + multiple: false + multiple_sep: ";" +- name: "Arguments" + arguments: + - type: "boolean_true" + name: "--emblmygff3" + description: "Means that the EMBL flat file comes from the EMBLmyGFF3 software.\ + \ This is an EMBL format dedicated for submission and contains particularity\ + \ to deal with. This parameter is needed to get a proper sequence id in the\ + \ GFF3 from an embl made with EMBLmyGFF3.\n" + info: null + direction: "input" + - type: "string" + name: "--primary_tag" + alternatives: + - "--pt" + - "-t" + description: "List of \"primary tag\". Useful to discard or keep specific features.\ + \ Multiple tags must be comma-separated.\n" + info: null + example: + - "tag1" + - "tag2" + required: false + direction: "input" + multiple: true + multiple_sep: ";" + - type: "boolean_true" + name: "--discard" + alternatives: + - "-d" + description: "Means that primary tags provided by the option \"primary_tag\" will\ + \ be discarded.\n" + info: null + direction: "input" + - type: "boolean_true" + name: "--keep" + alternatives: + - "-k" + description: "Means that only primary tags provided by the option \"primary_tag\"\ + \ will be kept.\n" + info: null + direction: "input" + - type: "file" + name: "--config" + alternatives: + - "-c" + description: "Input agat config file. By default AGAT takes as input agat_config.yaml\ + \ file from the working directory if any, otherwise it takes the original agat_config.yaml\ + \ shipped with AGAT. To get the agat_config.yaml locally type: \"agat config\ + \ --expose\". The --config option gives you the possibility to use your own\ + \ AGAT config file (located elsewhere or named differently).\n" + info: null + example: + - "custom_agat_config.yaml" + must_exist: true + create_parent: true + required: false + direction: "input" + multiple: false + multiple_sep: ";" +resources: +- type: "bash_script" + path: "script.sh" + is_executable: true +description: "The script takes an EMBL file as input, and will translate it in gff\ + \ format.\n" +test_resources: +- type: "bash_script" + path: "test.sh" + is_executable: true +- type: "file" + path: "test_data" +info: null +status: "enabled" +requirements: + commands: + - "ps" +keywords: +- "gene annotations" +- "GFF conversion" +license: "GPL-3.0" +references: + doi: + - "10.5281/zenodo.3552717" +links: + repository: "https://github.com/NBISweden/AGAT" + homepage: "https://github.com/NBISweden/AGAT" + documentation: "https://agat.readthedocs.io/en/latest/tools/agat_convert_embl2gff.html" + issue_tracker: "https://github.com/NBISweden/AGAT/issues" +runners: +- type: "executable" + id: "executable" + docker_setup_strategy: "ifneedbepullelsecachedbuild" +- type: "nextflow" + id: "nextflow" + directives: + tag: "$id" + auto: + simplifyInput: true + simplifyOutput: false + transcript: false + publish: false + config: + labels: + mem1gb: "memory = 1000000000.B" + mem2gb: "memory = 2000000000.B" + mem5gb: "memory = 5000000000.B" + mem10gb: "memory = 10000000000.B" + mem20gb: "memory = 20000000000.B" + mem50gb: "memory = 50000000000.B" + mem100gb: "memory = 100000000000.B" + mem200gb: "memory = 200000000000.B" + mem500gb: "memory = 500000000000.B" + mem1tb: "memory = 1000000000000.B" + mem2tb: "memory = 2000000000000.B" + mem5tb: "memory = 5000000000000.B" + mem10tb: "memory = 10000000000000.B" + mem20tb: "memory = 20000000000000.B" + mem50tb: "memory = 50000000000000.B" + mem100tb: "memory = 100000000000000.B" + mem200tb: "memory = 200000000000000.B" + mem500tb: "memory = 500000000000000.B" + mem1gib: "memory = 1073741824.B" + mem2gib: "memory = 2147483648.B" + mem4gib: "memory = 4294967296.B" + mem8gib: "memory = 8589934592.B" + mem16gib: "memory = 17179869184.B" + mem32gib: "memory = 34359738368.B" + mem64gib: "memory = 68719476736.B" + mem128gib: "memory = 137438953472.B" + mem256gib: "memory = 274877906944.B" + mem512gib: "memory = 549755813888.B" + mem1tib: "memory = 1099511627776.B" + mem2tib: "memory = 2199023255552.B" + mem4tib: "memory = 4398046511104.B" + mem8tib: "memory = 8796093022208.B" + mem16tib: "memory = 17592186044416.B" + mem32tib: "memory = 35184372088832.B" + mem64tib: "memory = 70368744177664.B" + mem128tib: "memory = 140737488355328.B" + mem256tib: "memory = 281474976710656.B" + mem512tib: "memory = 562949953421312.B" + cpu1: "cpus = 1" + cpu2: "cpus = 2" + cpu5: "cpus = 5" + cpu10: "cpus = 10" + cpu20: "cpus = 20" + cpu50: "cpus = 50" + cpu100: "cpus = 100" + cpu200: "cpus = 200" + cpu500: "cpus = 500" + cpu1000: "cpus = 1000" + debug: false + container: "docker" +engines: +- type: "docker" + id: "docker" + image: "quay.io/biocontainers/agat:1.4.0--pl5321hdfd78af_0" + target_registry: "images.viash-hub.com" + target_tag: "main" + namespace_separator: "/" + setup: + - type: "docker" + run: + - "agat --version | sed 's/AGAT\\s\\(.*\\)/agat: \"\\1\"/' > /var/software_versions.txt\n" + entrypoint: [] + cmd: null +- type: "native" + id: "native" +build_info: + config: "src/agat/agat_convert_embl2gff/config.vsh.yaml" + runner: "nextflow" + engine: "docker|native" + output: "target/nextflow/agat/agat_convert_embl2gff" + executable: "target/nextflow/agat/agat_convert_embl2gff/main.nf" + viash_version: "0.9.0-RC6" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" + git_remote: "https://github.com/viash-hub/biobox" +package_config: + name: "biobox" + version: "main" + description: "A collection of bioinformatics tools for working with sequence data.\n" + info: null + viash_version: "0.9.0-RC6" + source: "src" + target: "target" + config_mods: + - ".requirements.commands := ['ps']\n" + - ".engines += { type: \"native\" }" + - ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'" + - ".engines[.type == 'docker'].target_tag := 'main'" + keywords: + - "bioinformatics" + - "modules" + - "sequencing" + license: "MIT" + organization: "vsh" + links: + repository: "https://github.com/viash-hub/biobox" + issue_tracker: "https://github.com/viash-hub/biobox/issues" diff --git a/target/nextflow/agat/agat_convert_embl2gff/main.nf b/target/nextflow/agat/agat_convert_embl2gff/main.nf new file mode 100644 index 00000000..7d7fb77f --- /dev/null +++ b/target/nextflow/agat/agat_convert_embl2gff/main.nf @@ -0,0 +1,3627 @@ +// agat_convert_embl2gff main +// +// This wrapper script is auto-generated by viash 0.9.0-RC6 and is thus a +// derivative work thereof. This software comes with ABSOLUTELY NO WARRANTY from +// Data Intuitive. +// +// The component may contain files which fall under a different license. The +// authors of this component should specify the license in the header of such +// files, or include a separate license file detailing the licenses of all included +// files. +// +// Component authors: +// * Leïla Paquay (author, maintainer) + +//////////////////////////// +// VDSL3 helper functions // +//////////////////////////// + +// helper file: 'src/main/resources/io/viash/runners/nextflow/arguments/_checkArgumentType.nf' +class UnexpectedArgumentTypeException extends Exception { + String errorIdentifier + String stage + String plainName + String expectedClass + String foundClass + + // ${key ? " in module '$key'" : ""}${id ? " id '$id'" : ""} + UnexpectedArgumentTypeException(String errorIdentifier, String stage, String plainName, String expectedClass, String foundClass) { + super("Error${errorIdentifier ? " $errorIdentifier" : ""}:${stage ? " $stage" : "" } argument '${plainName}' has the wrong type. " + + "Expected type: ${expectedClass}. Found type: ${foundClass}") + this.errorIdentifier = errorIdentifier + this.stage = stage + this.plainName = plainName + this.expectedClass = expectedClass + this.foundClass = foundClass + } +} + +/** + * Checks if the given value is of the expected type. If not, an exception is thrown. + * + * @param stage The stage of the argument (input or output) + * @param par The parameter definition + * @param value The value to check + * @param errorIdentifier The identifier to use in the error message + * @return The value, if it is of the expected type + * @throws UnexpectedArgumentTypeException If the value is not of the expected type +*/ +def _checkArgumentType(String stage, Map par, Object value, String errorIdentifier) { + // expectedClass will only be != null if value is not of the expected type + def expectedClass = null + def foundClass = null + + // todo: split if need be + + if (!par.required && value == null) { + expectedClass = null + } else if (par.multiple) { + if (value !instanceof Collection) { + value = [value] + } + + // split strings + value = value.collectMany{ val -> + if (val instanceof String) { + // collect() to ensure that the result is a List and not simply an array + val.split(par.multiple_sep).collect() + } else { + [val] + } + } + + // process globs + if (par.type == "file" && par.direction == "input") { + value = value.collect{ it instanceof String ? file(it, hidden: true) : it }.flatten() + } + + // check types of elements in list + try { + value = value.collect { listVal -> + _checkArgumentType(stage, par + [multiple: false], listVal, errorIdentifier) + } + } catch (UnexpectedArgumentTypeException e) { + expectedClass = "List[${e.expectedClass}]" + foundClass = "List[${e.foundClass}]" + } + } else if (par.type == "string") { + // cast to string if need be + if (value instanceof GString) { + value = value.toString() + } + expectedClass = value instanceof String ? null : "String" + } else if (par.type == "integer") { + // cast to integer if need be + if (value instanceof String) { + try { + value = value.toInteger() + } catch (NumberFormatException e) { + // do nothing + } + } + if (value instanceof java.math.BigInteger) { + value = value.intValue() + } + expectedClass = value instanceof Integer ? null : "Integer" + } else if (par.type == "long") { + // cast to long if need be + if (value instanceof String) { + try { + value = value.toLong() + } catch (NumberFormatException e) { + // do nothing + } + } + if (value instanceof Integer) { + value = value.toLong() + } + expectedClass = value instanceof Long ? null : "Long" + } else if (par.type == "double") { + // cast to double if need be + if (value instanceof String) { + try { + value = value.toDouble() + } catch (NumberFormatException e) { + // do nothing + } + } + if (value instanceof java.math.BigDecimal) { + value = value.doubleValue() + } + if (value instanceof Float) { + value = value.toDouble() + } + expectedClass = value instanceof Double ? null : "Double" + } else if (par.type == "boolean" | par.type == "boolean_true" | par.type == "boolean_false") { + // cast to boolean if need be + if (value instanceof String) { + def valueLower = value.toLowerCase() + if (valueLower == "true") { + value = true + } else if (valueLower == "false") { + value = false + } + } + expectedClass = value instanceof Boolean ? null : "Boolean" + } else if (par.type == "file" && (par.direction == "input" || stage == "output")) { + // cast to path if need be + if (value instanceof String) { + value = file(value, hidden: true) + } + if (value instanceof File) { + value = value.toPath() + } + expectedClass = value instanceof Path ? null : "Path" + } else if (par.type == "file" && stage == "input" && par.direction == "output") { + // cast to string if need be + if (value instanceof GString) { + value = value.toString() + } + expectedClass = value instanceof String ? null : "String" + } else { + // didn't find a match for par.type + expectedClass = par.type + } + + if (expectedClass != null) { + if (foundClass == null) { + foundClass = value.getClass().getName() + } + throw new UnexpectedArgumentTypeException(errorIdentifier, stage, par.plainName, expectedClass, foundClass) + } + + return value +} +// helper file: 'src/main/resources/io/viash/runners/nextflow/arguments/_processInputValues.nf' +Map _processInputValues(Map inputs, Map config, String id, String key) { + if (!workflow.stubRun) { + config.allArguments.each { arg -> + if (arg.required) { + assert inputs.containsKey(arg.plainName) && inputs.get(arg.plainName) != null : + "Error in module '${key}' id '${id}': required input argument '${arg.plainName}' is missing" + } + } + + inputs = inputs.collectEntries { name, value -> + def par = config.allArguments.find { it.plainName == name && (it.direction == "input" || it.type == "file") } + assert par != null : "Error in module '${key}' id '${id}': '${name}' is not a valid input argument" + + value = _checkArgumentType("input", par, value, "in module '$key' id '$id'") + + [ name, value ] + } + } + return inputs +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/arguments/_processOutputValues.nf' +Map _processOutputValues(Map outputs, Map config, String id, String key) { + if (!workflow.stubRun) { + config.allArguments.each { arg -> + if (arg.direction == "output" && arg.required) { + assert outputs.containsKey(arg.plainName) && outputs.get(arg.plainName) != null : + "Error in module '${key}' id '${id}': required output argument '${arg.plainName}' is missing" + } + } + + outputs = outputs.collectEntries { name, value -> + def par = config.allArguments.find { it.plainName == name && it.direction == "output" } + assert par != null : "Error in module '${key}' id '${id}': '${name}' is not a valid output argument" + + value = _checkArgumentType("output", par, value, "in module '$key' id '$id'") + + [ name, value ] + } + } + return outputs +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/IDChecker.nf' +class IDChecker { + final def items = [] as Set + + @groovy.transform.WithWriteLock + boolean observe(String item) { + if (items.contains(item)) { + return false + } else { + items << item + return true + } + } + + @groovy.transform.WithReadLock + boolean contains(String item) { + return items.contains(item) + } + + @groovy.transform.WithReadLock + Set getItems() { + return items.clone() + } +} +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/_checkUniqueIds.nf' + +/** + * Check if the ids are unique across parameter sets + * + * @param parameterSets a list of parameter sets. + */ +private void _checkUniqueIds(List>> parameterSets) { + def ppIds = parameterSets.collect{it[0]} + assert ppIds.size() == ppIds.unique().size() : "All argument sets should have unique ids. Detected ids: $ppIds" +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/_getChild.nf' + +// helper functions for reading params from file // +def _getChild(parent, child) { + if (child.contains("://") || java.nio.file.Paths.get(child).isAbsolute()) { + child + } else { + def parentAbsolute = java.nio.file.Paths.get(parent).toAbsolutePath().toString() + parentAbsolute.replaceAll('/[^/]*$', "/") + child + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/_parseParamList.nf' +/** + * Figure out the param list format based on the file extension + * + * @param param_list A String containing the path to the parameter list file. + * + * @return A String containing the format of the parameter list file. + */ +def _paramListGuessFormat(param_list) { + if (param_list !instanceof String) { + "asis" + } else if (param_list.endsWith(".csv")) { + "csv" + } else if (param_list.endsWith(".json") || param_list.endsWith(".jsn")) { + "json" + } else if (param_list.endsWith(".yaml") || param_list.endsWith(".yml")) { + "yaml" + } else { + "yaml_blob" + } +} + + +/** + * Read the param list + * + * @param param_list One of the following: + * - A String containing the path to the parameter list file (csv, json or yaml), + * - A yaml blob of a list of maps (yaml_blob), + * - Or a groovy list of maps (asis). + * @param config A Map of the Viash configuration. + * + * @return A List of Maps containing the parameters. + */ +def _parseParamList(param_list, Map config) { + // first determine format by extension + def paramListFormat = _paramListGuessFormat(param_list) + + def paramListPath = (paramListFormat != "asis" && paramListFormat != "yaml_blob") ? + file(param_list, hidden: true) : + null + + // get the correct parser function for the detected params_list format + def paramSets = [] + if (paramListFormat == "asis") { + paramSets = param_list + } else if (paramListFormat == "yaml_blob") { + paramSets = readYamlBlob(param_list) + } else if (paramListFormat == "yaml") { + paramSets = readYaml(paramListPath) + } else if (paramListFormat == "json") { + paramSets = readJson(paramListPath) + } else if (paramListFormat == "csv") { + paramSets = readCsv(paramListPath) + } else { + error "Format of provided --param_list not recognised.\n" + + "Found: '$paramListFormat'.\n" + + "Expected: a csv file, a json file, a yaml file,\n" + + "a yaml blob or a groovy list of maps." + } + + // data checks + assert paramSets instanceof List: "--param_list should contain a list of maps" + for (value in paramSets) { + assert value instanceof Map: "--param_list should contain a list of maps" + } + + // id is argument + def idIsArgument = config.allArguments.any{it.plainName == "id"} + + // Reformat from List to List> by adding the ID as first element of a Tuple2 + paramSets = paramSets.collect({ data -> + def id = data.id + if (!idIsArgument) { + data = data.findAll{k, v -> k != "id"} + } + [id, data] + }) + + // Split parameters with 'multiple: true' + paramSets = paramSets.collect({ id, data -> + data = _splitParams(data, config) + [id, data] + }) + + // The paths of input files inside a param_list file may have been specified relatively to the + // location of the param_list file. These paths must be made absolute. + if (paramListPath) { + paramSets = paramSets.collect({ id, data -> + def new_data = data.collectEntries{ parName, parValue -> + def par = config.allArguments.find{it.plainName == parName} + if (par && par.type == "file" && par.direction == "input") { + if (parValue instanceof Collection) { + parValue = parValue.collectMany{path -> + def x = _resolveSiblingIfNotAbsolute(path, paramListPath) + x instanceof Collection ? x : [x] + } + } else { + parValue = _resolveSiblingIfNotAbsolute(parValue, paramListPath) + } + } + [parName, parValue] + } + [id, new_data] + }) + } + + return paramSets +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/_splitParams.nf' +/** + * Split parameters for arguments that accept multiple values using their separator + * + * @param paramList A Map containing parameters to split. + * @param config A Map of the Viash configuration. This Map can be generated from the config file + * using the readConfig() function. + * + * @return A Map of parameters where the parameter values have been split into a list using + * their seperator. + */ +Map _splitParams(Map parValues, Map config){ + def parsedParamValues = parValues.collectEntries { parName, parValue -> + def parameterSettings = config.allArguments.find({it.plainName == parName}) + + if (!parameterSettings) { + // if argument is not found, do not alter + return [parName, parValue] + } + if (parameterSettings.multiple) { // Check if parameter can accept multiple values + if (parValue instanceof Collection) { + parValue = parValue.collect{it instanceof String ? it.split(parameterSettings.multiple_sep) : it } + } else if (parValue instanceof String) { + parValue = parValue.split(parameterSettings.multiple_sep) + } else if (parValue == null) { + parValue = [] + } else { + parValue = [ parValue ] + } + parValue = parValue.flatten() + } + // For all parameters check if multiple values are only passed for + // arguments that allow it. Quietly simplify lists of length 1. + if (!parameterSettings.multiple && parValue instanceof Collection) { + assert parValue.size() == 1 : + "Error: argument ${parName} has too many values.\n" + + " Expected amount: 1. Found: ${parValue.size()}" + parValue = parValue[0] + } + [parName, parValue] + } + return parsedParamValues +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/channelFromParams.nf' +/** + * Parse nextflow parameters based on settings defined in a viash config. + * Return a list of parameter sets, each parameter set corresponding to + * an event in a nextflow channel. The output from this function can be used + * with Channel.fromList to create a nextflow channel with Vdsl3 formatted + * events. + * + * This function performs: + * - A filtering of the params which can be found in the config file. + * - Process the params_list argument which allows a user to to initialise + * a Vsdl3 channel with multiple parameter sets. Possible formats are + * csv, json, yaml, or simply a yaml_blob. A csv should have column names + * which correspond to the different arguments of this pipeline. A json or a yaml + * file should be a list of maps, each of which has keys corresponding to the + * arguments of the pipeline. A yaml blob can also be passed directly as a parameter. + * When passing a csv, json or yaml, relative path names are relativized to the + * location of the parameter file. + * - Combine the parameter sets into a vdsl3 Channel. + * + * @param params Input parameters. Can optionaly contain a 'param_list' key that + * provides a list of arguments that can be split up into multiple events + * in the output channel possible formats of param_lists are: a csv file, + * json file, a yaml file or a yaml blob. Each parameters set (event) must + * have a unique ID. + * @param config A Map of the Viash configuration. This Map can be generated from the config file + * using the readConfig() function. + * + * @return A list of parameters with the first element of the event being + * the event ID and the second element containing a map of the parsed parameters. + */ + +private List>> _paramsToParamSets(Map params, Map config){ + // todo: fetch key from run args + def key_ = config.name + + /* parse regular parameters (not in param_list) */ + /*************************************************/ + def globalParams = config.allArguments + .findAll { params.containsKey(it.plainName) } + .collectEntries { [ it.plainName, params[it.plainName] ] } + def globalID = params.get("id", null) + + /* process params_list arguments */ + /*********************************/ + def paramList = params.containsKey("param_list") && params.param_list != null ? + params.param_list : [] + // if (paramList instanceof String) { + // paramList = [paramList] + // } + // def paramSets = paramList.collectMany{ _parseParamList(it, config) } + // TODO: be able to process param_list when it is a list of strings + def paramSets = _parseParamList(paramList, config) + if (paramSets.isEmpty()) { + paramSets = [[null, [:]]] + } + + /* combine arguments into channel */ + /**********************************/ + def processedParams = paramSets.indexed().collect{ index, tup -> + // Process ID + def id = tup[0] ?: globalID + + if (workflow.stubRun && !id) { + // if stub run, explicitly add an id if missing + id = "stub${index}" + } + assert id != null: "Each parameter set should have at least an 'id'" + + // Process params + def parValues = globalParams + tup[1] + // // Remove parameters which are null, if the default is also null + // parValues = parValues.collectEntries{paramName, paramValue -> + // parameterSettings = config.functionality.allArguments.find({it.plainName == paramName}) + // if ( paramValue != null || parameterSettings.get("default", null) != null ) { + // [paramName, paramValue] + // } + // } + parValues = parValues.collectEntries { name, value -> + def par = config.allArguments.find { it.plainName == name && (it.direction == "input" || it.type == "file") } + assert par != null : "Error in module '${key_}' id '${id}': '${name}' is not a valid input argument" + + if (par == null) { + return [:] + } + value = _checkArgumentType("input", par, value, "in module '$key_' id '$id'") + + [ name, value ] + } + + [id, parValues] + } + + // Check if ids (first element of each list) is unique + _checkUniqueIds(processedParams) + return processedParams +} + +/** + * Parse nextflow parameters based on settings defined in a viash config + * and return a nextflow channel. + * + * @param params Input parameters. Can optionaly contain a 'param_list' key that + * provides a list of arguments that can be split up into multiple events + * in the output channel possible formats of param_lists are: a csv file, + * json file, a yaml file or a yaml blob. Each parameters set (event) must + * have a unique ID. + * @param config A Map of the Viash configuration. This Map can be generated from the config file + * using the readConfig() function. + * + * @return A nextflow Channel with events. Events are formatted as a tuple that contains + * first contains the ID of the event and as second element holds a parameter map. + * + * + */ +def channelFromParams(Map params, Map config) { + def processedParams = _paramsToParamSets(params, config) + return Channel.fromList(processedParams) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/checkUniqueIds.nf' +def checkUniqueIds(Map args) { + def stopOnError = args.stopOnError == null ? args.stopOnError : true + + def idChecker = new IDChecker() + + return filter { tup -> + if (!idChecker.observe(tup[0])) { + if (stopOnError) { + error "Duplicate id: ${tup[0]}" + } else { + log.warn "Duplicate id: ${tup[0]}, removing duplicate entry" + return false + } + } + return true + } +} +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/preprocessInputs.nf' +// This helper file will be deprecated soon +preprocessInputsDeprecationWarningPrinted = false + +def preprocessInputsDeprecationWarning() { + if (!preprocessInputsDeprecationWarningPrinted) { + preprocessInputsDeprecationWarningPrinted = true + System.err.println("Warning: preprocessInputs() is deprecated and will be removed in Viash 0.9.0.") + } +} + +/** + * Generate a nextflow Workflow that allows processing a channel of + * Vdsl3 formatted events and apply a Viash config to them: + * - Gather default parameters from the Viash config and make + * sure that they are correctly formatted (see applyConfig method). + * - Format the input parameters (also using the applyConfig method). + * - Apply the default parameter to the input parameters. + * - Do some assertions: + * ~ Check if the event IDs in the channel are unique. + * + * The events in the channel are formatted as tuples, with the + * first element of the tuples being a unique id of the parameter set, + * and the second element containg the the parameters themselves. + * Optional extra elements of the tuples will be passed to the output as is. + * + * @param args A map that must contain a 'config' key that points + * to a parsed config (see readConfig()). Optionally, a + * 'key' key can be provided which can be used to create a unique + * name for the workflow process. + * + * @return A workflow that allows processing a channel of Vdsl3 formatted events + * and apply a Viash config to them. + */ +def preprocessInputs(Map args) { + preprocessInputsDeprecationWarning() + + def config = args.config + assert config instanceof Map : + "Error in preprocessInputs: config must be a map. " + + "Expected class: Map. Found: config.getClass() is ${config.getClass()}" + def key_ = args.key ?: config.name + + // Get different parameter types (used throughout this function) + def defaultArgs = config.allArguments + .findAll { it.containsKey("default") } + .collectEntries { [ it.plainName, it.default ] } + + map { tup -> + def id = tup[0] + def data = tup[1] + def passthrough = tup.drop(2) + + def new_data = (defaultArgs + data).collectEntries { name, value -> + def par = config.allArguments.find { it.plainName == name && (it.direction == "input" || it.type == "file") } + + if (par != null) { + value = _checkArgumentType("input", par, value, "in module '$key_' id '$id'") + } + + [ name, value ] + } + + [ id, new_data ] + passthrough + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/runComponents.nf' +/** + * Run a list of components on a stream of data. + * + * @param components: list of Viash VDSL3 modules to run + * @param fromState: a closure, a map or a list of keys to extract from the input data. + * If a closure, it will be called with the id, the data and the component config. + * @param toState: a closure, a map or a list of keys to extract from the output data + * If a closure, it will be called with the id, the output data, the old state and the component config. + * @param filter: filter function to apply to the input. + * It will be called with the id, the data and the component config. + * @param id: id to use for the output data + * If a closure, it will be called with the id, the data and the component config. + * @param auto: auto options to pass to the components + * + * @return: a workflow that runs the components + **/ +def runComponents(Map args) { + log.warn("runComponents is deprecated, use runEach instead") + assert args.components: "runComponents should be passed a list of components to run" + + def components_ = args.components + if (components_ !instanceof List) { + components_ = [ components_ ] + } + assert components_.size() > 0: "pass at least one component to runComponents" + + def fromState_ = args.fromState + def toState_ = args.toState + def filter_ = args.filter + def id_ = args.id + + workflow runComponentsWf { + take: input_ch + main: + + // generate one channel per method + out_chs = components_.collect{ comp_ -> + def comp_config = comp_.config + + def filter_ch = filter_ + ? input_ch | filter{tup -> + filter_(tup[0], tup[1], comp_config) + } + : input_ch + def id_ch = id_ + ? filter_ch | map{tup -> + // def new_id = id_(tup[0], tup[1], comp_config) + def new_id = tup[0] + if (id_ instanceof String) { + new_id = id_ + } else if (id_ instanceof Closure) { + new_id = id_(new_id, tup[1], comp_config) + } + [new_id] + tup.drop(1) + } + : filter_ch + def data_ch = id_ch | map{tup -> + def new_data = tup[1] + if (fromState_ instanceof Map) { + new_data = fromState_.collectEntries{ key0, key1 -> + [key0, new_data[key1]] + } + } else if (fromState_ instanceof List) { + new_data = fromState_.collectEntries{ key -> + [key, new_data[key]] + } + } else if (fromState_ instanceof Closure) { + new_data = fromState_(tup[0], new_data, comp_config) + } + tup.take(1) + [new_data] + tup.drop(1) + } + def out_ch = data_ch + | comp_.run( + auto: (args.auto ?: [:]) + [simplifyInput: false, simplifyOutput: false] + ) + def post_ch = toState_ + ? out_ch | map{tup -> + def output = tup[1] + def old_state = tup[2] + def new_state = null + if (toState_ instanceof Map) { + new_state = old_state + toState_.collectEntries{ key0, key1 -> + [key0, output[key1]] + } + } else if (toState_ instanceof List) { + new_state = old_state + toState_.collectEntries{ key -> + [key, output[key]] + } + } else if (toState_ instanceof Closure) { + new_state = toState_(tup[0], output, old_state, comp_config) + } + [tup[0], new_state] + tup.drop(3) + } + : out_ch + + post_ch + } + + // mix all results + output_ch = + (out_chs.size == 1) + ? out_chs[0] + : out_chs[0].mix(*out_chs.drop(1)) + + emit: output_ch + } + + return runComponentsWf +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/runEach.nf' +/** + * Run a list of components on a stream of data. + * + * @param components: list of Viash VDSL3 modules to run + * @param fromState: a closure, a map or a list of keys to extract from the input data. + * If a closure, it will be called with the id, the data and the component itself. + * @param toState: a closure, a map or a list of keys to extract from the output data + * If a closure, it will be called with the id, the output data, the old state and the component itself. + * @param filter: filter function to apply to the input. + * It will be called with the id, the data and the component itself. + * @param id: id to use for the output data + * If a closure, it will be called with the id, the data and the component itself. + * @param auto: auto options to pass to the components + * + * @return: a workflow that runs the components + **/ +def runEach(Map args) { + assert args.components: "runEach should be passed a list of components to run" + + def components_ = args.components + if (components_ !instanceof List) { + components_ = [ components_ ] + } + assert components_.size() > 0: "pass at least one component to runEach" + + def fromState_ = args.fromState + def toState_ = args.toState + def filter_ = args.filter + def id_ = args.id + + workflow runEachWf { + take: input_ch + main: + + // generate one channel per method + out_chs = components_.collect{ comp_ -> + def filter_ch = filter_ + ? input_ch | filter{tup -> + filter_(tup[0], tup[1], comp_) + } + : input_ch + def id_ch = id_ + ? filter_ch | map{tup -> + def new_id = id_ + if (new_id instanceof Closure) { + new_id = new_id(tup[0], tup[1], comp_) + } + assert new_id instanceof String : "Error in runEach: id should be a String or a Closure that returns a String. Expected: id instanceof String. Found: ${new_id.getClass()}" + [new_id] + tup.drop(1) + } + : filter_ch + def data_ch = id_ch | map{tup -> + def new_data = tup[1] + if (fromState_ instanceof Map) { + new_data = fromState_.collectEntries{ key0, key1 -> + [key0, new_data[key1]] + } + } else if (fromState_ instanceof List) { + new_data = fromState_.collectEntries{ key -> + [key, new_data[key]] + } + } else if (fromState_ instanceof Closure) { + new_data = fromState_(tup[0], new_data, comp_) + } + tup.take(1) + [new_data] + tup.drop(1) + } + def out_ch = data_ch + | comp_.run( + auto: (args.auto ?: [:]) + [simplifyInput: false, simplifyOutput: false] + ) + def post_ch = toState_ + ? out_ch | map{tup -> + def output = tup[1] + def old_state = tup[2] + def new_state = null + if (toState_ instanceof Map) { + new_state = old_state + toState_.collectEntries{ key0, key1 -> + [key0, output[key1]] + } + } else if (toState_ instanceof List) { + new_state = old_state + toState_.collectEntries{ key -> + [key, output[key]] + } + } else if (toState_ instanceof Closure) { + new_state = toState_(tup[0], output, old_state, comp_) + } + [tup[0], new_state] + tup.drop(3) + } + : out_ch + + post_ch + } + + // mix all results + output_ch = + (out_chs.size == 1) + ? out_chs[0] + : out_chs[0].mix(*out_chs.drop(1)) + + emit: output_ch + } + + return runEachWf +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/safeJoin.nf' +/** + * Join sourceChannel to targetChannel + * + * This function joins the sourceChannel to the targetChannel. + * However, each id in the targetChannel must be present in the + * sourceChannel. If _meta.join_id exists in the targetChannel, that is + * used as an id instead. If the id doesn't match any id in the sourceChannel, + * an error is thrown. + */ + +def safeJoin(targetChannel, sourceChannel, key) { + def sourceIDs = new IDChecker() + + def sourceCheck = sourceChannel + | map { tup -> + sourceIDs.observe(tup[0]) + tup + } + def targetCheck = targetChannel + | map { tup -> + def id = tup[0] + + if (!sourceIDs.contains(id)) { + error ( + "Error in module '${key}' when merging output with original state.\n" + + " Reason: output with id '${id}' could not be joined with source channel.\n" + + " If the IDs in the output channel differ from the input channel,\n" + + " please set `tup[1]._meta.join_id to the original ID.\n" + + " Original IDs in input channel: ['${sourceIDs.getItems().join("', '")}'].\n" + + " Unexpected ID in the output channel: '${id}'.\n" + + " Example input event: [\"id\", [input: file(...)]],\n" + + " Example output event: [\"newid\", [output: file(...), _meta: [join_id: \"id\"]]]" + ) + } + // TODO: add link to our documentation on how to fix this + + tup + } + + sourceCheck.cross(targetChannel) + | map{ left, right -> + right + left.drop(1) + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/config/_processArgument.nf' +def _processArgument(arg) { + arg.multiple = arg.multiple != null ? arg.multiple : false + arg.required = arg.required != null ? arg.required : false + arg.direction = arg.direction != null ? arg.direction : "input" + arg.multiple_sep = arg.multiple_sep != null ? arg.multiple_sep : ";" + arg.plainName = arg.name.replaceAll("^-*", "") + + if (arg.type == "file") { + arg.must_exist = arg.must_exist != null ? arg.must_exist : true + arg.create_parent = arg.create_parent != null ? arg.create_parent : true + } + + // add default values to output files which haven't already got a default + if (arg.type == "file" && arg.direction == "output" && arg.default == null) { + def mult = arg.multiple ? "_*" : "" + def extSearch = "" + if (arg.default != null) { + extSearch = arg.default + } else if (arg.example != null) { + extSearch = arg.example + } + if (extSearch instanceof List) { + extSearch = extSearch[0] + } + def extSearchResult = extSearch.find("\\.[^\\.]+\$") + def ext = extSearchResult != null ? extSearchResult : "" + arg.default = "\$id.\$key.${arg.plainName}${mult}${ext}" + if (arg.multiple) { + arg.default = [arg.default] + } + } + + if (!arg.multiple) { + if (arg.default != null && arg.default instanceof List) { + arg.default = arg.default[0] + } + if (arg.example != null && arg.example instanceof List) { + arg.example = arg.example[0] + } + } + + if (arg.type == "boolean_true") { + arg.default = false + } + if (arg.type == "boolean_false") { + arg.default = true + } + + arg +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/config/addGlobalParams.nf' +def addGlobalArguments(config) { + def localConfig = [ + "argument_groups": [ + [ + "name": "Nextflow input-output arguments", + "description": "Input/output parameters for Nextflow itself. Please note that both publishDir and publish_dir are supported but at least one has to be configured.", + "arguments" : [ + [ + 'name': '--publish_dir', + 'required': true, + 'type': 'string', + 'description': 'Path to an output directory.', + 'example': 'output/', + 'multiple': false + ], + [ + 'name': '--param_list', + 'required': false, + 'type': 'string', + 'description': '''Allows inputting multiple parameter sets to initialise a Nextflow channel. A `param_list` can either be a list of maps, a csv file, a json file, a yaml file, or simply a yaml blob. + | + |* A list of maps (as-is) where the keys of each map corresponds to the arguments of the pipeline. Example: in a `nextflow.config` file: `param_list: [ ['id': 'foo', 'input': 'foo.txt'], ['id': 'bar', 'input': 'bar.txt'] ]`. + |* A csv file should have column names which correspond to the different arguments of this pipeline. Example: `--param_list data.csv` with columns `id,input`. + |* A json or a yaml file should be a list of maps, each of which has keys corresponding to the arguments of the pipeline. Example: `--param_list data.json` with contents `[ {'id': 'foo', 'input': 'foo.txt'}, {'id': 'bar', 'input': 'bar.txt'} ]`. + |* A yaml blob can also be passed directly as a string. Example: `--param_list "[ {'id': 'foo', 'input': 'foo.txt'}, {'id': 'bar', 'input': 'bar.txt'} ]"`. + | + |When passing a csv, json or yaml file, relative path names are relativized to the location of the parameter file. No relativation is performed when `param_list` is a list of maps (as-is) or a yaml blob.'''.stripMargin(), + 'example': 'my_params.yaml', + 'multiple': false, + 'hidden': true + ] + // TODO: allow multiple: true in param_list? + // TODO: allow to specify a --param_list_regex to filter the param_list? + // TODO: allow to specify a --param_list_from_state to remap entries in the param_list? + ] + ] + ] + ] + + return processConfig(_mergeMap(config, localConfig)) +} + +def _mergeMap(Map lhs, Map rhs) { + return rhs.inject(lhs.clone()) { map, entry -> + if (map[entry.key] instanceof Map && entry.value instanceof Map) { + map[entry.key] = _mergeMap(map[entry.key], entry.value) + } else if (map[entry.key] instanceof Collection && entry.value instanceof Collection) { + map[entry.key] += entry.value + } else { + map[entry.key] = entry.value + } + return map + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/config/generateHelp.nf' +def _generateArgumentHelp(param) { + // alternatives are not supported + // def names = param.alternatives ::: List(param.name) + + def unnamedProps = [ + ["required parameter", param.required], + ["multiple values allowed", param.multiple], + ["output", param.direction.toLowerCase() == "output"], + ["file must exist", param.type == "file" && param.must_exist] + ].findAll{it[1]}.collect{it[0]} + + def dflt = null + if (param.default != null) { + if (param.default instanceof List) { + dflt = param.default.join(param.multiple_sep != null ? param.multiple_sep : ", ") + } else { + dflt = param.default.toString() + } + } + def example = null + if (param.example != null) { + if (param.example instanceof List) { + example = param.example.join(param.multiple_sep != null ? param.multiple_sep : ", ") + } else { + example = param.example.toString() + } + } + def min = param.min?.toString() + def max = param.max?.toString() + + def escapeChoice = { choice -> + def s1 = choice.replaceAll("\\n", "\\\\n") + def s2 = s1.replaceAll("\"", """\\\"""") + s2.contains(",") || s2 != choice ? "\"" + s2 + "\"" : s2 + } + def choices = param.choices == null ? + null : + "[ " + param.choices.collect{escapeChoice(it.toString())}.join(", ") + " ]" + + def namedPropsStr = [ + ["type", ([param.type] + unnamedProps).join(", ")], + ["default", dflt], + ["example", example], + ["choices", choices], + ["min", min], + ["max", max] + ] + .findAll{it[1]} + .collect{"\n " + it[0] + ": " + it[1].replaceAll("\n", "\\n")} + .join("") + + def descStr = param.description == null ? + "" : + _paragraphWrap("\n" + param.description.trim(), 80 - 8).join("\n ") + + "\n --" + param.plainName + + namedPropsStr + + descStr +} + +// Based on Helper.generateHelp() in Helper.scala +def _generateHelp(config) { + def fun = config + + // PART 1: NAME AND VERSION + def nameStr = fun.name + + (fun.version == null ? "" : " " + fun.version) + + // PART 2: DESCRIPTION + def descrStr = fun.description == null ? + "" : + "\n\n" + _paragraphWrap(fun.description.trim(), 80).join("\n") + + // PART 3: Usage + def usageStr = fun.usage == null ? + "" : + "\n\nUsage:\n" + fun.usage.trim() + + // PART 4: Options + def argGroupStrs = fun.allArgumentGroups.collect{argGroup -> + def name = argGroup.name + def descriptionStr = argGroup.description == null ? + "" : + "\n " + _paragraphWrap(argGroup.description.trim(), 80-4).join("\n ") + "\n" + def arguments = argGroup.arguments.collect{arg -> + arg instanceof String ? fun.allArguments.find{it.plainName == arg} : arg + }.findAll{it != null} + def argumentStrs = arguments.collect{param -> _generateArgumentHelp(param)} + + "\n\n$name:" + + descriptionStr + + argumentStrs.join("\n") + } + + // FINAL: combine + def out = nameStr + + descrStr + + usageStr + + argGroupStrs.join("") + + return out +} + +// based on Format._paragraphWrap +def _paragraphWrap(str, maxLength) { + def outLines = [] + str.split("\n").each{par -> + def words = par.split("\\s").toList() + + def word = null + def line = words.pop() + while(!words.isEmpty()) { + word = words.pop() + if (line.length() + word.length() + 1 <= maxLength) { + line = line + " " + word + } else { + outLines.add(line) + line = word + } + } + if (words.isEmpty()) { + outLines.add(line) + } + } + return outLines +} + +def helpMessage(config) { + if (params.containsKey("help") && params.help) { + def mergedConfig = addGlobalArguments(config) + def helpStr = _generateHelp(mergedConfig) + println(helpStr) + exit 0 + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/config/processConfig.nf' +def processConfig(config) { + // set defaults for arguments + config.arguments = + (config.arguments ?: []).collect{_processArgument(it)} + + // set defaults for argument_group arguments + config.argument_groups = + (config.argument_groups ?: []).collect{grp -> + grp.arguments = (grp.arguments ?: []).collect{_processArgument(it)} + grp + } + + // create combined arguments list + config.allArguments = + config.arguments + + config.argument_groups.collectMany{it.arguments} + + // add missing argument groups (based on Functionality::allArgumentGroups()) + def argGroups = config.argument_groups + if (argGroups.any{it.name.toLowerCase() == "arguments"}) { + argGroups = argGroups.collect{ grp -> + if (grp.name.toLowerCase() == "arguments") { + grp = grp + [ + arguments: grp.arguments + config.arguments + ] + } + grp + } + } else { + argGroups = argGroups + [ + name: "Arguments", + arguments: config.arguments + ] + } + config.allArgumentGroups = argGroups + + config +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/config/readConfig.nf' + +def readConfig(file) { + def config = readYaml(file ?: moduleDir.resolve("config.vsh.yaml")) + processConfig(config) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/_resolveSiblingIfNotAbsolute.nf' +/** + * Resolve a path relative to the current file. + * + * @param str The path to resolve, as a String. + * @param parentPath The path to resolve relative to, as a Path. + * + * @return The path that may have been resovled, as a Path. + */ +def _resolveSiblingIfNotAbsolute(str, parentPath) { + if (str !instanceof String) { + return str + } + if (!_stringIsAbsolutePath(str)) { + return parentPath.resolveSibling(str) + } else { + return file(str, hidden: true) + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/_stringIsAbsolutePath.nf' +/** + * Check whether a path as a string is absolute. + * + * In the past, we tried using `file(., relative: true).isAbsolute()`, + * but the 'relative' option was added in 22.10.0. + * + * @param path The path to check, as a String. + * + * @return Whether the path is absolute, as a boolean. + */ +def _stringIsAbsolutePath(path) { + def _resolve_URL_PROTOCOL = ~/^([a-zA-Z][a-zA-Z0-9]*:)?\\/.+/ + + assert path instanceof String + return _resolve_URL_PROTOCOL.matcher(path).matches() +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/collectTraces.nf' +class CustomTraceObserver implements nextflow.trace.TraceObserver { + List traces + + CustomTraceObserver(List traces) { + this.traces = traces + } + + @Override + void onProcessComplete(nextflow.processor.TaskHandler handler, nextflow.trace.TraceRecord trace) { + def trace2 = trace.store.clone() + trace2.script = null + traces.add(trace2) + } + + @Override + void onProcessCached(nextflow.processor.TaskHandler handler, nextflow.trace.TraceRecord trace) { + def trace2 = trace.store.clone() + trace2.script = null + traces.add(trace2) + } +} + +def collectTraces() { + def traces = Collections.synchronizedList([]) + + // add custom trace observer which stores traces in the traces object + session.observers.add(new CustomTraceObserver(traces)) + + traces +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/deepClone.nf' +/** + * Performs a deep clone of the given object. + * @param x an object + */ +def deepClone(x) { + iterateMap(x, {it instanceof Cloneable ? it.clone() : it}) +} +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/getPublishDir.nf' +def getPublishDir() { + return params.containsKey("publish_dir") ? params.publish_dir : + params.containsKey("publishDir") ? params.publishDir : + null +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/getRootDir.nf' + +// Recurse upwards until we find a '.build.yaml' file +def _findBuildYamlFile(pathPossiblySymlink) { + def path = pathPossiblySymlink.toRealPath() + def child = path.resolve(".build.yaml") + if (java.nio.file.Files.isDirectory(path) && java.nio.file.Files.exists(child)) { + return child + } else { + def parent = path.getParent() + if (parent == null) { + return null + } else { + return _findBuildYamlFile(parent) + } + } +} + +// get the root of the target folder +def getRootDir() { + def dir = _findBuildYamlFile(meta.resources_dir) + assert dir != null: "Could not find .build.yaml in the folder structure" + dir.getParent() +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/iterateMap.nf' +/** + * Recursively apply a function over the leaves of an object. + * @param obj The object to iterate over. + * @param fun The function to apply to each value. + * @return The object with the function applied to each value. + */ +def iterateMap(obj, fun) { + if (obj instanceof List && obj !instanceof String) { + return obj.collect{item -> + iterateMap(item, fun) + } + } else if (obj instanceof Map) { + return obj.collectEntries{key, item -> + [key.toString(), iterateMap(item, fun)] + } + } else { + return fun(obj) + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/niceView.nf' +/** + * A view for printing the event of each channel as a YAML blob. + * This is useful for debugging. + */ +def niceView() { + workflow niceViewWf { + take: input + main: + output = input + | view{toYamlBlob(it)} + emit: output + } + return niceViewWf +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/readCsv.nf' + +def readCsv(file_path) { + def output = [] + def inputFile = file_path !instanceof Path ? file(file_path, hidden: true) : file_path + + // todo: allow escaped quotes in string + // todo: allow single quotes? + def splitRegex = java.util.regex.Pattern.compile(''',(?=(?:[^"]*"[^"]*")*[^"]*$)''') + def removeQuote = java.util.regex.Pattern.compile('''"(.*)"''') + + def br = java.nio.file.Files.newBufferedReader(inputFile) + + def row = -1 + def header = null + while (br.ready() && header == null) { + def line = br.readLine() + row++ + if (!line.startsWith("#")) { + header = splitRegex.split(line, -1).collect{field -> + m = removeQuote.matcher(field) + m.find() ? m.replaceFirst('$1') : field + } + } + } + assert header != null: "CSV file should contain a header" + + while (br.ready()) { + def line = br.readLine() + row++ + if (line == null) { + br.close() + break + } + + if (!line.startsWith("#")) { + def predata = splitRegex.split(line, -1) + def data = predata.collect{field -> + if (field == "") { + return null + } + def m = removeQuote.matcher(field) + if (m.find()) { + return m.replaceFirst('$1') + } else { + return field + } + } + assert header.size() == data.size(): "Row $row should contain the same number as fields as the header" + + def dataMap = [header, data].transpose().collectEntries().findAll{it.value != null} + output.add(dataMap) + } + } + + output +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/readJson.nf' +def readJson(file_path) { + def inputFile = file_path !instanceof Path ? file(file_path, hidden: true) : file_path + def jsonSlurper = new groovy.json.JsonSlurper() + jsonSlurper.parse(inputFile) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/readJsonBlob.nf' +def readJsonBlob(str) { + def jsonSlurper = new groovy.json.JsonSlurper() + jsonSlurper.parseText(str) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/readTaggedYaml.nf' +// Custom constructor to modify how certain objects are parsed from YAML +class CustomConstructor extends org.yaml.snakeyaml.constructor.Constructor { + Path root + + class ConstructPath extends org.yaml.snakeyaml.constructor.AbstractConstruct { + public Object construct(org.yaml.snakeyaml.nodes.Node node) { + String filename = (String) constructScalar(node); + if (root != null) { + return root.resolve(filename); + } + return java.nio.file.Paths.get(filename); + } + } + + CustomConstructor(org.yaml.snakeyaml.LoaderOptions options, Path root) { + super(options) + this.root = root + // Handling !file tag and parse it back to a File type + this.yamlConstructors.put(new org.yaml.snakeyaml.nodes.Tag("!file"), new ConstructPath()) + } +} + +def readTaggedYaml(Path path) { + def options = new org.yaml.snakeyaml.LoaderOptions() + def constructor = new CustomConstructor(options, path.getParent()) + def yaml = new org.yaml.snakeyaml.Yaml(constructor) + return yaml.load(path.text) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/readYaml.nf' +def readYaml(file_path) { + def inputFile = file_path !instanceof Path ? file(file_path, hidden: true) : file_path + def yamlSlurper = new org.yaml.snakeyaml.Yaml() + yamlSlurper.load(inputFile) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/readYamlBlob.nf' +def readYamlBlob(str) { + def yamlSlurper = new org.yaml.snakeyaml.Yaml() + yamlSlurper.load(str) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/toJsonBlob.nf' +String toJsonBlob(data) { + return groovy.json.JsonOutput.toJson(data) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/toTaggedYamlBlob.nf' +// Custom representer to modify how certain objects are represented in YAML +class CustomRepresenter extends org.yaml.snakeyaml.representer.Representer { + Path relativizer + + class RepresentPath implements org.yaml.snakeyaml.representer.Represent { + public String getFileName(Object obj) { + if (obj instanceof File) { + obj = ((File) obj).toPath(); + } + if (obj !instanceof Path) { + throw new IllegalArgumentException("Object: " + obj + " is not a Path or File"); + } + def path = (Path) obj; + + if (relativizer != null) { + return relativizer.relativize(path).toString() + } else { + return path.toString() + } + } + + public org.yaml.snakeyaml.nodes.Node representData(Object data) { + String filename = getFileName(data); + def tag = new org.yaml.snakeyaml.nodes.Tag("!file"); + return representScalar(tag, filename); + } + } + CustomRepresenter(org.yaml.snakeyaml.DumperOptions options, Path relativizer) { + super(options) + this.relativizer = relativizer + this.representers.put(sun.nio.fs.UnixPath, new RepresentPath()) + this.representers.put(Path, new RepresentPath()) + this.representers.put(File, new RepresentPath()) + } +} + +String toTaggedYamlBlob(data) { + return toRelativeTaggedYamlBlob(data, null) +} +String toRelativeTaggedYamlBlob(data, Path relativizer) { + def options = new org.yaml.snakeyaml.DumperOptions() + options.setDefaultFlowStyle(org.yaml.snakeyaml.DumperOptions.FlowStyle.BLOCK) + def representer = new CustomRepresenter(options, relativizer) + def yaml = new org.yaml.snakeyaml.Yaml(representer, options) + return yaml.dump(data) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/toYamlBlob.nf' +String toYamlBlob(data) { + def options = new org.yaml.snakeyaml.DumperOptions() + options.setDefaultFlowStyle(org.yaml.snakeyaml.DumperOptions.FlowStyle.BLOCK) + options.setPrettyFlow(true) + def yaml = new org.yaml.snakeyaml.Yaml(options) + def cleanData = iterateMap(data, { it instanceof Path ? it.toString() : it }) + return yaml.dump(cleanData) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/writeJson.nf' +void writeJson(data, file) { + assert data: "writeJson: data should not be null" + assert file: "writeJson: file should not be null" + file.write(toJsonBlob(data)) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/writeYaml.nf' +void writeYaml(data, file) { + assert data: "writeYaml: data should not be null" + assert file: "writeYaml: file should not be null" + file.write(toYamlBlob(data)) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/states/findStates.nf' +def findStates(Map params, Map config) { + def auto_config = deepClone(config) + def auto_params = deepClone(params) + + auto_config = auto_config.clone() + // override arguments + auto_config.argument_groups = [] + auto_config.arguments = [ + [ + type: "string", + name: "--id", + description: "A dummy identifier", + required: false + ], + [ + type: "file", + name: "--input_states", + example: "/path/to/input/directory/**/state.yaml", + description: "Path to input directory containing the datasets to be integrated.", + required: true, + multiple: true, + multiple_sep: ";" + ], + [ + type: "string", + name: "--filter", + example: "foo/.*/state.yaml", + description: "Regex to filter state files by path.", + required: false + ], + // to do: make this a yaml blob? + [ + type: "string", + name: "--rename_keys", + example: ["newKey1:oldKey1", "newKey2:oldKey2"], + description: "Rename keys in the detected input files. This is useful if the input files do not match the set of input arguments of the workflow.", + required: false, + multiple: true, + multiple_sep: ";" + ], + [ + type: "string", + name: "--settings", + example: '{"output_dataset": "dataset.h5ad", "k": 10}', + description: "Global arguments as a JSON glob to be passed to all components.", + required: false + ] + ] + if (!(auto_params.containsKey("id"))) { + auto_params["id"] = "auto" + } + + // run auto config through processConfig once more + auto_config = processConfig(auto_config) + + workflow findStatesWf { + helpMessage(auto_config) + + output_ch = + channelFromParams(auto_params, auto_config) + | flatMap { autoId, args -> + + def globalSettings = args.settings ? readYamlBlob(args.settings) : [:] + + // look for state files in input dir + def stateFiles = args.input_states + + // filter state files by regex + if (args.filter) { + stateFiles = stateFiles.findAll{ stateFile -> + def stateFileStr = stateFile.toString() + def matcher = stateFileStr =~ args.filter + matcher.matches()} + } + + // read in states + def states = stateFiles.collect { stateFile -> + def state_ = readTaggedYaml(stateFile) + [state_.id, state_] + } + + // construct renameMap + if (args.rename_keys) { + def renameMap = args.rename_keys.collectEntries{renameString -> + def split = renameString.split(";") + assert split.size() == 2: "Argument 'rename_keys' should be of the form 'newKey:oldKey,newKey:oldKey'" + split + } + + // rename keys in state, only let states through which have all keys + // also add global settings + states = states.collectMany{id, state -> + def newState = [:] + + for (key in renameMap.keySet()) { + def origKey = renameMap[key] + if (!(state.containsKey(origKey))) { + return [] + } + newState[key] = state[origKey] + } + + [[id, globalSettings + newState]] + } + } + + states + } + emit: + output_ch + } + + return findStatesWf +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/states/joinStates.nf' +def joinStates(Closure apply_) { + workflow joinStatesWf { + take: input_ch + main: + output_ch = input_ch + | toSortedList + | filter{ it.size() > 0 } + | map{ tups -> + def ids = tups.collect{it[0]} + def states = tups.collect{it[1]} + apply_(ids, states) + } + + emit: output_ch + } + return joinStatesWf +} +// helper file: 'src/main/resources/io/viash/runners/nextflow/states/publishStates.nf' +def collectFiles(obj) { + if (obj instanceof java.io.File || obj instanceof Path) { + return [obj] + } else if (obj instanceof List && obj !instanceof String) { + return obj.collectMany{item -> + collectFiles(item) + } + } else if (obj instanceof Map) { + return obj.collectMany{key, item -> + collectFiles(item) + } + } else { + return [] + } +} + +/** + * Recurse through a state and collect all input files and their target output filenames. + * @param obj The state to recurse through. + * @param prefix The prefix to prepend to the output filenames. + */ +def collectInputOutputPaths(obj, prefix) { + if (obj instanceof File || obj instanceof Path) { + def path = obj instanceof Path ? obj : obj.toPath() + def ext = path.getFileName().toString().find("\\.[^\\.]+\$") ?: "" + def newFilename = prefix + ext + return [[obj, newFilename]] + } else if (obj instanceof List && obj !instanceof String) { + return obj.withIndex().collectMany{item, ix -> + collectInputOutputPaths(item, prefix + "_" + ix) + } + } else if (obj instanceof Map) { + return obj.collectMany{key, item -> + collectInputOutputPaths(item, prefix + "." + key) + } + } else { + return [] + } +} + +def publishStates(Map args) { + def key_ = args.get("key") + def yamlTemplate_ = args.get("output_state", args.get("outputState", '$id.$key.state.yaml')) + + assert key_ != null : "publishStates: key must be specified" + + workflow publishStatesWf { + take: input_ch + main: + input_ch + | map { tup -> + def id_ = tup[0] + def state_ = tup[1] + + // the input files and the target output filenames + def inputoutputFilenames_ = collectInputOutputPaths(state_, id_ + "." + key_).transpose() + def inputFiles_ = inputoutputFilenames_[0] + def outputFilenames_ = inputoutputFilenames_[1] + + def yamlFilename = yamlTemplate_ + .replaceAll('\\$id', id_) + .replaceAll('\\$key', key_) + + // TODO: do the pathnames in state_ match up with the outputFilenames_? + + // convert state to yaml blob + def yamlBlob_ = toRelativeTaggedYamlBlob([id: id_] + state_, java.nio.file.Paths.get(yamlFilename)) + + [id_, yamlBlob_, yamlFilename, inputFiles_, outputFilenames_] + } + | publishStatesProc + emit: input_ch + } + return publishStatesWf +} +process publishStatesProc { + // todo: check publishpath? + publishDir path: "${getPublishDir()}/", mode: "copy" + tag "$id" + input: + tuple val(id), val(yamlBlob), val(yamlFile), path(inputFiles, stageAs: "_inputfile?/*"), val(outputFiles) + output: + tuple val(id), path{[yamlFile] + outputFiles} + script: + def copyCommands = [ + inputFiles instanceof List ? inputFiles : [inputFiles], + outputFiles instanceof List ? outputFiles : [outputFiles] + ] + .transpose() + .collectMany{infile, outfile -> + if (infile.toString() != outfile.toString()) { + [ + "[ -d \"\$(dirname '${outfile.toString()}')\" ] || mkdir -p \"\$(dirname '${outfile.toString()}')\"", + "cp -r '${infile.toString()}' '${outfile.toString()}'" + ] + } else { + // no need to copy if infile is the same as outfile + [] + } + } + """ +mkdir -p "\$(dirname '${yamlFile}')" +echo "Storing state as yaml" +echo '${yamlBlob}' > '${yamlFile}' +echo "Copying output files to destination folder" +${copyCommands.join("\n ")} +""" +} + + +// this assumes that the state contains no other values other than those specified in the config +def publishStatesByConfig(Map args) { + def config = args.get("config") + assert config != null : "publishStatesByConfig: config must be specified" + + def key_ = args.get("key", config.name) + assert key_ != null : "publishStatesByConfig: key must be specified" + + workflow publishStatesSimpleWf { + take: input_ch + main: + input_ch + | map { tup -> + def id_ = tup[0] + def state_ = tup[1] // e.g. [output: new File("myoutput.h5ad"), k: 10] + def origState_ = tup[2] // e.g. [output: '$id.$key.foo.h5ad'] + + // TODO: allow overriding the state.yaml template + // TODO TODO: if auto.publish == "state", add output_state as an argument + def yamlTemplate = params.containsKey("output_state") ? params.output_state : '$id.$key.state.yaml' + def yamlFilename = yamlTemplate + .replaceAll('\\$id', id_) + .replaceAll('\\$key', key_) + def yamlDir = java.nio.file.Paths.get(yamlFilename).getParent() + + // the processed state is a list of [key, value, inputPath, outputFilename] tuples, where + // - key is a String + // - value is any object that can be serialized to a Yaml (so a String/Integer/Long/Double/Boolean, a List, a Map, or a Path) + // - inputPath is a List[Path] + // - outputFilename is a List[String] + // - (key, value) are the tuples that will be saved to the state.yaml file + // - (inputPath, outputFilename) are the files that will be copied from src to dest (relative to the state.yaml) + def processedState = + config.allArguments + .findAll { it.direction == "output" } + .collectMany { par -> + def plainName_ = par.plainName + // if the state does not contain the key, it's an + // optional argument for which the component did + // not generate any output + if (!state_.containsKey(plainName_)) { + return [] + } + def value = state_[plainName_] + // if the parameter is not a file, it should be stored + // in the state as-is, but is not something that needs + // to be copied from the source path to the dest path + if (par.type != "file") { + return [[key: plainName_, value: value, inputPath: [], outputFilename: []]] + } + // if the orig state does not contain this filename, + // it's an optional argument for which the user specified + // that it should not be returned as a state + if (!origState_.containsKey(plainName_)) { + return [] + } + def filenameTemplate = origState_[plainName_] + // if the pararameter is multiple: true, fetch the template + if (par.multiple && filenameTemplate instanceof List) { + filenameTemplate = filenameTemplate[0] + } + // instantiate the template + def filename = filenameTemplate + .replaceAll('\\$id', id_) + .replaceAll('\\$key', key_) + if (par.multiple) { + // if the parameter is multiple: true, the filename + // should contain a wildcard '*' that is replaced with + // the index of the file + assert filename.contains("*") : "Module '${key_}' id '${id_}': Multiple output files specified, but no wildcard '*' in the filename: ${filename}" + def outputPerFile = value.withIndex().collect{ val, ix -> + def filename_ix = filename.replace("*", ix.toString()) + def value_ = java.nio.file.Paths.get(filename_ix) + // if id contains a slash + if (yamlDir != null) { + value_ = yamlDir.relativize(value_) + } + def inputPath = val instanceof File ? val.toPath() : val + [value: value_, inputPath: inputPath, outputFilename: filename_ix] + } + def transposedOutputs = ["value", "inputPath", "outputFilename"].collectEntries{ key -> + [key, outputPerFile.collect{dic -> dic[key]}] + } + return [[key: plainName_] + transposedOutputs] + } else { + def value_ = java.nio.file.Paths.get(filename) + // if id contains a slash + if (yamlDir != null) { + value_ = yamlDir.relativize(value_) + } + def inputPath = value instanceof File ? value.toPath() : value + return [[key: plainName_, value: value_, inputPath: [inputPath], outputFilename: [filename]]] + } + } + + def updatedState_ = processedState.collectEntries{[it.key, it.value]} + def inputPaths = processedState.collectMany{it.inputPath} + def outputFilenames = processedState.collectMany{it.outputFilename} + + // convert state to yaml blob + def yamlBlob_ = toTaggedYamlBlob([id: id_] + updatedState_) + + [id_, yamlBlob_, yamlFilename, inputPaths, outputFilenames] + } + | publishStatesProc + emit: input_ch + } + return publishStatesSimpleWf +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/states/setState.nf' +def setState(fun) { + assert fun instanceof Closure || fun instanceof Map || fun instanceof List : + "Error in setState: Expected process argument to be a Closure, a Map, or a List. Found: class ${fun.getClass()}" + + // if fun is a List, convert to map + if (fun instanceof List) { + // check whether fun is a list[string] + assert fun.every{it instanceof CharSequence} : "Error in setState: argument is a List, but not all elements are Strings" + fun = fun.collectEntries{[it, it]} + } + + // if fun is a map, convert to closure + if (fun instanceof Map) { + // check whether fun is a map[string, string] + assert fun.values().every{it instanceof CharSequence} : "Error in setState: argument is a Map, but not all values are Strings" + assert fun.keySet().every{it instanceof CharSequence} : "Error in setState: argument is a Map, but not all keys are Strings" + def funMap = fun.clone() + // turn the map into a closure to be used later on + fun = { id_, state_ -> + assert state_ instanceof Map : "Error in setState: the state is not a Map" + funMap.collectMany{newkey, origkey -> + if (state_.containsKey(origkey)) { + [[newkey, state_[origkey]]] + } else { + [] + } + }.collectEntries() + } + } + + map { tup -> + def id = tup[0] + def state = tup[1] + def unfilteredState = fun(id, state) + def newState = unfilteredState.findAll{key, val -> val != null} + [id, newState] + tup.drop(2) + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/workflowFactory/processAuto.nf' +// TODO: unit test processAuto +def processAuto(Map auto) { + // remove null values + auto = auto.findAll{k, v -> v != null} + + // check for unexpected keys + def expectedKeys = ["simplifyInput", "simplifyOutput", "transcript", "publish"] + def unexpectedKeys = auto.keySet() - expectedKeys + assert unexpectedKeys.isEmpty(), "unexpected keys in auto: '${unexpectedKeys.join("', '")}'" + + // check auto.simplifyInput + assert auto.simplifyInput instanceof Boolean, "auto.simplifyInput must be a boolean" + + // check auto.simplifyOutput + assert auto.simplifyOutput instanceof Boolean, "auto.simplifyOutput must be a boolean" + + // check auto.transcript + assert auto.transcript instanceof Boolean, "auto.transcript must be a boolean" + + // check auto.publish + assert auto.publish instanceof Boolean || auto.publish == "state", "auto.publish must be a boolean or 'state'" + + return auto.subMap(expectedKeys) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/workflowFactory/processDirectives.nf' +def assertMapKeys(map, expectedKeys, requiredKeys, mapName) { + assert map instanceof Map : "Expected argument '$mapName' to be a Map. Found: class ${map.getClass()}" + map.forEach { key, val -> + assert key in expectedKeys : "Unexpected key '$key' in ${mapName ? mapName + " " : ""}map" + } + requiredKeys.forEach { requiredKey -> + assert map.containsKey(requiredKey) : "Missing required key '$key' in ${mapName ? mapName + " " : ""}map" + } +} + +// TODO: unit test processDirectives +def processDirectives(Map drctv) { + // remove null values + drctv = drctv.findAll{k, v -> v != null} + + // check for unexpected keys + def expectedKeys = [ + "accelerator", "afterScript", "beforeScript", "cache", "conda", "container", "containerOptions", "cpus", "disk", "echo", "errorStrategy", "executor", "machineType", "maxErrors", "maxForks", "maxRetries", "memory", "module", "penv", "pod", "publishDir", "queue", "label", "scratch", "storeDir", "stageInMode", "stageOutMode", "tag", "time" + ] + def unexpectedKeys = drctv.keySet() - expectedKeys + assert unexpectedKeys.isEmpty() : "Unexpected keys in process directive: '${unexpectedKeys.join("', '")}'" + + /* DIRECTIVE accelerator + accepted examples: + - [ limit: 4, type: "nvidia-tesla-k80" ] + */ + if (drctv.containsKey("accelerator")) { + assertMapKeys(drctv["accelerator"], ["type", "limit", "request", "runtime"], [], "accelerator") + } + + /* DIRECTIVE afterScript + accepted examples: + - "source /cluster/bin/cleanup" + */ + if (drctv.containsKey("afterScript")) { + assert drctv["afterScript"] instanceof CharSequence + } + + /* DIRECTIVE beforeScript + accepted examples: + - "source /cluster/bin/setup" + */ + if (drctv.containsKey("beforeScript")) { + assert drctv["beforeScript"] instanceof CharSequence + } + + /* DIRECTIVE cache + accepted examples: + - true + - false + - "deep" + - "lenient" + */ + if (drctv.containsKey("cache")) { + assert drctv["cache"] instanceof CharSequence || drctv["cache"] instanceof Boolean + if (drctv["cache"] instanceof CharSequence) { + assert drctv["cache"] in ["deep", "lenient"] : "Unexpected value for cache" + } + } + + /* DIRECTIVE conda + accepted examples: + - "bwa=0.7.15" + - "bwa=0.7.15 fastqc=0.11.5" + - ["bwa=0.7.15", "fastqc=0.11.5"] + */ + if (drctv.containsKey("conda")) { + if (drctv["conda"] instanceof List) { + drctv["conda"] = drctv["conda"].join(" ") + } + assert drctv["conda"] instanceof CharSequence + } + + /* DIRECTIVE container + accepted examples: + - "foo/bar:tag" + - [ registry: "reg", image: "im", tag: "ta" ] + is transformed to "reg/im:ta" + - [ image: "im" ] + is transformed to "im:latest" + */ + if (drctv.containsKey("container")) { + assert drctv["container"] instanceof Map || drctv["container"] instanceof CharSequence + if (drctv["container"] instanceof Map) { + def m = drctv["container"] + assertMapKeys(m, [ "registry", "image", "tag" ], ["image"], "container") + def part1 = + System.getenv('OVERRIDE_CONTAINER_REGISTRY') ? System.getenv('OVERRIDE_CONTAINER_REGISTRY') + "/" : + params.containsKey("override_container_registry") ? params["override_container_registry"] + "/" : // todo: remove? + m.registry ? m.registry + "/" : + "" + def part2 = m.image + def part3 = m.tag ? ":" + m.tag : ":latest" + drctv["container"] = part1 + part2 + part3 + } + } + + /* DIRECTIVE containerOptions + accepted examples: + - "--foo bar" + - ["--foo bar", "-f b"] + */ + if (drctv.containsKey("containerOptions")) { + if (drctv["containerOptions"] instanceof List) { + drctv["containerOptions"] = drctv["containerOptions"].join(" ") + } + assert drctv["containerOptions"] instanceof CharSequence + } + + /* DIRECTIVE cpus + accepted examples: + - 1 + - 10 + */ + if (drctv.containsKey("cpus")) { + assert drctv["cpus"] instanceof Integer + } + + /* DIRECTIVE disk + accepted examples: + - "1 GB" + - "2TB" + - "3.2KB" + - "10.B" + */ + if (drctv.containsKey("disk")) { + assert drctv["disk"] instanceof CharSequence + // assert drctv["disk"].matches("[0-9]+(\\.[0-9]*)? *[KMGTPEZY]?B") + // ^ does not allow closures + } + + /* DIRECTIVE echo + accepted examples: + - true + - false + */ + if (drctv.containsKey("echo")) { + assert drctv["echo"] instanceof Boolean + } + + /* DIRECTIVE errorStrategy + accepted examples: + - "terminate" + - "finish" + */ + if (drctv.containsKey("errorStrategy")) { + assert drctv["errorStrategy"] instanceof CharSequence + assert drctv["errorStrategy"] in ["terminate", "finish", "ignore", "retry"] : "Unexpected value for errorStrategy" + } + + /* DIRECTIVE executor + accepted examples: + - "local" + - "sge" + */ + if (drctv.containsKey("executor")) { + assert drctv["executor"] instanceof CharSequence + assert drctv["executor"] in ["local", "sge", "uge", "lsf", "slurm", "pbs", "pbspro", "moab", "condor", "nqsii", "ignite", "k8s", "awsbatch", "google-pipelines"] : "Unexpected value for executor" + } + + /* DIRECTIVE machineType + accepted examples: + - "n1-highmem-8" + */ + if (drctv.containsKey("machineType")) { + assert drctv["machineType"] instanceof CharSequence + } + + /* DIRECTIVE maxErrors + accepted examples: + - 1 + - 3 + */ + if (drctv.containsKey("maxErrors")) { + assert drctv["maxErrors"] instanceof Integer + } + + /* DIRECTIVE maxForks + accepted examples: + - 1 + - 3 + */ + if (drctv.containsKey("maxForks")) { + assert drctv["maxForks"] instanceof Integer + } + + /* DIRECTIVE maxRetries + accepted examples: + - 1 + - 3 + */ + if (drctv.containsKey("maxRetries")) { + assert drctv["maxRetries"] instanceof Integer + } + + /* DIRECTIVE memory + accepted examples: + - "1 GB" + - "2TB" + - "3.2KB" + - "10.B" + */ + if (drctv.containsKey("memory")) { + assert drctv["memory"] instanceof CharSequence + // assert drctv["memory"].matches("[0-9]+(\\.[0-9]*)? *[KMGTPEZY]?B") + // ^ does not allow closures + } + + /* DIRECTIVE module + accepted examples: + - "ncbi-blast/2.2.27" + - "ncbi-blast/2.2.27:t_coffee/10.0" + - ["ncbi-blast/2.2.27", "t_coffee/10.0"] + */ + if (drctv.containsKey("module")) { + if (drctv["module"] instanceof List) { + drctv["module"] = drctv["module"].join(":") + } + assert drctv["module"] instanceof CharSequence + } + + /* DIRECTIVE penv + accepted examples: + - "smp" + */ + if (drctv.containsKey("penv")) { + assert drctv["penv"] instanceof CharSequence + } + + /* DIRECTIVE pod + accepted examples: + - [ label: "key", value: "val" ] + - [ annotation: "key", value: "val" ] + - [ env: "key", value: "val" ] + - [ [label: "l", value: "v"], [env: "e", value: "v"]] + */ + if (drctv.containsKey("pod")) { + if (drctv["pod"] instanceof Map) { + drctv["pod"] = [ drctv["pod"] ] + } + assert drctv["pod"] instanceof List + drctv["pod"].forEach { pod -> + assert pod instanceof Map + // TODO: should more checks be added? + // See https://www.nextflow.io/docs/latest/process.html?highlight=directives#pod + // e.g. does it contain 'label' and 'value', or 'annotation' and 'value', or ...? + } + } + + /* DIRECTIVE publishDir + accepted examples: + - [] + - [ [ path: "foo", enabled: true ], [ path: "bar", enabled: false ] ] + - "/path/to/dir" + is transformed to [[ path: "/path/to/dir" ]] + - [ path: "/path/to/dir", mode: "cache" ] + is transformed to [[ path: "/path/to/dir", mode: "cache" ]] + */ + // TODO: should we also look at params["publishDir"]? + if (drctv.containsKey("publishDir")) { + def pblsh = drctv["publishDir"] + + // check different options + assert pblsh instanceof List || pblsh instanceof Map || pblsh instanceof CharSequence + + // turn into list if not already so + // for some reason, 'if (!pblsh instanceof List) pblsh = [ pblsh ]' doesn't work. + pblsh = pblsh instanceof List ? pblsh : [ pblsh ] + + // check elements of publishDir + pblsh = pblsh.collect{ elem -> + // turn into map if not already so + elem = elem instanceof CharSequence ? [ path: elem ] : elem + + // check types and keys + assert elem instanceof Map : "Expected publish argument '$elem' to be a String or a Map. Found: class ${elem.getClass()}" + assertMapKeys(elem, [ "path", "mode", "overwrite", "pattern", "saveAs", "enabled" ], ["path"], "publishDir") + + // check elements in map + assert elem.containsKey("path") + assert elem["path"] instanceof CharSequence + if (elem.containsKey("mode")) { + assert elem["mode"] instanceof CharSequence + assert elem["mode"] in [ "symlink", "rellink", "link", "copy", "copyNoFollow", "move" ] + } + if (elem.containsKey("overwrite")) { + assert elem["overwrite"] instanceof Boolean + } + if (elem.containsKey("pattern")) { + assert elem["pattern"] instanceof CharSequence + } + if (elem.containsKey("saveAs")) { + assert elem["saveAs"] instanceof CharSequence //: "saveAs as a Closure is currently not supported. Surround your closure with single quotes to get the desired effect. Example: '\{ foo \}'" + } + if (elem.containsKey("enabled")) { + assert elem["enabled"] instanceof Boolean + } + + // return final result + elem + } + // store final directive + drctv["publishDir"] = pblsh + } + + /* DIRECTIVE queue + accepted examples: + - "long" + - "short,long" + - ["short", "long"] + */ + if (drctv.containsKey("queue")) { + if (drctv["queue"] instanceof List) { + drctv["queue"] = drctv["queue"].join(",") + } + assert drctv["queue"] instanceof CharSequence + } + + /* DIRECTIVE label + accepted examples: + - "big_mem" + - "big_cpu" + - ["big_mem", "big_cpu"] + */ + if (drctv.containsKey("label")) { + if (drctv["label"] instanceof CharSequence) { + drctv["label"] = [ drctv["label"] ] + } + assert drctv["label"] instanceof List + drctv["label"].forEach { label -> + assert label instanceof CharSequence + // assert label.matches("[a-zA-Z0-9]([a-zA-Z0-9_]*[a-zA-Z0-9])?") + // ^ does not allow closures + } + } + + /* DIRECTIVE scratch + accepted examples: + - true + - "/path/to/scratch" + - '$MY_PATH_TO_SCRATCH' + - "ram-disk" + */ + if (drctv.containsKey("scratch")) { + assert drctv["scratch"] == true || drctv["scratch"] instanceof CharSequence + } + + /* DIRECTIVE storeDir + accepted examples: + - "/path/to/storeDir" + */ + if (drctv.containsKey("storeDir")) { + assert drctv["storeDir"] instanceof CharSequence + } + + /* DIRECTIVE stageInMode + accepted examples: + - "copy" + - "link" + */ + if (drctv.containsKey("stageInMode")) { + assert drctv["stageInMode"] instanceof CharSequence + assert drctv["stageInMode"] in ["copy", "link", "symlink", "rellink"] + } + + /* DIRECTIVE stageOutMode + accepted examples: + - "copy" + - "link" + */ + if (drctv.containsKey("stageOutMode")) { + assert drctv["stageOutMode"] instanceof CharSequence + assert drctv["stageOutMode"] in ["copy", "move", "rsync"] + } + + /* DIRECTIVE tag + accepted examples: + - "foo" + - '$id' + */ + if (drctv.containsKey("tag")) { + assert drctv["tag"] instanceof CharSequence + } + + /* DIRECTIVE time + accepted examples: + - "1h" + - "2days" + - "1day 6hours 3minutes 30seconds" + */ + if (drctv.containsKey("time")) { + assert drctv["time"] instanceof CharSequence + // todo: validation regex? + } + + return drctv +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/workflowFactory/processWorkflowArgs.nf' +def processWorkflowArgs(Map args, Map defaultWfArgs, Map meta) { + // override defaults with args + def workflowArgs = defaultWfArgs + args + + // check whether 'key' exists + assert workflowArgs.containsKey("key") : "Error in module '${meta.config.name}': key is a required argument" + + // if 'key' is a closure, apply it to the original key + if (workflowArgs["key"] instanceof Closure) { + workflowArgs["key"] = workflowArgs["key"](meta.config.name) + } + def key = workflowArgs["key"] + assert key instanceof CharSequence : "Expected process argument 'key' to be a String. Found: class ${key.getClass()}" + assert key ==~ /^[a-zA-Z_]\w*$/ : "Error in module '$key': Expected process argument 'key' to consist of only letters, digits or underscores. Found: ${key}" + + // check for any unexpected keys + def expectedKeys = ["key", "directives", "auto", "map", "mapId", "mapData", "mapPassthrough", "filter", "runIf", "fromState", "toState", "args", "renameKeys", "debug"] + def unexpectedKeys = workflowArgs.keySet() - expectedKeys + assert unexpectedKeys.isEmpty() : "Error in module '$key': unexpected arguments to the '.run()' function: '${unexpectedKeys.join("', '")}'" + + // check whether directives exists and apply defaults + assert workflowArgs.containsKey("directives") : "Error in module '$key': directives is a required argument" + assert workflowArgs["directives"] instanceof Map : "Error in module '$key': Expected process argument 'directives' to be a Map. Found: class ${workflowArgs['directives'].getClass()}" + workflowArgs["directives"] = processDirectives(defaultWfArgs.directives + workflowArgs["directives"]) + + // check whether directives exists and apply defaults + assert workflowArgs.containsKey("auto") : "Error in module '$key': auto is a required argument" + assert workflowArgs["auto"] instanceof Map : "Error in module '$key': Expected process argument 'auto' to be a Map. Found: class ${workflowArgs['auto'].getClass()}" + workflowArgs["auto"] = processAuto(defaultWfArgs.auto + workflowArgs["auto"]) + + // auto define publish, if so desired + if (workflowArgs.auto.publish == true && (workflowArgs.directives.publishDir != null ? workflowArgs.directives.publishDir : [:]).isEmpty()) { + // can't assert at this level thanks to the no_publish profile + // assert params.containsKey("publishDir") || params.containsKey("publish_dir") : + // "Error in module '${workflowArgs['key']}': if auto.publish is true, params.publish_dir needs to be defined.\n" + + // " Example: params.publish_dir = \"./output/\"" + def publishDir = getPublishDir() + + if (publishDir != null) { + workflowArgs.directives.publishDir = [[ + path: publishDir, + saveAs: "{ it.startsWith('.') ? null : it }", // don't publish hidden files, by default + mode: "copy" + ]] + } + } + + // auto define transcript, if so desired + if (workflowArgs.auto.transcript == true) { + // can't assert at this level thanks to the no_publish profile + // assert params.containsKey("transcriptsDir") || params.containsKey("transcripts_dir") || params.containsKey("publishDir") || params.containsKey("publish_dir") : + // "Error in module '${workflowArgs['key']}': if auto.transcript is true, either params.transcripts_dir or params.publish_dir needs to be defined.\n" + + // " Example: params.transcripts_dir = \"./transcripts/\"" + def transcriptsDir = + params.containsKey("transcripts_dir") ? params.transcripts_dir : + params.containsKey("transcriptsDir") ? params.transcriptsDir : + params.containsKey("publish_dir") ? params.publish_dir + "/_transcripts" : + params.containsKey("publishDir") ? params.publishDir + "/_transcripts" : + null + if (transcriptsDir != null) { + def timestamp = nextflow.Nextflow.getSession().getWorkflowMetadata().start.format('yyyy-MM-dd_HH-mm-ss') + def transcriptsPublishDir = [ + path: "$transcriptsDir/$timestamp/\${task.process.replaceAll(':', '-')}/\${id}/", + saveAs: "{ it.startsWith('.') ? it.replaceAll('^.', '') : null }", + mode: "copy" + ] + def publishDirs = workflowArgs.directives.publishDir != null ? workflowArgs.directives.publishDir : null ? workflowArgs.directives.publishDir : [] + workflowArgs.directives.publishDir = publishDirs + transcriptsPublishDir + } + } + + // if this is a stubrun, remove certain directives? + if (workflow.stubRun) { + workflowArgs.directives.keySet().removeAll(["publishDir", "cpus", "memory", "label"]) + } + + for (nam in ["map", "mapId", "mapData", "mapPassthrough", "filter", "runIf"]) { + if (workflowArgs.containsKey(nam) && workflowArgs[nam]) { + assert workflowArgs[nam] instanceof Closure : "Error in module '$key': Expected process argument '$nam' to be null or a Closure. Found: class ${workflowArgs[nam].getClass()}" + } + } + + // TODO: should functions like 'map', 'mapId', 'mapData', 'mapPassthrough' be deprecated as well? + for (nam in ["map", "mapData", "mapPassthrough", "renameKeys"]) { + if (workflowArgs.containsKey(nam) && workflowArgs[nam] != null) { + log.warn "module '$key': workflow argument '$nam' is deprecated and will be removed in Viash 0.9.0. Please use 'fromState' and 'toState' instead." + } + } + + // check fromState + workflowArgs["fromState"] = _processFromState(workflowArgs.get("fromState"), key, meta.config) + + // check toState + workflowArgs["toState"] = _processToState(workflowArgs.get("toState"), key, meta.config) + + // return output + return workflowArgs +} + +def _processFromState(fromState, key_, config_) { + assert fromState == null || fromState instanceof Closure || fromState instanceof Map || fromState instanceof List : + "Error in module '$key_': Expected process argument 'fromState' to be null, a Closure, a Map, or a List. Found: class ${fromState.getClass()}" + if (fromState == null) { + return null + } + + // if fromState is a List, convert to map + if (fromState instanceof List) { + // check whether fromstate is a list[string] + assert fromState.every{it instanceof CharSequence} : "Error in module '$key_': fromState is a List, but not all elements are Strings" + fromState = fromState.collectEntries{[it, it]} + } + + // if fromState is a map, convert to closure + if (fromState instanceof Map) { + // check whether fromstate is a map[string, string] + assert fromState.values().every{it instanceof CharSequence} : "Error in module '$key_': fromState is a Map, but not all values are Strings" + assert fromState.keySet().every{it instanceof CharSequence} : "Error in module '$key_': fromState is a Map, but not all keys are Strings" + def fromStateMap = fromState.clone() + def requiredInputNames = meta.config.allArguments.findAll{it.required && it.direction == "Input"}.collect{it.plainName} + // turn the map into a closure to be used later on + fromState = { it -> + def state = it[1] + assert state instanceof Map : "Error in module '$key_': the state is not a Map" + def data = fromStateMap.collectMany{newkey, origkey -> + // check whether newkey corresponds to a required argument + if (state.containsKey(origkey)) { + [[newkey, state[origkey]]] + } else if (!requiredInputNames.contains(origkey)) { + [] + } else { + throw new Exception("Error in module '$key_': fromState key '$origkey' not found in current state") + } + }.collectEntries() + data + } + } + + return fromState +} + +def _processToState(toState, key_, config_) { + if (toState == null) { + toState = { tup -> tup[1] } + } + + // toState should be a closure, map[string, string], or list[string] + assert toState instanceof Closure || toState instanceof Map || toState instanceof List : + "Error in module '$key_': Expected process argument 'toState' to be a Closure, a Map, or a List. Found: class ${toState.getClass()}" + + // if toState is a List, convert to map + if (toState instanceof List) { + // check whether toState is a list[string] + assert toState.every{it instanceof CharSequence} : "Error in module '$key_': toState is a List, but not all elements are Strings" + toState = toState.collectEntries{[it, it]} + } + + // if toState is a map, convert to closure + if (toState instanceof Map) { + // check whether toState is a map[string, string] + assert toState.values().every{it instanceof CharSequence} : "Error in module '$key_': toState is a Map, but not all values are Strings" + assert toState.keySet().every{it instanceof CharSequence} : "Error in module '$key_': toState is a Map, but not all keys are Strings" + def toStateMap = toState.clone() + def requiredOutputNames = config_.allArguments.findAll{it.required && it.direction == "Output"}.collect{it.plainName} + // turn the map into a closure to be used later on + toState = { it -> + def output = it[1] + def state = it[2] + assert output instanceof Map : "Error in module '$key_': the output is not a Map" + assert state instanceof Map : "Error in module '$key_': the state is not a Map" + def extraEntries = toStateMap.collectMany{newkey, origkey -> + // check whether newkey corresponds to a required argument + if (output.containsKey(origkey)) { + [[newkey, output[origkey]]] + } else if (!requiredOutputNames.contains(origkey)) { + [] + } else { + throw new Exception("Error in module '$key_': toState key '$origkey' not found in current output") + } + }.collectEntries() + state + extraEntries + } + } + + return toState +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/workflowFactory/workflowFactory.nf' +def _debug(workflowArgs, debugKey) { + if (workflowArgs.debug) { + view { "process '${workflowArgs.key}' $debugKey tuple: $it" } + } else { + map { it } + } +} + +// depends on: innerWorkflowFactory +def workflowFactory(Map args, Map defaultWfArgs, Map meta) { + def workflowArgs = processWorkflowArgs(args, defaultWfArgs, meta) + def key_ = workflowArgs["key"] + + workflow workflowInstance { + take: input_ + + main: + def chModified = input_ + | checkUniqueIds([:]) + | _debug(workflowArgs, "input") + | map { tuple -> + tuple = deepClone(tuple) + + if (workflowArgs.map) { + tuple = workflowArgs.map(tuple) + } + if (workflowArgs.mapId) { + tuple[0] = workflowArgs.mapId(tuple[0]) + } + if (workflowArgs.mapData) { + tuple[1] = workflowArgs.mapData(tuple[1]) + } + if (workflowArgs.mapPassthrough) { + tuple = tuple.take(2) + workflowArgs.mapPassthrough(tuple.drop(2)) + } + + // check tuple + assert tuple instanceof List : + "Error in module '${key_}': element in channel should be a tuple [id, data, ...otherargs...]\n" + + " Example: [\"id\", [input: file('foo.txt'), arg: 10]].\n" + + " Expected class: List. Found: tuple.getClass() is ${tuple.getClass()}" + assert tuple.size() >= 2 : + "Error in module '${key_}': expected length of tuple in input channel to be two or greater.\n" + + " Example: [\"id\", [input: file('foo.txt'), arg: 10]].\n" + + " Found: tuple.size() == ${tuple.size()}" + + // check id field + if (tuple[0] instanceof GString) { + tuple[0] = tuple[0].toString() + } + assert tuple[0] instanceof CharSequence : + "Error in module '${key_}': first element of tuple in channel should be a String\n" + + " Example: [\"id\", [input: file('foo.txt'), arg: 10]].\n" + + " Found: ${tuple[0]}" + + // match file to input file + if (workflowArgs.auto.simplifyInput && (tuple[1] instanceof Path || tuple[1] instanceof List)) { + def inputFiles = meta.config.allArguments + .findAll { it.type == "file" && it.direction == "input" } + + assert inputFiles.size() == 1 : + "Error in module '${key_}' id '${tuple[0]}'.\n" + + " Anonymous file inputs are only allowed when the process has exactly one file input.\n" + + " Expected: inputFiles.size() == 1. Found: inputFiles.size() is ${inputFiles.size()}" + + tuple[1] = [[ inputFiles[0].plainName, tuple[1] ]].collectEntries() + } + + // check data field + assert tuple[1] instanceof Map : + "Error in module '${key_}' id '${tuple[0]}': second element of tuple in channel should be a Map\n" + + " Example: [\"id\", [input: file('foo.txt'), arg: 10]].\n" + + " Expected class: Map. Found: tuple[1].getClass() is ${tuple[1].getClass()}" + + // rename keys of data field in tuple + if (workflowArgs.renameKeys) { + assert workflowArgs.renameKeys instanceof Map : + "Error renaming data keys in module '${key_}' id '${tuple[0]}'.\n" + + " Example: renameKeys: ['new_key': 'old_key'].\n" + + " Expected class: Map. Found: renameKeys.getClass() is ${workflowArgs.renameKeys.getClass()}" + assert tuple[1] instanceof Map : + "Error renaming data keys in module '${key_}' id '${tuple[0]}'.\n" + + " Expected class: Map. Found: tuple[1].getClass() is ${tuple[1].getClass()}" + + // TODO: allow renameKeys to be a function? + workflowArgs.renameKeys.each { newKey, oldKey -> + assert newKey instanceof CharSequence : + "Error renaming data keys in module '${key_}' id '${tuple[0]}'.\n" + + " Example: renameKeys: ['new_key': 'old_key'].\n" + + " Expected class of newKey: String. Found: newKey.getClass() is ${newKey.getClass()}" + assert oldKey instanceof CharSequence : + "Error renaming data keys in module '${key_}' id '${tuple[0]}'.\n" + + " Example: renameKeys: ['new_key': 'old_key'].\n" + + " Expected class of oldKey: String. Found: oldKey.getClass() is ${oldKey.getClass()}" + assert tuple[1].containsKey(oldKey) : + "Error renaming data keys in module '${key}' id '${tuple[0]}'.\n" + + " Key '$oldKey' is missing in the data map. tuple[1].keySet() is '${tuple[1].keySet()}'" + tuple[1].put(newKey, tuple[1][oldKey]) + } + tuple[1].keySet().removeAll(workflowArgs.renameKeys.collect{ newKey, oldKey -> oldKey }) + } + tuple + } + + def chModifiedFiltered = workflowArgs.filter ? + chModified | filter{workflowArgs.filter(it)} : + chModified + + def chRun = null + def chPassthrough = null + if (workflowArgs.runIf) { + def runIfBranch = chModifiedFiltered.branch{ tup -> + run: workflowArgs.runIf(tup[0], tup[1]) + passthrough: true + } + chRun = runIfBranch.run + chPassthrough = runIfBranch.passthrough + } else { + chRun = chModifiedFiltered + chPassthrough = Channel.empty() + } + + def chArgs = workflowArgs.fromState ? + chRun | map{ + def new_data = workflowArgs.fromState(it.take(2)) + [it[0], new_data] + } : + chRun | map {tup -> tup.take(2)} + + // fill in defaults + def chArgsWithDefaults = chArgs + | map { tuple -> + def id_ = tuple[0] + def data_ = tuple[1] + + // TODO: could move fromState to here + + // fetch default params from functionality + def defaultArgs = meta.config.allArguments + .findAll { it.containsKey("default") } + .collectEntries { [ it.plainName, it.default ] } + + // fetch overrides in params + def paramArgs = meta.config.allArguments + .findAll { par -> + def argKey = key_ + "__" + par.plainName + params.containsKey(argKey) + } + .collectEntries { [ it.plainName, params[key_ + "__" + it.plainName] ] } + + // fetch overrides in data + def dataArgs = meta.config.allArguments + .findAll { data_.containsKey(it.plainName) } + .collectEntries { [ it.plainName, data_[it.plainName] ] } + + // combine params + def combinedArgs = defaultArgs + paramArgs + workflowArgs.args + dataArgs + + // remove arguments with explicit null values + combinedArgs + .removeAll{_, val -> val == null || val == "viash_no_value" || val == "force_null"} + + combinedArgs = _processInputValues(combinedArgs, meta.config, id_, key_) + + [id_, combinedArgs] + tuple.drop(2) + } + + // TODO: move some of the _meta.join_id wrangling to the safeJoin() function. + def chInitialOutput = chArgsWithDefaults + | _debug(workflowArgs, "processed") + // run workflow + | innerWorkflowFactory(workflowArgs) + // check output tuple + | map { id_, output_ -> + + // see if output map contains metadata + def meta_ = + output_ instanceof Map && output_.containsKey("_meta") ? + output_["_meta"] : + [:] + def join_id = meta_.join_id ?: id_ + + // remove metadata + output_ = output_.findAll{k, v -> k != "_meta"} + + // check value types + output_ = _processOutputValues(output_, meta.config, id_, key_) + + // simplify output if need be + if (workflowArgs.auto.simplifyOutput && output_.size() == 1) { + output_ = output_.values()[0] + } + + [join_id, id_, output_] + } + // | view{"chInitialOutput: ${it.take(3)}"} + + // join the output [prev_id, new_id, output] with the previous state [prev_id, state, ...] + def chNewState = safeJoin(chInitialOutput, chModifiedFiltered, key_) + // input tuple format: [join_id, id, output, prev_state, ...] + // output tuple format: [join_id, id, new_state, ...] + | map{ tup -> + def new_state = workflowArgs.toState(tup.drop(1).take(3)) + tup.take(2) + [new_state] + tup.drop(4) + } + + if (workflowArgs.auto.publish == "state") { + def chPublish = chNewState + // input tuple format: [join_id, id, new_state, ...] + // output tuple format: [join_id, id, new_state] + | map{ tup -> + tup.take(3) + } + + safeJoin(chPublish, chArgsWithDefaults, key_) + // input tuple format: [join_id, id, new_state, orig_state, ...] + // output tuple format: [id, new_state, orig_state] + | map { tup -> + tup.drop(1).take(3) + } + | publishStatesByConfig(key: key_, config: meta.config) + } + + // remove join_id and meta + chReturn = chNewState + | map { tup -> + // input tuple format: [join_id, id, new_state, ...] + // output tuple format: [id, new_state, ...] + tup.drop(1) + } + | _debug(workflowArgs, "output") + | concat(chPassthrough) + + emit: chReturn + } + + def wf = workflowInstance.cloneWithName(key_) + + // add factory function + wf.metaClass.run = { runArgs -> + workflowFactory(runArgs, workflowArgs, meta) + } + // add config to module for later introspection + wf.metaClass.config = meta.config + + return wf +} + +nextflow.enable.dsl=2 + +// START COMPONENT-SPECIFIC CODE + +// create meta object +meta = [ + "resources_dir": moduleDir.toRealPath().normalize(), + "config": processConfig(readJsonBlob('''{ + "name" : "agat_convert_embl2gff", + "namespace" : "agat", + "version" : "main", + "authors" : [ + { + "name" : "Leïla Paquay", + "roles" : [ + "author", + "maintainer" + ], + "info" : { + "links" : { + "email" : "leila@data-intuitive.com", + "github" : "Leila011", + "linkedin" : "leilapaquay" + }, + "organizations" : [ + { + "name" : "Data Intuitive", + "href" : "https://www.data-intuitive.com", + "role" : "Software Developer" + } + ] + } + } + ], + "argument_groups" : [ + { + "name" : "Inputs", + "arguments" : [ + { + "type" : "file", + "name" : "--embl", + "description" : "Input EMBL file that will be read.", + "example" : [ + "input.embl" + ], + "must_exist" : true, + "create_parent" : true, + "required" : true, + "direction" : "input", + "multiple" : false, + "multiple_sep" : ";" + } + ] + }, + { + "name" : "Outputs", + "arguments" : [ + { + "type" : "file", + "name" : "--output", + "alternatives" : [ + "-o", + "--out", + "--outfile", + "--gff" + ], + "description" : "Output GFF file. If no output file is specified, the output will be written to STDOUT.", + "example" : [ + "output.gff" + ], + "must_exist" : true, + "create_parent" : true, + "required" : false, + "direction" : "output", + "multiple" : false, + "multiple_sep" : ";" + } + ] + }, + { + "name" : "Arguments", + "arguments" : [ + { + "type" : "boolean_true", + "name" : "--emblmygff3", + "description" : "Means that the EMBL flat file comes from the EMBLmyGFF3 software. This is an EMBL format dedicated for submission and contains particularity to deal with. This parameter is needed to get a proper sequence id in the GFF3 from an embl made with EMBLmyGFF3.\n", + "direction" : "input" + }, + { + "type" : "string", + "name" : "--primary_tag", + "alternatives" : [ + "--pt", + "-t" + ], + "description" : "List of \\"primary tag\\". Useful to discard or keep specific features. Multiple tags must be comma-separated.\n", + "example" : [ + "tag1", + "tag2" + ], + "required" : false, + "direction" : "input", + "multiple" : true, + "multiple_sep" : ";" + }, + { + "type" : "boolean_true", + "name" : "--discard", + "alternatives" : [ + "-d" + ], + "description" : "Means that primary tags provided by the option \\"primary_tag\\" will be discarded.\n", + "direction" : "input" + }, + { + "type" : "boolean_true", + "name" : "--keep", + "alternatives" : [ + "-k" + ], + "description" : "Means that only primary tags provided by the option \\"primary_tag\\" will be kept.\n", + "direction" : "input" + }, + { + "type" : "file", + "name" : "--config", + "alternatives" : [ + "-c" + ], + "description" : "Input agat config file. By default AGAT takes as input agat_config.yaml file from the working directory if any, otherwise it takes the original agat_config.yaml shipped with AGAT. To get the agat_config.yaml locally type: \\"agat config --expose\\". The --config option gives you the possibility to use your own AGAT config file (located elsewhere or named differently).\n", + "example" : [ + "custom_agat_config.yaml" + ], + "must_exist" : true, + "create_parent" : true, + "required" : false, + "direction" : "input", + "multiple" : false, + "multiple_sep" : ";" + } + ] + } + ], + "resources" : [ + { + "type" : "bash_script", + "path" : "script.sh", + "is_executable" : true + } + ], + "description" : "The script takes an EMBL file as input, and will translate it in gff format.\n", + "test_resources" : [ + { + "type" : "bash_script", + "path" : "test.sh", + "is_executable" : true + }, + { + "type" : "file", + "path" : "test_data" + } + ], + "status" : "enabled", + "requirements" : { + "commands" : [ + "ps" + ] + }, + "keywords" : [ + "gene annotations", + "GFF conversion" + ], + "license" : "GPL-3.0", + "references" : { + "doi" : [ + "10.5281/zenodo.3552717" + ] + }, + "links" : { + "repository" : "https://github.com/NBISweden/AGAT", + "homepage" : "https://github.com/NBISweden/AGAT", + "documentation" : "https://agat.readthedocs.io/en/latest/tools/agat_convert_embl2gff.html", + "issue_tracker" : "https://github.com/NBISweden/AGAT/issues" + }, + "runners" : [ + { + "type" : "executable", + "id" : "executable", + "docker_setup_strategy" : "ifneedbepullelsecachedbuild" + }, + { + "type" : "nextflow", + "id" : "nextflow", + "directives" : { + "tag" : "$id" + }, + "auto" : { + "simplifyInput" : true, + "simplifyOutput" : false, + "transcript" : false, + "publish" : false + }, + "config" : { + "labels" : { + "mem1gb" : "memory = 1000000000.B", + "mem2gb" : "memory = 2000000000.B", + "mem5gb" : "memory = 5000000000.B", + "mem10gb" : "memory = 10000000000.B", + "mem20gb" : "memory = 20000000000.B", + "mem50gb" : "memory = 50000000000.B", + "mem100gb" : "memory = 100000000000.B", + "mem200gb" : "memory = 200000000000.B", + "mem500gb" : "memory = 500000000000.B", + "mem1tb" : "memory = 1000000000000.B", + "mem2tb" : "memory = 2000000000000.B", + "mem5tb" : "memory = 5000000000000.B", + "mem10tb" : "memory = 10000000000000.B", + "mem20tb" : "memory = 20000000000000.B", + "mem50tb" : "memory = 50000000000000.B", + "mem100tb" : "memory = 100000000000000.B", + "mem200tb" : "memory = 200000000000000.B", + "mem500tb" : "memory = 500000000000000.B", + "mem1gib" : "memory = 1073741824.B", + "mem2gib" : "memory = 2147483648.B", + "mem4gib" : "memory = 4294967296.B", + "mem8gib" : "memory = 8589934592.B", + "mem16gib" : "memory = 17179869184.B", + "mem32gib" : "memory = 34359738368.B", + "mem64gib" : "memory = 68719476736.B", + "mem128gib" : "memory = 137438953472.B", + "mem256gib" : "memory = 274877906944.B", + "mem512gib" : "memory = 549755813888.B", + "mem1tib" : "memory = 1099511627776.B", + "mem2tib" : "memory = 2199023255552.B", + "mem4tib" : "memory = 4398046511104.B", + "mem8tib" : "memory = 8796093022208.B", + "mem16tib" : "memory = 17592186044416.B", + "mem32tib" : "memory = 35184372088832.B", + "mem64tib" : "memory = 70368744177664.B", + "mem128tib" : "memory = 140737488355328.B", + "mem256tib" : "memory = 281474976710656.B", + "mem512tib" : "memory = 562949953421312.B", + "cpu1" : "cpus = 1", + "cpu2" : "cpus = 2", + "cpu5" : "cpus = 5", + "cpu10" : "cpus = 10", + "cpu20" : "cpus = 20", + "cpu50" : "cpus = 50", + "cpu100" : "cpus = 100", + "cpu200" : "cpus = 200", + "cpu500" : "cpus = 500", + "cpu1000" : "cpus = 1000" + } + }, + "debug" : false, + "container" : "docker" + } + ], + "engines" : [ + { + "type" : "docker", + "id" : "docker", + "image" : "quay.io/biocontainers/agat:1.4.0--pl5321hdfd78af_0", + "target_registry" : "images.viash-hub.com", + "target_tag" : "main", + "namespace_separator" : "/", + "setup" : [ + { + "type" : "docker", + "run" : [ + "agat --version | sed 's/AGAT\\\\s\\\\(.*\\\\)/agat: \\"\\\\1\\"/' > /var/software_versions.txt\n" + ] + } + ] + }, + { + "type" : "native", + "id" : "native" + } + ], + "build_info" : { + "config" : "/workdir/root/repo/src/agat/agat_convert_embl2gff/config.vsh.yaml", + "runner" : "nextflow", + "engine" : "docker|native", + "output" : "target/nextflow/agat/agat_convert_embl2gff", + "viash_version" : "0.9.0-RC6", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", + "git_remote" : "https://github.com/viash-hub/biobox" + }, + "package_config" : { + "name" : "biobox", + "version" : "main", + "description" : "A collection of bioinformatics tools for working with sequence data.\n", + "viash_version" : "0.9.0-RC6", + "source" : "src", + "target" : "target", + "config_mods" : [ + ".requirements.commands := ['ps']\n", + ".engines += { type: \\"native\\" }", + ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'", + ".engines[.type == 'docker'].target_tag := 'main'" + ], + "keywords" : [ + "bioinformatics", + "modules", + "sequencing" + ], + "license" : "MIT", + "organization" : "vsh", + "links" : { + "repository" : "https://github.com/viash-hub/biobox", + "issue_tracker" : "https://github.com/viash-hub/biobox/issues" + } + } +}''')) +] + +// resolve dependencies dependencies (if any) + + +// inner workflow +// inner workflow hook +def innerWorkflowFactory(args) { + def rawScript = '''set -e +tempscript=".viash_script.sh" +cat > "$tempscript" << VIASHMAIN +#!/bin/bash + +## VIASH START +# The following code has been auto-generated by Viash. +$( if [ ! -z ${VIASH_PAR_EMBL+x} ]; then echo "${VIASH_PAR_EMBL}" | sed "s#'#'\\"'\\"'#g;s#.*#par_embl='&'#" ; else echo "# par_embl="; fi ) +$( if [ ! -z ${VIASH_PAR_OUTPUT+x} ]; then echo "${VIASH_PAR_OUTPUT}" | sed "s#'#'\\"'\\"'#g;s#.*#par_output='&'#" ; else echo "# par_output="; fi ) +$( if [ ! -z ${VIASH_PAR_EMBLMYGFF3+x} ]; then echo "${VIASH_PAR_EMBLMYGFF3}" | sed "s#'#'\\"'\\"'#g;s#.*#par_emblmygff3='&'#" ; else echo "# par_emblmygff3="; fi ) +$( if [ ! -z ${VIASH_PAR_PRIMARY_TAG+x} ]; then echo "${VIASH_PAR_PRIMARY_TAG}" | sed "s#'#'\\"'\\"'#g;s#.*#par_primary_tag='&'#" ; else echo "# par_primary_tag="; fi ) +$( if [ ! -z ${VIASH_PAR_DISCARD+x} ]; then echo "${VIASH_PAR_DISCARD}" | sed "s#'#'\\"'\\"'#g;s#.*#par_discard='&'#" ; else echo "# par_discard="; fi ) +$( if [ ! -z ${VIASH_PAR_KEEP+x} ]; then echo "${VIASH_PAR_KEEP}" | sed "s#'#'\\"'\\"'#g;s#.*#par_keep='&'#" ; else echo "# par_keep="; fi ) +$( if [ ! -z ${VIASH_PAR_CONFIG+x} ]; then echo "${VIASH_PAR_CONFIG}" | sed "s#'#'\\"'\\"'#g;s#.*#par_config='&'#" ; else echo "# par_config="; fi ) +$( if [ ! -z ${VIASH_META_NAME+x} ]; then echo "${VIASH_META_NAME}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_name='&'#" ; else echo "# meta_name="; fi ) +$( if [ ! -z ${VIASH_META_FUNCTIONALITY_NAME+x} ]; then echo "${VIASH_META_FUNCTIONALITY_NAME}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_functionality_name='&'#" ; else echo "# meta_functionality_name="; fi ) +$( if [ ! -z ${VIASH_META_RESOURCES_DIR+x} ]; then echo "${VIASH_META_RESOURCES_DIR}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_resources_dir='&'#" ; else echo "# meta_resources_dir="; fi ) +$( if [ ! -z ${VIASH_META_EXECUTABLE+x} ]; then echo "${VIASH_META_EXECUTABLE}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_executable='&'#" ; else echo "# meta_executable="; fi ) +$( if [ ! -z ${VIASH_META_CONFIG+x} ]; then echo "${VIASH_META_CONFIG}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_config='&'#" ; else echo "# meta_config="; fi ) +$( if [ ! -z ${VIASH_META_TEMP_DIR+x} ]; then echo "${VIASH_META_TEMP_DIR}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_temp_dir='&'#" ; else echo "# meta_temp_dir="; fi ) +$( if [ ! -z ${VIASH_META_CPUS+x} ]; then echo "${VIASH_META_CPUS}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_cpus='&'#" ; else echo "# meta_cpus="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_B+x} ]; then echo "${VIASH_META_MEMORY_B}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_b='&'#" ; else echo "# meta_memory_b="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_KB+x} ]; then echo "${VIASH_META_MEMORY_KB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_kb='&'#" ; else echo "# meta_memory_kb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_MB+x} ]; then echo "${VIASH_META_MEMORY_MB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_mb='&'#" ; else echo "# meta_memory_mb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_GB+x} ]; then echo "${VIASH_META_MEMORY_GB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_gb='&'#" ; else echo "# meta_memory_gb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_TB+x} ]; then echo "${VIASH_META_MEMORY_TB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_tb='&'#" ; else echo "# meta_memory_tb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_PB+x} ]; then echo "${VIASH_META_MEMORY_PB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_pb='&'#" ; else echo "# meta_memory_pb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_KIB+x} ]; then echo "${VIASH_META_MEMORY_KIB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_kib='&'#" ; else echo "# meta_memory_kib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_MIB+x} ]; then echo "${VIASH_META_MEMORY_MIB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_mib='&'#" ; else echo "# meta_memory_mib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_GIB+x} ]; then echo "${VIASH_META_MEMORY_GIB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_gib='&'#" ; else echo "# meta_memory_gib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_TIB+x} ]; then echo "${VIASH_META_MEMORY_TIB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_tib='&'#" ; else echo "# meta_memory_tib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_pib='&'#" ; else echo "# meta_memory_pib="; fi ) + +## VIASH END + + +# unset flags +[[ "\\$par_emblmygff3" == "false" ]] && unset par_emblmygff3 +[[ "\\$par_discard" == "false" ]] && unset par_discard +[[ "\\$par_keep" == "false" ]] && unset par_keep + +# replace ';' with ',' +par_primary_tag=\\$(echo \\$par_primary_tag | tr ';' ',') + +# run agat_convert_embl2gff +agat_convert_embl2gff.pl \\\\ + --embl "\\$par_embl" \\\\ + -o "\\$par_output" \\\\ + \\${par_emblmygff3:+--emblmygff3} \\\\ + \\${par_primary_tag:+--primary_tag "\\${par_primary_tag}"} \\\\ + \\${par_discard:+-d} \\\\ + \\${par_keep:+-k} \\\\ + \\${par_config:+--config "\\${par_config}"} +VIASHMAIN +bash "$tempscript" +''' + + return vdsl3WorkflowFactory(args, meta, rawScript) +} + + + +/** + * Generate a workflow for VDSL3 modules. + * + * This function is called by the workflowFactory() function. + * + * Input channel: [id, input_map] + * Output channel: [id, output_map] + * + * Internally, this workflow will convert the input channel + * to a format which the Nextflow module will be able to handle. + */ +def vdsl3WorkflowFactory(Map args, Map meta, String rawScript) { + def key = args["key"] + def processObj = null + + workflow processWf { + take: input_ + main: + + if (processObj == null) { + processObj = _vdsl3ProcessFactory(args, meta, rawScript) + } + + output_ = input_ + | map { tuple -> + def id = tuple[0] + def data_ = tuple[1] + + if (workflow.stubRun) { + // add id if missing + data_ = [id: 'stub'] + data_ + } + + // process input files separately + def inputPaths = meta.config.allArguments + .findAll { it.type == "file" && it.direction == "input" } + .collect { par -> + def val = data_.containsKey(par.plainName) ? data_[par.plainName] : [] + def inputFiles = [] + if (val == null) { + inputFiles = [] + } else if (val instanceof List) { + inputFiles = val + } else if (val instanceof Path) { + inputFiles = [ val ] + } else { + inputFiles = [] + } + if (!workflow.stubRun) { + // throw error when an input file doesn't exist + inputFiles.each{ file -> + assert file.exists() : + "Error in module '${key}' id '${id}' argument '${par.plainName}'.\n" + + " Required input file does not exist.\n" + + " Path: '$file'.\n" + + " Expected input file to exist" + } + } + inputFiles + } + + // remove input files + def argsExclInputFiles = meta.config.allArguments + .findAll { (it.type != "file" || it.direction != "input") && data_.containsKey(it.plainName) } + .collectEntries { par -> + def parName = par.plainName + def val = data_[parName] + if (par.multiple && val instanceof Collection) { + val = val.join(par.multiple_sep) + } + if (par.direction == "output" && par.type == "file") { + val = val.replaceAll('\\$id', id).replaceAll('\\$key', key) + } + [parName, val] + } + + [ id ] + inputPaths + [ argsExclInputFiles, meta.resources_dir ] + } + | processObj + | map { output -> + def outputFiles = meta.config.allArguments + .findAll { it.type == "file" && it.direction == "output" } + .indexed() + .collectEntries{ index, par -> + def out = output[index + 1] + // strip dummy '.exitcode' file from output (see nextflow-io/nextflow#2678) + if (!out instanceof List || out.size() <= 1) { + if (par.multiple) { + out = [] + } else { + assert !par.required : + "Error in module '${key}' id '${output[0]}' argument '${par.plainName}'.\n" + + " Required output file is missing" + out = null + } + } else if (out.size() == 2 && !par.multiple) { + out = out[1] + } else { + out = out.drop(1) + } + [ par.plainName, out ] + } + + // drop null outputs + outputFiles.removeAll{it.value == null} + + [ output[0], outputFiles ] + } + emit: output_ + } + + return processWf +} + +// depends on: session? +def _vdsl3ProcessFactory(Map workflowArgs, Map meta, String rawScript) { + // autodetect process key + def wfKey = workflowArgs["key"] + def procKeyPrefix = "${wfKey}_process" + def scriptMeta = nextflow.script.ScriptMeta.current() + def existing = scriptMeta.getProcessNames().findAll{it.startsWith(procKeyPrefix)} + def numbers = existing.collect{it.replace(procKeyPrefix, "0").toInteger()} + def newNumber = (numbers + [-1]).max() + 1 + + def procKey = newNumber == 0 ? procKeyPrefix : "$procKeyPrefix$newNumber" + + if (newNumber > 0) { + log.warn "Key for module '${wfKey}' is duplicated.\n", + "If you run a component multiple times in the same workflow,\n" + + "it's recommended you set a unique key for every call,\n" + + "for example: ${wfKey}.run(key: \"foo\")." + } + + // subset directives and convert to list of tuples + def drctv = workflowArgs.directives + + // TODO: unit test the two commands below + // convert publish array into tags + def valueToStr = { val -> + // ignore closures + if (val instanceof CharSequence) { + if (!val.matches('^[{].*[}]$')) { + '"' + val + '"' + } else { + val + } + } else if (val instanceof List) { + "[" + val.collect{valueToStr(it)}.join(", ") + "]" + } else if (val instanceof Map) { + "[" + val.collect{k, v -> k + ": " + valueToStr(v)}.join(", ") + "]" + } else { + val.inspect() + } + } + + // multiple entries allowed: label, publishdir + def drctvStrs = drctv.collect { key, value -> + if (key in ["label", "publishDir"]) { + value.collect{ val -> + if (val instanceof Map) { + "\n$key " + val.collect{ k, v -> k + ": " + valueToStr(v) }.join(", ") + } else if (val == null) { + "" + } else { + "\n$key " + valueToStr(val) + } + }.join() + } else if (value instanceof Map) { + "\n$key " + value.collect{ k, v -> k + ": " + valueToStr(v) }.join(", ") + } else { + "\n$key " + valueToStr(value) + } + }.join() + + def inputPaths = meta.config.allArguments + .findAll { it.type == "file" && it.direction == "input" } + .collect { ', path(viash_par_' + it.plainName + ', stageAs: "_viash_par/' + it.plainName + '_?/*")' } + .join() + + def outputPaths = meta.config.allArguments + .findAll { it.type == "file" && it.direction == "output" } + .collect { par -> + // insert dummy into every output (see nextflow-io/nextflow#2678) + if (!par.multiple) { + ', path{[".exitcode", args.' + par.plainName + ']}' + } else { + ', path{[".exitcode"] + args.' + par.plainName + '}' + } + } + .join() + + // TODO: move this functionality somewhere else? + if (workflowArgs.auto.transcript) { + outputPaths = outputPaths + ', path{[".exitcode", ".command*"]}' + } else { + outputPaths = outputPaths + ', path{[".exitcode"]}' + } + + // create dirs for output files (based on BashWrapper.createParentFiles) + def createParentStr = meta.config.allArguments + .findAll { it.type == "file" && it.direction == "output" && it.create_parent } + .collect { par -> + "\${ args.containsKey(\"${par.plainName}\") ? \"mkdir_parent \\\"\" + (args[\"${par.plainName}\"] instanceof String ? args[\"${par.plainName}\"] : args[\"${par.plainName}\"].join('\" \"')) + \"\\\"\" : \"\" }" + } + .join("\n") + + // construct inputFileExports + def inputFileExports = meta.config.allArguments + .findAll { it.type == "file" && it.direction.toLowerCase() == "input" } + .collect { par -> + def viash_par_contents = "(viash_par_${par.plainName} instanceof List ? viash_par_${par.plainName}.join(\"${par.multiple_sep}\") : viash_par_${par.plainName})" + "\n\${viash_par_${par.plainName}.empty ? \"\" : \"export VIASH_PAR_${par.plainName.toUpperCase()}=\\\"\" + ${viash_par_contents} + \"\\\"\"}" + } + + // NOTE: if using docker, use /tmp instead of tmpDir! + def tmpDir = java.nio.file.Paths.get( + System.getenv('NXF_TEMP') ?: + System.getenv('VIASH_TEMP') ?: + System.getenv('VIASH_TMPDIR') ?: + System.getenv('VIASH_TEMPDIR') ?: + System.getenv('VIASH_TMP') ?: + System.getenv('TEMP') ?: + System.getenv('TMPDIR') ?: + System.getenv('TEMPDIR') ?: + System.getenv('TMP') ?: + '/tmp' + ).toAbsolutePath() + + // construct stub + def stub = meta.config.allArguments + .findAll { it.type == "file" && it.direction == "output" } + .collect { par -> + "\${ args.containsKey(\"${par.plainName}\") ? \"touch2 \\\"\" + (args[\"${par.plainName}\"] instanceof String ? args[\"${par.plainName}\"].replace(\"_*\", \"_0\") : args[\"${par.plainName}\"].join('\" \"')) + \"\\\"\" : \"\" }" + } + .join("\n") + + // escape script + def escapedScript = rawScript.replace('\\', '\\\\').replace('$', '\\$').replace('"""', '\\"\\"\\"') + + // publishdir assert + def assertStr = (workflowArgs.auto.publish == true) || workflowArgs.auto.transcript ? + """\nassert task.publishDir.size() > 0: "if auto.publish is true, params.publish_dir needs to be defined.\\n Example: --publish_dir './output/'" """ : + "" + + // generate process string + def procStr = + """nextflow.enable.dsl=2 + | + |process $procKey {$drctvStrs + |input: + | tuple val(id)$inputPaths, val(args), path(resourcesDir, stageAs: ".viash_meta_resources") + |output: + | tuple val("\$id")$outputPaths, optional: true + |stub: + |\"\"\" + |touch2() { mkdir -p "\\\$(dirname "\\\$1")" && touch "\\\$1" ; } + |$stub + |\"\"\" + |script:$assertStr + |def escapeText = { s -> s.toString().replaceAll('([`"])', '\\\\\\\\\$1') } + |def parInject = args + | .findAll{key, value -> value != null} + | .collect{key, value -> "export VIASH_PAR_\${key.toUpperCase()}=\\\"\${escapeText(value)}\\\""} + | .join("\\n") + |\"\"\" + |# meta exports + |export VIASH_META_RESOURCES_DIR="\${resourcesDir}" + |export VIASH_META_TEMP_DIR="${['docker', 'podman', 'charliecloud'].any{ it == workflow.containerEngine } ? '/tmp' : tmpDir}" + |export VIASH_META_NAME="${meta.config.name}" + |# export VIASH_META_EXECUTABLE="\\\$VIASH_META_RESOURCES_DIR/\\\$VIASH_META_NAME" + |export VIASH_META_CONFIG="\\\$VIASH_META_RESOURCES_DIR/.config.vsh.yaml" + |\${task.cpus ? "export VIASH_META_CPUS=\$task.cpus" : "" } + |\${task.memory?.bytes != null ? "export VIASH_META_MEMORY_B=\$task.memory.bytes" : "" } + |if [ ! -z \\\${VIASH_META_MEMORY_B+x} ]; then + | export VIASH_META_MEMORY_KB=\\\$(( (\\\$VIASH_META_MEMORY_B+999) / 1000 )) + | export VIASH_META_MEMORY_MB=\\\$(( (\\\$VIASH_META_MEMORY_KB+999) / 1000 )) + | export VIASH_META_MEMORY_GB=\\\$(( (\\\$VIASH_META_MEMORY_MB+999) / 1000 )) + | export VIASH_META_MEMORY_TB=\\\$(( (\\\$VIASH_META_MEMORY_GB+999) / 1000 )) + | export VIASH_META_MEMORY_PB=\\\$(( (\\\$VIASH_META_MEMORY_TB+999) / 1000 )) + | export VIASH_META_MEMORY_KIB=\\\$(( (\\\$VIASH_META_MEMORY_B+1023) / 1024 )) + | export VIASH_META_MEMORY_MIB=\\\$(( (\\\$VIASH_META_MEMORY_KIB+1023) / 1024 )) + | export VIASH_META_MEMORY_GIB=\\\$(( (\\\$VIASH_META_MEMORY_MIB+1023) / 1024 )) + | export VIASH_META_MEMORY_TIB=\\\$(( (\\\$VIASH_META_MEMORY_GIB+1023) / 1024 )) + | export VIASH_META_MEMORY_PIB=\\\$(( (\\\$VIASH_META_MEMORY_TIB+1023) / 1024 )) + |fi + | + |# meta synonyms + |export VIASH_TEMP="\\\$VIASH_META_TEMP_DIR" + |export TEMP_DIR="\\\$VIASH_META_TEMP_DIR" + | + |# create output dirs if need be + |function mkdir_parent { + | for file in "\\\$@"; do + | mkdir -p "\\\$(dirname "\\\$file")" + | done + |} + |$createParentStr + | + |# argument exports${inputFileExports.join()} + |\$parInject + | + |# process script + |${escapedScript} + |\"\"\" + |} + |""".stripMargin() + + // TODO: print on debug + // if (workflowArgs.debug == true) { + // println("######################\n$procStr\n######################") + // } + + // write process to temp file + def tempFile = java.nio.file.Files.createTempFile("viash-process-${procKey}-", ".nf") + addShutdownHook { java.nio.file.Files.deleteIfExists(tempFile) } + tempFile.text = procStr + + // create process from temp file + def binding = new nextflow.script.ScriptBinding([:]) + def session = nextflow.Nextflow.getSession() + def parser = new nextflow.script.ScriptParser(session) + .setModule(true) + .setBinding(binding) + def moduleScript = parser.runScript(tempFile) + .getScript() + + // register module in meta + def module = new nextflow.script.IncludeDef.Module(name: procKey) + scriptMeta.addModule(moduleScript, module.name, module.alias) + + // retrieve and return process from meta + return scriptMeta.getProcess(procKey) +} + +// defaults +meta["defaults"] = [ + // key to be used to trace the process and determine output names + key: null, + + // fixed arguments to be passed to script + args: [:], + + // default directives + directives: readJsonBlob('''{ + "container" : { + "registry" : "images.viash-hub.com", + "image" : "vsh/biobox/agat/agat_convert_embl2gff", + "tag" : "main" + }, + "tag" : "$id" +}'''), + + // auto settings + auto: readJsonBlob('''{ + "simplifyInput" : true, + "simplifyOutput" : false, + "transcript" : false, + "publish" : false +}'''), + + // Apply a map over the incoming tuple + // Example: `{ tup -> [ tup[0], [input: tup[1].output] ] + tup.drop(2) }` + map: null, + + // Apply a map over the ID element of a tuple (i.e. the first element) + // Example: `{ id -> id + "_foo" }` + mapId: null, + + // Apply a map over the data element of a tuple (i.e. the second element) + // Example: `{ data -> [ input: data.output ] }` + mapData: null, + + // Apply a map over the passthrough elements of a tuple (i.e. the tuple excl. the first two elements) + // Example: `{ pt -> pt.drop(1) }` + mapPassthrough: null, + + // Filter the channel + // Example: `{ tup -> tup[0] == "foo" }` + filter: null, + + // Choose whether or not to run the component on the tuple if the condition is true. + // Otherwise, the tuple will be passed through. + // Example: `{ tup -> tup[0] != "skip_this" }` + runIf: null, + + // Rename keys in the data field of the tuple (i.e. the second element) + // Will likely be deprecated in favour of `fromState`. + // Example: `[ "new_key": "old_key" ]` + renameKeys: null, + + // Fetch data from the state and pass it to the module without altering the current state. + // + // `fromState` should be `null`, `List[String]`, `Map[String, String]` or a function. + // + // - If it is `null`, the state will be passed to the module as is. + // - If it is a `List[String]`, the data will be the values of the state at the given keys. + // - If it is a `Map[String, String]`, the data will be the values of the state at the given keys, with the keys renamed according to the map. + // - If it is a function, the tuple (`[id, state]`) in the channel will be passed to the function, and the result will be used as the data. + // + // Example: `{ id, state -> [input: state.fastq_file] }` + // Default: `null` + fromState: null, + + // Determine how the state should be updated after the module has been run. + // + // `toState` should be `null`, `List[String]`, `Map[String, String]` or a function. + // + // - If it is `null`, the state will be replaced with the output of the module. + // - If it is a `List[String]`, the state will be updated with the values of the data at the given keys. + // - If it is a `Map[String, String]`, the state will be updated with the values of the data at the given keys, with the keys renamed according to the map. + // - If it is a function, a tuple (`[id, output, state]`) will be passed to the function, and the result will be used as the new state. + // + // Example: `{ id, output, state -> state + [counts: state.output] }` + // Default: `{ id, output, state -> output }` + toState: null, + + // Whether or not to print debug messages + // Default: `false` + debug: false +] + +// initialise default workflow +meta["workflow"] = workflowFactory([key: meta.config.name], meta.defaults, meta) + +// add workflow to environment +nextflow.script.ScriptMeta.current().addDefinition(meta.workflow) + +// anonymous workflow for running this module as a standalone +workflow { + // add id argument if it's not already in the config + // TODO: deep copy + def newConfig = deepClone(meta.config) + def newParams = deepClone(params) + + def argsContainsId = newConfig.allArguments.any{it.plainName == "id"} + if (!argsContainsId) { + def idArg = [ + 'name': '--id', + 'required': false, + 'type': 'string', + 'description': 'A unique id for every entry.', + 'multiple': false + ] + newConfig.arguments.add(0, idArg) + newConfig = processConfig(newConfig) + } + if (!newParams.containsKey("id")) { + newParams.id = "run" + } + + helpMessage(newConfig) + + channelFromParams(newParams, newConfig) + // make sure id is not in the state if id is not in the args + | map {id, state -> + if (!argsContainsId) { + [id, state.findAll{k, v -> k != "id"}] + } else { + [id, state] + } + } + | meta.workflow.run( + auto: [ publish: "state" ] + ) +} + +// END COMPONENT-SPECIFIC CODE diff --git a/target/nextflow/agat/agat_convert_embl2gff/nextflow.config b/target/nextflow/agat/agat_convert_embl2gff/nextflow.config new file mode 100644 index 00000000..49b9ff4b --- /dev/null +++ b/target/nextflow/agat/agat_convert_embl2gff/nextflow.config @@ -0,0 +1,126 @@ +manifest { + name = 'agat/agat_convert_embl2gff' + mainScript = 'main.nf' + nextflowVersion = '!>=20.12.1-edge' + version = 'main' + description = 'The script takes an EMBL file as input, and will translate it in gff format.\n' + author = 'Leïla Paquay' +} + +process.container = 'nextflow/bash:latest' + +// detect tempdir +tempDir = java.nio.file.Paths.get( + System.getenv('NXF_TEMP') ?: + System.getenv('VIASH_TEMP') ?: + System.getenv('TEMPDIR') ?: + System.getenv('TMPDIR') ?: + '/tmp' +).toAbsolutePath() + +profiles { + no_publish { + process { + withName: '.*' { + publishDir = [ + enabled: false + ] + } + } + } + mount_temp { + docker.temp = tempDir + podman.temp = tempDir + charliecloud.temp = tempDir + } + docker { + docker.enabled = true + // docker.userEmulation = true + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false + } + singularity { + singularity.enabled = true + singularity.autoMounts = true + docker.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false + } + podman { + podman.enabled = true + docker.enabled = false + singularity.enabled = false + shifter.enabled = false + charliecloud.enabled = false + } + shifter { + shifter.enabled = true + docker.enabled = false + singularity.enabled = false + podman.enabled = false + charliecloud.enabled = false + } + charliecloud { + charliecloud.enabled = true + docker.enabled = false + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + } +} + +process{ + withLabel: mem1gb { memory = 1000000000.B } + withLabel: mem2gb { memory = 2000000000.B } + withLabel: mem5gb { memory = 5000000000.B } + withLabel: mem10gb { memory = 10000000000.B } + withLabel: mem20gb { memory = 20000000000.B } + withLabel: mem50gb { memory = 50000000000.B } + withLabel: mem100gb { memory = 100000000000.B } + withLabel: mem200gb { memory = 200000000000.B } + withLabel: mem500gb { memory = 500000000000.B } + withLabel: mem1tb { memory = 1000000000000.B } + withLabel: mem2tb { memory = 2000000000000.B } + withLabel: mem5tb { memory = 5000000000000.B } + withLabel: mem10tb { memory = 10000000000000.B } + withLabel: mem20tb { memory = 20000000000000.B } + withLabel: mem50tb { memory = 50000000000000.B } + withLabel: mem100tb { memory = 100000000000000.B } + withLabel: mem200tb { memory = 200000000000000.B } + withLabel: mem500tb { memory = 500000000000000.B } + withLabel: mem1gib { memory = 1073741824.B } + withLabel: mem2gib { memory = 2147483648.B } + withLabel: mem4gib { memory = 4294967296.B } + withLabel: mem8gib { memory = 8589934592.B } + withLabel: mem16gib { memory = 17179869184.B } + withLabel: mem32gib { memory = 34359738368.B } + withLabel: mem64gib { memory = 68719476736.B } + withLabel: mem128gib { memory = 137438953472.B } + withLabel: mem256gib { memory = 274877906944.B } + withLabel: mem512gib { memory = 549755813888.B } + withLabel: mem1tib { memory = 1099511627776.B } + withLabel: mem2tib { memory = 2199023255552.B } + withLabel: mem4tib { memory = 4398046511104.B } + withLabel: mem8tib { memory = 8796093022208.B } + withLabel: mem16tib { memory = 17592186044416.B } + withLabel: mem32tib { memory = 35184372088832.B } + withLabel: mem64tib { memory = 70368744177664.B } + withLabel: mem128tib { memory = 140737488355328.B } + withLabel: mem256tib { memory = 281474976710656.B } + withLabel: mem512tib { memory = 562949953421312.B } + withLabel: cpu1 { cpus = 1 } + withLabel: cpu2 { cpus = 2 } + withLabel: cpu5 { cpus = 5 } + withLabel: cpu10 { cpus = 10 } + withLabel: cpu20 { cpus = 20 } + withLabel: cpu50 { cpus = 50 } + withLabel: cpu100 { cpus = 100 } + withLabel: cpu200 { cpus = 200 } + withLabel: cpu500 { cpus = 500 } + withLabel: cpu1000 { cpus = 1000 } +} + + diff --git a/target/nextflow/agat/agat_convert_embl2gff/nextflow_schema.json b/target/nextflow/agat/agat_convert_embl2gff/nextflow_schema.json new file mode 100644 index 00000000..c3c2b98f --- /dev/null +++ b/target/nextflow/agat/agat_convert_embl2gff/nextflow_schema.json @@ -0,0 +1,162 @@ +{ +"$schema": "http://json-schema.org/draft-07/schema", +"title": "agat_convert_embl2gff", +"description": "The script takes an EMBL file as input, and will translate it in gff format.\n", +"type": "object", +"definitions": { + + + + "inputs" : { + "title": "Inputs", + "type": "object", + "description": "No description", + "properties": { + + + "embl": { + "type": + "string", + "description": "Type: `file`, required, example: `input.embl`. Input EMBL file that will be read", + "help_text": "Type: `file`, required, example: `input.embl`. Input EMBL file that will be read." + + } + + +} +}, + + + "outputs" : { + "title": "Outputs", + "type": "object", + "description": "No description", + "properties": { + + + "output": { + "type": + "string", + "description": "Type: `file`, default: `$id.$key.output.gff`, example: `output.gff`. Output GFF file", + "help_text": "Type: `file`, default: `$id.$key.output.gff`, example: `output.gff`. Output GFF file. If no output file is specified, the output will be written to STDOUT." + , + "default": "$id.$key.output.gff" + } + + +} +}, + + + "arguments" : { + "title": "Arguments", + "type": "object", + "description": "No description", + "properties": { + + + "emblmygff3": { + "type": + "boolean", + "description": "Type: `boolean_true`, default: `false`. Means that the EMBL flat file comes from the EMBLmyGFF3 software", + "help_text": "Type: `boolean_true`, default: `false`. Means that the EMBL flat file comes from the EMBLmyGFF3 software. This is an EMBL format dedicated for submission and contains particularity to deal with. This parameter is needed to get a proper sequence id in the GFF3 from an embl made with EMBLmyGFF3.\n" + , + "default": "False" + } + + + , + "primary_tag": { + "type": + "string", + "description": "Type: List of `string`, example: `tag1:tag2`, multiple_sep: `\":\"`. List of \"primary tag\"", + "help_text": "Type: List of `string`, example: `tag1:tag2`, multiple_sep: `\":\"`. List of \"primary tag\". Useful to discard or keep specific features. Multiple tags must be comma-separated.\n" + + } + + + , + "discard": { + "type": + "boolean", + "description": "Type: `boolean_true`, default: `false`. Means that primary tags provided by the option \"primary_tag\" will be discarded", + "help_text": "Type: `boolean_true`, default: `false`. Means that primary tags provided by the option \"primary_tag\" will be discarded.\n" + , + "default": "False" + } + + + , + "keep": { + "type": + "boolean", + "description": "Type: `boolean_true`, default: `false`. Means that only primary tags provided by the option \"primary_tag\" will be kept", + "help_text": "Type: `boolean_true`, default: `false`. Means that only primary tags provided by the option \"primary_tag\" will be kept.\n" + , + "default": "False" + } + + + , + "config": { + "type": + "string", + "description": "Type: `file`, example: `custom_agat_config.yaml`. Input agat config file", + "help_text": "Type: `file`, example: `custom_agat_config.yaml`. Input agat config file. By default AGAT takes as input agat_config.yaml file from the working directory if any, otherwise it takes the original agat_config.yaml shipped with AGAT. To get the agat_config.yaml locally type: \"agat config --expose\". The --config option gives you the possibility to use your own AGAT config file (located elsewhere or named differently).\n" + + } + + +} +}, + + + "nextflow input-output arguments" : { + "title": "Nextflow input-output arguments", + "type": "object", + "description": "Input/output parameters for Nextflow itself. Please note that both publishDir and publish_dir are supported but at least one has to be configured.", + "properties": { + + + "publish_dir": { + "type": + "string", + "description": "Type: `string`, required, example: `output/`. Path to an output directory", + "help_text": "Type: `string`, required, example: `output/`. Path to an output directory." + + } + + + , + "param_list": { + "type": + "string", + "description": "Type: `string`, example: `my_params.yaml`. Allows inputting multiple parameter sets to initialise a Nextflow channel", + "help_text": "Type: `string`, example: `my_params.yaml`. Allows inputting multiple parameter sets to initialise a Nextflow channel. A `param_list` can either be a list of maps, a csv file, a json file, a yaml file, or simply a yaml blob.\n\n* A list of maps (as-is) where the keys of each map corresponds to the arguments of the pipeline. Example: in a `nextflow.config` file: `param_list: [ [\u0027id\u0027: \u0027foo\u0027, \u0027input\u0027: \u0027foo.txt\u0027], [\u0027id\u0027: \u0027bar\u0027, \u0027input\u0027: \u0027bar.txt\u0027] ]`.\n* A csv file should have column names which correspond to the different arguments of this pipeline. Example: `--param_list data.csv` with columns `id,input`.\n* A json or a yaml file should be a list of maps, each of which has keys corresponding to the arguments of the pipeline. Example: `--param_list data.json` with contents `[ {\u0027id\u0027: \u0027foo\u0027, \u0027input\u0027: \u0027foo.txt\u0027}, {\u0027id\u0027: \u0027bar\u0027, \u0027input\u0027: \u0027bar.txt\u0027} ]`.\n* A yaml blob can also be passed directly as a string. Example: `--param_list \"[ {\u0027id\u0027: \u0027foo\u0027, \u0027input\u0027: \u0027foo.txt\u0027}, {\u0027id\u0027: \u0027bar\u0027, \u0027input\u0027: \u0027bar.txt\u0027} ]\"`.\n\nWhen passing a csv, json or yaml file, relative path names are relativized to the location of the parameter file. No relativation is performed when `param_list` is a list of maps (as-is) or a yaml blob.", + "hidden": true + + } + + +} +} +}, +"allOf": [ + + { + "$ref": "#/definitions/inputs" + }, + + { + "$ref": "#/definitions/outputs" + }, + + { + "$ref": "#/definitions/arguments" + }, + + { + "$ref": "#/definitions/nextflow input-output arguments" + } +] +} diff --git a/target/nextflow/agat/agat_convert_sp_gff2gtf/.config.vsh.yaml b/target/nextflow/agat/agat_convert_sp_gff2gtf/.config.vsh.yaml index 8f72a88c..e64c6fec 100644 --- a/target/nextflow/agat/agat_convert_sp_gff2gtf/.config.vsh.yaml +++ b/target/nextflow/agat/agat_convert_sp_gff2gtf/.config.vsh.yaml @@ -228,7 +228,7 @@ build_info: output: "target/nextflow/agat/agat_convert_sp_gff2gtf" executable: "target/nextflow/agat/agat_convert_sp_gff2gtf/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/agat/agat_convert_sp_gff2gtf/main.nf b/target/nextflow/agat/agat_convert_sp_gff2gtf/main.nf index cec6415b..0c5de57f 100644 --- a/target/nextflow/agat/agat_convert_sp_gff2gtf/main.nf +++ b/target/nextflow/agat/agat_convert_sp_gff2gtf/main.nf @@ -3042,7 +3042,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/agat/agat_convert_sp_gff2gtf", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { diff --git a/target/nextflow/agat/agat_convert_sp_gff2tsv/.config.vsh.yaml b/target/nextflow/agat/agat_convert_sp_gff2tsv/.config.vsh.yaml new file mode 100644 index 00000000..61bfa22e --- /dev/null +++ b/target/nextflow/agat/agat_convert_sp_gff2tsv/.config.vsh.yaml @@ -0,0 +1,214 @@ +name: "agat_convert_sp_gff2tsv" +namespace: "agat" +version: "main" +authors: +- name: "Leïla Paquay" + roles: + - "author" + - "maintainer" + info: + links: + email: "leila@data-intuitive.com" + github: "Leila011" + linkedin: "leilapaquay" + organizations: + - name: "Data Intuitive" + href: "https://www.data-intuitive.com" + role: "Software Developer" +argument_groups: +- name: "Inputs" + arguments: + - type: "file" + name: "--gff" + alternatives: + - "-f" + description: "Input GTF/GFF file." + info: null + example: + - "input.gff" + must_exist: true + create_parent: true + required: true + direction: "input" + multiple: false + multiple_sep: ";" +- name: "Outputs" + arguments: + - type: "file" + name: "--output" + alternatives: + - "-o" + - "--out" + - "--outfile" + description: "Output GFF file. If no output file is specified, the output will\ + \ be written to STDOUT." + info: null + example: + - "output.gff" + must_exist: true + create_parent: true + required: true + direction: "output" + multiple: false + multiple_sep: ";" +- name: "Arguments" + arguments: + - type: "file" + name: "--config" + alternatives: + - "-c" + description: "String - Input agat config file. By default AGAT takes as input\n\ + agat_config.yaml file from the working directory if any,\notherwise it takes\ + \ the orignal agat_config.yaml shipped with\nAGAT. To get the agat_config.yaml\ + \ locally type: \"agat config\n--expose\". The --config option gives you the\ + \ possibility to use\nyour own AGAT config file (located elsewhere or named\n\ + differently). \n" + info: null + example: + - "custom_agat_config.yaml" + must_exist: true + create_parent: true + required: false + direction: "input" + multiple: false + multiple_sep: ";" +resources: +- type: "bash_script" + path: "script.sh" + is_executable: true +description: "The script aims to convert gtf/gff file into tabulated file. Attribute's\n\ + tags from the 9th column become column titles.\n" +test_resources: +- type: "bash_script" + path: "test.sh" + is_executable: true +- type: "file" + path: "test_data" +info: null +status: "enabled" +requirements: + commands: + - "ps" +keywords: +- "gene annotations" +- "GFF conversion" +license: "GPL-3.0" +references: + doi: + - "10.5281/zenodo.3552717" +links: + repository: "https://github.com/NBISweden/AGAT" + homepage: "https://github.com/NBISweden/AGAT" + documentation: "https://agat.readthedocs.io/en/latest/tools/agat_convert_sp_gff2tsv.html" + issue_tracker: "https://github.com/NBISweden/AGAT/issues" +runners: +- type: "executable" + id: "executable" + docker_setup_strategy: "ifneedbepullelsecachedbuild" +- type: "nextflow" + id: "nextflow" + directives: + tag: "$id" + auto: + simplifyInput: true + simplifyOutput: false + transcript: false + publish: false + config: + labels: + mem1gb: "memory = 1000000000.B" + mem2gb: "memory = 2000000000.B" + mem5gb: "memory = 5000000000.B" + mem10gb: "memory = 10000000000.B" + mem20gb: "memory = 20000000000.B" + mem50gb: "memory = 50000000000.B" + mem100gb: "memory = 100000000000.B" + mem200gb: "memory = 200000000000.B" + mem500gb: "memory = 500000000000.B" + mem1tb: "memory = 1000000000000.B" + mem2tb: "memory = 2000000000000.B" + mem5tb: "memory = 5000000000000.B" + mem10tb: "memory = 10000000000000.B" + mem20tb: "memory = 20000000000000.B" + mem50tb: "memory = 50000000000000.B" + mem100tb: "memory = 100000000000000.B" + mem200tb: "memory = 200000000000000.B" + mem500tb: "memory = 500000000000000.B" + mem1gib: "memory = 1073741824.B" + mem2gib: "memory = 2147483648.B" + mem4gib: "memory = 4294967296.B" + mem8gib: "memory = 8589934592.B" + mem16gib: "memory = 17179869184.B" + mem32gib: "memory = 34359738368.B" + mem64gib: "memory = 68719476736.B" + mem128gib: "memory = 137438953472.B" + mem256gib: "memory = 274877906944.B" + mem512gib: "memory = 549755813888.B" + mem1tib: "memory = 1099511627776.B" + mem2tib: "memory = 2199023255552.B" + mem4tib: "memory = 4398046511104.B" + mem8tib: "memory = 8796093022208.B" + mem16tib: "memory = 17592186044416.B" + mem32tib: "memory = 35184372088832.B" + mem64tib: "memory = 70368744177664.B" + mem128tib: "memory = 140737488355328.B" + mem256tib: "memory = 281474976710656.B" + mem512tib: "memory = 562949953421312.B" + cpu1: "cpus = 1" + cpu2: "cpus = 2" + cpu5: "cpus = 5" + cpu10: "cpus = 10" + cpu20: "cpus = 20" + cpu50: "cpus = 50" + cpu100: "cpus = 100" + cpu200: "cpus = 200" + cpu500: "cpus = 500" + cpu1000: "cpus = 1000" + debug: false + container: "docker" +engines: +- type: "docker" + id: "docker" + image: "quay.io/biocontainers/agat:1.4.0--pl5321hdfd78af_0" + target_registry: "images.viash-hub.com" + target_tag: "main" + namespace_separator: "/" + setup: + - type: "docker" + run: + - "agat --version | sed 's/AGAT\\s\\(.*\\)/agat: \"\\1\"/' > /var/software_versions.txt\n" + entrypoint: [] + cmd: null +- type: "native" + id: "native" +build_info: + config: "src/agat/agat_convert_sp_gff2tsv/config.vsh.yaml" + runner: "nextflow" + engine: "docker|native" + output: "target/nextflow/agat/agat_convert_sp_gff2tsv" + executable: "target/nextflow/agat/agat_convert_sp_gff2tsv/main.nf" + viash_version: "0.9.0-RC6" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" + git_remote: "https://github.com/viash-hub/biobox" +package_config: + name: "biobox" + version: "main" + description: "A collection of bioinformatics tools for working with sequence data.\n" + info: null + viash_version: "0.9.0-RC6" + source: "src" + target: "target" + config_mods: + - ".requirements.commands := ['ps']\n" + - ".engines += { type: \"native\" }" + - ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'" + - ".engines[.type == 'docker'].target_tag := 'main'" + keywords: + - "bioinformatics" + - "modules" + - "sequencing" + license: "MIT" + organization: "vsh" + links: + repository: "https://github.com/viash-hub/biobox" + issue_tracker: "https://github.com/viash-hub/biobox/issues" diff --git a/target/nextflow/agat/agat_convert_sp_gff2tsv/main.nf b/target/nextflow/agat/agat_convert_sp_gff2tsv/main.nf new file mode 100644 index 00000000..6058b608 --- /dev/null +++ b/target/nextflow/agat/agat_convert_sp_gff2tsv/main.nf @@ -0,0 +1,3570 @@ +// agat_convert_sp_gff2tsv main +// +// This wrapper script is auto-generated by viash 0.9.0-RC6 and is thus a +// derivative work thereof. This software comes with ABSOLUTELY NO WARRANTY from +// Data Intuitive. +// +// The component may contain files which fall under a different license. The +// authors of this component should specify the license in the header of such +// files, or include a separate license file detailing the licenses of all included +// files. +// +// Component authors: +// * Leïla Paquay (author, maintainer) + +//////////////////////////// +// VDSL3 helper functions // +//////////////////////////// + +// helper file: 'src/main/resources/io/viash/runners/nextflow/arguments/_checkArgumentType.nf' +class UnexpectedArgumentTypeException extends Exception { + String errorIdentifier + String stage + String plainName + String expectedClass + String foundClass + + // ${key ? " in module '$key'" : ""}${id ? " id '$id'" : ""} + UnexpectedArgumentTypeException(String errorIdentifier, String stage, String plainName, String expectedClass, String foundClass) { + super("Error${errorIdentifier ? " $errorIdentifier" : ""}:${stage ? " $stage" : "" } argument '${plainName}' has the wrong type. " + + "Expected type: ${expectedClass}. Found type: ${foundClass}") + this.errorIdentifier = errorIdentifier + this.stage = stage + this.plainName = plainName + this.expectedClass = expectedClass + this.foundClass = foundClass + } +} + +/** + * Checks if the given value is of the expected type. If not, an exception is thrown. + * + * @param stage The stage of the argument (input or output) + * @param par The parameter definition + * @param value The value to check + * @param errorIdentifier The identifier to use in the error message + * @return The value, if it is of the expected type + * @throws UnexpectedArgumentTypeException If the value is not of the expected type +*/ +def _checkArgumentType(String stage, Map par, Object value, String errorIdentifier) { + // expectedClass will only be != null if value is not of the expected type + def expectedClass = null + def foundClass = null + + // todo: split if need be + + if (!par.required && value == null) { + expectedClass = null + } else if (par.multiple) { + if (value !instanceof Collection) { + value = [value] + } + + // split strings + value = value.collectMany{ val -> + if (val instanceof String) { + // collect() to ensure that the result is a List and not simply an array + val.split(par.multiple_sep).collect() + } else { + [val] + } + } + + // process globs + if (par.type == "file" && par.direction == "input") { + value = value.collect{ it instanceof String ? file(it, hidden: true) : it }.flatten() + } + + // check types of elements in list + try { + value = value.collect { listVal -> + _checkArgumentType(stage, par + [multiple: false], listVal, errorIdentifier) + } + } catch (UnexpectedArgumentTypeException e) { + expectedClass = "List[${e.expectedClass}]" + foundClass = "List[${e.foundClass}]" + } + } else if (par.type == "string") { + // cast to string if need be + if (value instanceof GString) { + value = value.toString() + } + expectedClass = value instanceof String ? null : "String" + } else if (par.type == "integer") { + // cast to integer if need be + if (value instanceof String) { + try { + value = value.toInteger() + } catch (NumberFormatException e) { + // do nothing + } + } + if (value instanceof java.math.BigInteger) { + value = value.intValue() + } + expectedClass = value instanceof Integer ? null : "Integer" + } else if (par.type == "long") { + // cast to long if need be + if (value instanceof String) { + try { + value = value.toLong() + } catch (NumberFormatException e) { + // do nothing + } + } + if (value instanceof Integer) { + value = value.toLong() + } + expectedClass = value instanceof Long ? null : "Long" + } else if (par.type == "double") { + // cast to double if need be + if (value instanceof String) { + try { + value = value.toDouble() + } catch (NumberFormatException e) { + // do nothing + } + } + if (value instanceof java.math.BigDecimal) { + value = value.doubleValue() + } + if (value instanceof Float) { + value = value.toDouble() + } + expectedClass = value instanceof Double ? null : "Double" + } else if (par.type == "boolean" | par.type == "boolean_true" | par.type == "boolean_false") { + // cast to boolean if need be + if (value instanceof String) { + def valueLower = value.toLowerCase() + if (valueLower == "true") { + value = true + } else if (valueLower == "false") { + value = false + } + } + expectedClass = value instanceof Boolean ? null : "Boolean" + } else if (par.type == "file" && (par.direction == "input" || stage == "output")) { + // cast to path if need be + if (value instanceof String) { + value = file(value, hidden: true) + } + if (value instanceof File) { + value = value.toPath() + } + expectedClass = value instanceof Path ? null : "Path" + } else if (par.type == "file" && stage == "input" && par.direction == "output") { + // cast to string if need be + if (value instanceof GString) { + value = value.toString() + } + expectedClass = value instanceof String ? null : "String" + } else { + // didn't find a match for par.type + expectedClass = par.type + } + + if (expectedClass != null) { + if (foundClass == null) { + foundClass = value.getClass().getName() + } + throw new UnexpectedArgumentTypeException(errorIdentifier, stage, par.plainName, expectedClass, foundClass) + } + + return value +} +// helper file: 'src/main/resources/io/viash/runners/nextflow/arguments/_processInputValues.nf' +Map _processInputValues(Map inputs, Map config, String id, String key) { + if (!workflow.stubRun) { + config.allArguments.each { arg -> + if (arg.required) { + assert inputs.containsKey(arg.plainName) && inputs.get(arg.plainName) != null : + "Error in module '${key}' id '${id}': required input argument '${arg.plainName}' is missing" + } + } + + inputs = inputs.collectEntries { name, value -> + def par = config.allArguments.find { it.plainName == name && (it.direction == "input" || it.type == "file") } + assert par != null : "Error in module '${key}' id '${id}': '${name}' is not a valid input argument" + + value = _checkArgumentType("input", par, value, "in module '$key' id '$id'") + + [ name, value ] + } + } + return inputs +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/arguments/_processOutputValues.nf' +Map _processOutputValues(Map outputs, Map config, String id, String key) { + if (!workflow.stubRun) { + config.allArguments.each { arg -> + if (arg.direction == "output" && arg.required) { + assert outputs.containsKey(arg.plainName) && outputs.get(arg.plainName) != null : + "Error in module '${key}' id '${id}': required output argument '${arg.plainName}' is missing" + } + } + + outputs = outputs.collectEntries { name, value -> + def par = config.allArguments.find { it.plainName == name && it.direction == "output" } + assert par != null : "Error in module '${key}' id '${id}': '${name}' is not a valid output argument" + + value = _checkArgumentType("output", par, value, "in module '$key' id '$id'") + + [ name, value ] + } + } + return outputs +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/IDChecker.nf' +class IDChecker { + final def items = [] as Set + + @groovy.transform.WithWriteLock + boolean observe(String item) { + if (items.contains(item)) { + return false + } else { + items << item + return true + } + } + + @groovy.transform.WithReadLock + boolean contains(String item) { + return items.contains(item) + } + + @groovy.transform.WithReadLock + Set getItems() { + return items.clone() + } +} +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/_checkUniqueIds.nf' + +/** + * Check if the ids are unique across parameter sets + * + * @param parameterSets a list of parameter sets. + */ +private void _checkUniqueIds(List>> parameterSets) { + def ppIds = parameterSets.collect{it[0]} + assert ppIds.size() == ppIds.unique().size() : "All argument sets should have unique ids. Detected ids: $ppIds" +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/_getChild.nf' + +// helper functions for reading params from file // +def _getChild(parent, child) { + if (child.contains("://") || java.nio.file.Paths.get(child).isAbsolute()) { + child + } else { + def parentAbsolute = java.nio.file.Paths.get(parent).toAbsolutePath().toString() + parentAbsolute.replaceAll('/[^/]*$', "/") + child + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/_parseParamList.nf' +/** + * Figure out the param list format based on the file extension + * + * @param param_list A String containing the path to the parameter list file. + * + * @return A String containing the format of the parameter list file. + */ +def _paramListGuessFormat(param_list) { + if (param_list !instanceof String) { + "asis" + } else if (param_list.endsWith(".csv")) { + "csv" + } else if (param_list.endsWith(".json") || param_list.endsWith(".jsn")) { + "json" + } else if (param_list.endsWith(".yaml") || param_list.endsWith(".yml")) { + "yaml" + } else { + "yaml_blob" + } +} + + +/** + * Read the param list + * + * @param param_list One of the following: + * - A String containing the path to the parameter list file (csv, json or yaml), + * - A yaml blob of a list of maps (yaml_blob), + * - Or a groovy list of maps (asis). + * @param config A Map of the Viash configuration. + * + * @return A List of Maps containing the parameters. + */ +def _parseParamList(param_list, Map config) { + // first determine format by extension + def paramListFormat = _paramListGuessFormat(param_list) + + def paramListPath = (paramListFormat != "asis" && paramListFormat != "yaml_blob") ? + file(param_list, hidden: true) : + null + + // get the correct parser function for the detected params_list format + def paramSets = [] + if (paramListFormat == "asis") { + paramSets = param_list + } else if (paramListFormat == "yaml_blob") { + paramSets = readYamlBlob(param_list) + } else if (paramListFormat == "yaml") { + paramSets = readYaml(paramListPath) + } else if (paramListFormat == "json") { + paramSets = readJson(paramListPath) + } else if (paramListFormat == "csv") { + paramSets = readCsv(paramListPath) + } else { + error "Format of provided --param_list not recognised.\n" + + "Found: '$paramListFormat'.\n" + + "Expected: a csv file, a json file, a yaml file,\n" + + "a yaml blob or a groovy list of maps." + } + + // data checks + assert paramSets instanceof List: "--param_list should contain a list of maps" + for (value in paramSets) { + assert value instanceof Map: "--param_list should contain a list of maps" + } + + // id is argument + def idIsArgument = config.allArguments.any{it.plainName == "id"} + + // Reformat from List to List> by adding the ID as first element of a Tuple2 + paramSets = paramSets.collect({ data -> + def id = data.id + if (!idIsArgument) { + data = data.findAll{k, v -> k != "id"} + } + [id, data] + }) + + // Split parameters with 'multiple: true' + paramSets = paramSets.collect({ id, data -> + data = _splitParams(data, config) + [id, data] + }) + + // The paths of input files inside a param_list file may have been specified relatively to the + // location of the param_list file. These paths must be made absolute. + if (paramListPath) { + paramSets = paramSets.collect({ id, data -> + def new_data = data.collectEntries{ parName, parValue -> + def par = config.allArguments.find{it.plainName == parName} + if (par && par.type == "file" && par.direction == "input") { + if (parValue instanceof Collection) { + parValue = parValue.collectMany{path -> + def x = _resolveSiblingIfNotAbsolute(path, paramListPath) + x instanceof Collection ? x : [x] + } + } else { + parValue = _resolveSiblingIfNotAbsolute(parValue, paramListPath) + } + } + [parName, parValue] + } + [id, new_data] + }) + } + + return paramSets +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/_splitParams.nf' +/** + * Split parameters for arguments that accept multiple values using their separator + * + * @param paramList A Map containing parameters to split. + * @param config A Map of the Viash configuration. This Map can be generated from the config file + * using the readConfig() function. + * + * @return A Map of parameters where the parameter values have been split into a list using + * their seperator. + */ +Map _splitParams(Map parValues, Map config){ + def parsedParamValues = parValues.collectEntries { parName, parValue -> + def parameterSettings = config.allArguments.find({it.plainName == parName}) + + if (!parameterSettings) { + // if argument is not found, do not alter + return [parName, parValue] + } + if (parameterSettings.multiple) { // Check if parameter can accept multiple values + if (parValue instanceof Collection) { + parValue = parValue.collect{it instanceof String ? it.split(parameterSettings.multiple_sep) : it } + } else if (parValue instanceof String) { + parValue = parValue.split(parameterSettings.multiple_sep) + } else if (parValue == null) { + parValue = [] + } else { + parValue = [ parValue ] + } + parValue = parValue.flatten() + } + // For all parameters check if multiple values are only passed for + // arguments that allow it. Quietly simplify lists of length 1. + if (!parameterSettings.multiple && parValue instanceof Collection) { + assert parValue.size() == 1 : + "Error: argument ${parName} has too many values.\n" + + " Expected amount: 1. Found: ${parValue.size()}" + parValue = parValue[0] + } + [parName, parValue] + } + return parsedParamValues +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/channelFromParams.nf' +/** + * Parse nextflow parameters based on settings defined in a viash config. + * Return a list of parameter sets, each parameter set corresponding to + * an event in a nextflow channel. The output from this function can be used + * with Channel.fromList to create a nextflow channel with Vdsl3 formatted + * events. + * + * This function performs: + * - A filtering of the params which can be found in the config file. + * - Process the params_list argument which allows a user to to initialise + * a Vsdl3 channel with multiple parameter sets. Possible formats are + * csv, json, yaml, or simply a yaml_blob. A csv should have column names + * which correspond to the different arguments of this pipeline. A json or a yaml + * file should be a list of maps, each of which has keys corresponding to the + * arguments of the pipeline. A yaml blob can also be passed directly as a parameter. + * When passing a csv, json or yaml, relative path names are relativized to the + * location of the parameter file. + * - Combine the parameter sets into a vdsl3 Channel. + * + * @param params Input parameters. Can optionaly contain a 'param_list' key that + * provides a list of arguments that can be split up into multiple events + * in the output channel possible formats of param_lists are: a csv file, + * json file, a yaml file or a yaml blob. Each parameters set (event) must + * have a unique ID. + * @param config A Map of the Viash configuration. This Map can be generated from the config file + * using the readConfig() function. + * + * @return A list of parameters with the first element of the event being + * the event ID and the second element containing a map of the parsed parameters. + */ + +private List>> _paramsToParamSets(Map params, Map config){ + // todo: fetch key from run args + def key_ = config.name + + /* parse regular parameters (not in param_list) */ + /*************************************************/ + def globalParams = config.allArguments + .findAll { params.containsKey(it.plainName) } + .collectEntries { [ it.plainName, params[it.plainName] ] } + def globalID = params.get("id", null) + + /* process params_list arguments */ + /*********************************/ + def paramList = params.containsKey("param_list") && params.param_list != null ? + params.param_list : [] + // if (paramList instanceof String) { + // paramList = [paramList] + // } + // def paramSets = paramList.collectMany{ _parseParamList(it, config) } + // TODO: be able to process param_list when it is a list of strings + def paramSets = _parseParamList(paramList, config) + if (paramSets.isEmpty()) { + paramSets = [[null, [:]]] + } + + /* combine arguments into channel */ + /**********************************/ + def processedParams = paramSets.indexed().collect{ index, tup -> + // Process ID + def id = tup[0] ?: globalID + + if (workflow.stubRun && !id) { + // if stub run, explicitly add an id if missing + id = "stub${index}" + } + assert id != null: "Each parameter set should have at least an 'id'" + + // Process params + def parValues = globalParams + tup[1] + // // Remove parameters which are null, if the default is also null + // parValues = parValues.collectEntries{paramName, paramValue -> + // parameterSettings = config.functionality.allArguments.find({it.plainName == paramName}) + // if ( paramValue != null || parameterSettings.get("default", null) != null ) { + // [paramName, paramValue] + // } + // } + parValues = parValues.collectEntries { name, value -> + def par = config.allArguments.find { it.plainName == name && (it.direction == "input" || it.type == "file") } + assert par != null : "Error in module '${key_}' id '${id}': '${name}' is not a valid input argument" + + if (par == null) { + return [:] + } + value = _checkArgumentType("input", par, value, "in module '$key_' id '$id'") + + [ name, value ] + } + + [id, parValues] + } + + // Check if ids (first element of each list) is unique + _checkUniqueIds(processedParams) + return processedParams +} + +/** + * Parse nextflow parameters based on settings defined in a viash config + * and return a nextflow channel. + * + * @param params Input parameters. Can optionaly contain a 'param_list' key that + * provides a list of arguments that can be split up into multiple events + * in the output channel possible formats of param_lists are: a csv file, + * json file, a yaml file or a yaml blob. Each parameters set (event) must + * have a unique ID. + * @param config A Map of the Viash configuration. This Map can be generated from the config file + * using the readConfig() function. + * + * @return A nextflow Channel with events. Events are formatted as a tuple that contains + * first contains the ID of the event and as second element holds a parameter map. + * + * + */ +def channelFromParams(Map params, Map config) { + def processedParams = _paramsToParamSets(params, config) + return Channel.fromList(processedParams) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/checkUniqueIds.nf' +def checkUniqueIds(Map args) { + def stopOnError = args.stopOnError == null ? args.stopOnError : true + + def idChecker = new IDChecker() + + return filter { tup -> + if (!idChecker.observe(tup[0])) { + if (stopOnError) { + error "Duplicate id: ${tup[0]}" + } else { + log.warn "Duplicate id: ${tup[0]}, removing duplicate entry" + return false + } + } + return true + } +} +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/preprocessInputs.nf' +// This helper file will be deprecated soon +preprocessInputsDeprecationWarningPrinted = false + +def preprocessInputsDeprecationWarning() { + if (!preprocessInputsDeprecationWarningPrinted) { + preprocessInputsDeprecationWarningPrinted = true + System.err.println("Warning: preprocessInputs() is deprecated and will be removed in Viash 0.9.0.") + } +} + +/** + * Generate a nextflow Workflow that allows processing a channel of + * Vdsl3 formatted events and apply a Viash config to them: + * - Gather default parameters from the Viash config and make + * sure that they are correctly formatted (see applyConfig method). + * - Format the input parameters (also using the applyConfig method). + * - Apply the default parameter to the input parameters. + * - Do some assertions: + * ~ Check if the event IDs in the channel are unique. + * + * The events in the channel are formatted as tuples, with the + * first element of the tuples being a unique id of the parameter set, + * and the second element containg the the parameters themselves. + * Optional extra elements of the tuples will be passed to the output as is. + * + * @param args A map that must contain a 'config' key that points + * to a parsed config (see readConfig()). Optionally, a + * 'key' key can be provided which can be used to create a unique + * name for the workflow process. + * + * @return A workflow that allows processing a channel of Vdsl3 formatted events + * and apply a Viash config to them. + */ +def preprocessInputs(Map args) { + preprocessInputsDeprecationWarning() + + def config = args.config + assert config instanceof Map : + "Error in preprocessInputs: config must be a map. " + + "Expected class: Map. Found: config.getClass() is ${config.getClass()}" + def key_ = args.key ?: config.name + + // Get different parameter types (used throughout this function) + def defaultArgs = config.allArguments + .findAll { it.containsKey("default") } + .collectEntries { [ it.plainName, it.default ] } + + map { tup -> + def id = tup[0] + def data = tup[1] + def passthrough = tup.drop(2) + + def new_data = (defaultArgs + data).collectEntries { name, value -> + def par = config.allArguments.find { it.plainName == name && (it.direction == "input" || it.type == "file") } + + if (par != null) { + value = _checkArgumentType("input", par, value, "in module '$key_' id '$id'") + } + + [ name, value ] + } + + [ id, new_data ] + passthrough + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/runComponents.nf' +/** + * Run a list of components on a stream of data. + * + * @param components: list of Viash VDSL3 modules to run + * @param fromState: a closure, a map or a list of keys to extract from the input data. + * If a closure, it will be called with the id, the data and the component config. + * @param toState: a closure, a map or a list of keys to extract from the output data + * If a closure, it will be called with the id, the output data, the old state and the component config. + * @param filter: filter function to apply to the input. + * It will be called with the id, the data and the component config. + * @param id: id to use for the output data + * If a closure, it will be called with the id, the data and the component config. + * @param auto: auto options to pass to the components + * + * @return: a workflow that runs the components + **/ +def runComponents(Map args) { + log.warn("runComponents is deprecated, use runEach instead") + assert args.components: "runComponents should be passed a list of components to run" + + def components_ = args.components + if (components_ !instanceof List) { + components_ = [ components_ ] + } + assert components_.size() > 0: "pass at least one component to runComponents" + + def fromState_ = args.fromState + def toState_ = args.toState + def filter_ = args.filter + def id_ = args.id + + workflow runComponentsWf { + take: input_ch + main: + + // generate one channel per method + out_chs = components_.collect{ comp_ -> + def comp_config = comp_.config + + def filter_ch = filter_ + ? input_ch | filter{tup -> + filter_(tup[0], tup[1], comp_config) + } + : input_ch + def id_ch = id_ + ? filter_ch | map{tup -> + // def new_id = id_(tup[0], tup[1], comp_config) + def new_id = tup[0] + if (id_ instanceof String) { + new_id = id_ + } else if (id_ instanceof Closure) { + new_id = id_(new_id, tup[1], comp_config) + } + [new_id] + tup.drop(1) + } + : filter_ch + def data_ch = id_ch | map{tup -> + def new_data = tup[1] + if (fromState_ instanceof Map) { + new_data = fromState_.collectEntries{ key0, key1 -> + [key0, new_data[key1]] + } + } else if (fromState_ instanceof List) { + new_data = fromState_.collectEntries{ key -> + [key, new_data[key]] + } + } else if (fromState_ instanceof Closure) { + new_data = fromState_(tup[0], new_data, comp_config) + } + tup.take(1) + [new_data] + tup.drop(1) + } + def out_ch = data_ch + | comp_.run( + auto: (args.auto ?: [:]) + [simplifyInput: false, simplifyOutput: false] + ) + def post_ch = toState_ + ? out_ch | map{tup -> + def output = tup[1] + def old_state = tup[2] + def new_state = null + if (toState_ instanceof Map) { + new_state = old_state + toState_.collectEntries{ key0, key1 -> + [key0, output[key1]] + } + } else if (toState_ instanceof List) { + new_state = old_state + toState_.collectEntries{ key -> + [key, output[key]] + } + } else if (toState_ instanceof Closure) { + new_state = toState_(tup[0], output, old_state, comp_config) + } + [tup[0], new_state] + tup.drop(3) + } + : out_ch + + post_ch + } + + // mix all results + output_ch = + (out_chs.size == 1) + ? out_chs[0] + : out_chs[0].mix(*out_chs.drop(1)) + + emit: output_ch + } + + return runComponentsWf +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/runEach.nf' +/** + * Run a list of components on a stream of data. + * + * @param components: list of Viash VDSL3 modules to run + * @param fromState: a closure, a map or a list of keys to extract from the input data. + * If a closure, it will be called with the id, the data and the component itself. + * @param toState: a closure, a map or a list of keys to extract from the output data + * If a closure, it will be called with the id, the output data, the old state and the component itself. + * @param filter: filter function to apply to the input. + * It will be called with the id, the data and the component itself. + * @param id: id to use for the output data + * If a closure, it will be called with the id, the data and the component itself. + * @param auto: auto options to pass to the components + * + * @return: a workflow that runs the components + **/ +def runEach(Map args) { + assert args.components: "runEach should be passed a list of components to run" + + def components_ = args.components + if (components_ !instanceof List) { + components_ = [ components_ ] + } + assert components_.size() > 0: "pass at least one component to runEach" + + def fromState_ = args.fromState + def toState_ = args.toState + def filter_ = args.filter + def id_ = args.id + + workflow runEachWf { + take: input_ch + main: + + // generate one channel per method + out_chs = components_.collect{ comp_ -> + def filter_ch = filter_ + ? input_ch | filter{tup -> + filter_(tup[0], tup[1], comp_) + } + : input_ch + def id_ch = id_ + ? filter_ch | map{tup -> + def new_id = id_ + if (new_id instanceof Closure) { + new_id = new_id(tup[0], tup[1], comp_) + } + assert new_id instanceof String : "Error in runEach: id should be a String or a Closure that returns a String. Expected: id instanceof String. Found: ${new_id.getClass()}" + [new_id] + tup.drop(1) + } + : filter_ch + def data_ch = id_ch | map{tup -> + def new_data = tup[1] + if (fromState_ instanceof Map) { + new_data = fromState_.collectEntries{ key0, key1 -> + [key0, new_data[key1]] + } + } else if (fromState_ instanceof List) { + new_data = fromState_.collectEntries{ key -> + [key, new_data[key]] + } + } else if (fromState_ instanceof Closure) { + new_data = fromState_(tup[0], new_data, comp_) + } + tup.take(1) + [new_data] + tup.drop(1) + } + def out_ch = data_ch + | comp_.run( + auto: (args.auto ?: [:]) + [simplifyInput: false, simplifyOutput: false] + ) + def post_ch = toState_ + ? out_ch | map{tup -> + def output = tup[1] + def old_state = tup[2] + def new_state = null + if (toState_ instanceof Map) { + new_state = old_state + toState_.collectEntries{ key0, key1 -> + [key0, output[key1]] + } + } else if (toState_ instanceof List) { + new_state = old_state + toState_.collectEntries{ key -> + [key, output[key]] + } + } else if (toState_ instanceof Closure) { + new_state = toState_(tup[0], output, old_state, comp_) + } + [tup[0], new_state] + tup.drop(3) + } + : out_ch + + post_ch + } + + // mix all results + output_ch = + (out_chs.size == 1) + ? out_chs[0] + : out_chs[0].mix(*out_chs.drop(1)) + + emit: output_ch + } + + return runEachWf +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/safeJoin.nf' +/** + * Join sourceChannel to targetChannel + * + * This function joins the sourceChannel to the targetChannel. + * However, each id in the targetChannel must be present in the + * sourceChannel. If _meta.join_id exists in the targetChannel, that is + * used as an id instead. If the id doesn't match any id in the sourceChannel, + * an error is thrown. + */ + +def safeJoin(targetChannel, sourceChannel, key) { + def sourceIDs = new IDChecker() + + def sourceCheck = sourceChannel + | map { tup -> + sourceIDs.observe(tup[0]) + tup + } + def targetCheck = targetChannel + | map { tup -> + def id = tup[0] + + if (!sourceIDs.contains(id)) { + error ( + "Error in module '${key}' when merging output with original state.\n" + + " Reason: output with id '${id}' could not be joined with source channel.\n" + + " If the IDs in the output channel differ from the input channel,\n" + + " please set `tup[1]._meta.join_id to the original ID.\n" + + " Original IDs in input channel: ['${sourceIDs.getItems().join("', '")}'].\n" + + " Unexpected ID in the output channel: '${id}'.\n" + + " Example input event: [\"id\", [input: file(...)]],\n" + + " Example output event: [\"newid\", [output: file(...), _meta: [join_id: \"id\"]]]" + ) + } + // TODO: add link to our documentation on how to fix this + + tup + } + + sourceCheck.cross(targetChannel) + | map{ left, right -> + right + left.drop(1) + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/config/_processArgument.nf' +def _processArgument(arg) { + arg.multiple = arg.multiple != null ? arg.multiple : false + arg.required = arg.required != null ? arg.required : false + arg.direction = arg.direction != null ? arg.direction : "input" + arg.multiple_sep = arg.multiple_sep != null ? arg.multiple_sep : ";" + arg.plainName = arg.name.replaceAll("^-*", "") + + if (arg.type == "file") { + arg.must_exist = arg.must_exist != null ? arg.must_exist : true + arg.create_parent = arg.create_parent != null ? arg.create_parent : true + } + + // add default values to output files which haven't already got a default + if (arg.type == "file" && arg.direction == "output" && arg.default == null) { + def mult = arg.multiple ? "_*" : "" + def extSearch = "" + if (arg.default != null) { + extSearch = arg.default + } else if (arg.example != null) { + extSearch = arg.example + } + if (extSearch instanceof List) { + extSearch = extSearch[0] + } + def extSearchResult = extSearch.find("\\.[^\\.]+\$") + def ext = extSearchResult != null ? extSearchResult : "" + arg.default = "\$id.\$key.${arg.plainName}${mult}${ext}" + if (arg.multiple) { + arg.default = [arg.default] + } + } + + if (!arg.multiple) { + if (arg.default != null && arg.default instanceof List) { + arg.default = arg.default[0] + } + if (arg.example != null && arg.example instanceof List) { + arg.example = arg.example[0] + } + } + + if (arg.type == "boolean_true") { + arg.default = false + } + if (arg.type == "boolean_false") { + arg.default = true + } + + arg +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/config/addGlobalParams.nf' +def addGlobalArguments(config) { + def localConfig = [ + "argument_groups": [ + [ + "name": "Nextflow input-output arguments", + "description": "Input/output parameters for Nextflow itself. Please note that both publishDir and publish_dir are supported but at least one has to be configured.", + "arguments" : [ + [ + 'name': '--publish_dir', + 'required': true, + 'type': 'string', + 'description': 'Path to an output directory.', + 'example': 'output/', + 'multiple': false + ], + [ + 'name': '--param_list', + 'required': false, + 'type': 'string', + 'description': '''Allows inputting multiple parameter sets to initialise a Nextflow channel. A `param_list` can either be a list of maps, a csv file, a json file, a yaml file, or simply a yaml blob. + | + |* A list of maps (as-is) where the keys of each map corresponds to the arguments of the pipeline. Example: in a `nextflow.config` file: `param_list: [ ['id': 'foo', 'input': 'foo.txt'], ['id': 'bar', 'input': 'bar.txt'] ]`. + |* A csv file should have column names which correspond to the different arguments of this pipeline. Example: `--param_list data.csv` with columns `id,input`. + |* A json or a yaml file should be a list of maps, each of which has keys corresponding to the arguments of the pipeline. Example: `--param_list data.json` with contents `[ {'id': 'foo', 'input': 'foo.txt'}, {'id': 'bar', 'input': 'bar.txt'} ]`. + |* A yaml blob can also be passed directly as a string. Example: `--param_list "[ {'id': 'foo', 'input': 'foo.txt'}, {'id': 'bar', 'input': 'bar.txt'} ]"`. + | + |When passing a csv, json or yaml file, relative path names are relativized to the location of the parameter file. No relativation is performed when `param_list` is a list of maps (as-is) or a yaml blob.'''.stripMargin(), + 'example': 'my_params.yaml', + 'multiple': false, + 'hidden': true + ] + // TODO: allow multiple: true in param_list? + // TODO: allow to specify a --param_list_regex to filter the param_list? + // TODO: allow to specify a --param_list_from_state to remap entries in the param_list? + ] + ] + ] + ] + + return processConfig(_mergeMap(config, localConfig)) +} + +def _mergeMap(Map lhs, Map rhs) { + return rhs.inject(lhs.clone()) { map, entry -> + if (map[entry.key] instanceof Map && entry.value instanceof Map) { + map[entry.key] = _mergeMap(map[entry.key], entry.value) + } else if (map[entry.key] instanceof Collection && entry.value instanceof Collection) { + map[entry.key] += entry.value + } else { + map[entry.key] = entry.value + } + return map + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/config/generateHelp.nf' +def _generateArgumentHelp(param) { + // alternatives are not supported + // def names = param.alternatives ::: List(param.name) + + def unnamedProps = [ + ["required parameter", param.required], + ["multiple values allowed", param.multiple], + ["output", param.direction.toLowerCase() == "output"], + ["file must exist", param.type == "file" && param.must_exist] + ].findAll{it[1]}.collect{it[0]} + + def dflt = null + if (param.default != null) { + if (param.default instanceof List) { + dflt = param.default.join(param.multiple_sep != null ? param.multiple_sep : ", ") + } else { + dflt = param.default.toString() + } + } + def example = null + if (param.example != null) { + if (param.example instanceof List) { + example = param.example.join(param.multiple_sep != null ? param.multiple_sep : ", ") + } else { + example = param.example.toString() + } + } + def min = param.min?.toString() + def max = param.max?.toString() + + def escapeChoice = { choice -> + def s1 = choice.replaceAll("\\n", "\\\\n") + def s2 = s1.replaceAll("\"", """\\\"""") + s2.contains(",") || s2 != choice ? "\"" + s2 + "\"" : s2 + } + def choices = param.choices == null ? + null : + "[ " + param.choices.collect{escapeChoice(it.toString())}.join(", ") + " ]" + + def namedPropsStr = [ + ["type", ([param.type] + unnamedProps).join(", ")], + ["default", dflt], + ["example", example], + ["choices", choices], + ["min", min], + ["max", max] + ] + .findAll{it[1]} + .collect{"\n " + it[0] + ": " + it[1].replaceAll("\n", "\\n")} + .join("") + + def descStr = param.description == null ? + "" : + _paragraphWrap("\n" + param.description.trim(), 80 - 8).join("\n ") + + "\n --" + param.plainName + + namedPropsStr + + descStr +} + +// Based on Helper.generateHelp() in Helper.scala +def _generateHelp(config) { + def fun = config + + // PART 1: NAME AND VERSION + def nameStr = fun.name + + (fun.version == null ? "" : " " + fun.version) + + // PART 2: DESCRIPTION + def descrStr = fun.description == null ? + "" : + "\n\n" + _paragraphWrap(fun.description.trim(), 80).join("\n") + + // PART 3: Usage + def usageStr = fun.usage == null ? + "" : + "\n\nUsage:\n" + fun.usage.trim() + + // PART 4: Options + def argGroupStrs = fun.allArgumentGroups.collect{argGroup -> + def name = argGroup.name + def descriptionStr = argGroup.description == null ? + "" : + "\n " + _paragraphWrap(argGroup.description.trim(), 80-4).join("\n ") + "\n" + def arguments = argGroup.arguments.collect{arg -> + arg instanceof String ? fun.allArguments.find{it.plainName == arg} : arg + }.findAll{it != null} + def argumentStrs = arguments.collect{param -> _generateArgumentHelp(param)} + + "\n\n$name:" + + descriptionStr + + argumentStrs.join("\n") + } + + // FINAL: combine + def out = nameStr + + descrStr + + usageStr + + argGroupStrs.join("") + + return out +} + +// based on Format._paragraphWrap +def _paragraphWrap(str, maxLength) { + def outLines = [] + str.split("\n").each{par -> + def words = par.split("\\s").toList() + + def word = null + def line = words.pop() + while(!words.isEmpty()) { + word = words.pop() + if (line.length() + word.length() + 1 <= maxLength) { + line = line + " " + word + } else { + outLines.add(line) + line = word + } + } + if (words.isEmpty()) { + outLines.add(line) + } + } + return outLines +} + +def helpMessage(config) { + if (params.containsKey("help") && params.help) { + def mergedConfig = addGlobalArguments(config) + def helpStr = _generateHelp(mergedConfig) + println(helpStr) + exit 0 + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/config/processConfig.nf' +def processConfig(config) { + // set defaults for arguments + config.arguments = + (config.arguments ?: []).collect{_processArgument(it)} + + // set defaults for argument_group arguments + config.argument_groups = + (config.argument_groups ?: []).collect{grp -> + grp.arguments = (grp.arguments ?: []).collect{_processArgument(it)} + grp + } + + // create combined arguments list + config.allArguments = + config.arguments + + config.argument_groups.collectMany{it.arguments} + + // add missing argument groups (based on Functionality::allArgumentGroups()) + def argGroups = config.argument_groups + if (argGroups.any{it.name.toLowerCase() == "arguments"}) { + argGroups = argGroups.collect{ grp -> + if (grp.name.toLowerCase() == "arguments") { + grp = grp + [ + arguments: grp.arguments + config.arguments + ] + } + grp + } + } else { + argGroups = argGroups + [ + name: "Arguments", + arguments: config.arguments + ] + } + config.allArgumentGroups = argGroups + + config +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/config/readConfig.nf' + +def readConfig(file) { + def config = readYaml(file ?: moduleDir.resolve("config.vsh.yaml")) + processConfig(config) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/_resolveSiblingIfNotAbsolute.nf' +/** + * Resolve a path relative to the current file. + * + * @param str The path to resolve, as a String. + * @param parentPath The path to resolve relative to, as a Path. + * + * @return The path that may have been resovled, as a Path. + */ +def _resolveSiblingIfNotAbsolute(str, parentPath) { + if (str !instanceof String) { + return str + } + if (!_stringIsAbsolutePath(str)) { + return parentPath.resolveSibling(str) + } else { + return file(str, hidden: true) + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/_stringIsAbsolutePath.nf' +/** + * Check whether a path as a string is absolute. + * + * In the past, we tried using `file(., relative: true).isAbsolute()`, + * but the 'relative' option was added in 22.10.0. + * + * @param path The path to check, as a String. + * + * @return Whether the path is absolute, as a boolean. + */ +def _stringIsAbsolutePath(path) { + def _resolve_URL_PROTOCOL = ~/^([a-zA-Z][a-zA-Z0-9]*:)?\\/.+/ + + assert path instanceof String + return _resolve_URL_PROTOCOL.matcher(path).matches() +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/collectTraces.nf' +class CustomTraceObserver implements nextflow.trace.TraceObserver { + List traces + + CustomTraceObserver(List traces) { + this.traces = traces + } + + @Override + void onProcessComplete(nextflow.processor.TaskHandler handler, nextflow.trace.TraceRecord trace) { + def trace2 = trace.store.clone() + trace2.script = null + traces.add(trace2) + } + + @Override + void onProcessCached(nextflow.processor.TaskHandler handler, nextflow.trace.TraceRecord trace) { + def trace2 = trace.store.clone() + trace2.script = null + traces.add(trace2) + } +} + +def collectTraces() { + def traces = Collections.synchronizedList([]) + + // add custom trace observer which stores traces in the traces object + session.observers.add(new CustomTraceObserver(traces)) + + traces +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/deepClone.nf' +/** + * Performs a deep clone of the given object. + * @param x an object + */ +def deepClone(x) { + iterateMap(x, {it instanceof Cloneable ? it.clone() : it}) +} +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/getPublishDir.nf' +def getPublishDir() { + return params.containsKey("publish_dir") ? params.publish_dir : + params.containsKey("publishDir") ? params.publishDir : + null +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/getRootDir.nf' + +// Recurse upwards until we find a '.build.yaml' file +def _findBuildYamlFile(pathPossiblySymlink) { + def path = pathPossiblySymlink.toRealPath() + def child = path.resolve(".build.yaml") + if (java.nio.file.Files.isDirectory(path) && java.nio.file.Files.exists(child)) { + return child + } else { + def parent = path.getParent() + if (parent == null) { + return null + } else { + return _findBuildYamlFile(parent) + } + } +} + +// get the root of the target folder +def getRootDir() { + def dir = _findBuildYamlFile(meta.resources_dir) + assert dir != null: "Could not find .build.yaml in the folder structure" + dir.getParent() +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/iterateMap.nf' +/** + * Recursively apply a function over the leaves of an object. + * @param obj The object to iterate over. + * @param fun The function to apply to each value. + * @return The object with the function applied to each value. + */ +def iterateMap(obj, fun) { + if (obj instanceof List && obj !instanceof String) { + return obj.collect{item -> + iterateMap(item, fun) + } + } else if (obj instanceof Map) { + return obj.collectEntries{key, item -> + [key.toString(), iterateMap(item, fun)] + } + } else { + return fun(obj) + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/niceView.nf' +/** + * A view for printing the event of each channel as a YAML blob. + * This is useful for debugging. + */ +def niceView() { + workflow niceViewWf { + take: input + main: + output = input + | view{toYamlBlob(it)} + emit: output + } + return niceViewWf +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/readCsv.nf' + +def readCsv(file_path) { + def output = [] + def inputFile = file_path !instanceof Path ? file(file_path, hidden: true) : file_path + + // todo: allow escaped quotes in string + // todo: allow single quotes? + def splitRegex = java.util.regex.Pattern.compile(''',(?=(?:[^"]*"[^"]*")*[^"]*$)''') + def removeQuote = java.util.regex.Pattern.compile('''"(.*)"''') + + def br = java.nio.file.Files.newBufferedReader(inputFile) + + def row = -1 + def header = null + while (br.ready() && header == null) { + def line = br.readLine() + row++ + if (!line.startsWith("#")) { + header = splitRegex.split(line, -1).collect{field -> + m = removeQuote.matcher(field) + m.find() ? m.replaceFirst('$1') : field + } + } + } + assert header != null: "CSV file should contain a header" + + while (br.ready()) { + def line = br.readLine() + row++ + if (line == null) { + br.close() + break + } + + if (!line.startsWith("#")) { + def predata = splitRegex.split(line, -1) + def data = predata.collect{field -> + if (field == "") { + return null + } + def m = removeQuote.matcher(field) + if (m.find()) { + return m.replaceFirst('$1') + } else { + return field + } + } + assert header.size() == data.size(): "Row $row should contain the same number as fields as the header" + + def dataMap = [header, data].transpose().collectEntries().findAll{it.value != null} + output.add(dataMap) + } + } + + output +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/readJson.nf' +def readJson(file_path) { + def inputFile = file_path !instanceof Path ? file(file_path, hidden: true) : file_path + def jsonSlurper = new groovy.json.JsonSlurper() + jsonSlurper.parse(inputFile) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/readJsonBlob.nf' +def readJsonBlob(str) { + def jsonSlurper = new groovy.json.JsonSlurper() + jsonSlurper.parseText(str) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/readTaggedYaml.nf' +// Custom constructor to modify how certain objects are parsed from YAML +class CustomConstructor extends org.yaml.snakeyaml.constructor.Constructor { + Path root + + class ConstructPath extends org.yaml.snakeyaml.constructor.AbstractConstruct { + public Object construct(org.yaml.snakeyaml.nodes.Node node) { + String filename = (String) constructScalar(node); + if (root != null) { + return root.resolve(filename); + } + return java.nio.file.Paths.get(filename); + } + } + + CustomConstructor(org.yaml.snakeyaml.LoaderOptions options, Path root) { + super(options) + this.root = root + // Handling !file tag and parse it back to a File type + this.yamlConstructors.put(new org.yaml.snakeyaml.nodes.Tag("!file"), new ConstructPath()) + } +} + +def readTaggedYaml(Path path) { + def options = new org.yaml.snakeyaml.LoaderOptions() + def constructor = new CustomConstructor(options, path.getParent()) + def yaml = new org.yaml.snakeyaml.Yaml(constructor) + return yaml.load(path.text) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/readYaml.nf' +def readYaml(file_path) { + def inputFile = file_path !instanceof Path ? file(file_path, hidden: true) : file_path + def yamlSlurper = new org.yaml.snakeyaml.Yaml() + yamlSlurper.load(inputFile) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/readYamlBlob.nf' +def readYamlBlob(str) { + def yamlSlurper = new org.yaml.snakeyaml.Yaml() + yamlSlurper.load(str) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/toJsonBlob.nf' +String toJsonBlob(data) { + return groovy.json.JsonOutput.toJson(data) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/toTaggedYamlBlob.nf' +// Custom representer to modify how certain objects are represented in YAML +class CustomRepresenter extends org.yaml.snakeyaml.representer.Representer { + Path relativizer + + class RepresentPath implements org.yaml.snakeyaml.representer.Represent { + public String getFileName(Object obj) { + if (obj instanceof File) { + obj = ((File) obj).toPath(); + } + if (obj !instanceof Path) { + throw new IllegalArgumentException("Object: " + obj + " is not a Path or File"); + } + def path = (Path) obj; + + if (relativizer != null) { + return relativizer.relativize(path).toString() + } else { + return path.toString() + } + } + + public org.yaml.snakeyaml.nodes.Node representData(Object data) { + String filename = getFileName(data); + def tag = new org.yaml.snakeyaml.nodes.Tag("!file"); + return representScalar(tag, filename); + } + } + CustomRepresenter(org.yaml.snakeyaml.DumperOptions options, Path relativizer) { + super(options) + this.relativizer = relativizer + this.representers.put(sun.nio.fs.UnixPath, new RepresentPath()) + this.representers.put(Path, new RepresentPath()) + this.representers.put(File, new RepresentPath()) + } +} + +String toTaggedYamlBlob(data) { + return toRelativeTaggedYamlBlob(data, null) +} +String toRelativeTaggedYamlBlob(data, Path relativizer) { + def options = new org.yaml.snakeyaml.DumperOptions() + options.setDefaultFlowStyle(org.yaml.snakeyaml.DumperOptions.FlowStyle.BLOCK) + def representer = new CustomRepresenter(options, relativizer) + def yaml = new org.yaml.snakeyaml.Yaml(representer, options) + return yaml.dump(data) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/toYamlBlob.nf' +String toYamlBlob(data) { + def options = new org.yaml.snakeyaml.DumperOptions() + options.setDefaultFlowStyle(org.yaml.snakeyaml.DumperOptions.FlowStyle.BLOCK) + options.setPrettyFlow(true) + def yaml = new org.yaml.snakeyaml.Yaml(options) + def cleanData = iterateMap(data, { it instanceof Path ? it.toString() : it }) + return yaml.dump(cleanData) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/writeJson.nf' +void writeJson(data, file) { + assert data: "writeJson: data should not be null" + assert file: "writeJson: file should not be null" + file.write(toJsonBlob(data)) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/writeYaml.nf' +void writeYaml(data, file) { + assert data: "writeYaml: data should not be null" + assert file: "writeYaml: file should not be null" + file.write(toYamlBlob(data)) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/states/findStates.nf' +def findStates(Map params, Map config) { + def auto_config = deepClone(config) + def auto_params = deepClone(params) + + auto_config = auto_config.clone() + // override arguments + auto_config.argument_groups = [] + auto_config.arguments = [ + [ + type: "string", + name: "--id", + description: "A dummy identifier", + required: false + ], + [ + type: "file", + name: "--input_states", + example: "/path/to/input/directory/**/state.yaml", + description: "Path to input directory containing the datasets to be integrated.", + required: true, + multiple: true, + multiple_sep: ";" + ], + [ + type: "string", + name: "--filter", + example: "foo/.*/state.yaml", + description: "Regex to filter state files by path.", + required: false + ], + // to do: make this a yaml blob? + [ + type: "string", + name: "--rename_keys", + example: ["newKey1:oldKey1", "newKey2:oldKey2"], + description: "Rename keys in the detected input files. This is useful if the input files do not match the set of input arguments of the workflow.", + required: false, + multiple: true, + multiple_sep: ";" + ], + [ + type: "string", + name: "--settings", + example: '{"output_dataset": "dataset.h5ad", "k": 10}', + description: "Global arguments as a JSON glob to be passed to all components.", + required: false + ] + ] + if (!(auto_params.containsKey("id"))) { + auto_params["id"] = "auto" + } + + // run auto config through processConfig once more + auto_config = processConfig(auto_config) + + workflow findStatesWf { + helpMessage(auto_config) + + output_ch = + channelFromParams(auto_params, auto_config) + | flatMap { autoId, args -> + + def globalSettings = args.settings ? readYamlBlob(args.settings) : [:] + + // look for state files in input dir + def stateFiles = args.input_states + + // filter state files by regex + if (args.filter) { + stateFiles = stateFiles.findAll{ stateFile -> + def stateFileStr = stateFile.toString() + def matcher = stateFileStr =~ args.filter + matcher.matches()} + } + + // read in states + def states = stateFiles.collect { stateFile -> + def state_ = readTaggedYaml(stateFile) + [state_.id, state_] + } + + // construct renameMap + if (args.rename_keys) { + def renameMap = args.rename_keys.collectEntries{renameString -> + def split = renameString.split(";") + assert split.size() == 2: "Argument 'rename_keys' should be of the form 'newKey:oldKey,newKey:oldKey'" + split + } + + // rename keys in state, only let states through which have all keys + // also add global settings + states = states.collectMany{id, state -> + def newState = [:] + + for (key in renameMap.keySet()) { + def origKey = renameMap[key] + if (!(state.containsKey(origKey))) { + return [] + } + newState[key] = state[origKey] + } + + [[id, globalSettings + newState]] + } + } + + states + } + emit: + output_ch + } + + return findStatesWf +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/states/joinStates.nf' +def joinStates(Closure apply_) { + workflow joinStatesWf { + take: input_ch + main: + output_ch = input_ch + | toSortedList + | filter{ it.size() > 0 } + | map{ tups -> + def ids = tups.collect{it[0]} + def states = tups.collect{it[1]} + apply_(ids, states) + } + + emit: output_ch + } + return joinStatesWf +} +// helper file: 'src/main/resources/io/viash/runners/nextflow/states/publishStates.nf' +def collectFiles(obj) { + if (obj instanceof java.io.File || obj instanceof Path) { + return [obj] + } else if (obj instanceof List && obj !instanceof String) { + return obj.collectMany{item -> + collectFiles(item) + } + } else if (obj instanceof Map) { + return obj.collectMany{key, item -> + collectFiles(item) + } + } else { + return [] + } +} + +/** + * Recurse through a state and collect all input files and their target output filenames. + * @param obj The state to recurse through. + * @param prefix The prefix to prepend to the output filenames. + */ +def collectInputOutputPaths(obj, prefix) { + if (obj instanceof File || obj instanceof Path) { + def path = obj instanceof Path ? obj : obj.toPath() + def ext = path.getFileName().toString().find("\\.[^\\.]+\$") ?: "" + def newFilename = prefix + ext + return [[obj, newFilename]] + } else if (obj instanceof List && obj !instanceof String) { + return obj.withIndex().collectMany{item, ix -> + collectInputOutputPaths(item, prefix + "_" + ix) + } + } else if (obj instanceof Map) { + return obj.collectMany{key, item -> + collectInputOutputPaths(item, prefix + "." + key) + } + } else { + return [] + } +} + +def publishStates(Map args) { + def key_ = args.get("key") + def yamlTemplate_ = args.get("output_state", args.get("outputState", '$id.$key.state.yaml')) + + assert key_ != null : "publishStates: key must be specified" + + workflow publishStatesWf { + take: input_ch + main: + input_ch + | map { tup -> + def id_ = tup[0] + def state_ = tup[1] + + // the input files and the target output filenames + def inputoutputFilenames_ = collectInputOutputPaths(state_, id_ + "." + key_).transpose() + def inputFiles_ = inputoutputFilenames_[0] + def outputFilenames_ = inputoutputFilenames_[1] + + def yamlFilename = yamlTemplate_ + .replaceAll('\\$id', id_) + .replaceAll('\\$key', key_) + + // TODO: do the pathnames in state_ match up with the outputFilenames_? + + // convert state to yaml blob + def yamlBlob_ = toRelativeTaggedYamlBlob([id: id_] + state_, java.nio.file.Paths.get(yamlFilename)) + + [id_, yamlBlob_, yamlFilename, inputFiles_, outputFilenames_] + } + | publishStatesProc + emit: input_ch + } + return publishStatesWf +} +process publishStatesProc { + // todo: check publishpath? + publishDir path: "${getPublishDir()}/", mode: "copy" + tag "$id" + input: + tuple val(id), val(yamlBlob), val(yamlFile), path(inputFiles, stageAs: "_inputfile?/*"), val(outputFiles) + output: + tuple val(id), path{[yamlFile] + outputFiles} + script: + def copyCommands = [ + inputFiles instanceof List ? inputFiles : [inputFiles], + outputFiles instanceof List ? outputFiles : [outputFiles] + ] + .transpose() + .collectMany{infile, outfile -> + if (infile.toString() != outfile.toString()) { + [ + "[ -d \"\$(dirname '${outfile.toString()}')\" ] || mkdir -p \"\$(dirname '${outfile.toString()}')\"", + "cp -r '${infile.toString()}' '${outfile.toString()}'" + ] + } else { + // no need to copy if infile is the same as outfile + [] + } + } + """ +mkdir -p "\$(dirname '${yamlFile}')" +echo "Storing state as yaml" +echo '${yamlBlob}' > '${yamlFile}' +echo "Copying output files to destination folder" +${copyCommands.join("\n ")} +""" +} + + +// this assumes that the state contains no other values other than those specified in the config +def publishStatesByConfig(Map args) { + def config = args.get("config") + assert config != null : "publishStatesByConfig: config must be specified" + + def key_ = args.get("key", config.name) + assert key_ != null : "publishStatesByConfig: key must be specified" + + workflow publishStatesSimpleWf { + take: input_ch + main: + input_ch + | map { tup -> + def id_ = tup[0] + def state_ = tup[1] // e.g. [output: new File("myoutput.h5ad"), k: 10] + def origState_ = tup[2] // e.g. [output: '$id.$key.foo.h5ad'] + + // TODO: allow overriding the state.yaml template + // TODO TODO: if auto.publish == "state", add output_state as an argument + def yamlTemplate = params.containsKey("output_state") ? params.output_state : '$id.$key.state.yaml' + def yamlFilename = yamlTemplate + .replaceAll('\\$id', id_) + .replaceAll('\\$key', key_) + def yamlDir = java.nio.file.Paths.get(yamlFilename).getParent() + + // the processed state is a list of [key, value, inputPath, outputFilename] tuples, where + // - key is a String + // - value is any object that can be serialized to a Yaml (so a String/Integer/Long/Double/Boolean, a List, a Map, or a Path) + // - inputPath is a List[Path] + // - outputFilename is a List[String] + // - (key, value) are the tuples that will be saved to the state.yaml file + // - (inputPath, outputFilename) are the files that will be copied from src to dest (relative to the state.yaml) + def processedState = + config.allArguments + .findAll { it.direction == "output" } + .collectMany { par -> + def plainName_ = par.plainName + // if the state does not contain the key, it's an + // optional argument for which the component did + // not generate any output + if (!state_.containsKey(plainName_)) { + return [] + } + def value = state_[plainName_] + // if the parameter is not a file, it should be stored + // in the state as-is, but is not something that needs + // to be copied from the source path to the dest path + if (par.type != "file") { + return [[key: plainName_, value: value, inputPath: [], outputFilename: []]] + } + // if the orig state does not contain this filename, + // it's an optional argument for which the user specified + // that it should not be returned as a state + if (!origState_.containsKey(plainName_)) { + return [] + } + def filenameTemplate = origState_[plainName_] + // if the pararameter is multiple: true, fetch the template + if (par.multiple && filenameTemplate instanceof List) { + filenameTemplate = filenameTemplate[0] + } + // instantiate the template + def filename = filenameTemplate + .replaceAll('\\$id', id_) + .replaceAll('\\$key', key_) + if (par.multiple) { + // if the parameter is multiple: true, the filename + // should contain a wildcard '*' that is replaced with + // the index of the file + assert filename.contains("*") : "Module '${key_}' id '${id_}': Multiple output files specified, but no wildcard '*' in the filename: ${filename}" + def outputPerFile = value.withIndex().collect{ val, ix -> + def filename_ix = filename.replace("*", ix.toString()) + def value_ = java.nio.file.Paths.get(filename_ix) + // if id contains a slash + if (yamlDir != null) { + value_ = yamlDir.relativize(value_) + } + def inputPath = val instanceof File ? val.toPath() : val + [value: value_, inputPath: inputPath, outputFilename: filename_ix] + } + def transposedOutputs = ["value", "inputPath", "outputFilename"].collectEntries{ key -> + [key, outputPerFile.collect{dic -> dic[key]}] + } + return [[key: plainName_] + transposedOutputs] + } else { + def value_ = java.nio.file.Paths.get(filename) + // if id contains a slash + if (yamlDir != null) { + value_ = yamlDir.relativize(value_) + } + def inputPath = value instanceof File ? value.toPath() : value + return [[key: plainName_, value: value_, inputPath: [inputPath], outputFilename: [filename]]] + } + } + + def updatedState_ = processedState.collectEntries{[it.key, it.value]} + def inputPaths = processedState.collectMany{it.inputPath} + def outputFilenames = processedState.collectMany{it.outputFilename} + + // convert state to yaml blob + def yamlBlob_ = toTaggedYamlBlob([id: id_] + updatedState_) + + [id_, yamlBlob_, yamlFilename, inputPaths, outputFilenames] + } + | publishStatesProc + emit: input_ch + } + return publishStatesSimpleWf +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/states/setState.nf' +def setState(fun) { + assert fun instanceof Closure || fun instanceof Map || fun instanceof List : + "Error in setState: Expected process argument to be a Closure, a Map, or a List. Found: class ${fun.getClass()}" + + // if fun is a List, convert to map + if (fun instanceof List) { + // check whether fun is a list[string] + assert fun.every{it instanceof CharSequence} : "Error in setState: argument is a List, but not all elements are Strings" + fun = fun.collectEntries{[it, it]} + } + + // if fun is a map, convert to closure + if (fun instanceof Map) { + // check whether fun is a map[string, string] + assert fun.values().every{it instanceof CharSequence} : "Error in setState: argument is a Map, but not all values are Strings" + assert fun.keySet().every{it instanceof CharSequence} : "Error in setState: argument is a Map, but not all keys are Strings" + def funMap = fun.clone() + // turn the map into a closure to be used later on + fun = { id_, state_ -> + assert state_ instanceof Map : "Error in setState: the state is not a Map" + funMap.collectMany{newkey, origkey -> + if (state_.containsKey(origkey)) { + [[newkey, state_[origkey]]] + } else { + [] + } + }.collectEntries() + } + } + + map { tup -> + def id = tup[0] + def state = tup[1] + def unfilteredState = fun(id, state) + def newState = unfilteredState.findAll{key, val -> val != null} + [id, newState] + tup.drop(2) + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/workflowFactory/processAuto.nf' +// TODO: unit test processAuto +def processAuto(Map auto) { + // remove null values + auto = auto.findAll{k, v -> v != null} + + // check for unexpected keys + def expectedKeys = ["simplifyInput", "simplifyOutput", "transcript", "publish"] + def unexpectedKeys = auto.keySet() - expectedKeys + assert unexpectedKeys.isEmpty(), "unexpected keys in auto: '${unexpectedKeys.join("', '")}'" + + // check auto.simplifyInput + assert auto.simplifyInput instanceof Boolean, "auto.simplifyInput must be a boolean" + + // check auto.simplifyOutput + assert auto.simplifyOutput instanceof Boolean, "auto.simplifyOutput must be a boolean" + + // check auto.transcript + assert auto.transcript instanceof Boolean, "auto.transcript must be a boolean" + + // check auto.publish + assert auto.publish instanceof Boolean || auto.publish == "state", "auto.publish must be a boolean or 'state'" + + return auto.subMap(expectedKeys) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/workflowFactory/processDirectives.nf' +def assertMapKeys(map, expectedKeys, requiredKeys, mapName) { + assert map instanceof Map : "Expected argument '$mapName' to be a Map. Found: class ${map.getClass()}" + map.forEach { key, val -> + assert key in expectedKeys : "Unexpected key '$key' in ${mapName ? mapName + " " : ""}map" + } + requiredKeys.forEach { requiredKey -> + assert map.containsKey(requiredKey) : "Missing required key '$key' in ${mapName ? mapName + " " : ""}map" + } +} + +// TODO: unit test processDirectives +def processDirectives(Map drctv) { + // remove null values + drctv = drctv.findAll{k, v -> v != null} + + // check for unexpected keys + def expectedKeys = [ + "accelerator", "afterScript", "beforeScript", "cache", "conda", "container", "containerOptions", "cpus", "disk", "echo", "errorStrategy", "executor", "machineType", "maxErrors", "maxForks", "maxRetries", "memory", "module", "penv", "pod", "publishDir", "queue", "label", "scratch", "storeDir", "stageInMode", "stageOutMode", "tag", "time" + ] + def unexpectedKeys = drctv.keySet() - expectedKeys + assert unexpectedKeys.isEmpty() : "Unexpected keys in process directive: '${unexpectedKeys.join("', '")}'" + + /* DIRECTIVE accelerator + accepted examples: + - [ limit: 4, type: "nvidia-tesla-k80" ] + */ + if (drctv.containsKey("accelerator")) { + assertMapKeys(drctv["accelerator"], ["type", "limit", "request", "runtime"], [], "accelerator") + } + + /* DIRECTIVE afterScript + accepted examples: + - "source /cluster/bin/cleanup" + */ + if (drctv.containsKey("afterScript")) { + assert drctv["afterScript"] instanceof CharSequence + } + + /* DIRECTIVE beforeScript + accepted examples: + - "source /cluster/bin/setup" + */ + if (drctv.containsKey("beforeScript")) { + assert drctv["beforeScript"] instanceof CharSequence + } + + /* DIRECTIVE cache + accepted examples: + - true + - false + - "deep" + - "lenient" + */ + if (drctv.containsKey("cache")) { + assert drctv["cache"] instanceof CharSequence || drctv["cache"] instanceof Boolean + if (drctv["cache"] instanceof CharSequence) { + assert drctv["cache"] in ["deep", "lenient"] : "Unexpected value for cache" + } + } + + /* DIRECTIVE conda + accepted examples: + - "bwa=0.7.15" + - "bwa=0.7.15 fastqc=0.11.5" + - ["bwa=0.7.15", "fastqc=0.11.5"] + */ + if (drctv.containsKey("conda")) { + if (drctv["conda"] instanceof List) { + drctv["conda"] = drctv["conda"].join(" ") + } + assert drctv["conda"] instanceof CharSequence + } + + /* DIRECTIVE container + accepted examples: + - "foo/bar:tag" + - [ registry: "reg", image: "im", tag: "ta" ] + is transformed to "reg/im:ta" + - [ image: "im" ] + is transformed to "im:latest" + */ + if (drctv.containsKey("container")) { + assert drctv["container"] instanceof Map || drctv["container"] instanceof CharSequence + if (drctv["container"] instanceof Map) { + def m = drctv["container"] + assertMapKeys(m, [ "registry", "image", "tag" ], ["image"], "container") + def part1 = + System.getenv('OVERRIDE_CONTAINER_REGISTRY') ? System.getenv('OVERRIDE_CONTAINER_REGISTRY') + "/" : + params.containsKey("override_container_registry") ? params["override_container_registry"] + "/" : // todo: remove? + m.registry ? m.registry + "/" : + "" + def part2 = m.image + def part3 = m.tag ? ":" + m.tag : ":latest" + drctv["container"] = part1 + part2 + part3 + } + } + + /* DIRECTIVE containerOptions + accepted examples: + - "--foo bar" + - ["--foo bar", "-f b"] + */ + if (drctv.containsKey("containerOptions")) { + if (drctv["containerOptions"] instanceof List) { + drctv["containerOptions"] = drctv["containerOptions"].join(" ") + } + assert drctv["containerOptions"] instanceof CharSequence + } + + /* DIRECTIVE cpus + accepted examples: + - 1 + - 10 + */ + if (drctv.containsKey("cpus")) { + assert drctv["cpus"] instanceof Integer + } + + /* DIRECTIVE disk + accepted examples: + - "1 GB" + - "2TB" + - "3.2KB" + - "10.B" + */ + if (drctv.containsKey("disk")) { + assert drctv["disk"] instanceof CharSequence + // assert drctv["disk"].matches("[0-9]+(\\.[0-9]*)? *[KMGTPEZY]?B") + // ^ does not allow closures + } + + /* DIRECTIVE echo + accepted examples: + - true + - false + */ + if (drctv.containsKey("echo")) { + assert drctv["echo"] instanceof Boolean + } + + /* DIRECTIVE errorStrategy + accepted examples: + - "terminate" + - "finish" + */ + if (drctv.containsKey("errorStrategy")) { + assert drctv["errorStrategy"] instanceof CharSequence + assert drctv["errorStrategy"] in ["terminate", "finish", "ignore", "retry"] : "Unexpected value for errorStrategy" + } + + /* DIRECTIVE executor + accepted examples: + - "local" + - "sge" + */ + if (drctv.containsKey("executor")) { + assert drctv["executor"] instanceof CharSequence + assert drctv["executor"] in ["local", "sge", "uge", "lsf", "slurm", "pbs", "pbspro", "moab", "condor", "nqsii", "ignite", "k8s", "awsbatch", "google-pipelines"] : "Unexpected value for executor" + } + + /* DIRECTIVE machineType + accepted examples: + - "n1-highmem-8" + */ + if (drctv.containsKey("machineType")) { + assert drctv["machineType"] instanceof CharSequence + } + + /* DIRECTIVE maxErrors + accepted examples: + - 1 + - 3 + */ + if (drctv.containsKey("maxErrors")) { + assert drctv["maxErrors"] instanceof Integer + } + + /* DIRECTIVE maxForks + accepted examples: + - 1 + - 3 + */ + if (drctv.containsKey("maxForks")) { + assert drctv["maxForks"] instanceof Integer + } + + /* DIRECTIVE maxRetries + accepted examples: + - 1 + - 3 + */ + if (drctv.containsKey("maxRetries")) { + assert drctv["maxRetries"] instanceof Integer + } + + /* DIRECTIVE memory + accepted examples: + - "1 GB" + - "2TB" + - "3.2KB" + - "10.B" + */ + if (drctv.containsKey("memory")) { + assert drctv["memory"] instanceof CharSequence + // assert drctv["memory"].matches("[0-9]+(\\.[0-9]*)? *[KMGTPEZY]?B") + // ^ does not allow closures + } + + /* DIRECTIVE module + accepted examples: + - "ncbi-blast/2.2.27" + - "ncbi-blast/2.2.27:t_coffee/10.0" + - ["ncbi-blast/2.2.27", "t_coffee/10.0"] + */ + if (drctv.containsKey("module")) { + if (drctv["module"] instanceof List) { + drctv["module"] = drctv["module"].join(":") + } + assert drctv["module"] instanceof CharSequence + } + + /* DIRECTIVE penv + accepted examples: + - "smp" + */ + if (drctv.containsKey("penv")) { + assert drctv["penv"] instanceof CharSequence + } + + /* DIRECTIVE pod + accepted examples: + - [ label: "key", value: "val" ] + - [ annotation: "key", value: "val" ] + - [ env: "key", value: "val" ] + - [ [label: "l", value: "v"], [env: "e", value: "v"]] + */ + if (drctv.containsKey("pod")) { + if (drctv["pod"] instanceof Map) { + drctv["pod"] = [ drctv["pod"] ] + } + assert drctv["pod"] instanceof List + drctv["pod"].forEach { pod -> + assert pod instanceof Map + // TODO: should more checks be added? + // See https://www.nextflow.io/docs/latest/process.html?highlight=directives#pod + // e.g. does it contain 'label' and 'value', or 'annotation' and 'value', or ...? + } + } + + /* DIRECTIVE publishDir + accepted examples: + - [] + - [ [ path: "foo", enabled: true ], [ path: "bar", enabled: false ] ] + - "/path/to/dir" + is transformed to [[ path: "/path/to/dir" ]] + - [ path: "/path/to/dir", mode: "cache" ] + is transformed to [[ path: "/path/to/dir", mode: "cache" ]] + */ + // TODO: should we also look at params["publishDir"]? + if (drctv.containsKey("publishDir")) { + def pblsh = drctv["publishDir"] + + // check different options + assert pblsh instanceof List || pblsh instanceof Map || pblsh instanceof CharSequence + + // turn into list if not already so + // for some reason, 'if (!pblsh instanceof List) pblsh = [ pblsh ]' doesn't work. + pblsh = pblsh instanceof List ? pblsh : [ pblsh ] + + // check elements of publishDir + pblsh = pblsh.collect{ elem -> + // turn into map if not already so + elem = elem instanceof CharSequence ? [ path: elem ] : elem + + // check types and keys + assert elem instanceof Map : "Expected publish argument '$elem' to be a String or a Map. Found: class ${elem.getClass()}" + assertMapKeys(elem, [ "path", "mode", "overwrite", "pattern", "saveAs", "enabled" ], ["path"], "publishDir") + + // check elements in map + assert elem.containsKey("path") + assert elem["path"] instanceof CharSequence + if (elem.containsKey("mode")) { + assert elem["mode"] instanceof CharSequence + assert elem["mode"] in [ "symlink", "rellink", "link", "copy", "copyNoFollow", "move" ] + } + if (elem.containsKey("overwrite")) { + assert elem["overwrite"] instanceof Boolean + } + if (elem.containsKey("pattern")) { + assert elem["pattern"] instanceof CharSequence + } + if (elem.containsKey("saveAs")) { + assert elem["saveAs"] instanceof CharSequence //: "saveAs as a Closure is currently not supported. Surround your closure with single quotes to get the desired effect. Example: '\{ foo \}'" + } + if (elem.containsKey("enabled")) { + assert elem["enabled"] instanceof Boolean + } + + // return final result + elem + } + // store final directive + drctv["publishDir"] = pblsh + } + + /* DIRECTIVE queue + accepted examples: + - "long" + - "short,long" + - ["short", "long"] + */ + if (drctv.containsKey("queue")) { + if (drctv["queue"] instanceof List) { + drctv["queue"] = drctv["queue"].join(",") + } + assert drctv["queue"] instanceof CharSequence + } + + /* DIRECTIVE label + accepted examples: + - "big_mem" + - "big_cpu" + - ["big_mem", "big_cpu"] + */ + if (drctv.containsKey("label")) { + if (drctv["label"] instanceof CharSequence) { + drctv["label"] = [ drctv["label"] ] + } + assert drctv["label"] instanceof List + drctv["label"].forEach { label -> + assert label instanceof CharSequence + // assert label.matches("[a-zA-Z0-9]([a-zA-Z0-9_]*[a-zA-Z0-9])?") + // ^ does not allow closures + } + } + + /* DIRECTIVE scratch + accepted examples: + - true + - "/path/to/scratch" + - '$MY_PATH_TO_SCRATCH' + - "ram-disk" + */ + if (drctv.containsKey("scratch")) { + assert drctv["scratch"] == true || drctv["scratch"] instanceof CharSequence + } + + /* DIRECTIVE storeDir + accepted examples: + - "/path/to/storeDir" + */ + if (drctv.containsKey("storeDir")) { + assert drctv["storeDir"] instanceof CharSequence + } + + /* DIRECTIVE stageInMode + accepted examples: + - "copy" + - "link" + */ + if (drctv.containsKey("stageInMode")) { + assert drctv["stageInMode"] instanceof CharSequence + assert drctv["stageInMode"] in ["copy", "link", "symlink", "rellink"] + } + + /* DIRECTIVE stageOutMode + accepted examples: + - "copy" + - "link" + */ + if (drctv.containsKey("stageOutMode")) { + assert drctv["stageOutMode"] instanceof CharSequence + assert drctv["stageOutMode"] in ["copy", "move", "rsync"] + } + + /* DIRECTIVE tag + accepted examples: + - "foo" + - '$id' + */ + if (drctv.containsKey("tag")) { + assert drctv["tag"] instanceof CharSequence + } + + /* DIRECTIVE time + accepted examples: + - "1h" + - "2days" + - "1day 6hours 3minutes 30seconds" + */ + if (drctv.containsKey("time")) { + assert drctv["time"] instanceof CharSequence + // todo: validation regex? + } + + return drctv +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/workflowFactory/processWorkflowArgs.nf' +def processWorkflowArgs(Map args, Map defaultWfArgs, Map meta) { + // override defaults with args + def workflowArgs = defaultWfArgs + args + + // check whether 'key' exists + assert workflowArgs.containsKey("key") : "Error in module '${meta.config.name}': key is a required argument" + + // if 'key' is a closure, apply it to the original key + if (workflowArgs["key"] instanceof Closure) { + workflowArgs["key"] = workflowArgs["key"](meta.config.name) + } + def key = workflowArgs["key"] + assert key instanceof CharSequence : "Expected process argument 'key' to be a String. Found: class ${key.getClass()}" + assert key ==~ /^[a-zA-Z_]\w*$/ : "Error in module '$key': Expected process argument 'key' to consist of only letters, digits or underscores. Found: ${key}" + + // check for any unexpected keys + def expectedKeys = ["key", "directives", "auto", "map", "mapId", "mapData", "mapPassthrough", "filter", "runIf", "fromState", "toState", "args", "renameKeys", "debug"] + def unexpectedKeys = workflowArgs.keySet() - expectedKeys + assert unexpectedKeys.isEmpty() : "Error in module '$key': unexpected arguments to the '.run()' function: '${unexpectedKeys.join("', '")}'" + + // check whether directives exists and apply defaults + assert workflowArgs.containsKey("directives") : "Error in module '$key': directives is a required argument" + assert workflowArgs["directives"] instanceof Map : "Error in module '$key': Expected process argument 'directives' to be a Map. Found: class ${workflowArgs['directives'].getClass()}" + workflowArgs["directives"] = processDirectives(defaultWfArgs.directives + workflowArgs["directives"]) + + // check whether directives exists and apply defaults + assert workflowArgs.containsKey("auto") : "Error in module '$key': auto is a required argument" + assert workflowArgs["auto"] instanceof Map : "Error in module '$key': Expected process argument 'auto' to be a Map. Found: class ${workflowArgs['auto'].getClass()}" + workflowArgs["auto"] = processAuto(defaultWfArgs.auto + workflowArgs["auto"]) + + // auto define publish, if so desired + if (workflowArgs.auto.publish == true && (workflowArgs.directives.publishDir != null ? workflowArgs.directives.publishDir : [:]).isEmpty()) { + // can't assert at this level thanks to the no_publish profile + // assert params.containsKey("publishDir") || params.containsKey("publish_dir") : + // "Error in module '${workflowArgs['key']}': if auto.publish is true, params.publish_dir needs to be defined.\n" + + // " Example: params.publish_dir = \"./output/\"" + def publishDir = getPublishDir() + + if (publishDir != null) { + workflowArgs.directives.publishDir = [[ + path: publishDir, + saveAs: "{ it.startsWith('.') ? null : it }", // don't publish hidden files, by default + mode: "copy" + ]] + } + } + + // auto define transcript, if so desired + if (workflowArgs.auto.transcript == true) { + // can't assert at this level thanks to the no_publish profile + // assert params.containsKey("transcriptsDir") || params.containsKey("transcripts_dir") || params.containsKey("publishDir") || params.containsKey("publish_dir") : + // "Error in module '${workflowArgs['key']}': if auto.transcript is true, either params.transcripts_dir or params.publish_dir needs to be defined.\n" + + // " Example: params.transcripts_dir = \"./transcripts/\"" + def transcriptsDir = + params.containsKey("transcripts_dir") ? params.transcripts_dir : + params.containsKey("transcriptsDir") ? params.transcriptsDir : + params.containsKey("publish_dir") ? params.publish_dir + "/_transcripts" : + params.containsKey("publishDir") ? params.publishDir + "/_transcripts" : + null + if (transcriptsDir != null) { + def timestamp = nextflow.Nextflow.getSession().getWorkflowMetadata().start.format('yyyy-MM-dd_HH-mm-ss') + def transcriptsPublishDir = [ + path: "$transcriptsDir/$timestamp/\${task.process.replaceAll(':', '-')}/\${id}/", + saveAs: "{ it.startsWith('.') ? it.replaceAll('^.', '') : null }", + mode: "copy" + ] + def publishDirs = workflowArgs.directives.publishDir != null ? workflowArgs.directives.publishDir : null ? workflowArgs.directives.publishDir : [] + workflowArgs.directives.publishDir = publishDirs + transcriptsPublishDir + } + } + + // if this is a stubrun, remove certain directives? + if (workflow.stubRun) { + workflowArgs.directives.keySet().removeAll(["publishDir", "cpus", "memory", "label"]) + } + + for (nam in ["map", "mapId", "mapData", "mapPassthrough", "filter", "runIf"]) { + if (workflowArgs.containsKey(nam) && workflowArgs[nam]) { + assert workflowArgs[nam] instanceof Closure : "Error in module '$key': Expected process argument '$nam' to be null or a Closure. Found: class ${workflowArgs[nam].getClass()}" + } + } + + // TODO: should functions like 'map', 'mapId', 'mapData', 'mapPassthrough' be deprecated as well? + for (nam in ["map", "mapData", "mapPassthrough", "renameKeys"]) { + if (workflowArgs.containsKey(nam) && workflowArgs[nam] != null) { + log.warn "module '$key': workflow argument '$nam' is deprecated and will be removed in Viash 0.9.0. Please use 'fromState' and 'toState' instead." + } + } + + // check fromState + workflowArgs["fromState"] = _processFromState(workflowArgs.get("fromState"), key, meta.config) + + // check toState + workflowArgs["toState"] = _processToState(workflowArgs.get("toState"), key, meta.config) + + // return output + return workflowArgs +} + +def _processFromState(fromState, key_, config_) { + assert fromState == null || fromState instanceof Closure || fromState instanceof Map || fromState instanceof List : + "Error in module '$key_': Expected process argument 'fromState' to be null, a Closure, a Map, or a List. Found: class ${fromState.getClass()}" + if (fromState == null) { + return null + } + + // if fromState is a List, convert to map + if (fromState instanceof List) { + // check whether fromstate is a list[string] + assert fromState.every{it instanceof CharSequence} : "Error in module '$key_': fromState is a List, but not all elements are Strings" + fromState = fromState.collectEntries{[it, it]} + } + + // if fromState is a map, convert to closure + if (fromState instanceof Map) { + // check whether fromstate is a map[string, string] + assert fromState.values().every{it instanceof CharSequence} : "Error in module '$key_': fromState is a Map, but not all values are Strings" + assert fromState.keySet().every{it instanceof CharSequence} : "Error in module '$key_': fromState is a Map, but not all keys are Strings" + def fromStateMap = fromState.clone() + def requiredInputNames = meta.config.allArguments.findAll{it.required && it.direction == "Input"}.collect{it.plainName} + // turn the map into a closure to be used later on + fromState = { it -> + def state = it[1] + assert state instanceof Map : "Error in module '$key_': the state is not a Map" + def data = fromStateMap.collectMany{newkey, origkey -> + // check whether newkey corresponds to a required argument + if (state.containsKey(origkey)) { + [[newkey, state[origkey]]] + } else if (!requiredInputNames.contains(origkey)) { + [] + } else { + throw new Exception("Error in module '$key_': fromState key '$origkey' not found in current state") + } + }.collectEntries() + data + } + } + + return fromState +} + +def _processToState(toState, key_, config_) { + if (toState == null) { + toState = { tup -> tup[1] } + } + + // toState should be a closure, map[string, string], or list[string] + assert toState instanceof Closure || toState instanceof Map || toState instanceof List : + "Error in module '$key_': Expected process argument 'toState' to be a Closure, a Map, or a List. Found: class ${toState.getClass()}" + + // if toState is a List, convert to map + if (toState instanceof List) { + // check whether toState is a list[string] + assert toState.every{it instanceof CharSequence} : "Error in module '$key_': toState is a List, but not all elements are Strings" + toState = toState.collectEntries{[it, it]} + } + + // if toState is a map, convert to closure + if (toState instanceof Map) { + // check whether toState is a map[string, string] + assert toState.values().every{it instanceof CharSequence} : "Error in module '$key_': toState is a Map, but not all values are Strings" + assert toState.keySet().every{it instanceof CharSequence} : "Error in module '$key_': toState is a Map, but not all keys are Strings" + def toStateMap = toState.clone() + def requiredOutputNames = config_.allArguments.findAll{it.required && it.direction == "Output"}.collect{it.plainName} + // turn the map into a closure to be used later on + toState = { it -> + def output = it[1] + def state = it[2] + assert output instanceof Map : "Error in module '$key_': the output is not a Map" + assert state instanceof Map : "Error in module '$key_': the state is not a Map" + def extraEntries = toStateMap.collectMany{newkey, origkey -> + // check whether newkey corresponds to a required argument + if (output.containsKey(origkey)) { + [[newkey, output[origkey]]] + } else if (!requiredOutputNames.contains(origkey)) { + [] + } else { + throw new Exception("Error in module '$key_': toState key '$origkey' not found in current output") + } + }.collectEntries() + state + extraEntries + } + } + + return toState +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/workflowFactory/workflowFactory.nf' +def _debug(workflowArgs, debugKey) { + if (workflowArgs.debug) { + view { "process '${workflowArgs.key}' $debugKey tuple: $it" } + } else { + map { it } + } +} + +// depends on: innerWorkflowFactory +def workflowFactory(Map args, Map defaultWfArgs, Map meta) { + def workflowArgs = processWorkflowArgs(args, defaultWfArgs, meta) + def key_ = workflowArgs["key"] + + workflow workflowInstance { + take: input_ + + main: + def chModified = input_ + | checkUniqueIds([:]) + | _debug(workflowArgs, "input") + | map { tuple -> + tuple = deepClone(tuple) + + if (workflowArgs.map) { + tuple = workflowArgs.map(tuple) + } + if (workflowArgs.mapId) { + tuple[0] = workflowArgs.mapId(tuple[0]) + } + if (workflowArgs.mapData) { + tuple[1] = workflowArgs.mapData(tuple[1]) + } + if (workflowArgs.mapPassthrough) { + tuple = tuple.take(2) + workflowArgs.mapPassthrough(tuple.drop(2)) + } + + // check tuple + assert tuple instanceof List : + "Error in module '${key_}': element in channel should be a tuple [id, data, ...otherargs...]\n" + + " Example: [\"id\", [input: file('foo.txt'), arg: 10]].\n" + + " Expected class: List. Found: tuple.getClass() is ${tuple.getClass()}" + assert tuple.size() >= 2 : + "Error in module '${key_}': expected length of tuple in input channel to be two or greater.\n" + + " Example: [\"id\", [input: file('foo.txt'), arg: 10]].\n" + + " Found: tuple.size() == ${tuple.size()}" + + // check id field + if (tuple[0] instanceof GString) { + tuple[0] = tuple[0].toString() + } + assert tuple[0] instanceof CharSequence : + "Error in module '${key_}': first element of tuple in channel should be a String\n" + + " Example: [\"id\", [input: file('foo.txt'), arg: 10]].\n" + + " Found: ${tuple[0]}" + + // match file to input file + if (workflowArgs.auto.simplifyInput && (tuple[1] instanceof Path || tuple[1] instanceof List)) { + def inputFiles = meta.config.allArguments + .findAll { it.type == "file" && it.direction == "input" } + + assert inputFiles.size() == 1 : + "Error in module '${key_}' id '${tuple[0]}'.\n" + + " Anonymous file inputs are only allowed when the process has exactly one file input.\n" + + " Expected: inputFiles.size() == 1. Found: inputFiles.size() is ${inputFiles.size()}" + + tuple[1] = [[ inputFiles[0].plainName, tuple[1] ]].collectEntries() + } + + // check data field + assert tuple[1] instanceof Map : + "Error in module '${key_}' id '${tuple[0]}': second element of tuple in channel should be a Map\n" + + " Example: [\"id\", [input: file('foo.txt'), arg: 10]].\n" + + " Expected class: Map. Found: tuple[1].getClass() is ${tuple[1].getClass()}" + + // rename keys of data field in tuple + if (workflowArgs.renameKeys) { + assert workflowArgs.renameKeys instanceof Map : + "Error renaming data keys in module '${key_}' id '${tuple[0]}'.\n" + + " Example: renameKeys: ['new_key': 'old_key'].\n" + + " Expected class: Map. Found: renameKeys.getClass() is ${workflowArgs.renameKeys.getClass()}" + assert tuple[1] instanceof Map : + "Error renaming data keys in module '${key_}' id '${tuple[0]}'.\n" + + " Expected class: Map. Found: tuple[1].getClass() is ${tuple[1].getClass()}" + + // TODO: allow renameKeys to be a function? + workflowArgs.renameKeys.each { newKey, oldKey -> + assert newKey instanceof CharSequence : + "Error renaming data keys in module '${key_}' id '${tuple[0]}'.\n" + + " Example: renameKeys: ['new_key': 'old_key'].\n" + + " Expected class of newKey: String. Found: newKey.getClass() is ${newKey.getClass()}" + assert oldKey instanceof CharSequence : + "Error renaming data keys in module '${key_}' id '${tuple[0]}'.\n" + + " Example: renameKeys: ['new_key': 'old_key'].\n" + + " Expected class of oldKey: String. Found: oldKey.getClass() is ${oldKey.getClass()}" + assert tuple[1].containsKey(oldKey) : + "Error renaming data keys in module '${key}' id '${tuple[0]}'.\n" + + " Key '$oldKey' is missing in the data map. tuple[1].keySet() is '${tuple[1].keySet()}'" + tuple[1].put(newKey, tuple[1][oldKey]) + } + tuple[1].keySet().removeAll(workflowArgs.renameKeys.collect{ newKey, oldKey -> oldKey }) + } + tuple + } + + def chModifiedFiltered = workflowArgs.filter ? + chModified | filter{workflowArgs.filter(it)} : + chModified + + def chRun = null + def chPassthrough = null + if (workflowArgs.runIf) { + def runIfBranch = chModifiedFiltered.branch{ tup -> + run: workflowArgs.runIf(tup[0], tup[1]) + passthrough: true + } + chRun = runIfBranch.run + chPassthrough = runIfBranch.passthrough + } else { + chRun = chModifiedFiltered + chPassthrough = Channel.empty() + } + + def chArgs = workflowArgs.fromState ? + chRun | map{ + def new_data = workflowArgs.fromState(it.take(2)) + [it[0], new_data] + } : + chRun | map {tup -> tup.take(2)} + + // fill in defaults + def chArgsWithDefaults = chArgs + | map { tuple -> + def id_ = tuple[0] + def data_ = tuple[1] + + // TODO: could move fromState to here + + // fetch default params from functionality + def defaultArgs = meta.config.allArguments + .findAll { it.containsKey("default") } + .collectEntries { [ it.plainName, it.default ] } + + // fetch overrides in params + def paramArgs = meta.config.allArguments + .findAll { par -> + def argKey = key_ + "__" + par.plainName + params.containsKey(argKey) + } + .collectEntries { [ it.plainName, params[key_ + "__" + it.plainName] ] } + + // fetch overrides in data + def dataArgs = meta.config.allArguments + .findAll { data_.containsKey(it.plainName) } + .collectEntries { [ it.plainName, data_[it.plainName] ] } + + // combine params + def combinedArgs = defaultArgs + paramArgs + workflowArgs.args + dataArgs + + // remove arguments with explicit null values + combinedArgs + .removeAll{_, val -> val == null || val == "viash_no_value" || val == "force_null"} + + combinedArgs = _processInputValues(combinedArgs, meta.config, id_, key_) + + [id_, combinedArgs] + tuple.drop(2) + } + + // TODO: move some of the _meta.join_id wrangling to the safeJoin() function. + def chInitialOutput = chArgsWithDefaults + | _debug(workflowArgs, "processed") + // run workflow + | innerWorkflowFactory(workflowArgs) + // check output tuple + | map { id_, output_ -> + + // see if output map contains metadata + def meta_ = + output_ instanceof Map && output_.containsKey("_meta") ? + output_["_meta"] : + [:] + def join_id = meta_.join_id ?: id_ + + // remove metadata + output_ = output_.findAll{k, v -> k != "_meta"} + + // check value types + output_ = _processOutputValues(output_, meta.config, id_, key_) + + // simplify output if need be + if (workflowArgs.auto.simplifyOutput && output_.size() == 1) { + output_ = output_.values()[0] + } + + [join_id, id_, output_] + } + // | view{"chInitialOutput: ${it.take(3)}"} + + // join the output [prev_id, new_id, output] with the previous state [prev_id, state, ...] + def chNewState = safeJoin(chInitialOutput, chModifiedFiltered, key_) + // input tuple format: [join_id, id, output, prev_state, ...] + // output tuple format: [join_id, id, new_state, ...] + | map{ tup -> + def new_state = workflowArgs.toState(tup.drop(1).take(3)) + tup.take(2) + [new_state] + tup.drop(4) + } + + if (workflowArgs.auto.publish == "state") { + def chPublish = chNewState + // input tuple format: [join_id, id, new_state, ...] + // output tuple format: [join_id, id, new_state] + | map{ tup -> + tup.take(3) + } + + safeJoin(chPublish, chArgsWithDefaults, key_) + // input tuple format: [join_id, id, new_state, orig_state, ...] + // output tuple format: [id, new_state, orig_state] + | map { tup -> + tup.drop(1).take(3) + } + | publishStatesByConfig(key: key_, config: meta.config) + } + + // remove join_id and meta + chReturn = chNewState + | map { tup -> + // input tuple format: [join_id, id, new_state, ...] + // output tuple format: [id, new_state, ...] + tup.drop(1) + } + | _debug(workflowArgs, "output") + | concat(chPassthrough) + + emit: chReturn + } + + def wf = workflowInstance.cloneWithName(key_) + + // add factory function + wf.metaClass.run = { runArgs -> + workflowFactory(runArgs, workflowArgs, meta) + } + // add config to module for later introspection + wf.metaClass.config = meta.config + + return wf +} + +nextflow.enable.dsl=2 + +// START COMPONENT-SPECIFIC CODE + +// create meta object +meta = [ + "resources_dir": moduleDir.toRealPath().normalize(), + "config": processConfig(readJsonBlob('''{ + "name" : "agat_convert_sp_gff2tsv", + "namespace" : "agat", + "version" : "main", + "authors" : [ + { + "name" : "Leïla Paquay", + "roles" : [ + "author", + "maintainer" + ], + "info" : { + "links" : { + "email" : "leila@data-intuitive.com", + "github" : "Leila011", + "linkedin" : "leilapaquay" + }, + "organizations" : [ + { + "name" : "Data Intuitive", + "href" : "https://www.data-intuitive.com", + "role" : "Software Developer" + } + ] + } + } + ], + "argument_groups" : [ + { + "name" : "Inputs", + "arguments" : [ + { + "type" : "file", + "name" : "--gff", + "alternatives" : [ + "-f" + ], + "description" : "Input GTF/GFF file.", + "example" : [ + "input.gff" + ], + "must_exist" : true, + "create_parent" : true, + "required" : true, + "direction" : "input", + "multiple" : false, + "multiple_sep" : ";" + } + ] + }, + { + "name" : "Outputs", + "arguments" : [ + { + "type" : "file", + "name" : "--output", + "alternatives" : [ + "-o", + "--out", + "--outfile" + ], + "description" : "Output GFF file. If no output file is specified, the output will be written to STDOUT.", + "example" : [ + "output.gff" + ], + "must_exist" : true, + "create_parent" : true, + "required" : true, + "direction" : "output", + "multiple" : false, + "multiple_sep" : ";" + } + ] + }, + { + "name" : "Arguments", + "arguments" : [ + { + "type" : "file", + "name" : "--config", + "alternatives" : [ + "-c" + ], + "description" : "String - Input agat config file. By default AGAT takes as input\nagat_config.yaml file from the working directory if any,\notherwise it takes the orignal agat_config.yaml shipped with\nAGAT. To get the agat_config.yaml locally type: \\"agat config\n--expose\\". The --config option gives you the possibility to use\nyour own AGAT config file (located elsewhere or named\ndifferently). \n", + "example" : [ + "custom_agat_config.yaml" + ], + "must_exist" : true, + "create_parent" : true, + "required" : false, + "direction" : "input", + "multiple" : false, + "multiple_sep" : ";" + } + ] + } + ], + "resources" : [ + { + "type" : "bash_script", + "path" : "script.sh", + "is_executable" : true + } + ], + "description" : "The script aims to convert gtf/gff file into tabulated file. Attribute's\ntags from the 9th column become column titles.\n", + "test_resources" : [ + { + "type" : "bash_script", + "path" : "test.sh", + "is_executable" : true + }, + { + "type" : "file", + "path" : "test_data" + } + ], + "status" : "enabled", + "requirements" : { + "commands" : [ + "ps" + ] + }, + "keywords" : [ + "gene annotations", + "GFF conversion" + ], + "license" : "GPL-3.0", + "references" : { + "doi" : [ + "10.5281/zenodo.3552717" + ] + }, + "links" : { + "repository" : "https://github.com/NBISweden/AGAT", + "homepage" : "https://github.com/NBISweden/AGAT", + "documentation" : "https://agat.readthedocs.io/en/latest/tools/agat_convert_sp_gff2tsv.html", + "issue_tracker" : "https://github.com/NBISweden/AGAT/issues" + }, + "runners" : [ + { + "type" : "executable", + "id" : "executable", + "docker_setup_strategy" : "ifneedbepullelsecachedbuild" + }, + { + "type" : "nextflow", + "id" : "nextflow", + "directives" : { + "tag" : "$id" + }, + "auto" : { + "simplifyInput" : true, + "simplifyOutput" : false, + "transcript" : false, + "publish" : false + }, + "config" : { + "labels" : { + "mem1gb" : "memory = 1000000000.B", + "mem2gb" : "memory = 2000000000.B", + "mem5gb" : "memory = 5000000000.B", + "mem10gb" : "memory = 10000000000.B", + "mem20gb" : "memory = 20000000000.B", + "mem50gb" : "memory = 50000000000.B", + "mem100gb" : "memory = 100000000000.B", + "mem200gb" : "memory = 200000000000.B", + "mem500gb" : "memory = 500000000000.B", + "mem1tb" : "memory = 1000000000000.B", + "mem2tb" : "memory = 2000000000000.B", + "mem5tb" : "memory = 5000000000000.B", + "mem10tb" : "memory = 10000000000000.B", + "mem20tb" : "memory = 20000000000000.B", + "mem50tb" : "memory = 50000000000000.B", + "mem100tb" : "memory = 100000000000000.B", + "mem200tb" : "memory = 200000000000000.B", + "mem500tb" : "memory = 500000000000000.B", + "mem1gib" : "memory = 1073741824.B", + "mem2gib" : "memory = 2147483648.B", + "mem4gib" : "memory = 4294967296.B", + "mem8gib" : "memory = 8589934592.B", + "mem16gib" : "memory = 17179869184.B", + "mem32gib" : "memory = 34359738368.B", + "mem64gib" : "memory = 68719476736.B", + "mem128gib" : "memory = 137438953472.B", + "mem256gib" : "memory = 274877906944.B", + "mem512gib" : "memory = 549755813888.B", + "mem1tib" : "memory = 1099511627776.B", + "mem2tib" : "memory = 2199023255552.B", + "mem4tib" : "memory = 4398046511104.B", + "mem8tib" : "memory = 8796093022208.B", + "mem16tib" : "memory = 17592186044416.B", + "mem32tib" : "memory = 35184372088832.B", + "mem64tib" : "memory = 70368744177664.B", + "mem128tib" : "memory = 140737488355328.B", + "mem256tib" : "memory = 281474976710656.B", + "mem512tib" : "memory = 562949953421312.B", + "cpu1" : "cpus = 1", + "cpu2" : "cpus = 2", + "cpu5" : "cpus = 5", + "cpu10" : "cpus = 10", + "cpu20" : "cpus = 20", + "cpu50" : "cpus = 50", + "cpu100" : "cpus = 100", + "cpu200" : "cpus = 200", + "cpu500" : "cpus = 500", + "cpu1000" : "cpus = 1000" + } + }, + "debug" : false, + "container" : "docker" + } + ], + "engines" : [ + { + "type" : "docker", + "id" : "docker", + "image" : "quay.io/biocontainers/agat:1.4.0--pl5321hdfd78af_0", + "target_registry" : "images.viash-hub.com", + "target_tag" : "main", + "namespace_separator" : "/", + "setup" : [ + { + "type" : "docker", + "run" : [ + "agat --version | sed 's/AGAT\\\\s\\\\(.*\\\\)/agat: \\"\\\\1\\"/' > /var/software_versions.txt\n" + ] + } + ] + }, + { + "type" : "native", + "id" : "native" + } + ], + "build_info" : { + "config" : "/workdir/root/repo/src/agat/agat_convert_sp_gff2tsv/config.vsh.yaml", + "runner" : "nextflow", + "engine" : "docker|native", + "output" : "target/nextflow/agat/agat_convert_sp_gff2tsv", + "viash_version" : "0.9.0-RC6", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", + "git_remote" : "https://github.com/viash-hub/biobox" + }, + "package_config" : { + "name" : "biobox", + "version" : "main", + "description" : "A collection of bioinformatics tools for working with sequence data.\n", + "viash_version" : "0.9.0-RC6", + "source" : "src", + "target" : "target", + "config_mods" : [ + ".requirements.commands := ['ps']\n", + ".engines += { type: \\"native\\" }", + ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'", + ".engines[.type == 'docker'].target_tag := 'main'" + ], + "keywords" : [ + "bioinformatics", + "modules", + "sequencing" + ], + "license" : "MIT", + "organization" : "vsh", + "links" : { + "repository" : "https://github.com/viash-hub/biobox", + "issue_tracker" : "https://github.com/viash-hub/biobox/issues" + } + } +}''')) +] + +// resolve dependencies dependencies (if any) + + +// inner workflow +// inner workflow hook +def innerWorkflowFactory(args) { + def rawScript = '''set -e +tempscript=".viash_script.sh" +cat > "$tempscript" << VIASHMAIN +#!/bin/bash + +## VIASH START +# The following code has been auto-generated by Viash. +$( if [ ! -z ${VIASH_PAR_GFF+x} ]; then echo "${VIASH_PAR_GFF}" | sed "s#'#'\\"'\\"'#g;s#.*#par_gff='&'#" ; else echo "# par_gff="; fi ) +$( if [ ! -z ${VIASH_PAR_OUTPUT+x} ]; then echo "${VIASH_PAR_OUTPUT}" | sed "s#'#'\\"'\\"'#g;s#.*#par_output='&'#" ; else echo "# par_output="; fi ) +$( if [ ! -z ${VIASH_PAR_CONFIG+x} ]; then echo "${VIASH_PAR_CONFIG}" | sed "s#'#'\\"'\\"'#g;s#.*#par_config='&'#" ; else echo "# par_config="; fi ) +$( if [ ! -z ${VIASH_META_NAME+x} ]; then echo "${VIASH_META_NAME}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_name='&'#" ; else echo "# meta_name="; fi ) +$( if [ ! -z ${VIASH_META_FUNCTIONALITY_NAME+x} ]; then echo "${VIASH_META_FUNCTIONALITY_NAME}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_functionality_name='&'#" ; else echo "# meta_functionality_name="; fi ) +$( if [ ! -z ${VIASH_META_RESOURCES_DIR+x} ]; then echo "${VIASH_META_RESOURCES_DIR}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_resources_dir='&'#" ; else echo "# meta_resources_dir="; fi ) +$( if [ ! -z ${VIASH_META_EXECUTABLE+x} ]; then echo "${VIASH_META_EXECUTABLE}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_executable='&'#" ; else echo "# meta_executable="; fi ) +$( if [ ! -z ${VIASH_META_CONFIG+x} ]; then echo "${VIASH_META_CONFIG}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_config='&'#" ; else echo "# meta_config="; fi ) +$( if [ ! -z ${VIASH_META_TEMP_DIR+x} ]; then echo "${VIASH_META_TEMP_DIR}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_temp_dir='&'#" ; else echo "# meta_temp_dir="; fi ) +$( if [ ! -z ${VIASH_META_CPUS+x} ]; then echo "${VIASH_META_CPUS}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_cpus='&'#" ; else echo "# meta_cpus="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_B+x} ]; then echo "${VIASH_META_MEMORY_B}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_b='&'#" ; else echo "# meta_memory_b="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_KB+x} ]; then echo "${VIASH_META_MEMORY_KB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_kb='&'#" ; else echo "# meta_memory_kb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_MB+x} ]; then echo "${VIASH_META_MEMORY_MB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_mb='&'#" ; else echo "# meta_memory_mb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_GB+x} ]; then echo "${VIASH_META_MEMORY_GB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_gb='&'#" ; else echo "# meta_memory_gb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_TB+x} ]; then echo "${VIASH_META_MEMORY_TB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_tb='&'#" ; else echo "# meta_memory_tb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_PB+x} ]; then echo "${VIASH_META_MEMORY_PB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_pb='&'#" ; else echo "# meta_memory_pb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_KIB+x} ]; then echo "${VIASH_META_MEMORY_KIB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_kib='&'#" ; else echo "# meta_memory_kib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_MIB+x} ]; then echo "${VIASH_META_MEMORY_MIB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_mib='&'#" ; else echo "# meta_memory_mib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_GIB+x} ]; then echo "${VIASH_META_MEMORY_GIB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_gib='&'#" ; else echo "# meta_memory_gib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_TIB+x} ]; then echo "${VIASH_META_MEMORY_TIB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_tib='&'#" ; else echo "# meta_memory_tib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_pib='&'#" ; else echo "# meta_memory_pib="; fi ) + +## VIASH END + +agat_convert_sp_gff2tsv.pl \\\\ + -f "\\$par_gff" \\\\ + -o "\\$par_output" \\\\ + \\${par_config:+--config "\\${par_config}"} +VIASHMAIN +bash "$tempscript" +''' + + return vdsl3WorkflowFactory(args, meta, rawScript) +} + + + +/** + * Generate a workflow for VDSL3 modules. + * + * This function is called by the workflowFactory() function. + * + * Input channel: [id, input_map] + * Output channel: [id, output_map] + * + * Internally, this workflow will convert the input channel + * to a format which the Nextflow module will be able to handle. + */ +def vdsl3WorkflowFactory(Map args, Map meta, String rawScript) { + def key = args["key"] + def processObj = null + + workflow processWf { + take: input_ + main: + + if (processObj == null) { + processObj = _vdsl3ProcessFactory(args, meta, rawScript) + } + + output_ = input_ + | map { tuple -> + def id = tuple[0] + def data_ = tuple[1] + + if (workflow.stubRun) { + // add id if missing + data_ = [id: 'stub'] + data_ + } + + // process input files separately + def inputPaths = meta.config.allArguments + .findAll { it.type == "file" && it.direction == "input" } + .collect { par -> + def val = data_.containsKey(par.plainName) ? data_[par.plainName] : [] + def inputFiles = [] + if (val == null) { + inputFiles = [] + } else if (val instanceof List) { + inputFiles = val + } else if (val instanceof Path) { + inputFiles = [ val ] + } else { + inputFiles = [] + } + if (!workflow.stubRun) { + // throw error when an input file doesn't exist + inputFiles.each{ file -> + assert file.exists() : + "Error in module '${key}' id '${id}' argument '${par.plainName}'.\n" + + " Required input file does not exist.\n" + + " Path: '$file'.\n" + + " Expected input file to exist" + } + } + inputFiles + } + + // remove input files + def argsExclInputFiles = meta.config.allArguments + .findAll { (it.type != "file" || it.direction != "input") && data_.containsKey(it.plainName) } + .collectEntries { par -> + def parName = par.plainName + def val = data_[parName] + if (par.multiple && val instanceof Collection) { + val = val.join(par.multiple_sep) + } + if (par.direction == "output" && par.type == "file") { + val = val.replaceAll('\\$id', id).replaceAll('\\$key', key) + } + [parName, val] + } + + [ id ] + inputPaths + [ argsExclInputFiles, meta.resources_dir ] + } + | processObj + | map { output -> + def outputFiles = meta.config.allArguments + .findAll { it.type == "file" && it.direction == "output" } + .indexed() + .collectEntries{ index, par -> + def out = output[index + 1] + // strip dummy '.exitcode' file from output (see nextflow-io/nextflow#2678) + if (!out instanceof List || out.size() <= 1) { + if (par.multiple) { + out = [] + } else { + assert !par.required : + "Error in module '${key}' id '${output[0]}' argument '${par.plainName}'.\n" + + " Required output file is missing" + out = null + } + } else if (out.size() == 2 && !par.multiple) { + out = out[1] + } else { + out = out.drop(1) + } + [ par.plainName, out ] + } + + // drop null outputs + outputFiles.removeAll{it.value == null} + + [ output[0], outputFiles ] + } + emit: output_ + } + + return processWf +} + +// depends on: session? +def _vdsl3ProcessFactory(Map workflowArgs, Map meta, String rawScript) { + // autodetect process key + def wfKey = workflowArgs["key"] + def procKeyPrefix = "${wfKey}_process" + def scriptMeta = nextflow.script.ScriptMeta.current() + def existing = scriptMeta.getProcessNames().findAll{it.startsWith(procKeyPrefix)} + def numbers = existing.collect{it.replace(procKeyPrefix, "0").toInteger()} + def newNumber = (numbers + [-1]).max() + 1 + + def procKey = newNumber == 0 ? procKeyPrefix : "$procKeyPrefix$newNumber" + + if (newNumber > 0) { + log.warn "Key for module '${wfKey}' is duplicated.\n", + "If you run a component multiple times in the same workflow,\n" + + "it's recommended you set a unique key for every call,\n" + + "for example: ${wfKey}.run(key: \"foo\")." + } + + // subset directives and convert to list of tuples + def drctv = workflowArgs.directives + + // TODO: unit test the two commands below + // convert publish array into tags + def valueToStr = { val -> + // ignore closures + if (val instanceof CharSequence) { + if (!val.matches('^[{].*[}]$')) { + '"' + val + '"' + } else { + val + } + } else if (val instanceof List) { + "[" + val.collect{valueToStr(it)}.join(", ") + "]" + } else if (val instanceof Map) { + "[" + val.collect{k, v -> k + ": " + valueToStr(v)}.join(", ") + "]" + } else { + val.inspect() + } + } + + // multiple entries allowed: label, publishdir + def drctvStrs = drctv.collect { key, value -> + if (key in ["label", "publishDir"]) { + value.collect{ val -> + if (val instanceof Map) { + "\n$key " + val.collect{ k, v -> k + ": " + valueToStr(v) }.join(", ") + } else if (val == null) { + "" + } else { + "\n$key " + valueToStr(val) + } + }.join() + } else if (value instanceof Map) { + "\n$key " + value.collect{ k, v -> k + ": " + valueToStr(v) }.join(", ") + } else { + "\n$key " + valueToStr(value) + } + }.join() + + def inputPaths = meta.config.allArguments + .findAll { it.type == "file" && it.direction == "input" } + .collect { ', path(viash_par_' + it.plainName + ', stageAs: "_viash_par/' + it.plainName + '_?/*")' } + .join() + + def outputPaths = meta.config.allArguments + .findAll { it.type == "file" && it.direction == "output" } + .collect { par -> + // insert dummy into every output (see nextflow-io/nextflow#2678) + if (!par.multiple) { + ', path{[".exitcode", args.' + par.plainName + ']}' + } else { + ', path{[".exitcode"] + args.' + par.plainName + '}' + } + } + .join() + + // TODO: move this functionality somewhere else? + if (workflowArgs.auto.transcript) { + outputPaths = outputPaths + ', path{[".exitcode", ".command*"]}' + } else { + outputPaths = outputPaths + ', path{[".exitcode"]}' + } + + // create dirs for output files (based on BashWrapper.createParentFiles) + def createParentStr = meta.config.allArguments + .findAll { it.type == "file" && it.direction == "output" && it.create_parent } + .collect { par -> + "\${ args.containsKey(\"${par.plainName}\") ? \"mkdir_parent \\\"\" + (args[\"${par.plainName}\"] instanceof String ? args[\"${par.plainName}\"] : args[\"${par.plainName}\"].join('\" \"')) + \"\\\"\" : \"\" }" + } + .join("\n") + + // construct inputFileExports + def inputFileExports = meta.config.allArguments + .findAll { it.type == "file" && it.direction.toLowerCase() == "input" } + .collect { par -> + def viash_par_contents = "(viash_par_${par.plainName} instanceof List ? viash_par_${par.plainName}.join(\"${par.multiple_sep}\") : viash_par_${par.plainName})" + "\n\${viash_par_${par.plainName}.empty ? \"\" : \"export VIASH_PAR_${par.plainName.toUpperCase()}=\\\"\" + ${viash_par_contents} + \"\\\"\"}" + } + + // NOTE: if using docker, use /tmp instead of tmpDir! + def tmpDir = java.nio.file.Paths.get( + System.getenv('NXF_TEMP') ?: + System.getenv('VIASH_TEMP') ?: + System.getenv('VIASH_TMPDIR') ?: + System.getenv('VIASH_TEMPDIR') ?: + System.getenv('VIASH_TMP') ?: + System.getenv('TEMP') ?: + System.getenv('TMPDIR') ?: + System.getenv('TEMPDIR') ?: + System.getenv('TMP') ?: + '/tmp' + ).toAbsolutePath() + + // construct stub + def stub = meta.config.allArguments + .findAll { it.type == "file" && it.direction == "output" } + .collect { par -> + "\${ args.containsKey(\"${par.plainName}\") ? \"touch2 \\\"\" + (args[\"${par.plainName}\"] instanceof String ? args[\"${par.plainName}\"].replace(\"_*\", \"_0\") : args[\"${par.plainName}\"].join('\" \"')) + \"\\\"\" : \"\" }" + } + .join("\n") + + // escape script + def escapedScript = rawScript.replace('\\', '\\\\').replace('$', '\\$').replace('"""', '\\"\\"\\"') + + // publishdir assert + def assertStr = (workflowArgs.auto.publish == true) || workflowArgs.auto.transcript ? + """\nassert task.publishDir.size() > 0: "if auto.publish is true, params.publish_dir needs to be defined.\\n Example: --publish_dir './output/'" """ : + "" + + // generate process string + def procStr = + """nextflow.enable.dsl=2 + | + |process $procKey {$drctvStrs + |input: + | tuple val(id)$inputPaths, val(args), path(resourcesDir, stageAs: ".viash_meta_resources") + |output: + | tuple val("\$id")$outputPaths, optional: true + |stub: + |\"\"\" + |touch2() { mkdir -p "\\\$(dirname "\\\$1")" && touch "\\\$1" ; } + |$stub + |\"\"\" + |script:$assertStr + |def escapeText = { s -> s.toString().replaceAll('([`"])', '\\\\\\\\\$1') } + |def parInject = args + | .findAll{key, value -> value != null} + | .collect{key, value -> "export VIASH_PAR_\${key.toUpperCase()}=\\\"\${escapeText(value)}\\\""} + | .join("\\n") + |\"\"\" + |# meta exports + |export VIASH_META_RESOURCES_DIR="\${resourcesDir}" + |export VIASH_META_TEMP_DIR="${['docker', 'podman', 'charliecloud'].any{ it == workflow.containerEngine } ? '/tmp' : tmpDir}" + |export VIASH_META_NAME="${meta.config.name}" + |# export VIASH_META_EXECUTABLE="\\\$VIASH_META_RESOURCES_DIR/\\\$VIASH_META_NAME" + |export VIASH_META_CONFIG="\\\$VIASH_META_RESOURCES_DIR/.config.vsh.yaml" + |\${task.cpus ? "export VIASH_META_CPUS=\$task.cpus" : "" } + |\${task.memory?.bytes != null ? "export VIASH_META_MEMORY_B=\$task.memory.bytes" : "" } + |if [ ! -z \\\${VIASH_META_MEMORY_B+x} ]; then + | export VIASH_META_MEMORY_KB=\\\$(( (\\\$VIASH_META_MEMORY_B+999) / 1000 )) + | export VIASH_META_MEMORY_MB=\\\$(( (\\\$VIASH_META_MEMORY_KB+999) / 1000 )) + | export VIASH_META_MEMORY_GB=\\\$(( (\\\$VIASH_META_MEMORY_MB+999) / 1000 )) + | export VIASH_META_MEMORY_TB=\\\$(( (\\\$VIASH_META_MEMORY_GB+999) / 1000 )) + | export VIASH_META_MEMORY_PB=\\\$(( (\\\$VIASH_META_MEMORY_TB+999) / 1000 )) + | export VIASH_META_MEMORY_KIB=\\\$(( (\\\$VIASH_META_MEMORY_B+1023) / 1024 )) + | export VIASH_META_MEMORY_MIB=\\\$(( (\\\$VIASH_META_MEMORY_KIB+1023) / 1024 )) + | export VIASH_META_MEMORY_GIB=\\\$(( (\\\$VIASH_META_MEMORY_MIB+1023) / 1024 )) + | export VIASH_META_MEMORY_TIB=\\\$(( (\\\$VIASH_META_MEMORY_GIB+1023) / 1024 )) + | export VIASH_META_MEMORY_PIB=\\\$(( (\\\$VIASH_META_MEMORY_TIB+1023) / 1024 )) + |fi + | + |# meta synonyms + |export VIASH_TEMP="\\\$VIASH_META_TEMP_DIR" + |export TEMP_DIR="\\\$VIASH_META_TEMP_DIR" + | + |# create output dirs if need be + |function mkdir_parent { + | for file in "\\\$@"; do + | mkdir -p "\\\$(dirname "\\\$file")" + | done + |} + |$createParentStr + | + |# argument exports${inputFileExports.join()} + |\$parInject + | + |# process script + |${escapedScript} + |\"\"\" + |} + |""".stripMargin() + + // TODO: print on debug + // if (workflowArgs.debug == true) { + // println("######################\n$procStr\n######################") + // } + + // write process to temp file + def tempFile = java.nio.file.Files.createTempFile("viash-process-${procKey}-", ".nf") + addShutdownHook { java.nio.file.Files.deleteIfExists(tempFile) } + tempFile.text = procStr + + // create process from temp file + def binding = new nextflow.script.ScriptBinding([:]) + def session = nextflow.Nextflow.getSession() + def parser = new nextflow.script.ScriptParser(session) + .setModule(true) + .setBinding(binding) + def moduleScript = parser.runScript(tempFile) + .getScript() + + // register module in meta + def module = new nextflow.script.IncludeDef.Module(name: procKey) + scriptMeta.addModule(moduleScript, module.name, module.alias) + + // retrieve and return process from meta + return scriptMeta.getProcess(procKey) +} + +// defaults +meta["defaults"] = [ + // key to be used to trace the process and determine output names + key: null, + + // fixed arguments to be passed to script + args: [:], + + // default directives + directives: readJsonBlob('''{ + "container" : { + "registry" : "images.viash-hub.com", + "image" : "vsh/biobox/agat/agat_convert_sp_gff2tsv", + "tag" : "main" + }, + "tag" : "$id" +}'''), + + // auto settings + auto: readJsonBlob('''{ + "simplifyInput" : true, + "simplifyOutput" : false, + "transcript" : false, + "publish" : false +}'''), + + // Apply a map over the incoming tuple + // Example: `{ tup -> [ tup[0], [input: tup[1].output] ] + tup.drop(2) }` + map: null, + + // Apply a map over the ID element of a tuple (i.e. the first element) + // Example: `{ id -> id + "_foo" }` + mapId: null, + + // Apply a map over the data element of a tuple (i.e. the second element) + // Example: `{ data -> [ input: data.output ] }` + mapData: null, + + // Apply a map over the passthrough elements of a tuple (i.e. the tuple excl. the first two elements) + // Example: `{ pt -> pt.drop(1) }` + mapPassthrough: null, + + // Filter the channel + // Example: `{ tup -> tup[0] == "foo" }` + filter: null, + + // Choose whether or not to run the component on the tuple if the condition is true. + // Otherwise, the tuple will be passed through. + // Example: `{ tup -> tup[0] != "skip_this" }` + runIf: null, + + // Rename keys in the data field of the tuple (i.e. the second element) + // Will likely be deprecated in favour of `fromState`. + // Example: `[ "new_key": "old_key" ]` + renameKeys: null, + + // Fetch data from the state and pass it to the module without altering the current state. + // + // `fromState` should be `null`, `List[String]`, `Map[String, String]` or a function. + // + // - If it is `null`, the state will be passed to the module as is. + // - If it is a `List[String]`, the data will be the values of the state at the given keys. + // - If it is a `Map[String, String]`, the data will be the values of the state at the given keys, with the keys renamed according to the map. + // - If it is a function, the tuple (`[id, state]`) in the channel will be passed to the function, and the result will be used as the data. + // + // Example: `{ id, state -> [input: state.fastq_file] }` + // Default: `null` + fromState: null, + + // Determine how the state should be updated after the module has been run. + // + // `toState` should be `null`, `List[String]`, `Map[String, String]` or a function. + // + // - If it is `null`, the state will be replaced with the output of the module. + // - If it is a `List[String]`, the state will be updated with the values of the data at the given keys. + // - If it is a `Map[String, String]`, the state will be updated with the values of the data at the given keys, with the keys renamed according to the map. + // - If it is a function, a tuple (`[id, output, state]`) will be passed to the function, and the result will be used as the new state. + // + // Example: `{ id, output, state -> state + [counts: state.output] }` + // Default: `{ id, output, state -> output }` + toState: null, + + // Whether or not to print debug messages + // Default: `false` + debug: false +] + +// initialise default workflow +meta["workflow"] = workflowFactory([key: meta.config.name], meta.defaults, meta) + +// add workflow to environment +nextflow.script.ScriptMeta.current().addDefinition(meta.workflow) + +// anonymous workflow for running this module as a standalone +workflow { + // add id argument if it's not already in the config + // TODO: deep copy + def newConfig = deepClone(meta.config) + def newParams = deepClone(params) + + def argsContainsId = newConfig.allArguments.any{it.plainName == "id"} + if (!argsContainsId) { + def idArg = [ + 'name': '--id', + 'required': false, + 'type': 'string', + 'description': 'A unique id for every entry.', + 'multiple': false + ] + newConfig.arguments.add(0, idArg) + newConfig = processConfig(newConfig) + } + if (!newParams.containsKey("id")) { + newParams.id = "run" + } + + helpMessage(newConfig) + + channelFromParams(newParams, newConfig) + // make sure id is not in the state if id is not in the args + | map {id, state -> + if (!argsContainsId) { + [id, state.findAll{k, v -> k != "id"}] + } else { + [id, state] + } + } + | meta.workflow.run( + auto: [ publish: "state" ] + ) +} + +// END COMPONENT-SPECIFIC CODE diff --git a/target/nextflow/agat/agat_convert_sp_gff2tsv/nextflow.config b/target/nextflow/agat/agat_convert_sp_gff2tsv/nextflow.config new file mode 100644 index 00000000..7a7f2aba --- /dev/null +++ b/target/nextflow/agat/agat_convert_sp_gff2tsv/nextflow.config @@ -0,0 +1,126 @@ +manifest { + name = 'agat/agat_convert_sp_gff2tsv' + mainScript = 'main.nf' + nextflowVersion = '!>=20.12.1-edge' + version = 'main' + description = 'The script aims to convert gtf/gff file into tabulated file. Attribute\'s\ntags from the 9th column become column titles.\n' + author = 'Leïla Paquay' +} + +process.container = 'nextflow/bash:latest' + +// detect tempdir +tempDir = java.nio.file.Paths.get( + System.getenv('NXF_TEMP') ?: + System.getenv('VIASH_TEMP') ?: + System.getenv('TEMPDIR') ?: + System.getenv('TMPDIR') ?: + '/tmp' +).toAbsolutePath() + +profiles { + no_publish { + process { + withName: '.*' { + publishDir = [ + enabled: false + ] + } + } + } + mount_temp { + docker.temp = tempDir + podman.temp = tempDir + charliecloud.temp = tempDir + } + docker { + docker.enabled = true + // docker.userEmulation = true + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false + } + singularity { + singularity.enabled = true + singularity.autoMounts = true + docker.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false + } + podman { + podman.enabled = true + docker.enabled = false + singularity.enabled = false + shifter.enabled = false + charliecloud.enabled = false + } + shifter { + shifter.enabled = true + docker.enabled = false + singularity.enabled = false + podman.enabled = false + charliecloud.enabled = false + } + charliecloud { + charliecloud.enabled = true + docker.enabled = false + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + } +} + +process{ + withLabel: mem1gb { memory = 1000000000.B } + withLabel: mem2gb { memory = 2000000000.B } + withLabel: mem5gb { memory = 5000000000.B } + withLabel: mem10gb { memory = 10000000000.B } + withLabel: mem20gb { memory = 20000000000.B } + withLabel: mem50gb { memory = 50000000000.B } + withLabel: mem100gb { memory = 100000000000.B } + withLabel: mem200gb { memory = 200000000000.B } + withLabel: mem500gb { memory = 500000000000.B } + withLabel: mem1tb { memory = 1000000000000.B } + withLabel: mem2tb { memory = 2000000000000.B } + withLabel: mem5tb { memory = 5000000000000.B } + withLabel: mem10tb { memory = 10000000000000.B } + withLabel: mem20tb { memory = 20000000000000.B } + withLabel: mem50tb { memory = 50000000000000.B } + withLabel: mem100tb { memory = 100000000000000.B } + withLabel: mem200tb { memory = 200000000000000.B } + withLabel: mem500tb { memory = 500000000000000.B } + withLabel: mem1gib { memory = 1073741824.B } + withLabel: mem2gib { memory = 2147483648.B } + withLabel: mem4gib { memory = 4294967296.B } + withLabel: mem8gib { memory = 8589934592.B } + withLabel: mem16gib { memory = 17179869184.B } + withLabel: mem32gib { memory = 34359738368.B } + withLabel: mem64gib { memory = 68719476736.B } + withLabel: mem128gib { memory = 137438953472.B } + withLabel: mem256gib { memory = 274877906944.B } + withLabel: mem512gib { memory = 549755813888.B } + withLabel: mem1tib { memory = 1099511627776.B } + withLabel: mem2tib { memory = 2199023255552.B } + withLabel: mem4tib { memory = 4398046511104.B } + withLabel: mem8tib { memory = 8796093022208.B } + withLabel: mem16tib { memory = 17592186044416.B } + withLabel: mem32tib { memory = 35184372088832.B } + withLabel: mem64tib { memory = 70368744177664.B } + withLabel: mem128tib { memory = 140737488355328.B } + withLabel: mem256tib { memory = 281474976710656.B } + withLabel: mem512tib { memory = 562949953421312.B } + withLabel: cpu1 { cpus = 1 } + withLabel: cpu2 { cpus = 2 } + withLabel: cpu5 { cpus = 5 } + withLabel: cpu10 { cpus = 10 } + withLabel: cpu20 { cpus = 20 } + withLabel: cpu50 { cpus = 50 } + withLabel: cpu100 { cpus = 100 } + withLabel: cpu200 { cpus = 200 } + withLabel: cpu500 { cpus = 500 } + withLabel: cpu1000 { cpus = 1000 } +} + + diff --git a/target/nextflow/agat/agat_convert_sp_gff2tsv/nextflow_schema.json b/target/nextflow/agat/agat_convert_sp_gff2tsv/nextflow_schema.json new file mode 100644 index 00000000..b432323e --- /dev/null +++ b/target/nextflow/agat/agat_convert_sp_gff2tsv/nextflow_schema.json @@ -0,0 +1,119 @@ +{ +"$schema": "http://json-schema.org/draft-07/schema", +"title": "agat_convert_sp_gff2tsv", +"description": "The script aims to convert gtf/gff file into tabulated file. Attribute\u0027s\ntags from the 9th column become column titles.\n", +"type": "object", +"definitions": { + + + + "inputs" : { + "title": "Inputs", + "type": "object", + "description": "No description", + "properties": { + + + "gff": { + "type": + "string", + "description": "Type: `file`, required, example: `input.gff`. Input GTF/GFF file", + "help_text": "Type: `file`, required, example: `input.gff`. Input GTF/GFF file." + + } + + +} +}, + + + "outputs" : { + "title": "Outputs", + "type": "object", + "description": "No description", + "properties": { + + + "output": { + "type": + "string", + "description": "Type: `file`, required, default: `$id.$key.output.gff`, example: `output.gff`. Output GFF file", + "help_text": "Type: `file`, required, default: `$id.$key.output.gff`, example: `output.gff`. Output GFF file. If no output file is specified, the output will be written to STDOUT." + , + "default": "$id.$key.output.gff" + } + + +} +}, + + + "arguments" : { + "title": "Arguments", + "type": "object", + "description": "No description", + "properties": { + + + "config": { + "type": + "string", + "description": "Type: `file`, example: `custom_agat_config.yaml`. String - Input agat config file", + "help_text": "Type: `file`, example: `custom_agat_config.yaml`. String - Input agat config file. By default AGAT takes as input\nagat_config.yaml file from the working directory if any,\notherwise it takes the orignal agat_config.yaml shipped with\nAGAT. To get the agat_config.yaml locally type: \"agat config\n--expose\". The --config option gives you the possibility to use\nyour own AGAT config file (located elsewhere or named\ndifferently). \n" + + } + + +} +}, + + + "nextflow input-output arguments" : { + "title": "Nextflow input-output arguments", + "type": "object", + "description": "Input/output parameters for Nextflow itself. Please note that both publishDir and publish_dir are supported but at least one has to be configured.", + "properties": { + + + "publish_dir": { + "type": + "string", + "description": "Type: `string`, required, example: `output/`. Path to an output directory", + "help_text": "Type: `string`, required, example: `output/`. Path to an output directory." + + } + + + , + "param_list": { + "type": + "string", + "description": "Type: `string`, example: `my_params.yaml`. Allows inputting multiple parameter sets to initialise a Nextflow channel", + "help_text": "Type: `string`, example: `my_params.yaml`. Allows inputting multiple parameter sets to initialise a Nextflow channel. A `param_list` can either be a list of maps, a csv file, a json file, a yaml file, or simply a yaml blob.\n\n* A list of maps (as-is) where the keys of each map corresponds to the arguments of the pipeline. Example: in a `nextflow.config` file: `param_list: [ [\u0027id\u0027: \u0027foo\u0027, \u0027input\u0027: \u0027foo.txt\u0027], [\u0027id\u0027: \u0027bar\u0027, \u0027input\u0027: \u0027bar.txt\u0027] ]`.\n* A csv file should have column names which correspond to the different arguments of this pipeline. Example: `--param_list data.csv` with columns `id,input`.\n* A json or a yaml file should be a list of maps, each of which has keys corresponding to the arguments of the pipeline. Example: `--param_list data.json` with contents `[ {\u0027id\u0027: \u0027foo\u0027, \u0027input\u0027: \u0027foo.txt\u0027}, {\u0027id\u0027: \u0027bar\u0027, \u0027input\u0027: \u0027bar.txt\u0027} ]`.\n* A yaml blob can also be passed directly as a string. Example: `--param_list \"[ {\u0027id\u0027: \u0027foo\u0027, \u0027input\u0027: \u0027foo.txt\u0027}, {\u0027id\u0027: \u0027bar\u0027, \u0027input\u0027: \u0027bar.txt\u0027} ]\"`.\n\nWhen passing a csv, json or yaml file, relative path names are relativized to the location of the parameter file. No relativation is performed when `param_list` is a list of maps (as-is) or a yaml blob.", + "hidden": true + + } + + +} +} +}, +"allOf": [ + + { + "$ref": "#/definitions/inputs" + }, + + { + "$ref": "#/definitions/outputs" + }, + + { + "$ref": "#/definitions/arguments" + }, + + { + "$ref": "#/definitions/nextflow input-output arguments" + } +] +} diff --git a/target/nextflow/agat/agat_convert_sp_gxf2gxf/.config.vsh.yaml b/target/nextflow/agat/agat_convert_sp_gxf2gxf/.config.vsh.yaml new file mode 100644 index 00000000..cb844e3c --- /dev/null +++ b/target/nextflow/agat/agat_convert_sp_gxf2gxf/.config.vsh.yaml @@ -0,0 +1,221 @@ +name: "agat_convert_sp_gxf2gxf" +namespace: "agat" +version: "main" +authors: +- name: "Leïla Paquay" + roles: + - "author" + - "maintainer" + info: + links: + email: "leila@data-intuitive.com" + github: "Leila011" + linkedin: "leilapaquay" + organizations: + - name: "Data Intuitive" + href: "https://www.data-intuitive.com" + role: "Software Developer" +argument_groups: +- name: "Inputs" + arguments: + - type: "file" + name: "--gxf" + alternatives: + - "-g" + - "--gtf" + - "--gff" + description: "String - Input GTF/GFF file. Compressed file with .gz extension\ + \ is accepted.\n" + info: null + example: + - "input.gff" + must_exist: true + create_parent: true + required: true + direction: "input" + multiple: false + multiple_sep: ";" +- name: "Outputs" + arguments: + - type: "file" + name: "--output" + alternatives: + - "-o" + description: "String - Output GFF file. If no output file is specified, the output\ + \ will be written to STDOUT.\n" + info: null + example: + - "output.gff" + must_exist: true + create_parent: true + required: true + direction: "output" + multiple: false + multiple_sep: ";" +- name: "Arguments" + arguments: + - type: "file" + name: "--config" + alternatives: + - "-c" + description: "String - Input agat config file. By default AGAT takes as input\ + \ agat_config.yaml file from the working directory if any, otherwise it takes\ + \ the original agat_config.yaml shipped with AGAT. To get the agat_config.yaml\ + \ locally type: \"agat config --expose\". The --config option gives you the\ + \ possibility to use your own AGAT config file (located elsewhere or named differently).\n" + info: null + example: + - "custom_agat_config.yaml" + must_exist: true + create_parent: true + required: false + direction: "input" + multiple: false + multiple_sep: ";" +resources: +- type: "bash_script" + path: "script.sh" + is_executable: true +description: "This script fixes and/or standardizes any GTF/GFF file into full sorted\n\ + GTF/GFF file. It AGAT parser removes duplicate features, fixes\nduplicated IDs,\ + \ adds missing ID and/or Parent attributes, deflates\nfactorized attributes (attributes\ + \ with several parents are duplicated\nwith uniq ID), add missing features when\ + \ possible (e.g. add exon if only\nCDS described, add UTR if CDS and exon described),\ + \ fix feature locations\n(e.g. check exon is embedded in the parent features mRNA,\ + \ gene), etc...\n\nAll AGAT's scripts with the _sp_ prefix use the AGAT parser,\ + \ before to\nperform any supplementary task. So, it is not necessary to run this\n\ + script prior the use of any other _sp_ script.\n" +test_resources: +- type: "bash_script" + path: "test.sh" + is_executable: true +- type: "file" + path: "test_data" +info: null +status: "enabled" +requirements: + commands: + - "ps" +keywords: +- "gene annotations" +- "GFF conversion" +license: "GPL-3.0" +references: + doi: + - "10.5281/zenodo.3552717" +links: + repository: "https://github.com/NBISweden/AGAT" + homepage: "https://github.com/NBISweden/AGAT" + documentation: "https://agat.readthedocs.io/en/latest/tools/agat_convert_sp_gxf2gxf.html" + issue_tracker: "https://github.com/NBISweden/AGAT/issues" +runners: +- type: "executable" + id: "executable" + docker_setup_strategy: "ifneedbepullelsecachedbuild" +- type: "nextflow" + id: "nextflow" + directives: + tag: "$id" + auto: + simplifyInput: true + simplifyOutput: false + transcript: false + publish: false + config: + labels: + mem1gb: "memory = 1000000000.B" + mem2gb: "memory = 2000000000.B" + mem5gb: "memory = 5000000000.B" + mem10gb: "memory = 10000000000.B" + mem20gb: "memory = 20000000000.B" + mem50gb: "memory = 50000000000.B" + mem100gb: "memory = 100000000000.B" + mem200gb: "memory = 200000000000.B" + mem500gb: "memory = 500000000000.B" + mem1tb: "memory = 1000000000000.B" + mem2tb: "memory = 2000000000000.B" + mem5tb: "memory = 5000000000000.B" + mem10tb: "memory = 10000000000000.B" + mem20tb: "memory = 20000000000000.B" + mem50tb: "memory = 50000000000000.B" + mem100tb: "memory = 100000000000000.B" + mem200tb: "memory = 200000000000000.B" + mem500tb: "memory = 500000000000000.B" + mem1gib: "memory = 1073741824.B" + mem2gib: "memory = 2147483648.B" + mem4gib: "memory = 4294967296.B" + mem8gib: "memory = 8589934592.B" + mem16gib: "memory = 17179869184.B" + mem32gib: "memory = 34359738368.B" + mem64gib: "memory = 68719476736.B" + mem128gib: "memory = 137438953472.B" + mem256gib: "memory = 274877906944.B" + mem512gib: "memory = 549755813888.B" + mem1tib: "memory = 1099511627776.B" + mem2tib: "memory = 2199023255552.B" + mem4tib: "memory = 4398046511104.B" + mem8tib: "memory = 8796093022208.B" + mem16tib: "memory = 17592186044416.B" + mem32tib: "memory = 35184372088832.B" + mem64tib: "memory = 70368744177664.B" + mem128tib: "memory = 140737488355328.B" + mem256tib: "memory = 281474976710656.B" + mem512tib: "memory = 562949953421312.B" + cpu1: "cpus = 1" + cpu2: "cpus = 2" + cpu5: "cpus = 5" + cpu10: "cpus = 10" + cpu20: "cpus = 20" + cpu50: "cpus = 50" + cpu100: "cpus = 100" + cpu200: "cpus = 200" + cpu500: "cpus = 500" + cpu1000: "cpus = 1000" + debug: false + container: "docker" +engines: +- type: "docker" + id: "docker" + image: "quay.io/biocontainers/agat:1.4.0--pl5321hdfd78af_0" + target_registry: "images.viash-hub.com" + target_tag: "main" + namespace_separator: "/" + setup: + - type: "docker" + run: + - "agat --version | sed 's/AGAT\\s\\(.*\\)/agat: \"\\1\"/' > /var/software_versions.txt\n" + entrypoint: [] + cmd: null +- type: "native" + id: "native" +build_info: + config: "src/agat/agat_convert_sp_gxf2gxf/config.vsh.yaml" + runner: "nextflow" + engine: "docker|native" + output: "target/nextflow/agat/agat_convert_sp_gxf2gxf" + executable: "target/nextflow/agat/agat_convert_sp_gxf2gxf/main.nf" + viash_version: "0.9.0-RC6" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" + git_remote: "https://github.com/viash-hub/biobox" +package_config: + name: "biobox" + version: "main" + description: "A collection of bioinformatics tools for working with sequence data.\n" + info: null + viash_version: "0.9.0-RC6" + source: "src" + target: "target" + config_mods: + - ".requirements.commands := ['ps']\n" + - ".engines += { type: \"native\" }" + - ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'" + - ".engines[.type == 'docker'].target_tag := 'main'" + keywords: + - "bioinformatics" + - "modules" + - "sequencing" + license: "MIT" + organization: "vsh" + links: + repository: "https://github.com/viash-hub/biobox" + issue_tracker: "https://github.com/viash-hub/biobox/issues" diff --git a/target/nextflow/agat/agat_convert_sp_gxf2gxf/main.nf b/target/nextflow/agat/agat_convert_sp_gxf2gxf/main.nf new file mode 100644 index 00000000..1f5e6dd6 --- /dev/null +++ b/target/nextflow/agat/agat_convert_sp_gxf2gxf/main.nf @@ -0,0 +1,3570 @@ +// agat_convert_sp_gxf2gxf main +// +// This wrapper script is auto-generated by viash 0.9.0-RC6 and is thus a +// derivative work thereof. This software comes with ABSOLUTELY NO WARRANTY from +// Data Intuitive. +// +// The component may contain files which fall under a different license. The +// authors of this component should specify the license in the header of such +// files, or include a separate license file detailing the licenses of all included +// files. +// +// Component authors: +// * Leïla Paquay (author, maintainer) + +//////////////////////////// +// VDSL3 helper functions // +//////////////////////////// + +// helper file: 'src/main/resources/io/viash/runners/nextflow/arguments/_checkArgumentType.nf' +class UnexpectedArgumentTypeException extends Exception { + String errorIdentifier + String stage + String plainName + String expectedClass + String foundClass + + // ${key ? " in module '$key'" : ""}${id ? " id '$id'" : ""} + UnexpectedArgumentTypeException(String errorIdentifier, String stage, String plainName, String expectedClass, String foundClass) { + super("Error${errorIdentifier ? " $errorIdentifier" : ""}:${stage ? " $stage" : "" } argument '${plainName}' has the wrong type. " + + "Expected type: ${expectedClass}. Found type: ${foundClass}") + this.errorIdentifier = errorIdentifier + this.stage = stage + this.plainName = plainName + this.expectedClass = expectedClass + this.foundClass = foundClass + } +} + +/** + * Checks if the given value is of the expected type. If not, an exception is thrown. + * + * @param stage The stage of the argument (input or output) + * @param par The parameter definition + * @param value The value to check + * @param errorIdentifier The identifier to use in the error message + * @return The value, if it is of the expected type + * @throws UnexpectedArgumentTypeException If the value is not of the expected type +*/ +def _checkArgumentType(String stage, Map par, Object value, String errorIdentifier) { + // expectedClass will only be != null if value is not of the expected type + def expectedClass = null + def foundClass = null + + // todo: split if need be + + if (!par.required && value == null) { + expectedClass = null + } else if (par.multiple) { + if (value !instanceof Collection) { + value = [value] + } + + // split strings + value = value.collectMany{ val -> + if (val instanceof String) { + // collect() to ensure that the result is a List and not simply an array + val.split(par.multiple_sep).collect() + } else { + [val] + } + } + + // process globs + if (par.type == "file" && par.direction == "input") { + value = value.collect{ it instanceof String ? file(it, hidden: true) : it }.flatten() + } + + // check types of elements in list + try { + value = value.collect { listVal -> + _checkArgumentType(stage, par + [multiple: false], listVal, errorIdentifier) + } + } catch (UnexpectedArgumentTypeException e) { + expectedClass = "List[${e.expectedClass}]" + foundClass = "List[${e.foundClass}]" + } + } else if (par.type == "string") { + // cast to string if need be + if (value instanceof GString) { + value = value.toString() + } + expectedClass = value instanceof String ? null : "String" + } else if (par.type == "integer") { + // cast to integer if need be + if (value instanceof String) { + try { + value = value.toInteger() + } catch (NumberFormatException e) { + // do nothing + } + } + if (value instanceof java.math.BigInteger) { + value = value.intValue() + } + expectedClass = value instanceof Integer ? null : "Integer" + } else if (par.type == "long") { + // cast to long if need be + if (value instanceof String) { + try { + value = value.toLong() + } catch (NumberFormatException e) { + // do nothing + } + } + if (value instanceof Integer) { + value = value.toLong() + } + expectedClass = value instanceof Long ? null : "Long" + } else if (par.type == "double") { + // cast to double if need be + if (value instanceof String) { + try { + value = value.toDouble() + } catch (NumberFormatException e) { + // do nothing + } + } + if (value instanceof java.math.BigDecimal) { + value = value.doubleValue() + } + if (value instanceof Float) { + value = value.toDouble() + } + expectedClass = value instanceof Double ? null : "Double" + } else if (par.type == "boolean" | par.type == "boolean_true" | par.type == "boolean_false") { + // cast to boolean if need be + if (value instanceof String) { + def valueLower = value.toLowerCase() + if (valueLower == "true") { + value = true + } else if (valueLower == "false") { + value = false + } + } + expectedClass = value instanceof Boolean ? null : "Boolean" + } else if (par.type == "file" && (par.direction == "input" || stage == "output")) { + // cast to path if need be + if (value instanceof String) { + value = file(value, hidden: true) + } + if (value instanceof File) { + value = value.toPath() + } + expectedClass = value instanceof Path ? null : "Path" + } else if (par.type == "file" && stage == "input" && par.direction == "output") { + // cast to string if need be + if (value instanceof GString) { + value = value.toString() + } + expectedClass = value instanceof String ? null : "String" + } else { + // didn't find a match for par.type + expectedClass = par.type + } + + if (expectedClass != null) { + if (foundClass == null) { + foundClass = value.getClass().getName() + } + throw new UnexpectedArgumentTypeException(errorIdentifier, stage, par.plainName, expectedClass, foundClass) + } + + return value +} +// helper file: 'src/main/resources/io/viash/runners/nextflow/arguments/_processInputValues.nf' +Map _processInputValues(Map inputs, Map config, String id, String key) { + if (!workflow.stubRun) { + config.allArguments.each { arg -> + if (arg.required) { + assert inputs.containsKey(arg.plainName) && inputs.get(arg.plainName) != null : + "Error in module '${key}' id '${id}': required input argument '${arg.plainName}' is missing" + } + } + + inputs = inputs.collectEntries { name, value -> + def par = config.allArguments.find { it.plainName == name && (it.direction == "input" || it.type == "file") } + assert par != null : "Error in module '${key}' id '${id}': '${name}' is not a valid input argument" + + value = _checkArgumentType("input", par, value, "in module '$key' id '$id'") + + [ name, value ] + } + } + return inputs +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/arguments/_processOutputValues.nf' +Map _processOutputValues(Map outputs, Map config, String id, String key) { + if (!workflow.stubRun) { + config.allArguments.each { arg -> + if (arg.direction == "output" && arg.required) { + assert outputs.containsKey(arg.plainName) && outputs.get(arg.plainName) != null : + "Error in module '${key}' id '${id}': required output argument '${arg.plainName}' is missing" + } + } + + outputs = outputs.collectEntries { name, value -> + def par = config.allArguments.find { it.plainName == name && it.direction == "output" } + assert par != null : "Error in module '${key}' id '${id}': '${name}' is not a valid output argument" + + value = _checkArgumentType("output", par, value, "in module '$key' id '$id'") + + [ name, value ] + } + } + return outputs +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/IDChecker.nf' +class IDChecker { + final def items = [] as Set + + @groovy.transform.WithWriteLock + boolean observe(String item) { + if (items.contains(item)) { + return false + } else { + items << item + return true + } + } + + @groovy.transform.WithReadLock + boolean contains(String item) { + return items.contains(item) + } + + @groovy.transform.WithReadLock + Set getItems() { + return items.clone() + } +} +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/_checkUniqueIds.nf' + +/** + * Check if the ids are unique across parameter sets + * + * @param parameterSets a list of parameter sets. + */ +private void _checkUniqueIds(List>> parameterSets) { + def ppIds = parameterSets.collect{it[0]} + assert ppIds.size() == ppIds.unique().size() : "All argument sets should have unique ids. Detected ids: $ppIds" +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/_getChild.nf' + +// helper functions for reading params from file // +def _getChild(parent, child) { + if (child.contains("://") || java.nio.file.Paths.get(child).isAbsolute()) { + child + } else { + def parentAbsolute = java.nio.file.Paths.get(parent).toAbsolutePath().toString() + parentAbsolute.replaceAll('/[^/]*$', "/") + child + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/_parseParamList.nf' +/** + * Figure out the param list format based on the file extension + * + * @param param_list A String containing the path to the parameter list file. + * + * @return A String containing the format of the parameter list file. + */ +def _paramListGuessFormat(param_list) { + if (param_list !instanceof String) { + "asis" + } else if (param_list.endsWith(".csv")) { + "csv" + } else if (param_list.endsWith(".json") || param_list.endsWith(".jsn")) { + "json" + } else if (param_list.endsWith(".yaml") || param_list.endsWith(".yml")) { + "yaml" + } else { + "yaml_blob" + } +} + + +/** + * Read the param list + * + * @param param_list One of the following: + * - A String containing the path to the parameter list file (csv, json or yaml), + * - A yaml blob of a list of maps (yaml_blob), + * - Or a groovy list of maps (asis). + * @param config A Map of the Viash configuration. + * + * @return A List of Maps containing the parameters. + */ +def _parseParamList(param_list, Map config) { + // first determine format by extension + def paramListFormat = _paramListGuessFormat(param_list) + + def paramListPath = (paramListFormat != "asis" && paramListFormat != "yaml_blob") ? + file(param_list, hidden: true) : + null + + // get the correct parser function for the detected params_list format + def paramSets = [] + if (paramListFormat == "asis") { + paramSets = param_list + } else if (paramListFormat == "yaml_blob") { + paramSets = readYamlBlob(param_list) + } else if (paramListFormat == "yaml") { + paramSets = readYaml(paramListPath) + } else if (paramListFormat == "json") { + paramSets = readJson(paramListPath) + } else if (paramListFormat == "csv") { + paramSets = readCsv(paramListPath) + } else { + error "Format of provided --param_list not recognised.\n" + + "Found: '$paramListFormat'.\n" + + "Expected: a csv file, a json file, a yaml file,\n" + + "a yaml blob or a groovy list of maps." + } + + // data checks + assert paramSets instanceof List: "--param_list should contain a list of maps" + for (value in paramSets) { + assert value instanceof Map: "--param_list should contain a list of maps" + } + + // id is argument + def idIsArgument = config.allArguments.any{it.plainName == "id"} + + // Reformat from List to List> by adding the ID as first element of a Tuple2 + paramSets = paramSets.collect({ data -> + def id = data.id + if (!idIsArgument) { + data = data.findAll{k, v -> k != "id"} + } + [id, data] + }) + + // Split parameters with 'multiple: true' + paramSets = paramSets.collect({ id, data -> + data = _splitParams(data, config) + [id, data] + }) + + // The paths of input files inside a param_list file may have been specified relatively to the + // location of the param_list file. These paths must be made absolute. + if (paramListPath) { + paramSets = paramSets.collect({ id, data -> + def new_data = data.collectEntries{ parName, parValue -> + def par = config.allArguments.find{it.plainName == parName} + if (par && par.type == "file" && par.direction == "input") { + if (parValue instanceof Collection) { + parValue = parValue.collectMany{path -> + def x = _resolveSiblingIfNotAbsolute(path, paramListPath) + x instanceof Collection ? x : [x] + } + } else { + parValue = _resolveSiblingIfNotAbsolute(parValue, paramListPath) + } + } + [parName, parValue] + } + [id, new_data] + }) + } + + return paramSets +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/_splitParams.nf' +/** + * Split parameters for arguments that accept multiple values using their separator + * + * @param paramList A Map containing parameters to split. + * @param config A Map of the Viash configuration. This Map can be generated from the config file + * using the readConfig() function. + * + * @return A Map of parameters where the parameter values have been split into a list using + * their seperator. + */ +Map _splitParams(Map parValues, Map config){ + def parsedParamValues = parValues.collectEntries { parName, parValue -> + def parameterSettings = config.allArguments.find({it.plainName == parName}) + + if (!parameterSettings) { + // if argument is not found, do not alter + return [parName, parValue] + } + if (parameterSettings.multiple) { // Check if parameter can accept multiple values + if (parValue instanceof Collection) { + parValue = parValue.collect{it instanceof String ? it.split(parameterSettings.multiple_sep) : it } + } else if (parValue instanceof String) { + parValue = parValue.split(parameterSettings.multiple_sep) + } else if (parValue == null) { + parValue = [] + } else { + parValue = [ parValue ] + } + parValue = parValue.flatten() + } + // For all parameters check if multiple values are only passed for + // arguments that allow it. Quietly simplify lists of length 1. + if (!parameterSettings.multiple && parValue instanceof Collection) { + assert parValue.size() == 1 : + "Error: argument ${parName} has too many values.\n" + + " Expected amount: 1. Found: ${parValue.size()}" + parValue = parValue[0] + } + [parName, parValue] + } + return parsedParamValues +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/channelFromParams.nf' +/** + * Parse nextflow parameters based on settings defined in a viash config. + * Return a list of parameter sets, each parameter set corresponding to + * an event in a nextflow channel. The output from this function can be used + * with Channel.fromList to create a nextflow channel with Vdsl3 formatted + * events. + * + * This function performs: + * - A filtering of the params which can be found in the config file. + * - Process the params_list argument which allows a user to to initialise + * a Vsdl3 channel with multiple parameter sets. Possible formats are + * csv, json, yaml, or simply a yaml_blob. A csv should have column names + * which correspond to the different arguments of this pipeline. A json or a yaml + * file should be a list of maps, each of which has keys corresponding to the + * arguments of the pipeline. A yaml blob can also be passed directly as a parameter. + * When passing a csv, json or yaml, relative path names are relativized to the + * location of the parameter file. + * - Combine the parameter sets into a vdsl3 Channel. + * + * @param params Input parameters. Can optionaly contain a 'param_list' key that + * provides a list of arguments that can be split up into multiple events + * in the output channel possible formats of param_lists are: a csv file, + * json file, a yaml file or a yaml blob. Each parameters set (event) must + * have a unique ID. + * @param config A Map of the Viash configuration. This Map can be generated from the config file + * using the readConfig() function. + * + * @return A list of parameters with the first element of the event being + * the event ID and the second element containing a map of the parsed parameters. + */ + +private List>> _paramsToParamSets(Map params, Map config){ + // todo: fetch key from run args + def key_ = config.name + + /* parse regular parameters (not in param_list) */ + /*************************************************/ + def globalParams = config.allArguments + .findAll { params.containsKey(it.plainName) } + .collectEntries { [ it.plainName, params[it.plainName] ] } + def globalID = params.get("id", null) + + /* process params_list arguments */ + /*********************************/ + def paramList = params.containsKey("param_list") && params.param_list != null ? + params.param_list : [] + // if (paramList instanceof String) { + // paramList = [paramList] + // } + // def paramSets = paramList.collectMany{ _parseParamList(it, config) } + // TODO: be able to process param_list when it is a list of strings + def paramSets = _parseParamList(paramList, config) + if (paramSets.isEmpty()) { + paramSets = [[null, [:]]] + } + + /* combine arguments into channel */ + /**********************************/ + def processedParams = paramSets.indexed().collect{ index, tup -> + // Process ID + def id = tup[0] ?: globalID + + if (workflow.stubRun && !id) { + // if stub run, explicitly add an id if missing + id = "stub${index}" + } + assert id != null: "Each parameter set should have at least an 'id'" + + // Process params + def parValues = globalParams + tup[1] + // // Remove parameters which are null, if the default is also null + // parValues = parValues.collectEntries{paramName, paramValue -> + // parameterSettings = config.functionality.allArguments.find({it.plainName == paramName}) + // if ( paramValue != null || parameterSettings.get("default", null) != null ) { + // [paramName, paramValue] + // } + // } + parValues = parValues.collectEntries { name, value -> + def par = config.allArguments.find { it.plainName == name && (it.direction == "input" || it.type == "file") } + assert par != null : "Error in module '${key_}' id '${id}': '${name}' is not a valid input argument" + + if (par == null) { + return [:] + } + value = _checkArgumentType("input", par, value, "in module '$key_' id '$id'") + + [ name, value ] + } + + [id, parValues] + } + + // Check if ids (first element of each list) is unique + _checkUniqueIds(processedParams) + return processedParams +} + +/** + * Parse nextflow parameters based on settings defined in a viash config + * and return a nextflow channel. + * + * @param params Input parameters. Can optionaly contain a 'param_list' key that + * provides a list of arguments that can be split up into multiple events + * in the output channel possible formats of param_lists are: a csv file, + * json file, a yaml file or a yaml blob. Each parameters set (event) must + * have a unique ID. + * @param config A Map of the Viash configuration. This Map can be generated from the config file + * using the readConfig() function. + * + * @return A nextflow Channel with events. Events are formatted as a tuple that contains + * first contains the ID of the event and as second element holds a parameter map. + * + * + */ +def channelFromParams(Map params, Map config) { + def processedParams = _paramsToParamSets(params, config) + return Channel.fromList(processedParams) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/checkUniqueIds.nf' +def checkUniqueIds(Map args) { + def stopOnError = args.stopOnError == null ? args.stopOnError : true + + def idChecker = new IDChecker() + + return filter { tup -> + if (!idChecker.observe(tup[0])) { + if (stopOnError) { + error "Duplicate id: ${tup[0]}" + } else { + log.warn "Duplicate id: ${tup[0]}, removing duplicate entry" + return false + } + } + return true + } +} +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/preprocessInputs.nf' +// This helper file will be deprecated soon +preprocessInputsDeprecationWarningPrinted = false + +def preprocessInputsDeprecationWarning() { + if (!preprocessInputsDeprecationWarningPrinted) { + preprocessInputsDeprecationWarningPrinted = true + System.err.println("Warning: preprocessInputs() is deprecated and will be removed in Viash 0.9.0.") + } +} + +/** + * Generate a nextflow Workflow that allows processing a channel of + * Vdsl3 formatted events and apply a Viash config to them: + * - Gather default parameters from the Viash config and make + * sure that they are correctly formatted (see applyConfig method). + * - Format the input parameters (also using the applyConfig method). + * - Apply the default parameter to the input parameters. + * - Do some assertions: + * ~ Check if the event IDs in the channel are unique. + * + * The events in the channel are formatted as tuples, with the + * first element of the tuples being a unique id of the parameter set, + * and the second element containg the the parameters themselves. + * Optional extra elements of the tuples will be passed to the output as is. + * + * @param args A map that must contain a 'config' key that points + * to a parsed config (see readConfig()). Optionally, a + * 'key' key can be provided which can be used to create a unique + * name for the workflow process. + * + * @return A workflow that allows processing a channel of Vdsl3 formatted events + * and apply a Viash config to them. + */ +def preprocessInputs(Map args) { + preprocessInputsDeprecationWarning() + + def config = args.config + assert config instanceof Map : + "Error in preprocessInputs: config must be a map. " + + "Expected class: Map. Found: config.getClass() is ${config.getClass()}" + def key_ = args.key ?: config.name + + // Get different parameter types (used throughout this function) + def defaultArgs = config.allArguments + .findAll { it.containsKey("default") } + .collectEntries { [ it.plainName, it.default ] } + + map { tup -> + def id = tup[0] + def data = tup[1] + def passthrough = tup.drop(2) + + def new_data = (defaultArgs + data).collectEntries { name, value -> + def par = config.allArguments.find { it.plainName == name && (it.direction == "input" || it.type == "file") } + + if (par != null) { + value = _checkArgumentType("input", par, value, "in module '$key_' id '$id'") + } + + [ name, value ] + } + + [ id, new_data ] + passthrough + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/runComponents.nf' +/** + * Run a list of components on a stream of data. + * + * @param components: list of Viash VDSL3 modules to run + * @param fromState: a closure, a map or a list of keys to extract from the input data. + * If a closure, it will be called with the id, the data and the component config. + * @param toState: a closure, a map or a list of keys to extract from the output data + * If a closure, it will be called with the id, the output data, the old state and the component config. + * @param filter: filter function to apply to the input. + * It will be called with the id, the data and the component config. + * @param id: id to use for the output data + * If a closure, it will be called with the id, the data and the component config. + * @param auto: auto options to pass to the components + * + * @return: a workflow that runs the components + **/ +def runComponents(Map args) { + log.warn("runComponents is deprecated, use runEach instead") + assert args.components: "runComponents should be passed a list of components to run" + + def components_ = args.components + if (components_ !instanceof List) { + components_ = [ components_ ] + } + assert components_.size() > 0: "pass at least one component to runComponents" + + def fromState_ = args.fromState + def toState_ = args.toState + def filter_ = args.filter + def id_ = args.id + + workflow runComponentsWf { + take: input_ch + main: + + // generate one channel per method + out_chs = components_.collect{ comp_ -> + def comp_config = comp_.config + + def filter_ch = filter_ + ? input_ch | filter{tup -> + filter_(tup[0], tup[1], comp_config) + } + : input_ch + def id_ch = id_ + ? filter_ch | map{tup -> + // def new_id = id_(tup[0], tup[1], comp_config) + def new_id = tup[0] + if (id_ instanceof String) { + new_id = id_ + } else if (id_ instanceof Closure) { + new_id = id_(new_id, tup[1], comp_config) + } + [new_id] + tup.drop(1) + } + : filter_ch + def data_ch = id_ch | map{tup -> + def new_data = tup[1] + if (fromState_ instanceof Map) { + new_data = fromState_.collectEntries{ key0, key1 -> + [key0, new_data[key1]] + } + } else if (fromState_ instanceof List) { + new_data = fromState_.collectEntries{ key -> + [key, new_data[key]] + } + } else if (fromState_ instanceof Closure) { + new_data = fromState_(tup[0], new_data, comp_config) + } + tup.take(1) + [new_data] + tup.drop(1) + } + def out_ch = data_ch + | comp_.run( + auto: (args.auto ?: [:]) + [simplifyInput: false, simplifyOutput: false] + ) + def post_ch = toState_ + ? out_ch | map{tup -> + def output = tup[1] + def old_state = tup[2] + def new_state = null + if (toState_ instanceof Map) { + new_state = old_state + toState_.collectEntries{ key0, key1 -> + [key0, output[key1]] + } + } else if (toState_ instanceof List) { + new_state = old_state + toState_.collectEntries{ key -> + [key, output[key]] + } + } else if (toState_ instanceof Closure) { + new_state = toState_(tup[0], output, old_state, comp_config) + } + [tup[0], new_state] + tup.drop(3) + } + : out_ch + + post_ch + } + + // mix all results + output_ch = + (out_chs.size == 1) + ? out_chs[0] + : out_chs[0].mix(*out_chs.drop(1)) + + emit: output_ch + } + + return runComponentsWf +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/runEach.nf' +/** + * Run a list of components on a stream of data. + * + * @param components: list of Viash VDSL3 modules to run + * @param fromState: a closure, a map or a list of keys to extract from the input data. + * If a closure, it will be called with the id, the data and the component itself. + * @param toState: a closure, a map or a list of keys to extract from the output data + * If a closure, it will be called with the id, the output data, the old state and the component itself. + * @param filter: filter function to apply to the input. + * It will be called with the id, the data and the component itself. + * @param id: id to use for the output data + * If a closure, it will be called with the id, the data and the component itself. + * @param auto: auto options to pass to the components + * + * @return: a workflow that runs the components + **/ +def runEach(Map args) { + assert args.components: "runEach should be passed a list of components to run" + + def components_ = args.components + if (components_ !instanceof List) { + components_ = [ components_ ] + } + assert components_.size() > 0: "pass at least one component to runEach" + + def fromState_ = args.fromState + def toState_ = args.toState + def filter_ = args.filter + def id_ = args.id + + workflow runEachWf { + take: input_ch + main: + + // generate one channel per method + out_chs = components_.collect{ comp_ -> + def filter_ch = filter_ + ? input_ch | filter{tup -> + filter_(tup[0], tup[1], comp_) + } + : input_ch + def id_ch = id_ + ? filter_ch | map{tup -> + def new_id = id_ + if (new_id instanceof Closure) { + new_id = new_id(tup[0], tup[1], comp_) + } + assert new_id instanceof String : "Error in runEach: id should be a String or a Closure that returns a String. Expected: id instanceof String. Found: ${new_id.getClass()}" + [new_id] + tup.drop(1) + } + : filter_ch + def data_ch = id_ch | map{tup -> + def new_data = tup[1] + if (fromState_ instanceof Map) { + new_data = fromState_.collectEntries{ key0, key1 -> + [key0, new_data[key1]] + } + } else if (fromState_ instanceof List) { + new_data = fromState_.collectEntries{ key -> + [key, new_data[key]] + } + } else if (fromState_ instanceof Closure) { + new_data = fromState_(tup[0], new_data, comp_) + } + tup.take(1) + [new_data] + tup.drop(1) + } + def out_ch = data_ch + | comp_.run( + auto: (args.auto ?: [:]) + [simplifyInput: false, simplifyOutput: false] + ) + def post_ch = toState_ + ? out_ch | map{tup -> + def output = tup[1] + def old_state = tup[2] + def new_state = null + if (toState_ instanceof Map) { + new_state = old_state + toState_.collectEntries{ key0, key1 -> + [key0, output[key1]] + } + } else if (toState_ instanceof List) { + new_state = old_state + toState_.collectEntries{ key -> + [key, output[key]] + } + } else if (toState_ instanceof Closure) { + new_state = toState_(tup[0], output, old_state, comp_) + } + [tup[0], new_state] + tup.drop(3) + } + : out_ch + + post_ch + } + + // mix all results + output_ch = + (out_chs.size == 1) + ? out_chs[0] + : out_chs[0].mix(*out_chs.drop(1)) + + emit: output_ch + } + + return runEachWf +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/safeJoin.nf' +/** + * Join sourceChannel to targetChannel + * + * This function joins the sourceChannel to the targetChannel. + * However, each id in the targetChannel must be present in the + * sourceChannel. If _meta.join_id exists in the targetChannel, that is + * used as an id instead. If the id doesn't match any id in the sourceChannel, + * an error is thrown. + */ + +def safeJoin(targetChannel, sourceChannel, key) { + def sourceIDs = new IDChecker() + + def sourceCheck = sourceChannel + | map { tup -> + sourceIDs.observe(tup[0]) + tup + } + def targetCheck = targetChannel + | map { tup -> + def id = tup[0] + + if (!sourceIDs.contains(id)) { + error ( + "Error in module '${key}' when merging output with original state.\n" + + " Reason: output with id '${id}' could not be joined with source channel.\n" + + " If the IDs in the output channel differ from the input channel,\n" + + " please set `tup[1]._meta.join_id to the original ID.\n" + + " Original IDs in input channel: ['${sourceIDs.getItems().join("', '")}'].\n" + + " Unexpected ID in the output channel: '${id}'.\n" + + " Example input event: [\"id\", [input: file(...)]],\n" + + " Example output event: [\"newid\", [output: file(...), _meta: [join_id: \"id\"]]]" + ) + } + // TODO: add link to our documentation on how to fix this + + tup + } + + sourceCheck.cross(targetChannel) + | map{ left, right -> + right + left.drop(1) + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/config/_processArgument.nf' +def _processArgument(arg) { + arg.multiple = arg.multiple != null ? arg.multiple : false + arg.required = arg.required != null ? arg.required : false + arg.direction = arg.direction != null ? arg.direction : "input" + arg.multiple_sep = arg.multiple_sep != null ? arg.multiple_sep : ";" + arg.plainName = arg.name.replaceAll("^-*", "") + + if (arg.type == "file") { + arg.must_exist = arg.must_exist != null ? arg.must_exist : true + arg.create_parent = arg.create_parent != null ? arg.create_parent : true + } + + // add default values to output files which haven't already got a default + if (arg.type == "file" && arg.direction == "output" && arg.default == null) { + def mult = arg.multiple ? "_*" : "" + def extSearch = "" + if (arg.default != null) { + extSearch = arg.default + } else if (arg.example != null) { + extSearch = arg.example + } + if (extSearch instanceof List) { + extSearch = extSearch[0] + } + def extSearchResult = extSearch.find("\\.[^\\.]+\$") + def ext = extSearchResult != null ? extSearchResult : "" + arg.default = "\$id.\$key.${arg.plainName}${mult}${ext}" + if (arg.multiple) { + arg.default = [arg.default] + } + } + + if (!arg.multiple) { + if (arg.default != null && arg.default instanceof List) { + arg.default = arg.default[0] + } + if (arg.example != null && arg.example instanceof List) { + arg.example = arg.example[0] + } + } + + if (arg.type == "boolean_true") { + arg.default = false + } + if (arg.type == "boolean_false") { + arg.default = true + } + + arg +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/config/addGlobalParams.nf' +def addGlobalArguments(config) { + def localConfig = [ + "argument_groups": [ + [ + "name": "Nextflow input-output arguments", + "description": "Input/output parameters for Nextflow itself. Please note that both publishDir and publish_dir are supported but at least one has to be configured.", + "arguments" : [ + [ + 'name': '--publish_dir', + 'required': true, + 'type': 'string', + 'description': 'Path to an output directory.', + 'example': 'output/', + 'multiple': false + ], + [ + 'name': '--param_list', + 'required': false, + 'type': 'string', + 'description': '''Allows inputting multiple parameter sets to initialise a Nextflow channel. A `param_list` can either be a list of maps, a csv file, a json file, a yaml file, or simply a yaml blob. + | + |* A list of maps (as-is) where the keys of each map corresponds to the arguments of the pipeline. Example: in a `nextflow.config` file: `param_list: [ ['id': 'foo', 'input': 'foo.txt'], ['id': 'bar', 'input': 'bar.txt'] ]`. + |* A csv file should have column names which correspond to the different arguments of this pipeline. Example: `--param_list data.csv` with columns `id,input`. + |* A json or a yaml file should be a list of maps, each of which has keys corresponding to the arguments of the pipeline. Example: `--param_list data.json` with contents `[ {'id': 'foo', 'input': 'foo.txt'}, {'id': 'bar', 'input': 'bar.txt'} ]`. + |* A yaml blob can also be passed directly as a string. Example: `--param_list "[ {'id': 'foo', 'input': 'foo.txt'}, {'id': 'bar', 'input': 'bar.txt'} ]"`. + | + |When passing a csv, json or yaml file, relative path names are relativized to the location of the parameter file. No relativation is performed when `param_list` is a list of maps (as-is) or a yaml blob.'''.stripMargin(), + 'example': 'my_params.yaml', + 'multiple': false, + 'hidden': true + ] + // TODO: allow multiple: true in param_list? + // TODO: allow to specify a --param_list_regex to filter the param_list? + // TODO: allow to specify a --param_list_from_state to remap entries in the param_list? + ] + ] + ] + ] + + return processConfig(_mergeMap(config, localConfig)) +} + +def _mergeMap(Map lhs, Map rhs) { + return rhs.inject(lhs.clone()) { map, entry -> + if (map[entry.key] instanceof Map && entry.value instanceof Map) { + map[entry.key] = _mergeMap(map[entry.key], entry.value) + } else if (map[entry.key] instanceof Collection && entry.value instanceof Collection) { + map[entry.key] += entry.value + } else { + map[entry.key] = entry.value + } + return map + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/config/generateHelp.nf' +def _generateArgumentHelp(param) { + // alternatives are not supported + // def names = param.alternatives ::: List(param.name) + + def unnamedProps = [ + ["required parameter", param.required], + ["multiple values allowed", param.multiple], + ["output", param.direction.toLowerCase() == "output"], + ["file must exist", param.type == "file" && param.must_exist] + ].findAll{it[1]}.collect{it[0]} + + def dflt = null + if (param.default != null) { + if (param.default instanceof List) { + dflt = param.default.join(param.multiple_sep != null ? param.multiple_sep : ", ") + } else { + dflt = param.default.toString() + } + } + def example = null + if (param.example != null) { + if (param.example instanceof List) { + example = param.example.join(param.multiple_sep != null ? param.multiple_sep : ", ") + } else { + example = param.example.toString() + } + } + def min = param.min?.toString() + def max = param.max?.toString() + + def escapeChoice = { choice -> + def s1 = choice.replaceAll("\\n", "\\\\n") + def s2 = s1.replaceAll("\"", """\\\"""") + s2.contains(",") || s2 != choice ? "\"" + s2 + "\"" : s2 + } + def choices = param.choices == null ? + null : + "[ " + param.choices.collect{escapeChoice(it.toString())}.join(", ") + " ]" + + def namedPropsStr = [ + ["type", ([param.type] + unnamedProps).join(", ")], + ["default", dflt], + ["example", example], + ["choices", choices], + ["min", min], + ["max", max] + ] + .findAll{it[1]} + .collect{"\n " + it[0] + ": " + it[1].replaceAll("\n", "\\n")} + .join("") + + def descStr = param.description == null ? + "" : + _paragraphWrap("\n" + param.description.trim(), 80 - 8).join("\n ") + + "\n --" + param.plainName + + namedPropsStr + + descStr +} + +// Based on Helper.generateHelp() in Helper.scala +def _generateHelp(config) { + def fun = config + + // PART 1: NAME AND VERSION + def nameStr = fun.name + + (fun.version == null ? "" : " " + fun.version) + + // PART 2: DESCRIPTION + def descrStr = fun.description == null ? + "" : + "\n\n" + _paragraphWrap(fun.description.trim(), 80).join("\n") + + // PART 3: Usage + def usageStr = fun.usage == null ? + "" : + "\n\nUsage:\n" + fun.usage.trim() + + // PART 4: Options + def argGroupStrs = fun.allArgumentGroups.collect{argGroup -> + def name = argGroup.name + def descriptionStr = argGroup.description == null ? + "" : + "\n " + _paragraphWrap(argGroup.description.trim(), 80-4).join("\n ") + "\n" + def arguments = argGroup.arguments.collect{arg -> + arg instanceof String ? fun.allArguments.find{it.plainName == arg} : arg + }.findAll{it != null} + def argumentStrs = arguments.collect{param -> _generateArgumentHelp(param)} + + "\n\n$name:" + + descriptionStr + + argumentStrs.join("\n") + } + + // FINAL: combine + def out = nameStr + + descrStr + + usageStr + + argGroupStrs.join("") + + return out +} + +// based on Format._paragraphWrap +def _paragraphWrap(str, maxLength) { + def outLines = [] + str.split("\n").each{par -> + def words = par.split("\\s").toList() + + def word = null + def line = words.pop() + while(!words.isEmpty()) { + word = words.pop() + if (line.length() + word.length() + 1 <= maxLength) { + line = line + " " + word + } else { + outLines.add(line) + line = word + } + } + if (words.isEmpty()) { + outLines.add(line) + } + } + return outLines +} + +def helpMessage(config) { + if (params.containsKey("help") && params.help) { + def mergedConfig = addGlobalArguments(config) + def helpStr = _generateHelp(mergedConfig) + println(helpStr) + exit 0 + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/config/processConfig.nf' +def processConfig(config) { + // set defaults for arguments + config.arguments = + (config.arguments ?: []).collect{_processArgument(it)} + + // set defaults for argument_group arguments + config.argument_groups = + (config.argument_groups ?: []).collect{grp -> + grp.arguments = (grp.arguments ?: []).collect{_processArgument(it)} + grp + } + + // create combined arguments list + config.allArguments = + config.arguments + + config.argument_groups.collectMany{it.arguments} + + // add missing argument groups (based on Functionality::allArgumentGroups()) + def argGroups = config.argument_groups + if (argGroups.any{it.name.toLowerCase() == "arguments"}) { + argGroups = argGroups.collect{ grp -> + if (grp.name.toLowerCase() == "arguments") { + grp = grp + [ + arguments: grp.arguments + config.arguments + ] + } + grp + } + } else { + argGroups = argGroups + [ + name: "Arguments", + arguments: config.arguments + ] + } + config.allArgumentGroups = argGroups + + config +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/config/readConfig.nf' + +def readConfig(file) { + def config = readYaml(file ?: moduleDir.resolve("config.vsh.yaml")) + processConfig(config) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/_resolveSiblingIfNotAbsolute.nf' +/** + * Resolve a path relative to the current file. + * + * @param str The path to resolve, as a String. + * @param parentPath The path to resolve relative to, as a Path. + * + * @return The path that may have been resovled, as a Path. + */ +def _resolveSiblingIfNotAbsolute(str, parentPath) { + if (str !instanceof String) { + return str + } + if (!_stringIsAbsolutePath(str)) { + return parentPath.resolveSibling(str) + } else { + return file(str, hidden: true) + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/_stringIsAbsolutePath.nf' +/** + * Check whether a path as a string is absolute. + * + * In the past, we tried using `file(., relative: true).isAbsolute()`, + * but the 'relative' option was added in 22.10.0. + * + * @param path The path to check, as a String. + * + * @return Whether the path is absolute, as a boolean. + */ +def _stringIsAbsolutePath(path) { + def _resolve_URL_PROTOCOL = ~/^([a-zA-Z][a-zA-Z0-9]*:)?\\/.+/ + + assert path instanceof String + return _resolve_URL_PROTOCOL.matcher(path).matches() +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/collectTraces.nf' +class CustomTraceObserver implements nextflow.trace.TraceObserver { + List traces + + CustomTraceObserver(List traces) { + this.traces = traces + } + + @Override + void onProcessComplete(nextflow.processor.TaskHandler handler, nextflow.trace.TraceRecord trace) { + def trace2 = trace.store.clone() + trace2.script = null + traces.add(trace2) + } + + @Override + void onProcessCached(nextflow.processor.TaskHandler handler, nextflow.trace.TraceRecord trace) { + def trace2 = trace.store.clone() + trace2.script = null + traces.add(trace2) + } +} + +def collectTraces() { + def traces = Collections.synchronizedList([]) + + // add custom trace observer which stores traces in the traces object + session.observers.add(new CustomTraceObserver(traces)) + + traces +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/deepClone.nf' +/** + * Performs a deep clone of the given object. + * @param x an object + */ +def deepClone(x) { + iterateMap(x, {it instanceof Cloneable ? it.clone() : it}) +} +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/getPublishDir.nf' +def getPublishDir() { + return params.containsKey("publish_dir") ? params.publish_dir : + params.containsKey("publishDir") ? params.publishDir : + null +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/getRootDir.nf' + +// Recurse upwards until we find a '.build.yaml' file +def _findBuildYamlFile(pathPossiblySymlink) { + def path = pathPossiblySymlink.toRealPath() + def child = path.resolve(".build.yaml") + if (java.nio.file.Files.isDirectory(path) && java.nio.file.Files.exists(child)) { + return child + } else { + def parent = path.getParent() + if (parent == null) { + return null + } else { + return _findBuildYamlFile(parent) + } + } +} + +// get the root of the target folder +def getRootDir() { + def dir = _findBuildYamlFile(meta.resources_dir) + assert dir != null: "Could not find .build.yaml in the folder structure" + dir.getParent() +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/iterateMap.nf' +/** + * Recursively apply a function over the leaves of an object. + * @param obj The object to iterate over. + * @param fun The function to apply to each value. + * @return The object with the function applied to each value. + */ +def iterateMap(obj, fun) { + if (obj instanceof List && obj !instanceof String) { + return obj.collect{item -> + iterateMap(item, fun) + } + } else if (obj instanceof Map) { + return obj.collectEntries{key, item -> + [key.toString(), iterateMap(item, fun)] + } + } else { + return fun(obj) + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/niceView.nf' +/** + * A view for printing the event of each channel as a YAML blob. + * This is useful for debugging. + */ +def niceView() { + workflow niceViewWf { + take: input + main: + output = input + | view{toYamlBlob(it)} + emit: output + } + return niceViewWf +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/readCsv.nf' + +def readCsv(file_path) { + def output = [] + def inputFile = file_path !instanceof Path ? file(file_path, hidden: true) : file_path + + // todo: allow escaped quotes in string + // todo: allow single quotes? + def splitRegex = java.util.regex.Pattern.compile(''',(?=(?:[^"]*"[^"]*")*[^"]*$)''') + def removeQuote = java.util.regex.Pattern.compile('''"(.*)"''') + + def br = java.nio.file.Files.newBufferedReader(inputFile) + + def row = -1 + def header = null + while (br.ready() && header == null) { + def line = br.readLine() + row++ + if (!line.startsWith("#")) { + header = splitRegex.split(line, -1).collect{field -> + m = removeQuote.matcher(field) + m.find() ? m.replaceFirst('$1') : field + } + } + } + assert header != null: "CSV file should contain a header" + + while (br.ready()) { + def line = br.readLine() + row++ + if (line == null) { + br.close() + break + } + + if (!line.startsWith("#")) { + def predata = splitRegex.split(line, -1) + def data = predata.collect{field -> + if (field == "") { + return null + } + def m = removeQuote.matcher(field) + if (m.find()) { + return m.replaceFirst('$1') + } else { + return field + } + } + assert header.size() == data.size(): "Row $row should contain the same number as fields as the header" + + def dataMap = [header, data].transpose().collectEntries().findAll{it.value != null} + output.add(dataMap) + } + } + + output +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/readJson.nf' +def readJson(file_path) { + def inputFile = file_path !instanceof Path ? file(file_path, hidden: true) : file_path + def jsonSlurper = new groovy.json.JsonSlurper() + jsonSlurper.parse(inputFile) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/readJsonBlob.nf' +def readJsonBlob(str) { + def jsonSlurper = new groovy.json.JsonSlurper() + jsonSlurper.parseText(str) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/readTaggedYaml.nf' +// Custom constructor to modify how certain objects are parsed from YAML +class CustomConstructor extends org.yaml.snakeyaml.constructor.Constructor { + Path root + + class ConstructPath extends org.yaml.snakeyaml.constructor.AbstractConstruct { + public Object construct(org.yaml.snakeyaml.nodes.Node node) { + String filename = (String) constructScalar(node); + if (root != null) { + return root.resolve(filename); + } + return java.nio.file.Paths.get(filename); + } + } + + CustomConstructor(org.yaml.snakeyaml.LoaderOptions options, Path root) { + super(options) + this.root = root + // Handling !file tag and parse it back to a File type + this.yamlConstructors.put(new org.yaml.snakeyaml.nodes.Tag("!file"), new ConstructPath()) + } +} + +def readTaggedYaml(Path path) { + def options = new org.yaml.snakeyaml.LoaderOptions() + def constructor = new CustomConstructor(options, path.getParent()) + def yaml = new org.yaml.snakeyaml.Yaml(constructor) + return yaml.load(path.text) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/readYaml.nf' +def readYaml(file_path) { + def inputFile = file_path !instanceof Path ? file(file_path, hidden: true) : file_path + def yamlSlurper = new org.yaml.snakeyaml.Yaml() + yamlSlurper.load(inputFile) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/readYamlBlob.nf' +def readYamlBlob(str) { + def yamlSlurper = new org.yaml.snakeyaml.Yaml() + yamlSlurper.load(str) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/toJsonBlob.nf' +String toJsonBlob(data) { + return groovy.json.JsonOutput.toJson(data) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/toTaggedYamlBlob.nf' +// Custom representer to modify how certain objects are represented in YAML +class CustomRepresenter extends org.yaml.snakeyaml.representer.Representer { + Path relativizer + + class RepresentPath implements org.yaml.snakeyaml.representer.Represent { + public String getFileName(Object obj) { + if (obj instanceof File) { + obj = ((File) obj).toPath(); + } + if (obj !instanceof Path) { + throw new IllegalArgumentException("Object: " + obj + " is not a Path or File"); + } + def path = (Path) obj; + + if (relativizer != null) { + return relativizer.relativize(path).toString() + } else { + return path.toString() + } + } + + public org.yaml.snakeyaml.nodes.Node representData(Object data) { + String filename = getFileName(data); + def tag = new org.yaml.snakeyaml.nodes.Tag("!file"); + return representScalar(tag, filename); + } + } + CustomRepresenter(org.yaml.snakeyaml.DumperOptions options, Path relativizer) { + super(options) + this.relativizer = relativizer + this.representers.put(sun.nio.fs.UnixPath, new RepresentPath()) + this.representers.put(Path, new RepresentPath()) + this.representers.put(File, new RepresentPath()) + } +} + +String toTaggedYamlBlob(data) { + return toRelativeTaggedYamlBlob(data, null) +} +String toRelativeTaggedYamlBlob(data, Path relativizer) { + def options = new org.yaml.snakeyaml.DumperOptions() + options.setDefaultFlowStyle(org.yaml.snakeyaml.DumperOptions.FlowStyle.BLOCK) + def representer = new CustomRepresenter(options, relativizer) + def yaml = new org.yaml.snakeyaml.Yaml(representer, options) + return yaml.dump(data) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/toYamlBlob.nf' +String toYamlBlob(data) { + def options = new org.yaml.snakeyaml.DumperOptions() + options.setDefaultFlowStyle(org.yaml.snakeyaml.DumperOptions.FlowStyle.BLOCK) + options.setPrettyFlow(true) + def yaml = new org.yaml.snakeyaml.Yaml(options) + def cleanData = iterateMap(data, { it instanceof Path ? it.toString() : it }) + return yaml.dump(cleanData) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/writeJson.nf' +void writeJson(data, file) { + assert data: "writeJson: data should not be null" + assert file: "writeJson: file should not be null" + file.write(toJsonBlob(data)) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/writeYaml.nf' +void writeYaml(data, file) { + assert data: "writeYaml: data should not be null" + assert file: "writeYaml: file should not be null" + file.write(toYamlBlob(data)) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/states/findStates.nf' +def findStates(Map params, Map config) { + def auto_config = deepClone(config) + def auto_params = deepClone(params) + + auto_config = auto_config.clone() + // override arguments + auto_config.argument_groups = [] + auto_config.arguments = [ + [ + type: "string", + name: "--id", + description: "A dummy identifier", + required: false + ], + [ + type: "file", + name: "--input_states", + example: "/path/to/input/directory/**/state.yaml", + description: "Path to input directory containing the datasets to be integrated.", + required: true, + multiple: true, + multiple_sep: ";" + ], + [ + type: "string", + name: "--filter", + example: "foo/.*/state.yaml", + description: "Regex to filter state files by path.", + required: false + ], + // to do: make this a yaml blob? + [ + type: "string", + name: "--rename_keys", + example: ["newKey1:oldKey1", "newKey2:oldKey2"], + description: "Rename keys in the detected input files. This is useful if the input files do not match the set of input arguments of the workflow.", + required: false, + multiple: true, + multiple_sep: ";" + ], + [ + type: "string", + name: "--settings", + example: '{"output_dataset": "dataset.h5ad", "k": 10}', + description: "Global arguments as a JSON glob to be passed to all components.", + required: false + ] + ] + if (!(auto_params.containsKey("id"))) { + auto_params["id"] = "auto" + } + + // run auto config through processConfig once more + auto_config = processConfig(auto_config) + + workflow findStatesWf { + helpMessage(auto_config) + + output_ch = + channelFromParams(auto_params, auto_config) + | flatMap { autoId, args -> + + def globalSettings = args.settings ? readYamlBlob(args.settings) : [:] + + // look for state files in input dir + def stateFiles = args.input_states + + // filter state files by regex + if (args.filter) { + stateFiles = stateFiles.findAll{ stateFile -> + def stateFileStr = stateFile.toString() + def matcher = stateFileStr =~ args.filter + matcher.matches()} + } + + // read in states + def states = stateFiles.collect { stateFile -> + def state_ = readTaggedYaml(stateFile) + [state_.id, state_] + } + + // construct renameMap + if (args.rename_keys) { + def renameMap = args.rename_keys.collectEntries{renameString -> + def split = renameString.split(";") + assert split.size() == 2: "Argument 'rename_keys' should be of the form 'newKey:oldKey,newKey:oldKey'" + split + } + + // rename keys in state, only let states through which have all keys + // also add global settings + states = states.collectMany{id, state -> + def newState = [:] + + for (key in renameMap.keySet()) { + def origKey = renameMap[key] + if (!(state.containsKey(origKey))) { + return [] + } + newState[key] = state[origKey] + } + + [[id, globalSettings + newState]] + } + } + + states + } + emit: + output_ch + } + + return findStatesWf +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/states/joinStates.nf' +def joinStates(Closure apply_) { + workflow joinStatesWf { + take: input_ch + main: + output_ch = input_ch + | toSortedList + | filter{ it.size() > 0 } + | map{ tups -> + def ids = tups.collect{it[0]} + def states = tups.collect{it[1]} + apply_(ids, states) + } + + emit: output_ch + } + return joinStatesWf +} +// helper file: 'src/main/resources/io/viash/runners/nextflow/states/publishStates.nf' +def collectFiles(obj) { + if (obj instanceof java.io.File || obj instanceof Path) { + return [obj] + } else if (obj instanceof List && obj !instanceof String) { + return obj.collectMany{item -> + collectFiles(item) + } + } else if (obj instanceof Map) { + return obj.collectMany{key, item -> + collectFiles(item) + } + } else { + return [] + } +} + +/** + * Recurse through a state and collect all input files and their target output filenames. + * @param obj The state to recurse through. + * @param prefix The prefix to prepend to the output filenames. + */ +def collectInputOutputPaths(obj, prefix) { + if (obj instanceof File || obj instanceof Path) { + def path = obj instanceof Path ? obj : obj.toPath() + def ext = path.getFileName().toString().find("\\.[^\\.]+\$") ?: "" + def newFilename = prefix + ext + return [[obj, newFilename]] + } else if (obj instanceof List && obj !instanceof String) { + return obj.withIndex().collectMany{item, ix -> + collectInputOutputPaths(item, prefix + "_" + ix) + } + } else if (obj instanceof Map) { + return obj.collectMany{key, item -> + collectInputOutputPaths(item, prefix + "." + key) + } + } else { + return [] + } +} + +def publishStates(Map args) { + def key_ = args.get("key") + def yamlTemplate_ = args.get("output_state", args.get("outputState", '$id.$key.state.yaml')) + + assert key_ != null : "publishStates: key must be specified" + + workflow publishStatesWf { + take: input_ch + main: + input_ch + | map { tup -> + def id_ = tup[0] + def state_ = tup[1] + + // the input files and the target output filenames + def inputoutputFilenames_ = collectInputOutputPaths(state_, id_ + "." + key_).transpose() + def inputFiles_ = inputoutputFilenames_[0] + def outputFilenames_ = inputoutputFilenames_[1] + + def yamlFilename = yamlTemplate_ + .replaceAll('\\$id', id_) + .replaceAll('\\$key', key_) + + // TODO: do the pathnames in state_ match up with the outputFilenames_? + + // convert state to yaml blob + def yamlBlob_ = toRelativeTaggedYamlBlob([id: id_] + state_, java.nio.file.Paths.get(yamlFilename)) + + [id_, yamlBlob_, yamlFilename, inputFiles_, outputFilenames_] + } + | publishStatesProc + emit: input_ch + } + return publishStatesWf +} +process publishStatesProc { + // todo: check publishpath? + publishDir path: "${getPublishDir()}/", mode: "copy" + tag "$id" + input: + tuple val(id), val(yamlBlob), val(yamlFile), path(inputFiles, stageAs: "_inputfile?/*"), val(outputFiles) + output: + tuple val(id), path{[yamlFile] + outputFiles} + script: + def copyCommands = [ + inputFiles instanceof List ? inputFiles : [inputFiles], + outputFiles instanceof List ? outputFiles : [outputFiles] + ] + .transpose() + .collectMany{infile, outfile -> + if (infile.toString() != outfile.toString()) { + [ + "[ -d \"\$(dirname '${outfile.toString()}')\" ] || mkdir -p \"\$(dirname '${outfile.toString()}')\"", + "cp -r '${infile.toString()}' '${outfile.toString()}'" + ] + } else { + // no need to copy if infile is the same as outfile + [] + } + } + """ +mkdir -p "\$(dirname '${yamlFile}')" +echo "Storing state as yaml" +echo '${yamlBlob}' > '${yamlFile}' +echo "Copying output files to destination folder" +${copyCommands.join("\n ")} +""" +} + + +// this assumes that the state contains no other values other than those specified in the config +def publishStatesByConfig(Map args) { + def config = args.get("config") + assert config != null : "publishStatesByConfig: config must be specified" + + def key_ = args.get("key", config.name) + assert key_ != null : "publishStatesByConfig: key must be specified" + + workflow publishStatesSimpleWf { + take: input_ch + main: + input_ch + | map { tup -> + def id_ = tup[0] + def state_ = tup[1] // e.g. [output: new File("myoutput.h5ad"), k: 10] + def origState_ = tup[2] // e.g. [output: '$id.$key.foo.h5ad'] + + // TODO: allow overriding the state.yaml template + // TODO TODO: if auto.publish == "state", add output_state as an argument + def yamlTemplate = params.containsKey("output_state") ? params.output_state : '$id.$key.state.yaml' + def yamlFilename = yamlTemplate + .replaceAll('\\$id', id_) + .replaceAll('\\$key', key_) + def yamlDir = java.nio.file.Paths.get(yamlFilename).getParent() + + // the processed state is a list of [key, value, inputPath, outputFilename] tuples, where + // - key is a String + // - value is any object that can be serialized to a Yaml (so a String/Integer/Long/Double/Boolean, a List, a Map, or a Path) + // - inputPath is a List[Path] + // - outputFilename is a List[String] + // - (key, value) are the tuples that will be saved to the state.yaml file + // - (inputPath, outputFilename) are the files that will be copied from src to dest (relative to the state.yaml) + def processedState = + config.allArguments + .findAll { it.direction == "output" } + .collectMany { par -> + def plainName_ = par.plainName + // if the state does not contain the key, it's an + // optional argument for which the component did + // not generate any output + if (!state_.containsKey(plainName_)) { + return [] + } + def value = state_[plainName_] + // if the parameter is not a file, it should be stored + // in the state as-is, but is not something that needs + // to be copied from the source path to the dest path + if (par.type != "file") { + return [[key: plainName_, value: value, inputPath: [], outputFilename: []]] + } + // if the orig state does not contain this filename, + // it's an optional argument for which the user specified + // that it should not be returned as a state + if (!origState_.containsKey(plainName_)) { + return [] + } + def filenameTemplate = origState_[plainName_] + // if the pararameter is multiple: true, fetch the template + if (par.multiple && filenameTemplate instanceof List) { + filenameTemplate = filenameTemplate[0] + } + // instantiate the template + def filename = filenameTemplate + .replaceAll('\\$id', id_) + .replaceAll('\\$key', key_) + if (par.multiple) { + // if the parameter is multiple: true, the filename + // should contain a wildcard '*' that is replaced with + // the index of the file + assert filename.contains("*") : "Module '${key_}' id '${id_}': Multiple output files specified, but no wildcard '*' in the filename: ${filename}" + def outputPerFile = value.withIndex().collect{ val, ix -> + def filename_ix = filename.replace("*", ix.toString()) + def value_ = java.nio.file.Paths.get(filename_ix) + // if id contains a slash + if (yamlDir != null) { + value_ = yamlDir.relativize(value_) + } + def inputPath = val instanceof File ? val.toPath() : val + [value: value_, inputPath: inputPath, outputFilename: filename_ix] + } + def transposedOutputs = ["value", "inputPath", "outputFilename"].collectEntries{ key -> + [key, outputPerFile.collect{dic -> dic[key]}] + } + return [[key: plainName_] + transposedOutputs] + } else { + def value_ = java.nio.file.Paths.get(filename) + // if id contains a slash + if (yamlDir != null) { + value_ = yamlDir.relativize(value_) + } + def inputPath = value instanceof File ? value.toPath() : value + return [[key: plainName_, value: value_, inputPath: [inputPath], outputFilename: [filename]]] + } + } + + def updatedState_ = processedState.collectEntries{[it.key, it.value]} + def inputPaths = processedState.collectMany{it.inputPath} + def outputFilenames = processedState.collectMany{it.outputFilename} + + // convert state to yaml blob + def yamlBlob_ = toTaggedYamlBlob([id: id_] + updatedState_) + + [id_, yamlBlob_, yamlFilename, inputPaths, outputFilenames] + } + | publishStatesProc + emit: input_ch + } + return publishStatesSimpleWf +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/states/setState.nf' +def setState(fun) { + assert fun instanceof Closure || fun instanceof Map || fun instanceof List : + "Error in setState: Expected process argument to be a Closure, a Map, or a List. Found: class ${fun.getClass()}" + + // if fun is a List, convert to map + if (fun instanceof List) { + // check whether fun is a list[string] + assert fun.every{it instanceof CharSequence} : "Error in setState: argument is a List, but not all elements are Strings" + fun = fun.collectEntries{[it, it]} + } + + // if fun is a map, convert to closure + if (fun instanceof Map) { + // check whether fun is a map[string, string] + assert fun.values().every{it instanceof CharSequence} : "Error in setState: argument is a Map, but not all values are Strings" + assert fun.keySet().every{it instanceof CharSequence} : "Error in setState: argument is a Map, but not all keys are Strings" + def funMap = fun.clone() + // turn the map into a closure to be used later on + fun = { id_, state_ -> + assert state_ instanceof Map : "Error in setState: the state is not a Map" + funMap.collectMany{newkey, origkey -> + if (state_.containsKey(origkey)) { + [[newkey, state_[origkey]]] + } else { + [] + } + }.collectEntries() + } + } + + map { tup -> + def id = tup[0] + def state = tup[1] + def unfilteredState = fun(id, state) + def newState = unfilteredState.findAll{key, val -> val != null} + [id, newState] + tup.drop(2) + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/workflowFactory/processAuto.nf' +// TODO: unit test processAuto +def processAuto(Map auto) { + // remove null values + auto = auto.findAll{k, v -> v != null} + + // check for unexpected keys + def expectedKeys = ["simplifyInput", "simplifyOutput", "transcript", "publish"] + def unexpectedKeys = auto.keySet() - expectedKeys + assert unexpectedKeys.isEmpty(), "unexpected keys in auto: '${unexpectedKeys.join("', '")}'" + + // check auto.simplifyInput + assert auto.simplifyInput instanceof Boolean, "auto.simplifyInput must be a boolean" + + // check auto.simplifyOutput + assert auto.simplifyOutput instanceof Boolean, "auto.simplifyOutput must be a boolean" + + // check auto.transcript + assert auto.transcript instanceof Boolean, "auto.transcript must be a boolean" + + // check auto.publish + assert auto.publish instanceof Boolean || auto.publish == "state", "auto.publish must be a boolean or 'state'" + + return auto.subMap(expectedKeys) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/workflowFactory/processDirectives.nf' +def assertMapKeys(map, expectedKeys, requiredKeys, mapName) { + assert map instanceof Map : "Expected argument '$mapName' to be a Map. Found: class ${map.getClass()}" + map.forEach { key, val -> + assert key in expectedKeys : "Unexpected key '$key' in ${mapName ? mapName + " " : ""}map" + } + requiredKeys.forEach { requiredKey -> + assert map.containsKey(requiredKey) : "Missing required key '$key' in ${mapName ? mapName + " " : ""}map" + } +} + +// TODO: unit test processDirectives +def processDirectives(Map drctv) { + // remove null values + drctv = drctv.findAll{k, v -> v != null} + + // check for unexpected keys + def expectedKeys = [ + "accelerator", "afterScript", "beforeScript", "cache", "conda", "container", "containerOptions", "cpus", "disk", "echo", "errorStrategy", "executor", "machineType", "maxErrors", "maxForks", "maxRetries", "memory", "module", "penv", "pod", "publishDir", "queue", "label", "scratch", "storeDir", "stageInMode", "stageOutMode", "tag", "time" + ] + def unexpectedKeys = drctv.keySet() - expectedKeys + assert unexpectedKeys.isEmpty() : "Unexpected keys in process directive: '${unexpectedKeys.join("', '")}'" + + /* DIRECTIVE accelerator + accepted examples: + - [ limit: 4, type: "nvidia-tesla-k80" ] + */ + if (drctv.containsKey("accelerator")) { + assertMapKeys(drctv["accelerator"], ["type", "limit", "request", "runtime"], [], "accelerator") + } + + /* DIRECTIVE afterScript + accepted examples: + - "source /cluster/bin/cleanup" + */ + if (drctv.containsKey("afterScript")) { + assert drctv["afterScript"] instanceof CharSequence + } + + /* DIRECTIVE beforeScript + accepted examples: + - "source /cluster/bin/setup" + */ + if (drctv.containsKey("beforeScript")) { + assert drctv["beforeScript"] instanceof CharSequence + } + + /* DIRECTIVE cache + accepted examples: + - true + - false + - "deep" + - "lenient" + */ + if (drctv.containsKey("cache")) { + assert drctv["cache"] instanceof CharSequence || drctv["cache"] instanceof Boolean + if (drctv["cache"] instanceof CharSequence) { + assert drctv["cache"] in ["deep", "lenient"] : "Unexpected value for cache" + } + } + + /* DIRECTIVE conda + accepted examples: + - "bwa=0.7.15" + - "bwa=0.7.15 fastqc=0.11.5" + - ["bwa=0.7.15", "fastqc=0.11.5"] + */ + if (drctv.containsKey("conda")) { + if (drctv["conda"] instanceof List) { + drctv["conda"] = drctv["conda"].join(" ") + } + assert drctv["conda"] instanceof CharSequence + } + + /* DIRECTIVE container + accepted examples: + - "foo/bar:tag" + - [ registry: "reg", image: "im", tag: "ta" ] + is transformed to "reg/im:ta" + - [ image: "im" ] + is transformed to "im:latest" + */ + if (drctv.containsKey("container")) { + assert drctv["container"] instanceof Map || drctv["container"] instanceof CharSequence + if (drctv["container"] instanceof Map) { + def m = drctv["container"] + assertMapKeys(m, [ "registry", "image", "tag" ], ["image"], "container") + def part1 = + System.getenv('OVERRIDE_CONTAINER_REGISTRY') ? System.getenv('OVERRIDE_CONTAINER_REGISTRY') + "/" : + params.containsKey("override_container_registry") ? params["override_container_registry"] + "/" : // todo: remove? + m.registry ? m.registry + "/" : + "" + def part2 = m.image + def part3 = m.tag ? ":" + m.tag : ":latest" + drctv["container"] = part1 + part2 + part3 + } + } + + /* DIRECTIVE containerOptions + accepted examples: + - "--foo bar" + - ["--foo bar", "-f b"] + */ + if (drctv.containsKey("containerOptions")) { + if (drctv["containerOptions"] instanceof List) { + drctv["containerOptions"] = drctv["containerOptions"].join(" ") + } + assert drctv["containerOptions"] instanceof CharSequence + } + + /* DIRECTIVE cpus + accepted examples: + - 1 + - 10 + */ + if (drctv.containsKey("cpus")) { + assert drctv["cpus"] instanceof Integer + } + + /* DIRECTIVE disk + accepted examples: + - "1 GB" + - "2TB" + - "3.2KB" + - "10.B" + */ + if (drctv.containsKey("disk")) { + assert drctv["disk"] instanceof CharSequence + // assert drctv["disk"].matches("[0-9]+(\\.[0-9]*)? *[KMGTPEZY]?B") + // ^ does not allow closures + } + + /* DIRECTIVE echo + accepted examples: + - true + - false + */ + if (drctv.containsKey("echo")) { + assert drctv["echo"] instanceof Boolean + } + + /* DIRECTIVE errorStrategy + accepted examples: + - "terminate" + - "finish" + */ + if (drctv.containsKey("errorStrategy")) { + assert drctv["errorStrategy"] instanceof CharSequence + assert drctv["errorStrategy"] in ["terminate", "finish", "ignore", "retry"] : "Unexpected value for errorStrategy" + } + + /* DIRECTIVE executor + accepted examples: + - "local" + - "sge" + */ + if (drctv.containsKey("executor")) { + assert drctv["executor"] instanceof CharSequence + assert drctv["executor"] in ["local", "sge", "uge", "lsf", "slurm", "pbs", "pbspro", "moab", "condor", "nqsii", "ignite", "k8s", "awsbatch", "google-pipelines"] : "Unexpected value for executor" + } + + /* DIRECTIVE machineType + accepted examples: + - "n1-highmem-8" + */ + if (drctv.containsKey("machineType")) { + assert drctv["machineType"] instanceof CharSequence + } + + /* DIRECTIVE maxErrors + accepted examples: + - 1 + - 3 + */ + if (drctv.containsKey("maxErrors")) { + assert drctv["maxErrors"] instanceof Integer + } + + /* DIRECTIVE maxForks + accepted examples: + - 1 + - 3 + */ + if (drctv.containsKey("maxForks")) { + assert drctv["maxForks"] instanceof Integer + } + + /* DIRECTIVE maxRetries + accepted examples: + - 1 + - 3 + */ + if (drctv.containsKey("maxRetries")) { + assert drctv["maxRetries"] instanceof Integer + } + + /* DIRECTIVE memory + accepted examples: + - "1 GB" + - "2TB" + - "3.2KB" + - "10.B" + */ + if (drctv.containsKey("memory")) { + assert drctv["memory"] instanceof CharSequence + // assert drctv["memory"].matches("[0-9]+(\\.[0-9]*)? *[KMGTPEZY]?B") + // ^ does not allow closures + } + + /* DIRECTIVE module + accepted examples: + - "ncbi-blast/2.2.27" + - "ncbi-blast/2.2.27:t_coffee/10.0" + - ["ncbi-blast/2.2.27", "t_coffee/10.0"] + */ + if (drctv.containsKey("module")) { + if (drctv["module"] instanceof List) { + drctv["module"] = drctv["module"].join(":") + } + assert drctv["module"] instanceof CharSequence + } + + /* DIRECTIVE penv + accepted examples: + - "smp" + */ + if (drctv.containsKey("penv")) { + assert drctv["penv"] instanceof CharSequence + } + + /* DIRECTIVE pod + accepted examples: + - [ label: "key", value: "val" ] + - [ annotation: "key", value: "val" ] + - [ env: "key", value: "val" ] + - [ [label: "l", value: "v"], [env: "e", value: "v"]] + */ + if (drctv.containsKey("pod")) { + if (drctv["pod"] instanceof Map) { + drctv["pod"] = [ drctv["pod"] ] + } + assert drctv["pod"] instanceof List + drctv["pod"].forEach { pod -> + assert pod instanceof Map + // TODO: should more checks be added? + // See https://www.nextflow.io/docs/latest/process.html?highlight=directives#pod + // e.g. does it contain 'label' and 'value', or 'annotation' and 'value', or ...? + } + } + + /* DIRECTIVE publishDir + accepted examples: + - [] + - [ [ path: "foo", enabled: true ], [ path: "bar", enabled: false ] ] + - "/path/to/dir" + is transformed to [[ path: "/path/to/dir" ]] + - [ path: "/path/to/dir", mode: "cache" ] + is transformed to [[ path: "/path/to/dir", mode: "cache" ]] + */ + // TODO: should we also look at params["publishDir"]? + if (drctv.containsKey("publishDir")) { + def pblsh = drctv["publishDir"] + + // check different options + assert pblsh instanceof List || pblsh instanceof Map || pblsh instanceof CharSequence + + // turn into list if not already so + // for some reason, 'if (!pblsh instanceof List) pblsh = [ pblsh ]' doesn't work. + pblsh = pblsh instanceof List ? pblsh : [ pblsh ] + + // check elements of publishDir + pblsh = pblsh.collect{ elem -> + // turn into map if not already so + elem = elem instanceof CharSequence ? [ path: elem ] : elem + + // check types and keys + assert elem instanceof Map : "Expected publish argument '$elem' to be a String or a Map. Found: class ${elem.getClass()}" + assertMapKeys(elem, [ "path", "mode", "overwrite", "pattern", "saveAs", "enabled" ], ["path"], "publishDir") + + // check elements in map + assert elem.containsKey("path") + assert elem["path"] instanceof CharSequence + if (elem.containsKey("mode")) { + assert elem["mode"] instanceof CharSequence + assert elem["mode"] in [ "symlink", "rellink", "link", "copy", "copyNoFollow", "move" ] + } + if (elem.containsKey("overwrite")) { + assert elem["overwrite"] instanceof Boolean + } + if (elem.containsKey("pattern")) { + assert elem["pattern"] instanceof CharSequence + } + if (elem.containsKey("saveAs")) { + assert elem["saveAs"] instanceof CharSequence //: "saveAs as a Closure is currently not supported. Surround your closure with single quotes to get the desired effect. Example: '\{ foo \}'" + } + if (elem.containsKey("enabled")) { + assert elem["enabled"] instanceof Boolean + } + + // return final result + elem + } + // store final directive + drctv["publishDir"] = pblsh + } + + /* DIRECTIVE queue + accepted examples: + - "long" + - "short,long" + - ["short", "long"] + */ + if (drctv.containsKey("queue")) { + if (drctv["queue"] instanceof List) { + drctv["queue"] = drctv["queue"].join(",") + } + assert drctv["queue"] instanceof CharSequence + } + + /* DIRECTIVE label + accepted examples: + - "big_mem" + - "big_cpu" + - ["big_mem", "big_cpu"] + */ + if (drctv.containsKey("label")) { + if (drctv["label"] instanceof CharSequence) { + drctv["label"] = [ drctv["label"] ] + } + assert drctv["label"] instanceof List + drctv["label"].forEach { label -> + assert label instanceof CharSequence + // assert label.matches("[a-zA-Z0-9]([a-zA-Z0-9_]*[a-zA-Z0-9])?") + // ^ does not allow closures + } + } + + /* DIRECTIVE scratch + accepted examples: + - true + - "/path/to/scratch" + - '$MY_PATH_TO_SCRATCH' + - "ram-disk" + */ + if (drctv.containsKey("scratch")) { + assert drctv["scratch"] == true || drctv["scratch"] instanceof CharSequence + } + + /* DIRECTIVE storeDir + accepted examples: + - "/path/to/storeDir" + */ + if (drctv.containsKey("storeDir")) { + assert drctv["storeDir"] instanceof CharSequence + } + + /* DIRECTIVE stageInMode + accepted examples: + - "copy" + - "link" + */ + if (drctv.containsKey("stageInMode")) { + assert drctv["stageInMode"] instanceof CharSequence + assert drctv["stageInMode"] in ["copy", "link", "symlink", "rellink"] + } + + /* DIRECTIVE stageOutMode + accepted examples: + - "copy" + - "link" + */ + if (drctv.containsKey("stageOutMode")) { + assert drctv["stageOutMode"] instanceof CharSequence + assert drctv["stageOutMode"] in ["copy", "move", "rsync"] + } + + /* DIRECTIVE tag + accepted examples: + - "foo" + - '$id' + */ + if (drctv.containsKey("tag")) { + assert drctv["tag"] instanceof CharSequence + } + + /* DIRECTIVE time + accepted examples: + - "1h" + - "2days" + - "1day 6hours 3minutes 30seconds" + */ + if (drctv.containsKey("time")) { + assert drctv["time"] instanceof CharSequence + // todo: validation regex? + } + + return drctv +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/workflowFactory/processWorkflowArgs.nf' +def processWorkflowArgs(Map args, Map defaultWfArgs, Map meta) { + // override defaults with args + def workflowArgs = defaultWfArgs + args + + // check whether 'key' exists + assert workflowArgs.containsKey("key") : "Error in module '${meta.config.name}': key is a required argument" + + // if 'key' is a closure, apply it to the original key + if (workflowArgs["key"] instanceof Closure) { + workflowArgs["key"] = workflowArgs["key"](meta.config.name) + } + def key = workflowArgs["key"] + assert key instanceof CharSequence : "Expected process argument 'key' to be a String. Found: class ${key.getClass()}" + assert key ==~ /^[a-zA-Z_]\w*$/ : "Error in module '$key': Expected process argument 'key' to consist of only letters, digits or underscores. Found: ${key}" + + // check for any unexpected keys + def expectedKeys = ["key", "directives", "auto", "map", "mapId", "mapData", "mapPassthrough", "filter", "runIf", "fromState", "toState", "args", "renameKeys", "debug"] + def unexpectedKeys = workflowArgs.keySet() - expectedKeys + assert unexpectedKeys.isEmpty() : "Error in module '$key': unexpected arguments to the '.run()' function: '${unexpectedKeys.join("', '")}'" + + // check whether directives exists and apply defaults + assert workflowArgs.containsKey("directives") : "Error in module '$key': directives is a required argument" + assert workflowArgs["directives"] instanceof Map : "Error in module '$key': Expected process argument 'directives' to be a Map. Found: class ${workflowArgs['directives'].getClass()}" + workflowArgs["directives"] = processDirectives(defaultWfArgs.directives + workflowArgs["directives"]) + + // check whether directives exists and apply defaults + assert workflowArgs.containsKey("auto") : "Error in module '$key': auto is a required argument" + assert workflowArgs["auto"] instanceof Map : "Error in module '$key': Expected process argument 'auto' to be a Map. Found: class ${workflowArgs['auto'].getClass()}" + workflowArgs["auto"] = processAuto(defaultWfArgs.auto + workflowArgs["auto"]) + + // auto define publish, if so desired + if (workflowArgs.auto.publish == true && (workflowArgs.directives.publishDir != null ? workflowArgs.directives.publishDir : [:]).isEmpty()) { + // can't assert at this level thanks to the no_publish profile + // assert params.containsKey("publishDir") || params.containsKey("publish_dir") : + // "Error in module '${workflowArgs['key']}': if auto.publish is true, params.publish_dir needs to be defined.\n" + + // " Example: params.publish_dir = \"./output/\"" + def publishDir = getPublishDir() + + if (publishDir != null) { + workflowArgs.directives.publishDir = [[ + path: publishDir, + saveAs: "{ it.startsWith('.') ? null : it }", // don't publish hidden files, by default + mode: "copy" + ]] + } + } + + // auto define transcript, if so desired + if (workflowArgs.auto.transcript == true) { + // can't assert at this level thanks to the no_publish profile + // assert params.containsKey("transcriptsDir") || params.containsKey("transcripts_dir") || params.containsKey("publishDir") || params.containsKey("publish_dir") : + // "Error in module '${workflowArgs['key']}': if auto.transcript is true, either params.transcripts_dir or params.publish_dir needs to be defined.\n" + + // " Example: params.transcripts_dir = \"./transcripts/\"" + def transcriptsDir = + params.containsKey("transcripts_dir") ? params.transcripts_dir : + params.containsKey("transcriptsDir") ? params.transcriptsDir : + params.containsKey("publish_dir") ? params.publish_dir + "/_transcripts" : + params.containsKey("publishDir") ? params.publishDir + "/_transcripts" : + null + if (transcriptsDir != null) { + def timestamp = nextflow.Nextflow.getSession().getWorkflowMetadata().start.format('yyyy-MM-dd_HH-mm-ss') + def transcriptsPublishDir = [ + path: "$transcriptsDir/$timestamp/\${task.process.replaceAll(':', '-')}/\${id}/", + saveAs: "{ it.startsWith('.') ? it.replaceAll('^.', '') : null }", + mode: "copy" + ] + def publishDirs = workflowArgs.directives.publishDir != null ? workflowArgs.directives.publishDir : null ? workflowArgs.directives.publishDir : [] + workflowArgs.directives.publishDir = publishDirs + transcriptsPublishDir + } + } + + // if this is a stubrun, remove certain directives? + if (workflow.stubRun) { + workflowArgs.directives.keySet().removeAll(["publishDir", "cpus", "memory", "label"]) + } + + for (nam in ["map", "mapId", "mapData", "mapPassthrough", "filter", "runIf"]) { + if (workflowArgs.containsKey(nam) && workflowArgs[nam]) { + assert workflowArgs[nam] instanceof Closure : "Error in module '$key': Expected process argument '$nam' to be null or a Closure. Found: class ${workflowArgs[nam].getClass()}" + } + } + + // TODO: should functions like 'map', 'mapId', 'mapData', 'mapPassthrough' be deprecated as well? + for (nam in ["map", "mapData", "mapPassthrough", "renameKeys"]) { + if (workflowArgs.containsKey(nam) && workflowArgs[nam] != null) { + log.warn "module '$key': workflow argument '$nam' is deprecated and will be removed in Viash 0.9.0. Please use 'fromState' and 'toState' instead." + } + } + + // check fromState + workflowArgs["fromState"] = _processFromState(workflowArgs.get("fromState"), key, meta.config) + + // check toState + workflowArgs["toState"] = _processToState(workflowArgs.get("toState"), key, meta.config) + + // return output + return workflowArgs +} + +def _processFromState(fromState, key_, config_) { + assert fromState == null || fromState instanceof Closure || fromState instanceof Map || fromState instanceof List : + "Error in module '$key_': Expected process argument 'fromState' to be null, a Closure, a Map, or a List. Found: class ${fromState.getClass()}" + if (fromState == null) { + return null + } + + // if fromState is a List, convert to map + if (fromState instanceof List) { + // check whether fromstate is a list[string] + assert fromState.every{it instanceof CharSequence} : "Error in module '$key_': fromState is a List, but not all elements are Strings" + fromState = fromState.collectEntries{[it, it]} + } + + // if fromState is a map, convert to closure + if (fromState instanceof Map) { + // check whether fromstate is a map[string, string] + assert fromState.values().every{it instanceof CharSequence} : "Error in module '$key_': fromState is a Map, but not all values are Strings" + assert fromState.keySet().every{it instanceof CharSequence} : "Error in module '$key_': fromState is a Map, but not all keys are Strings" + def fromStateMap = fromState.clone() + def requiredInputNames = meta.config.allArguments.findAll{it.required && it.direction == "Input"}.collect{it.plainName} + // turn the map into a closure to be used later on + fromState = { it -> + def state = it[1] + assert state instanceof Map : "Error in module '$key_': the state is not a Map" + def data = fromStateMap.collectMany{newkey, origkey -> + // check whether newkey corresponds to a required argument + if (state.containsKey(origkey)) { + [[newkey, state[origkey]]] + } else if (!requiredInputNames.contains(origkey)) { + [] + } else { + throw new Exception("Error in module '$key_': fromState key '$origkey' not found in current state") + } + }.collectEntries() + data + } + } + + return fromState +} + +def _processToState(toState, key_, config_) { + if (toState == null) { + toState = { tup -> tup[1] } + } + + // toState should be a closure, map[string, string], or list[string] + assert toState instanceof Closure || toState instanceof Map || toState instanceof List : + "Error in module '$key_': Expected process argument 'toState' to be a Closure, a Map, or a List. Found: class ${toState.getClass()}" + + // if toState is a List, convert to map + if (toState instanceof List) { + // check whether toState is a list[string] + assert toState.every{it instanceof CharSequence} : "Error in module '$key_': toState is a List, but not all elements are Strings" + toState = toState.collectEntries{[it, it]} + } + + // if toState is a map, convert to closure + if (toState instanceof Map) { + // check whether toState is a map[string, string] + assert toState.values().every{it instanceof CharSequence} : "Error in module '$key_': toState is a Map, but not all values are Strings" + assert toState.keySet().every{it instanceof CharSequence} : "Error in module '$key_': toState is a Map, but not all keys are Strings" + def toStateMap = toState.clone() + def requiredOutputNames = config_.allArguments.findAll{it.required && it.direction == "Output"}.collect{it.plainName} + // turn the map into a closure to be used later on + toState = { it -> + def output = it[1] + def state = it[2] + assert output instanceof Map : "Error in module '$key_': the output is not a Map" + assert state instanceof Map : "Error in module '$key_': the state is not a Map" + def extraEntries = toStateMap.collectMany{newkey, origkey -> + // check whether newkey corresponds to a required argument + if (output.containsKey(origkey)) { + [[newkey, output[origkey]]] + } else if (!requiredOutputNames.contains(origkey)) { + [] + } else { + throw new Exception("Error in module '$key_': toState key '$origkey' not found in current output") + } + }.collectEntries() + state + extraEntries + } + } + + return toState +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/workflowFactory/workflowFactory.nf' +def _debug(workflowArgs, debugKey) { + if (workflowArgs.debug) { + view { "process '${workflowArgs.key}' $debugKey tuple: $it" } + } else { + map { it } + } +} + +// depends on: innerWorkflowFactory +def workflowFactory(Map args, Map defaultWfArgs, Map meta) { + def workflowArgs = processWorkflowArgs(args, defaultWfArgs, meta) + def key_ = workflowArgs["key"] + + workflow workflowInstance { + take: input_ + + main: + def chModified = input_ + | checkUniqueIds([:]) + | _debug(workflowArgs, "input") + | map { tuple -> + tuple = deepClone(tuple) + + if (workflowArgs.map) { + tuple = workflowArgs.map(tuple) + } + if (workflowArgs.mapId) { + tuple[0] = workflowArgs.mapId(tuple[0]) + } + if (workflowArgs.mapData) { + tuple[1] = workflowArgs.mapData(tuple[1]) + } + if (workflowArgs.mapPassthrough) { + tuple = tuple.take(2) + workflowArgs.mapPassthrough(tuple.drop(2)) + } + + // check tuple + assert tuple instanceof List : + "Error in module '${key_}': element in channel should be a tuple [id, data, ...otherargs...]\n" + + " Example: [\"id\", [input: file('foo.txt'), arg: 10]].\n" + + " Expected class: List. Found: tuple.getClass() is ${tuple.getClass()}" + assert tuple.size() >= 2 : + "Error in module '${key_}': expected length of tuple in input channel to be two or greater.\n" + + " Example: [\"id\", [input: file('foo.txt'), arg: 10]].\n" + + " Found: tuple.size() == ${tuple.size()}" + + // check id field + if (tuple[0] instanceof GString) { + tuple[0] = tuple[0].toString() + } + assert tuple[0] instanceof CharSequence : + "Error in module '${key_}': first element of tuple in channel should be a String\n" + + " Example: [\"id\", [input: file('foo.txt'), arg: 10]].\n" + + " Found: ${tuple[0]}" + + // match file to input file + if (workflowArgs.auto.simplifyInput && (tuple[1] instanceof Path || tuple[1] instanceof List)) { + def inputFiles = meta.config.allArguments + .findAll { it.type == "file" && it.direction == "input" } + + assert inputFiles.size() == 1 : + "Error in module '${key_}' id '${tuple[0]}'.\n" + + " Anonymous file inputs are only allowed when the process has exactly one file input.\n" + + " Expected: inputFiles.size() == 1. Found: inputFiles.size() is ${inputFiles.size()}" + + tuple[1] = [[ inputFiles[0].plainName, tuple[1] ]].collectEntries() + } + + // check data field + assert tuple[1] instanceof Map : + "Error in module '${key_}' id '${tuple[0]}': second element of tuple in channel should be a Map\n" + + " Example: [\"id\", [input: file('foo.txt'), arg: 10]].\n" + + " Expected class: Map. Found: tuple[1].getClass() is ${tuple[1].getClass()}" + + // rename keys of data field in tuple + if (workflowArgs.renameKeys) { + assert workflowArgs.renameKeys instanceof Map : + "Error renaming data keys in module '${key_}' id '${tuple[0]}'.\n" + + " Example: renameKeys: ['new_key': 'old_key'].\n" + + " Expected class: Map. Found: renameKeys.getClass() is ${workflowArgs.renameKeys.getClass()}" + assert tuple[1] instanceof Map : + "Error renaming data keys in module '${key_}' id '${tuple[0]}'.\n" + + " Expected class: Map. Found: tuple[1].getClass() is ${tuple[1].getClass()}" + + // TODO: allow renameKeys to be a function? + workflowArgs.renameKeys.each { newKey, oldKey -> + assert newKey instanceof CharSequence : + "Error renaming data keys in module '${key_}' id '${tuple[0]}'.\n" + + " Example: renameKeys: ['new_key': 'old_key'].\n" + + " Expected class of newKey: String. Found: newKey.getClass() is ${newKey.getClass()}" + assert oldKey instanceof CharSequence : + "Error renaming data keys in module '${key_}' id '${tuple[0]}'.\n" + + " Example: renameKeys: ['new_key': 'old_key'].\n" + + " Expected class of oldKey: String. Found: oldKey.getClass() is ${oldKey.getClass()}" + assert tuple[1].containsKey(oldKey) : + "Error renaming data keys in module '${key}' id '${tuple[0]}'.\n" + + " Key '$oldKey' is missing in the data map. tuple[1].keySet() is '${tuple[1].keySet()}'" + tuple[1].put(newKey, tuple[1][oldKey]) + } + tuple[1].keySet().removeAll(workflowArgs.renameKeys.collect{ newKey, oldKey -> oldKey }) + } + tuple + } + + def chModifiedFiltered = workflowArgs.filter ? + chModified | filter{workflowArgs.filter(it)} : + chModified + + def chRun = null + def chPassthrough = null + if (workflowArgs.runIf) { + def runIfBranch = chModifiedFiltered.branch{ tup -> + run: workflowArgs.runIf(tup[0], tup[1]) + passthrough: true + } + chRun = runIfBranch.run + chPassthrough = runIfBranch.passthrough + } else { + chRun = chModifiedFiltered + chPassthrough = Channel.empty() + } + + def chArgs = workflowArgs.fromState ? + chRun | map{ + def new_data = workflowArgs.fromState(it.take(2)) + [it[0], new_data] + } : + chRun | map {tup -> tup.take(2)} + + // fill in defaults + def chArgsWithDefaults = chArgs + | map { tuple -> + def id_ = tuple[0] + def data_ = tuple[1] + + // TODO: could move fromState to here + + // fetch default params from functionality + def defaultArgs = meta.config.allArguments + .findAll { it.containsKey("default") } + .collectEntries { [ it.plainName, it.default ] } + + // fetch overrides in params + def paramArgs = meta.config.allArguments + .findAll { par -> + def argKey = key_ + "__" + par.plainName + params.containsKey(argKey) + } + .collectEntries { [ it.plainName, params[key_ + "__" + it.plainName] ] } + + // fetch overrides in data + def dataArgs = meta.config.allArguments + .findAll { data_.containsKey(it.plainName) } + .collectEntries { [ it.plainName, data_[it.plainName] ] } + + // combine params + def combinedArgs = defaultArgs + paramArgs + workflowArgs.args + dataArgs + + // remove arguments with explicit null values + combinedArgs + .removeAll{_, val -> val == null || val == "viash_no_value" || val == "force_null"} + + combinedArgs = _processInputValues(combinedArgs, meta.config, id_, key_) + + [id_, combinedArgs] + tuple.drop(2) + } + + // TODO: move some of the _meta.join_id wrangling to the safeJoin() function. + def chInitialOutput = chArgsWithDefaults + | _debug(workflowArgs, "processed") + // run workflow + | innerWorkflowFactory(workflowArgs) + // check output tuple + | map { id_, output_ -> + + // see if output map contains metadata + def meta_ = + output_ instanceof Map && output_.containsKey("_meta") ? + output_["_meta"] : + [:] + def join_id = meta_.join_id ?: id_ + + // remove metadata + output_ = output_.findAll{k, v -> k != "_meta"} + + // check value types + output_ = _processOutputValues(output_, meta.config, id_, key_) + + // simplify output if need be + if (workflowArgs.auto.simplifyOutput && output_.size() == 1) { + output_ = output_.values()[0] + } + + [join_id, id_, output_] + } + // | view{"chInitialOutput: ${it.take(3)}"} + + // join the output [prev_id, new_id, output] with the previous state [prev_id, state, ...] + def chNewState = safeJoin(chInitialOutput, chModifiedFiltered, key_) + // input tuple format: [join_id, id, output, prev_state, ...] + // output tuple format: [join_id, id, new_state, ...] + | map{ tup -> + def new_state = workflowArgs.toState(tup.drop(1).take(3)) + tup.take(2) + [new_state] + tup.drop(4) + } + + if (workflowArgs.auto.publish == "state") { + def chPublish = chNewState + // input tuple format: [join_id, id, new_state, ...] + // output tuple format: [join_id, id, new_state] + | map{ tup -> + tup.take(3) + } + + safeJoin(chPublish, chArgsWithDefaults, key_) + // input tuple format: [join_id, id, new_state, orig_state, ...] + // output tuple format: [id, new_state, orig_state] + | map { tup -> + tup.drop(1).take(3) + } + | publishStatesByConfig(key: key_, config: meta.config) + } + + // remove join_id and meta + chReturn = chNewState + | map { tup -> + // input tuple format: [join_id, id, new_state, ...] + // output tuple format: [id, new_state, ...] + tup.drop(1) + } + | _debug(workflowArgs, "output") + | concat(chPassthrough) + + emit: chReturn + } + + def wf = workflowInstance.cloneWithName(key_) + + // add factory function + wf.metaClass.run = { runArgs -> + workflowFactory(runArgs, workflowArgs, meta) + } + // add config to module for later introspection + wf.metaClass.config = meta.config + + return wf +} + +nextflow.enable.dsl=2 + +// START COMPONENT-SPECIFIC CODE + +// create meta object +meta = [ + "resources_dir": moduleDir.toRealPath().normalize(), + "config": processConfig(readJsonBlob('''{ + "name" : "agat_convert_sp_gxf2gxf", + "namespace" : "agat", + "version" : "main", + "authors" : [ + { + "name" : "Leïla Paquay", + "roles" : [ + "author", + "maintainer" + ], + "info" : { + "links" : { + "email" : "leila@data-intuitive.com", + "github" : "Leila011", + "linkedin" : "leilapaquay" + }, + "organizations" : [ + { + "name" : "Data Intuitive", + "href" : "https://www.data-intuitive.com", + "role" : "Software Developer" + } + ] + } + } + ], + "argument_groups" : [ + { + "name" : "Inputs", + "arguments" : [ + { + "type" : "file", + "name" : "--gxf", + "alternatives" : [ + "-g", + "--gtf", + "--gff" + ], + "description" : "String - Input GTF/GFF file. Compressed file with .gz extension is accepted.\n", + "example" : [ + "input.gff" + ], + "must_exist" : true, + "create_parent" : true, + "required" : true, + "direction" : "input", + "multiple" : false, + "multiple_sep" : ";" + } + ] + }, + { + "name" : "Outputs", + "arguments" : [ + { + "type" : "file", + "name" : "--output", + "alternatives" : [ + "-o" + ], + "description" : "String - Output GFF file. If no output file is specified, the output will be written to STDOUT.\n", + "example" : [ + "output.gff" + ], + "must_exist" : true, + "create_parent" : true, + "required" : true, + "direction" : "output", + "multiple" : false, + "multiple_sep" : ";" + } + ] + }, + { + "name" : "Arguments", + "arguments" : [ + { + "type" : "file", + "name" : "--config", + "alternatives" : [ + "-c" + ], + "description" : "String - Input agat config file. By default AGAT takes as input agat_config.yaml file from the working directory if any, otherwise it takes the original agat_config.yaml shipped with AGAT. To get the agat_config.yaml locally type: \\"agat config --expose\\". The --config option gives you the possibility to use your own AGAT config file (located elsewhere or named differently).\n", + "example" : [ + "custom_agat_config.yaml" + ], + "must_exist" : true, + "create_parent" : true, + "required" : false, + "direction" : "input", + "multiple" : false, + "multiple_sep" : ";" + } + ] + } + ], + "resources" : [ + { + "type" : "bash_script", + "path" : "script.sh", + "is_executable" : true + } + ], + "description" : "This script fixes and/or standardizes any GTF/GFF file into full sorted\nGTF/GFF file. It AGAT parser removes duplicate features, fixes\nduplicated IDs, adds missing ID and/or Parent attributes, deflates\nfactorized attributes (attributes with several parents are duplicated\nwith uniq ID), add missing features when possible (e.g. add exon if only\nCDS described, add UTR if CDS and exon described), fix feature locations\n(e.g. check exon is embedded in the parent features mRNA, gene), etc...\n\nAll AGAT's scripts with the _sp_ prefix use the AGAT parser, before to\nperform any supplementary task. So, it is not necessary to run this\nscript prior the use of any other _sp_ script.\n", + "test_resources" : [ + { + "type" : "bash_script", + "path" : "test.sh", + "is_executable" : true + }, + { + "type" : "file", + "path" : "test_data" + } + ], + "status" : "enabled", + "requirements" : { + "commands" : [ + "ps" + ] + }, + "keywords" : [ + "gene annotations", + "GFF conversion" + ], + "license" : "GPL-3.0", + "references" : { + "doi" : [ + "10.5281/zenodo.3552717" + ] + }, + "links" : { + "repository" : "https://github.com/NBISweden/AGAT", + "homepage" : "https://github.com/NBISweden/AGAT", + "documentation" : "https://agat.readthedocs.io/en/latest/tools/agat_convert_sp_gxf2gxf.html", + "issue_tracker" : "https://github.com/NBISweden/AGAT/issues" + }, + "runners" : [ + { + "type" : "executable", + "id" : "executable", + "docker_setup_strategy" : "ifneedbepullelsecachedbuild" + }, + { + "type" : "nextflow", + "id" : "nextflow", + "directives" : { + "tag" : "$id" + }, + "auto" : { + "simplifyInput" : true, + "simplifyOutput" : false, + "transcript" : false, + "publish" : false + }, + "config" : { + "labels" : { + "mem1gb" : "memory = 1000000000.B", + "mem2gb" : "memory = 2000000000.B", + "mem5gb" : "memory = 5000000000.B", + "mem10gb" : "memory = 10000000000.B", + "mem20gb" : "memory = 20000000000.B", + "mem50gb" : "memory = 50000000000.B", + "mem100gb" : "memory = 100000000000.B", + "mem200gb" : "memory = 200000000000.B", + "mem500gb" : "memory = 500000000000.B", + "mem1tb" : "memory = 1000000000000.B", + "mem2tb" : "memory = 2000000000000.B", + "mem5tb" : "memory = 5000000000000.B", + "mem10tb" : "memory = 10000000000000.B", + "mem20tb" : "memory = 20000000000000.B", + "mem50tb" : "memory = 50000000000000.B", + "mem100tb" : "memory = 100000000000000.B", + "mem200tb" : "memory = 200000000000000.B", + "mem500tb" : "memory = 500000000000000.B", + "mem1gib" : "memory = 1073741824.B", + "mem2gib" : "memory = 2147483648.B", + "mem4gib" : "memory = 4294967296.B", + "mem8gib" : "memory = 8589934592.B", + "mem16gib" : "memory = 17179869184.B", + "mem32gib" : "memory = 34359738368.B", + "mem64gib" : "memory = 68719476736.B", + "mem128gib" : "memory = 137438953472.B", + "mem256gib" : "memory = 274877906944.B", + "mem512gib" : "memory = 549755813888.B", + "mem1tib" : "memory = 1099511627776.B", + "mem2tib" : "memory = 2199023255552.B", + "mem4tib" : "memory = 4398046511104.B", + "mem8tib" : "memory = 8796093022208.B", + "mem16tib" : "memory = 17592186044416.B", + "mem32tib" : "memory = 35184372088832.B", + "mem64tib" : "memory = 70368744177664.B", + "mem128tib" : "memory = 140737488355328.B", + "mem256tib" : "memory = 281474976710656.B", + "mem512tib" : "memory = 562949953421312.B", + "cpu1" : "cpus = 1", + "cpu2" : "cpus = 2", + "cpu5" : "cpus = 5", + "cpu10" : "cpus = 10", + "cpu20" : "cpus = 20", + "cpu50" : "cpus = 50", + "cpu100" : "cpus = 100", + "cpu200" : "cpus = 200", + "cpu500" : "cpus = 500", + "cpu1000" : "cpus = 1000" + } + }, + "debug" : false, + "container" : "docker" + } + ], + "engines" : [ + { + "type" : "docker", + "id" : "docker", + "image" : "quay.io/biocontainers/agat:1.4.0--pl5321hdfd78af_0", + "target_registry" : "images.viash-hub.com", + "target_tag" : "main", + "namespace_separator" : "/", + "setup" : [ + { + "type" : "docker", + "run" : [ + "agat --version | sed 's/AGAT\\\\s\\\\(.*\\\\)/agat: \\"\\\\1\\"/' > /var/software_versions.txt\n" + ] + } + ] + }, + { + "type" : "native", + "id" : "native" + } + ], + "build_info" : { + "config" : "/workdir/root/repo/src/agat/agat_convert_sp_gxf2gxf/config.vsh.yaml", + "runner" : "nextflow", + "engine" : "docker|native", + "output" : "target/nextflow/agat/agat_convert_sp_gxf2gxf", + "viash_version" : "0.9.0-RC6", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", + "git_remote" : "https://github.com/viash-hub/biobox" + }, + "package_config" : { + "name" : "biobox", + "version" : "main", + "description" : "A collection of bioinformatics tools for working with sequence data.\n", + "viash_version" : "0.9.0-RC6", + "source" : "src", + "target" : "target", + "config_mods" : [ + ".requirements.commands := ['ps']\n", + ".engines += { type: \\"native\\" }", + ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'", + ".engines[.type == 'docker'].target_tag := 'main'" + ], + "keywords" : [ + "bioinformatics", + "modules", + "sequencing" + ], + "license" : "MIT", + "organization" : "vsh", + "links" : { + "repository" : "https://github.com/viash-hub/biobox", + "issue_tracker" : "https://github.com/viash-hub/biobox/issues" + } + } +}''')) +] + +// resolve dependencies dependencies (if any) + + +// inner workflow +// inner workflow hook +def innerWorkflowFactory(args) { + def rawScript = '''set -e +tempscript=".viash_script.sh" +cat > "$tempscript" << VIASHMAIN +#!/bin/bash + +## VIASH START +# The following code has been auto-generated by Viash. +$( if [ ! -z ${VIASH_PAR_GXF+x} ]; then echo "${VIASH_PAR_GXF}" | sed "s#'#'\\"'\\"'#g;s#.*#par_gxf='&'#" ; else echo "# par_gxf="; fi ) +$( if [ ! -z ${VIASH_PAR_OUTPUT+x} ]; then echo "${VIASH_PAR_OUTPUT}" | sed "s#'#'\\"'\\"'#g;s#.*#par_output='&'#" ; else echo "# par_output="; fi ) +$( if [ ! -z ${VIASH_PAR_CONFIG+x} ]; then echo "${VIASH_PAR_CONFIG}" | sed "s#'#'\\"'\\"'#g;s#.*#par_config='&'#" ; else echo "# par_config="; fi ) +$( if [ ! -z ${VIASH_META_NAME+x} ]; then echo "${VIASH_META_NAME}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_name='&'#" ; else echo "# meta_name="; fi ) +$( if [ ! -z ${VIASH_META_FUNCTIONALITY_NAME+x} ]; then echo "${VIASH_META_FUNCTIONALITY_NAME}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_functionality_name='&'#" ; else echo "# meta_functionality_name="; fi ) +$( if [ ! -z ${VIASH_META_RESOURCES_DIR+x} ]; then echo "${VIASH_META_RESOURCES_DIR}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_resources_dir='&'#" ; else echo "# meta_resources_dir="; fi ) +$( if [ ! -z ${VIASH_META_EXECUTABLE+x} ]; then echo "${VIASH_META_EXECUTABLE}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_executable='&'#" ; else echo "# meta_executable="; fi ) +$( if [ ! -z ${VIASH_META_CONFIG+x} ]; then echo "${VIASH_META_CONFIG}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_config='&'#" ; else echo "# meta_config="; fi ) +$( if [ ! -z ${VIASH_META_TEMP_DIR+x} ]; then echo "${VIASH_META_TEMP_DIR}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_temp_dir='&'#" ; else echo "# meta_temp_dir="; fi ) +$( if [ ! -z ${VIASH_META_CPUS+x} ]; then echo "${VIASH_META_CPUS}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_cpus='&'#" ; else echo "# meta_cpus="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_B+x} ]; then echo "${VIASH_META_MEMORY_B}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_b='&'#" ; else echo "# meta_memory_b="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_KB+x} ]; then echo "${VIASH_META_MEMORY_KB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_kb='&'#" ; else echo "# meta_memory_kb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_MB+x} ]; then echo "${VIASH_META_MEMORY_MB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_mb='&'#" ; else echo "# meta_memory_mb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_GB+x} ]; then echo "${VIASH_META_MEMORY_GB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_gb='&'#" ; else echo "# meta_memory_gb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_TB+x} ]; then echo "${VIASH_META_MEMORY_TB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_tb='&'#" ; else echo "# meta_memory_tb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_PB+x} ]; then echo "${VIASH_META_MEMORY_PB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_pb='&'#" ; else echo "# meta_memory_pb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_KIB+x} ]; then echo "${VIASH_META_MEMORY_KIB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_kib='&'#" ; else echo "# meta_memory_kib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_MIB+x} ]; then echo "${VIASH_META_MEMORY_MIB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_mib='&'#" ; else echo "# meta_memory_mib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_GIB+x} ]; then echo "${VIASH_META_MEMORY_GIB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_gib='&'#" ; else echo "# meta_memory_gib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_TIB+x} ]; then echo "${VIASH_META_MEMORY_TIB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_tib='&'#" ; else echo "# meta_memory_tib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_pib='&'#" ; else echo "# meta_memory_pib="; fi ) + +## VIASH END + +agat_convert_sp_gxf2gxf.pl \\\\ + -g "\\$par_gxf" \\\\ + -o "\\$par_output" \\\\ + \\${par_config:+--config "\\${par_config}"} +VIASHMAIN +bash "$tempscript" +''' + + return vdsl3WorkflowFactory(args, meta, rawScript) +} + + + +/** + * Generate a workflow for VDSL3 modules. + * + * This function is called by the workflowFactory() function. + * + * Input channel: [id, input_map] + * Output channel: [id, output_map] + * + * Internally, this workflow will convert the input channel + * to a format which the Nextflow module will be able to handle. + */ +def vdsl3WorkflowFactory(Map args, Map meta, String rawScript) { + def key = args["key"] + def processObj = null + + workflow processWf { + take: input_ + main: + + if (processObj == null) { + processObj = _vdsl3ProcessFactory(args, meta, rawScript) + } + + output_ = input_ + | map { tuple -> + def id = tuple[0] + def data_ = tuple[1] + + if (workflow.stubRun) { + // add id if missing + data_ = [id: 'stub'] + data_ + } + + // process input files separately + def inputPaths = meta.config.allArguments + .findAll { it.type == "file" && it.direction == "input" } + .collect { par -> + def val = data_.containsKey(par.plainName) ? data_[par.plainName] : [] + def inputFiles = [] + if (val == null) { + inputFiles = [] + } else if (val instanceof List) { + inputFiles = val + } else if (val instanceof Path) { + inputFiles = [ val ] + } else { + inputFiles = [] + } + if (!workflow.stubRun) { + // throw error when an input file doesn't exist + inputFiles.each{ file -> + assert file.exists() : + "Error in module '${key}' id '${id}' argument '${par.plainName}'.\n" + + " Required input file does not exist.\n" + + " Path: '$file'.\n" + + " Expected input file to exist" + } + } + inputFiles + } + + // remove input files + def argsExclInputFiles = meta.config.allArguments + .findAll { (it.type != "file" || it.direction != "input") && data_.containsKey(it.plainName) } + .collectEntries { par -> + def parName = par.plainName + def val = data_[parName] + if (par.multiple && val instanceof Collection) { + val = val.join(par.multiple_sep) + } + if (par.direction == "output" && par.type == "file") { + val = val.replaceAll('\\$id', id).replaceAll('\\$key', key) + } + [parName, val] + } + + [ id ] + inputPaths + [ argsExclInputFiles, meta.resources_dir ] + } + | processObj + | map { output -> + def outputFiles = meta.config.allArguments + .findAll { it.type == "file" && it.direction == "output" } + .indexed() + .collectEntries{ index, par -> + def out = output[index + 1] + // strip dummy '.exitcode' file from output (see nextflow-io/nextflow#2678) + if (!out instanceof List || out.size() <= 1) { + if (par.multiple) { + out = [] + } else { + assert !par.required : + "Error in module '${key}' id '${output[0]}' argument '${par.plainName}'.\n" + + " Required output file is missing" + out = null + } + } else if (out.size() == 2 && !par.multiple) { + out = out[1] + } else { + out = out.drop(1) + } + [ par.plainName, out ] + } + + // drop null outputs + outputFiles.removeAll{it.value == null} + + [ output[0], outputFiles ] + } + emit: output_ + } + + return processWf +} + +// depends on: session? +def _vdsl3ProcessFactory(Map workflowArgs, Map meta, String rawScript) { + // autodetect process key + def wfKey = workflowArgs["key"] + def procKeyPrefix = "${wfKey}_process" + def scriptMeta = nextflow.script.ScriptMeta.current() + def existing = scriptMeta.getProcessNames().findAll{it.startsWith(procKeyPrefix)} + def numbers = existing.collect{it.replace(procKeyPrefix, "0").toInteger()} + def newNumber = (numbers + [-1]).max() + 1 + + def procKey = newNumber == 0 ? procKeyPrefix : "$procKeyPrefix$newNumber" + + if (newNumber > 0) { + log.warn "Key for module '${wfKey}' is duplicated.\n", + "If you run a component multiple times in the same workflow,\n" + + "it's recommended you set a unique key for every call,\n" + + "for example: ${wfKey}.run(key: \"foo\")." + } + + // subset directives and convert to list of tuples + def drctv = workflowArgs.directives + + // TODO: unit test the two commands below + // convert publish array into tags + def valueToStr = { val -> + // ignore closures + if (val instanceof CharSequence) { + if (!val.matches('^[{].*[}]$')) { + '"' + val + '"' + } else { + val + } + } else if (val instanceof List) { + "[" + val.collect{valueToStr(it)}.join(", ") + "]" + } else if (val instanceof Map) { + "[" + val.collect{k, v -> k + ": " + valueToStr(v)}.join(", ") + "]" + } else { + val.inspect() + } + } + + // multiple entries allowed: label, publishdir + def drctvStrs = drctv.collect { key, value -> + if (key in ["label", "publishDir"]) { + value.collect{ val -> + if (val instanceof Map) { + "\n$key " + val.collect{ k, v -> k + ": " + valueToStr(v) }.join(", ") + } else if (val == null) { + "" + } else { + "\n$key " + valueToStr(val) + } + }.join() + } else if (value instanceof Map) { + "\n$key " + value.collect{ k, v -> k + ": " + valueToStr(v) }.join(", ") + } else { + "\n$key " + valueToStr(value) + } + }.join() + + def inputPaths = meta.config.allArguments + .findAll { it.type == "file" && it.direction == "input" } + .collect { ', path(viash_par_' + it.plainName + ', stageAs: "_viash_par/' + it.plainName + '_?/*")' } + .join() + + def outputPaths = meta.config.allArguments + .findAll { it.type == "file" && it.direction == "output" } + .collect { par -> + // insert dummy into every output (see nextflow-io/nextflow#2678) + if (!par.multiple) { + ', path{[".exitcode", args.' + par.plainName + ']}' + } else { + ', path{[".exitcode"] + args.' + par.plainName + '}' + } + } + .join() + + // TODO: move this functionality somewhere else? + if (workflowArgs.auto.transcript) { + outputPaths = outputPaths + ', path{[".exitcode", ".command*"]}' + } else { + outputPaths = outputPaths + ', path{[".exitcode"]}' + } + + // create dirs for output files (based on BashWrapper.createParentFiles) + def createParentStr = meta.config.allArguments + .findAll { it.type == "file" && it.direction == "output" && it.create_parent } + .collect { par -> + "\${ args.containsKey(\"${par.plainName}\") ? \"mkdir_parent \\\"\" + (args[\"${par.plainName}\"] instanceof String ? args[\"${par.plainName}\"] : args[\"${par.plainName}\"].join('\" \"')) + \"\\\"\" : \"\" }" + } + .join("\n") + + // construct inputFileExports + def inputFileExports = meta.config.allArguments + .findAll { it.type == "file" && it.direction.toLowerCase() == "input" } + .collect { par -> + def viash_par_contents = "(viash_par_${par.plainName} instanceof List ? viash_par_${par.plainName}.join(\"${par.multiple_sep}\") : viash_par_${par.plainName})" + "\n\${viash_par_${par.plainName}.empty ? \"\" : \"export VIASH_PAR_${par.plainName.toUpperCase()}=\\\"\" + ${viash_par_contents} + \"\\\"\"}" + } + + // NOTE: if using docker, use /tmp instead of tmpDir! + def tmpDir = java.nio.file.Paths.get( + System.getenv('NXF_TEMP') ?: + System.getenv('VIASH_TEMP') ?: + System.getenv('VIASH_TMPDIR') ?: + System.getenv('VIASH_TEMPDIR') ?: + System.getenv('VIASH_TMP') ?: + System.getenv('TEMP') ?: + System.getenv('TMPDIR') ?: + System.getenv('TEMPDIR') ?: + System.getenv('TMP') ?: + '/tmp' + ).toAbsolutePath() + + // construct stub + def stub = meta.config.allArguments + .findAll { it.type == "file" && it.direction == "output" } + .collect { par -> + "\${ args.containsKey(\"${par.plainName}\") ? \"touch2 \\\"\" + (args[\"${par.plainName}\"] instanceof String ? args[\"${par.plainName}\"].replace(\"_*\", \"_0\") : args[\"${par.plainName}\"].join('\" \"')) + \"\\\"\" : \"\" }" + } + .join("\n") + + // escape script + def escapedScript = rawScript.replace('\\', '\\\\').replace('$', '\\$').replace('"""', '\\"\\"\\"') + + // publishdir assert + def assertStr = (workflowArgs.auto.publish == true) || workflowArgs.auto.transcript ? + """\nassert task.publishDir.size() > 0: "if auto.publish is true, params.publish_dir needs to be defined.\\n Example: --publish_dir './output/'" """ : + "" + + // generate process string + def procStr = + """nextflow.enable.dsl=2 + | + |process $procKey {$drctvStrs + |input: + | tuple val(id)$inputPaths, val(args), path(resourcesDir, stageAs: ".viash_meta_resources") + |output: + | tuple val("\$id")$outputPaths, optional: true + |stub: + |\"\"\" + |touch2() { mkdir -p "\\\$(dirname "\\\$1")" && touch "\\\$1" ; } + |$stub + |\"\"\" + |script:$assertStr + |def escapeText = { s -> s.toString().replaceAll('([`"])', '\\\\\\\\\$1') } + |def parInject = args + | .findAll{key, value -> value != null} + | .collect{key, value -> "export VIASH_PAR_\${key.toUpperCase()}=\\\"\${escapeText(value)}\\\""} + | .join("\\n") + |\"\"\" + |# meta exports + |export VIASH_META_RESOURCES_DIR="\${resourcesDir}" + |export VIASH_META_TEMP_DIR="${['docker', 'podman', 'charliecloud'].any{ it == workflow.containerEngine } ? '/tmp' : tmpDir}" + |export VIASH_META_NAME="${meta.config.name}" + |# export VIASH_META_EXECUTABLE="\\\$VIASH_META_RESOURCES_DIR/\\\$VIASH_META_NAME" + |export VIASH_META_CONFIG="\\\$VIASH_META_RESOURCES_DIR/.config.vsh.yaml" + |\${task.cpus ? "export VIASH_META_CPUS=\$task.cpus" : "" } + |\${task.memory?.bytes != null ? "export VIASH_META_MEMORY_B=\$task.memory.bytes" : "" } + |if [ ! -z \\\${VIASH_META_MEMORY_B+x} ]; then + | export VIASH_META_MEMORY_KB=\\\$(( (\\\$VIASH_META_MEMORY_B+999) / 1000 )) + | export VIASH_META_MEMORY_MB=\\\$(( (\\\$VIASH_META_MEMORY_KB+999) / 1000 )) + | export VIASH_META_MEMORY_GB=\\\$(( (\\\$VIASH_META_MEMORY_MB+999) / 1000 )) + | export VIASH_META_MEMORY_TB=\\\$(( (\\\$VIASH_META_MEMORY_GB+999) / 1000 )) + | export VIASH_META_MEMORY_PB=\\\$(( (\\\$VIASH_META_MEMORY_TB+999) / 1000 )) + | export VIASH_META_MEMORY_KIB=\\\$(( (\\\$VIASH_META_MEMORY_B+1023) / 1024 )) + | export VIASH_META_MEMORY_MIB=\\\$(( (\\\$VIASH_META_MEMORY_KIB+1023) / 1024 )) + | export VIASH_META_MEMORY_GIB=\\\$(( (\\\$VIASH_META_MEMORY_MIB+1023) / 1024 )) + | export VIASH_META_MEMORY_TIB=\\\$(( (\\\$VIASH_META_MEMORY_GIB+1023) / 1024 )) + | export VIASH_META_MEMORY_PIB=\\\$(( (\\\$VIASH_META_MEMORY_TIB+1023) / 1024 )) + |fi + | + |# meta synonyms + |export VIASH_TEMP="\\\$VIASH_META_TEMP_DIR" + |export TEMP_DIR="\\\$VIASH_META_TEMP_DIR" + | + |# create output dirs if need be + |function mkdir_parent { + | for file in "\\\$@"; do + | mkdir -p "\\\$(dirname "\\\$file")" + | done + |} + |$createParentStr + | + |# argument exports${inputFileExports.join()} + |\$parInject + | + |# process script + |${escapedScript} + |\"\"\" + |} + |""".stripMargin() + + // TODO: print on debug + // if (workflowArgs.debug == true) { + // println("######################\n$procStr\n######################") + // } + + // write process to temp file + def tempFile = java.nio.file.Files.createTempFile("viash-process-${procKey}-", ".nf") + addShutdownHook { java.nio.file.Files.deleteIfExists(tempFile) } + tempFile.text = procStr + + // create process from temp file + def binding = new nextflow.script.ScriptBinding([:]) + def session = nextflow.Nextflow.getSession() + def parser = new nextflow.script.ScriptParser(session) + .setModule(true) + .setBinding(binding) + def moduleScript = parser.runScript(tempFile) + .getScript() + + // register module in meta + def module = new nextflow.script.IncludeDef.Module(name: procKey) + scriptMeta.addModule(moduleScript, module.name, module.alias) + + // retrieve and return process from meta + return scriptMeta.getProcess(procKey) +} + +// defaults +meta["defaults"] = [ + // key to be used to trace the process and determine output names + key: null, + + // fixed arguments to be passed to script + args: [:], + + // default directives + directives: readJsonBlob('''{ + "container" : { + "registry" : "images.viash-hub.com", + "image" : "vsh/biobox/agat/agat_convert_sp_gxf2gxf", + "tag" : "main" + }, + "tag" : "$id" +}'''), + + // auto settings + auto: readJsonBlob('''{ + "simplifyInput" : true, + "simplifyOutput" : false, + "transcript" : false, + "publish" : false +}'''), + + // Apply a map over the incoming tuple + // Example: `{ tup -> [ tup[0], [input: tup[1].output] ] + tup.drop(2) }` + map: null, + + // Apply a map over the ID element of a tuple (i.e. the first element) + // Example: `{ id -> id + "_foo" }` + mapId: null, + + // Apply a map over the data element of a tuple (i.e. the second element) + // Example: `{ data -> [ input: data.output ] }` + mapData: null, + + // Apply a map over the passthrough elements of a tuple (i.e. the tuple excl. the first two elements) + // Example: `{ pt -> pt.drop(1) }` + mapPassthrough: null, + + // Filter the channel + // Example: `{ tup -> tup[0] == "foo" }` + filter: null, + + // Choose whether or not to run the component on the tuple if the condition is true. + // Otherwise, the tuple will be passed through. + // Example: `{ tup -> tup[0] != "skip_this" }` + runIf: null, + + // Rename keys in the data field of the tuple (i.e. the second element) + // Will likely be deprecated in favour of `fromState`. + // Example: `[ "new_key": "old_key" ]` + renameKeys: null, + + // Fetch data from the state and pass it to the module without altering the current state. + // + // `fromState` should be `null`, `List[String]`, `Map[String, String]` or a function. + // + // - If it is `null`, the state will be passed to the module as is. + // - If it is a `List[String]`, the data will be the values of the state at the given keys. + // - If it is a `Map[String, String]`, the data will be the values of the state at the given keys, with the keys renamed according to the map. + // - If it is a function, the tuple (`[id, state]`) in the channel will be passed to the function, and the result will be used as the data. + // + // Example: `{ id, state -> [input: state.fastq_file] }` + // Default: `null` + fromState: null, + + // Determine how the state should be updated after the module has been run. + // + // `toState` should be `null`, `List[String]`, `Map[String, String]` or a function. + // + // - If it is `null`, the state will be replaced with the output of the module. + // - If it is a `List[String]`, the state will be updated with the values of the data at the given keys. + // - If it is a `Map[String, String]`, the state will be updated with the values of the data at the given keys, with the keys renamed according to the map. + // - If it is a function, a tuple (`[id, output, state]`) will be passed to the function, and the result will be used as the new state. + // + // Example: `{ id, output, state -> state + [counts: state.output] }` + // Default: `{ id, output, state -> output }` + toState: null, + + // Whether or not to print debug messages + // Default: `false` + debug: false +] + +// initialise default workflow +meta["workflow"] = workflowFactory([key: meta.config.name], meta.defaults, meta) + +// add workflow to environment +nextflow.script.ScriptMeta.current().addDefinition(meta.workflow) + +// anonymous workflow for running this module as a standalone +workflow { + // add id argument if it's not already in the config + // TODO: deep copy + def newConfig = deepClone(meta.config) + def newParams = deepClone(params) + + def argsContainsId = newConfig.allArguments.any{it.plainName == "id"} + if (!argsContainsId) { + def idArg = [ + 'name': '--id', + 'required': false, + 'type': 'string', + 'description': 'A unique id for every entry.', + 'multiple': false + ] + newConfig.arguments.add(0, idArg) + newConfig = processConfig(newConfig) + } + if (!newParams.containsKey("id")) { + newParams.id = "run" + } + + helpMessage(newConfig) + + channelFromParams(newParams, newConfig) + // make sure id is not in the state if id is not in the args + | map {id, state -> + if (!argsContainsId) { + [id, state.findAll{k, v -> k != "id"}] + } else { + [id, state] + } + } + | meta.workflow.run( + auto: [ publish: "state" ] + ) +} + +// END COMPONENT-SPECIFIC CODE diff --git a/target/nextflow/agat/agat_convert_sp_gxf2gxf/nextflow.config b/target/nextflow/agat/agat_convert_sp_gxf2gxf/nextflow.config new file mode 100644 index 00000000..63cfe130 --- /dev/null +++ b/target/nextflow/agat/agat_convert_sp_gxf2gxf/nextflow.config @@ -0,0 +1,126 @@ +manifest { + name = 'agat/agat_convert_sp_gxf2gxf' + mainScript = 'main.nf' + nextflowVersion = '!>=20.12.1-edge' + version = 'main' + description = 'This script fixes and/or standardizes any GTF/GFF file into full sorted\nGTF/GFF file. It AGAT parser removes duplicate features, fixes\nduplicated IDs, adds missing ID and/or Parent attributes, deflates\nfactorized attributes (attributes with several parents are duplicated\nwith uniq ID), add missing features when possible (e.g. add exon if only\nCDS described, add UTR if CDS and exon described), fix feature locations\n(e.g. check exon is embedded in the parent features mRNA, gene), etc...\n\nAll AGAT\'s scripts with the _sp_ prefix use the AGAT parser, before to\nperform any supplementary task. So, it is not necessary to run this\nscript prior the use of any other _sp_ script.\n' + author = 'Leïla Paquay' +} + +process.container = 'nextflow/bash:latest' + +// detect tempdir +tempDir = java.nio.file.Paths.get( + System.getenv('NXF_TEMP') ?: + System.getenv('VIASH_TEMP') ?: + System.getenv('TEMPDIR') ?: + System.getenv('TMPDIR') ?: + '/tmp' +).toAbsolutePath() + +profiles { + no_publish { + process { + withName: '.*' { + publishDir = [ + enabled: false + ] + } + } + } + mount_temp { + docker.temp = tempDir + podman.temp = tempDir + charliecloud.temp = tempDir + } + docker { + docker.enabled = true + // docker.userEmulation = true + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false + } + singularity { + singularity.enabled = true + singularity.autoMounts = true + docker.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false + } + podman { + podman.enabled = true + docker.enabled = false + singularity.enabled = false + shifter.enabled = false + charliecloud.enabled = false + } + shifter { + shifter.enabled = true + docker.enabled = false + singularity.enabled = false + podman.enabled = false + charliecloud.enabled = false + } + charliecloud { + charliecloud.enabled = true + docker.enabled = false + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + } +} + +process{ + withLabel: mem1gb { memory = 1000000000.B } + withLabel: mem2gb { memory = 2000000000.B } + withLabel: mem5gb { memory = 5000000000.B } + withLabel: mem10gb { memory = 10000000000.B } + withLabel: mem20gb { memory = 20000000000.B } + withLabel: mem50gb { memory = 50000000000.B } + withLabel: mem100gb { memory = 100000000000.B } + withLabel: mem200gb { memory = 200000000000.B } + withLabel: mem500gb { memory = 500000000000.B } + withLabel: mem1tb { memory = 1000000000000.B } + withLabel: mem2tb { memory = 2000000000000.B } + withLabel: mem5tb { memory = 5000000000000.B } + withLabel: mem10tb { memory = 10000000000000.B } + withLabel: mem20tb { memory = 20000000000000.B } + withLabel: mem50tb { memory = 50000000000000.B } + withLabel: mem100tb { memory = 100000000000000.B } + withLabel: mem200tb { memory = 200000000000000.B } + withLabel: mem500tb { memory = 500000000000000.B } + withLabel: mem1gib { memory = 1073741824.B } + withLabel: mem2gib { memory = 2147483648.B } + withLabel: mem4gib { memory = 4294967296.B } + withLabel: mem8gib { memory = 8589934592.B } + withLabel: mem16gib { memory = 17179869184.B } + withLabel: mem32gib { memory = 34359738368.B } + withLabel: mem64gib { memory = 68719476736.B } + withLabel: mem128gib { memory = 137438953472.B } + withLabel: mem256gib { memory = 274877906944.B } + withLabel: mem512gib { memory = 549755813888.B } + withLabel: mem1tib { memory = 1099511627776.B } + withLabel: mem2tib { memory = 2199023255552.B } + withLabel: mem4tib { memory = 4398046511104.B } + withLabel: mem8tib { memory = 8796093022208.B } + withLabel: mem16tib { memory = 17592186044416.B } + withLabel: mem32tib { memory = 35184372088832.B } + withLabel: mem64tib { memory = 70368744177664.B } + withLabel: mem128tib { memory = 140737488355328.B } + withLabel: mem256tib { memory = 281474976710656.B } + withLabel: mem512tib { memory = 562949953421312.B } + withLabel: cpu1 { cpus = 1 } + withLabel: cpu2 { cpus = 2 } + withLabel: cpu5 { cpus = 5 } + withLabel: cpu10 { cpus = 10 } + withLabel: cpu20 { cpus = 20 } + withLabel: cpu50 { cpus = 50 } + withLabel: cpu100 { cpus = 100 } + withLabel: cpu200 { cpus = 200 } + withLabel: cpu500 { cpus = 500 } + withLabel: cpu1000 { cpus = 1000 } +} + + diff --git a/target/nextflow/agat/agat_convert_sp_gxf2gxf/nextflow_schema.json b/target/nextflow/agat/agat_convert_sp_gxf2gxf/nextflow_schema.json new file mode 100644 index 00000000..79b232fd --- /dev/null +++ b/target/nextflow/agat/agat_convert_sp_gxf2gxf/nextflow_schema.json @@ -0,0 +1,119 @@ +{ +"$schema": "http://json-schema.org/draft-07/schema", +"title": "agat_convert_sp_gxf2gxf", +"description": "This script fixes and/or standardizes any GTF/GFF file into full sorted\nGTF/GFF file. It AGAT parser removes duplicate features, fixes\nduplicated IDs, adds missing ID and/or Parent attributes, deflates\nfactorized attributes (attributes with several parents are duplicated\nwith uniq ID), add missing features when possible (e.g. add exon if only\nCDS described, add UTR if CDS and exon described), fix feature locations\n(e.g. check exon is embedded in the parent features mRNA, gene), etc...\n\nAll AGAT\u0027s scripts with the _sp_ prefix use the AGAT parser, before to\nperform any supplementary task. So, it is not necessary to run this\nscript prior the use of any other _sp_ script.\n", +"type": "object", +"definitions": { + + + + "inputs" : { + "title": "Inputs", + "type": "object", + "description": "No description", + "properties": { + + + "gxf": { + "type": + "string", + "description": "Type: `file`, required, example: `input.gff`. String - Input GTF/GFF file", + "help_text": "Type: `file`, required, example: `input.gff`. String - Input GTF/GFF file. Compressed file with .gz extension is accepted.\n" + + } + + +} +}, + + + "outputs" : { + "title": "Outputs", + "type": "object", + "description": "No description", + "properties": { + + + "output": { + "type": + "string", + "description": "Type: `file`, required, default: `$id.$key.output.gff`, example: `output.gff`. String - Output GFF file", + "help_text": "Type: `file`, required, default: `$id.$key.output.gff`, example: `output.gff`. String - Output GFF file. If no output file is specified, the output will be written to STDOUT.\n" + , + "default": "$id.$key.output.gff" + } + + +} +}, + + + "arguments" : { + "title": "Arguments", + "type": "object", + "description": "No description", + "properties": { + + + "config": { + "type": + "string", + "description": "Type: `file`, example: `custom_agat_config.yaml`. String - Input agat config file", + "help_text": "Type: `file`, example: `custom_agat_config.yaml`. String - Input agat config file. By default AGAT takes as input agat_config.yaml file from the working directory if any, otherwise it takes the original agat_config.yaml shipped with AGAT. To get the agat_config.yaml locally type: \"agat config --expose\". The --config option gives you the possibility to use your own AGAT config file (located elsewhere or named differently).\n" + + } + + +} +}, + + + "nextflow input-output arguments" : { + "title": "Nextflow input-output arguments", + "type": "object", + "description": "Input/output parameters for Nextflow itself. Please note that both publishDir and publish_dir are supported but at least one has to be configured.", + "properties": { + + + "publish_dir": { + "type": + "string", + "description": "Type: `string`, required, example: `output/`. Path to an output directory", + "help_text": "Type: `string`, required, example: `output/`. Path to an output directory." + + } + + + , + "param_list": { + "type": + "string", + "description": "Type: `string`, example: `my_params.yaml`. Allows inputting multiple parameter sets to initialise a Nextflow channel", + "help_text": "Type: `string`, example: `my_params.yaml`. Allows inputting multiple parameter sets to initialise a Nextflow channel. A `param_list` can either be a list of maps, a csv file, a json file, a yaml file, or simply a yaml blob.\n\n* A list of maps (as-is) where the keys of each map corresponds to the arguments of the pipeline. Example: in a `nextflow.config` file: `param_list: [ [\u0027id\u0027: \u0027foo\u0027, \u0027input\u0027: \u0027foo.txt\u0027], [\u0027id\u0027: \u0027bar\u0027, \u0027input\u0027: \u0027bar.txt\u0027] ]`.\n* A csv file should have column names which correspond to the different arguments of this pipeline. Example: `--param_list data.csv` with columns `id,input`.\n* A json or a yaml file should be a list of maps, each of which has keys corresponding to the arguments of the pipeline. Example: `--param_list data.json` with contents `[ {\u0027id\u0027: \u0027foo\u0027, \u0027input\u0027: \u0027foo.txt\u0027}, {\u0027id\u0027: \u0027bar\u0027, \u0027input\u0027: \u0027bar.txt\u0027} ]`.\n* A yaml blob can also be passed directly as a string. Example: `--param_list \"[ {\u0027id\u0027: \u0027foo\u0027, \u0027input\u0027: \u0027foo.txt\u0027}, {\u0027id\u0027: \u0027bar\u0027, \u0027input\u0027: \u0027bar.txt\u0027} ]\"`.\n\nWhen passing a csv, json or yaml file, relative path names are relativized to the location of the parameter file. No relativation is performed when `param_list` is a list of maps (as-is) or a yaml blob.", + "hidden": true + + } + + +} +} +}, +"allOf": [ + + { + "$ref": "#/definitions/inputs" + }, + + { + "$ref": "#/definitions/outputs" + }, + + { + "$ref": "#/definitions/arguments" + }, + + { + "$ref": "#/definitions/nextflow input-output arguments" + } +] +} diff --git a/target/nextflow/arriba/.config.vsh.yaml b/target/nextflow/arriba/.config.vsh.yaml index b1f7eb97..e146cbe2 100644 --- a/target/nextflow/arriba/.config.vsh.yaml +++ b/target/nextflow/arriba/.config.vsh.yaml @@ -706,7 +706,7 @@ build_info: output: "target/nextflow/arriba" executable: "target/nextflow/arriba/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/arriba/main.nf b/target/nextflow/arriba/main.nf index be7fcd27..42721c59 100644 --- a/target/nextflow/arriba/main.nf +++ b/target/nextflow/arriba/main.nf @@ -3566,7 +3566,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/arriba", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { diff --git a/target/nextflow/bcl_convert/.config.vsh.yaml b/target/nextflow/bcl_convert/.config.vsh.yaml index e65a6024..eccb7a87 100644 --- a/target/nextflow/bcl_convert/.config.vsh.yaml +++ b/target/nextflow/bcl_convert/.config.vsh.yaml @@ -418,7 +418,7 @@ build_info: output: "target/nextflow/bcl_convert" executable: "target/nextflow/bcl_convert/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/bcl_convert/main.nf b/target/nextflow/bcl_convert/main.nf index e9837c2d..2d2b9751 100644 --- a/target/nextflow/bcl_convert/main.nf +++ b/target/nextflow/bcl_convert/main.nf @@ -3303,7 +3303,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/bcl_convert", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { diff --git a/target/nextflow/bd_rhapsody/bd_rhapsody_make_reference/.config.vsh.yaml b/target/nextflow/bd_rhapsody/bd_rhapsody_make_reference/.config.vsh.yaml index f6d1cdd0..4bb348e2 100644 --- a/target/nextflow/bd_rhapsody/bd_rhapsody_make_reference/.config.vsh.yaml +++ b/target/nextflow/bd_rhapsody/bd_rhapsody_make_reference/.config.vsh.yaml @@ -270,7 +270,7 @@ build_info: output: "target/nextflow/bd_rhapsody/bd_rhapsody_make_reference" executable: "target/nextflow/bd_rhapsody/bd_rhapsody_make_reference/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/bd_rhapsody/bd_rhapsody_make_reference/main.nf b/target/nextflow/bd_rhapsody/bd_rhapsody_make_reference/main.nf index 1d10579c..e8dedd5e 100644 --- a/target/nextflow/bd_rhapsody/bd_rhapsody_make_reference/main.nf +++ b/target/nextflow/bd_rhapsody/bd_rhapsody_make_reference/main.nf @@ -3116,7 +3116,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/bd_rhapsody/bd_rhapsody_make_reference", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { diff --git a/target/nextflow/bedtools/bedtools_bamtofastq/.config.vsh.yaml b/target/nextflow/bedtools/bedtools_bamtofastq/.config.vsh.yaml new file mode 100644 index 00000000..1285e8dd --- /dev/null +++ b/target/nextflow/bedtools/bedtools_bamtofastq/.config.vsh.yaml @@ -0,0 +1,213 @@ +name: "bedtools_bamtofastq" +namespace: "bedtools" +version: "main" +authors: +- name: "Theodoro Gasperin Terra Camargo" + roles: + - "author" + - "maintainer" + info: + links: + email: "theodorogtc@gmail.com" + github: "tgaspe" + linkedin: "theodoro-gasperin-terra-camargo" + organizations: + - name: "Data Intuitive" + href: "https://www.data-intuitive.com" + role: "Bioinformatician" +argument_groups: +- name: "Inputs" + arguments: + - type: "file" + name: "--input" + alternatives: + - "-i" + description: "Input BAM file to be converted to FASTQ." + info: null + must_exist: true + create_parent: true + required: true + direction: "input" + multiple: false + multiple_sep: ";" +- name: "Outputs" + arguments: + - type: "file" + name: "--fastq" + alternatives: + - "-fq" + description: "Output FASTQ file." + info: null + must_exist: true + create_parent: true + required: true + direction: "output" + multiple: false + multiple_sep: ";" + - type: "file" + name: "--fastq2" + alternatives: + - "-fq2" + description: "FASTQ for second end. Used if BAM contains paired-end data.\nBAM\ + \ should be sorted by query name is creating paired FASTQ.\n" + info: null + must_exist: true + create_parent: true + required: false + direction: "output" + multiple: false + multiple_sep: ";" +- name: "Options" + arguments: + - type: "boolean_true" + name: "--tags" + description: "Create FASTQ based on the mate info in the BAM R2 and Q2 tags.\n" + info: null + direction: "input" +resources: +- type: "bash_script" + path: "script.sh" + is_executable: true +description: "Conversion tool for extracting FASTQ records from sequence alignments\ + \ in BAM format.\n" +test_resources: +- type: "bash_script" + path: "test.sh" + is_executable: true +- type: "file" + path: "test_data" +info: null +status: "enabled" +requirements: + commands: + - "ps" +keywords: +- "Conversion" +- "BAM" +- "FASTQ" +license: "MIT" +references: + doi: + - "10.1093/bioinformatics/btq033" +links: + repository: "https://github.com/arq5x/bedtools2" + homepage: "https://bedtools.readthedocs.io/en/latest/#" + documentation: "https://bedtools.readthedocs.io/en/latest/content/tools/bamtofastq.html" + issue_tracker: "https://github.com/arq5x/bedtools2/issues" +runners: +- type: "executable" + id: "executable" + docker_setup_strategy: "ifneedbepullelsecachedbuild" +- type: "nextflow" + id: "nextflow" + directives: + tag: "$id" + auto: + simplifyInput: true + simplifyOutput: false + transcript: false + publish: false + config: + labels: + mem1gb: "memory = 1000000000.B" + mem2gb: "memory = 2000000000.B" + mem5gb: "memory = 5000000000.B" + mem10gb: "memory = 10000000000.B" + mem20gb: "memory = 20000000000.B" + mem50gb: "memory = 50000000000.B" + mem100gb: "memory = 100000000000.B" + mem200gb: "memory = 200000000000.B" + mem500gb: "memory = 500000000000.B" + mem1tb: "memory = 1000000000000.B" + mem2tb: "memory = 2000000000000.B" + mem5tb: "memory = 5000000000000.B" + mem10tb: "memory = 10000000000000.B" + mem20tb: "memory = 20000000000000.B" + mem50tb: "memory = 50000000000000.B" + mem100tb: "memory = 100000000000000.B" + mem200tb: "memory = 200000000000000.B" + mem500tb: "memory = 500000000000000.B" + mem1gib: "memory = 1073741824.B" + mem2gib: "memory = 2147483648.B" + mem4gib: "memory = 4294967296.B" + mem8gib: "memory = 8589934592.B" + mem16gib: "memory = 17179869184.B" + mem32gib: "memory = 34359738368.B" + mem64gib: "memory = 68719476736.B" + mem128gib: "memory = 137438953472.B" + mem256gib: "memory = 274877906944.B" + mem512gib: "memory = 549755813888.B" + mem1tib: "memory = 1099511627776.B" + mem2tib: "memory = 2199023255552.B" + mem4tib: "memory = 4398046511104.B" + mem8tib: "memory = 8796093022208.B" + mem16tib: "memory = 17592186044416.B" + mem32tib: "memory = 35184372088832.B" + mem64tib: "memory = 70368744177664.B" + mem128tib: "memory = 140737488355328.B" + mem256tib: "memory = 281474976710656.B" + mem512tib: "memory = 562949953421312.B" + cpu1: "cpus = 1" + cpu2: "cpus = 2" + cpu5: "cpus = 5" + cpu10: "cpus = 10" + cpu20: "cpus = 20" + cpu50: "cpus = 50" + cpu100: "cpus = 100" + cpu200: "cpus = 200" + cpu500: "cpus = 500" + cpu1000: "cpus = 1000" + debug: false + container: "docker" +engines: +- type: "docker" + id: "docker" + image: "debian:stable-slim" + target_registry: "images.viash-hub.com" + target_tag: "main" + namespace_separator: "/" + setup: + - type: "apt" + packages: + - "bedtools" + - "procps" + interactive: false + - type: "docker" + run: + - "echo \"bedtools: \\\"$(bedtools --version | sed -n 's/^bedtools //p')\\\"\"\ + \ > /var/software_versions.txt\n" + entrypoint: [] + cmd: null +- type: "native" + id: "native" +build_info: + config: "src/bedtools/bedtools_bamtofastq/config.vsh.yaml" + runner: "nextflow" + engine: "docker|native" + output: "target/nextflow/bedtools/bedtools_bamtofastq" + executable: "target/nextflow/bedtools/bedtools_bamtofastq/main.nf" + viash_version: "0.9.0-RC6" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" + git_remote: "https://github.com/viash-hub/biobox" +package_config: + name: "biobox" + version: "main" + description: "A collection of bioinformatics tools for working with sequence data.\n" + info: null + viash_version: "0.9.0-RC6" + source: "src" + target: "target" + config_mods: + - ".requirements.commands := ['ps']\n" + - ".engines += { type: \"native\" }" + - ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'" + - ".engines[.type == 'docker'].target_tag := 'main'" + keywords: + - "bioinformatics" + - "modules" + - "sequencing" + license: "MIT" + organization: "vsh" + links: + repository: "https://github.com/viash-hub/biobox" + issue_tracker: "https://github.com/viash-hub/biobox/issues" diff --git a/target/nextflow/bedtools/bedtools_bamtofastq/main.nf b/target/nextflow/bedtools/bedtools_bamtofastq/main.nf new file mode 100644 index 00000000..ef29b827 --- /dev/null +++ b/target/nextflow/bedtools/bedtools_bamtofastq/main.nf @@ -0,0 +1,3584 @@ +// bedtools_bamtofastq main +// +// This wrapper script is auto-generated by viash 0.9.0-RC6 and is thus a +// derivative work thereof. This software comes with ABSOLUTELY NO WARRANTY from +// Data Intuitive. +// +// The component may contain files which fall under a different license. The +// authors of this component should specify the license in the header of such +// files, or include a separate license file detailing the licenses of all included +// files. +// +// Component authors: +// * Theodoro Gasperin Terra Camargo (author, maintainer) + +//////////////////////////// +// VDSL3 helper functions // +//////////////////////////// + +// helper file: 'src/main/resources/io/viash/runners/nextflow/arguments/_checkArgumentType.nf' +class UnexpectedArgumentTypeException extends Exception { + String errorIdentifier + String stage + String plainName + String expectedClass + String foundClass + + // ${key ? " in module '$key'" : ""}${id ? " id '$id'" : ""} + UnexpectedArgumentTypeException(String errorIdentifier, String stage, String plainName, String expectedClass, String foundClass) { + super("Error${errorIdentifier ? " $errorIdentifier" : ""}:${stage ? " $stage" : "" } argument '${plainName}' has the wrong type. " + + "Expected type: ${expectedClass}. Found type: ${foundClass}") + this.errorIdentifier = errorIdentifier + this.stage = stage + this.plainName = plainName + this.expectedClass = expectedClass + this.foundClass = foundClass + } +} + +/** + * Checks if the given value is of the expected type. If not, an exception is thrown. + * + * @param stage The stage of the argument (input or output) + * @param par The parameter definition + * @param value The value to check + * @param errorIdentifier The identifier to use in the error message + * @return The value, if it is of the expected type + * @throws UnexpectedArgumentTypeException If the value is not of the expected type +*/ +def _checkArgumentType(String stage, Map par, Object value, String errorIdentifier) { + // expectedClass will only be != null if value is not of the expected type + def expectedClass = null + def foundClass = null + + // todo: split if need be + + if (!par.required && value == null) { + expectedClass = null + } else if (par.multiple) { + if (value !instanceof Collection) { + value = [value] + } + + // split strings + value = value.collectMany{ val -> + if (val instanceof String) { + // collect() to ensure that the result is a List and not simply an array + val.split(par.multiple_sep).collect() + } else { + [val] + } + } + + // process globs + if (par.type == "file" && par.direction == "input") { + value = value.collect{ it instanceof String ? file(it, hidden: true) : it }.flatten() + } + + // check types of elements in list + try { + value = value.collect { listVal -> + _checkArgumentType(stage, par + [multiple: false], listVal, errorIdentifier) + } + } catch (UnexpectedArgumentTypeException e) { + expectedClass = "List[${e.expectedClass}]" + foundClass = "List[${e.foundClass}]" + } + } else if (par.type == "string") { + // cast to string if need be + if (value instanceof GString) { + value = value.toString() + } + expectedClass = value instanceof String ? null : "String" + } else if (par.type == "integer") { + // cast to integer if need be + if (value instanceof String) { + try { + value = value.toInteger() + } catch (NumberFormatException e) { + // do nothing + } + } + if (value instanceof java.math.BigInteger) { + value = value.intValue() + } + expectedClass = value instanceof Integer ? null : "Integer" + } else if (par.type == "long") { + // cast to long if need be + if (value instanceof String) { + try { + value = value.toLong() + } catch (NumberFormatException e) { + // do nothing + } + } + if (value instanceof Integer) { + value = value.toLong() + } + expectedClass = value instanceof Long ? null : "Long" + } else if (par.type == "double") { + // cast to double if need be + if (value instanceof String) { + try { + value = value.toDouble() + } catch (NumberFormatException e) { + // do nothing + } + } + if (value instanceof java.math.BigDecimal) { + value = value.doubleValue() + } + if (value instanceof Float) { + value = value.toDouble() + } + expectedClass = value instanceof Double ? null : "Double" + } else if (par.type == "boolean" | par.type == "boolean_true" | par.type == "boolean_false") { + // cast to boolean if need be + if (value instanceof String) { + def valueLower = value.toLowerCase() + if (valueLower == "true") { + value = true + } else if (valueLower == "false") { + value = false + } + } + expectedClass = value instanceof Boolean ? null : "Boolean" + } else if (par.type == "file" && (par.direction == "input" || stage == "output")) { + // cast to path if need be + if (value instanceof String) { + value = file(value, hidden: true) + } + if (value instanceof File) { + value = value.toPath() + } + expectedClass = value instanceof Path ? null : "Path" + } else if (par.type == "file" && stage == "input" && par.direction == "output") { + // cast to string if need be + if (value instanceof GString) { + value = value.toString() + } + expectedClass = value instanceof String ? null : "String" + } else { + // didn't find a match for par.type + expectedClass = par.type + } + + if (expectedClass != null) { + if (foundClass == null) { + foundClass = value.getClass().getName() + } + throw new UnexpectedArgumentTypeException(errorIdentifier, stage, par.plainName, expectedClass, foundClass) + } + + return value +} +// helper file: 'src/main/resources/io/viash/runners/nextflow/arguments/_processInputValues.nf' +Map _processInputValues(Map inputs, Map config, String id, String key) { + if (!workflow.stubRun) { + config.allArguments.each { arg -> + if (arg.required) { + assert inputs.containsKey(arg.plainName) && inputs.get(arg.plainName) != null : + "Error in module '${key}' id '${id}': required input argument '${arg.plainName}' is missing" + } + } + + inputs = inputs.collectEntries { name, value -> + def par = config.allArguments.find { it.plainName == name && (it.direction == "input" || it.type == "file") } + assert par != null : "Error in module '${key}' id '${id}': '${name}' is not a valid input argument" + + value = _checkArgumentType("input", par, value, "in module '$key' id '$id'") + + [ name, value ] + } + } + return inputs +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/arguments/_processOutputValues.nf' +Map _processOutputValues(Map outputs, Map config, String id, String key) { + if (!workflow.stubRun) { + config.allArguments.each { arg -> + if (arg.direction == "output" && arg.required) { + assert outputs.containsKey(arg.plainName) && outputs.get(arg.plainName) != null : + "Error in module '${key}' id '${id}': required output argument '${arg.plainName}' is missing" + } + } + + outputs = outputs.collectEntries { name, value -> + def par = config.allArguments.find { it.plainName == name && it.direction == "output" } + assert par != null : "Error in module '${key}' id '${id}': '${name}' is not a valid output argument" + + value = _checkArgumentType("output", par, value, "in module '$key' id '$id'") + + [ name, value ] + } + } + return outputs +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/IDChecker.nf' +class IDChecker { + final def items = [] as Set + + @groovy.transform.WithWriteLock + boolean observe(String item) { + if (items.contains(item)) { + return false + } else { + items << item + return true + } + } + + @groovy.transform.WithReadLock + boolean contains(String item) { + return items.contains(item) + } + + @groovy.transform.WithReadLock + Set getItems() { + return items.clone() + } +} +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/_checkUniqueIds.nf' + +/** + * Check if the ids are unique across parameter sets + * + * @param parameterSets a list of parameter sets. + */ +private void _checkUniqueIds(List>> parameterSets) { + def ppIds = parameterSets.collect{it[0]} + assert ppIds.size() == ppIds.unique().size() : "All argument sets should have unique ids. Detected ids: $ppIds" +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/_getChild.nf' + +// helper functions for reading params from file // +def _getChild(parent, child) { + if (child.contains("://") || java.nio.file.Paths.get(child).isAbsolute()) { + child + } else { + def parentAbsolute = java.nio.file.Paths.get(parent).toAbsolutePath().toString() + parentAbsolute.replaceAll('/[^/]*$', "/") + child + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/_parseParamList.nf' +/** + * Figure out the param list format based on the file extension + * + * @param param_list A String containing the path to the parameter list file. + * + * @return A String containing the format of the parameter list file. + */ +def _paramListGuessFormat(param_list) { + if (param_list !instanceof String) { + "asis" + } else if (param_list.endsWith(".csv")) { + "csv" + } else if (param_list.endsWith(".json") || param_list.endsWith(".jsn")) { + "json" + } else if (param_list.endsWith(".yaml") || param_list.endsWith(".yml")) { + "yaml" + } else { + "yaml_blob" + } +} + + +/** + * Read the param list + * + * @param param_list One of the following: + * - A String containing the path to the parameter list file (csv, json or yaml), + * - A yaml blob of a list of maps (yaml_blob), + * - Or a groovy list of maps (asis). + * @param config A Map of the Viash configuration. + * + * @return A List of Maps containing the parameters. + */ +def _parseParamList(param_list, Map config) { + // first determine format by extension + def paramListFormat = _paramListGuessFormat(param_list) + + def paramListPath = (paramListFormat != "asis" && paramListFormat != "yaml_blob") ? + file(param_list, hidden: true) : + null + + // get the correct parser function for the detected params_list format + def paramSets = [] + if (paramListFormat == "asis") { + paramSets = param_list + } else if (paramListFormat == "yaml_blob") { + paramSets = readYamlBlob(param_list) + } else if (paramListFormat == "yaml") { + paramSets = readYaml(paramListPath) + } else if (paramListFormat == "json") { + paramSets = readJson(paramListPath) + } else if (paramListFormat == "csv") { + paramSets = readCsv(paramListPath) + } else { + error "Format of provided --param_list not recognised.\n" + + "Found: '$paramListFormat'.\n" + + "Expected: a csv file, a json file, a yaml file,\n" + + "a yaml blob or a groovy list of maps." + } + + // data checks + assert paramSets instanceof List: "--param_list should contain a list of maps" + for (value in paramSets) { + assert value instanceof Map: "--param_list should contain a list of maps" + } + + // id is argument + def idIsArgument = config.allArguments.any{it.plainName == "id"} + + // Reformat from List to List> by adding the ID as first element of a Tuple2 + paramSets = paramSets.collect({ data -> + def id = data.id + if (!idIsArgument) { + data = data.findAll{k, v -> k != "id"} + } + [id, data] + }) + + // Split parameters with 'multiple: true' + paramSets = paramSets.collect({ id, data -> + data = _splitParams(data, config) + [id, data] + }) + + // The paths of input files inside a param_list file may have been specified relatively to the + // location of the param_list file. These paths must be made absolute. + if (paramListPath) { + paramSets = paramSets.collect({ id, data -> + def new_data = data.collectEntries{ parName, parValue -> + def par = config.allArguments.find{it.plainName == parName} + if (par && par.type == "file" && par.direction == "input") { + if (parValue instanceof Collection) { + parValue = parValue.collectMany{path -> + def x = _resolveSiblingIfNotAbsolute(path, paramListPath) + x instanceof Collection ? x : [x] + } + } else { + parValue = _resolveSiblingIfNotAbsolute(parValue, paramListPath) + } + } + [parName, parValue] + } + [id, new_data] + }) + } + + return paramSets +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/_splitParams.nf' +/** + * Split parameters for arguments that accept multiple values using their separator + * + * @param paramList A Map containing parameters to split. + * @param config A Map of the Viash configuration. This Map can be generated from the config file + * using the readConfig() function. + * + * @return A Map of parameters where the parameter values have been split into a list using + * their seperator. + */ +Map _splitParams(Map parValues, Map config){ + def parsedParamValues = parValues.collectEntries { parName, parValue -> + def parameterSettings = config.allArguments.find({it.plainName == parName}) + + if (!parameterSettings) { + // if argument is not found, do not alter + return [parName, parValue] + } + if (parameterSettings.multiple) { // Check if parameter can accept multiple values + if (parValue instanceof Collection) { + parValue = parValue.collect{it instanceof String ? it.split(parameterSettings.multiple_sep) : it } + } else if (parValue instanceof String) { + parValue = parValue.split(parameterSettings.multiple_sep) + } else if (parValue == null) { + parValue = [] + } else { + parValue = [ parValue ] + } + parValue = parValue.flatten() + } + // For all parameters check if multiple values are only passed for + // arguments that allow it. Quietly simplify lists of length 1. + if (!parameterSettings.multiple && parValue instanceof Collection) { + assert parValue.size() == 1 : + "Error: argument ${parName} has too many values.\n" + + " Expected amount: 1. Found: ${parValue.size()}" + parValue = parValue[0] + } + [parName, parValue] + } + return parsedParamValues +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/channelFromParams.nf' +/** + * Parse nextflow parameters based on settings defined in a viash config. + * Return a list of parameter sets, each parameter set corresponding to + * an event in a nextflow channel. The output from this function can be used + * with Channel.fromList to create a nextflow channel with Vdsl3 formatted + * events. + * + * This function performs: + * - A filtering of the params which can be found in the config file. + * - Process the params_list argument which allows a user to to initialise + * a Vsdl3 channel with multiple parameter sets. Possible formats are + * csv, json, yaml, or simply a yaml_blob. A csv should have column names + * which correspond to the different arguments of this pipeline. A json or a yaml + * file should be a list of maps, each of which has keys corresponding to the + * arguments of the pipeline. A yaml blob can also be passed directly as a parameter. + * When passing a csv, json or yaml, relative path names are relativized to the + * location of the parameter file. + * - Combine the parameter sets into a vdsl3 Channel. + * + * @param params Input parameters. Can optionaly contain a 'param_list' key that + * provides a list of arguments that can be split up into multiple events + * in the output channel possible formats of param_lists are: a csv file, + * json file, a yaml file or a yaml blob. Each parameters set (event) must + * have a unique ID. + * @param config A Map of the Viash configuration. This Map can be generated from the config file + * using the readConfig() function. + * + * @return A list of parameters with the first element of the event being + * the event ID and the second element containing a map of the parsed parameters. + */ + +private List>> _paramsToParamSets(Map params, Map config){ + // todo: fetch key from run args + def key_ = config.name + + /* parse regular parameters (not in param_list) */ + /*************************************************/ + def globalParams = config.allArguments + .findAll { params.containsKey(it.plainName) } + .collectEntries { [ it.plainName, params[it.plainName] ] } + def globalID = params.get("id", null) + + /* process params_list arguments */ + /*********************************/ + def paramList = params.containsKey("param_list") && params.param_list != null ? + params.param_list : [] + // if (paramList instanceof String) { + // paramList = [paramList] + // } + // def paramSets = paramList.collectMany{ _parseParamList(it, config) } + // TODO: be able to process param_list when it is a list of strings + def paramSets = _parseParamList(paramList, config) + if (paramSets.isEmpty()) { + paramSets = [[null, [:]]] + } + + /* combine arguments into channel */ + /**********************************/ + def processedParams = paramSets.indexed().collect{ index, tup -> + // Process ID + def id = tup[0] ?: globalID + + if (workflow.stubRun && !id) { + // if stub run, explicitly add an id if missing + id = "stub${index}" + } + assert id != null: "Each parameter set should have at least an 'id'" + + // Process params + def parValues = globalParams + tup[1] + // // Remove parameters which are null, if the default is also null + // parValues = parValues.collectEntries{paramName, paramValue -> + // parameterSettings = config.functionality.allArguments.find({it.plainName == paramName}) + // if ( paramValue != null || parameterSettings.get("default", null) != null ) { + // [paramName, paramValue] + // } + // } + parValues = parValues.collectEntries { name, value -> + def par = config.allArguments.find { it.plainName == name && (it.direction == "input" || it.type == "file") } + assert par != null : "Error in module '${key_}' id '${id}': '${name}' is not a valid input argument" + + if (par == null) { + return [:] + } + value = _checkArgumentType("input", par, value, "in module '$key_' id '$id'") + + [ name, value ] + } + + [id, parValues] + } + + // Check if ids (first element of each list) is unique + _checkUniqueIds(processedParams) + return processedParams +} + +/** + * Parse nextflow parameters based on settings defined in a viash config + * and return a nextflow channel. + * + * @param params Input parameters. Can optionaly contain a 'param_list' key that + * provides a list of arguments that can be split up into multiple events + * in the output channel possible formats of param_lists are: a csv file, + * json file, a yaml file or a yaml blob. Each parameters set (event) must + * have a unique ID. + * @param config A Map of the Viash configuration. This Map can be generated from the config file + * using the readConfig() function. + * + * @return A nextflow Channel with events. Events are formatted as a tuple that contains + * first contains the ID of the event and as second element holds a parameter map. + * + * + */ +def channelFromParams(Map params, Map config) { + def processedParams = _paramsToParamSets(params, config) + return Channel.fromList(processedParams) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/checkUniqueIds.nf' +def checkUniqueIds(Map args) { + def stopOnError = args.stopOnError == null ? args.stopOnError : true + + def idChecker = new IDChecker() + + return filter { tup -> + if (!idChecker.observe(tup[0])) { + if (stopOnError) { + error "Duplicate id: ${tup[0]}" + } else { + log.warn "Duplicate id: ${tup[0]}, removing duplicate entry" + return false + } + } + return true + } +} +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/preprocessInputs.nf' +// This helper file will be deprecated soon +preprocessInputsDeprecationWarningPrinted = false + +def preprocessInputsDeprecationWarning() { + if (!preprocessInputsDeprecationWarningPrinted) { + preprocessInputsDeprecationWarningPrinted = true + System.err.println("Warning: preprocessInputs() is deprecated and will be removed in Viash 0.9.0.") + } +} + +/** + * Generate a nextflow Workflow that allows processing a channel of + * Vdsl3 formatted events and apply a Viash config to them: + * - Gather default parameters from the Viash config and make + * sure that they are correctly formatted (see applyConfig method). + * - Format the input parameters (also using the applyConfig method). + * - Apply the default parameter to the input parameters. + * - Do some assertions: + * ~ Check if the event IDs in the channel are unique. + * + * The events in the channel are formatted as tuples, with the + * first element of the tuples being a unique id of the parameter set, + * and the second element containg the the parameters themselves. + * Optional extra elements of the tuples will be passed to the output as is. + * + * @param args A map that must contain a 'config' key that points + * to a parsed config (see readConfig()). Optionally, a + * 'key' key can be provided which can be used to create a unique + * name for the workflow process. + * + * @return A workflow that allows processing a channel of Vdsl3 formatted events + * and apply a Viash config to them. + */ +def preprocessInputs(Map args) { + preprocessInputsDeprecationWarning() + + def config = args.config + assert config instanceof Map : + "Error in preprocessInputs: config must be a map. " + + "Expected class: Map. Found: config.getClass() is ${config.getClass()}" + def key_ = args.key ?: config.name + + // Get different parameter types (used throughout this function) + def defaultArgs = config.allArguments + .findAll { it.containsKey("default") } + .collectEntries { [ it.plainName, it.default ] } + + map { tup -> + def id = tup[0] + def data = tup[1] + def passthrough = tup.drop(2) + + def new_data = (defaultArgs + data).collectEntries { name, value -> + def par = config.allArguments.find { it.plainName == name && (it.direction == "input" || it.type == "file") } + + if (par != null) { + value = _checkArgumentType("input", par, value, "in module '$key_' id '$id'") + } + + [ name, value ] + } + + [ id, new_data ] + passthrough + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/runComponents.nf' +/** + * Run a list of components on a stream of data. + * + * @param components: list of Viash VDSL3 modules to run + * @param fromState: a closure, a map or a list of keys to extract from the input data. + * If a closure, it will be called with the id, the data and the component config. + * @param toState: a closure, a map or a list of keys to extract from the output data + * If a closure, it will be called with the id, the output data, the old state and the component config. + * @param filter: filter function to apply to the input. + * It will be called with the id, the data and the component config. + * @param id: id to use for the output data + * If a closure, it will be called with the id, the data and the component config. + * @param auto: auto options to pass to the components + * + * @return: a workflow that runs the components + **/ +def runComponents(Map args) { + log.warn("runComponents is deprecated, use runEach instead") + assert args.components: "runComponents should be passed a list of components to run" + + def components_ = args.components + if (components_ !instanceof List) { + components_ = [ components_ ] + } + assert components_.size() > 0: "pass at least one component to runComponents" + + def fromState_ = args.fromState + def toState_ = args.toState + def filter_ = args.filter + def id_ = args.id + + workflow runComponentsWf { + take: input_ch + main: + + // generate one channel per method + out_chs = components_.collect{ comp_ -> + def comp_config = comp_.config + + def filter_ch = filter_ + ? input_ch | filter{tup -> + filter_(tup[0], tup[1], comp_config) + } + : input_ch + def id_ch = id_ + ? filter_ch | map{tup -> + // def new_id = id_(tup[0], tup[1], comp_config) + def new_id = tup[0] + if (id_ instanceof String) { + new_id = id_ + } else if (id_ instanceof Closure) { + new_id = id_(new_id, tup[1], comp_config) + } + [new_id] + tup.drop(1) + } + : filter_ch + def data_ch = id_ch | map{tup -> + def new_data = tup[1] + if (fromState_ instanceof Map) { + new_data = fromState_.collectEntries{ key0, key1 -> + [key0, new_data[key1]] + } + } else if (fromState_ instanceof List) { + new_data = fromState_.collectEntries{ key -> + [key, new_data[key]] + } + } else if (fromState_ instanceof Closure) { + new_data = fromState_(tup[0], new_data, comp_config) + } + tup.take(1) + [new_data] + tup.drop(1) + } + def out_ch = data_ch + | comp_.run( + auto: (args.auto ?: [:]) + [simplifyInput: false, simplifyOutput: false] + ) + def post_ch = toState_ + ? out_ch | map{tup -> + def output = tup[1] + def old_state = tup[2] + def new_state = null + if (toState_ instanceof Map) { + new_state = old_state + toState_.collectEntries{ key0, key1 -> + [key0, output[key1]] + } + } else if (toState_ instanceof List) { + new_state = old_state + toState_.collectEntries{ key -> + [key, output[key]] + } + } else if (toState_ instanceof Closure) { + new_state = toState_(tup[0], output, old_state, comp_config) + } + [tup[0], new_state] + tup.drop(3) + } + : out_ch + + post_ch + } + + // mix all results + output_ch = + (out_chs.size == 1) + ? out_chs[0] + : out_chs[0].mix(*out_chs.drop(1)) + + emit: output_ch + } + + return runComponentsWf +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/runEach.nf' +/** + * Run a list of components on a stream of data. + * + * @param components: list of Viash VDSL3 modules to run + * @param fromState: a closure, a map or a list of keys to extract from the input data. + * If a closure, it will be called with the id, the data and the component itself. + * @param toState: a closure, a map or a list of keys to extract from the output data + * If a closure, it will be called with the id, the output data, the old state and the component itself. + * @param filter: filter function to apply to the input. + * It will be called with the id, the data and the component itself. + * @param id: id to use for the output data + * If a closure, it will be called with the id, the data and the component itself. + * @param auto: auto options to pass to the components + * + * @return: a workflow that runs the components + **/ +def runEach(Map args) { + assert args.components: "runEach should be passed a list of components to run" + + def components_ = args.components + if (components_ !instanceof List) { + components_ = [ components_ ] + } + assert components_.size() > 0: "pass at least one component to runEach" + + def fromState_ = args.fromState + def toState_ = args.toState + def filter_ = args.filter + def id_ = args.id + + workflow runEachWf { + take: input_ch + main: + + // generate one channel per method + out_chs = components_.collect{ comp_ -> + def filter_ch = filter_ + ? input_ch | filter{tup -> + filter_(tup[0], tup[1], comp_) + } + : input_ch + def id_ch = id_ + ? filter_ch | map{tup -> + def new_id = id_ + if (new_id instanceof Closure) { + new_id = new_id(tup[0], tup[1], comp_) + } + assert new_id instanceof String : "Error in runEach: id should be a String or a Closure that returns a String. Expected: id instanceof String. Found: ${new_id.getClass()}" + [new_id] + tup.drop(1) + } + : filter_ch + def data_ch = id_ch | map{tup -> + def new_data = tup[1] + if (fromState_ instanceof Map) { + new_data = fromState_.collectEntries{ key0, key1 -> + [key0, new_data[key1]] + } + } else if (fromState_ instanceof List) { + new_data = fromState_.collectEntries{ key -> + [key, new_data[key]] + } + } else if (fromState_ instanceof Closure) { + new_data = fromState_(tup[0], new_data, comp_) + } + tup.take(1) + [new_data] + tup.drop(1) + } + def out_ch = data_ch + | comp_.run( + auto: (args.auto ?: [:]) + [simplifyInput: false, simplifyOutput: false] + ) + def post_ch = toState_ + ? out_ch | map{tup -> + def output = tup[1] + def old_state = tup[2] + def new_state = null + if (toState_ instanceof Map) { + new_state = old_state + toState_.collectEntries{ key0, key1 -> + [key0, output[key1]] + } + } else if (toState_ instanceof List) { + new_state = old_state + toState_.collectEntries{ key -> + [key, output[key]] + } + } else if (toState_ instanceof Closure) { + new_state = toState_(tup[0], output, old_state, comp_) + } + [tup[0], new_state] + tup.drop(3) + } + : out_ch + + post_ch + } + + // mix all results + output_ch = + (out_chs.size == 1) + ? out_chs[0] + : out_chs[0].mix(*out_chs.drop(1)) + + emit: output_ch + } + + return runEachWf +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/safeJoin.nf' +/** + * Join sourceChannel to targetChannel + * + * This function joins the sourceChannel to the targetChannel. + * However, each id in the targetChannel must be present in the + * sourceChannel. If _meta.join_id exists in the targetChannel, that is + * used as an id instead. If the id doesn't match any id in the sourceChannel, + * an error is thrown. + */ + +def safeJoin(targetChannel, sourceChannel, key) { + def sourceIDs = new IDChecker() + + def sourceCheck = sourceChannel + | map { tup -> + sourceIDs.observe(tup[0]) + tup + } + def targetCheck = targetChannel + | map { tup -> + def id = tup[0] + + if (!sourceIDs.contains(id)) { + error ( + "Error in module '${key}' when merging output with original state.\n" + + " Reason: output with id '${id}' could not be joined with source channel.\n" + + " If the IDs in the output channel differ from the input channel,\n" + + " please set `tup[1]._meta.join_id to the original ID.\n" + + " Original IDs in input channel: ['${sourceIDs.getItems().join("', '")}'].\n" + + " Unexpected ID in the output channel: '${id}'.\n" + + " Example input event: [\"id\", [input: file(...)]],\n" + + " Example output event: [\"newid\", [output: file(...), _meta: [join_id: \"id\"]]]" + ) + } + // TODO: add link to our documentation on how to fix this + + tup + } + + sourceCheck.cross(targetChannel) + | map{ left, right -> + right + left.drop(1) + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/config/_processArgument.nf' +def _processArgument(arg) { + arg.multiple = arg.multiple != null ? arg.multiple : false + arg.required = arg.required != null ? arg.required : false + arg.direction = arg.direction != null ? arg.direction : "input" + arg.multiple_sep = arg.multiple_sep != null ? arg.multiple_sep : ";" + arg.plainName = arg.name.replaceAll("^-*", "") + + if (arg.type == "file") { + arg.must_exist = arg.must_exist != null ? arg.must_exist : true + arg.create_parent = arg.create_parent != null ? arg.create_parent : true + } + + // add default values to output files which haven't already got a default + if (arg.type == "file" && arg.direction == "output" && arg.default == null) { + def mult = arg.multiple ? "_*" : "" + def extSearch = "" + if (arg.default != null) { + extSearch = arg.default + } else if (arg.example != null) { + extSearch = arg.example + } + if (extSearch instanceof List) { + extSearch = extSearch[0] + } + def extSearchResult = extSearch.find("\\.[^\\.]+\$") + def ext = extSearchResult != null ? extSearchResult : "" + arg.default = "\$id.\$key.${arg.plainName}${mult}${ext}" + if (arg.multiple) { + arg.default = [arg.default] + } + } + + if (!arg.multiple) { + if (arg.default != null && arg.default instanceof List) { + arg.default = arg.default[0] + } + if (arg.example != null && arg.example instanceof List) { + arg.example = arg.example[0] + } + } + + if (arg.type == "boolean_true") { + arg.default = false + } + if (arg.type == "boolean_false") { + arg.default = true + } + + arg +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/config/addGlobalParams.nf' +def addGlobalArguments(config) { + def localConfig = [ + "argument_groups": [ + [ + "name": "Nextflow input-output arguments", + "description": "Input/output parameters for Nextflow itself. Please note that both publishDir and publish_dir are supported but at least one has to be configured.", + "arguments" : [ + [ + 'name': '--publish_dir', + 'required': true, + 'type': 'string', + 'description': 'Path to an output directory.', + 'example': 'output/', + 'multiple': false + ], + [ + 'name': '--param_list', + 'required': false, + 'type': 'string', + 'description': '''Allows inputting multiple parameter sets to initialise a Nextflow channel. A `param_list` can either be a list of maps, a csv file, a json file, a yaml file, or simply a yaml blob. + | + |* A list of maps (as-is) where the keys of each map corresponds to the arguments of the pipeline. Example: in a `nextflow.config` file: `param_list: [ ['id': 'foo', 'input': 'foo.txt'], ['id': 'bar', 'input': 'bar.txt'] ]`. + |* A csv file should have column names which correspond to the different arguments of this pipeline. Example: `--param_list data.csv` with columns `id,input`. + |* A json or a yaml file should be a list of maps, each of which has keys corresponding to the arguments of the pipeline. Example: `--param_list data.json` with contents `[ {'id': 'foo', 'input': 'foo.txt'}, {'id': 'bar', 'input': 'bar.txt'} ]`. + |* A yaml blob can also be passed directly as a string. Example: `--param_list "[ {'id': 'foo', 'input': 'foo.txt'}, {'id': 'bar', 'input': 'bar.txt'} ]"`. + | + |When passing a csv, json or yaml file, relative path names are relativized to the location of the parameter file. No relativation is performed when `param_list` is a list of maps (as-is) or a yaml blob.'''.stripMargin(), + 'example': 'my_params.yaml', + 'multiple': false, + 'hidden': true + ] + // TODO: allow multiple: true in param_list? + // TODO: allow to specify a --param_list_regex to filter the param_list? + // TODO: allow to specify a --param_list_from_state to remap entries in the param_list? + ] + ] + ] + ] + + return processConfig(_mergeMap(config, localConfig)) +} + +def _mergeMap(Map lhs, Map rhs) { + return rhs.inject(lhs.clone()) { map, entry -> + if (map[entry.key] instanceof Map && entry.value instanceof Map) { + map[entry.key] = _mergeMap(map[entry.key], entry.value) + } else if (map[entry.key] instanceof Collection && entry.value instanceof Collection) { + map[entry.key] += entry.value + } else { + map[entry.key] = entry.value + } + return map + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/config/generateHelp.nf' +def _generateArgumentHelp(param) { + // alternatives are not supported + // def names = param.alternatives ::: List(param.name) + + def unnamedProps = [ + ["required parameter", param.required], + ["multiple values allowed", param.multiple], + ["output", param.direction.toLowerCase() == "output"], + ["file must exist", param.type == "file" && param.must_exist] + ].findAll{it[1]}.collect{it[0]} + + def dflt = null + if (param.default != null) { + if (param.default instanceof List) { + dflt = param.default.join(param.multiple_sep != null ? param.multiple_sep : ", ") + } else { + dflt = param.default.toString() + } + } + def example = null + if (param.example != null) { + if (param.example instanceof List) { + example = param.example.join(param.multiple_sep != null ? param.multiple_sep : ", ") + } else { + example = param.example.toString() + } + } + def min = param.min?.toString() + def max = param.max?.toString() + + def escapeChoice = { choice -> + def s1 = choice.replaceAll("\\n", "\\\\n") + def s2 = s1.replaceAll("\"", """\\\"""") + s2.contains(",") || s2 != choice ? "\"" + s2 + "\"" : s2 + } + def choices = param.choices == null ? + null : + "[ " + param.choices.collect{escapeChoice(it.toString())}.join(", ") + " ]" + + def namedPropsStr = [ + ["type", ([param.type] + unnamedProps).join(", ")], + ["default", dflt], + ["example", example], + ["choices", choices], + ["min", min], + ["max", max] + ] + .findAll{it[1]} + .collect{"\n " + it[0] + ": " + it[1].replaceAll("\n", "\\n")} + .join("") + + def descStr = param.description == null ? + "" : + _paragraphWrap("\n" + param.description.trim(), 80 - 8).join("\n ") + + "\n --" + param.plainName + + namedPropsStr + + descStr +} + +// Based on Helper.generateHelp() in Helper.scala +def _generateHelp(config) { + def fun = config + + // PART 1: NAME AND VERSION + def nameStr = fun.name + + (fun.version == null ? "" : " " + fun.version) + + // PART 2: DESCRIPTION + def descrStr = fun.description == null ? + "" : + "\n\n" + _paragraphWrap(fun.description.trim(), 80).join("\n") + + // PART 3: Usage + def usageStr = fun.usage == null ? + "" : + "\n\nUsage:\n" + fun.usage.trim() + + // PART 4: Options + def argGroupStrs = fun.allArgumentGroups.collect{argGroup -> + def name = argGroup.name + def descriptionStr = argGroup.description == null ? + "" : + "\n " + _paragraphWrap(argGroup.description.trim(), 80-4).join("\n ") + "\n" + def arguments = argGroup.arguments.collect{arg -> + arg instanceof String ? fun.allArguments.find{it.plainName == arg} : arg + }.findAll{it != null} + def argumentStrs = arguments.collect{param -> _generateArgumentHelp(param)} + + "\n\n$name:" + + descriptionStr + + argumentStrs.join("\n") + } + + // FINAL: combine + def out = nameStr + + descrStr + + usageStr + + argGroupStrs.join("") + + return out +} + +// based on Format._paragraphWrap +def _paragraphWrap(str, maxLength) { + def outLines = [] + str.split("\n").each{par -> + def words = par.split("\\s").toList() + + def word = null + def line = words.pop() + while(!words.isEmpty()) { + word = words.pop() + if (line.length() + word.length() + 1 <= maxLength) { + line = line + " " + word + } else { + outLines.add(line) + line = word + } + } + if (words.isEmpty()) { + outLines.add(line) + } + } + return outLines +} + +def helpMessage(config) { + if (params.containsKey("help") && params.help) { + def mergedConfig = addGlobalArguments(config) + def helpStr = _generateHelp(mergedConfig) + println(helpStr) + exit 0 + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/config/processConfig.nf' +def processConfig(config) { + // set defaults for arguments + config.arguments = + (config.arguments ?: []).collect{_processArgument(it)} + + // set defaults for argument_group arguments + config.argument_groups = + (config.argument_groups ?: []).collect{grp -> + grp.arguments = (grp.arguments ?: []).collect{_processArgument(it)} + grp + } + + // create combined arguments list + config.allArguments = + config.arguments + + config.argument_groups.collectMany{it.arguments} + + // add missing argument groups (based on Functionality::allArgumentGroups()) + def argGroups = config.argument_groups + if (argGroups.any{it.name.toLowerCase() == "arguments"}) { + argGroups = argGroups.collect{ grp -> + if (grp.name.toLowerCase() == "arguments") { + grp = grp + [ + arguments: grp.arguments + config.arguments + ] + } + grp + } + } else { + argGroups = argGroups + [ + name: "Arguments", + arguments: config.arguments + ] + } + config.allArgumentGroups = argGroups + + config +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/config/readConfig.nf' + +def readConfig(file) { + def config = readYaml(file ?: moduleDir.resolve("config.vsh.yaml")) + processConfig(config) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/_resolveSiblingIfNotAbsolute.nf' +/** + * Resolve a path relative to the current file. + * + * @param str The path to resolve, as a String. + * @param parentPath The path to resolve relative to, as a Path. + * + * @return The path that may have been resovled, as a Path. + */ +def _resolveSiblingIfNotAbsolute(str, parentPath) { + if (str !instanceof String) { + return str + } + if (!_stringIsAbsolutePath(str)) { + return parentPath.resolveSibling(str) + } else { + return file(str, hidden: true) + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/_stringIsAbsolutePath.nf' +/** + * Check whether a path as a string is absolute. + * + * In the past, we tried using `file(., relative: true).isAbsolute()`, + * but the 'relative' option was added in 22.10.0. + * + * @param path The path to check, as a String. + * + * @return Whether the path is absolute, as a boolean. + */ +def _stringIsAbsolutePath(path) { + def _resolve_URL_PROTOCOL = ~/^([a-zA-Z][a-zA-Z0-9]*:)?\\/.+/ + + assert path instanceof String + return _resolve_URL_PROTOCOL.matcher(path).matches() +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/collectTraces.nf' +class CustomTraceObserver implements nextflow.trace.TraceObserver { + List traces + + CustomTraceObserver(List traces) { + this.traces = traces + } + + @Override + void onProcessComplete(nextflow.processor.TaskHandler handler, nextflow.trace.TraceRecord trace) { + def trace2 = trace.store.clone() + trace2.script = null + traces.add(trace2) + } + + @Override + void onProcessCached(nextflow.processor.TaskHandler handler, nextflow.trace.TraceRecord trace) { + def trace2 = trace.store.clone() + trace2.script = null + traces.add(trace2) + } +} + +def collectTraces() { + def traces = Collections.synchronizedList([]) + + // add custom trace observer which stores traces in the traces object + session.observers.add(new CustomTraceObserver(traces)) + + traces +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/deepClone.nf' +/** + * Performs a deep clone of the given object. + * @param x an object + */ +def deepClone(x) { + iterateMap(x, {it instanceof Cloneable ? it.clone() : it}) +} +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/getPublishDir.nf' +def getPublishDir() { + return params.containsKey("publish_dir") ? params.publish_dir : + params.containsKey("publishDir") ? params.publishDir : + null +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/getRootDir.nf' + +// Recurse upwards until we find a '.build.yaml' file +def _findBuildYamlFile(pathPossiblySymlink) { + def path = pathPossiblySymlink.toRealPath() + def child = path.resolve(".build.yaml") + if (java.nio.file.Files.isDirectory(path) && java.nio.file.Files.exists(child)) { + return child + } else { + def parent = path.getParent() + if (parent == null) { + return null + } else { + return _findBuildYamlFile(parent) + } + } +} + +// get the root of the target folder +def getRootDir() { + def dir = _findBuildYamlFile(meta.resources_dir) + assert dir != null: "Could not find .build.yaml in the folder structure" + dir.getParent() +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/iterateMap.nf' +/** + * Recursively apply a function over the leaves of an object. + * @param obj The object to iterate over. + * @param fun The function to apply to each value. + * @return The object with the function applied to each value. + */ +def iterateMap(obj, fun) { + if (obj instanceof List && obj !instanceof String) { + return obj.collect{item -> + iterateMap(item, fun) + } + } else if (obj instanceof Map) { + return obj.collectEntries{key, item -> + [key.toString(), iterateMap(item, fun)] + } + } else { + return fun(obj) + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/niceView.nf' +/** + * A view for printing the event of each channel as a YAML blob. + * This is useful for debugging. + */ +def niceView() { + workflow niceViewWf { + take: input + main: + output = input + | view{toYamlBlob(it)} + emit: output + } + return niceViewWf +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/readCsv.nf' + +def readCsv(file_path) { + def output = [] + def inputFile = file_path !instanceof Path ? file(file_path, hidden: true) : file_path + + // todo: allow escaped quotes in string + // todo: allow single quotes? + def splitRegex = java.util.regex.Pattern.compile(''',(?=(?:[^"]*"[^"]*")*[^"]*$)''') + def removeQuote = java.util.regex.Pattern.compile('''"(.*)"''') + + def br = java.nio.file.Files.newBufferedReader(inputFile) + + def row = -1 + def header = null + while (br.ready() && header == null) { + def line = br.readLine() + row++ + if (!line.startsWith("#")) { + header = splitRegex.split(line, -1).collect{field -> + m = removeQuote.matcher(field) + m.find() ? m.replaceFirst('$1') : field + } + } + } + assert header != null: "CSV file should contain a header" + + while (br.ready()) { + def line = br.readLine() + row++ + if (line == null) { + br.close() + break + } + + if (!line.startsWith("#")) { + def predata = splitRegex.split(line, -1) + def data = predata.collect{field -> + if (field == "") { + return null + } + def m = removeQuote.matcher(field) + if (m.find()) { + return m.replaceFirst('$1') + } else { + return field + } + } + assert header.size() == data.size(): "Row $row should contain the same number as fields as the header" + + def dataMap = [header, data].transpose().collectEntries().findAll{it.value != null} + output.add(dataMap) + } + } + + output +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/readJson.nf' +def readJson(file_path) { + def inputFile = file_path !instanceof Path ? file(file_path, hidden: true) : file_path + def jsonSlurper = new groovy.json.JsonSlurper() + jsonSlurper.parse(inputFile) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/readJsonBlob.nf' +def readJsonBlob(str) { + def jsonSlurper = new groovy.json.JsonSlurper() + jsonSlurper.parseText(str) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/readTaggedYaml.nf' +// Custom constructor to modify how certain objects are parsed from YAML +class CustomConstructor extends org.yaml.snakeyaml.constructor.Constructor { + Path root + + class ConstructPath extends org.yaml.snakeyaml.constructor.AbstractConstruct { + public Object construct(org.yaml.snakeyaml.nodes.Node node) { + String filename = (String) constructScalar(node); + if (root != null) { + return root.resolve(filename); + } + return java.nio.file.Paths.get(filename); + } + } + + CustomConstructor(org.yaml.snakeyaml.LoaderOptions options, Path root) { + super(options) + this.root = root + // Handling !file tag and parse it back to a File type + this.yamlConstructors.put(new org.yaml.snakeyaml.nodes.Tag("!file"), new ConstructPath()) + } +} + +def readTaggedYaml(Path path) { + def options = new org.yaml.snakeyaml.LoaderOptions() + def constructor = new CustomConstructor(options, path.getParent()) + def yaml = new org.yaml.snakeyaml.Yaml(constructor) + return yaml.load(path.text) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/readYaml.nf' +def readYaml(file_path) { + def inputFile = file_path !instanceof Path ? file(file_path, hidden: true) : file_path + def yamlSlurper = new org.yaml.snakeyaml.Yaml() + yamlSlurper.load(inputFile) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/readYamlBlob.nf' +def readYamlBlob(str) { + def yamlSlurper = new org.yaml.snakeyaml.Yaml() + yamlSlurper.load(str) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/toJsonBlob.nf' +String toJsonBlob(data) { + return groovy.json.JsonOutput.toJson(data) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/toTaggedYamlBlob.nf' +// Custom representer to modify how certain objects are represented in YAML +class CustomRepresenter extends org.yaml.snakeyaml.representer.Representer { + Path relativizer + + class RepresentPath implements org.yaml.snakeyaml.representer.Represent { + public String getFileName(Object obj) { + if (obj instanceof File) { + obj = ((File) obj).toPath(); + } + if (obj !instanceof Path) { + throw new IllegalArgumentException("Object: " + obj + " is not a Path or File"); + } + def path = (Path) obj; + + if (relativizer != null) { + return relativizer.relativize(path).toString() + } else { + return path.toString() + } + } + + public org.yaml.snakeyaml.nodes.Node representData(Object data) { + String filename = getFileName(data); + def tag = new org.yaml.snakeyaml.nodes.Tag("!file"); + return representScalar(tag, filename); + } + } + CustomRepresenter(org.yaml.snakeyaml.DumperOptions options, Path relativizer) { + super(options) + this.relativizer = relativizer + this.representers.put(sun.nio.fs.UnixPath, new RepresentPath()) + this.representers.put(Path, new RepresentPath()) + this.representers.put(File, new RepresentPath()) + } +} + +String toTaggedYamlBlob(data) { + return toRelativeTaggedYamlBlob(data, null) +} +String toRelativeTaggedYamlBlob(data, Path relativizer) { + def options = new org.yaml.snakeyaml.DumperOptions() + options.setDefaultFlowStyle(org.yaml.snakeyaml.DumperOptions.FlowStyle.BLOCK) + def representer = new CustomRepresenter(options, relativizer) + def yaml = new org.yaml.snakeyaml.Yaml(representer, options) + return yaml.dump(data) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/toYamlBlob.nf' +String toYamlBlob(data) { + def options = new org.yaml.snakeyaml.DumperOptions() + options.setDefaultFlowStyle(org.yaml.snakeyaml.DumperOptions.FlowStyle.BLOCK) + options.setPrettyFlow(true) + def yaml = new org.yaml.snakeyaml.Yaml(options) + def cleanData = iterateMap(data, { it instanceof Path ? it.toString() : it }) + return yaml.dump(cleanData) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/writeJson.nf' +void writeJson(data, file) { + assert data: "writeJson: data should not be null" + assert file: "writeJson: file should not be null" + file.write(toJsonBlob(data)) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/writeYaml.nf' +void writeYaml(data, file) { + assert data: "writeYaml: data should not be null" + assert file: "writeYaml: file should not be null" + file.write(toYamlBlob(data)) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/states/findStates.nf' +def findStates(Map params, Map config) { + def auto_config = deepClone(config) + def auto_params = deepClone(params) + + auto_config = auto_config.clone() + // override arguments + auto_config.argument_groups = [] + auto_config.arguments = [ + [ + type: "string", + name: "--id", + description: "A dummy identifier", + required: false + ], + [ + type: "file", + name: "--input_states", + example: "/path/to/input/directory/**/state.yaml", + description: "Path to input directory containing the datasets to be integrated.", + required: true, + multiple: true, + multiple_sep: ";" + ], + [ + type: "string", + name: "--filter", + example: "foo/.*/state.yaml", + description: "Regex to filter state files by path.", + required: false + ], + // to do: make this a yaml blob? + [ + type: "string", + name: "--rename_keys", + example: ["newKey1:oldKey1", "newKey2:oldKey2"], + description: "Rename keys in the detected input files. This is useful if the input files do not match the set of input arguments of the workflow.", + required: false, + multiple: true, + multiple_sep: ";" + ], + [ + type: "string", + name: "--settings", + example: '{"output_dataset": "dataset.h5ad", "k": 10}', + description: "Global arguments as a JSON glob to be passed to all components.", + required: false + ] + ] + if (!(auto_params.containsKey("id"))) { + auto_params["id"] = "auto" + } + + // run auto config through processConfig once more + auto_config = processConfig(auto_config) + + workflow findStatesWf { + helpMessage(auto_config) + + output_ch = + channelFromParams(auto_params, auto_config) + | flatMap { autoId, args -> + + def globalSettings = args.settings ? readYamlBlob(args.settings) : [:] + + // look for state files in input dir + def stateFiles = args.input_states + + // filter state files by regex + if (args.filter) { + stateFiles = stateFiles.findAll{ stateFile -> + def stateFileStr = stateFile.toString() + def matcher = stateFileStr =~ args.filter + matcher.matches()} + } + + // read in states + def states = stateFiles.collect { stateFile -> + def state_ = readTaggedYaml(stateFile) + [state_.id, state_] + } + + // construct renameMap + if (args.rename_keys) { + def renameMap = args.rename_keys.collectEntries{renameString -> + def split = renameString.split(";") + assert split.size() == 2: "Argument 'rename_keys' should be of the form 'newKey:oldKey,newKey:oldKey'" + split + } + + // rename keys in state, only let states through which have all keys + // also add global settings + states = states.collectMany{id, state -> + def newState = [:] + + for (key in renameMap.keySet()) { + def origKey = renameMap[key] + if (!(state.containsKey(origKey))) { + return [] + } + newState[key] = state[origKey] + } + + [[id, globalSettings + newState]] + } + } + + states + } + emit: + output_ch + } + + return findStatesWf +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/states/joinStates.nf' +def joinStates(Closure apply_) { + workflow joinStatesWf { + take: input_ch + main: + output_ch = input_ch + | toSortedList + | filter{ it.size() > 0 } + | map{ tups -> + def ids = tups.collect{it[0]} + def states = tups.collect{it[1]} + apply_(ids, states) + } + + emit: output_ch + } + return joinStatesWf +} +// helper file: 'src/main/resources/io/viash/runners/nextflow/states/publishStates.nf' +def collectFiles(obj) { + if (obj instanceof java.io.File || obj instanceof Path) { + return [obj] + } else if (obj instanceof List && obj !instanceof String) { + return obj.collectMany{item -> + collectFiles(item) + } + } else if (obj instanceof Map) { + return obj.collectMany{key, item -> + collectFiles(item) + } + } else { + return [] + } +} + +/** + * Recurse through a state and collect all input files and their target output filenames. + * @param obj The state to recurse through. + * @param prefix The prefix to prepend to the output filenames. + */ +def collectInputOutputPaths(obj, prefix) { + if (obj instanceof File || obj instanceof Path) { + def path = obj instanceof Path ? obj : obj.toPath() + def ext = path.getFileName().toString().find("\\.[^\\.]+\$") ?: "" + def newFilename = prefix + ext + return [[obj, newFilename]] + } else if (obj instanceof List && obj !instanceof String) { + return obj.withIndex().collectMany{item, ix -> + collectInputOutputPaths(item, prefix + "_" + ix) + } + } else if (obj instanceof Map) { + return obj.collectMany{key, item -> + collectInputOutputPaths(item, prefix + "." + key) + } + } else { + return [] + } +} + +def publishStates(Map args) { + def key_ = args.get("key") + def yamlTemplate_ = args.get("output_state", args.get("outputState", '$id.$key.state.yaml')) + + assert key_ != null : "publishStates: key must be specified" + + workflow publishStatesWf { + take: input_ch + main: + input_ch + | map { tup -> + def id_ = tup[0] + def state_ = tup[1] + + // the input files and the target output filenames + def inputoutputFilenames_ = collectInputOutputPaths(state_, id_ + "." + key_).transpose() + def inputFiles_ = inputoutputFilenames_[0] + def outputFilenames_ = inputoutputFilenames_[1] + + def yamlFilename = yamlTemplate_ + .replaceAll('\\$id', id_) + .replaceAll('\\$key', key_) + + // TODO: do the pathnames in state_ match up with the outputFilenames_? + + // convert state to yaml blob + def yamlBlob_ = toRelativeTaggedYamlBlob([id: id_] + state_, java.nio.file.Paths.get(yamlFilename)) + + [id_, yamlBlob_, yamlFilename, inputFiles_, outputFilenames_] + } + | publishStatesProc + emit: input_ch + } + return publishStatesWf +} +process publishStatesProc { + // todo: check publishpath? + publishDir path: "${getPublishDir()}/", mode: "copy" + tag "$id" + input: + tuple val(id), val(yamlBlob), val(yamlFile), path(inputFiles, stageAs: "_inputfile?/*"), val(outputFiles) + output: + tuple val(id), path{[yamlFile] + outputFiles} + script: + def copyCommands = [ + inputFiles instanceof List ? inputFiles : [inputFiles], + outputFiles instanceof List ? outputFiles : [outputFiles] + ] + .transpose() + .collectMany{infile, outfile -> + if (infile.toString() != outfile.toString()) { + [ + "[ -d \"\$(dirname '${outfile.toString()}')\" ] || mkdir -p \"\$(dirname '${outfile.toString()}')\"", + "cp -r '${infile.toString()}' '${outfile.toString()}'" + ] + } else { + // no need to copy if infile is the same as outfile + [] + } + } + """ +mkdir -p "\$(dirname '${yamlFile}')" +echo "Storing state as yaml" +echo '${yamlBlob}' > '${yamlFile}' +echo "Copying output files to destination folder" +${copyCommands.join("\n ")} +""" +} + + +// this assumes that the state contains no other values other than those specified in the config +def publishStatesByConfig(Map args) { + def config = args.get("config") + assert config != null : "publishStatesByConfig: config must be specified" + + def key_ = args.get("key", config.name) + assert key_ != null : "publishStatesByConfig: key must be specified" + + workflow publishStatesSimpleWf { + take: input_ch + main: + input_ch + | map { tup -> + def id_ = tup[0] + def state_ = tup[1] // e.g. [output: new File("myoutput.h5ad"), k: 10] + def origState_ = tup[2] // e.g. [output: '$id.$key.foo.h5ad'] + + // TODO: allow overriding the state.yaml template + // TODO TODO: if auto.publish == "state", add output_state as an argument + def yamlTemplate = params.containsKey("output_state") ? params.output_state : '$id.$key.state.yaml' + def yamlFilename = yamlTemplate + .replaceAll('\\$id', id_) + .replaceAll('\\$key', key_) + def yamlDir = java.nio.file.Paths.get(yamlFilename).getParent() + + // the processed state is a list of [key, value, inputPath, outputFilename] tuples, where + // - key is a String + // - value is any object that can be serialized to a Yaml (so a String/Integer/Long/Double/Boolean, a List, a Map, or a Path) + // - inputPath is a List[Path] + // - outputFilename is a List[String] + // - (key, value) are the tuples that will be saved to the state.yaml file + // - (inputPath, outputFilename) are the files that will be copied from src to dest (relative to the state.yaml) + def processedState = + config.allArguments + .findAll { it.direction == "output" } + .collectMany { par -> + def plainName_ = par.plainName + // if the state does not contain the key, it's an + // optional argument for which the component did + // not generate any output + if (!state_.containsKey(plainName_)) { + return [] + } + def value = state_[plainName_] + // if the parameter is not a file, it should be stored + // in the state as-is, but is not something that needs + // to be copied from the source path to the dest path + if (par.type != "file") { + return [[key: plainName_, value: value, inputPath: [], outputFilename: []]] + } + // if the orig state does not contain this filename, + // it's an optional argument for which the user specified + // that it should not be returned as a state + if (!origState_.containsKey(plainName_)) { + return [] + } + def filenameTemplate = origState_[plainName_] + // if the pararameter is multiple: true, fetch the template + if (par.multiple && filenameTemplate instanceof List) { + filenameTemplate = filenameTemplate[0] + } + // instantiate the template + def filename = filenameTemplate + .replaceAll('\\$id', id_) + .replaceAll('\\$key', key_) + if (par.multiple) { + // if the parameter is multiple: true, the filename + // should contain a wildcard '*' that is replaced with + // the index of the file + assert filename.contains("*") : "Module '${key_}' id '${id_}': Multiple output files specified, but no wildcard '*' in the filename: ${filename}" + def outputPerFile = value.withIndex().collect{ val, ix -> + def filename_ix = filename.replace("*", ix.toString()) + def value_ = java.nio.file.Paths.get(filename_ix) + // if id contains a slash + if (yamlDir != null) { + value_ = yamlDir.relativize(value_) + } + def inputPath = val instanceof File ? val.toPath() : val + [value: value_, inputPath: inputPath, outputFilename: filename_ix] + } + def transposedOutputs = ["value", "inputPath", "outputFilename"].collectEntries{ key -> + [key, outputPerFile.collect{dic -> dic[key]}] + } + return [[key: plainName_] + transposedOutputs] + } else { + def value_ = java.nio.file.Paths.get(filename) + // if id contains a slash + if (yamlDir != null) { + value_ = yamlDir.relativize(value_) + } + def inputPath = value instanceof File ? value.toPath() : value + return [[key: plainName_, value: value_, inputPath: [inputPath], outputFilename: [filename]]] + } + } + + def updatedState_ = processedState.collectEntries{[it.key, it.value]} + def inputPaths = processedState.collectMany{it.inputPath} + def outputFilenames = processedState.collectMany{it.outputFilename} + + // convert state to yaml blob + def yamlBlob_ = toTaggedYamlBlob([id: id_] + updatedState_) + + [id_, yamlBlob_, yamlFilename, inputPaths, outputFilenames] + } + | publishStatesProc + emit: input_ch + } + return publishStatesSimpleWf +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/states/setState.nf' +def setState(fun) { + assert fun instanceof Closure || fun instanceof Map || fun instanceof List : + "Error in setState: Expected process argument to be a Closure, a Map, or a List. Found: class ${fun.getClass()}" + + // if fun is a List, convert to map + if (fun instanceof List) { + // check whether fun is a list[string] + assert fun.every{it instanceof CharSequence} : "Error in setState: argument is a List, but not all elements are Strings" + fun = fun.collectEntries{[it, it]} + } + + // if fun is a map, convert to closure + if (fun instanceof Map) { + // check whether fun is a map[string, string] + assert fun.values().every{it instanceof CharSequence} : "Error in setState: argument is a Map, but not all values are Strings" + assert fun.keySet().every{it instanceof CharSequence} : "Error in setState: argument is a Map, but not all keys are Strings" + def funMap = fun.clone() + // turn the map into a closure to be used later on + fun = { id_, state_ -> + assert state_ instanceof Map : "Error in setState: the state is not a Map" + funMap.collectMany{newkey, origkey -> + if (state_.containsKey(origkey)) { + [[newkey, state_[origkey]]] + } else { + [] + } + }.collectEntries() + } + } + + map { tup -> + def id = tup[0] + def state = tup[1] + def unfilteredState = fun(id, state) + def newState = unfilteredState.findAll{key, val -> val != null} + [id, newState] + tup.drop(2) + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/workflowFactory/processAuto.nf' +// TODO: unit test processAuto +def processAuto(Map auto) { + // remove null values + auto = auto.findAll{k, v -> v != null} + + // check for unexpected keys + def expectedKeys = ["simplifyInput", "simplifyOutput", "transcript", "publish"] + def unexpectedKeys = auto.keySet() - expectedKeys + assert unexpectedKeys.isEmpty(), "unexpected keys in auto: '${unexpectedKeys.join("', '")}'" + + // check auto.simplifyInput + assert auto.simplifyInput instanceof Boolean, "auto.simplifyInput must be a boolean" + + // check auto.simplifyOutput + assert auto.simplifyOutput instanceof Boolean, "auto.simplifyOutput must be a boolean" + + // check auto.transcript + assert auto.transcript instanceof Boolean, "auto.transcript must be a boolean" + + // check auto.publish + assert auto.publish instanceof Boolean || auto.publish == "state", "auto.publish must be a boolean or 'state'" + + return auto.subMap(expectedKeys) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/workflowFactory/processDirectives.nf' +def assertMapKeys(map, expectedKeys, requiredKeys, mapName) { + assert map instanceof Map : "Expected argument '$mapName' to be a Map. Found: class ${map.getClass()}" + map.forEach { key, val -> + assert key in expectedKeys : "Unexpected key '$key' in ${mapName ? mapName + " " : ""}map" + } + requiredKeys.forEach { requiredKey -> + assert map.containsKey(requiredKey) : "Missing required key '$key' in ${mapName ? mapName + " " : ""}map" + } +} + +// TODO: unit test processDirectives +def processDirectives(Map drctv) { + // remove null values + drctv = drctv.findAll{k, v -> v != null} + + // check for unexpected keys + def expectedKeys = [ + "accelerator", "afterScript", "beforeScript", "cache", "conda", "container", "containerOptions", "cpus", "disk", "echo", "errorStrategy", "executor", "machineType", "maxErrors", "maxForks", "maxRetries", "memory", "module", "penv", "pod", "publishDir", "queue", "label", "scratch", "storeDir", "stageInMode", "stageOutMode", "tag", "time" + ] + def unexpectedKeys = drctv.keySet() - expectedKeys + assert unexpectedKeys.isEmpty() : "Unexpected keys in process directive: '${unexpectedKeys.join("', '")}'" + + /* DIRECTIVE accelerator + accepted examples: + - [ limit: 4, type: "nvidia-tesla-k80" ] + */ + if (drctv.containsKey("accelerator")) { + assertMapKeys(drctv["accelerator"], ["type", "limit", "request", "runtime"], [], "accelerator") + } + + /* DIRECTIVE afterScript + accepted examples: + - "source /cluster/bin/cleanup" + */ + if (drctv.containsKey("afterScript")) { + assert drctv["afterScript"] instanceof CharSequence + } + + /* DIRECTIVE beforeScript + accepted examples: + - "source /cluster/bin/setup" + */ + if (drctv.containsKey("beforeScript")) { + assert drctv["beforeScript"] instanceof CharSequence + } + + /* DIRECTIVE cache + accepted examples: + - true + - false + - "deep" + - "lenient" + */ + if (drctv.containsKey("cache")) { + assert drctv["cache"] instanceof CharSequence || drctv["cache"] instanceof Boolean + if (drctv["cache"] instanceof CharSequence) { + assert drctv["cache"] in ["deep", "lenient"] : "Unexpected value for cache" + } + } + + /* DIRECTIVE conda + accepted examples: + - "bwa=0.7.15" + - "bwa=0.7.15 fastqc=0.11.5" + - ["bwa=0.7.15", "fastqc=0.11.5"] + */ + if (drctv.containsKey("conda")) { + if (drctv["conda"] instanceof List) { + drctv["conda"] = drctv["conda"].join(" ") + } + assert drctv["conda"] instanceof CharSequence + } + + /* DIRECTIVE container + accepted examples: + - "foo/bar:tag" + - [ registry: "reg", image: "im", tag: "ta" ] + is transformed to "reg/im:ta" + - [ image: "im" ] + is transformed to "im:latest" + */ + if (drctv.containsKey("container")) { + assert drctv["container"] instanceof Map || drctv["container"] instanceof CharSequence + if (drctv["container"] instanceof Map) { + def m = drctv["container"] + assertMapKeys(m, [ "registry", "image", "tag" ], ["image"], "container") + def part1 = + System.getenv('OVERRIDE_CONTAINER_REGISTRY') ? System.getenv('OVERRIDE_CONTAINER_REGISTRY') + "/" : + params.containsKey("override_container_registry") ? params["override_container_registry"] + "/" : // todo: remove? + m.registry ? m.registry + "/" : + "" + def part2 = m.image + def part3 = m.tag ? ":" + m.tag : ":latest" + drctv["container"] = part1 + part2 + part3 + } + } + + /* DIRECTIVE containerOptions + accepted examples: + - "--foo bar" + - ["--foo bar", "-f b"] + */ + if (drctv.containsKey("containerOptions")) { + if (drctv["containerOptions"] instanceof List) { + drctv["containerOptions"] = drctv["containerOptions"].join(" ") + } + assert drctv["containerOptions"] instanceof CharSequence + } + + /* DIRECTIVE cpus + accepted examples: + - 1 + - 10 + */ + if (drctv.containsKey("cpus")) { + assert drctv["cpus"] instanceof Integer + } + + /* DIRECTIVE disk + accepted examples: + - "1 GB" + - "2TB" + - "3.2KB" + - "10.B" + */ + if (drctv.containsKey("disk")) { + assert drctv["disk"] instanceof CharSequence + // assert drctv["disk"].matches("[0-9]+(\\.[0-9]*)? *[KMGTPEZY]?B") + // ^ does not allow closures + } + + /* DIRECTIVE echo + accepted examples: + - true + - false + */ + if (drctv.containsKey("echo")) { + assert drctv["echo"] instanceof Boolean + } + + /* DIRECTIVE errorStrategy + accepted examples: + - "terminate" + - "finish" + */ + if (drctv.containsKey("errorStrategy")) { + assert drctv["errorStrategy"] instanceof CharSequence + assert drctv["errorStrategy"] in ["terminate", "finish", "ignore", "retry"] : "Unexpected value for errorStrategy" + } + + /* DIRECTIVE executor + accepted examples: + - "local" + - "sge" + */ + if (drctv.containsKey("executor")) { + assert drctv["executor"] instanceof CharSequence + assert drctv["executor"] in ["local", "sge", "uge", "lsf", "slurm", "pbs", "pbspro", "moab", "condor", "nqsii", "ignite", "k8s", "awsbatch", "google-pipelines"] : "Unexpected value for executor" + } + + /* DIRECTIVE machineType + accepted examples: + - "n1-highmem-8" + */ + if (drctv.containsKey("machineType")) { + assert drctv["machineType"] instanceof CharSequence + } + + /* DIRECTIVE maxErrors + accepted examples: + - 1 + - 3 + */ + if (drctv.containsKey("maxErrors")) { + assert drctv["maxErrors"] instanceof Integer + } + + /* DIRECTIVE maxForks + accepted examples: + - 1 + - 3 + */ + if (drctv.containsKey("maxForks")) { + assert drctv["maxForks"] instanceof Integer + } + + /* DIRECTIVE maxRetries + accepted examples: + - 1 + - 3 + */ + if (drctv.containsKey("maxRetries")) { + assert drctv["maxRetries"] instanceof Integer + } + + /* DIRECTIVE memory + accepted examples: + - "1 GB" + - "2TB" + - "3.2KB" + - "10.B" + */ + if (drctv.containsKey("memory")) { + assert drctv["memory"] instanceof CharSequence + // assert drctv["memory"].matches("[0-9]+(\\.[0-9]*)? *[KMGTPEZY]?B") + // ^ does not allow closures + } + + /* DIRECTIVE module + accepted examples: + - "ncbi-blast/2.2.27" + - "ncbi-blast/2.2.27:t_coffee/10.0" + - ["ncbi-blast/2.2.27", "t_coffee/10.0"] + */ + if (drctv.containsKey("module")) { + if (drctv["module"] instanceof List) { + drctv["module"] = drctv["module"].join(":") + } + assert drctv["module"] instanceof CharSequence + } + + /* DIRECTIVE penv + accepted examples: + - "smp" + */ + if (drctv.containsKey("penv")) { + assert drctv["penv"] instanceof CharSequence + } + + /* DIRECTIVE pod + accepted examples: + - [ label: "key", value: "val" ] + - [ annotation: "key", value: "val" ] + - [ env: "key", value: "val" ] + - [ [label: "l", value: "v"], [env: "e", value: "v"]] + */ + if (drctv.containsKey("pod")) { + if (drctv["pod"] instanceof Map) { + drctv["pod"] = [ drctv["pod"] ] + } + assert drctv["pod"] instanceof List + drctv["pod"].forEach { pod -> + assert pod instanceof Map + // TODO: should more checks be added? + // See https://www.nextflow.io/docs/latest/process.html?highlight=directives#pod + // e.g. does it contain 'label' and 'value', or 'annotation' and 'value', or ...? + } + } + + /* DIRECTIVE publishDir + accepted examples: + - [] + - [ [ path: "foo", enabled: true ], [ path: "bar", enabled: false ] ] + - "/path/to/dir" + is transformed to [[ path: "/path/to/dir" ]] + - [ path: "/path/to/dir", mode: "cache" ] + is transformed to [[ path: "/path/to/dir", mode: "cache" ]] + */ + // TODO: should we also look at params["publishDir"]? + if (drctv.containsKey("publishDir")) { + def pblsh = drctv["publishDir"] + + // check different options + assert pblsh instanceof List || pblsh instanceof Map || pblsh instanceof CharSequence + + // turn into list if not already so + // for some reason, 'if (!pblsh instanceof List) pblsh = [ pblsh ]' doesn't work. + pblsh = pblsh instanceof List ? pblsh : [ pblsh ] + + // check elements of publishDir + pblsh = pblsh.collect{ elem -> + // turn into map if not already so + elem = elem instanceof CharSequence ? [ path: elem ] : elem + + // check types and keys + assert elem instanceof Map : "Expected publish argument '$elem' to be a String or a Map. Found: class ${elem.getClass()}" + assertMapKeys(elem, [ "path", "mode", "overwrite", "pattern", "saveAs", "enabled" ], ["path"], "publishDir") + + // check elements in map + assert elem.containsKey("path") + assert elem["path"] instanceof CharSequence + if (elem.containsKey("mode")) { + assert elem["mode"] instanceof CharSequence + assert elem["mode"] in [ "symlink", "rellink", "link", "copy", "copyNoFollow", "move" ] + } + if (elem.containsKey("overwrite")) { + assert elem["overwrite"] instanceof Boolean + } + if (elem.containsKey("pattern")) { + assert elem["pattern"] instanceof CharSequence + } + if (elem.containsKey("saveAs")) { + assert elem["saveAs"] instanceof CharSequence //: "saveAs as a Closure is currently not supported. Surround your closure with single quotes to get the desired effect. Example: '\{ foo \}'" + } + if (elem.containsKey("enabled")) { + assert elem["enabled"] instanceof Boolean + } + + // return final result + elem + } + // store final directive + drctv["publishDir"] = pblsh + } + + /* DIRECTIVE queue + accepted examples: + - "long" + - "short,long" + - ["short", "long"] + */ + if (drctv.containsKey("queue")) { + if (drctv["queue"] instanceof List) { + drctv["queue"] = drctv["queue"].join(",") + } + assert drctv["queue"] instanceof CharSequence + } + + /* DIRECTIVE label + accepted examples: + - "big_mem" + - "big_cpu" + - ["big_mem", "big_cpu"] + */ + if (drctv.containsKey("label")) { + if (drctv["label"] instanceof CharSequence) { + drctv["label"] = [ drctv["label"] ] + } + assert drctv["label"] instanceof List + drctv["label"].forEach { label -> + assert label instanceof CharSequence + // assert label.matches("[a-zA-Z0-9]([a-zA-Z0-9_]*[a-zA-Z0-9])?") + // ^ does not allow closures + } + } + + /* DIRECTIVE scratch + accepted examples: + - true + - "/path/to/scratch" + - '$MY_PATH_TO_SCRATCH' + - "ram-disk" + */ + if (drctv.containsKey("scratch")) { + assert drctv["scratch"] == true || drctv["scratch"] instanceof CharSequence + } + + /* DIRECTIVE storeDir + accepted examples: + - "/path/to/storeDir" + */ + if (drctv.containsKey("storeDir")) { + assert drctv["storeDir"] instanceof CharSequence + } + + /* DIRECTIVE stageInMode + accepted examples: + - "copy" + - "link" + */ + if (drctv.containsKey("stageInMode")) { + assert drctv["stageInMode"] instanceof CharSequence + assert drctv["stageInMode"] in ["copy", "link", "symlink", "rellink"] + } + + /* DIRECTIVE stageOutMode + accepted examples: + - "copy" + - "link" + */ + if (drctv.containsKey("stageOutMode")) { + assert drctv["stageOutMode"] instanceof CharSequence + assert drctv["stageOutMode"] in ["copy", "move", "rsync"] + } + + /* DIRECTIVE tag + accepted examples: + - "foo" + - '$id' + */ + if (drctv.containsKey("tag")) { + assert drctv["tag"] instanceof CharSequence + } + + /* DIRECTIVE time + accepted examples: + - "1h" + - "2days" + - "1day 6hours 3minutes 30seconds" + */ + if (drctv.containsKey("time")) { + assert drctv["time"] instanceof CharSequence + // todo: validation regex? + } + + return drctv +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/workflowFactory/processWorkflowArgs.nf' +def processWorkflowArgs(Map args, Map defaultWfArgs, Map meta) { + // override defaults with args + def workflowArgs = defaultWfArgs + args + + // check whether 'key' exists + assert workflowArgs.containsKey("key") : "Error in module '${meta.config.name}': key is a required argument" + + // if 'key' is a closure, apply it to the original key + if (workflowArgs["key"] instanceof Closure) { + workflowArgs["key"] = workflowArgs["key"](meta.config.name) + } + def key = workflowArgs["key"] + assert key instanceof CharSequence : "Expected process argument 'key' to be a String. Found: class ${key.getClass()}" + assert key ==~ /^[a-zA-Z_]\w*$/ : "Error in module '$key': Expected process argument 'key' to consist of only letters, digits or underscores. Found: ${key}" + + // check for any unexpected keys + def expectedKeys = ["key", "directives", "auto", "map", "mapId", "mapData", "mapPassthrough", "filter", "runIf", "fromState", "toState", "args", "renameKeys", "debug"] + def unexpectedKeys = workflowArgs.keySet() - expectedKeys + assert unexpectedKeys.isEmpty() : "Error in module '$key': unexpected arguments to the '.run()' function: '${unexpectedKeys.join("', '")}'" + + // check whether directives exists and apply defaults + assert workflowArgs.containsKey("directives") : "Error in module '$key': directives is a required argument" + assert workflowArgs["directives"] instanceof Map : "Error in module '$key': Expected process argument 'directives' to be a Map. Found: class ${workflowArgs['directives'].getClass()}" + workflowArgs["directives"] = processDirectives(defaultWfArgs.directives + workflowArgs["directives"]) + + // check whether directives exists and apply defaults + assert workflowArgs.containsKey("auto") : "Error in module '$key': auto is a required argument" + assert workflowArgs["auto"] instanceof Map : "Error in module '$key': Expected process argument 'auto' to be a Map. Found: class ${workflowArgs['auto'].getClass()}" + workflowArgs["auto"] = processAuto(defaultWfArgs.auto + workflowArgs["auto"]) + + // auto define publish, if so desired + if (workflowArgs.auto.publish == true && (workflowArgs.directives.publishDir != null ? workflowArgs.directives.publishDir : [:]).isEmpty()) { + // can't assert at this level thanks to the no_publish profile + // assert params.containsKey("publishDir") || params.containsKey("publish_dir") : + // "Error in module '${workflowArgs['key']}': if auto.publish is true, params.publish_dir needs to be defined.\n" + + // " Example: params.publish_dir = \"./output/\"" + def publishDir = getPublishDir() + + if (publishDir != null) { + workflowArgs.directives.publishDir = [[ + path: publishDir, + saveAs: "{ it.startsWith('.') ? null : it }", // don't publish hidden files, by default + mode: "copy" + ]] + } + } + + // auto define transcript, if so desired + if (workflowArgs.auto.transcript == true) { + // can't assert at this level thanks to the no_publish profile + // assert params.containsKey("transcriptsDir") || params.containsKey("transcripts_dir") || params.containsKey("publishDir") || params.containsKey("publish_dir") : + // "Error in module '${workflowArgs['key']}': if auto.transcript is true, either params.transcripts_dir or params.publish_dir needs to be defined.\n" + + // " Example: params.transcripts_dir = \"./transcripts/\"" + def transcriptsDir = + params.containsKey("transcripts_dir") ? params.transcripts_dir : + params.containsKey("transcriptsDir") ? params.transcriptsDir : + params.containsKey("publish_dir") ? params.publish_dir + "/_transcripts" : + params.containsKey("publishDir") ? params.publishDir + "/_transcripts" : + null + if (transcriptsDir != null) { + def timestamp = nextflow.Nextflow.getSession().getWorkflowMetadata().start.format('yyyy-MM-dd_HH-mm-ss') + def transcriptsPublishDir = [ + path: "$transcriptsDir/$timestamp/\${task.process.replaceAll(':', '-')}/\${id}/", + saveAs: "{ it.startsWith('.') ? it.replaceAll('^.', '') : null }", + mode: "copy" + ] + def publishDirs = workflowArgs.directives.publishDir != null ? workflowArgs.directives.publishDir : null ? workflowArgs.directives.publishDir : [] + workflowArgs.directives.publishDir = publishDirs + transcriptsPublishDir + } + } + + // if this is a stubrun, remove certain directives? + if (workflow.stubRun) { + workflowArgs.directives.keySet().removeAll(["publishDir", "cpus", "memory", "label"]) + } + + for (nam in ["map", "mapId", "mapData", "mapPassthrough", "filter", "runIf"]) { + if (workflowArgs.containsKey(nam) && workflowArgs[nam]) { + assert workflowArgs[nam] instanceof Closure : "Error in module '$key': Expected process argument '$nam' to be null or a Closure. Found: class ${workflowArgs[nam].getClass()}" + } + } + + // TODO: should functions like 'map', 'mapId', 'mapData', 'mapPassthrough' be deprecated as well? + for (nam in ["map", "mapData", "mapPassthrough", "renameKeys"]) { + if (workflowArgs.containsKey(nam) && workflowArgs[nam] != null) { + log.warn "module '$key': workflow argument '$nam' is deprecated and will be removed in Viash 0.9.0. Please use 'fromState' and 'toState' instead." + } + } + + // check fromState + workflowArgs["fromState"] = _processFromState(workflowArgs.get("fromState"), key, meta.config) + + // check toState + workflowArgs["toState"] = _processToState(workflowArgs.get("toState"), key, meta.config) + + // return output + return workflowArgs +} + +def _processFromState(fromState, key_, config_) { + assert fromState == null || fromState instanceof Closure || fromState instanceof Map || fromState instanceof List : + "Error in module '$key_': Expected process argument 'fromState' to be null, a Closure, a Map, or a List. Found: class ${fromState.getClass()}" + if (fromState == null) { + return null + } + + // if fromState is a List, convert to map + if (fromState instanceof List) { + // check whether fromstate is a list[string] + assert fromState.every{it instanceof CharSequence} : "Error in module '$key_': fromState is a List, but not all elements are Strings" + fromState = fromState.collectEntries{[it, it]} + } + + // if fromState is a map, convert to closure + if (fromState instanceof Map) { + // check whether fromstate is a map[string, string] + assert fromState.values().every{it instanceof CharSequence} : "Error in module '$key_': fromState is a Map, but not all values are Strings" + assert fromState.keySet().every{it instanceof CharSequence} : "Error in module '$key_': fromState is a Map, but not all keys are Strings" + def fromStateMap = fromState.clone() + def requiredInputNames = meta.config.allArguments.findAll{it.required && it.direction == "Input"}.collect{it.plainName} + // turn the map into a closure to be used later on + fromState = { it -> + def state = it[1] + assert state instanceof Map : "Error in module '$key_': the state is not a Map" + def data = fromStateMap.collectMany{newkey, origkey -> + // check whether newkey corresponds to a required argument + if (state.containsKey(origkey)) { + [[newkey, state[origkey]]] + } else if (!requiredInputNames.contains(origkey)) { + [] + } else { + throw new Exception("Error in module '$key_': fromState key '$origkey' not found in current state") + } + }.collectEntries() + data + } + } + + return fromState +} + +def _processToState(toState, key_, config_) { + if (toState == null) { + toState = { tup -> tup[1] } + } + + // toState should be a closure, map[string, string], or list[string] + assert toState instanceof Closure || toState instanceof Map || toState instanceof List : + "Error in module '$key_': Expected process argument 'toState' to be a Closure, a Map, or a List. Found: class ${toState.getClass()}" + + // if toState is a List, convert to map + if (toState instanceof List) { + // check whether toState is a list[string] + assert toState.every{it instanceof CharSequence} : "Error in module '$key_': toState is a List, but not all elements are Strings" + toState = toState.collectEntries{[it, it]} + } + + // if toState is a map, convert to closure + if (toState instanceof Map) { + // check whether toState is a map[string, string] + assert toState.values().every{it instanceof CharSequence} : "Error in module '$key_': toState is a Map, but not all values are Strings" + assert toState.keySet().every{it instanceof CharSequence} : "Error in module '$key_': toState is a Map, but not all keys are Strings" + def toStateMap = toState.clone() + def requiredOutputNames = config_.allArguments.findAll{it.required && it.direction == "Output"}.collect{it.plainName} + // turn the map into a closure to be used later on + toState = { it -> + def output = it[1] + def state = it[2] + assert output instanceof Map : "Error in module '$key_': the output is not a Map" + assert state instanceof Map : "Error in module '$key_': the state is not a Map" + def extraEntries = toStateMap.collectMany{newkey, origkey -> + // check whether newkey corresponds to a required argument + if (output.containsKey(origkey)) { + [[newkey, output[origkey]]] + } else if (!requiredOutputNames.contains(origkey)) { + [] + } else { + throw new Exception("Error in module '$key_': toState key '$origkey' not found in current output") + } + }.collectEntries() + state + extraEntries + } + } + + return toState +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/workflowFactory/workflowFactory.nf' +def _debug(workflowArgs, debugKey) { + if (workflowArgs.debug) { + view { "process '${workflowArgs.key}' $debugKey tuple: $it" } + } else { + map { it } + } +} + +// depends on: innerWorkflowFactory +def workflowFactory(Map args, Map defaultWfArgs, Map meta) { + def workflowArgs = processWorkflowArgs(args, defaultWfArgs, meta) + def key_ = workflowArgs["key"] + + workflow workflowInstance { + take: input_ + + main: + def chModified = input_ + | checkUniqueIds([:]) + | _debug(workflowArgs, "input") + | map { tuple -> + tuple = deepClone(tuple) + + if (workflowArgs.map) { + tuple = workflowArgs.map(tuple) + } + if (workflowArgs.mapId) { + tuple[0] = workflowArgs.mapId(tuple[0]) + } + if (workflowArgs.mapData) { + tuple[1] = workflowArgs.mapData(tuple[1]) + } + if (workflowArgs.mapPassthrough) { + tuple = tuple.take(2) + workflowArgs.mapPassthrough(tuple.drop(2)) + } + + // check tuple + assert tuple instanceof List : + "Error in module '${key_}': element in channel should be a tuple [id, data, ...otherargs...]\n" + + " Example: [\"id\", [input: file('foo.txt'), arg: 10]].\n" + + " Expected class: List. Found: tuple.getClass() is ${tuple.getClass()}" + assert tuple.size() >= 2 : + "Error in module '${key_}': expected length of tuple in input channel to be two or greater.\n" + + " Example: [\"id\", [input: file('foo.txt'), arg: 10]].\n" + + " Found: tuple.size() == ${tuple.size()}" + + // check id field + if (tuple[0] instanceof GString) { + tuple[0] = tuple[0].toString() + } + assert tuple[0] instanceof CharSequence : + "Error in module '${key_}': first element of tuple in channel should be a String\n" + + " Example: [\"id\", [input: file('foo.txt'), arg: 10]].\n" + + " Found: ${tuple[0]}" + + // match file to input file + if (workflowArgs.auto.simplifyInput && (tuple[1] instanceof Path || tuple[1] instanceof List)) { + def inputFiles = meta.config.allArguments + .findAll { it.type == "file" && it.direction == "input" } + + assert inputFiles.size() == 1 : + "Error in module '${key_}' id '${tuple[0]}'.\n" + + " Anonymous file inputs are only allowed when the process has exactly one file input.\n" + + " Expected: inputFiles.size() == 1. Found: inputFiles.size() is ${inputFiles.size()}" + + tuple[1] = [[ inputFiles[0].plainName, tuple[1] ]].collectEntries() + } + + // check data field + assert tuple[1] instanceof Map : + "Error in module '${key_}' id '${tuple[0]}': second element of tuple in channel should be a Map\n" + + " Example: [\"id\", [input: file('foo.txt'), arg: 10]].\n" + + " Expected class: Map. Found: tuple[1].getClass() is ${tuple[1].getClass()}" + + // rename keys of data field in tuple + if (workflowArgs.renameKeys) { + assert workflowArgs.renameKeys instanceof Map : + "Error renaming data keys in module '${key_}' id '${tuple[0]}'.\n" + + " Example: renameKeys: ['new_key': 'old_key'].\n" + + " Expected class: Map. Found: renameKeys.getClass() is ${workflowArgs.renameKeys.getClass()}" + assert tuple[1] instanceof Map : + "Error renaming data keys in module '${key_}' id '${tuple[0]}'.\n" + + " Expected class: Map. Found: tuple[1].getClass() is ${tuple[1].getClass()}" + + // TODO: allow renameKeys to be a function? + workflowArgs.renameKeys.each { newKey, oldKey -> + assert newKey instanceof CharSequence : + "Error renaming data keys in module '${key_}' id '${tuple[0]}'.\n" + + " Example: renameKeys: ['new_key': 'old_key'].\n" + + " Expected class of newKey: String. Found: newKey.getClass() is ${newKey.getClass()}" + assert oldKey instanceof CharSequence : + "Error renaming data keys in module '${key_}' id '${tuple[0]}'.\n" + + " Example: renameKeys: ['new_key': 'old_key'].\n" + + " Expected class of oldKey: String. Found: oldKey.getClass() is ${oldKey.getClass()}" + assert tuple[1].containsKey(oldKey) : + "Error renaming data keys in module '${key}' id '${tuple[0]}'.\n" + + " Key '$oldKey' is missing in the data map. tuple[1].keySet() is '${tuple[1].keySet()}'" + tuple[1].put(newKey, tuple[1][oldKey]) + } + tuple[1].keySet().removeAll(workflowArgs.renameKeys.collect{ newKey, oldKey -> oldKey }) + } + tuple + } + + def chModifiedFiltered = workflowArgs.filter ? + chModified | filter{workflowArgs.filter(it)} : + chModified + + def chRun = null + def chPassthrough = null + if (workflowArgs.runIf) { + def runIfBranch = chModifiedFiltered.branch{ tup -> + run: workflowArgs.runIf(tup[0], tup[1]) + passthrough: true + } + chRun = runIfBranch.run + chPassthrough = runIfBranch.passthrough + } else { + chRun = chModifiedFiltered + chPassthrough = Channel.empty() + } + + def chArgs = workflowArgs.fromState ? + chRun | map{ + def new_data = workflowArgs.fromState(it.take(2)) + [it[0], new_data] + } : + chRun | map {tup -> tup.take(2)} + + // fill in defaults + def chArgsWithDefaults = chArgs + | map { tuple -> + def id_ = tuple[0] + def data_ = tuple[1] + + // TODO: could move fromState to here + + // fetch default params from functionality + def defaultArgs = meta.config.allArguments + .findAll { it.containsKey("default") } + .collectEntries { [ it.plainName, it.default ] } + + // fetch overrides in params + def paramArgs = meta.config.allArguments + .findAll { par -> + def argKey = key_ + "__" + par.plainName + params.containsKey(argKey) + } + .collectEntries { [ it.plainName, params[key_ + "__" + it.plainName] ] } + + // fetch overrides in data + def dataArgs = meta.config.allArguments + .findAll { data_.containsKey(it.plainName) } + .collectEntries { [ it.plainName, data_[it.plainName] ] } + + // combine params + def combinedArgs = defaultArgs + paramArgs + workflowArgs.args + dataArgs + + // remove arguments with explicit null values + combinedArgs + .removeAll{_, val -> val == null || val == "viash_no_value" || val == "force_null"} + + combinedArgs = _processInputValues(combinedArgs, meta.config, id_, key_) + + [id_, combinedArgs] + tuple.drop(2) + } + + // TODO: move some of the _meta.join_id wrangling to the safeJoin() function. + def chInitialOutput = chArgsWithDefaults + | _debug(workflowArgs, "processed") + // run workflow + | innerWorkflowFactory(workflowArgs) + // check output tuple + | map { id_, output_ -> + + // see if output map contains metadata + def meta_ = + output_ instanceof Map && output_.containsKey("_meta") ? + output_["_meta"] : + [:] + def join_id = meta_.join_id ?: id_ + + // remove metadata + output_ = output_.findAll{k, v -> k != "_meta"} + + // check value types + output_ = _processOutputValues(output_, meta.config, id_, key_) + + // simplify output if need be + if (workflowArgs.auto.simplifyOutput && output_.size() == 1) { + output_ = output_.values()[0] + } + + [join_id, id_, output_] + } + // | view{"chInitialOutput: ${it.take(3)}"} + + // join the output [prev_id, new_id, output] with the previous state [prev_id, state, ...] + def chNewState = safeJoin(chInitialOutput, chModifiedFiltered, key_) + // input tuple format: [join_id, id, output, prev_state, ...] + // output tuple format: [join_id, id, new_state, ...] + | map{ tup -> + def new_state = workflowArgs.toState(tup.drop(1).take(3)) + tup.take(2) + [new_state] + tup.drop(4) + } + + if (workflowArgs.auto.publish == "state") { + def chPublish = chNewState + // input tuple format: [join_id, id, new_state, ...] + // output tuple format: [join_id, id, new_state] + | map{ tup -> + tup.take(3) + } + + safeJoin(chPublish, chArgsWithDefaults, key_) + // input tuple format: [join_id, id, new_state, orig_state, ...] + // output tuple format: [id, new_state, orig_state] + | map { tup -> + tup.drop(1).take(3) + } + | publishStatesByConfig(key: key_, config: meta.config) + } + + // remove join_id and meta + chReturn = chNewState + | map { tup -> + // input tuple format: [join_id, id, new_state, ...] + // output tuple format: [id, new_state, ...] + tup.drop(1) + } + | _debug(workflowArgs, "output") + | concat(chPassthrough) + + emit: chReturn + } + + def wf = workflowInstance.cloneWithName(key_) + + // add factory function + wf.metaClass.run = { runArgs -> + workflowFactory(runArgs, workflowArgs, meta) + } + // add config to module for later introspection + wf.metaClass.config = meta.config + + return wf +} + +nextflow.enable.dsl=2 + +// START COMPONENT-SPECIFIC CODE + +// create meta object +meta = [ + "resources_dir": moduleDir.toRealPath().normalize(), + "config": processConfig(readJsonBlob('''{ + "name" : "bedtools_bamtofastq", + "namespace" : "bedtools", + "version" : "main", + "authors" : [ + { + "name" : "Theodoro Gasperin Terra Camargo", + "roles" : [ + "author", + "maintainer" + ], + "info" : { + "links" : { + "email" : "theodorogtc@gmail.com", + "github" : "tgaspe", + "linkedin" : "theodoro-gasperin-terra-camargo" + }, + "organizations" : [ + { + "name" : "Data Intuitive", + "href" : "https://www.data-intuitive.com", + "role" : "Bioinformatician" + } + ] + } + } + ], + "argument_groups" : [ + { + "name" : "Inputs", + "arguments" : [ + { + "type" : "file", + "name" : "--input", + "alternatives" : [ + "-i" + ], + "description" : "Input BAM file to be converted to FASTQ.", + "must_exist" : true, + "create_parent" : true, + "required" : true, + "direction" : "input", + "multiple" : false, + "multiple_sep" : ";" + } + ] + }, + { + "name" : "Outputs", + "arguments" : [ + { + "type" : "file", + "name" : "--fastq", + "alternatives" : [ + "-fq" + ], + "description" : "Output FASTQ file.", + "must_exist" : true, + "create_parent" : true, + "required" : true, + "direction" : "output", + "multiple" : false, + "multiple_sep" : ";" + }, + { + "type" : "file", + "name" : "--fastq2", + "alternatives" : [ + "-fq2" + ], + "description" : "FASTQ for second end. Used if BAM contains paired-end data.\nBAM should be sorted by query name is creating paired FASTQ.\n", + "must_exist" : true, + "create_parent" : true, + "required" : false, + "direction" : "output", + "multiple" : false, + "multiple_sep" : ";" + } + ] + }, + { + "name" : "Options", + "arguments" : [ + { + "type" : "boolean_true", + "name" : "--tags", + "description" : "Create FASTQ based on the mate info in the BAM R2 and Q2 tags.\n", + "direction" : "input" + } + ] + } + ], + "resources" : [ + { + "type" : "bash_script", + "path" : "script.sh", + "is_executable" : true + } + ], + "description" : "Conversion tool for extracting FASTQ records from sequence alignments in BAM format.\n", + "test_resources" : [ + { + "type" : "bash_script", + "path" : "test.sh", + "is_executable" : true + }, + { + "type" : "file", + "path" : "test_data" + } + ], + "status" : "enabled", + "requirements" : { + "commands" : [ + "ps" + ] + }, + "keywords" : [ + "Conversion", + "BAM", + "FASTQ" + ], + "license" : "MIT", + "references" : { + "doi" : [ + "10.1093/bioinformatics/btq033" + ] + }, + "links" : { + "repository" : "https://github.com/arq5x/bedtools2", + "homepage" : "https://bedtools.readthedocs.io/en/latest/#", + "documentation" : "https://bedtools.readthedocs.io/en/latest/content/tools/bamtofastq.html", + "issue_tracker" : "https://github.com/arq5x/bedtools2/issues" + }, + "runners" : [ + { + "type" : "executable", + "id" : "executable", + "docker_setup_strategy" : "ifneedbepullelsecachedbuild" + }, + { + "type" : "nextflow", + "id" : "nextflow", + "directives" : { + "tag" : "$id" + }, + "auto" : { + "simplifyInput" : true, + "simplifyOutput" : false, + "transcript" : false, + "publish" : false + }, + "config" : { + "labels" : { + "mem1gb" : "memory = 1000000000.B", + "mem2gb" : "memory = 2000000000.B", + "mem5gb" : "memory = 5000000000.B", + "mem10gb" : "memory = 10000000000.B", + "mem20gb" : "memory = 20000000000.B", + "mem50gb" : "memory = 50000000000.B", + "mem100gb" : "memory = 100000000000.B", + "mem200gb" : "memory = 200000000000.B", + "mem500gb" : "memory = 500000000000.B", + "mem1tb" : "memory = 1000000000000.B", + "mem2tb" : "memory = 2000000000000.B", + "mem5tb" : "memory = 5000000000000.B", + "mem10tb" : "memory = 10000000000000.B", + "mem20tb" : "memory = 20000000000000.B", + "mem50tb" : "memory = 50000000000000.B", + "mem100tb" : "memory = 100000000000000.B", + "mem200tb" : "memory = 200000000000000.B", + "mem500tb" : "memory = 500000000000000.B", + "mem1gib" : "memory = 1073741824.B", + "mem2gib" : "memory = 2147483648.B", + "mem4gib" : "memory = 4294967296.B", + "mem8gib" : "memory = 8589934592.B", + "mem16gib" : "memory = 17179869184.B", + "mem32gib" : "memory = 34359738368.B", + "mem64gib" : "memory = 68719476736.B", + "mem128gib" : "memory = 137438953472.B", + "mem256gib" : "memory = 274877906944.B", + "mem512gib" : "memory = 549755813888.B", + "mem1tib" : "memory = 1099511627776.B", + "mem2tib" : "memory = 2199023255552.B", + "mem4tib" : "memory = 4398046511104.B", + "mem8tib" : "memory = 8796093022208.B", + "mem16tib" : "memory = 17592186044416.B", + "mem32tib" : "memory = 35184372088832.B", + "mem64tib" : "memory = 70368744177664.B", + "mem128tib" : "memory = 140737488355328.B", + "mem256tib" : "memory = 281474976710656.B", + "mem512tib" : "memory = 562949953421312.B", + "cpu1" : "cpus = 1", + "cpu2" : "cpus = 2", + "cpu5" : "cpus = 5", + "cpu10" : "cpus = 10", + "cpu20" : "cpus = 20", + "cpu50" : "cpus = 50", + "cpu100" : "cpus = 100", + "cpu200" : "cpus = 200", + "cpu500" : "cpus = 500", + "cpu1000" : "cpus = 1000" + } + }, + "debug" : false, + "container" : "docker" + } + ], + "engines" : [ + { + "type" : "docker", + "id" : "docker", + "image" : "debian:stable-slim", + "target_registry" : "images.viash-hub.com", + "target_tag" : "main", + "namespace_separator" : "/", + "setup" : [ + { + "type" : "apt", + "packages" : [ + "bedtools", + "procps" + ], + "interactive" : false + }, + { + "type" : "docker", + "run" : [ + "echo \\"bedtools: \\\\\\"$(bedtools --version | sed -n 's/^bedtools //p')\\\\\\"\\" > /var/software_versions.txt\n" + ] + } + ] + }, + { + "type" : "native", + "id" : "native" + } + ], + "build_info" : { + "config" : "/workdir/root/repo/src/bedtools/bedtools_bamtofastq/config.vsh.yaml", + "runner" : "nextflow", + "engine" : "docker|native", + "output" : "target/nextflow/bedtools/bedtools_bamtofastq", + "viash_version" : "0.9.0-RC6", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", + "git_remote" : "https://github.com/viash-hub/biobox" + }, + "package_config" : { + "name" : "biobox", + "version" : "main", + "description" : "A collection of bioinformatics tools for working with sequence data.\n", + "viash_version" : "0.9.0-RC6", + "source" : "src", + "target" : "target", + "config_mods" : [ + ".requirements.commands := ['ps']\n", + ".engines += { type: \\"native\\" }", + ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'", + ".engines[.type == 'docker'].target_tag := 'main'" + ], + "keywords" : [ + "bioinformatics", + "modules", + "sequencing" + ], + "license" : "MIT", + "organization" : "vsh", + "links" : { + "repository" : "https://github.com/viash-hub/biobox", + "issue_tracker" : "https://github.com/viash-hub/biobox/issues" + } + } +}''')) +] + +// resolve dependencies dependencies (if any) + + +// inner workflow +// inner workflow hook +def innerWorkflowFactory(args) { + def rawScript = '''set -e +tempscript=".viash_script.sh" +cat > "$tempscript" << VIASHMAIN +#!/bin/bash + +## VIASH START +# The following code has been auto-generated by Viash. +$( if [ ! -z ${VIASH_PAR_INPUT+x} ]; then echo "${VIASH_PAR_INPUT}" | sed "s#'#'\\"'\\"'#g;s#.*#par_input='&'#" ; else echo "# par_input="; fi ) +$( if [ ! -z ${VIASH_PAR_FASTQ+x} ]; then echo "${VIASH_PAR_FASTQ}" | sed "s#'#'\\"'\\"'#g;s#.*#par_fastq='&'#" ; else echo "# par_fastq="; fi ) +$( if [ ! -z ${VIASH_PAR_FASTQ2+x} ]; then echo "${VIASH_PAR_FASTQ2}" | sed "s#'#'\\"'\\"'#g;s#.*#par_fastq2='&'#" ; else echo "# par_fastq2="; fi ) +$( if [ ! -z ${VIASH_PAR_TAGS+x} ]; then echo "${VIASH_PAR_TAGS}" | sed "s#'#'\\"'\\"'#g;s#.*#par_tags='&'#" ; else echo "# par_tags="; fi ) +$( if [ ! -z ${VIASH_META_NAME+x} ]; then echo "${VIASH_META_NAME}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_name='&'#" ; else echo "# meta_name="; fi ) +$( if [ ! -z ${VIASH_META_FUNCTIONALITY_NAME+x} ]; then echo "${VIASH_META_FUNCTIONALITY_NAME}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_functionality_name='&'#" ; else echo "# meta_functionality_name="; fi ) +$( if [ ! -z ${VIASH_META_RESOURCES_DIR+x} ]; then echo "${VIASH_META_RESOURCES_DIR}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_resources_dir='&'#" ; else echo "# meta_resources_dir="; fi ) +$( if [ ! -z ${VIASH_META_EXECUTABLE+x} ]; then echo "${VIASH_META_EXECUTABLE}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_executable='&'#" ; else echo "# meta_executable="; fi ) +$( if [ ! -z ${VIASH_META_CONFIG+x} ]; then echo "${VIASH_META_CONFIG}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_config='&'#" ; else echo "# meta_config="; fi ) +$( if [ ! -z ${VIASH_META_TEMP_DIR+x} ]; then echo "${VIASH_META_TEMP_DIR}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_temp_dir='&'#" ; else echo "# meta_temp_dir="; fi ) +$( if [ ! -z ${VIASH_META_CPUS+x} ]; then echo "${VIASH_META_CPUS}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_cpus='&'#" ; else echo "# meta_cpus="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_B+x} ]; then echo "${VIASH_META_MEMORY_B}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_b='&'#" ; else echo "# meta_memory_b="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_KB+x} ]; then echo "${VIASH_META_MEMORY_KB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_kb='&'#" ; else echo "# meta_memory_kb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_MB+x} ]; then echo "${VIASH_META_MEMORY_MB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_mb='&'#" ; else echo "# meta_memory_mb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_GB+x} ]; then echo "${VIASH_META_MEMORY_GB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_gb='&'#" ; else echo "# meta_memory_gb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_TB+x} ]; then echo "${VIASH_META_MEMORY_TB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_tb='&'#" ; else echo "# meta_memory_tb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_PB+x} ]; then echo "${VIASH_META_MEMORY_PB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_pb='&'#" ; else echo "# meta_memory_pb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_KIB+x} ]; then echo "${VIASH_META_MEMORY_KIB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_kib='&'#" ; else echo "# meta_memory_kib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_MIB+x} ]; then echo "${VIASH_META_MEMORY_MIB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_mib='&'#" ; else echo "# meta_memory_mib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_GIB+x} ]; then echo "${VIASH_META_MEMORY_GIB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_gib='&'#" ; else echo "# meta_memory_gib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_TIB+x} ]; then echo "${VIASH_META_MEMORY_TIB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_tib='&'#" ; else echo "# meta_memory_tib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_pib='&'#" ; else echo "# meta_memory_pib="; fi ) + +## VIASH END + +# Exit on error +set -eo pipefail + +# Unset parameters +[[ "\\$par_tags" == "false" ]] && unset par_tags + +# Execute bedtools bamtofastq with the provided arguments +bedtools bamtofastq \\\\ + \\${par_tags:+-tags} \\\\ + \\${par_fastq2:+-fq2 "\\$par_fastq2"} \\\\ + -i "\\$par_input" \\\\ + -fq "\\$par_fastq" + +VIASHMAIN +bash "$tempscript" +''' + + return vdsl3WorkflowFactory(args, meta, rawScript) +} + + + +/** + * Generate a workflow for VDSL3 modules. + * + * This function is called by the workflowFactory() function. + * + * Input channel: [id, input_map] + * Output channel: [id, output_map] + * + * Internally, this workflow will convert the input channel + * to a format which the Nextflow module will be able to handle. + */ +def vdsl3WorkflowFactory(Map args, Map meta, String rawScript) { + def key = args["key"] + def processObj = null + + workflow processWf { + take: input_ + main: + + if (processObj == null) { + processObj = _vdsl3ProcessFactory(args, meta, rawScript) + } + + output_ = input_ + | map { tuple -> + def id = tuple[0] + def data_ = tuple[1] + + if (workflow.stubRun) { + // add id if missing + data_ = [id: 'stub'] + data_ + } + + // process input files separately + def inputPaths = meta.config.allArguments + .findAll { it.type == "file" && it.direction == "input" } + .collect { par -> + def val = data_.containsKey(par.plainName) ? data_[par.plainName] : [] + def inputFiles = [] + if (val == null) { + inputFiles = [] + } else if (val instanceof List) { + inputFiles = val + } else if (val instanceof Path) { + inputFiles = [ val ] + } else { + inputFiles = [] + } + if (!workflow.stubRun) { + // throw error when an input file doesn't exist + inputFiles.each{ file -> + assert file.exists() : + "Error in module '${key}' id '${id}' argument '${par.plainName}'.\n" + + " Required input file does not exist.\n" + + " Path: '$file'.\n" + + " Expected input file to exist" + } + } + inputFiles + } + + // remove input files + def argsExclInputFiles = meta.config.allArguments + .findAll { (it.type != "file" || it.direction != "input") && data_.containsKey(it.plainName) } + .collectEntries { par -> + def parName = par.plainName + def val = data_[parName] + if (par.multiple && val instanceof Collection) { + val = val.join(par.multiple_sep) + } + if (par.direction == "output" && par.type == "file") { + val = val.replaceAll('\\$id', id).replaceAll('\\$key', key) + } + [parName, val] + } + + [ id ] + inputPaths + [ argsExclInputFiles, meta.resources_dir ] + } + | processObj + | map { output -> + def outputFiles = meta.config.allArguments + .findAll { it.type == "file" && it.direction == "output" } + .indexed() + .collectEntries{ index, par -> + def out = output[index + 1] + // strip dummy '.exitcode' file from output (see nextflow-io/nextflow#2678) + if (!out instanceof List || out.size() <= 1) { + if (par.multiple) { + out = [] + } else { + assert !par.required : + "Error in module '${key}' id '${output[0]}' argument '${par.plainName}'.\n" + + " Required output file is missing" + out = null + } + } else if (out.size() == 2 && !par.multiple) { + out = out[1] + } else { + out = out.drop(1) + } + [ par.plainName, out ] + } + + // drop null outputs + outputFiles.removeAll{it.value == null} + + [ output[0], outputFiles ] + } + emit: output_ + } + + return processWf +} + +// depends on: session? +def _vdsl3ProcessFactory(Map workflowArgs, Map meta, String rawScript) { + // autodetect process key + def wfKey = workflowArgs["key"] + def procKeyPrefix = "${wfKey}_process" + def scriptMeta = nextflow.script.ScriptMeta.current() + def existing = scriptMeta.getProcessNames().findAll{it.startsWith(procKeyPrefix)} + def numbers = existing.collect{it.replace(procKeyPrefix, "0").toInteger()} + def newNumber = (numbers + [-1]).max() + 1 + + def procKey = newNumber == 0 ? procKeyPrefix : "$procKeyPrefix$newNumber" + + if (newNumber > 0) { + log.warn "Key for module '${wfKey}' is duplicated.\n", + "If you run a component multiple times in the same workflow,\n" + + "it's recommended you set a unique key for every call,\n" + + "for example: ${wfKey}.run(key: \"foo\")." + } + + // subset directives and convert to list of tuples + def drctv = workflowArgs.directives + + // TODO: unit test the two commands below + // convert publish array into tags + def valueToStr = { val -> + // ignore closures + if (val instanceof CharSequence) { + if (!val.matches('^[{].*[}]$')) { + '"' + val + '"' + } else { + val + } + } else if (val instanceof List) { + "[" + val.collect{valueToStr(it)}.join(", ") + "]" + } else if (val instanceof Map) { + "[" + val.collect{k, v -> k + ": " + valueToStr(v)}.join(", ") + "]" + } else { + val.inspect() + } + } + + // multiple entries allowed: label, publishdir + def drctvStrs = drctv.collect { key, value -> + if (key in ["label", "publishDir"]) { + value.collect{ val -> + if (val instanceof Map) { + "\n$key " + val.collect{ k, v -> k + ": " + valueToStr(v) }.join(", ") + } else if (val == null) { + "" + } else { + "\n$key " + valueToStr(val) + } + }.join() + } else if (value instanceof Map) { + "\n$key " + value.collect{ k, v -> k + ": " + valueToStr(v) }.join(", ") + } else { + "\n$key " + valueToStr(value) + } + }.join() + + def inputPaths = meta.config.allArguments + .findAll { it.type == "file" && it.direction == "input" } + .collect { ', path(viash_par_' + it.plainName + ', stageAs: "_viash_par/' + it.plainName + '_?/*")' } + .join() + + def outputPaths = meta.config.allArguments + .findAll { it.type == "file" && it.direction == "output" } + .collect { par -> + // insert dummy into every output (see nextflow-io/nextflow#2678) + if (!par.multiple) { + ', path{[".exitcode", args.' + par.plainName + ']}' + } else { + ', path{[".exitcode"] + args.' + par.plainName + '}' + } + } + .join() + + // TODO: move this functionality somewhere else? + if (workflowArgs.auto.transcript) { + outputPaths = outputPaths + ', path{[".exitcode", ".command*"]}' + } else { + outputPaths = outputPaths + ', path{[".exitcode"]}' + } + + // create dirs for output files (based on BashWrapper.createParentFiles) + def createParentStr = meta.config.allArguments + .findAll { it.type == "file" && it.direction == "output" && it.create_parent } + .collect { par -> + "\${ args.containsKey(\"${par.plainName}\") ? \"mkdir_parent \\\"\" + (args[\"${par.plainName}\"] instanceof String ? args[\"${par.plainName}\"] : args[\"${par.plainName}\"].join('\" \"')) + \"\\\"\" : \"\" }" + } + .join("\n") + + // construct inputFileExports + def inputFileExports = meta.config.allArguments + .findAll { it.type == "file" && it.direction.toLowerCase() == "input" } + .collect { par -> + def viash_par_contents = "(viash_par_${par.plainName} instanceof List ? viash_par_${par.plainName}.join(\"${par.multiple_sep}\") : viash_par_${par.plainName})" + "\n\${viash_par_${par.plainName}.empty ? \"\" : \"export VIASH_PAR_${par.plainName.toUpperCase()}=\\\"\" + ${viash_par_contents} + \"\\\"\"}" + } + + // NOTE: if using docker, use /tmp instead of tmpDir! + def tmpDir = java.nio.file.Paths.get( + System.getenv('NXF_TEMP') ?: + System.getenv('VIASH_TEMP') ?: + System.getenv('VIASH_TMPDIR') ?: + System.getenv('VIASH_TEMPDIR') ?: + System.getenv('VIASH_TMP') ?: + System.getenv('TEMP') ?: + System.getenv('TMPDIR') ?: + System.getenv('TEMPDIR') ?: + System.getenv('TMP') ?: + '/tmp' + ).toAbsolutePath() + + // construct stub + def stub = meta.config.allArguments + .findAll { it.type == "file" && it.direction == "output" } + .collect { par -> + "\${ args.containsKey(\"${par.plainName}\") ? \"touch2 \\\"\" + (args[\"${par.plainName}\"] instanceof String ? args[\"${par.plainName}\"].replace(\"_*\", \"_0\") : args[\"${par.plainName}\"].join('\" \"')) + \"\\\"\" : \"\" }" + } + .join("\n") + + // escape script + def escapedScript = rawScript.replace('\\', '\\\\').replace('$', '\\$').replace('"""', '\\"\\"\\"') + + // publishdir assert + def assertStr = (workflowArgs.auto.publish == true) || workflowArgs.auto.transcript ? + """\nassert task.publishDir.size() > 0: "if auto.publish is true, params.publish_dir needs to be defined.\\n Example: --publish_dir './output/'" """ : + "" + + // generate process string + def procStr = + """nextflow.enable.dsl=2 + | + |process $procKey {$drctvStrs + |input: + | tuple val(id)$inputPaths, val(args), path(resourcesDir, stageAs: ".viash_meta_resources") + |output: + | tuple val("\$id")$outputPaths, optional: true + |stub: + |\"\"\" + |touch2() { mkdir -p "\\\$(dirname "\\\$1")" && touch "\\\$1" ; } + |$stub + |\"\"\" + |script:$assertStr + |def escapeText = { s -> s.toString().replaceAll('([`"])', '\\\\\\\\\$1') } + |def parInject = args + | .findAll{key, value -> value != null} + | .collect{key, value -> "export VIASH_PAR_\${key.toUpperCase()}=\\\"\${escapeText(value)}\\\""} + | .join("\\n") + |\"\"\" + |# meta exports + |export VIASH_META_RESOURCES_DIR="\${resourcesDir}" + |export VIASH_META_TEMP_DIR="${['docker', 'podman', 'charliecloud'].any{ it == workflow.containerEngine } ? '/tmp' : tmpDir}" + |export VIASH_META_NAME="${meta.config.name}" + |# export VIASH_META_EXECUTABLE="\\\$VIASH_META_RESOURCES_DIR/\\\$VIASH_META_NAME" + |export VIASH_META_CONFIG="\\\$VIASH_META_RESOURCES_DIR/.config.vsh.yaml" + |\${task.cpus ? "export VIASH_META_CPUS=\$task.cpus" : "" } + |\${task.memory?.bytes != null ? "export VIASH_META_MEMORY_B=\$task.memory.bytes" : "" } + |if [ ! -z \\\${VIASH_META_MEMORY_B+x} ]; then + | export VIASH_META_MEMORY_KB=\\\$(( (\\\$VIASH_META_MEMORY_B+999) / 1000 )) + | export VIASH_META_MEMORY_MB=\\\$(( (\\\$VIASH_META_MEMORY_KB+999) / 1000 )) + | export VIASH_META_MEMORY_GB=\\\$(( (\\\$VIASH_META_MEMORY_MB+999) / 1000 )) + | export VIASH_META_MEMORY_TB=\\\$(( (\\\$VIASH_META_MEMORY_GB+999) / 1000 )) + | export VIASH_META_MEMORY_PB=\\\$(( (\\\$VIASH_META_MEMORY_TB+999) / 1000 )) + | export VIASH_META_MEMORY_KIB=\\\$(( (\\\$VIASH_META_MEMORY_B+1023) / 1024 )) + | export VIASH_META_MEMORY_MIB=\\\$(( (\\\$VIASH_META_MEMORY_KIB+1023) / 1024 )) + | export VIASH_META_MEMORY_GIB=\\\$(( (\\\$VIASH_META_MEMORY_MIB+1023) / 1024 )) + | export VIASH_META_MEMORY_TIB=\\\$(( (\\\$VIASH_META_MEMORY_GIB+1023) / 1024 )) + | export VIASH_META_MEMORY_PIB=\\\$(( (\\\$VIASH_META_MEMORY_TIB+1023) / 1024 )) + |fi + | + |# meta synonyms + |export VIASH_TEMP="\\\$VIASH_META_TEMP_DIR" + |export TEMP_DIR="\\\$VIASH_META_TEMP_DIR" + | + |# create output dirs if need be + |function mkdir_parent { + | for file in "\\\$@"; do + | mkdir -p "\\\$(dirname "\\\$file")" + | done + |} + |$createParentStr + | + |# argument exports${inputFileExports.join()} + |\$parInject + | + |# process script + |${escapedScript} + |\"\"\" + |} + |""".stripMargin() + + // TODO: print on debug + // if (workflowArgs.debug == true) { + // println("######################\n$procStr\n######################") + // } + + // write process to temp file + def tempFile = java.nio.file.Files.createTempFile("viash-process-${procKey}-", ".nf") + addShutdownHook { java.nio.file.Files.deleteIfExists(tempFile) } + tempFile.text = procStr + + // create process from temp file + def binding = new nextflow.script.ScriptBinding([:]) + def session = nextflow.Nextflow.getSession() + def parser = new nextflow.script.ScriptParser(session) + .setModule(true) + .setBinding(binding) + def moduleScript = parser.runScript(tempFile) + .getScript() + + // register module in meta + def module = new nextflow.script.IncludeDef.Module(name: procKey) + scriptMeta.addModule(moduleScript, module.name, module.alias) + + // retrieve and return process from meta + return scriptMeta.getProcess(procKey) +} + +// defaults +meta["defaults"] = [ + // key to be used to trace the process and determine output names + key: null, + + // fixed arguments to be passed to script + args: [:], + + // default directives + directives: readJsonBlob('''{ + "container" : { + "registry" : "images.viash-hub.com", + "image" : "vsh/biobox/bedtools/bedtools_bamtofastq", + "tag" : "main" + }, + "tag" : "$id" +}'''), + + // auto settings + auto: readJsonBlob('''{ + "simplifyInput" : true, + "simplifyOutput" : false, + "transcript" : false, + "publish" : false +}'''), + + // Apply a map over the incoming tuple + // Example: `{ tup -> [ tup[0], [input: tup[1].output] ] + tup.drop(2) }` + map: null, + + // Apply a map over the ID element of a tuple (i.e. the first element) + // Example: `{ id -> id + "_foo" }` + mapId: null, + + // Apply a map over the data element of a tuple (i.e. the second element) + // Example: `{ data -> [ input: data.output ] }` + mapData: null, + + // Apply a map over the passthrough elements of a tuple (i.e. the tuple excl. the first two elements) + // Example: `{ pt -> pt.drop(1) }` + mapPassthrough: null, + + // Filter the channel + // Example: `{ tup -> tup[0] == "foo" }` + filter: null, + + // Choose whether or not to run the component on the tuple if the condition is true. + // Otherwise, the tuple will be passed through. + // Example: `{ tup -> tup[0] != "skip_this" }` + runIf: null, + + // Rename keys in the data field of the tuple (i.e. the second element) + // Will likely be deprecated in favour of `fromState`. + // Example: `[ "new_key": "old_key" ]` + renameKeys: null, + + // Fetch data from the state and pass it to the module without altering the current state. + // + // `fromState` should be `null`, `List[String]`, `Map[String, String]` or a function. + // + // - If it is `null`, the state will be passed to the module as is. + // - If it is a `List[String]`, the data will be the values of the state at the given keys. + // - If it is a `Map[String, String]`, the data will be the values of the state at the given keys, with the keys renamed according to the map. + // - If it is a function, the tuple (`[id, state]`) in the channel will be passed to the function, and the result will be used as the data. + // + // Example: `{ id, state -> [input: state.fastq_file] }` + // Default: `null` + fromState: null, + + // Determine how the state should be updated after the module has been run. + // + // `toState` should be `null`, `List[String]`, `Map[String, String]` or a function. + // + // - If it is `null`, the state will be replaced with the output of the module. + // - If it is a `List[String]`, the state will be updated with the values of the data at the given keys. + // - If it is a `Map[String, String]`, the state will be updated with the values of the data at the given keys, with the keys renamed according to the map. + // - If it is a function, a tuple (`[id, output, state]`) will be passed to the function, and the result will be used as the new state. + // + // Example: `{ id, output, state -> state + [counts: state.output] }` + // Default: `{ id, output, state -> output }` + toState: null, + + // Whether or not to print debug messages + // Default: `false` + debug: false +] + +// initialise default workflow +meta["workflow"] = workflowFactory([key: meta.config.name], meta.defaults, meta) + +// add workflow to environment +nextflow.script.ScriptMeta.current().addDefinition(meta.workflow) + +// anonymous workflow for running this module as a standalone +workflow { + // add id argument if it's not already in the config + // TODO: deep copy + def newConfig = deepClone(meta.config) + def newParams = deepClone(params) + + def argsContainsId = newConfig.allArguments.any{it.plainName == "id"} + if (!argsContainsId) { + def idArg = [ + 'name': '--id', + 'required': false, + 'type': 'string', + 'description': 'A unique id for every entry.', + 'multiple': false + ] + newConfig.arguments.add(0, idArg) + newConfig = processConfig(newConfig) + } + if (!newParams.containsKey("id")) { + newParams.id = "run" + } + + helpMessage(newConfig) + + channelFromParams(newParams, newConfig) + // make sure id is not in the state if id is not in the args + | map {id, state -> + if (!argsContainsId) { + [id, state.findAll{k, v -> k != "id"}] + } else { + [id, state] + } + } + | meta.workflow.run( + auto: [ publish: "state" ] + ) +} + +// END COMPONENT-SPECIFIC CODE diff --git a/target/nextflow/bedtools/bedtools_bamtofastq/nextflow.config b/target/nextflow/bedtools/bedtools_bamtofastq/nextflow.config new file mode 100644 index 00000000..a5df6603 --- /dev/null +++ b/target/nextflow/bedtools/bedtools_bamtofastq/nextflow.config @@ -0,0 +1,126 @@ +manifest { + name = 'bedtools/bedtools_bamtofastq' + mainScript = 'main.nf' + nextflowVersion = '!>=20.12.1-edge' + version = 'main' + description = 'Conversion tool for extracting FASTQ records from sequence alignments in BAM format.\n' + author = 'Theodoro Gasperin Terra Camargo' +} + +process.container = 'nextflow/bash:latest' + +// detect tempdir +tempDir = java.nio.file.Paths.get( + System.getenv('NXF_TEMP') ?: + System.getenv('VIASH_TEMP') ?: + System.getenv('TEMPDIR') ?: + System.getenv('TMPDIR') ?: + '/tmp' +).toAbsolutePath() + +profiles { + no_publish { + process { + withName: '.*' { + publishDir = [ + enabled: false + ] + } + } + } + mount_temp { + docker.temp = tempDir + podman.temp = tempDir + charliecloud.temp = tempDir + } + docker { + docker.enabled = true + // docker.userEmulation = true + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false + } + singularity { + singularity.enabled = true + singularity.autoMounts = true + docker.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false + } + podman { + podman.enabled = true + docker.enabled = false + singularity.enabled = false + shifter.enabled = false + charliecloud.enabled = false + } + shifter { + shifter.enabled = true + docker.enabled = false + singularity.enabled = false + podman.enabled = false + charliecloud.enabled = false + } + charliecloud { + charliecloud.enabled = true + docker.enabled = false + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + } +} + +process{ + withLabel: mem1gb { memory = 1000000000.B } + withLabel: mem2gb { memory = 2000000000.B } + withLabel: mem5gb { memory = 5000000000.B } + withLabel: mem10gb { memory = 10000000000.B } + withLabel: mem20gb { memory = 20000000000.B } + withLabel: mem50gb { memory = 50000000000.B } + withLabel: mem100gb { memory = 100000000000.B } + withLabel: mem200gb { memory = 200000000000.B } + withLabel: mem500gb { memory = 500000000000.B } + withLabel: mem1tb { memory = 1000000000000.B } + withLabel: mem2tb { memory = 2000000000000.B } + withLabel: mem5tb { memory = 5000000000000.B } + withLabel: mem10tb { memory = 10000000000000.B } + withLabel: mem20tb { memory = 20000000000000.B } + withLabel: mem50tb { memory = 50000000000000.B } + withLabel: mem100tb { memory = 100000000000000.B } + withLabel: mem200tb { memory = 200000000000000.B } + withLabel: mem500tb { memory = 500000000000000.B } + withLabel: mem1gib { memory = 1073741824.B } + withLabel: mem2gib { memory = 2147483648.B } + withLabel: mem4gib { memory = 4294967296.B } + withLabel: mem8gib { memory = 8589934592.B } + withLabel: mem16gib { memory = 17179869184.B } + withLabel: mem32gib { memory = 34359738368.B } + withLabel: mem64gib { memory = 68719476736.B } + withLabel: mem128gib { memory = 137438953472.B } + withLabel: mem256gib { memory = 274877906944.B } + withLabel: mem512gib { memory = 549755813888.B } + withLabel: mem1tib { memory = 1099511627776.B } + withLabel: mem2tib { memory = 2199023255552.B } + withLabel: mem4tib { memory = 4398046511104.B } + withLabel: mem8tib { memory = 8796093022208.B } + withLabel: mem16tib { memory = 17592186044416.B } + withLabel: mem32tib { memory = 35184372088832.B } + withLabel: mem64tib { memory = 70368744177664.B } + withLabel: mem128tib { memory = 140737488355328.B } + withLabel: mem256tib { memory = 281474976710656.B } + withLabel: mem512tib { memory = 562949953421312.B } + withLabel: cpu1 { cpus = 1 } + withLabel: cpu2 { cpus = 2 } + withLabel: cpu5 { cpus = 5 } + withLabel: cpu10 { cpus = 10 } + withLabel: cpu20 { cpus = 20 } + withLabel: cpu50 { cpus = 50 } + withLabel: cpu100 { cpus = 100 } + withLabel: cpu200 { cpus = 200 } + withLabel: cpu500 { cpus = 500 } + withLabel: cpu1000 { cpus = 1000 } +} + + diff --git a/target/nextflow/bedtools/bedtools_bamtofastq/nextflow_schema.json b/target/nextflow/bedtools/bedtools_bamtofastq/nextflow_schema.json new file mode 100644 index 00000000..59912ee3 --- /dev/null +++ b/target/nextflow/bedtools/bedtools_bamtofastq/nextflow_schema.json @@ -0,0 +1,131 @@ +{ +"$schema": "http://json-schema.org/draft-07/schema", +"title": "bedtools_bamtofastq", +"description": "Conversion tool for extracting FASTQ records from sequence alignments in BAM format.\n", +"type": "object", +"definitions": { + + + + "inputs" : { + "title": "Inputs", + "type": "object", + "description": "No description", + "properties": { + + + "input": { + "type": + "string", + "description": "Type: `file`, required. Input BAM file to be converted to FASTQ", + "help_text": "Type: `file`, required. Input BAM file to be converted to FASTQ." + + } + + +} +}, + + + "outputs" : { + "title": "Outputs", + "type": "object", + "description": "No description", + "properties": { + + + "fastq": { + "type": + "string", + "description": "Type: `file`, required, default: `$id.$key.fastq.fastq`. Output FASTQ file", + "help_text": "Type: `file`, required, default: `$id.$key.fastq.fastq`. Output FASTQ file." + , + "default": "$id.$key.fastq.fastq" + } + + + , + "fastq2": { + "type": + "string", + "description": "Type: `file`, default: `$id.$key.fastq2.fastq2`. FASTQ for second end", + "help_text": "Type: `file`, default: `$id.$key.fastq2.fastq2`. FASTQ for second end. Used if BAM contains paired-end data.\nBAM should be sorted by query name is creating paired FASTQ.\n" + , + "default": "$id.$key.fastq2.fastq2" + } + + +} +}, + + + "options" : { + "title": "Options", + "type": "object", + "description": "No description", + "properties": { + + + "tags": { + "type": + "boolean", + "description": "Type: `boolean_true`, default: `false`. Create FASTQ based on the mate info in the BAM R2 and Q2 tags", + "help_text": "Type: `boolean_true`, default: `false`. Create FASTQ based on the mate info in the BAM R2 and Q2 tags.\n" + , + "default": "False" + } + + +} +}, + + + "nextflow input-output arguments" : { + "title": "Nextflow input-output arguments", + "type": "object", + "description": "Input/output parameters for Nextflow itself. Please note that both publishDir and publish_dir are supported but at least one has to be configured.", + "properties": { + + + "publish_dir": { + "type": + "string", + "description": "Type: `string`, required, example: `output/`. Path to an output directory", + "help_text": "Type: `string`, required, example: `output/`. Path to an output directory." + + } + + + , + "param_list": { + "type": + "string", + "description": "Type: `string`, example: `my_params.yaml`. Allows inputting multiple parameter sets to initialise a Nextflow channel", + "help_text": "Type: `string`, example: `my_params.yaml`. Allows inputting multiple parameter sets to initialise a Nextflow channel. A `param_list` can either be a list of maps, a csv file, a json file, a yaml file, or simply a yaml blob.\n\n* A list of maps (as-is) where the keys of each map corresponds to the arguments of the pipeline. Example: in a `nextflow.config` file: `param_list: [ [\u0027id\u0027: \u0027foo\u0027, \u0027input\u0027: \u0027foo.txt\u0027], [\u0027id\u0027: \u0027bar\u0027, \u0027input\u0027: \u0027bar.txt\u0027] ]`.\n* A csv file should have column names which correspond to the different arguments of this pipeline. Example: `--param_list data.csv` with columns `id,input`.\n* A json or a yaml file should be a list of maps, each of which has keys corresponding to the arguments of the pipeline. Example: `--param_list data.json` with contents `[ {\u0027id\u0027: \u0027foo\u0027, \u0027input\u0027: \u0027foo.txt\u0027}, {\u0027id\u0027: \u0027bar\u0027, \u0027input\u0027: \u0027bar.txt\u0027} ]`.\n* A yaml blob can also be passed directly as a string. Example: `--param_list \"[ {\u0027id\u0027: \u0027foo\u0027, \u0027input\u0027: \u0027foo.txt\u0027}, {\u0027id\u0027: \u0027bar\u0027, \u0027input\u0027: \u0027bar.txt\u0027} ]\"`.\n\nWhen passing a csv, json or yaml file, relative path names are relativized to the location of the parameter file. No relativation is performed when `param_list` is a list of maps (as-is) or a yaml blob.", + "hidden": true + + } + + +} +} +}, +"allOf": [ + + { + "$ref": "#/definitions/inputs" + }, + + { + "$ref": "#/definitions/outputs" + }, + + { + "$ref": "#/definitions/options" + }, + + { + "$ref": "#/definitions/nextflow input-output arguments" + } +] +} diff --git a/target/nextflow/bedtools/bedtools_bedtobam/.config.vsh.yaml b/target/nextflow/bedtools/bedtools_bedtobam/.config.vsh.yaml new file mode 100644 index 00000000..14d8fcfd --- /dev/null +++ b/target/nextflow/bedtools/bedtools_bedtobam/.config.vsh.yaml @@ -0,0 +1,240 @@ +name: "bedtools_bedtobam" +namespace: "bedtools" +version: "main" +authors: +- name: "Theodoro Gasperin Terra Camargo" + roles: + - "author" + - "maintainer" + info: + links: + email: "theodorogtc@gmail.com" + github: "tgaspe" + linkedin: "theodoro-gasperin-terra-camargo" + organizations: + - name: "Data Intuitive" + href: "https://www.data-intuitive.com" + role: "Bioinformatician" +argument_groups: +- name: "Inputs" + arguments: + - type: "file" + name: "--input" + alternatives: + - "-i" + description: "Input file (bed/gff/vcf)." + info: null + must_exist: true + create_parent: true + required: true + direction: "input" + multiple: false + multiple_sep: ";" + - type: "file" + name: "--genome" + alternatives: + - "-g" + description: "Input genome file.\nNOTE: This is not a fasta file. This is a two-column\ + \ tab-delimited file\nwhere the first column is the chromosome name and the\ + \ second their sizes.\n" + info: null + must_exist: true + create_parent: true + required: true + direction: "input" + multiple: false + multiple_sep: ";" +- name: "Outputs" + arguments: + - type: "file" + name: "--output" + alternatives: + - "-o" + description: "Output BAM file to be written." + info: null + must_exist: true + create_parent: true + required: false + direction: "output" + multiple: false + multiple_sep: ";" +- name: "Options" + arguments: + - type: "integer" + name: "--map_quality" + alternatives: + - "-mapq" + description: "Set the mappinq quality for the BAM records.\n" + info: null + default: + - 255 + required: false + min: 0 + max: 255 + direction: "input" + multiple: false + multiple_sep: ";" + - type: "boolean_true" + name: "--bed12" + description: "The BED file is in BED12 format. The BAM CIGAR\nstring will reflect\ + \ BED \"blocks\".\n" + info: null + direction: "input" + - type: "boolean_true" + name: "--uncompress_bam" + alternatives: + - "-ubam" + description: "Write uncompressed BAM output. Default writes compressed BAM.\n" + info: null + direction: "input" +resources: +- type: "bash_script" + path: "script.sh" + is_executable: true +description: "Converts feature records (bed/gff/vcf) to BAM format." +test_resources: +- type: "bash_script" + path: "test.sh" + is_executable: true +info: null +status: "enabled" +requirements: + commands: + - "ps" +keywords: +- "Converts" +- "BED" +- "GFF" +- "VCF" +- "BAM" +license: "MIT" +references: + doi: + - "10.1093/bioinformatics/btq033" +links: + repository: "https://github.com/arq5x/bedtools2" + homepage: "https://bedtools.readthedocs.io/en/latest/#" + documentation: "https://bedtools.readthedocs.io/en/latest/content/tools/bedtobam.html" + issue_tracker: "https://github.com/arq5x/bedtools2/issues" +runners: +- type: "executable" + id: "executable" + docker_setup_strategy: "ifneedbepullelsecachedbuild" +- type: "nextflow" + id: "nextflow" + directives: + tag: "$id" + auto: + simplifyInput: true + simplifyOutput: false + transcript: false + publish: false + config: + labels: + mem1gb: "memory = 1000000000.B" + mem2gb: "memory = 2000000000.B" + mem5gb: "memory = 5000000000.B" + mem10gb: "memory = 10000000000.B" + mem20gb: "memory = 20000000000.B" + mem50gb: "memory = 50000000000.B" + mem100gb: "memory = 100000000000.B" + mem200gb: "memory = 200000000000.B" + mem500gb: "memory = 500000000000.B" + mem1tb: "memory = 1000000000000.B" + mem2tb: "memory = 2000000000000.B" + mem5tb: "memory = 5000000000000.B" + mem10tb: "memory = 10000000000000.B" + mem20tb: "memory = 20000000000000.B" + mem50tb: "memory = 50000000000000.B" + mem100tb: "memory = 100000000000000.B" + mem200tb: "memory = 200000000000000.B" + mem500tb: "memory = 500000000000000.B" + mem1gib: "memory = 1073741824.B" + mem2gib: "memory = 2147483648.B" + mem4gib: "memory = 4294967296.B" + mem8gib: "memory = 8589934592.B" + mem16gib: "memory = 17179869184.B" + mem32gib: "memory = 34359738368.B" + mem64gib: "memory = 68719476736.B" + mem128gib: "memory = 137438953472.B" + mem256gib: "memory = 274877906944.B" + mem512gib: "memory = 549755813888.B" + mem1tib: "memory = 1099511627776.B" + mem2tib: "memory = 2199023255552.B" + mem4tib: "memory = 4398046511104.B" + mem8tib: "memory = 8796093022208.B" + mem16tib: "memory = 17592186044416.B" + mem32tib: "memory = 35184372088832.B" + mem64tib: "memory = 70368744177664.B" + mem128tib: "memory = 140737488355328.B" + mem256tib: "memory = 281474976710656.B" + mem512tib: "memory = 562949953421312.B" + cpu1: "cpus = 1" + cpu2: "cpus = 2" + cpu5: "cpus = 5" + cpu10: "cpus = 10" + cpu20: "cpus = 20" + cpu50: "cpus = 50" + cpu100: "cpus = 100" + cpu200: "cpus = 200" + cpu500: "cpus = 500" + cpu1000: "cpus = 1000" + debug: false + container: "docker" +engines: +- type: "docker" + id: "docker" + image: "debian:stable-slim" + target_registry: "images.viash-hub.com" + target_tag: "main" + namespace_separator: "/" + setup: + - type: "apt" + packages: + - "bedtools" + - "procps" + interactive: false + - type: "docker" + run: + - "echo \"bedtools: \\\"$(bedtools --version | sed -n 's/^bedtools //p')\\\"\"\ + \ > /var/software_versions.txt\n" + test_setup: + - type: "apt" + packages: + - "samtools" + interactive: false + entrypoint: [] + cmd: null +- type: "native" + id: "native" +build_info: + config: "src/bedtools/bedtools_bedtobam/config.vsh.yaml" + runner: "nextflow" + engine: "docker|native" + output: "target/nextflow/bedtools/bedtools_bedtobam" + executable: "target/nextflow/bedtools/bedtools_bedtobam/main.nf" + viash_version: "0.9.0-RC6" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" + git_remote: "https://github.com/viash-hub/biobox" +package_config: + name: "biobox" + version: "main" + description: "A collection of bioinformatics tools for working with sequence data.\n" + info: null + viash_version: "0.9.0-RC6" + source: "src" + target: "target" + config_mods: + - ".requirements.commands := ['ps']\n" + - ".engines += { type: \"native\" }" + - ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'" + - ".engines[.type == 'docker'].target_tag := 'main'" + keywords: + - "bioinformatics" + - "modules" + - "sequencing" + license: "MIT" + organization: "vsh" + links: + repository: "https://github.com/viash-hub/biobox" + issue_tracker: "https://github.com/viash-hub/biobox/issues" diff --git a/target/nextflow/bedtools/bedtools_bedtobam/main.nf b/target/nextflow/bedtools/bedtools_bedtobam/main.nf new file mode 100644 index 00000000..51abddf9 --- /dev/null +++ b/target/nextflow/bedtools/bedtools_bedtobam/main.nf @@ -0,0 +1,3620 @@ +// bedtools_bedtobam main +// +// This wrapper script is auto-generated by viash 0.9.0-RC6 and is thus a +// derivative work thereof. This software comes with ABSOLUTELY NO WARRANTY from +// Data Intuitive. +// +// The component may contain files which fall under a different license. The +// authors of this component should specify the license in the header of such +// files, or include a separate license file detailing the licenses of all included +// files. +// +// Component authors: +// * Theodoro Gasperin Terra Camargo (author, maintainer) + +//////////////////////////// +// VDSL3 helper functions // +//////////////////////////// + +// helper file: 'src/main/resources/io/viash/runners/nextflow/arguments/_checkArgumentType.nf' +class UnexpectedArgumentTypeException extends Exception { + String errorIdentifier + String stage + String plainName + String expectedClass + String foundClass + + // ${key ? " in module '$key'" : ""}${id ? " id '$id'" : ""} + UnexpectedArgumentTypeException(String errorIdentifier, String stage, String plainName, String expectedClass, String foundClass) { + super("Error${errorIdentifier ? " $errorIdentifier" : ""}:${stage ? " $stage" : "" } argument '${plainName}' has the wrong type. " + + "Expected type: ${expectedClass}. Found type: ${foundClass}") + this.errorIdentifier = errorIdentifier + this.stage = stage + this.plainName = plainName + this.expectedClass = expectedClass + this.foundClass = foundClass + } +} + +/** + * Checks if the given value is of the expected type. If not, an exception is thrown. + * + * @param stage The stage of the argument (input or output) + * @param par The parameter definition + * @param value The value to check + * @param errorIdentifier The identifier to use in the error message + * @return The value, if it is of the expected type + * @throws UnexpectedArgumentTypeException If the value is not of the expected type +*/ +def _checkArgumentType(String stage, Map par, Object value, String errorIdentifier) { + // expectedClass will only be != null if value is not of the expected type + def expectedClass = null + def foundClass = null + + // todo: split if need be + + if (!par.required && value == null) { + expectedClass = null + } else if (par.multiple) { + if (value !instanceof Collection) { + value = [value] + } + + // split strings + value = value.collectMany{ val -> + if (val instanceof String) { + // collect() to ensure that the result is a List and not simply an array + val.split(par.multiple_sep).collect() + } else { + [val] + } + } + + // process globs + if (par.type == "file" && par.direction == "input") { + value = value.collect{ it instanceof String ? file(it, hidden: true) : it }.flatten() + } + + // check types of elements in list + try { + value = value.collect { listVal -> + _checkArgumentType(stage, par + [multiple: false], listVal, errorIdentifier) + } + } catch (UnexpectedArgumentTypeException e) { + expectedClass = "List[${e.expectedClass}]" + foundClass = "List[${e.foundClass}]" + } + } else if (par.type == "string") { + // cast to string if need be + if (value instanceof GString) { + value = value.toString() + } + expectedClass = value instanceof String ? null : "String" + } else if (par.type == "integer") { + // cast to integer if need be + if (value instanceof String) { + try { + value = value.toInteger() + } catch (NumberFormatException e) { + // do nothing + } + } + if (value instanceof java.math.BigInteger) { + value = value.intValue() + } + expectedClass = value instanceof Integer ? null : "Integer" + } else if (par.type == "long") { + // cast to long if need be + if (value instanceof String) { + try { + value = value.toLong() + } catch (NumberFormatException e) { + // do nothing + } + } + if (value instanceof Integer) { + value = value.toLong() + } + expectedClass = value instanceof Long ? null : "Long" + } else if (par.type == "double") { + // cast to double if need be + if (value instanceof String) { + try { + value = value.toDouble() + } catch (NumberFormatException e) { + // do nothing + } + } + if (value instanceof java.math.BigDecimal) { + value = value.doubleValue() + } + if (value instanceof Float) { + value = value.toDouble() + } + expectedClass = value instanceof Double ? null : "Double" + } else if (par.type == "boolean" | par.type == "boolean_true" | par.type == "boolean_false") { + // cast to boolean if need be + if (value instanceof String) { + def valueLower = value.toLowerCase() + if (valueLower == "true") { + value = true + } else if (valueLower == "false") { + value = false + } + } + expectedClass = value instanceof Boolean ? null : "Boolean" + } else if (par.type == "file" && (par.direction == "input" || stage == "output")) { + // cast to path if need be + if (value instanceof String) { + value = file(value, hidden: true) + } + if (value instanceof File) { + value = value.toPath() + } + expectedClass = value instanceof Path ? null : "Path" + } else if (par.type == "file" && stage == "input" && par.direction == "output") { + // cast to string if need be + if (value instanceof GString) { + value = value.toString() + } + expectedClass = value instanceof String ? null : "String" + } else { + // didn't find a match for par.type + expectedClass = par.type + } + + if (expectedClass != null) { + if (foundClass == null) { + foundClass = value.getClass().getName() + } + throw new UnexpectedArgumentTypeException(errorIdentifier, stage, par.plainName, expectedClass, foundClass) + } + + return value +} +// helper file: 'src/main/resources/io/viash/runners/nextflow/arguments/_processInputValues.nf' +Map _processInputValues(Map inputs, Map config, String id, String key) { + if (!workflow.stubRun) { + config.allArguments.each { arg -> + if (arg.required) { + assert inputs.containsKey(arg.plainName) && inputs.get(arg.plainName) != null : + "Error in module '${key}' id '${id}': required input argument '${arg.plainName}' is missing" + } + } + + inputs = inputs.collectEntries { name, value -> + def par = config.allArguments.find { it.plainName == name && (it.direction == "input" || it.type == "file") } + assert par != null : "Error in module '${key}' id '${id}': '${name}' is not a valid input argument" + + value = _checkArgumentType("input", par, value, "in module '$key' id '$id'") + + [ name, value ] + } + } + return inputs +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/arguments/_processOutputValues.nf' +Map _processOutputValues(Map outputs, Map config, String id, String key) { + if (!workflow.stubRun) { + config.allArguments.each { arg -> + if (arg.direction == "output" && arg.required) { + assert outputs.containsKey(arg.plainName) && outputs.get(arg.plainName) != null : + "Error in module '${key}' id '${id}': required output argument '${arg.plainName}' is missing" + } + } + + outputs = outputs.collectEntries { name, value -> + def par = config.allArguments.find { it.plainName == name && it.direction == "output" } + assert par != null : "Error in module '${key}' id '${id}': '${name}' is not a valid output argument" + + value = _checkArgumentType("output", par, value, "in module '$key' id '$id'") + + [ name, value ] + } + } + return outputs +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/IDChecker.nf' +class IDChecker { + final def items = [] as Set + + @groovy.transform.WithWriteLock + boolean observe(String item) { + if (items.contains(item)) { + return false + } else { + items << item + return true + } + } + + @groovy.transform.WithReadLock + boolean contains(String item) { + return items.contains(item) + } + + @groovy.transform.WithReadLock + Set getItems() { + return items.clone() + } +} +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/_checkUniqueIds.nf' + +/** + * Check if the ids are unique across parameter sets + * + * @param parameterSets a list of parameter sets. + */ +private void _checkUniqueIds(List>> parameterSets) { + def ppIds = parameterSets.collect{it[0]} + assert ppIds.size() == ppIds.unique().size() : "All argument sets should have unique ids. Detected ids: $ppIds" +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/_getChild.nf' + +// helper functions for reading params from file // +def _getChild(parent, child) { + if (child.contains("://") || java.nio.file.Paths.get(child).isAbsolute()) { + child + } else { + def parentAbsolute = java.nio.file.Paths.get(parent).toAbsolutePath().toString() + parentAbsolute.replaceAll('/[^/]*$', "/") + child + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/_parseParamList.nf' +/** + * Figure out the param list format based on the file extension + * + * @param param_list A String containing the path to the parameter list file. + * + * @return A String containing the format of the parameter list file. + */ +def _paramListGuessFormat(param_list) { + if (param_list !instanceof String) { + "asis" + } else if (param_list.endsWith(".csv")) { + "csv" + } else if (param_list.endsWith(".json") || param_list.endsWith(".jsn")) { + "json" + } else if (param_list.endsWith(".yaml") || param_list.endsWith(".yml")) { + "yaml" + } else { + "yaml_blob" + } +} + + +/** + * Read the param list + * + * @param param_list One of the following: + * - A String containing the path to the parameter list file (csv, json or yaml), + * - A yaml blob of a list of maps (yaml_blob), + * - Or a groovy list of maps (asis). + * @param config A Map of the Viash configuration. + * + * @return A List of Maps containing the parameters. + */ +def _parseParamList(param_list, Map config) { + // first determine format by extension + def paramListFormat = _paramListGuessFormat(param_list) + + def paramListPath = (paramListFormat != "asis" && paramListFormat != "yaml_blob") ? + file(param_list, hidden: true) : + null + + // get the correct parser function for the detected params_list format + def paramSets = [] + if (paramListFormat == "asis") { + paramSets = param_list + } else if (paramListFormat == "yaml_blob") { + paramSets = readYamlBlob(param_list) + } else if (paramListFormat == "yaml") { + paramSets = readYaml(paramListPath) + } else if (paramListFormat == "json") { + paramSets = readJson(paramListPath) + } else if (paramListFormat == "csv") { + paramSets = readCsv(paramListPath) + } else { + error "Format of provided --param_list not recognised.\n" + + "Found: '$paramListFormat'.\n" + + "Expected: a csv file, a json file, a yaml file,\n" + + "a yaml blob or a groovy list of maps." + } + + // data checks + assert paramSets instanceof List: "--param_list should contain a list of maps" + for (value in paramSets) { + assert value instanceof Map: "--param_list should contain a list of maps" + } + + // id is argument + def idIsArgument = config.allArguments.any{it.plainName == "id"} + + // Reformat from List to List> by adding the ID as first element of a Tuple2 + paramSets = paramSets.collect({ data -> + def id = data.id + if (!idIsArgument) { + data = data.findAll{k, v -> k != "id"} + } + [id, data] + }) + + // Split parameters with 'multiple: true' + paramSets = paramSets.collect({ id, data -> + data = _splitParams(data, config) + [id, data] + }) + + // The paths of input files inside a param_list file may have been specified relatively to the + // location of the param_list file. These paths must be made absolute. + if (paramListPath) { + paramSets = paramSets.collect({ id, data -> + def new_data = data.collectEntries{ parName, parValue -> + def par = config.allArguments.find{it.plainName == parName} + if (par && par.type == "file" && par.direction == "input") { + if (parValue instanceof Collection) { + parValue = parValue.collectMany{path -> + def x = _resolveSiblingIfNotAbsolute(path, paramListPath) + x instanceof Collection ? x : [x] + } + } else { + parValue = _resolveSiblingIfNotAbsolute(parValue, paramListPath) + } + } + [parName, parValue] + } + [id, new_data] + }) + } + + return paramSets +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/_splitParams.nf' +/** + * Split parameters for arguments that accept multiple values using their separator + * + * @param paramList A Map containing parameters to split. + * @param config A Map of the Viash configuration. This Map can be generated from the config file + * using the readConfig() function. + * + * @return A Map of parameters where the parameter values have been split into a list using + * their seperator. + */ +Map _splitParams(Map parValues, Map config){ + def parsedParamValues = parValues.collectEntries { parName, parValue -> + def parameterSettings = config.allArguments.find({it.plainName == parName}) + + if (!parameterSettings) { + // if argument is not found, do not alter + return [parName, parValue] + } + if (parameterSettings.multiple) { // Check if parameter can accept multiple values + if (parValue instanceof Collection) { + parValue = parValue.collect{it instanceof String ? it.split(parameterSettings.multiple_sep) : it } + } else if (parValue instanceof String) { + parValue = parValue.split(parameterSettings.multiple_sep) + } else if (parValue == null) { + parValue = [] + } else { + parValue = [ parValue ] + } + parValue = parValue.flatten() + } + // For all parameters check if multiple values are only passed for + // arguments that allow it. Quietly simplify lists of length 1. + if (!parameterSettings.multiple && parValue instanceof Collection) { + assert parValue.size() == 1 : + "Error: argument ${parName} has too many values.\n" + + " Expected amount: 1. Found: ${parValue.size()}" + parValue = parValue[0] + } + [parName, parValue] + } + return parsedParamValues +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/channelFromParams.nf' +/** + * Parse nextflow parameters based on settings defined in a viash config. + * Return a list of parameter sets, each parameter set corresponding to + * an event in a nextflow channel. The output from this function can be used + * with Channel.fromList to create a nextflow channel with Vdsl3 formatted + * events. + * + * This function performs: + * - A filtering of the params which can be found in the config file. + * - Process the params_list argument which allows a user to to initialise + * a Vsdl3 channel with multiple parameter sets. Possible formats are + * csv, json, yaml, or simply a yaml_blob. A csv should have column names + * which correspond to the different arguments of this pipeline. A json or a yaml + * file should be a list of maps, each of which has keys corresponding to the + * arguments of the pipeline. A yaml blob can also be passed directly as a parameter. + * When passing a csv, json or yaml, relative path names are relativized to the + * location of the parameter file. + * - Combine the parameter sets into a vdsl3 Channel. + * + * @param params Input parameters. Can optionaly contain a 'param_list' key that + * provides a list of arguments that can be split up into multiple events + * in the output channel possible formats of param_lists are: a csv file, + * json file, a yaml file or a yaml blob. Each parameters set (event) must + * have a unique ID. + * @param config A Map of the Viash configuration. This Map can be generated from the config file + * using the readConfig() function. + * + * @return A list of parameters with the first element of the event being + * the event ID and the second element containing a map of the parsed parameters. + */ + +private List>> _paramsToParamSets(Map params, Map config){ + // todo: fetch key from run args + def key_ = config.name + + /* parse regular parameters (not in param_list) */ + /*************************************************/ + def globalParams = config.allArguments + .findAll { params.containsKey(it.plainName) } + .collectEntries { [ it.plainName, params[it.plainName] ] } + def globalID = params.get("id", null) + + /* process params_list arguments */ + /*********************************/ + def paramList = params.containsKey("param_list") && params.param_list != null ? + params.param_list : [] + // if (paramList instanceof String) { + // paramList = [paramList] + // } + // def paramSets = paramList.collectMany{ _parseParamList(it, config) } + // TODO: be able to process param_list when it is a list of strings + def paramSets = _parseParamList(paramList, config) + if (paramSets.isEmpty()) { + paramSets = [[null, [:]]] + } + + /* combine arguments into channel */ + /**********************************/ + def processedParams = paramSets.indexed().collect{ index, tup -> + // Process ID + def id = tup[0] ?: globalID + + if (workflow.stubRun && !id) { + // if stub run, explicitly add an id if missing + id = "stub${index}" + } + assert id != null: "Each parameter set should have at least an 'id'" + + // Process params + def parValues = globalParams + tup[1] + // // Remove parameters which are null, if the default is also null + // parValues = parValues.collectEntries{paramName, paramValue -> + // parameterSettings = config.functionality.allArguments.find({it.plainName == paramName}) + // if ( paramValue != null || parameterSettings.get("default", null) != null ) { + // [paramName, paramValue] + // } + // } + parValues = parValues.collectEntries { name, value -> + def par = config.allArguments.find { it.plainName == name && (it.direction == "input" || it.type == "file") } + assert par != null : "Error in module '${key_}' id '${id}': '${name}' is not a valid input argument" + + if (par == null) { + return [:] + } + value = _checkArgumentType("input", par, value, "in module '$key_' id '$id'") + + [ name, value ] + } + + [id, parValues] + } + + // Check if ids (first element of each list) is unique + _checkUniqueIds(processedParams) + return processedParams +} + +/** + * Parse nextflow parameters based on settings defined in a viash config + * and return a nextflow channel. + * + * @param params Input parameters. Can optionaly contain a 'param_list' key that + * provides a list of arguments that can be split up into multiple events + * in the output channel possible formats of param_lists are: a csv file, + * json file, a yaml file or a yaml blob. Each parameters set (event) must + * have a unique ID. + * @param config A Map of the Viash configuration. This Map can be generated from the config file + * using the readConfig() function. + * + * @return A nextflow Channel with events. Events are formatted as a tuple that contains + * first contains the ID of the event and as second element holds a parameter map. + * + * + */ +def channelFromParams(Map params, Map config) { + def processedParams = _paramsToParamSets(params, config) + return Channel.fromList(processedParams) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/checkUniqueIds.nf' +def checkUniqueIds(Map args) { + def stopOnError = args.stopOnError == null ? args.stopOnError : true + + def idChecker = new IDChecker() + + return filter { tup -> + if (!idChecker.observe(tup[0])) { + if (stopOnError) { + error "Duplicate id: ${tup[0]}" + } else { + log.warn "Duplicate id: ${tup[0]}, removing duplicate entry" + return false + } + } + return true + } +} +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/preprocessInputs.nf' +// This helper file will be deprecated soon +preprocessInputsDeprecationWarningPrinted = false + +def preprocessInputsDeprecationWarning() { + if (!preprocessInputsDeprecationWarningPrinted) { + preprocessInputsDeprecationWarningPrinted = true + System.err.println("Warning: preprocessInputs() is deprecated and will be removed in Viash 0.9.0.") + } +} + +/** + * Generate a nextflow Workflow that allows processing a channel of + * Vdsl3 formatted events and apply a Viash config to them: + * - Gather default parameters from the Viash config and make + * sure that they are correctly formatted (see applyConfig method). + * - Format the input parameters (also using the applyConfig method). + * - Apply the default parameter to the input parameters. + * - Do some assertions: + * ~ Check if the event IDs in the channel are unique. + * + * The events in the channel are formatted as tuples, with the + * first element of the tuples being a unique id of the parameter set, + * and the second element containg the the parameters themselves. + * Optional extra elements of the tuples will be passed to the output as is. + * + * @param args A map that must contain a 'config' key that points + * to a parsed config (see readConfig()). Optionally, a + * 'key' key can be provided which can be used to create a unique + * name for the workflow process. + * + * @return A workflow that allows processing a channel of Vdsl3 formatted events + * and apply a Viash config to them. + */ +def preprocessInputs(Map args) { + preprocessInputsDeprecationWarning() + + def config = args.config + assert config instanceof Map : + "Error in preprocessInputs: config must be a map. " + + "Expected class: Map. Found: config.getClass() is ${config.getClass()}" + def key_ = args.key ?: config.name + + // Get different parameter types (used throughout this function) + def defaultArgs = config.allArguments + .findAll { it.containsKey("default") } + .collectEntries { [ it.plainName, it.default ] } + + map { tup -> + def id = tup[0] + def data = tup[1] + def passthrough = tup.drop(2) + + def new_data = (defaultArgs + data).collectEntries { name, value -> + def par = config.allArguments.find { it.plainName == name && (it.direction == "input" || it.type == "file") } + + if (par != null) { + value = _checkArgumentType("input", par, value, "in module '$key_' id '$id'") + } + + [ name, value ] + } + + [ id, new_data ] + passthrough + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/runComponents.nf' +/** + * Run a list of components on a stream of data. + * + * @param components: list of Viash VDSL3 modules to run + * @param fromState: a closure, a map or a list of keys to extract from the input data. + * If a closure, it will be called with the id, the data and the component config. + * @param toState: a closure, a map or a list of keys to extract from the output data + * If a closure, it will be called with the id, the output data, the old state and the component config. + * @param filter: filter function to apply to the input. + * It will be called with the id, the data and the component config. + * @param id: id to use for the output data + * If a closure, it will be called with the id, the data and the component config. + * @param auto: auto options to pass to the components + * + * @return: a workflow that runs the components + **/ +def runComponents(Map args) { + log.warn("runComponents is deprecated, use runEach instead") + assert args.components: "runComponents should be passed a list of components to run" + + def components_ = args.components + if (components_ !instanceof List) { + components_ = [ components_ ] + } + assert components_.size() > 0: "pass at least one component to runComponents" + + def fromState_ = args.fromState + def toState_ = args.toState + def filter_ = args.filter + def id_ = args.id + + workflow runComponentsWf { + take: input_ch + main: + + // generate one channel per method + out_chs = components_.collect{ comp_ -> + def comp_config = comp_.config + + def filter_ch = filter_ + ? input_ch | filter{tup -> + filter_(tup[0], tup[1], comp_config) + } + : input_ch + def id_ch = id_ + ? filter_ch | map{tup -> + // def new_id = id_(tup[0], tup[1], comp_config) + def new_id = tup[0] + if (id_ instanceof String) { + new_id = id_ + } else if (id_ instanceof Closure) { + new_id = id_(new_id, tup[1], comp_config) + } + [new_id] + tup.drop(1) + } + : filter_ch + def data_ch = id_ch | map{tup -> + def new_data = tup[1] + if (fromState_ instanceof Map) { + new_data = fromState_.collectEntries{ key0, key1 -> + [key0, new_data[key1]] + } + } else if (fromState_ instanceof List) { + new_data = fromState_.collectEntries{ key -> + [key, new_data[key]] + } + } else if (fromState_ instanceof Closure) { + new_data = fromState_(tup[0], new_data, comp_config) + } + tup.take(1) + [new_data] + tup.drop(1) + } + def out_ch = data_ch + | comp_.run( + auto: (args.auto ?: [:]) + [simplifyInput: false, simplifyOutput: false] + ) + def post_ch = toState_ + ? out_ch | map{tup -> + def output = tup[1] + def old_state = tup[2] + def new_state = null + if (toState_ instanceof Map) { + new_state = old_state + toState_.collectEntries{ key0, key1 -> + [key0, output[key1]] + } + } else if (toState_ instanceof List) { + new_state = old_state + toState_.collectEntries{ key -> + [key, output[key]] + } + } else if (toState_ instanceof Closure) { + new_state = toState_(tup[0], output, old_state, comp_config) + } + [tup[0], new_state] + tup.drop(3) + } + : out_ch + + post_ch + } + + // mix all results + output_ch = + (out_chs.size == 1) + ? out_chs[0] + : out_chs[0].mix(*out_chs.drop(1)) + + emit: output_ch + } + + return runComponentsWf +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/runEach.nf' +/** + * Run a list of components on a stream of data. + * + * @param components: list of Viash VDSL3 modules to run + * @param fromState: a closure, a map or a list of keys to extract from the input data. + * If a closure, it will be called with the id, the data and the component itself. + * @param toState: a closure, a map or a list of keys to extract from the output data + * If a closure, it will be called with the id, the output data, the old state and the component itself. + * @param filter: filter function to apply to the input. + * It will be called with the id, the data and the component itself. + * @param id: id to use for the output data + * If a closure, it will be called with the id, the data and the component itself. + * @param auto: auto options to pass to the components + * + * @return: a workflow that runs the components + **/ +def runEach(Map args) { + assert args.components: "runEach should be passed a list of components to run" + + def components_ = args.components + if (components_ !instanceof List) { + components_ = [ components_ ] + } + assert components_.size() > 0: "pass at least one component to runEach" + + def fromState_ = args.fromState + def toState_ = args.toState + def filter_ = args.filter + def id_ = args.id + + workflow runEachWf { + take: input_ch + main: + + // generate one channel per method + out_chs = components_.collect{ comp_ -> + def filter_ch = filter_ + ? input_ch | filter{tup -> + filter_(tup[0], tup[1], comp_) + } + : input_ch + def id_ch = id_ + ? filter_ch | map{tup -> + def new_id = id_ + if (new_id instanceof Closure) { + new_id = new_id(tup[0], tup[1], comp_) + } + assert new_id instanceof String : "Error in runEach: id should be a String or a Closure that returns a String. Expected: id instanceof String. Found: ${new_id.getClass()}" + [new_id] + tup.drop(1) + } + : filter_ch + def data_ch = id_ch | map{tup -> + def new_data = tup[1] + if (fromState_ instanceof Map) { + new_data = fromState_.collectEntries{ key0, key1 -> + [key0, new_data[key1]] + } + } else if (fromState_ instanceof List) { + new_data = fromState_.collectEntries{ key -> + [key, new_data[key]] + } + } else if (fromState_ instanceof Closure) { + new_data = fromState_(tup[0], new_data, comp_) + } + tup.take(1) + [new_data] + tup.drop(1) + } + def out_ch = data_ch + | comp_.run( + auto: (args.auto ?: [:]) + [simplifyInput: false, simplifyOutput: false] + ) + def post_ch = toState_ + ? out_ch | map{tup -> + def output = tup[1] + def old_state = tup[2] + def new_state = null + if (toState_ instanceof Map) { + new_state = old_state + toState_.collectEntries{ key0, key1 -> + [key0, output[key1]] + } + } else if (toState_ instanceof List) { + new_state = old_state + toState_.collectEntries{ key -> + [key, output[key]] + } + } else if (toState_ instanceof Closure) { + new_state = toState_(tup[0], output, old_state, comp_) + } + [tup[0], new_state] + tup.drop(3) + } + : out_ch + + post_ch + } + + // mix all results + output_ch = + (out_chs.size == 1) + ? out_chs[0] + : out_chs[0].mix(*out_chs.drop(1)) + + emit: output_ch + } + + return runEachWf +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/channel/safeJoin.nf' +/** + * Join sourceChannel to targetChannel + * + * This function joins the sourceChannel to the targetChannel. + * However, each id in the targetChannel must be present in the + * sourceChannel. If _meta.join_id exists in the targetChannel, that is + * used as an id instead. If the id doesn't match any id in the sourceChannel, + * an error is thrown. + */ + +def safeJoin(targetChannel, sourceChannel, key) { + def sourceIDs = new IDChecker() + + def sourceCheck = sourceChannel + | map { tup -> + sourceIDs.observe(tup[0]) + tup + } + def targetCheck = targetChannel + | map { tup -> + def id = tup[0] + + if (!sourceIDs.contains(id)) { + error ( + "Error in module '${key}' when merging output with original state.\n" + + " Reason: output with id '${id}' could not be joined with source channel.\n" + + " If the IDs in the output channel differ from the input channel,\n" + + " please set `tup[1]._meta.join_id to the original ID.\n" + + " Original IDs in input channel: ['${sourceIDs.getItems().join("', '")}'].\n" + + " Unexpected ID in the output channel: '${id}'.\n" + + " Example input event: [\"id\", [input: file(...)]],\n" + + " Example output event: [\"newid\", [output: file(...), _meta: [join_id: \"id\"]]]" + ) + } + // TODO: add link to our documentation on how to fix this + + tup + } + + sourceCheck.cross(targetChannel) + | map{ left, right -> + right + left.drop(1) + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/config/_processArgument.nf' +def _processArgument(arg) { + arg.multiple = arg.multiple != null ? arg.multiple : false + arg.required = arg.required != null ? arg.required : false + arg.direction = arg.direction != null ? arg.direction : "input" + arg.multiple_sep = arg.multiple_sep != null ? arg.multiple_sep : ";" + arg.plainName = arg.name.replaceAll("^-*", "") + + if (arg.type == "file") { + arg.must_exist = arg.must_exist != null ? arg.must_exist : true + arg.create_parent = arg.create_parent != null ? arg.create_parent : true + } + + // add default values to output files which haven't already got a default + if (arg.type == "file" && arg.direction == "output" && arg.default == null) { + def mult = arg.multiple ? "_*" : "" + def extSearch = "" + if (arg.default != null) { + extSearch = arg.default + } else if (arg.example != null) { + extSearch = arg.example + } + if (extSearch instanceof List) { + extSearch = extSearch[0] + } + def extSearchResult = extSearch.find("\\.[^\\.]+\$") + def ext = extSearchResult != null ? extSearchResult : "" + arg.default = "\$id.\$key.${arg.plainName}${mult}${ext}" + if (arg.multiple) { + arg.default = [arg.default] + } + } + + if (!arg.multiple) { + if (arg.default != null && arg.default instanceof List) { + arg.default = arg.default[0] + } + if (arg.example != null && arg.example instanceof List) { + arg.example = arg.example[0] + } + } + + if (arg.type == "boolean_true") { + arg.default = false + } + if (arg.type == "boolean_false") { + arg.default = true + } + + arg +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/config/addGlobalParams.nf' +def addGlobalArguments(config) { + def localConfig = [ + "argument_groups": [ + [ + "name": "Nextflow input-output arguments", + "description": "Input/output parameters for Nextflow itself. Please note that both publishDir and publish_dir are supported but at least one has to be configured.", + "arguments" : [ + [ + 'name': '--publish_dir', + 'required': true, + 'type': 'string', + 'description': 'Path to an output directory.', + 'example': 'output/', + 'multiple': false + ], + [ + 'name': '--param_list', + 'required': false, + 'type': 'string', + 'description': '''Allows inputting multiple parameter sets to initialise a Nextflow channel. A `param_list` can either be a list of maps, a csv file, a json file, a yaml file, or simply a yaml blob. + | + |* A list of maps (as-is) where the keys of each map corresponds to the arguments of the pipeline. Example: in a `nextflow.config` file: `param_list: [ ['id': 'foo', 'input': 'foo.txt'], ['id': 'bar', 'input': 'bar.txt'] ]`. + |* A csv file should have column names which correspond to the different arguments of this pipeline. Example: `--param_list data.csv` with columns `id,input`. + |* A json or a yaml file should be a list of maps, each of which has keys corresponding to the arguments of the pipeline. Example: `--param_list data.json` with contents `[ {'id': 'foo', 'input': 'foo.txt'}, {'id': 'bar', 'input': 'bar.txt'} ]`. + |* A yaml blob can also be passed directly as a string. Example: `--param_list "[ {'id': 'foo', 'input': 'foo.txt'}, {'id': 'bar', 'input': 'bar.txt'} ]"`. + | + |When passing a csv, json or yaml file, relative path names are relativized to the location of the parameter file. No relativation is performed when `param_list` is a list of maps (as-is) or a yaml blob.'''.stripMargin(), + 'example': 'my_params.yaml', + 'multiple': false, + 'hidden': true + ] + // TODO: allow multiple: true in param_list? + // TODO: allow to specify a --param_list_regex to filter the param_list? + // TODO: allow to specify a --param_list_from_state to remap entries in the param_list? + ] + ] + ] + ] + + return processConfig(_mergeMap(config, localConfig)) +} + +def _mergeMap(Map lhs, Map rhs) { + return rhs.inject(lhs.clone()) { map, entry -> + if (map[entry.key] instanceof Map && entry.value instanceof Map) { + map[entry.key] = _mergeMap(map[entry.key], entry.value) + } else if (map[entry.key] instanceof Collection && entry.value instanceof Collection) { + map[entry.key] += entry.value + } else { + map[entry.key] = entry.value + } + return map + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/config/generateHelp.nf' +def _generateArgumentHelp(param) { + // alternatives are not supported + // def names = param.alternatives ::: List(param.name) + + def unnamedProps = [ + ["required parameter", param.required], + ["multiple values allowed", param.multiple], + ["output", param.direction.toLowerCase() == "output"], + ["file must exist", param.type == "file" && param.must_exist] + ].findAll{it[1]}.collect{it[0]} + + def dflt = null + if (param.default != null) { + if (param.default instanceof List) { + dflt = param.default.join(param.multiple_sep != null ? param.multiple_sep : ", ") + } else { + dflt = param.default.toString() + } + } + def example = null + if (param.example != null) { + if (param.example instanceof List) { + example = param.example.join(param.multiple_sep != null ? param.multiple_sep : ", ") + } else { + example = param.example.toString() + } + } + def min = param.min?.toString() + def max = param.max?.toString() + + def escapeChoice = { choice -> + def s1 = choice.replaceAll("\\n", "\\\\n") + def s2 = s1.replaceAll("\"", """\\\"""") + s2.contains(",") || s2 != choice ? "\"" + s2 + "\"" : s2 + } + def choices = param.choices == null ? + null : + "[ " + param.choices.collect{escapeChoice(it.toString())}.join(", ") + " ]" + + def namedPropsStr = [ + ["type", ([param.type] + unnamedProps).join(", ")], + ["default", dflt], + ["example", example], + ["choices", choices], + ["min", min], + ["max", max] + ] + .findAll{it[1]} + .collect{"\n " + it[0] + ": " + it[1].replaceAll("\n", "\\n")} + .join("") + + def descStr = param.description == null ? + "" : + _paragraphWrap("\n" + param.description.trim(), 80 - 8).join("\n ") + + "\n --" + param.plainName + + namedPropsStr + + descStr +} + +// Based on Helper.generateHelp() in Helper.scala +def _generateHelp(config) { + def fun = config + + // PART 1: NAME AND VERSION + def nameStr = fun.name + + (fun.version == null ? "" : " " + fun.version) + + // PART 2: DESCRIPTION + def descrStr = fun.description == null ? + "" : + "\n\n" + _paragraphWrap(fun.description.trim(), 80).join("\n") + + // PART 3: Usage + def usageStr = fun.usage == null ? + "" : + "\n\nUsage:\n" + fun.usage.trim() + + // PART 4: Options + def argGroupStrs = fun.allArgumentGroups.collect{argGroup -> + def name = argGroup.name + def descriptionStr = argGroup.description == null ? + "" : + "\n " + _paragraphWrap(argGroup.description.trim(), 80-4).join("\n ") + "\n" + def arguments = argGroup.arguments.collect{arg -> + arg instanceof String ? fun.allArguments.find{it.plainName == arg} : arg + }.findAll{it != null} + def argumentStrs = arguments.collect{param -> _generateArgumentHelp(param)} + + "\n\n$name:" + + descriptionStr + + argumentStrs.join("\n") + } + + // FINAL: combine + def out = nameStr + + descrStr + + usageStr + + argGroupStrs.join("") + + return out +} + +// based on Format._paragraphWrap +def _paragraphWrap(str, maxLength) { + def outLines = [] + str.split("\n").each{par -> + def words = par.split("\\s").toList() + + def word = null + def line = words.pop() + while(!words.isEmpty()) { + word = words.pop() + if (line.length() + word.length() + 1 <= maxLength) { + line = line + " " + word + } else { + outLines.add(line) + line = word + } + } + if (words.isEmpty()) { + outLines.add(line) + } + } + return outLines +} + +def helpMessage(config) { + if (params.containsKey("help") && params.help) { + def mergedConfig = addGlobalArguments(config) + def helpStr = _generateHelp(mergedConfig) + println(helpStr) + exit 0 + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/config/processConfig.nf' +def processConfig(config) { + // set defaults for arguments + config.arguments = + (config.arguments ?: []).collect{_processArgument(it)} + + // set defaults for argument_group arguments + config.argument_groups = + (config.argument_groups ?: []).collect{grp -> + grp.arguments = (grp.arguments ?: []).collect{_processArgument(it)} + grp + } + + // create combined arguments list + config.allArguments = + config.arguments + + config.argument_groups.collectMany{it.arguments} + + // add missing argument groups (based on Functionality::allArgumentGroups()) + def argGroups = config.argument_groups + if (argGroups.any{it.name.toLowerCase() == "arguments"}) { + argGroups = argGroups.collect{ grp -> + if (grp.name.toLowerCase() == "arguments") { + grp = grp + [ + arguments: grp.arguments + config.arguments + ] + } + grp + } + } else { + argGroups = argGroups + [ + name: "Arguments", + arguments: config.arguments + ] + } + config.allArgumentGroups = argGroups + + config +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/config/readConfig.nf' + +def readConfig(file) { + def config = readYaml(file ?: moduleDir.resolve("config.vsh.yaml")) + processConfig(config) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/_resolveSiblingIfNotAbsolute.nf' +/** + * Resolve a path relative to the current file. + * + * @param str The path to resolve, as a String. + * @param parentPath The path to resolve relative to, as a Path. + * + * @return The path that may have been resovled, as a Path. + */ +def _resolveSiblingIfNotAbsolute(str, parentPath) { + if (str !instanceof String) { + return str + } + if (!_stringIsAbsolutePath(str)) { + return parentPath.resolveSibling(str) + } else { + return file(str, hidden: true) + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/_stringIsAbsolutePath.nf' +/** + * Check whether a path as a string is absolute. + * + * In the past, we tried using `file(., relative: true).isAbsolute()`, + * but the 'relative' option was added in 22.10.0. + * + * @param path The path to check, as a String. + * + * @return Whether the path is absolute, as a boolean. + */ +def _stringIsAbsolutePath(path) { + def _resolve_URL_PROTOCOL = ~/^([a-zA-Z][a-zA-Z0-9]*:)?\\/.+/ + + assert path instanceof String + return _resolve_URL_PROTOCOL.matcher(path).matches() +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/collectTraces.nf' +class CustomTraceObserver implements nextflow.trace.TraceObserver { + List traces + + CustomTraceObserver(List traces) { + this.traces = traces + } + + @Override + void onProcessComplete(nextflow.processor.TaskHandler handler, nextflow.trace.TraceRecord trace) { + def trace2 = trace.store.clone() + trace2.script = null + traces.add(trace2) + } + + @Override + void onProcessCached(nextflow.processor.TaskHandler handler, nextflow.trace.TraceRecord trace) { + def trace2 = trace.store.clone() + trace2.script = null + traces.add(trace2) + } +} + +def collectTraces() { + def traces = Collections.synchronizedList([]) + + // add custom trace observer which stores traces in the traces object + session.observers.add(new CustomTraceObserver(traces)) + + traces +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/deepClone.nf' +/** + * Performs a deep clone of the given object. + * @param x an object + */ +def deepClone(x) { + iterateMap(x, {it instanceof Cloneable ? it.clone() : it}) +} +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/getPublishDir.nf' +def getPublishDir() { + return params.containsKey("publish_dir") ? params.publish_dir : + params.containsKey("publishDir") ? params.publishDir : + null +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/getRootDir.nf' + +// Recurse upwards until we find a '.build.yaml' file +def _findBuildYamlFile(pathPossiblySymlink) { + def path = pathPossiblySymlink.toRealPath() + def child = path.resolve(".build.yaml") + if (java.nio.file.Files.isDirectory(path) && java.nio.file.Files.exists(child)) { + return child + } else { + def parent = path.getParent() + if (parent == null) { + return null + } else { + return _findBuildYamlFile(parent) + } + } +} + +// get the root of the target folder +def getRootDir() { + def dir = _findBuildYamlFile(meta.resources_dir) + assert dir != null: "Could not find .build.yaml in the folder structure" + dir.getParent() +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/iterateMap.nf' +/** + * Recursively apply a function over the leaves of an object. + * @param obj The object to iterate over. + * @param fun The function to apply to each value. + * @return The object with the function applied to each value. + */ +def iterateMap(obj, fun) { + if (obj instanceof List && obj !instanceof String) { + return obj.collect{item -> + iterateMap(item, fun) + } + } else if (obj instanceof Map) { + return obj.collectEntries{key, item -> + [key.toString(), iterateMap(item, fun)] + } + } else { + return fun(obj) + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/functions/niceView.nf' +/** + * A view for printing the event of each channel as a YAML blob. + * This is useful for debugging. + */ +def niceView() { + workflow niceViewWf { + take: input + main: + output = input + | view{toYamlBlob(it)} + emit: output + } + return niceViewWf +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/readCsv.nf' + +def readCsv(file_path) { + def output = [] + def inputFile = file_path !instanceof Path ? file(file_path, hidden: true) : file_path + + // todo: allow escaped quotes in string + // todo: allow single quotes? + def splitRegex = java.util.regex.Pattern.compile(''',(?=(?:[^"]*"[^"]*")*[^"]*$)''') + def removeQuote = java.util.regex.Pattern.compile('''"(.*)"''') + + def br = java.nio.file.Files.newBufferedReader(inputFile) + + def row = -1 + def header = null + while (br.ready() && header == null) { + def line = br.readLine() + row++ + if (!line.startsWith("#")) { + header = splitRegex.split(line, -1).collect{field -> + m = removeQuote.matcher(field) + m.find() ? m.replaceFirst('$1') : field + } + } + } + assert header != null: "CSV file should contain a header" + + while (br.ready()) { + def line = br.readLine() + row++ + if (line == null) { + br.close() + break + } + + if (!line.startsWith("#")) { + def predata = splitRegex.split(line, -1) + def data = predata.collect{field -> + if (field == "") { + return null + } + def m = removeQuote.matcher(field) + if (m.find()) { + return m.replaceFirst('$1') + } else { + return field + } + } + assert header.size() == data.size(): "Row $row should contain the same number as fields as the header" + + def dataMap = [header, data].transpose().collectEntries().findAll{it.value != null} + output.add(dataMap) + } + } + + output +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/readJson.nf' +def readJson(file_path) { + def inputFile = file_path !instanceof Path ? file(file_path, hidden: true) : file_path + def jsonSlurper = new groovy.json.JsonSlurper() + jsonSlurper.parse(inputFile) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/readJsonBlob.nf' +def readJsonBlob(str) { + def jsonSlurper = new groovy.json.JsonSlurper() + jsonSlurper.parseText(str) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/readTaggedYaml.nf' +// Custom constructor to modify how certain objects are parsed from YAML +class CustomConstructor extends org.yaml.snakeyaml.constructor.Constructor { + Path root + + class ConstructPath extends org.yaml.snakeyaml.constructor.AbstractConstruct { + public Object construct(org.yaml.snakeyaml.nodes.Node node) { + String filename = (String) constructScalar(node); + if (root != null) { + return root.resolve(filename); + } + return java.nio.file.Paths.get(filename); + } + } + + CustomConstructor(org.yaml.snakeyaml.LoaderOptions options, Path root) { + super(options) + this.root = root + // Handling !file tag and parse it back to a File type + this.yamlConstructors.put(new org.yaml.snakeyaml.nodes.Tag("!file"), new ConstructPath()) + } +} + +def readTaggedYaml(Path path) { + def options = new org.yaml.snakeyaml.LoaderOptions() + def constructor = new CustomConstructor(options, path.getParent()) + def yaml = new org.yaml.snakeyaml.Yaml(constructor) + return yaml.load(path.text) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/readYaml.nf' +def readYaml(file_path) { + def inputFile = file_path !instanceof Path ? file(file_path, hidden: true) : file_path + def yamlSlurper = new org.yaml.snakeyaml.Yaml() + yamlSlurper.load(inputFile) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/readYamlBlob.nf' +def readYamlBlob(str) { + def yamlSlurper = new org.yaml.snakeyaml.Yaml() + yamlSlurper.load(str) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/toJsonBlob.nf' +String toJsonBlob(data) { + return groovy.json.JsonOutput.toJson(data) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/toTaggedYamlBlob.nf' +// Custom representer to modify how certain objects are represented in YAML +class CustomRepresenter extends org.yaml.snakeyaml.representer.Representer { + Path relativizer + + class RepresentPath implements org.yaml.snakeyaml.representer.Represent { + public String getFileName(Object obj) { + if (obj instanceof File) { + obj = ((File) obj).toPath(); + } + if (obj !instanceof Path) { + throw new IllegalArgumentException("Object: " + obj + " is not a Path or File"); + } + def path = (Path) obj; + + if (relativizer != null) { + return relativizer.relativize(path).toString() + } else { + return path.toString() + } + } + + public org.yaml.snakeyaml.nodes.Node representData(Object data) { + String filename = getFileName(data); + def tag = new org.yaml.snakeyaml.nodes.Tag("!file"); + return representScalar(tag, filename); + } + } + CustomRepresenter(org.yaml.snakeyaml.DumperOptions options, Path relativizer) { + super(options) + this.relativizer = relativizer + this.representers.put(sun.nio.fs.UnixPath, new RepresentPath()) + this.representers.put(Path, new RepresentPath()) + this.representers.put(File, new RepresentPath()) + } +} + +String toTaggedYamlBlob(data) { + return toRelativeTaggedYamlBlob(data, null) +} +String toRelativeTaggedYamlBlob(data, Path relativizer) { + def options = new org.yaml.snakeyaml.DumperOptions() + options.setDefaultFlowStyle(org.yaml.snakeyaml.DumperOptions.FlowStyle.BLOCK) + def representer = new CustomRepresenter(options, relativizer) + def yaml = new org.yaml.snakeyaml.Yaml(representer, options) + return yaml.dump(data) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/toYamlBlob.nf' +String toYamlBlob(data) { + def options = new org.yaml.snakeyaml.DumperOptions() + options.setDefaultFlowStyle(org.yaml.snakeyaml.DumperOptions.FlowStyle.BLOCK) + options.setPrettyFlow(true) + def yaml = new org.yaml.snakeyaml.Yaml(options) + def cleanData = iterateMap(data, { it instanceof Path ? it.toString() : it }) + return yaml.dump(cleanData) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/writeJson.nf' +void writeJson(data, file) { + assert data: "writeJson: data should not be null" + assert file: "writeJson: file should not be null" + file.write(toJsonBlob(data)) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/readwrite/writeYaml.nf' +void writeYaml(data, file) { + assert data: "writeYaml: data should not be null" + assert file: "writeYaml: file should not be null" + file.write(toYamlBlob(data)) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/states/findStates.nf' +def findStates(Map params, Map config) { + def auto_config = deepClone(config) + def auto_params = deepClone(params) + + auto_config = auto_config.clone() + // override arguments + auto_config.argument_groups = [] + auto_config.arguments = [ + [ + type: "string", + name: "--id", + description: "A dummy identifier", + required: false + ], + [ + type: "file", + name: "--input_states", + example: "/path/to/input/directory/**/state.yaml", + description: "Path to input directory containing the datasets to be integrated.", + required: true, + multiple: true, + multiple_sep: ";" + ], + [ + type: "string", + name: "--filter", + example: "foo/.*/state.yaml", + description: "Regex to filter state files by path.", + required: false + ], + // to do: make this a yaml blob? + [ + type: "string", + name: "--rename_keys", + example: ["newKey1:oldKey1", "newKey2:oldKey2"], + description: "Rename keys in the detected input files. This is useful if the input files do not match the set of input arguments of the workflow.", + required: false, + multiple: true, + multiple_sep: ";" + ], + [ + type: "string", + name: "--settings", + example: '{"output_dataset": "dataset.h5ad", "k": 10}', + description: "Global arguments as a JSON glob to be passed to all components.", + required: false + ] + ] + if (!(auto_params.containsKey("id"))) { + auto_params["id"] = "auto" + } + + // run auto config through processConfig once more + auto_config = processConfig(auto_config) + + workflow findStatesWf { + helpMessage(auto_config) + + output_ch = + channelFromParams(auto_params, auto_config) + | flatMap { autoId, args -> + + def globalSettings = args.settings ? readYamlBlob(args.settings) : [:] + + // look for state files in input dir + def stateFiles = args.input_states + + // filter state files by regex + if (args.filter) { + stateFiles = stateFiles.findAll{ stateFile -> + def stateFileStr = stateFile.toString() + def matcher = stateFileStr =~ args.filter + matcher.matches()} + } + + // read in states + def states = stateFiles.collect { stateFile -> + def state_ = readTaggedYaml(stateFile) + [state_.id, state_] + } + + // construct renameMap + if (args.rename_keys) { + def renameMap = args.rename_keys.collectEntries{renameString -> + def split = renameString.split(";") + assert split.size() == 2: "Argument 'rename_keys' should be of the form 'newKey:oldKey,newKey:oldKey'" + split + } + + // rename keys in state, only let states through which have all keys + // also add global settings + states = states.collectMany{id, state -> + def newState = [:] + + for (key in renameMap.keySet()) { + def origKey = renameMap[key] + if (!(state.containsKey(origKey))) { + return [] + } + newState[key] = state[origKey] + } + + [[id, globalSettings + newState]] + } + } + + states + } + emit: + output_ch + } + + return findStatesWf +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/states/joinStates.nf' +def joinStates(Closure apply_) { + workflow joinStatesWf { + take: input_ch + main: + output_ch = input_ch + | toSortedList + | filter{ it.size() > 0 } + | map{ tups -> + def ids = tups.collect{it[0]} + def states = tups.collect{it[1]} + apply_(ids, states) + } + + emit: output_ch + } + return joinStatesWf +} +// helper file: 'src/main/resources/io/viash/runners/nextflow/states/publishStates.nf' +def collectFiles(obj) { + if (obj instanceof java.io.File || obj instanceof Path) { + return [obj] + } else if (obj instanceof List && obj !instanceof String) { + return obj.collectMany{item -> + collectFiles(item) + } + } else if (obj instanceof Map) { + return obj.collectMany{key, item -> + collectFiles(item) + } + } else { + return [] + } +} + +/** + * Recurse through a state and collect all input files and their target output filenames. + * @param obj The state to recurse through. + * @param prefix The prefix to prepend to the output filenames. + */ +def collectInputOutputPaths(obj, prefix) { + if (obj instanceof File || obj instanceof Path) { + def path = obj instanceof Path ? obj : obj.toPath() + def ext = path.getFileName().toString().find("\\.[^\\.]+\$") ?: "" + def newFilename = prefix + ext + return [[obj, newFilename]] + } else if (obj instanceof List && obj !instanceof String) { + return obj.withIndex().collectMany{item, ix -> + collectInputOutputPaths(item, prefix + "_" + ix) + } + } else if (obj instanceof Map) { + return obj.collectMany{key, item -> + collectInputOutputPaths(item, prefix + "." + key) + } + } else { + return [] + } +} + +def publishStates(Map args) { + def key_ = args.get("key") + def yamlTemplate_ = args.get("output_state", args.get("outputState", '$id.$key.state.yaml')) + + assert key_ != null : "publishStates: key must be specified" + + workflow publishStatesWf { + take: input_ch + main: + input_ch + | map { tup -> + def id_ = tup[0] + def state_ = tup[1] + + // the input files and the target output filenames + def inputoutputFilenames_ = collectInputOutputPaths(state_, id_ + "." + key_).transpose() + def inputFiles_ = inputoutputFilenames_[0] + def outputFilenames_ = inputoutputFilenames_[1] + + def yamlFilename = yamlTemplate_ + .replaceAll('\\$id', id_) + .replaceAll('\\$key', key_) + + // TODO: do the pathnames in state_ match up with the outputFilenames_? + + // convert state to yaml blob + def yamlBlob_ = toRelativeTaggedYamlBlob([id: id_] + state_, java.nio.file.Paths.get(yamlFilename)) + + [id_, yamlBlob_, yamlFilename, inputFiles_, outputFilenames_] + } + | publishStatesProc + emit: input_ch + } + return publishStatesWf +} +process publishStatesProc { + // todo: check publishpath? + publishDir path: "${getPublishDir()}/", mode: "copy" + tag "$id" + input: + tuple val(id), val(yamlBlob), val(yamlFile), path(inputFiles, stageAs: "_inputfile?/*"), val(outputFiles) + output: + tuple val(id), path{[yamlFile] + outputFiles} + script: + def copyCommands = [ + inputFiles instanceof List ? inputFiles : [inputFiles], + outputFiles instanceof List ? outputFiles : [outputFiles] + ] + .transpose() + .collectMany{infile, outfile -> + if (infile.toString() != outfile.toString()) { + [ + "[ -d \"\$(dirname '${outfile.toString()}')\" ] || mkdir -p \"\$(dirname '${outfile.toString()}')\"", + "cp -r '${infile.toString()}' '${outfile.toString()}'" + ] + } else { + // no need to copy if infile is the same as outfile + [] + } + } + """ +mkdir -p "\$(dirname '${yamlFile}')" +echo "Storing state as yaml" +echo '${yamlBlob}' > '${yamlFile}' +echo "Copying output files to destination folder" +${copyCommands.join("\n ")} +""" +} + + +// this assumes that the state contains no other values other than those specified in the config +def publishStatesByConfig(Map args) { + def config = args.get("config") + assert config != null : "publishStatesByConfig: config must be specified" + + def key_ = args.get("key", config.name) + assert key_ != null : "publishStatesByConfig: key must be specified" + + workflow publishStatesSimpleWf { + take: input_ch + main: + input_ch + | map { tup -> + def id_ = tup[0] + def state_ = tup[1] // e.g. [output: new File("myoutput.h5ad"), k: 10] + def origState_ = tup[2] // e.g. [output: '$id.$key.foo.h5ad'] + + // TODO: allow overriding the state.yaml template + // TODO TODO: if auto.publish == "state", add output_state as an argument + def yamlTemplate = params.containsKey("output_state") ? params.output_state : '$id.$key.state.yaml' + def yamlFilename = yamlTemplate + .replaceAll('\\$id', id_) + .replaceAll('\\$key', key_) + def yamlDir = java.nio.file.Paths.get(yamlFilename).getParent() + + // the processed state is a list of [key, value, inputPath, outputFilename] tuples, where + // - key is a String + // - value is any object that can be serialized to a Yaml (so a String/Integer/Long/Double/Boolean, a List, a Map, or a Path) + // - inputPath is a List[Path] + // - outputFilename is a List[String] + // - (key, value) are the tuples that will be saved to the state.yaml file + // - (inputPath, outputFilename) are the files that will be copied from src to dest (relative to the state.yaml) + def processedState = + config.allArguments + .findAll { it.direction == "output" } + .collectMany { par -> + def plainName_ = par.plainName + // if the state does not contain the key, it's an + // optional argument for which the component did + // not generate any output + if (!state_.containsKey(plainName_)) { + return [] + } + def value = state_[plainName_] + // if the parameter is not a file, it should be stored + // in the state as-is, but is not something that needs + // to be copied from the source path to the dest path + if (par.type != "file") { + return [[key: plainName_, value: value, inputPath: [], outputFilename: []]] + } + // if the orig state does not contain this filename, + // it's an optional argument for which the user specified + // that it should not be returned as a state + if (!origState_.containsKey(plainName_)) { + return [] + } + def filenameTemplate = origState_[plainName_] + // if the pararameter is multiple: true, fetch the template + if (par.multiple && filenameTemplate instanceof List) { + filenameTemplate = filenameTemplate[0] + } + // instantiate the template + def filename = filenameTemplate + .replaceAll('\\$id', id_) + .replaceAll('\\$key', key_) + if (par.multiple) { + // if the parameter is multiple: true, the filename + // should contain a wildcard '*' that is replaced with + // the index of the file + assert filename.contains("*") : "Module '${key_}' id '${id_}': Multiple output files specified, but no wildcard '*' in the filename: ${filename}" + def outputPerFile = value.withIndex().collect{ val, ix -> + def filename_ix = filename.replace("*", ix.toString()) + def value_ = java.nio.file.Paths.get(filename_ix) + // if id contains a slash + if (yamlDir != null) { + value_ = yamlDir.relativize(value_) + } + def inputPath = val instanceof File ? val.toPath() : val + [value: value_, inputPath: inputPath, outputFilename: filename_ix] + } + def transposedOutputs = ["value", "inputPath", "outputFilename"].collectEntries{ key -> + [key, outputPerFile.collect{dic -> dic[key]}] + } + return [[key: plainName_] + transposedOutputs] + } else { + def value_ = java.nio.file.Paths.get(filename) + // if id contains a slash + if (yamlDir != null) { + value_ = yamlDir.relativize(value_) + } + def inputPath = value instanceof File ? value.toPath() : value + return [[key: plainName_, value: value_, inputPath: [inputPath], outputFilename: [filename]]] + } + } + + def updatedState_ = processedState.collectEntries{[it.key, it.value]} + def inputPaths = processedState.collectMany{it.inputPath} + def outputFilenames = processedState.collectMany{it.outputFilename} + + // convert state to yaml blob + def yamlBlob_ = toTaggedYamlBlob([id: id_] + updatedState_) + + [id_, yamlBlob_, yamlFilename, inputPaths, outputFilenames] + } + | publishStatesProc + emit: input_ch + } + return publishStatesSimpleWf +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/states/setState.nf' +def setState(fun) { + assert fun instanceof Closure || fun instanceof Map || fun instanceof List : + "Error in setState: Expected process argument to be a Closure, a Map, or a List. Found: class ${fun.getClass()}" + + // if fun is a List, convert to map + if (fun instanceof List) { + // check whether fun is a list[string] + assert fun.every{it instanceof CharSequence} : "Error in setState: argument is a List, but not all elements are Strings" + fun = fun.collectEntries{[it, it]} + } + + // if fun is a map, convert to closure + if (fun instanceof Map) { + // check whether fun is a map[string, string] + assert fun.values().every{it instanceof CharSequence} : "Error in setState: argument is a Map, but not all values are Strings" + assert fun.keySet().every{it instanceof CharSequence} : "Error in setState: argument is a Map, but not all keys are Strings" + def funMap = fun.clone() + // turn the map into a closure to be used later on + fun = { id_, state_ -> + assert state_ instanceof Map : "Error in setState: the state is not a Map" + funMap.collectMany{newkey, origkey -> + if (state_.containsKey(origkey)) { + [[newkey, state_[origkey]]] + } else { + [] + } + }.collectEntries() + } + } + + map { tup -> + def id = tup[0] + def state = tup[1] + def unfilteredState = fun(id, state) + def newState = unfilteredState.findAll{key, val -> val != null} + [id, newState] + tup.drop(2) + } +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/workflowFactory/processAuto.nf' +// TODO: unit test processAuto +def processAuto(Map auto) { + // remove null values + auto = auto.findAll{k, v -> v != null} + + // check for unexpected keys + def expectedKeys = ["simplifyInput", "simplifyOutput", "transcript", "publish"] + def unexpectedKeys = auto.keySet() - expectedKeys + assert unexpectedKeys.isEmpty(), "unexpected keys in auto: '${unexpectedKeys.join("', '")}'" + + // check auto.simplifyInput + assert auto.simplifyInput instanceof Boolean, "auto.simplifyInput must be a boolean" + + // check auto.simplifyOutput + assert auto.simplifyOutput instanceof Boolean, "auto.simplifyOutput must be a boolean" + + // check auto.transcript + assert auto.transcript instanceof Boolean, "auto.transcript must be a boolean" + + // check auto.publish + assert auto.publish instanceof Boolean || auto.publish == "state", "auto.publish must be a boolean or 'state'" + + return auto.subMap(expectedKeys) +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/workflowFactory/processDirectives.nf' +def assertMapKeys(map, expectedKeys, requiredKeys, mapName) { + assert map instanceof Map : "Expected argument '$mapName' to be a Map. Found: class ${map.getClass()}" + map.forEach { key, val -> + assert key in expectedKeys : "Unexpected key '$key' in ${mapName ? mapName + " " : ""}map" + } + requiredKeys.forEach { requiredKey -> + assert map.containsKey(requiredKey) : "Missing required key '$key' in ${mapName ? mapName + " " : ""}map" + } +} + +// TODO: unit test processDirectives +def processDirectives(Map drctv) { + // remove null values + drctv = drctv.findAll{k, v -> v != null} + + // check for unexpected keys + def expectedKeys = [ + "accelerator", "afterScript", "beforeScript", "cache", "conda", "container", "containerOptions", "cpus", "disk", "echo", "errorStrategy", "executor", "machineType", "maxErrors", "maxForks", "maxRetries", "memory", "module", "penv", "pod", "publishDir", "queue", "label", "scratch", "storeDir", "stageInMode", "stageOutMode", "tag", "time" + ] + def unexpectedKeys = drctv.keySet() - expectedKeys + assert unexpectedKeys.isEmpty() : "Unexpected keys in process directive: '${unexpectedKeys.join("', '")}'" + + /* DIRECTIVE accelerator + accepted examples: + - [ limit: 4, type: "nvidia-tesla-k80" ] + */ + if (drctv.containsKey("accelerator")) { + assertMapKeys(drctv["accelerator"], ["type", "limit", "request", "runtime"], [], "accelerator") + } + + /* DIRECTIVE afterScript + accepted examples: + - "source /cluster/bin/cleanup" + */ + if (drctv.containsKey("afterScript")) { + assert drctv["afterScript"] instanceof CharSequence + } + + /* DIRECTIVE beforeScript + accepted examples: + - "source /cluster/bin/setup" + */ + if (drctv.containsKey("beforeScript")) { + assert drctv["beforeScript"] instanceof CharSequence + } + + /* DIRECTIVE cache + accepted examples: + - true + - false + - "deep" + - "lenient" + */ + if (drctv.containsKey("cache")) { + assert drctv["cache"] instanceof CharSequence || drctv["cache"] instanceof Boolean + if (drctv["cache"] instanceof CharSequence) { + assert drctv["cache"] in ["deep", "lenient"] : "Unexpected value for cache" + } + } + + /* DIRECTIVE conda + accepted examples: + - "bwa=0.7.15" + - "bwa=0.7.15 fastqc=0.11.5" + - ["bwa=0.7.15", "fastqc=0.11.5"] + */ + if (drctv.containsKey("conda")) { + if (drctv["conda"] instanceof List) { + drctv["conda"] = drctv["conda"].join(" ") + } + assert drctv["conda"] instanceof CharSequence + } + + /* DIRECTIVE container + accepted examples: + - "foo/bar:tag" + - [ registry: "reg", image: "im", tag: "ta" ] + is transformed to "reg/im:ta" + - [ image: "im" ] + is transformed to "im:latest" + */ + if (drctv.containsKey("container")) { + assert drctv["container"] instanceof Map || drctv["container"] instanceof CharSequence + if (drctv["container"] instanceof Map) { + def m = drctv["container"] + assertMapKeys(m, [ "registry", "image", "tag" ], ["image"], "container") + def part1 = + System.getenv('OVERRIDE_CONTAINER_REGISTRY') ? System.getenv('OVERRIDE_CONTAINER_REGISTRY') + "/" : + params.containsKey("override_container_registry") ? params["override_container_registry"] + "/" : // todo: remove? + m.registry ? m.registry + "/" : + "" + def part2 = m.image + def part3 = m.tag ? ":" + m.tag : ":latest" + drctv["container"] = part1 + part2 + part3 + } + } + + /* DIRECTIVE containerOptions + accepted examples: + - "--foo bar" + - ["--foo bar", "-f b"] + */ + if (drctv.containsKey("containerOptions")) { + if (drctv["containerOptions"] instanceof List) { + drctv["containerOptions"] = drctv["containerOptions"].join(" ") + } + assert drctv["containerOptions"] instanceof CharSequence + } + + /* DIRECTIVE cpus + accepted examples: + - 1 + - 10 + */ + if (drctv.containsKey("cpus")) { + assert drctv["cpus"] instanceof Integer + } + + /* DIRECTIVE disk + accepted examples: + - "1 GB" + - "2TB" + - "3.2KB" + - "10.B" + */ + if (drctv.containsKey("disk")) { + assert drctv["disk"] instanceof CharSequence + // assert drctv["disk"].matches("[0-9]+(\\.[0-9]*)? *[KMGTPEZY]?B") + // ^ does not allow closures + } + + /* DIRECTIVE echo + accepted examples: + - true + - false + */ + if (drctv.containsKey("echo")) { + assert drctv["echo"] instanceof Boolean + } + + /* DIRECTIVE errorStrategy + accepted examples: + - "terminate" + - "finish" + */ + if (drctv.containsKey("errorStrategy")) { + assert drctv["errorStrategy"] instanceof CharSequence + assert drctv["errorStrategy"] in ["terminate", "finish", "ignore", "retry"] : "Unexpected value for errorStrategy" + } + + /* DIRECTIVE executor + accepted examples: + - "local" + - "sge" + */ + if (drctv.containsKey("executor")) { + assert drctv["executor"] instanceof CharSequence + assert drctv["executor"] in ["local", "sge", "uge", "lsf", "slurm", "pbs", "pbspro", "moab", "condor", "nqsii", "ignite", "k8s", "awsbatch", "google-pipelines"] : "Unexpected value for executor" + } + + /* DIRECTIVE machineType + accepted examples: + - "n1-highmem-8" + */ + if (drctv.containsKey("machineType")) { + assert drctv["machineType"] instanceof CharSequence + } + + /* DIRECTIVE maxErrors + accepted examples: + - 1 + - 3 + */ + if (drctv.containsKey("maxErrors")) { + assert drctv["maxErrors"] instanceof Integer + } + + /* DIRECTIVE maxForks + accepted examples: + - 1 + - 3 + */ + if (drctv.containsKey("maxForks")) { + assert drctv["maxForks"] instanceof Integer + } + + /* DIRECTIVE maxRetries + accepted examples: + - 1 + - 3 + */ + if (drctv.containsKey("maxRetries")) { + assert drctv["maxRetries"] instanceof Integer + } + + /* DIRECTIVE memory + accepted examples: + - "1 GB" + - "2TB" + - "3.2KB" + - "10.B" + */ + if (drctv.containsKey("memory")) { + assert drctv["memory"] instanceof CharSequence + // assert drctv["memory"].matches("[0-9]+(\\.[0-9]*)? *[KMGTPEZY]?B") + // ^ does not allow closures + } + + /* DIRECTIVE module + accepted examples: + - "ncbi-blast/2.2.27" + - "ncbi-blast/2.2.27:t_coffee/10.0" + - ["ncbi-blast/2.2.27", "t_coffee/10.0"] + */ + if (drctv.containsKey("module")) { + if (drctv["module"] instanceof List) { + drctv["module"] = drctv["module"].join(":") + } + assert drctv["module"] instanceof CharSequence + } + + /* DIRECTIVE penv + accepted examples: + - "smp" + */ + if (drctv.containsKey("penv")) { + assert drctv["penv"] instanceof CharSequence + } + + /* DIRECTIVE pod + accepted examples: + - [ label: "key", value: "val" ] + - [ annotation: "key", value: "val" ] + - [ env: "key", value: "val" ] + - [ [label: "l", value: "v"], [env: "e", value: "v"]] + */ + if (drctv.containsKey("pod")) { + if (drctv["pod"] instanceof Map) { + drctv["pod"] = [ drctv["pod"] ] + } + assert drctv["pod"] instanceof List + drctv["pod"].forEach { pod -> + assert pod instanceof Map + // TODO: should more checks be added? + // See https://www.nextflow.io/docs/latest/process.html?highlight=directives#pod + // e.g. does it contain 'label' and 'value', or 'annotation' and 'value', or ...? + } + } + + /* DIRECTIVE publishDir + accepted examples: + - [] + - [ [ path: "foo", enabled: true ], [ path: "bar", enabled: false ] ] + - "/path/to/dir" + is transformed to [[ path: "/path/to/dir" ]] + - [ path: "/path/to/dir", mode: "cache" ] + is transformed to [[ path: "/path/to/dir", mode: "cache" ]] + */ + // TODO: should we also look at params["publishDir"]? + if (drctv.containsKey("publishDir")) { + def pblsh = drctv["publishDir"] + + // check different options + assert pblsh instanceof List || pblsh instanceof Map || pblsh instanceof CharSequence + + // turn into list if not already so + // for some reason, 'if (!pblsh instanceof List) pblsh = [ pblsh ]' doesn't work. + pblsh = pblsh instanceof List ? pblsh : [ pblsh ] + + // check elements of publishDir + pblsh = pblsh.collect{ elem -> + // turn into map if not already so + elem = elem instanceof CharSequence ? [ path: elem ] : elem + + // check types and keys + assert elem instanceof Map : "Expected publish argument '$elem' to be a String or a Map. Found: class ${elem.getClass()}" + assertMapKeys(elem, [ "path", "mode", "overwrite", "pattern", "saveAs", "enabled" ], ["path"], "publishDir") + + // check elements in map + assert elem.containsKey("path") + assert elem["path"] instanceof CharSequence + if (elem.containsKey("mode")) { + assert elem["mode"] instanceof CharSequence + assert elem["mode"] in [ "symlink", "rellink", "link", "copy", "copyNoFollow", "move" ] + } + if (elem.containsKey("overwrite")) { + assert elem["overwrite"] instanceof Boolean + } + if (elem.containsKey("pattern")) { + assert elem["pattern"] instanceof CharSequence + } + if (elem.containsKey("saveAs")) { + assert elem["saveAs"] instanceof CharSequence //: "saveAs as a Closure is currently not supported. Surround your closure with single quotes to get the desired effect. Example: '\{ foo \}'" + } + if (elem.containsKey("enabled")) { + assert elem["enabled"] instanceof Boolean + } + + // return final result + elem + } + // store final directive + drctv["publishDir"] = pblsh + } + + /* DIRECTIVE queue + accepted examples: + - "long" + - "short,long" + - ["short", "long"] + */ + if (drctv.containsKey("queue")) { + if (drctv["queue"] instanceof List) { + drctv["queue"] = drctv["queue"].join(",") + } + assert drctv["queue"] instanceof CharSequence + } + + /* DIRECTIVE label + accepted examples: + - "big_mem" + - "big_cpu" + - ["big_mem", "big_cpu"] + */ + if (drctv.containsKey("label")) { + if (drctv["label"] instanceof CharSequence) { + drctv["label"] = [ drctv["label"] ] + } + assert drctv["label"] instanceof List + drctv["label"].forEach { label -> + assert label instanceof CharSequence + // assert label.matches("[a-zA-Z0-9]([a-zA-Z0-9_]*[a-zA-Z0-9])?") + // ^ does not allow closures + } + } + + /* DIRECTIVE scratch + accepted examples: + - true + - "/path/to/scratch" + - '$MY_PATH_TO_SCRATCH' + - "ram-disk" + */ + if (drctv.containsKey("scratch")) { + assert drctv["scratch"] == true || drctv["scratch"] instanceof CharSequence + } + + /* DIRECTIVE storeDir + accepted examples: + - "/path/to/storeDir" + */ + if (drctv.containsKey("storeDir")) { + assert drctv["storeDir"] instanceof CharSequence + } + + /* DIRECTIVE stageInMode + accepted examples: + - "copy" + - "link" + */ + if (drctv.containsKey("stageInMode")) { + assert drctv["stageInMode"] instanceof CharSequence + assert drctv["stageInMode"] in ["copy", "link", "symlink", "rellink"] + } + + /* DIRECTIVE stageOutMode + accepted examples: + - "copy" + - "link" + */ + if (drctv.containsKey("stageOutMode")) { + assert drctv["stageOutMode"] instanceof CharSequence + assert drctv["stageOutMode"] in ["copy", "move", "rsync"] + } + + /* DIRECTIVE tag + accepted examples: + - "foo" + - '$id' + */ + if (drctv.containsKey("tag")) { + assert drctv["tag"] instanceof CharSequence + } + + /* DIRECTIVE time + accepted examples: + - "1h" + - "2days" + - "1day 6hours 3minutes 30seconds" + */ + if (drctv.containsKey("time")) { + assert drctv["time"] instanceof CharSequence + // todo: validation regex? + } + + return drctv +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/workflowFactory/processWorkflowArgs.nf' +def processWorkflowArgs(Map args, Map defaultWfArgs, Map meta) { + // override defaults with args + def workflowArgs = defaultWfArgs + args + + // check whether 'key' exists + assert workflowArgs.containsKey("key") : "Error in module '${meta.config.name}': key is a required argument" + + // if 'key' is a closure, apply it to the original key + if (workflowArgs["key"] instanceof Closure) { + workflowArgs["key"] = workflowArgs["key"](meta.config.name) + } + def key = workflowArgs["key"] + assert key instanceof CharSequence : "Expected process argument 'key' to be a String. Found: class ${key.getClass()}" + assert key ==~ /^[a-zA-Z_]\w*$/ : "Error in module '$key': Expected process argument 'key' to consist of only letters, digits or underscores. Found: ${key}" + + // check for any unexpected keys + def expectedKeys = ["key", "directives", "auto", "map", "mapId", "mapData", "mapPassthrough", "filter", "runIf", "fromState", "toState", "args", "renameKeys", "debug"] + def unexpectedKeys = workflowArgs.keySet() - expectedKeys + assert unexpectedKeys.isEmpty() : "Error in module '$key': unexpected arguments to the '.run()' function: '${unexpectedKeys.join("', '")}'" + + // check whether directives exists and apply defaults + assert workflowArgs.containsKey("directives") : "Error in module '$key': directives is a required argument" + assert workflowArgs["directives"] instanceof Map : "Error in module '$key': Expected process argument 'directives' to be a Map. Found: class ${workflowArgs['directives'].getClass()}" + workflowArgs["directives"] = processDirectives(defaultWfArgs.directives + workflowArgs["directives"]) + + // check whether directives exists and apply defaults + assert workflowArgs.containsKey("auto") : "Error in module '$key': auto is a required argument" + assert workflowArgs["auto"] instanceof Map : "Error in module '$key': Expected process argument 'auto' to be a Map. Found: class ${workflowArgs['auto'].getClass()}" + workflowArgs["auto"] = processAuto(defaultWfArgs.auto + workflowArgs["auto"]) + + // auto define publish, if so desired + if (workflowArgs.auto.publish == true && (workflowArgs.directives.publishDir != null ? workflowArgs.directives.publishDir : [:]).isEmpty()) { + // can't assert at this level thanks to the no_publish profile + // assert params.containsKey("publishDir") || params.containsKey("publish_dir") : + // "Error in module '${workflowArgs['key']}': if auto.publish is true, params.publish_dir needs to be defined.\n" + + // " Example: params.publish_dir = \"./output/\"" + def publishDir = getPublishDir() + + if (publishDir != null) { + workflowArgs.directives.publishDir = [[ + path: publishDir, + saveAs: "{ it.startsWith('.') ? null : it }", // don't publish hidden files, by default + mode: "copy" + ]] + } + } + + // auto define transcript, if so desired + if (workflowArgs.auto.transcript == true) { + // can't assert at this level thanks to the no_publish profile + // assert params.containsKey("transcriptsDir") || params.containsKey("transcripts_dir") || params.containsKey("publishDir") || params.containsKey("publish_dir") : + // "Error in module '${workflowArgs['key']}': if auto.transcript is true, either params.transcripts_dir or params.publish_dir needs to be defined.\n" + + // " Example: params.transcripts_dir = \"./transcripts/\"" + def transcriptsDir = + params.containsKey("transcripts_dir") ? params.transcripts_dir : + params.containsKey("transcriptsDir") ? params.transcriptsDir : + params.containsKey("publish_dir") ? params.publish_dir + "/_transcripts" : + params.containsKey("publishDir") ? params.publishDir + "/_transcripts" : + null + if (transcriptsDir != null) { + def timestamp = nextflow.Nextflow.getSession().getWorkflowMetadata().start.format('yyyy-MM-dd_HH-mm-ss') + def transcriptsPublishDir = [ + path: "$transcriptsDir/$timestamp/\${task.process.replaceAll(':', '-')}/\${id}/", + saveAs: "{ it.startsWith('.') ? it.replaceAll('^.', '') : null }", + mode: "copy" + ] + def publishDirs = workflowArgs.directives.publishDir != null ? workflowArgs.directives.publishDir : null ? workflowArgs.directives.publishDir : [] + workflowArgs.directives.publishDir = publishDirs + transcriptsPublishDir + } + } + + // if this is a stubrun, remove certain directives? + if (workflow.stubRun) { + workflowArgs.directives.keySet().removeAll(["publishDir", "cpus", "memory", "label"]) + } + + for (nam in ["map", "mapId", "mapData", "mapPassthrough", "filter", "runIf"]) { + if (workflowArgs.containsKey(nam) && workflowArgs[nam]) { + assert workflowArgs[nam] instanceof Closure : "Error in module '$key': Expected process argument '$nam' to be null or a Closure. Found: class ${workflowArgs[nam].getClass()}" + } + } + + // TODO: should functions like 'map', 'mapId', 'mapData', 'mapPassthrough' be deprecated as well? + for (nam in ["map", "mapData", "mapPassthrough", "renameKeys"]) { + if (workflowArgs.containsKey(nam) && workflowArgs[nam] != null) { + log.warn "module '$key': workflow argument '$nam' is deprecated and will be removed in Viash 0.9.0. Please use 'fromState' and 'toState' instead." + } + } + + // check fromState + workflowArgs["fromState"] = _processFromState(workflowArgs.get("fromState"), key, meta.config) + + // check toState + workflowArgs["toState"] = _processToState(workflowArgs.get("toState"), key, meta.config) + + // return output + return workflowArgs +} + +def _processFromState(fromState, key_, config_) { + assert fromState == null || fromState instanceof Closure || fromState instanceof Map || fromState instanceof List : + "Error in module '$key_': Expected process argument 'fromState' to be null, a Closure, a Map, or a List. Found: class ${fromState.getClass()}" + if (fromState == null) { + return null + } + + // if fromState is a List, convert to map + if (fromState instanceof List) { + // check whether fromstate is a list[string] + assert fromState.every{it instanceof CharSequence} : "Error in module '$key_': fromState is a List, but not all elements are Strings" + fromState = fromState.collectEntries{[it, it]} + } + + // if fromState is a map, convert to closure + if (fromState instanceof Map) { + // check whether fromstate is a map[string, string] + assert fromState.values().every{it instanceof CharSequence} : "Error in module '$key_': fromState is a Map, but not all values are Strings" + assert fromState.keySet().every{it instanceof CharSequence} : "Error in module '$key_': fromState is a Map, but not all keys are Strings" + def fromStateMap = fromState.clone() + def requiredInputNames = meta.config.allArguments.findAll{it.required && it.direction == "Input"}.collect{it.plainName} + // turn the map into a closure to be used later on + fromState = { it -> + def state = it[1] + assert state instanceof Map : "Error in module '$key_': the state is not a Map" + def data = fromStateMap.collectMany{newkey, origkey -> + // check whether newkey corresponds to a required argument + if (state.containsKey(origkey)) { + [[newkey, state[origkey]]] + } else if (!requiredInputNames.contains(origkey)) { + [] + } else { + throw new Exception("Error in module '$key_': fromState key '$origkey' not found in current state") + } + }.collectEntries() + data + } + } + + return fromState +} + +def _processToState(toState, key_, config_) { + if (toState == null) { + toState = { tup -> tup[1] } + } + + // toState should be a closure, map[string, string], or list[string] + assert toState instanceof Closure || toState instanceof Map || toState instanceof List : + "Error in module '$key_': Expected process argument 'toState' to be a Closure, a Map, or a List. Found: class ${toState.getClass()}" + + // if toState is a List, convert to map + if (toState instanceof List) { + // check whether toState is a list[string] + assert toState.every{it instanceof CharSequence} : "Error in module '$key_': toState is a List, but not all elements are Strings" + toState = toState.collectEntries{[it, it]} + } + + // if toState is a map, convert to closure + if (toState instanceof Map) { + // check whether toState is a map[string, string] + assert toState.values().every{it instanceof CharSequence} : "Error in module '$key_': toState is a Map, but not all values are Strings" + assert toState.keySet().every{it instanceof CharSequence} : "Error in module '$key_': toState is a Map, but not all keys are Strings" + def toStateMap = toState.clone() + def requiredOutputNames = config_.allArguments.findAll{it.required && it.direction == "Output"}.collect{it.plainName} + // turn the map into a closure to be used later on + toState = { it -> + def output = it[1] + def state = it[2] + assert output instanceof Map : "Error in module '$key_': the output is not a Map" + assert state instanceof Map : "Error in module '$key_': the state is not a Map" + def extraEntries = toStateMap.collectMany{newkey, origkey -> + // check whether newkey corresponds to a required argument + if (output.containsKey(origkey)) { + [[newkey, output[origkey]]] + } else if (!requiredOutputNames.contains(origkey)) { + [] + } else { + throw new Exception("Error in module '$key_': toState key '$origkey' not found in current output") + } + }.collectEntries() + state + extraEntries + } + } + + return toState +} + +// helper file: 'src/main/resources/io/viash/runners/nextflow/workflowFactory/workflowFactory.nf' +def _debug(workflowArgs, debugKey) { + if (workflowArgs.debug) { + view { "process '${workflowArgs.key}' $debugKey tuple: $it" } + } else { + map { it } + } +} + +// depends on: innerWorkflowFactory +def workflowFactory(Map args, Map defaultWfArgs, Map meta) { + def workflowArgs = processWorkflowArgs(args, defaultWfArgs, meta) + def key_ = workflowArgs["key"] + + workflow workflowInstance { + take: input_ + + main: + def chModified = input_ + | checkUniqueIds([:]) + | _debug(workflowArgs, "input") + | map { tuple -> + tuple = deepClone(tuple) + + if (workflowArgs.map) { + tuple = workflowArgs.map(tuple) + } + if (workflowArgs.mapId) { + tuple[0] = workflowArgs.mapId(tuple[0]) + } + if (workflowArgs.mapData) { + tuple[1] = workflowArgs.mapData(tuple[1]) + } + if (workflowArgs.mapPassthrough) { + tuple = tuple.take(2) + workflowArgs.mapPassthrough(tuple.drop(2)) + } + + // check tuple + assert tuple instanceof List : + "Error in module '${key_}': element in channel should be a tuple [id, data, ...otherargs...]\n" + + " Example: [\"id\", [input: file('foo.txt'), arg: 10]].\n" + + " Expected class: List. Found: tuple.getClass() is ${tuple.getClass()}" + assert tuple.size() >= 2 : + "Error in module '${key_}': expected length of tuple in input channel to be two or greater.\n" + + " Example: [\"id\", [input: file('foo.txt'), arg: 10]].\n" + + " Found: tuple.size() == ${tuple.size()}" + + // check id field + if (tuple[0] instanceof GString) { + tuple[0] = tuple[0].toString() + } + assert tuple[0] instanceof CharSequence : + "Error in module '${key_}': first element of tuple in channel should be a String\n" + + " Example: [\"id\", [input: file('foo.txt'), arg: 10]].\n" + + " Found: ${tuple[0]}" + + // match file to input file + if (workflowArgs.auto.simplifyInput && (tuple[1] instanceof Path || tuple[1] instanceof List)) { + def inputFiles = meta.config.allArguments + .findAll { it.type == "file" && it.direction == "input" } + + assert inputFiles.size() == 1 : + "Error in module '${key_}' id '${tuple[0]}'.\n" + + " Anonymous file inputs are only allowed when the process has exactly one file input.\n" + + " Expected: inputFiles.size() == 1. Found: inputFiles.size() is ${inputFiles.size()}" + + tuple[1] = [[ inputFiles[0].plainName, tuple[1] ]].collectEntries() + } + + // check data field + assert tuple[1] instanceof Map : + "Error in module '${key_}' id '${tuple[0]}': second element of tuple in channel should be a Map\n" + + " Example: [\"id\", [input: file('foo.txt'), arg: 10]].\n" + + " Expected class: Map. Found: tuple[1].getClass() is ${tuple[1].getClass()}" + + // rename keys of data field in tuple + if (workflowArgs.renameKeys) { + assert workflowArgs.renameKeys instanceof Map : + "Error renaming data keys in module '${key_}' id '${tuple[0]}'.\n" + + " Example: renameKeys: ['new_key': 'old_key'].\n" + + " Expected class: Map. Found: renameKeys.getClass() is ${workflowArgs.renameKeys.getClass()}" + assert tuple[1] instanceof Map : + "Error renaming data keys in module '${key_}' id '${tuple[0]}'.\n" + + " Expected class: Map. Found: tuple[1].getClass() is ${tuple[1].getClass()}" + + // TODO: allow renameKeys to be a function? + workflowArgs.renameKeys.each { newKey, oldKey -> + assert newKey instanceof CharSequence : + "Error renaming data keys in module '${key_}' id '${tuple[0]}'.\n" + + " Example: renameKeys: ['new_key': 'old_key'].\n" + + " Expected class of newKey: String. Found: newKey.getClass() is ${newKey.getClass()}" + assert oldKey instanceof CharSequence : + "Error renaming data keys in module '${key_}' id '${tuple[0]}'.\n" + + " Example: renameKeys: ['new_key': 'old_key'].\n" + + " Expected class of oldKey: String. Found: oldKey.getClass() is ${oldKey.getClass()}" + assert tuple[1].containsKey(oldKey) : + "Error renaming data keys in module '${key}' id '${tuple[0]}'.\n" + + " Key '$oldKey' is missing in the data map. tuple[1].keySet() is '${tuple[1].keySet()}'" + tuple[1].put(newKey, tuple[1][oldKey]) + } + tuple[1].keySet().removeAll(workflowArgs.renameKeys.collect{ newKey, oldKey -> oldKey }) + } + tuple + } + + def chModifiedFiltered = workflowArgs.filter ? + chModified | filter{workflowArgs.filter(it)} : + chModified + + def chRun = null + def chPassthrough = null + if (workflowArgs.runIf) { + def runIfBranch = chModifiedFiltered.branch{ tup -> + run: workflowArgs.runIf(tup[0], tup[1]) + passthrough: true + } + chRun = runIfBranch.run + chPassthrough = runIfBranch.passthrough + } else { + chRun = chModifiedFiltered + chPassthrough = Channel.empty() + } + + def chArgs = workflowArgs.fromState ? + chRun | map{ + def new_data = workflowArgs.fromState(it.take(2)) + [it[0], new_data] + } : + chRun | map {tup -> tup.take(2)} + + // fill in defaults + def chArgsWithDefaults = chArgs + | map { tuple -> + def id_ = tuple[0] + def data_ = tuple[1] + + // TODO: could move fromState to here + + // fetch default params from functionality + def defaultArgs = meta.config.allArguments + .findAll { it.containsKey("default") } + .collectEntries { [ it.plainName, it.default ] } + + // fetch overrides in params + def paramArgs = meta.config.allArguments + .findAll { par -> + def argKey = key_ + "__" + par.plainName + params.containsKey(argKey) + } + .collectEntries { [ it.plainName, params[key_ + "__" + it.plainName] ] } + + // fetch overrides in data + def dataArgs = meta.config.allArguments + .findAll { data_.containsKey(it.plainName) } + .collectEntries { [ it.plainName, data_[it.plainName] ] } + + // combine params + def combinedArgs = defaultArgs + paramArgs + workflowArgs.args + dataArgs + + // remove arguments with explicit null values + combinedArgs + .removeAll{_, val -> val == null || val == "viash_no_value" || val == "force_null"} + + combinedArgs = _processInputValues(combinedArgs, meta.config, id_, key_) + + [id_, combinedArgs] + tuple.drop(2) + } + + // TODO: move some of the _meta.join_id wrangling to the safeJoin() function. + def chInitialOutput = chArgsWithDefaults + | _debug(workflowArgs, "processed") + // run workflow + | innerWorkflowFactory(workflowArgs) + // check output tuple + | map { id_, output_ -> + + // see if output map contains metadata + def meta_ = + output_ instanceof Map && output_.containsKey("_meta") ? + output_["_meta"] : + [:] + def join_id = meta_.join_id ?: id_ + + // remove metadata + output_ = output_.findAll{k, v -> k != "_meta"} + + // check value types + output_ = _processOutputValues(output_, meta.config, id_, key_) + + // simplify output if need be + if (workflowArgs.auto.simplifyOutput && output_.size() == 1) { + output_ = output_.values()[0] + } + + [join_id, id_, output_] + } + // | view{"chInitialOutput: ${it.take(3)}"} + + // join the output [prev_id, new_id, output] with the previous state [prev_id, state, ...] + def chNewState = safeJoin(chInitialOutput, chModifiedFiltered, key_) + // input tuple format: [join_id, id, output, prev_state, ...] + // output tuple format: [join_id, id, new_state, ...] + | map{ tup -> + def new_state = workflowArgs.toState(tup.drop(1).take(3)) + tup.take(2) + [new_state] + tup.drop(4) + } + + if (workflowArgs.auto.publish == "state") { + def chPublish = chNewState + // input tuple format: [join_id, id, new_state, ...] + // output tuple format: [join_id, id, new_state] + | map{ tup -> + tup.take(3) + } + + safeJoin(chPublish, chArgsWithDefaults, key_) + // input tuple format: [join_id, id, new_state, orig_state, ...] + // output tuple format: [id, new_state, orig_state] + | map { tup -> + tup.drop(1).take(3) + } + | publishStatesByConfig(key: key_, config: meta.config) + } + + // remove join_id and meta + chReturn = chNewState + | map { tup -> + // input tuple format: [join_id, id, new_state, ...] + // output tuple format: [id, new_state, ...] + tup.drop(1) + } + | _debug(workflowArgs, "output") + | concat(chPassthrough) + + emit: chReturn + } + + def wf = workflowInstance.cloneWithName(key_) + + // add factory function + wf.metaClass.run = { runArgs -> + workflowFactory(runArgs, workflowArgs, meta) + } + // add config to module for later introspection + wf.metaClass.config = meta.config + + return wf +} + +nextflow.enable.dsl=2 + +// START COMPONENT-SPECIFIC CODE + +// create meta object +meta = [ + "resources_dir": moduleDir.toRealPath().normalize(), + "config": processConfig(readJsonBlob('''{ + "name" : "bedtools_bedtobam", + "namespace" : "bedtools", + "version" : "main", + "authors" : [ + { + "name" : "Theodoro Gasperin Terra Camargo", + "roles" : [ + "author", + "maintainer" + ], + "info" : { + "links" : { + "email" : "theodorogtc@gmail.com", + "github" : "tgaspe", + "linkedin" : "theodoro-gasperin-terra-camargo" + }, + "organizations" : [ + { + "name" : "Data Intuitive", + "href" : "https://www.data-intuitive.com", + "role" : "Bioinformatician" + } + ] + } + } + ], + "argument_groups" : [ + { + "name" : "Inputs", + "arguments" : [ + { + "type" : "file", + "name" : "--input", + "alternatives" : [ + "-i" + ], + "description" : "Input file (bed/gff/vcf).", + "must_exist" : true, + "create_parent" : true, + "required" : true, + "direction" : "input", + "multiple" : false, + "multiple_sep" : ";" + }, + { + "type" : "file", + "name" : "--genome", + "alternatives" : [ + "-g" + ], + "description" : "Input genome file.\nNOTE: This is not a fasta file. This is a two-column tab-delimited file\nwhere the first column is the chromosome name and the second their sizes.\n", + "must_exist" : true, + "create_parent" : true, + "required" : true, + "direction" : "input", + "multiple" : false, + "multiple_sep" : ";" + } + ] + }, + { + "name" : "Outputs", + "arguments" : [ + { + "type" : "file", + "name" : "--output", + "alternatives" : [ + "-o" + ], + "description" : "Output BAM file to be written.", + "must_exist" : true, + "create_parent" : true, + "required" : false, + "direction" : "output", + "multiple" : false, + "multiple_sep" : ";" + } + ] + }, + { + "name" : "Options", + "arguments" : [ + { + "type" : "integer", + "name" : "--map_quality", + "alternatives" : [ + "-mapq" + ], + "description" : "Set the mappinq quality for the BAM records.\n", + "default" : [ + 255 + ], + "required" : false, + "min" : 0, + "max" : 255, + "direction" : "input", + "multiple" : false, + "multiple_sep" : ";" + }, + { + "type" : "boolean_true", + "name" : "--bed12", + "description" : "The BED file is in BED12 format. The BAM CIGAR\nstring will reflect BED \\"blocks\\".\n", + "direction" : "input" + }, + { + "type" : "boolean_true", + "name" : "--uncompress_bam", + "alternatives" : [ + "-ubam" + ], + "description" : "Write uncompressed BAM output. Default writes compressed BAM.\n", + "direction" : "input" + } + ] + } + ], + "resources" : [ + { + "type" : "bash_script", + "path" : "script.sh", + "is_executable" : true + } + ], + "description" : "Converts feature records (bed/gff/vcf) to BAM format.", + "test_resources" : [ + { + "type" : "bash_script", + "path" : "test.sh", + "is_executable" : true + } + ], + "status" : "enabled", + "requirements" : { + "commands" : [ + "ps" + ] + }, + "keywords" : [ + "Converts", + "BED", + "GFF", + "VCF", + "BAM" + ], + "license" : "MIT", + "references" : { + "doi" : [ + "10.1093/bioinformatics/btq033" + ] + }, + "links" : { + "repository" : "https://github.com/arq5x/bedtools2", + "homepage" : "https://bedtools.readthedocs.io/en/latest/#", + "documentation" : "https://bedtools.readthedocs.io/en/latest/content/tools/bedtobam.html", + "issue_tracker" : "https://github.com/arq5x/bedtools2/issues" + }, + "runners" : [ + { + "type" : "executable", + "id" : "executable", + "docker_setup_strategy" : "ifneedbepullelsecachedbuild" + }, + { + "type" : "nextflow", + "id" : "nextflow", + "directives" : { + "tag" : "$id" + }, + "auto" : { + "simplifyInput" : true, + "simplifyOutput" : false, + "transcript" : false, + "publish" : false + }, + "config" : { + "labels" : { + "mem1gb" : "memory = 1000000000.B", + "mem2gb" : "memory = 2000000000.B", + "mem5gb" : "memory = 5000000000.B", + "mem10gb" : "memory = 10000000000.B", + "mem20gb" : "memory = 20000000000.B", + "mem50gb" : "memory = 50000000000.B", + "mem100gb" : "memory = 100000000000.B", + "mem200gb" : "memory = 200000000000.B", + "mem500gb" : "memory = 500000000000.B", + "mem1tb" : "memory = 1000000000000.B", + "mem2tb" : "memory = 2000000000000.B", + "mem5tb" : "memory = 5000000000000.B", + "mem10tb" : "memory = 10000000000000.B", + "mem20tb" : "memory = 20000000000000.B", + "mem50tb" : "memory = 50000000000000.B", + "mem100tb" : "memory = 100000000000000.B", + "mem200tb" : "memory = 200000000000000.B", + "mem500tb" : "memory = 500000000000000.B", + "mem1gib" : "memory = 1073741824.B", + "mem2gib" : "memory = 2147483648.B", + "mem4gib" : "memory = 4294967296.B", + "mem8gib" : "memory = 8589934592.B", + "mem16gib" : "memory = 17179869184.B", + "mem32gib" : "memory = 34359738368.B", + "mem64gib" : "memory = 68719476736.B", + "mem128gib" : "memory = 137438953472.B", + "mem256gib" : "memory = 274877906944.B", + "mem512gib" : "memory = 549755813888.B", + "mem1tib" : "memory = 1099511627776.B", + "mem2tib" : "memory = 2199023255552.B", + "mem4tib" : "memory = 4398046511104.B", + "mem8tib" : "memory = 8796093022208.B", + "mem16tib" : "memory = 17592186044416.B", + "mem32tib" : "memory = 35184372088832.B", + "mem64tib" : "memory = 70368744177664.B", + "mem128tib" : "memory = 140737488355328.B", + "mem256tib" : "memory = 281474976710656.B", + "mem512tib" : "memory = 562949953421312.B", + "cpu1" : "cpus = 1", + "cpu2" : "cpus = 2", + "cpu5" : "cpus = 5", + "cpu10" : "cpus = 10", + "cpu20" : "cpus = 20", + "cpu50" : "cpus = 50", + "cpu100" : "cpus = 100", + "cpu200" : "cpus = 200", + "cpu500" : "cpus = 500", + "cpu1000" : "cpus = 1000" + } + }, + "debug" : false, + "container" : "docker" + } + ], + "engines" : [ + { + "type" : "docker", + "id" : "docker", + "image" : "debian:stable-slim", + "target_registry" : "images.viash-hub.com", + "target_tag" : "main", + "namespace_separator" : "/", + "setup" : [ + { + "type" : "apt", + "packages" : [ + "bedtools", + "procps" + ], + "interactive" : false + }, + { + "type" : "docker", + "run" : [ + "echo \\"bedtools: \\\\\\"$(bedtools --version | sed -n 's/^bedtools //p')\\\\\\"\\" > /var/software_versions.txt\n" + ] + } + ], + "test_setup" : [ + { + "type" : "apt", + "packages" : [ + "samtools" + ], + "interactive" : false + } + ] + }, + { + "type" : "native", + "id" : "native" + } + ], + "build_info" : { + "config" : "/workdir/root/repo/src/bedtools/bedtools_bedtobam/config.vsh.yaml", + "runner" : "nextflow", + "engine" : "docker|native", + "output" : "target/nextflow/bedtools/bedtools_bedtobam", + "viash_version" : "0.9.0-RC6", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", + "git_remote" : "https://github.com/viash-hub/biobox" + }, + "package_config" : { + "name" : "biobox", + "version" : "main", + "description" : "A collection of bioinformatics tools for working with sequence data.\n", + "viash_version" : "0.9.0-RC6", + "source" : "src", + "target" : "target", + "config_mods" : [ + ".requirements.commands := ['ps']\n", + ".engines += { type: \\"native\\" }", + ".engines[.type == 'docker'].target_registry := 'images.viash-hub.com'", + ".engines[.type == 'docker'].target_tag := 'main'" + ], + "keywords" : [ + "bioinformatics", + "modules", + "sequencing" + ], + "license" : "MIT", + "organization" : "vsh", + "links" : { + "repository" : "https://github.com/viash-hub/biobox", + "issue_tracker" : "https://github.com/viash-hub/biobox/issues" + } + } +}''')) +] + +// resolve dependencies dependencies (if any) + + +// inner workflow +// inner workflow hook +def innerWorkflowFactory(args) { + def rawScript = '''set -e +tempscript=".viash_script.sh" +cat > "$tempscript" << VIASHMAIN +#!/bin/bash + +## VIASH START +# The following code has been auto-generated by Viash. +$( if [ ! -z ${VIASH_PAR_INPUT+x} ]; then echo "${VIASH_PAR_INPUT}" | sed "s#'#'\\"'\\"'#g;s#.*#par_input='&'#" ; else echo "# par_input="; fi ) +$( if [ ! -z ${VIASH_PAR_GENOME+x} ]; then echo "${VIASH_PAR_GENOME}" | sed "s#'#'\\"'\\"'#g;s#.*#par_genome='&'#" ; else echo "# par_genome="; fi ) +$( if [ ! -z ${VIASH_PAR_OUTPUT+x} ]; then echo "${VIASH_PAR_OUTPUT}" | sed "s#'#'\\"'\\"'#g;s#.*#par_output='&'#" ; else echo "# par_output="; fi ) +$( if [ ! -z ${VIASH_PAR_MAP_QUALITY+x} ]; then echo "${VIASH_PAR_MAP_QUALITY}" | sed "s#'#'\\"'\\"'#g;s#.*#par_map_quality='&'#" ; else echo "# par_map_quality="; fi ) +$( if [ ! -z ${VIASH_PAR_BED12+x} ]; then echo "${VIASH_PAR_BED12}" | sed "s#'#'\\"'\\"'#g;s#.*#par_bed12='&'#" ; else echo "# par_bed12="; fi ) +$( if [ ! -z ${VIASH_PAR_UNCOMPRESS_BAM+x} ]; then echo "${VIASH_PAR_UNCOMPRESS_BAM}" | sed "s#'#'\\"'\\"'#g;s#.*#par_uncompress_bam='&'#" ; else echo "# par_uncompress_bam="; fi ) +$( if [ ! -z ${VIASH_META_NAME+x} ]; then echo "${VIASH_META_NAME}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_name='&'#" ; else echo "# meta_name="; fi ) +$( if [ ! -z ${VIASH_META_FUNCTIONALITY_NAME+x} ]; then echo "${VIASH_META_FUNCTIONALITY_NAME}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_functionality_name='&'#" ; else echo "# meta_functionality_name="; fi ) +$( if [ ! -z ${VIASH_META_RESOURCES_DIR+x} ]; then echo "${VIASH_META_RESOURCES_DIR}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_resources_dir='&'#" ; else echo "# meta_resources_dir="; fi ) +$( if [ ! -z ${VIASH_META_EXECUTABLE+x} ]; then echo "${VIASH_META_EXECUTABLE}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_executable='&'#" ; else echo "# meta_executable="; fi ) +$( if [ ! -z ${VIASH_META_CONFIG+x} ]; then echo "${VIASH_META_CONFIG}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_config='&'#" ; else echo "# meta_config="; fi ) +$( if [ ! -z ${VIASH_META_TEMP_DIR+x} ]; then echo "${VIASH_META_TEMP_DIR}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_temp_dir='&'#" ; else echo "# meta_temp_dir="; fi ) +$( if [ ! -z ${VIASH_META_CPUS+x} ]; then echo "${VIASH_META_CPUS}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_cpus='&'#" ; else echo "# meta_cpus="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_B+x} ]; then echo "${VIASH_META_MEMORY_B}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_b='&'#" ; else echo "# meta_memory_b="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_KB+x} ]; then echo "${VIASH_META_MEMORY_KB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_kb='&'#" ; else echo "# meta_memory_kb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_MB+x} ]; then echo "${VIASH_META_MEMORY_MB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_mb='&'#" ; else echo "# meta_memory_mb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_GB+x} ]; then echo "${VIASH_META_MEMORY_GB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_gb='&'#" ; else echo "# meta_memory_gb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_TB+x} ]; then echo "${VIASH_META_MEMORY_TB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_tb='&'#" ; else echo "# meta_memory_tb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_PB+x} ]; then echo "${VIASH_META_MEMORY_PB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_pb='&'#" ; else echo "# meta_memory_pb="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_KIB+x} ]; then echo "${VIASH_META_MEMORY_KIB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_kib='&'#" ; else echo "# meta_memory_kib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_MIB+x} ]; then echo "${VIASH_META_MEMORY_MIB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_mib='&'#" ; else echo "# meta_memory_mib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_GIB+x} ]; then echo "${VIASH_META_MEMORY_GIB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_gib='&'#" ; else echo "# meta_memory_gib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_TIB+x} ]; then echo "${VIASH_META_MEMORY_TIB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_tib='&'#" ; else echo "# meta_memory_tib="; fi ) +$( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_pib='&'#" ; else echo "# meta_memory_pib="; fi ) + +## VIASH END + +set -eo pipefail + +# Unset parameters +[[ "\\$par_bed12" == "false" ]] && unset par_bed12 +[[ "\\$par_uncompress_bam" == "false" ]] && unset par_uncompress_bam + +# Execute bedtools bed to bam +bedtools bedtobam \\\\ + \\${par_bed12:+-bed12} \\\\ + \\${par_uncompress_bam:+-ubam} \\\\ + \\${par_map_quality:+-mapq "\\$par_map_quality"} \\\\ + -i "\\$par_input" \\\\ + -g "\\$par_genome" \\\\ + > "\\$par_output" +VIASHMAIN +bash "$tempscript" +''' + + return vdsl3WorkflowFactory(args, meta, rawScript) +} + + + +/** + * Generate a workflow for VDSL3 modules. + * + * This function is called by the workflowFactory() function. + * + * Input channel: [id, input_map] + * Output channel: [id, output_map] + * + * Internally, this workflow will convert the input channel + * to a format which the Nextflow module will be able to handle. + */ +def vdsl3WorkflowFactory(Map args, Map meta, String rawScript) { + def key = args["key"] + def processObj = null + + workflow processWf { + take: input_ + main: + + if (processObj == null) { + processObj = _vdsl3ProcessFactory(args, meta, rawScript) + } + + output_ = input_ + | map { tuple -> + def id = tuple[0] + def data_ = tuple[1] + + if (workflow.stubRun) { + // add id if missing + data_ = [id: 'stub'] + data_ + } + + // process input files separately + def inputPaths = meta.config.allArguments + .findAll { it.type == "file" && it.direction == "input" } + .collect { par -> + def val = data_.containsKey(par.plainName) ? data_[par.plainName] : [] + def inputFiles = [] + if (val == null) { + inputFiles = [] + } else if (val instanceof List) { + inputFiles = val + } else if (val instanceof Path) { + inputFiles = [ val ] + } else { + inputFiles = [] + } + if (!workflow.stubRun) { + // throw error when an input file doesn't exist + inputFiles.each{ file -> + assert file.exists() : + "Error in module '${key}' id '${id}' argument '${par.plainName}'.\n" + + " Required input file does not exist.\n" + + " Path: '$file'.\n" + + " Expected input file to exist" + } + } + inputFiles + } + + // remove input files + def argsExclInputFiles = meta.config.allArguments + .findAll { (it.type != "file" || it.direction != "input") && data_.containsKey(it.plainName) } + .collectEntries { par -> + def parName = par.plainName + def val = data_[parName] + if (par.multiple && val instanceof Collection) { + val = val.join(par.multiple_sep) + } + if (par.direction == "output" && par.type == "file") { + val = val.replaceAll('\\$id', id).replaceAll('\\$key', key) + } + [parName, val] + } + + [ id ] + inputPaths + [ argsExclInputFiles, meta.resources_dir ] + } + | processObj + | map { output -> + def outputFiles = meta.config.allArguments + .findAll { it.type == "file" && it.direction == "output" } + .indexed() + .collectEntries{ index, par -> + def out = output[index + 1] + // strip dummy '.exitcode' file from output (see nextflow-io/nextflow#2678) + if (!out instanceof List || out.size() <= 1) { + if (par.multiple) { + out = [] + } else { + assert !par.required : + "Error in module '${key}' id '${output[0]}' argument '${par.plainName}'.\n" + + " Required output file is missing" + out = null + } + } else if (out.size() == 2 && !par.multiple) { + out = out[1] + } else { + out = out.drop(1) + } + [ par.plainName, out ] + } + + // drop null outputs + outputFiles.removeAll{it.value == null} + + [ output[0], outputFiles ] + } + emit: output_ + } + + return processWf +} + +// depends on: session? +def _vdsl3ProcessFactory(Map workflowArgs, Map meta, String rawScript) { + // autodetect process key + def wfKey = workflowArgs["key"] + def procKeyPrefix = "${wfKey}_process" + def scriptMeta = nextflow.script.ScriptMeta.current() + def existing = scriptMeta.getProcessNames().findAll{it.startsWith(procKeyPrefix)} + def numbers = existing.collect{it.replace(procKeyPrefix, "0").toInteger()} + def newNumber = (numbers + [-1]).max() + 1 + + def procKey = newNumber == 0 ? procKeyPrefix : "$procKeyPrefix$newNumber" + + if (newNumber > 0) { + log.warn "Key for module '${wfKey}' is duplicated.\n", + "If you run a component multiple times in the same workflow,\n" + + "it's recommended you set a unique key for every call,\n" + + "for example: ${wfKey}.run(key: \"foo\")." + } + + // subset directives and convert to list of tuples + def drctv = workflowArgs.directives + + // TODO: unit test the two commands below + // convert publish array into tags + def valueToStr = { val -> + // ignore closures + if (val instanceof CharSequence) { + if (!val.matches('^[{].*[}]$')) { + '"' + val + '"' + } else { + val + } + } else if (val instanceof List) { + "[" + val.collect{valueToStr(it)}.join(", ") + "]" + } else if (val instanceof Map) { + "[" + val.collect{k, v -> k + ": " + valueToStr(v)}.join(", ") + "]" + } else { + val.inspect() + } + } + + // multiple entries allowed: label, publishdir + def drctvStrs = drctv.collect { key, value -> + if (key in ["label", "publishDir"]) { + value.collect{ val -> + if (val instanceof Map) { + "\n$key " + val.collect{ k, v -> k + ": " + valueToStr(v) }.join(", ") + } else if (val == null) { + "" + } else { + "\n$key " + valueToStr(val) + } + }.join() + } else if (value instanceof Map) { + "\n$key " + value.collect{ k, v -> k + ": " + valueToStr(v) }.join(", ") + } else { + "\n$key " + valueToStr(value) + } + }.join() + + def inputPaths = meta.config.allArguments + .findAll { it.type == "file" && it.direction == "input" } + .collect { ', path(viash_par_' + it.plainName + ', stageAs: "_viash_par/' + it.plainName + '_?/*")' } + .join() + + def outputPaths = meta.config.allArguments + .findAll { it.type == "file" && it.direction == "output" } + .collect { par -> + // insert dummy into every output (see nextflow-io/nextflow#2678) + if (!par.multiple) { + ', path{[".exitcode", args.' + par.plainName + ']}' + } else { + ', path{[".exitcode"] + args.' + par.plainName + '}' + } + } + .join() + + // TODO: move this functionality somewhere else? + if (workflowArgs.auto.transcript) { + outputPaths = outputPaths + ', path{[".exitcode", ".command*"]}' + } else { + outputPaths = outputPaths + ', path{[".exitcode"]}' + } + + // create dirs for output files (based on BashWrapper.createParentFiles) + def createParentStr = meta.config.allArguments + .findAll { it.type == "file" && it.direction == "output" && it.create_parent } + .collect { par -> + "\${ args.containsKey(\"${par.plainName}\") ? \"mkdir_parent \\\"\" + (args[\"${par.plainName}\"] instanceof String ? args[\"${par.plainName}\"] : args[\"${par.plainName}\"].join('\" \"')) + \"\\\"\" : \"\" }" + } + .join("\n") + + // construct inputFileExports + def inputFileExports = meta.config.allArguments + .findAll { it.type == "file" && it.direction.toLowerCase() == "input" } + .collect { par -> + def viash_par_contents = "(viash_par_${par.plainName} instanceof List ? viash_par_${par.plainName}.join(\"${par.multiple_sep}\") : viash_par_${par.plainName})" + "\n\${viash_par_${par.plainName}.empty ? \"\" : \"export VIASH_PAR_${par.plainName.toUpperCase()}=\\\"\" + ${viash_par_contents} + \"\\\"\"}" + } + + // NOTE: if using docker, use /tmp instead of tmpDir! + def tmpDir = java.nio.file.Paths.get( + System.getenv('NXF_TEMP') ?: + System.getenv('VIASH_TEMP') ?: + System.getenv('VIASH_TMPDIR') ?: + System.getenv('VIASH_TEMPDIR') ?: + System.getenv('VIASH_TMP') ?: + System.getenv('TEMP') ?: + System.getenv('TMPDIR') ?: + System.getenv('TEMPDIR') ?: + System.getenv('TMP') ?: + '/tmp' + ).toAbsolutePath() + + // construct stub + def stub = meta.config.allArguments + .findAll { it.type == "file" && it.direction == "output" } + .collect { par -> + "\${ args.containsKey(\"${par.plainName}\") ? \"touch2 \\\"\" + (args[\"${par.plainName}\"] instanceof String ? args[\"${par.plainName}\"].replace(\"_*\", \"_0\") : args[\"${par.plainName}\"].join('\" \"')) + \"\\\"\" : \"\" }" + } + .join("\n") + + // escape script + def escapedScript = rawScript.replace('\\', '\\\\').replace('$', '\\$').replace('"""', '\\"\\"\\"') + + // publishdir assert + def assertStr = (workflowArgs.auto.publish == true) || workflowArgs.auto.transcript ? + """\nassert task.publishDir.size() > 0: "if auto.publish is true, params.publish_dir needs to be defined.\\n Example: --publish_dir './output/'" """ : + "" + + // generate process string + def procStr = + """nextflow.enable.dsl=2 + | + |process $procKey {$drctvStrs + |input: + | tuple val(id)$inputPaths, val(args), path(resourcesDir, stageAs: ".viash_meta_resources") + |output: + | tuple val("\$id")$outputPaths, optional: true + |stub: + |\"\"\" + |touch2() { mkdir -p "\\\$(dirname "\\\$1")" && touch "\\\$1" ; } + |$stub + |\"\"\" + |script:$assertStr + |def escapeText = { s -> s.toString().replaceAll('([`"])', '\\\\\\\\\$1') } + |def parInject = args + | .findAll{key, value -> value != null} + | .collect{key, value -> "export VIASH_PAR_\${key.toUpperCase()}=\\\"\${escapeText(value)}\\\""} + | .join("\\n") + |\"\"\" + |# meta exports + |export VIASH_META_RESOURCES_DIR="\${resourcesDir}" + |export VIASH_META_TEMP_DIR="${['docker', 'podman', 'charliecloud'].any{ it == workflow.containerEngine } ? '/tmp' : tmpDir}" + |export VIASH_META_NAME="${meta.config.name}" + |# export VIASH_META_EXECUTABLE="\\\$VIASH_META_RESOURCES_DIR/\\\$VIASH_META_NAME" + |export VIASH_META_CONFIG="\\\$VIASH_META_RESOURCES_DIR/.config.vsh.yaml" + |\${task.cpus ? "export VIASH_META_CPUS=\$task.cpus" : "" } + |\${task.memory?.bytes != null ? "export VIASH_META_MEMORY_B=\$task.memory.bytes" : "" } + |if [ ! -z \\\${VIASH_META_MEMORY_B+x} ]; then + | export VIASH_META_MEMORY_KB=\\\$(( (\\\$VIASH_META_MEMORY_B+999) / 1000 )) + | export VIASH_META_MEMORY_MB=\\\$(( (\\\$VIASH_META_MEMORY_KB+999) / 1000 )) + | export VIASH_META_MEMORY_GB=\\\$(( (\\\$VIASH_META_MEMORY_MB+999) / 1000 )) + | export VIASH_META_MEMORY_TB=\\\$(( (\\\$VIASH_META_MEMORY_GB+999) / 1000 )) + | export VIASH_META_MEMORY_PB=\\\$(( (\\\$VIASH_META_MEMORY_TB+999) / 1000 )) + | export VIASH_META_MEMORY_KIB=\\\$(( (\\\$VIASH_META_MEMORY_B+1023) / 1024 )) + | export VIASH_META_MEMORY_MIB=\\\$(( (\\\$VIASH_META_MEMORY_KIB+1023) / 1024 )) + | export VIASH_META_MEMORY_GIB=\\\$(( (\\\$VIASH_META_MEMORY_MIB+1023) / 1024 )) + | export VIASH_META_MEMORY_TIB=\\\$(( (\\\$VIASH_META_MEMORY_GIB+1023) / 1024 )) + | export VIASH_META_MEMORY_PIB=\\\$(( (\\\$VIASH_META_MEMORY_TIB+1023) / 1024 )) + |fi + | + |# meta synonyms + |export VIASH_TEMP="\\\$VIASH_META_TEMP_DIR" + |export TEMP_DIR="\\\$VIASH_META_TEMP_DIR" + | + |# create output dirs if need be + |function mkdir_parent { + | for file in "\\\$@"; do + | mkdir -p "\\\$(dirname "\\\$file")" + | done + |} + |$createParentStr + | + |# argument exports${inputFileExports.join()} + |\$parInject + | + |# process script + |${escapedScript} + |\"\"\" + |} + |""".stripMargin() + + // TODO: print on debug + // if (workflowArgs.debug == true) { + // println("######################\n$procStr\n######################") + // } + + // write process to temp file + def tempFile = java.nio.file.Files.createTempFile("viash-process-${procKey}-", ".nf") + addShutdownHook { java.nio.file.Files.deleteIfExists(tempFile) } + tempFile.text = procStr + + // create process from temp file + def binding = new nextflow.script.ScriptBinding([:]) + def session = nextflow.Nextflow.getSession() + def parser = new nextflow.script.ScriptParser(session) + .setModule(true) + .setBinding(binding) + def moduleScript = parser.runScript(tempFile) + .getScript() + + // register module in meta + def module = new nextflow.script.IncludeDef.Module(name: procKey) + scriptMeta.addModule(moduleScript, module.name, module.alias) + + // retrieve and return process from meta + return scriptMeta.getProcess(procKey) +} + +// defaults +meta["defaults"] = [ + // key to be used to trace the process and determine output names + key: null, + + // fixed arguments to be passed to script + args: [:], + + // default directives + directives: readJsonBlob('''{ + "container" : { + "registry" : "images.viash-hub.com", + "image" : "vsh/biobox/bedtools/bedtools_bedtobam", + "tag" : "main" + }, + "tag" : "$id" +}'''), + + // auto settings + auto: readJsonBlob('''{ + "simplifyInput" : true, + "simplifyOutput" : false, + "transcript" : false, + "publish" : false +}'''), + + // Apply a map over the incoming tuple + // Example: `{ tup -> [ tup[0], [input: tup[1].output] ] + tup.drop(2) }` + map: null, + + // Apply a map over the ID element of a tuple (i.e. the first element) + // Example: `{ id -> id + "_foo" }` + mapId: null, + + // Apply a map over the data element of a tuple (i.e. the second element) + // Example: `{ data -> [ input: data.output ] }` + mapData: null, + + // Apply a map over the passthrough elements of a tuple (i.e. the tuple excl. the first two elements) + // Example: `{ pt -> pt.drop(1) }` + mapPassthrough: null, + + // Filter the channel + // Example: `{ tup -> tup[0] == "foo" }` + filter: null, + + // Choose whether or not to run the component on the tuple if the condition is true. + // Otherwise, the tuple will be passed through. + // Example: `{ tup -> tup[0] != "skip_this" }` + runIf: null, + + // Rename keys in the data field of the tuple (i.e. the second element) + // Will likely be deprecated in favour of `fromState`. + // Example: `[ "new_key": "old_key" ]` + renameKeys: null, + + // Fetch data from the state and pass it to the module without altering the current state. + // + // `fromState` should be `null`, `List[String]`, `Map[String, String]` or a function. + // + // - If it is `null`, the state will be passed to the module as is. + // - If it is a `List[String]`, the data will be the values of the state at the given keys. + // - If it is a `Map[String, String]`, the data will be the values of the state at the given keys, with the keys renamed according to the map. + // - If it is a function, the tuple (`[id, state]`) in the channel will be passed to the function, and the result will be used as the data. + // + // Example: `{ id, state -> [input: state.fastq_file] }` + // Default: `null` + fromState: null, + + // Determine how the state should be updated after the module has been run. + // + // `toState` should be `null`, `List[String]`, `Map[String, String]` or a function. + // + // - If it is `null`, the state will be replaced with the output of the module. + // - If it is a `List[String]`, the state will be updated with the values of the data at the given keys. + // - If it is a `Map[String, String]`, the state will be updated with the values of the data at the given keys, with the keys renamed according to the map. + // - If it is a function, a tuple (`[id, output, state]`) will be passed to the function, and the result will be used as the new state. + // + // Example: `{ id, output, state -> state + [counts: state.output] }` + // Default: `{ id, output, state -> output }` + toState: null, + + // Whether or not to print debug messages + // Default: `false` + debug: false +] + +// initialise default workflow +meta["workflow"] = workflowFactory([key: meta.config.name], meta.defaults, meta) + +// add workflow to environment +nextflow.script.ScriptMeta.current().addDefinition(meta.workflow) + +// anonymous workflow for running this module as a standalone +workflow { + // add id argument if it's not already in the config + // TODO: deep copy + def newConfig = deepClone(meta.config) + def newParams = deepClone(params) + + def argsContainsId = newConfig.allArguments.any{it.plainName == "id"} + if (!argsContainsId) { + def idArg = [ + 'name': '--id', + 'required': false, + 'type': 'string', + 'description': 'A unique id for every entry.', + 'multiple': false + ] + newConfig.arguments.add(0, idArg) + newConfig = processConfig(newConfig) + } + if (!newParams.containsKey("id")) { + newParams.id = "run" + } + + helpMessage(newConfig) + + channelFromParams(newParams, newConfig) + // make sure id is not in the state if id is not in the args + | map {id, state -> + if (!argsContainsId) { + [id, state.findAll{k, v -> k != "id"}] + } else { + [id, state] + } + } + | meta.workflow.run( + auto: [ publish: "state" ] + ) +} + +// END COMPONENT-SPECIFIC CODE diff --git a/target/nextflow/bedtools/bedtools_bedtobam/nextflow.config b/target/nextflow/bedtools/bedtools_bedtobam/nextflow.config new file mode 100644 index 00000000..d56396d1 --- /dev/null +++ b/target/nextflow/bedtools/bedtools_bedtobam/nextflow.config @@ -0,0 +1,126 @@ +manifest { + name = 'bedtools/bedtools_bedtobam' + mainScript = 'main.nf' + nextflowVersion = '!>=20.12.1-edge' + version = 'main' + description = 'Converts feature records (bed/gff/vcf) to BAM format.' + author = 'Theodoro Gasperin Terra Camargo' +} + +process.container = 'nextflow/bash:latest' + +// detect tempdir +tempDir = java.nio.file.Paths.get( + System.getenv('NXF_TEMP') ?: + System.getenv('VIASH_TEMP') ?: + System.getenv('TEMPDIR') ?: + System.getenv('TMPDIR') ?: + '/tmp' +).toAbsolutePath() + +profiles { + no_publish { + process { + withName: '.*' { + publishDir = [ + enabled: false + ] + } + } + } + mount_temp { + docker.temp = tempDir + podman.temp = tempDir + charliecloud.temp = tempDir + } + docker { + docker.enabled = true + // docker.userEmulation = true + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false + } + singularity { + singularity.enabled = true + singularity.autoMounts = true + docker.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false + } + podman { + podman.enabled = true + docker.enabled = false + singularity.enabled = false + shifter.enabled = false + charliecloud.enabled = false + } + shifter { + shifter.enabled = true + docker.enabled = false + singularity.enabled = false + podman.enabled = false + charliecloud.enabled = false + } + charliecloud { + charliecloud.enabled = true + docker.enabled = false + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + } +} + +process{ + withLabel: mem1gb { memory = 1000000000.B } + withLabel: mem2gb { memory = 2000000000.B } + withLabel: mem5gb { memory = 5000000000.B } + withLabel: mem10gb { memory = 10000000000.B } + withLabel: mem20gb { memory = 20000000000.B } + withLabel: mem50gb { memory = 50000000000.B } + withLabel: mem100gb { memory = 100000000000.B } + withLabel: mem200gb { memory = 200000000000.B } + withLabel: mem500gb { memory = 500000000000.B } + withLabel: mem1tb { memory = 1000000000000.B } + withLabel: mem2tb { memory = 2000000000000.B } + withLabel: mem5tb { memory = 5000000000000.B } + withLabel: mem10tb { memory = 10000000000000.B } + withLabel: mem20tb { memory = 20000000000000.B } + withLabel: mem50tb { memory = 50000000000000.B } + withLabel: mem100tb { memory = 100000000000000.B } + withLabel: mem200tb { memory = 200000000000000.B } + withLabel: mem500tb { memory = 500000000000000.B } + withLabel: mem1gib { memory = 1073741824.B } + withLabel: mem2gib { memory = 2147483648.B } + withLabel: mem4gib { memory = 4294967296.B } + withLabel: mem8gib { memory = 8589934592.B } + withLabel: mem16gib { memory = 17179869184.B } + withLabel: mem32gib { memory = 34359738368.B } + withLabel: mem64gib { memory = 68719476736.B } + withLabel: mem128gib { memory = 137438953472.B } + withLabel: mem256gib { memory = 274877906944.B } + withLabel: mem512gib { memory = 549755813888.B } + withLabel: mem1tib { memory = 1099511627776.B } + withLabel: mem2tib { memory = 2199023255552.B } + withLabel: mem4tib { memory = 4398046511104.B } + withLabel: mem8tib { memory = 8796093022208.B } + withLabel: mem16tib { memory = 17592186044416.B } + withLabel: mem32tib { memory = 35184372088832.B } + withLabel: mem64tib { memory = 70368744177664.B } + withLabel: mem128tib { memory = 140737488355328.B } + withLabel: mem256tib { memory = 281474976710656.B } + withLabel: mem512tib { memory = 562949953421312.B } + withLabel: cpu1 { cpus = 1 } + withLabel: cpu2 { cpus = 2 } + withLabel: cpu5 { cpus = 5 } + withLabel: cpu10 { cpus = 10 } + withLabel: cpu20 { cpus = 20 } + withLabel: cpu50 { cpus = 50 } + withLabel: cpu100 { cpus = 100 } + withLabel: cpu200 { cpus = 200 } + withLabel: cpu500 { cpus = 500 } + withLabel: cpu1000 { cpus = 1000 } +} + + diff --git a/target/nextflow/bedtools/bedtools_bedtobam/nextflow_schema.json b/target/nextflow/bedtools/bedtools_bedtobam/nextflow_schema.json new file mode 100644 index 00000000..0654aa9b --- /dev/null +++ b/target/nextflow/bedtools/bedtools_bedtobam/nextflow_schema.json @@ -0,0 +1,152 @@ +{ +"$schema": "http://json-schema.org/draft-07/schema", +"title": "bedtools_bedtobam", +"description": "Converts feature records (bed/gff/vcf) to BAM format.", +"type": "object", +"definitions": { + + + + "inputs" : { + "title": "Inputs", + "type": "object", + "description": "No description", + "properties": { + + + "input": { + "type": + "string", + "description": "Type: `file`, required. Input file (bed/gff/vcf)", + "help_text": "Type: `file`, required. Input file (bed/gff/vcf)." + + } + + + , + "genome": { + "type": + "string", + "description": "Type: `file`, required. Input genome file", + "help_text": "Type: `file`, required. Input genome file.\nNOTE: This is not a fasta file. This is a two-column tab-delimited file\nwhere the first column is the chromosome name and the second their sizes.\n" + + } + + +} +}, + + + "outputs" : { + "title": "Outputs", + "type": "object", + "description": "No description", + "properties": { + + + "output": { + "type": + "string", + "description": "Type: `file`, default: `$id.$key.output.output`. Output BAM file to be written", + "help_text": "Type: `file`, default: `$id.$key.output.output`. Output BAM file to be written." + , + "default": "$id.$key.output.output" + } + + +} +}, + + + "options" : { + "title": "Options", + "type": "object", + "description": "No description", + "properties": { + + + "map_quality": { + "type": + "integer", + "description": "Type: `integer`, default: `255`. Set the mappinq quality for the BAM records", + "help_text": "Type: `integer`, default: `255`. Set the mappinq quality for the BAM records.\n" + , + "default": "255" + } + + + , + "bed12": { + "type": + "boolean", + "description": "Type: `boolean_true`, default: `false`. The BED file is in BED12 format", + "help_text": "Type: `boolean_true`, default: `false`. The BED file is in BED12 format. The BAM CIGAR\nstring will reflect BED \"blocks\".\n" + , + "default": "False" + } + + + , + "uncompress_bam": { + "type": + "boolean", + "description": "Type: `boolean_true`, default: `false`. Write uncompressed BAM output", + "help_text": "Type: `boolean_true`, default: `false`. Write uncompressed BAM output. Default writes compressed BAM.\n" + , + "default": "False" + } + + +} +}, + + + "nextflow input-output arguments" : { + "title": "Nextflow input-output arguments", + "type": "object", + "description": "Input/output parameters for Nextflow itself. Please note that both publishDir and publish_dir are supported but at least one has to be configured.", + "properties": { + + + "publish_dir": { + "type": + "string", + "description": "Type: `string`, required, example: `output/`. Path to an output directory", + "help_text": "Type: `string`, required, example: `output/`. Path to an output directory." + + } + + + , + "param_list": { + "type": + "string", + "description": "Type: `string`, example: `my_params.yaml`. Allows inputting multiple parameter sets to initialise a Nextflow channel", + "help_text": "Type: `string`, example: `my_params.yaml`. Allows inputting multiple parameter sets to initialise a Nextflow channel. A `param_list` can either be a list of maps, a csv file, a json file, a yaml file, or simply a yaml blob.\n\n* A list of maps (as-is) where the keys of each map corresponds to the arguments of the pipeline. Example: in a `nextflow.config` file: `param_list: [ [\u0027id\u0027: \u0027foo\u0027, \u0027input\u0027: \u0027foo.txt\u0027], [\u0027id\u0027: \u0027bar\u0027, \u0027input\u0027: \u0027bar.txt\u0027] ]`.\n* A csv file should have column names which correspond to the different arguments of this pipeline. Example: `--param_list data.csv` with columns `id,input`.\n* A json or a yaml file should be a list of maps, each of which has keys corresponding to the arguments of the pipeline. Example: `--param_list data.json` with contents `[ {\u0027id\u0027: \u0027foo\u0027, \u0027input\u0027: \u0027foo.txt\u0027}, {\u0027id\u0027: \u0027bar\u0027, \u0027input\u0027: \u0027bar.txt\u0027} ]`.\n* A yaml blob can also be passed directly as a string. Example: `--param_list \"[ {\u0027id\u0027: \u0027foo\u0027, \u0027input\u0027: \u0027foo.txt\u0027}, {\u0027id\u0027: \u0027bar\u0027, \u0027input\u0027: \u0027bar.txt\u0027} ]\"`.\n\nWhen passing a csv, json or yaml file, relative path names are relativized to the location of the parameter file. No relativation is performed when `param_list` is a list of maps (as-is) or a yaml blob.", + "hidden": true + + } + + +} +} +}, +"allOf": [ + + { + "$ref": "#/definitions/inputs" + }, + + { + "$ref": "#/definitions/outputs" + }, + + { + "$ref": "#/definitions/options" + }, + + { + "$ref": "#/definitions/nextflow input-output arguments" + } +] +} diff --git a/target/nextflow/bedtools/bedtools_getfasta/.config.vsh.yaml b/target/nextflow/bedtools/bedtools_getfasta/.config.vsh.yaml index 5294f105..945b8e07 100644 --- a/target/nextflow/bedtools/bedtools_getfasta/.config.vsh.yaml +++ b/target/nextflow/bedtools/bedtools_getfasta/.config.vsh.yaml @@ -232,7 +232,7 @@ build_info: output: "target/nextflow/bedtools/bedtools_getfasta" executable: "target/nextflow/bedtools/bedtools_getfasta/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/bedtools/bedtools_getfasta/main.nf b/target/nextflow/bedtools/bedtools_getfasta/main.nf index 03243ad8..ed94158e 100644 --- a/target/nextflow/bedtools/bedtools_getfasta/main.nf +++ b/target/nextflow/bedtools/bedtools_getfasta/main.nf @@ -3060,7 +3060,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/bedtools/bedtools_getfasta", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { diff --git a/target/nextflow/bedtools/bedtools_intersect/.config.vsh.yaml b/target/nextflow/bedtools/bedtools_intersect/.config.vsh.yaml index 77f6ff49..cad25689 100644 --- a/target/nextflow/bedtools/bedtools_intersect/.config.vsh.yaml +++ b/target/nextflow/bedtools/bedtools_intersect/.config.vsh.yaml @@ -410,7 +410,7 @@ build_info: output: "target/nextflow/bedtools/bedtools_intersect" executable: "target/nextflow/bedtools/bedtools_intersect/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/bedtools/bedtools_intersect/main.nf b/target/nextflow/bedtools/bedtools_intersect/main.nf index 21e2f560..2134053c 100644 --- a/target/nextflow/bedtools/bedtools_intersect/main.nf +++ b/target/nextflow/bedtools/bedtools_intersect/main.nf @@ -3256,7 +3256,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/bedtools/bedtools_intersect", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { @@ -3350,27 +3350,35 @@ $( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" ## VIASH END -[[ "\\$par_write_a" == "false" ]] && unset par_write_a -[[ "\\$par_write_b" == "false" ]] && unset par_write_b -[[ "\\$par_left_outer_join" == "false" ]] && unset par_left_outer_join -[[ "\\$par_write_overlap" == "false" ]] && unset par_write_overlap -[[ "\\$par_write_overlap_plus" == "false" ]] && unset par_write_overlap_plus -[[ "\\$par_report_A_if_no_overlap" == "false" ]] && unset par_report_A_if_no_overlap -[[ "\\$par_number_of_overlaps_A" == "false" ]] && unset par_number_of_overlaps_A -[[ "\\$par_report_no_overlaps_A" == "false" ]] && unset par_report_no_overlaps_A -[[ "\\$par_uncompressed_bam" == "false" ]] && unset par_uncompressed_bam -[[ "\\$par_same_strand" == "false" ]] && unset par_same_strand -[[ "\\$par_opposite_strand" == "false" ]] && unset par_opposite_strand -[[ "\\$par_reciprocal_overlap" == "false" ]] && unset par_reciprocal_overlap -[[ "\\$par_either_overlap" == "false" ]] && unset par_either_overlap -[[ "\\$par_split" == "false" ]] && unset par_split -[[ "\\$par_nonamecheck" == "false" ]] && unset par_nonamecheck -[[ "\\$par_sorted" == "false" ]] && unset par_sorted -[[ "\\$par_filenames" == "false" ]] && unset par_filenames -[[ "\\$par_sortout" == "false" ]] && unset par_sortout -[[ "\\$par_bed" == "false" ]] && unset par_bed -[[ "\\$par_header" == "false" ]] && unset par_header -[[ "\\$par_no_buffer_output" == "false" ]] && unset par_no_buffer_output +unset_if_false=( + par_write_a + par_write_b + par_left_outer_join + par_write_overlap + par_write_overlap_plus + par_report_A_if_no_overlap + par_number_of_overlaps_A + par_report_no_overlaps_A + par_uncompressed_bam + par_same_strand + par_opposite_strand + par_reciprocal_overlap + par_either_overlap + par_split + par_nonamecheck + par_sorted + par_filenames + par_sortout + par_bed + par_no_buffer_output + par_header +) + +for par in \\${unset_if_false[@]}; do + test_val="\\${!par}" + [[ "\\$test_val" == "false" ]] && unset \\$par +done + # Create input array IFS=";" read -ra input <<< \\$par_input_b diff --git a/target/nextflow/bedtools/bedtools_sort/.config.vsh.yaml b/target/nextflow/bedtools/bedtools_sort/.config.vsh.yaml index e291efaf..2a3701c4 100644 --- a/target/nextflow/bedtools/bedtools_sort/.config.vsh.yaml +++ b/target/nextflow/bedtools/bedtools_sort/.config.vsh.yaml @@ -222,7 +222,7 @@ build_info: output: "target/nextflow/bedtools/bedtools_sort" executable: "target/nextflow/bedtools/bedtools_sort/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/bedtools/bedtools_sort/main.nf b/target/nextflow/bedtools/bedtools_sort/main.nf index db020f24..37f080c1 100644 --- a/target/nextflow/bedtools/bedtools_sort/main.nf +++ b/target/nextflow/bedtools/bedtools_sort/main.nf @@ -3066,7 +3066,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/bedtools/bedtools_sort", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { @@ -3143,13 +3143,20 @@ $( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" ## VIASH END # Unset parameters -[[ "\\$par_sizeA" == "false" ]] && unset par_sizeA -[[ "\\$par_sizeD" == "false" ]] && unset par_sizeD -[[ "\\$par_chrThenSizeA" == "false" ]] && unset par_chrThenSizeA -[[ "\\$par_chrThenSizeD" == "false" ]] && unset par_chrThenSizeD -[[ "\\$par_chrThenScoreA" == "false" ]] && unset par_chrThenScoreA -[[ "\\$par_chrThenScoreD" == "false" ]] && unset par_chrThenScoreD -[[ "\\$par_header" == "false" ]] && unset par_header +unset_if_false=( + par_sizeA + par_sizeD + par_chrThenSizeA + par_chrThenSizeD + par_chrThenScoreA + par_chrThenScoreD + par_header +) + +for par in \\${unset_if_false[@]}; do + test_val="\\${!par}" + [[ "\\$test_val" == "false" ]] && unset \\$par +done # Execute bedtools sort with the provided arguments bedtools sort \\\\ diff --git a/target/nextflow/busco/busco_download_datasets/.config.vsh.yaml b/target/nextflow/busco/busco_download_datasets/.config.vsh.yaml index be21b050..c61be1b4 100644 --- a/target/nextflow/busco/busco_download_datasets/.config.vsh.yaml +++ b/target/nextflow/busco/busco_download_datasets/.config.vsh.yaml @@ -158,7 +158,7 @@ build_info: output: "target/nextflow/busco/busco_download_datasets" executable: "target/nextflow/busco/busco_download_datasets/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/busco/busco_download_datasets/main.nf b/target/nextflow/busco/busco_download_datasets/main.nf index af68d99b..4cba66c4 100644 --- a/target/nextflow/busco/busco_download_datasets/main.nf +++ b/target/nextflow/busco/busco_download_datasets/main.nf @@ -2985,7 +2985,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/busco/busco_download_datasets", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { diff --git a/target/nextflow/busco/busco_list_datasets/.config.vsh.yaml b/target/nextflow/busco/busco_list_datasets/.config.vsh.yaml index 5c652a8b..0f221099 100644 --- a/target/nextflow/busco/busco_list_datasets/.config.vsh.yaml +++ b/target/nextflow/busco/busco_list_datasets/.config.vsh.yaml @@ -145,7 +145,7 @@ build_info: output: "target/nextflow/busco/busco_list_datasets" executable: "target/nextflow/busco/busco_list_datasets/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/busco/busco_list_datasets/main.nf b/target/nextflow/busco/busco_list_datasets/main.nf index 5b9ceca1..2bd87c65 100644 --- a/target/nextflow/busco/busco_list_datasets/main.nf +++ b/target/nextflow/busco/busco_list_datasets/main.nf @@ -2971,7 +2971,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/busco/busco_list_datasets", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { diff --git a/target/nextflow/busco/busco_run/.config.vsh.yaml b/target/nextflow/busco/busco_run/.config.vsh.yaml index 82ba4e9e..353a6f7a 100644 --- a/target/nextflow/busco/busco_run/.config.vsh.yaml +++ b/target/nextflow/busco/busco_run/.config.vsh.yaml @@ -423,7 +423,7 @@ build_info: output: "target/nextflow/busco/busco_run" executable: "target/nextflow/busco/busco_run/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/busco/busco_run/main.nf b/target/nextflow/busco/busco_run/main.nf index dce90dac..6bc9ba38 100644 --- a/target/nextflow/busco/busco_run/main.nf +++ b/target/nextflow/busco/busco_run/main.nf @@ -3283,7 +3283,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/busco/busco_run", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { @@ -3376,18 +3376,24 @@ $( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" ## VIASH END +unset_if_false=( + par_tar + par_force + par_quiet + par_restart + par_auto_lineage + par_auto_lineage_euk + par_auto_lineage_prok + par_augustus + par_long + par_scaffold_composition + par_miniprot +) -[[ "\\$par_tar" == "false" ]] && unset par_tar -[[ "\\$par_force" == "false" ]] && unset par_force -[[ "\\$par_quiet" == "false" ]] && unset par_quiet -[[ "\\$par_restart" == "false" ]] && unset par_restart -[[ "\\$par_auto_lineage" == "false" ]] && unset par_auto_lineage -[[ "\\$par_auto_lineage_euk" == "false" ]] && unset par_auto_lineage_euk -[[ "\\$par_auto_lineage_prok" == "false" ]] && unset par_auto_lineage_prok -[[ "\\$par_augustus" == "false" ]] && unset par_augustus -[[ "\\$par_long" == "false" ]] && unset par_long -[[ "\\$par_scaffold_composition" == "false" ]] && unset par_scaffold_composition -[[ "\\$par_miniprot" == "false" ]] && unset par_miniprot +for par in \\${unset_if_false[@]}; do + test_val="\\${!par}" + [[ "\\$test_val" == "false" ]] && unset \\$par +done tmp_dir=\\$(mktemp -d -p "\\$meta_temp_dir" busco_XXXXXXXXX) prefix=\\$(openssl rand -hex 8) diff --git a/target/nextflow/busco/busco_run/nextflow_schema.json b/target/nextflow/busco/busco_run/nextflow_schema.json new file mode 100644 index 00000000..64390d89 --- /dev/null +++ b/target/nextflow/busco/busco_run/nextflow_schema.json @@ -0,0 +1,471 @@ +{ +"$schema": "http://json-schema.org/draft-07/schema", +"title": "busco_run", +"description": "Assessment of genome assembly and annotation completeness with single copy orthologs", +"type": "object", +"definitions": { + + + + "inputs" : { + "title": "Inputs", + "type": "object", + "description": "No description", + "properties": { + + + "input": { + "type": + "string", + "description": "Type: `file`, required, example: `file.fasta`. Input sequence file in FASTA format", + "help_text": "Type: `file`, required, example: `file.fasta`. Input sequence file in FASTA format. Can be an assembled genome or transcriptome (DNA), or protein sequences from an annotated gene set. Also possible to use a path to a directory containing multiple input files.\n" + + } + + + , + "mode": { + "type": + "string", + "description": "Type: `string`, required, example: `proteins`, choices: ``genome`, `geno`, `transcriptome`, `tran`, `proteins`, `prot``. Specify which BUSCO analysis mode to run", + "help_text": "Type: `string`, required, example: `proteins`, choices: ``genome`, `geno`, `transcriptome`, `tran`, `proteins`, `prot``. Specify which BUSCO analysis mode to run. There are three valid modes:\n - geno or genome, for genome assemblies (DNA)\n - tran or transcriptome, for transcriptome assemblies (DNA)\n - prot or proteins, for annotated gene sets (protein)\n", + "enum": ["genome", "geno", "transcriptome", "tran", "proteins", "prot"] + + + } + + + , + "lineage_dataset": { + "type": + "string", + "description": "Type: `string`, example: `stramenopiles_odb10`. Specify a BUSCO lineage dataset that is most closely related to the assembly or gene set being assessed", + "help_text": "Type: `string`, example: `stramenopiles_odb10`. Specify a BUSCO lineage dataset that is most closely related to the assembly or gene set being assessed. \nThe full list of available datasets can be viewed [here](https://busco-data.ezlab.org/v5/data/lineages/) or by running the busco/busco_list_datasets component.\nWhen unsure, the \"--auto_lineage\" flag can be set to automatically find the optimal lineage path.\nBUSCO will automatically download the requested dataset if it is not already present in the download folder. \nYou can optionally provide a path to a local dataset instead of a name, e.g. path/to/dataset.\nDatasets can be downloaded using the busco/busco_download_dataset component.\n" + + } + + +} +}, + + + "outputs" : { + "title": "Outputs", + "type": "object", + "description": "No description", + "properties": { + + + "short_summary_json": { + "type": + "string", + "description": "Type: `file`, default: `$id.$key.short_summary_json.json`, example: `short_summary.json`. Output file for short summary in JSON format", + "help_text": "Type: `file`, default: `$id.$key.short_summary_json.json`, example: `short_summary.json`. Output file for short summary in JSON format.\n" + , + "default": "$id.$key.short_summary_json.json" + } + + + , + "short_summary_txt": { + "type": + "string", + "description": "Type: `file`, default: `$id.$key.short_summary_txt.txt`, example: `short_summary.txt`. Output file for short summary in TXT format", + "help_text": "Type: `file`, default: `$id.$key.short_summary_txt.txt`, example: `short_summary.txt`. Output file for short summary in TXT format.\n" + , + "default": "$id.$key.short_summary_txt.txt" + } + + + , + "full_table": { + "type": + "string", + "description": "Type: `file`, default: `$id.$key.full_table.tsv`, example: `full_table.tsv`. Full table output in TSV format", + "help_text": "Type: `file`, default: `$id.$key.full_table.tsv`, example: `full_table.tsv`. Full table output in TSV format.\n" + , + "default": "$id.$key.full_table.tsv" + } + + + , + "missing_busco_list": { + "type": + "string", + "description": "Type: `file`, default: `$id.$key.missing_busco_list.tsv`, example: `missing_busco_list.tsv`. Missing list output in TSV format", + "help_text": "Type: `file`, default: `$id.$key.missing_busco_list.tsv`, example: `missing_busco_list.tsv`. Missing list output in TSV format.\n" + , + "default": "$id.$key.missing_busco_list.tsv" + } + + + , + "output_dir": { + "type": + "string", + "description": "Type: `file`, default: `$id.$key.output_dir.output_dir`, example: `output_dir/`. The full output directory, if so desired", + "help_text": "Type: `file`, default: `$id.$key.output_dir.output_dir`, example: `output_dir/`. The full output directory, if so desired.\n" + , + "default": "$id.$key.output_dir.output_dir" + } + + +} +}, + + + "resource and run settings" : { + "title": "Resource and Run Settings", + "type": "object", + "description": "No description", + "properties": { + + + "force": { + "type": + "boolean", + "description": "Type: `boolean_true`, default: `false`. Force rewriting of existing files", + "help_text": "Type: `boolean_true`, default: `false`. Force rewriting of existing files. Must be used when output files with the provided name already exist.\n" + , + "default": "False" + } + + + , + "quiet": { + "type": + "boolean", + "description": "Type: `boolean_true`, default: `false`. Disable the info logs, displays only errors", + "help_text": "Type: `boolean_true`, default: `false`. Disable the info logs, displays only errors.\n" + , + "default": "False" + } + + + , + "restart": { + "type": + "boolean", + "description": "Type: `boolean_true`, default: `false`. Continue a run that had already partially completed", + "help_text": "Type: `boolean_true`, default: `false`. Continue a run that had already partially completed. Restarting skips calls to tools that have completed but performs all pre- and post-processing steps.\n" + , + "default": "False" + } + + + , + "tar": { + "type": + "boolean", + "description": "Type: `boolean_true`, default: `false`. Compress some subdirectories with many files to save space", + "help_text": "Type: `boolean_true`, default: `false`. Compress some subdirectories with many files to save space.\n" + , + "default": "False" + } + + +} +}, + + + "lineage dataset settings" : { + "title": "Lineage Dataset Settings", + "type": "object", + "description": "No description", + "properties": { + + + "auto_lineage": { + "type": + "boolean", + "description": "Type: `boolean_true`, default: `false`. Run auto-lineage pipelilne to automatically determine BUSCO lineage dataset that is most closely related to the assembly or gene set being assessed", + "help_text": "Type: `boolean_true`, default: `false`. Run auto-lineage pipelilne to automatically determine BUSCO lineage dataset that is most closely related to the assembly or gene set being assessed.\n" + , + "default": "False" + } + + + , + "auto_lineage_euk": { + "type": + "boolean", + "description": "Type: `boolean_true`, default: `false`. Run auto-placement just on eukaryota tree to find optimal lineage path", + "help_text": "Type: `boolean_true`, default: `false`. Run auto-placement just on eukaryota tree to find optimal lineage path.\n" + , + "default": "False" + } + + + , + "auto_lineage_prok": { + "type": + "boolean", + "description": "Type: `boolean_true`, default: `false`. Run auto_lineage just on prokaryota trees to find optimum lineage path", + "help_text": "Type: `boolean_true`, default: `false`. Run auto_lineage just on prokaryota trees to find optimum lineage path.\n" + , + "default": "False" + } + + + , + "datasets_version": { + "type": + "string", + "description": "Type: `string`, example: `odb10`. Specify the version of BUSCO datasets\n", + "help_text": "Type: `string`, example: `odb10`. Specify the version of BUSCO datasets\n" + + } + + +} +}, + + + "augustus settings" : { + "title": "Augustus Settings", + "type": "object", + "description": "No description", + "properties": { + + + "augustus": { + "type": + "boolean", + "description": "Type: `boolean_true`, default: `false`. Use augustus gene predictor for eukaryote runs", + "help_text": "Type: `boolean_true`, default: `false`. Use augustus gene predictor for eukaryote runs.\n" + , + "default": "False" + } + + + , + "augustus_parameters": { + "type": + "string", + "description": "Type: `string`, example: `--PARAM1=VALUE1,--PARAM2=VALUE2`. Additional parameters to be passed to Augustus (see Augustus documentation: https://github", + "help_text": "Type: `string`, example: `--PARAM1=VALUE1,--PARAM2=VALUE2`. Additional parameters to be passed to Augustus (see Augustus documentation: https://github.com/Gaius-Augustus/Augustus/blob/master/docs/RUNNING-AUGUSTUS.md).\nParameters should be contained within a single string, without whitespace and seperated by commas.\n" + + } + + + , + "augustus_species": { + "type": + "string", + "description": "Type: `string`. Specify the augustus species\n", + "help_text": "Type: `string`. Specify the augustus species\n" + + } + + + , + "long": { + "type": + "boolean", + "description": "Type: `boolean_true`, default: `false`. Optimize Augustus self-training mode", + "help_text": "Type: `boolean_true`, default: `false`. Optimize Augustus self-training mode. This adds considerably to the run time, but can improve results for some non-model organisms.\n" + , + "default": "False" + } + + +} +}, + + + "bbtools settings" : { + "title": "BBTools Settings", + "type": "object", + "description": "No description", + "properties": { + + + "contig_break": { + "type": + "integer", + "description": "Type: `integer`. Number of contiguous Ns to signify a break between contigs in BBTools analysis", + "help_text": "Type: `integer`. Number of contiguous Ns to signify a break between contigs in BBTools analysis.\n" + + } + + + , + "limit": { + "type": + "integer", + "description": "Type: `integer`. Number of candidate regions (contig or transcript) from the BLAST output to consider per BUSCO", + "help_text": "Type: `integer`. Number of candidate regions (contig or transcript) from the BLAST output to consider per BUSCO.\nThis option is only effective in pipelines using BLAST, i.e. the genome pipeline (see --augustus) or the prokaryota transcriptome pipeline.\n" + + } + + + , + "scaffold_composition": { + "type": + "boolean", + "description": "Type: `boolean_true`, default: `false`. Writes ACGTN content per scaffold to a file scaffold_composition", + "help_text": "Type: `boolean_true`, default: `false`. Writes ACGTN content per scaffold to a file scaffold_composition.txt.\n" + , + "default": "False" + } + + +} +}, + + + "blast settings" : { + "title": "BLAST Settings", + "type": "object", + "description": "No description", + "properties": { + + + "e_value": { + "type": + "number", + "description": "Type: `double`. E-value cutoff for BLAST searches", + "help_text": "Type: `double`. E-value cutoff for BLAST searches.\n" + + } + + +} +}, + + + "protein gene prediction settings" : { + "title": "Protein Gene Prediction settings", + "type": "object", + "description": "No description", + "properties": { + + + "miniprot": { + "type": + "boolean", + "description": "Type: `boolean_true`, default: `false`. Use Miniprot gene predictor", + "help_text": "Type: `boolean_true`, default: `false`. Use Miniprot gene predictor.\n" + , + "default": "False" + } + + +} +}, + + + "metaeuk settings" : { + "title": "MetaEuk Settings", + "type": "object", + "description": "No description", + "properties": { + + + "metaeuk": { + "type": + "boolean", + "description": "Type: `boolean_true`, default: `false`. Use Metaeuk gene predictor", + "help_text": "Type: `boolean_true`, default: `false`. Use Metaeuk gene predictor.\n" + , + "default": "False" + } + + + , + "metaeuk_parameters": { + "type": + "string", + "description": "Type: `string`, example: `--max-overlap=15,--min-exon-aa=15`. Pass additional arguments to Metaeuk for the first run (see Metaeuk documentation https://github", + "help_text": "Type: `string`, example: `--max-overlap=15,--min-exon-aa=15`. Pass additional arguments to Metaeuk for the first run (see Metaeuk documentation https://github.com/soedinglab/metaeuk).\nAll parameters should be contained within a single string with no white space, with each parameter separated by a comma.\n" + + } + + + , + "metaeuk_rerun_parameters": { + "type": + "string", + "description": "Type: `string`, example: `--max-overlap=15,--min-exon-aa=15`. Pass additional arguments to Metaeuk for the second run (see Metaeuk documentation https://github", + "help_text": "Type: `string`, example: `--max-overlap=15,--min-exon-aa=15`. Pass additional arguments to Metaeuk for the second run (see Metaeuk documentation https://github.com/soedinglab/metaeuk).\nAll parameters should be contained within a single string with no white space, with each parameter separated by a comma.\n" + + } + + +} +}, + + + "nextflow input-output arguments" : { + "title": "Nextflow input-output arguments", + "type": "object", + "description": "Input/output parameters for Nextflow itself. Please note that both publishDir and publish_dir are supported but at least one has to be configured.", + "properties": { + + + "publish_dir": { + "type": + "string", + "description": "Type: `string`, required, example: `output/`. Path to an output directory", + "help_text": "Type: `string`, required, example: `output/`. Path to an output directory." + + } + + + , + "param_list": { + "type": + "string", + "description": "Type: `string`, example: `my_params.yaml`. Allows inputting multiple parameter sets to initialise a Nextflow channel", + "help_text": "Type: `string`, example: `my_params.yaml`. Allows inputting multiple parameter sets to initialise a Nextflow channel. A `param_list` can either be a list of maps, a csv file, a json file, a yaml file, or simply a yaml blob.\n\n* A list of maps (as-is) where the keys of each map corresponds to the arguments of the pipeline. Example: in a `nextflow.config` file: `param_list: [ [\u0027id\u0027: \u0027foo\u0027, \u0027input\u0027: \u0027foo.txt\u0027], [\u0027id\u0027: \u0027bar\u0027, \u0027input\u0027: \u0027bar.txt\u0027] ]`.\n* A csv file should have column names which correspond to the different arguments of this pipeline. Example: `--param_list data.csv` with columns `id,input`.\n* A json or a yaml file should be a list of maps, each of which has keys corresponding to the arguments of the pipeline. Example: `--param_list data.json` with contents `[ {\u0027id\u0027: \u0027foo\u0027, \u0027input\u0027: \u0027foo.txt\u0027}, {\u0027id\u0027: \u0027bar\u0027, \u0027input\u0027: \u0027bar.txt\u0027} ]`.\n* A yaml blob can also be passed directly as a string. Example: `--param_list \"[ {\u0027id\u0027: \u0027foo\u0027, \u0027input\u0027: \u0027foo.txt\u0027}, {\u0027id\u0027: \u0027bar\u0027, \u0027input\u0027: \u0027bar.txt\u0027} ]\"`.\n\nWhen passing a csv, json or yaml file, relative path names are relativized to the location of the parameter file. No relativation is performed when `param_list` is a list of maps (as-is) or a yaml blob.", + "hidden": true + + } + + +} +} +}, +"allOf": [ + + { + "$ref": "#/definitions/inputs" + }, + + { + "$ref": "#/definitions/outputs" + }, + + { + "$ref": "#/definitions/resource and run settings" + }, + + { + "$ref": "#/definitions/lineage dataset settings" + }, + + { + "$ref": "#/definitions/augustus settings" + }, + + { + "$ref": "#/definitions/bbtools settings" + }, + + { + "$ref": "#/definitions/blast settings" + }, + + { + "$ref": "#/definitions/protein gene prediction settings" + }, + + { + "$ref": "#/definitions/metaeuk settings" + }, + + { + "$ref": "#/definitions/nextflow input-output arguments" + } +] +} diff --git a/target/nextflow/cutadapt/.config.vsh.yaml b/target/nextflow/cutadapt/.config.vsh.yaml index c20c4158..59424cc3 100644 --- a/target/nextflow/cutadapt/.config.vsh.yaml +++ b/target/nextflow/cutadapt/.config.vsh.yaml @@ -740,7 +740,7 @@ build_info: output: "target/nextflow/cutadapt" executable: "target/nextflow/cutadapt/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/cutadapt/main.nf b/target/nextflow/cutadapt/main.nf index 896eff9a..f04b4c3f 100644 --- a/target/nextflow/cutadapt/main.nf +++ b/target/nextflow/cutadapt/main.nf @@ -3593,7 +3593,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/cutadapt", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { diff --git a/target/nextflow/falco/.config.vsh.yaml b/target/nextflow/falco/.config.vsh.yaml index dd968924..1da2720d 100644 --- a/target/nextflow/falco/.config.vsh.yaml +++ b/target/nextflow/falco/.config.vsh.yaml @@ -317,7 +317,7 @@ build_info: output: "target/nextflow/falco" executable: "target/nextflow/falco/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/falco/main.nf b/target/nextflow/falco/main.nf index 4be4c595..ddde22db 100644 --- a/target/nextflow/falco/main.nf +++ b/target/nextflow/falco/main.nf @@ -3144,7 +3144,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/falco", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { diff --git a/target/nextflow/fastp/.config.vsh.yaml b/target/nextflow/fastp/.config.vsh.yaml index 3885d73b..28f262b8 100644 --- a/target/nextflow/fastp/.config.vsh.yaml +++ b/target/nextflow/fastp/.config.vsh.yaml @@ -1083,7 +1083,7 @@ build_info: output: "target/nextflow/fastp" executable: "target/nextflow/fastp/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/fastp/main.nf b/target/nextflow/fastp/main.nf index 7d611b96..1b9685d0 100644 --- a/target/nextflow/fastp/main.nf +++ b/target/nextflow/fastp/main.nf @@ -3997,7 +3997,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/fastp", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { @@ -4139,25 +4139,32 @@ $( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" ## VIASH END # disable flags -[[ "\\$par_disable_adapter_trimming" == "false" ]] && unset par_disable_adapter_trimming -[[ "\\$par_detect_adapter_for_pe" == "false" ]] && unset par_detect_adapter_for_pe -[[ "\\$par_merge" == "false" ]] && unset par_merge -[[ "\\$par_include_unmerged" == "false" ]] && unset par_include_unmerged -[[ "\\$par_interleaved_in" == "false" ]] && unset par_interleaved_in -[[ "\\$par_fix_mgi_id" == "false" ]] && unset par_fix_mgi_id -[[ "\\$par_phred64" == "false" ]] && unset par_phred64 -[[ "\\$par_dont_overwrite" == "false" ]] && unset par_dont_overwrite -[[ "\\$par_verbose" == "false" ]] && unset par_verbose -[[ "\\$par_dedup" == "false" ]] && unset par_dedup -[[ "\\$par_dont_eval_duplication" == "false" ]] && unset par_dont_eval_duplication -[[ "\\$par_trim_poly_g" == "false" ]] && unset par_trim_poly_g -[[ "\\$par_disable_trim_poly_g" == "false" ]] && unset par_disable_trim_poly_g -[[ "\\$par_trim_poly_x" == "false" ]] && unset par_trim_poly_x -[[ "\\$par_disable_quality_filtering" == "false" ]] && unset par_disable_quality_filtering -[[ "\\$par_disable_length_filtering" == "false" ]] && unset par_disable_length_filtering -[[ "\\$par_low_complexity_filter" == "false" ]] && unset par_low_complexity_filter -[[ "\\$par_umi" == "false" ]] && unset par_umi -[[ "\\$par_overrepresentation_analysis" == "false" ]] && unset par_overrepresentation_analysis +unset_if_false=( + par_disable_adapter_trimming + par_detect_adapter_for_pe + par_merge + par_include_unmerged + par_interleaved_in + par_fix_mgi_id + par_phred64 + par_dont_overwrite + par_verbose + par_dedup + par_dont_eval_duplication + par_trim_poly_g + par_disable_trim_poly_g + par_trim_poly_x + par_disable_quality_filtering + par_disable_length_filtering + par_low_complexity_filter + par_umi + par_overrepresentation_analysis +) + +for par in \\${unset_if_false[@]}; do + test_val="\\${!par}" + [[ "\\$test_val" == "false" ]] && unset \\$par +done # run command fastp \\\\ diff --git a/target/nextflow/featurecounts/.config.vsh.yaml b/target/nextflow/featurecounts/.config.vsh.yaml index bf17624f..4ba020bd 100644 --- a/target/nextflow/featurecounts/.config.vsh.yaml +++ b/target/nextflow/featurecounts/.config.vsh.yaml @@ -645,7 +645,7 @@ build_info: output: "target/nextflow/featurecounts" executable: "target/nextflow/featurecounts/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/featurecounts/main.nf b/target/nextflow/featurecounts/main.nf index dee49097..4383b6d0 100644 --- a/target/nextflow/featurecounts/main.nf +++ b/target/nextflow/featurecounts/main.nf @@ -3523,7 +3523,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/featurecounts", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { @@ -3648,24 +3648,31 @@ par_feature_type=\\$(echo \\$par_feature_type | tr ',' ';') par_extra_attributes=\\$(echo \\$par_extra_attributes | tr ',' ';') # unset flag variables -[[ "\\$par_feature_level" == "false" ]] && unset par_feature_level -[[ "\\$par_overlapping" == "false" ]] && unset par_overlapping -[[ "\\$par_largest_overlap" == "false" ]] && unset par_largest_overlap -[[ "\\$par_multi_mapping" == "false" ]] && unset par_multi_mapping -[[ "\\$par_fraction" == "false" ]] && unset par_fraction -[[ "\\$par_split_only" == "false" ]] && unset par_split_only -[[ "\\$par_non_split_only" == "false" ]] && unset par_non_split_only -[[ "\\$par_primary" == "false" ]] && unset par_primary -[[ "\\$par_ignore_dup" == "false" ]] && unset par_ignore_dup -[[ "\\$par_paired" == "false" ]] && unset par_paired -[[ "\\$par_count_read_pairs" == "false" ]] && unset par_count_read_pairs -[[ "\\$par_both_aligned" == "false" ]] && unset par_both_aligned -[[ "\\$par_check_pe_dist" == "false" ]] && unset par_check_pe_dist -[[ "\\$par_same_strand" == "false" ]] && unset par_same_strand -[[ "\\$par_donotsort" == "false" ]] && unset par_donotsort -[[ "\\$par_by_read_group" == "false" ]] && unset par_by_read_group -[[ "\\$par_long_reads" == "false" ]] && unset par_long_reads -[[ "\\$par_verbose" == "false" ]] && unset par_verbose +unset_if_false=( + par_feature_level + par_overlapping + par_largest_overlap + par_multi_mapping + par_fraction + par_split_only + par_non_split_only + par_primary + par_ignore_dup + par_paired + par_count_read_pairs + par_both_aligned + par_check_pe_dist + par_same_strand + par_donotsort + par_by_read_group + par_long_reads + par_verbose +) + +for par in \\${unset_if_false[@]}; do + test_val="\\${!par}" + [[ "\\$test_val" == "false" ]] && unset \\$par +done IFS=";" read -ra input <<< \\$par_input diff --git a/target/nextflow/gffread/.config.vsh.yaml b/target/nextflow/gffread/.config.vsh.yaml index fdbdc6a9..208da938 100644 --- a/target/nextflow/gffread/.config.vsh.yaml +++ b/target/nextflow/gffread/.config.vsh.yaml @@ -685,7 +685,7 @@ build_info: output: "target/nextflow/gffread" executable: "target/nextflow/gffread/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/gffread/main.nf b/target/nextflow/gffread/main.nf index 6f81a9dd..2c58fc24 100644 --- a/target/nextflow/gffread/main.nf +++ b/target/nextflow/gffread/main.nf @@ -3580,7 +3580,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/gffread", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { @@ -3710,51 +3710,58 @@ $( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" ## VIASH END # unset flags -[[ "\\$par_coding" == "false" ]] && unset par_coding -[[ "\\$par_strict_range" == "false" ]] && unset par_strict_range -[[ "\\$par_no_single_exon" == "false" ]] && unset par_no_single_exon -[[ "\\$par_no_exon_attrs" == "false" ]] && unset par_no_exon_attrs -[[ "\\$par_nc" == "false" ]] && unset par_nc -[[ "\\$par_ignore_locus" == "false" ]] && unset par_ignore_locus -[[ "\\$par_description" == "false" ]] && unset par_description -[[ "\\$par_sort_alpha" == "false" ]] && unset par_sort_alpha -[[ "\\$par_keep_genes" == "false" ]] && unset par_keep_genes -[[ "\\$par_keep_attrs" == "false" ]] && unset par_keep_attrs -[[ "\\$par_keep_exon_attrs" == "false" ]] && unset par_keep_exon_attrs -[[ "\\$par_keep_comments" == "false" ]] && unset par_keep_comments -[[ "\\$par_process_other" == "false" ]] && unset par_process_other -[[ "\\$par_rm_stop_codons" == "false" ]] && unset par_rm_stop_codons -[[ "\\$par_adj_cds_start" == "false" ]] && unset par_adj_cds_start -[[ "\\$par_opposite_strand" == "false" ]] && unset par_opposite_strand -[[ "\\$par_coding_status" == "false" ]] && unset par_coding_status -[[ "\\$par_add_hasCDS" == "false" ]] && unset par_add_hasCDS -[[ "\\$par_adj_stop" == "false" ]] && unset par_adj_stop -[[ "\\$par_rm_noncanon" == "false" ]] && unset par_rm_noncanon -[[ "\\$par_complete_cds" == "false" ]] && unset par_complete_cds -[[ "\\$par_no_pseudo" == "false" ]] && unset par_no_pseudo -[[ "\\$par_in_bed" == "false" ]] && unset par_in_bed -[[ "\\$par_in_tlf" == "false" ]] && unset par_in_tlf -[[ "\\$par_stream" == "false" ]] && unset par_stream -[[ "\\$par_merge" == "false" ]] && unset par_merge -[[ "\\$par_rm_redundant" == "false" ]] && unset par_rm_redundant -[[ "\\$par_no_boundary" == "false" ]] && unset par_no_boundary -[[ "\\$par_no_overlap" == "false" ]] && unset par_no_overlap -[[ "\\$par_force_exons" == "false" ]] && unset par_force_exons -[[ "\\$par_gene2exon" == "false" ]] && unset par_gene2exon -[[ "\\$par_t_adopt" == "false" ]] && unset par_t_adopt -[[ "\\$par_decode" == "false" ]] && unset par_decode -[[ "\\$par_merge_exons" == "false" ]] && unset par_merge_exons -[[ "\\$par_junctions" == "false" ]] && unset par_junctions -[[ "\\$par_w_nocds" == "false" ]] && unset par_w_nocds -[[ "\\$par_tr_cds" == "false" ]] && unset par_tr_cds -[[ "\\$par_w_coords" == "false" ]] && unset par_w_coords -[[ "\\$par_stop_dot" == "false" ]] && unset par_stop_dot -[[ "\\$par_id_version" == "false" ]] && unset par_id_version -[[ "\\$par_gtf_output" == "false" ]] && unset par_gtf_output -[[ "\\$par_bed" == "false" ]] && unset par_bed -[[ "\\$par_tlf" == "false" ]] && unset par_tlf -[[ "\\$par_expose_dups" == "false" ]] && unset par_expose_dups -[[ "\\$par_cluster_only" == "false" ]] && unset par_cluster_only +unset_if_false=( + par_coding + par_strict_range + par_no_single_exon + par_no_exon_attrs + par_nc + par_ignore_locus + par_description + par_sort_alpha + par_keep_genes + par_keep_attrs + par_keep_exon_attrs + par_keep_comments + par_process_other + par_rm_stop_codons + par_adj_cds_start + par_opposite_strand + par_coding_status + par_add_hasCDS + par_adj_stop + par_rm_noncanon + par_complete_cds + par_no_pseudo + par_in_bed + par_in_tlf + par_stream + par_merge + par_rm_redundant + par_no_boundary + par_no_overlap + par_force_exons + par_gene2exon + par_t_adopt + par_decode + par_merge_exons + par_junctions + par_w_nocds + par_tr_cds + par_w_coords + par_stop_dot + par_id_version + par_gtf_output + par_bed + par_tlf + par_expose_dups + par_cluster_only +) + +for par in \\${unset_if_false[@]}; do + test_val="\\${!par}" + [[ "\\$test_val" == "false" ]] && unset \\$par +done # if par_table is not empty, replace ";" with "," par_table=\\$(echo "\\$par_table" | tr ';' ',') diff --git a/target/nextflow/lofreq/lofreq_call/.config.vsh.yaml b/target/nextflow/lofreq/lofreq_call/.config.vsh.yaml index 87474b13..6ceb7a35 100644 --- a/target/nextflow/lofreq/lofreq_call/.config.vsh.yaml +++ b/target/nextflow/lofreq/lofreq_call/.config.vsh.yaml @@ -507,7 +507,7 @@ build_info: output: "target/nextflow/lofreq/lofreq_call" executable: "target/nextflow/lofreq/lofreq_call/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/lofreq/lofreq_call/main.nf b/target/nextflow/lofreq/lofreq_call/main.nf index 0652ec69..1141d34c 100644 --- a/target/nextflow/lofreq/lofreq_call/main.nf +++ b/target/nextflow/lofreq/lofreq_call/main.nf @@ -3388,7 +3388,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/lofreq/lofreq_call", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { @@ -3489,21 +3489,28 @@ $( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" ## VIASH END # Unset all parameters that are set to "false" -[[ "\\$par_no_baq" == "false" ]] && unset par_no_baq -[[ "\\$par_no_idaq" == "false" ]] && unset par_no_idaq -[[ "\\$par_del_baq" == "false" ]] && unset par_del_baq -[[ "\\$par_no_ext_baq" == "false" ]] && unset par_no_ext_baq -[[ "\\$par_no_mq" == "false" ]] && unset par_no_mq -[[ "\\$par_call_indels" == "false" ]] && unset par_call_indels -[[ "\\$par_only_indels" == "false" ]] && unset par_only_indels -[[ "\\$par_src_qual" == "false" ]] && unset par_src_qual -[[ "\\$par_illumina_13" == "false" ]] && unset par_illumina_13 -[[ "\\$par_use_orphan" == "false" ]] && unset par_use_orphan -[[ "\\$par_plp_summary_only" == "false" ]] && unset par_plp_summary_only -[[ "\\$par_no_default_filter" == "false" ]] && unset par_no_default_filter -[[ "\\$par_force_overwrite" == "false" ]] && unset par_force_overwrite -[[ "\\$par_verbose" == "false" ]] && unset par_verbose -[[ "\\$par_debug" == "false" ]] && unset par_debug +unset_if_false=( + par_no_baq + par_no_idaq + par_del_baq + par_no_ext_baq + par_no_mq + par_call_indels + par_only_indels + par_src_qual + par_illumina_13 + par_use_orphan + par_plp_summary_only + par_no_default_filter + par_force_overwrite + par_verbose + par_debug +) + +for par in \\${unset_if_false[@]}; do + test_val="\\${!par}" + [[ "\\$test_val" == "false" ]] && unset \\$par +done # Run lofreq call lofreq call \\\\ diff --git a/target/nextflow/lofreq/lofreq_indelqual/.config.vsh.yaml b/target/nextflow/lofreq/lofreq_indelqual/.config.vsh.yaml index fce81c02..3566bc19 100644 --- a/target/nextflow/lofreq/lofreq_indelqual/.config.vsh.yaml +++ b/target/nextflow/lofreq/lofreq_indelqual/.config.vsh.yaml @@ -215,7 +215,7 @@ build_info: output: "target/nextflow/lofreq/lofreq_indelqual" executable: "target/nextflow/lofreq/lofreq_indelqual/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/lofreq/lofreq_indelqual/main.nf b/target/nextflow/lofreq/lofreq_indelqual/main.nf index d01f9575..3b0658ec 100644 --- a/target/nextflow/lofreq/lofreq_indelqual/main.nf +++ b/target/nextflow/lofreq/lofreq_indelqual/main.nf @@ -3051,7 +3051,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/lofreq/lofreq_indelqual", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { diff --git a/target/nextflow/multiqc/.config.vsh.yaml b/target/nextflow/multiqc/.config.vsh.yaml index 580eef09..9d2c2581 100644 --- a/target/nextflow/multiqc/.config.vsh.yaml +++ b/target/nextflow/multiqc/.config.vsh.yaml @@ -456,7 +456,7 @@ build_info: output: "target/nextflow/multiqc" executable: "target/nextflow/multiqc/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/multiqc/main.nf b/target/nextflow/multiqc/main.nf index 5a93f4ae..5cfc4eb0 100644 --- a/target/nextflow/multiqc/main.nf +++ b/target/nextflow/multiqc/main.nf @@ -3340,7 +3340,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/multiqc", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { @@ -3441,26 +3441,32 @@ $( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" #!/bin/bash # disable flags -[[ "\\$par_ignore_symlinks" == "false" ]] && unset par_ignore_symlinks -[[ "\\$par_dirs" == "false" ]] && unset par_dirs -[[ "\\$par_full_names" == "false" ]] && unset par_full_names -[[ "\\$par_fn_as_s_name" == "false" ]] && unset par_fn_as_s_name -[[ "\\$par_profile_runtime" == "false" ]] && unset par_profile_runtime -[[ "\\$par_verbose" == "false" ]] && unset par_verbose -[[ "\\$par_quiet" == "false" ]] && unset par_quiet -[[ "\\$par_strict" == "false" ]] && unset par_strict -[[ "\\$par_development" == "false" ]] && unset par_development -[[ "\\$par_require_logs" == "false" ]] && unset par_require_logs -[[ "\\$par_no_megaqc_upload" == "false" ]] && unset par_no_megaqc_upload -[[ "\\$par_no_ansi" == "false" ]] && unset par_no_ansi -[[ "\\$par_flat" == "false" ]] && unset par_flat -[[ "\\$par_interactive" == "false" ]] && unset par_interactive -[[ "\\$par_static_plot_export" == "false" ]] && unset par_static_plot_export -[[ "\\$par_data_dir" == "false" ]] && unset par_data_dir -[[ "\\$par_no_data_dir" == "false" ]] && unset par_no_data_dir -[[ "\\$par_zip_data_dir" == "false" ]] && unset par_zip_data_dir -[[ "\\$par_pdf" == "false" ]] && unset par_pdf +unset_if_false=( + par_ignore_symlinks + par_dirs + par_full_names + par_fn_as_s_name + par_profile_runtime + par_verbose + par_quiet + par_strict + par_development + par_require_logs + par_no_megaqc_upload + par_no_ansi + par_flat + par_interactive + par_static_plot_export + par_data_dir + par_no_data_dir + par_zip_data_dir + par_pdf +) +for par in \\${unset_if_false[@]}; do + test_val="\\${!par}" + [[ "\\$test_val" == "false" ]] && unset \\$par +done # handle inputs out_dir=\\$(dirname "\\$par_output_report") diff --git a/target/nextflow/pear/.config.vsh.yaml b/target/nextflow/pear/.config.vsh.yaml index 4da23a4c..2b1ec956 100644 --- a/target/nextflow/pear/.config.vsh.yaml +++ b/target/nextflow/pear/.config.vsh.yaml @@ -398,7 +398,7 @@ build_info: output: "target/nextflow/pear" executable: "target/nextflow/pear/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/pear/main.nf b/target/nextflow/pear/main.nf index ceaa5828..853fb1c4 100644 --- a/target/nextflow/pear/main.nf +++ b/target/nextflow/pear/main.nf @@ -3233,7 +3233,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/pear", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { diff --git a/target/nextflow/salmon/salmon_index/.config.vsh.yaml b/target/nextflow/salmon/salmon_index/.config.vsh.yaml index 58dd224c..c3c40390 100644 --- a/target/nextflow/salmon/salmon_index/.config.vsh.yaml +++ b/target/nextflow/salmon/salmon_index/.config.vsh.yaml @@ -277,7 +277,7 @@ build_info: output: "target/nextflow/salmon/salmon_index" executable: "target/nextflow/salmon/salmon_index/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/salmon/salmon_index/main.nf b/target/nextflow/salmon/salmon_index/main.nf index fd7349b3..da9c2453 100644 --- a/target/nextflow/salmon/salmon_index/main.nf +++ b/target/nextflow/salmon/salmon_index/main.nf @@ -3103,7 +3103,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/salmon/salmon_index", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { @@ -3183,12 +3183,19 @@ $( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" ## VIASH END -[[ "\\$par_gencode" == "false" ]] && unset par_gencode -[[ "\\$par_features" == "false" ]] && unset par_features -[[ "\\$par_keep_duplicates" == "false" ]] && unset par_keep_duplicates -[[ "\\$par_keep_fixed_fasta" == "false" ]] && unset par_keep_fixed_fasta -[[ "\\$par_sparse" == "false" ]] && unset par_sparse -[[ "\\$par_no_clip" == "false" ]] && unset par_no_clip +unset_if_false=( + par_gencode + par_features + par_keep_duplicates + par_keep_fixed_fasta + par_sparse + par_no_clip +) + +for par in \\${unset_if_false[@]}; do + test_val="\\${!par}" + [[ "\\$test_val" == "false" ]] && unset \\$par +done tmp_dir=\\$(mktemp -d -p "\\$meta_temp_dir" "\\${meta_functionality_name}_XXXXXX") mkdir -p "\\$tmp_dir/temp" diff --git a/target/nextflow/salmon/salmon_quant/.config.vsh.yaml b/target/nextflow/salmon/salmon_quant/.config.vsh.yaml index c30624dc..c4bd21d0 100644 --- a/target/nextflow/salmon/salmon_quant/.config.vsh.yaml +++ b/target/nextflow/salmon/salmon_quant/.config.vsh.yaml @@ -1173,7 +1173,7 @@ build_info: output: "target/nextflow/salmon/salmon_quant" executable: "target/nextflow/salmon/salmon_quant/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/salmon/salmon_quant/main.nf b/target/nextflow/salmon/salmon_quant/main.nf index 3adb7a6f..a6fe62da 100644 --- a/target/nextflow/salmon/salmon_quant/main.nf +++ b/target/nextflow/salmon/salmon_quant/main.nf @@ -3938,7 +3938,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/salmon/salmon_quant", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { @@ -4095,49 +4095,55 @@ $( if [ ! -z ${VIASH_META_MEMORY_TIB+x} ]; then echo "${VIASH_META_MEMORY_TIB}" $( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" | sed "s#'#'\\"'\\"'#g;s#.*#meta_memory_pib='&'#" ; else echo "# meta_memory_pib="; fi ) ## VIASH END +unset_if_false=( + par_discard_orphans + par_ont + par_seq_bias + par_gc_bias + par_pos_bias + par_meta + par_discard_orphans_quasi + par_disable_chaining_heuristic + par_allow_dovetail + par_recover_orphans + par_mimicBT2 + par_mimic_strictBT2 + par_softclip + par_softclip_overhangs + par_full_length_alignment + par_hard_filter + par_write_mappings + par_write_qualities + par_alternative_init_mode + par_skip_quant + par_dump_eq + par_dump_eq_weights + par_reduce_GC_memory + par_init_uniform + par_no_length_correction + par_no_effective_length_correction + par_no_single_frag_prob + par_no_frag_length_dist + par_no_bias_length_threshold + par_useEM + par_useVBOpt + par_no_Gamma_draw + par_bootstrap_reproject + par_quiet + par_per_transcript_prior + par_per_nucleotide_prior + par_write_orphan_links + par_write_unmapped_names + par_no_error_model + par_sample_out + par_sample_unaligned + par_gencode +) -[[ "\\$par_discard_orphans" == "false" ]] && unset par_discard_orphans -[[ "\\$par_ont" == "false" ]] && unset par_ont -[[ "\\$par_seq_bias" == "false" ]] && unset par_seq_bias -[[ "\\$par_gc_bias" == "false" ]] && unset par_gc_bias -[[ "\\$par_pos_bias" == "false" ]] && unset par_pos_bias -[[ "\\$par_meta" == "false" ]] && unset par_meta -[[ "\\$par_discard_orphans_quasi" == "false" ]] && unset par_discard_orphans_quasi -[[ "\\$par_disable_chaining_heuristic" == "false" ]] && unset par_disable_chaining_heuristic -[[ "\\$par_allow_dovetail" == "false" ]] && unset par_allow_dovetail -[[ "\\$par_recover_orphans" == "false" ]] && unset par_recover_orphans -[[ "\\$par_mimicBT2" == "false" ]] && unset par_mimicBT2 -[[ "\\$par_mimic_strictBT2" == "false" ]] && unset par_mimic_strictBT2 -[[ "\\$par_softclip" == "false" ]] && unset par_softclip -[[ "\\$par_softclip_overhangs" == "false" ]] && unset par_softclip_overhangs -[[ "\\$par_full_length_alignment" == "false" ]] && unset par_full_length_alignment -[[ "\\$par_hard_filter" == "false" ]] && unset par_hard_filter -[[ "\\$par_write_mappings" == "false" ]] && unset par_write_mappings -[[ "\\$par_write_qualities" == "false" ]] && unset par_write_qualities -[[ "\\$par_alternative_init_mode" == "false" ]] && unset par_alternative_init_mode -[[ "\\$par_skip_quant" == "false" ]] && unset par_skip_quant -[[ "\\$par_dump_eq" == "false" ]] && unset par_dump_eq -[[ "\\$par_dump_eq_weights" == "false" ]] && unset par_dump_eq_weights -[[ "\\$par_reduce_GC_memory" == "false" ]] && unset par_reduce_GC_memory -[[ "\\$par_init_uniform" == "false" ]] && unset par_init_uniform -[[ "\\$par_no_length_correction" == "false" ]] && unset par_no_length_correction -[[ "\\$par_no_effective_length_correction" == "false" ]] && unset par_no_effective_length_correction -[[ "\\$par_no_single_frag_prob" == "false" ]] && unset par_no_single_frag_prob -[[ "\\$par_no_frag_length_dist" == "false" ]] && unset par_no_frag_length_dist -[[ "\\$par_no_bias_length_threshold" == "false" ]] && unset par_no_bias_length_threshold -[[ "\\$par_useEM" == "false" ]] && unset par_useEM -[[ "\\$par_useVBOpt" == "false" ]] && unset par_useVBOpt -[[ "\\$par_no_Gamma_draw" == "false" ]] && unset par_no_Gamma_draw -[[ "\\$par_bootstrap_reproject" == "false" ]] && unset par_bootstrap_reproject -[[ "\\$par_quiet" == "false" ]] && unset par_quiet -[[ "\\$par_per_transcript_prior" == "false" ]] && unset par_per_transcript_prior -[[ "\\$par_per_nucleotide_prior" == "false" ]] && unset par_per_nucleotide_prior -[[ "\\$par_write_orphan_links" == "false" ]] && unset par_write_orphan_links -[[ "\\$par_write_unmapped_names" == "false" ]] && unset par_write_unmapped_names -[[ "\\$par_no_error_model" == "false" ]] && unset par_no_error_model -[[ "\\$par_sample_out" == "false" ]] && unset par_sample_out -[[ "\\$par_sample_unaligned" == "false" ]] && unset par_sample_unaligned -[[ "\\$par_gencode" == "false" ]] && unset par_gencode +for par in \\${unset_if_false[@]}; do + test_val="\\${!par}" + [[ "\\$test_val" == "false" ]] && unset \\$par +done IFS=";" read -ra unmated_reads <<< \\$par_unmated_reads IFS=";" read -ra mates1 <<< \\$par_mates1 diff --git a/target/nextflow/samtools/samtools_collate/.config.vsh.yaml b/target/nextflow/samtools/samtools_collate/.config.vsh.yaml index 5c5036dd..b8a18346 100644 --- a/target/nextflow/samtools/samtools_collate/.config.vsh.yaml +++ b/target/nextflow/samtools/samtools_collate/.config.vsh.yaml @@ -264,7 +264,7 @@ build_info: output: "target/nextflow/samtools/samtools_collate" executable: "target/nextflow/samtools/samtools_collate/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/samtools/samtools_collate/main.nf b/target/nextflow/samtools/samtools_collate/main.nf index 34006567..faedab07 100644 --- a/target/nextflow/samtools/samtools_collate/main.nf +++ b/target/nextflow/samtools/samtools_collate/main.nf @@ -3114,7 +3114,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/samtools/samtools_collate", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { diff --git a/target/nextflow/samtools/samtools_faidx/.config.vsh.yaml b/target/nextflow/samtools/samtools_faidx/.config.vsh.yaml index cce7765b..f31dedcc 100644 --- a/target/nextflow/samtools/samtools_faidx/.config.vsh.yaml +++ b/target/nextflow/samtools/samtools_faidx/.config.vsh.yaml @@ -243,7 +243,7 @@ build_info: output: "target/nextflow/samtools/samtools_faidx" executable: "target/nextflow/samtools/samtools_faidx/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/samtools/samtools_faidx/main.nf b/target/nextflow/samtools/samtools_faidx/main.nf index 0ec566c2..ec97ef94 100644 --- a/target/nextflow/samtools/samtools_faidx/main.nf +++ b/target/nextflow/samtools/samtools_faidx/main.nf @@ -3086,7 +3086,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/samtools/samtools_faidx", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { diff --git a/target/nextflow/bedtools/bedtools_getfasta/nextflow_schema.json b/target/nextflow/samtools/samtools_faidx/nextflow_schema.json similarity index 50% rename from target/nextflow/bedtools/bedtools_getfasta/nextflow_schema.json rename to target/nextflow/samtools/samtools_faidx/nextflow_schema.json index c3f7e079..5e00f832 100644 --- a/target/nextflow/bedtools/bedtools_getfasta/nextflow_schema.json +++ b/target/nextflow/samtools/samtools_faidx/nextflow_schema.json @@ -1,46 +1,46 @@ { "$schema": "http://json-schema.org/draft-07/schema", -"title": "bedtools_getfasta", -"description": "Extract sequences from a FASTA file for each of the intervals defined in a BED/GFF/VCF file.", +"title": "samtools_faidx", +"description": "Indexes FASTA files to enable random access to fasta and fastq files.", "type": "object", "definitions": { - "input arguments" : { - "title": "Input arguments", + "inputs" : { + "title": "Inputs", "type": "object", "description": "No description", "properties": { - "input_fasta": { + "input": { "type": "string", - "description": "Type: `file`. FASTA file containing sequences for each interval specified in the input BED file", - "help_text": "Type: `file`. FASTA file containing sequences for each interval specified in the input BED file.\nThe headers in the input FASTA file must exactly match the chromosome column in the BED file.\n" + "description": "Type: `file`. FASTA input file", + "help_text": "Type: `file`. FASTA input file.\n" } , - "input_bed": { + "length": { "type": - "string", - "description": "Type: `file`. BED file containing intervals to extract from the FASTA file", - "help_text": "Type: `file`. BED file containing intervals to extract from the FASTA file.\nBED files containing a single region require a newline character\nat the end of the line, otherwise a blank output file is produced.\n" - - } - - - , - "rna": { - "type": - "boolean", - "description": "Type: `boolean_true`, default: `false`. The FASTA is RNA not DNA", - "help_text": "Type: `boolean_true`, default: `false`. The FASTA is RNA not DNA. Reverse complementation handled accordingly.\n" + "integer", + "description": "Type: `integer`, default: `60`. Length for FASTA sequence line wrapping", + "help_text": "Type: `integer`, default: `60`. Length for FASTA sequence line wrapping. If zero, this means do not\nline wrap. Defaults to the line length in the input file.\n" , - "default": "False" + "default": "60" + } + + + , + "region_file": { + "type": + "string", + "description": "Type: `file`. File of regions", + "help_text": "Type: `file`. File of regions. Format is chr:from-to. One per line.\nMust be used with --output to avoid sending output to stdout.\n" + } @@ -48,29 +48,8 @@ }, - "run arguments" : { - "title": "Run arguments", - "type": "object", - "description": "No description", - "properties": { - - - "strandedness": { - "type": - "boolean", - "description": "Type: `boolean_true`, default: `false`. Force strandedness", - "help_text": "Type: `boolean_true`, default: `false`. Force strandedness. If the feature occupies the antisense strand, the output sequence will\nbe reverse complemented. By default strandedness is not taken into account.\n" - , - "default": "False" - } - - -} -}, - - - "output arguments" : { - "title": "Output arguments", + "outputs" : { + "title": "Outputs", "type": "object", "description": "No description", "properties": { @@ -79,74 +58,84 @@ "output": { "type": "string", - "description": "Type: `file`, required, default: `$id.$key.output.output`. Output file where the output from the \u0027bedtools getfasta\u0027 commend will\nbe written to", - "help_text": "Type: `file`, required, default: `$id.$key.output.output`. Output file where the output from the \u0027bedtools getfasta\u0027 commend will\nbe written to.\n" + "description": "Type: `file`, required, default: `$id.$key.output.fasta`, example: `output.fasta`. Write output to file", + "help_text": "Type: `file`, required, default: `$id.$key.output.fasta`, example: `output.fasta`. Write output to file.\n" , - "default": "$id.$key.output.output" + "default": "$id.$key.output.fasta" } , - "tab": { + "mark_strand": { + "type": + "string", + "description": "Type: `string`, default: `rc`. Add strand indicator to sequence name", + "help_text": "Type: `string`, default: `rc`. Add strand indicator to sequence name. Options are:\n[ rc, no, sign, custom,\u003cpos\u003e,\u003cneg\u003e ]\n" + , + "default": "rc" + } + + + , + "fai_idx": { + "type": + "string", + "description": "Type: `file`, default: `$id.$key.fai_idx.fai`, example: `file.fa.fai`. Read/Write to specified index file (default file", + "help_text": "Type: `file`, default: `$id.$key.fai_idx.fai`, example: `file.fa.fai`. Read/Write to specified index file (default file.fa.fai).\n" + , + "default": "$id.$key.fai_idx.fai" + } + + + , + "gzi_idx": { + "type": + "string", + "description": "Type: `file`, default: `$id.$key.gzi_idx.gzi`, example: `file.fa.gz.gzi`. Read/Write to specified compressed file index (used with ", + "help_text": "Type: `file`, default: `$id.$key.gzi_idx.gzi`, example: `file.fa.gz.gzi`. Read/Write to specified compressed file index (used with .gz files, default file.fa.gz.gzi).\n" + , + "default": "$id.$key.gzi_idx.gzi" + } + + + , + "fastq": { "type": "boolean", - "description": "Type: `boolean_true`, default: `false`. Report extract sequences in a tab-delimited format instead of in FASTA format", - "help_text": "Type: `boolean_true`, default: `false`. Report extract sequences in a tab-delimited format instead of in FASTA format.\n" + "description": "Type: `boolean_true`, default: `false`. Read FASTQ files and output extracted sequences in FASTQ format", + "help_text": "Type: `boolean_true`, default: `false`. Read FASTQ files and output extracted sequences in FASTQ format. Same as using samtools fqidx.\n" + , + "default": "False" + } + + +} +}, + + + "options" : { + "title": "Options", + "type": "object", + "description": "No description", + "properties": { + + + "continue": { + "type": + "boolean", + "description": "Type: `boolean_true`, default: `false`. Continue working if a non-existent region is requested", + "help_text": "Type: `boolean_true`, default: `false`. Continue working if a non-existent region is requested.\n" , "default": "False" } , - "bed_out": { + "reverse_complement": { "type": "boolean", - "description": "Type: `boolean_true`, default: `false`. Report extract sequences in a tab-delimited BED format instead of in FASTA format", - "help_text": "Type: `boolean_true`, default: `false`. Report extract sequences in a tab-delimited BED format instead of in FASTA format.\n" - , - "default": "False" - } - - - , - "name": { - "type": - "boolean", - "description": "Type: `boolean_true`, default: `false`. Set the FASTA header for each extracted sequence to be the \"name\" and coordinate columns from the BED feature", - "help_text": "Type: `boolean_true`, default: `false`. Set the FASTA header for each extracted sequence to be the \"name\" and coordinate columns from the BED feature.\n" - , - "default": "False" - } - - - , - "name_only": { - "type": - "boolean", - "description": "Type: `boolean_true`, default: `false`. Set the FASTA header for each extracted sequence to be the \"name\" columns from the BED feature", - "help_text": "Type: `boolean_true`, default: `false`. Set the FASTA header for each extracted sequence to be the \"name\" columns from the BED feature.\n" - , - "default": "False" - } - - - , - "split": { - "type": - "boolean", - "description": "Type: `boolean_true`, default: `false`. When --input is in BED12 format, create a separate fasta entry for each block in a BED12 record,\nblocks being described in the 11th and 12th column of the BED", - "help_text": "Type: `boolean_true`, default: `false`. When --input is in BED12 format, create a separate fasta entry for each block in a BED12 record,\nblocks being described in the 11th and 12th column of the BED.\n" - , - "default": "False" - } - - - , - "full_header": { - "type": - "boolean", - "description": "Type: `boolean_true`, default: `false`. Use full fasta header", - "help_text": "Type: `boolean_true`, default: `false`. Use full fasta header. By default, only the word before the first space or tab is used.\n" + "description": "Type: `boolean_true`, default: `false`. Reverse complement sequences", + "help_text": "Type: `boolean_true`, default: `false`. Reverse complement sequences.\n" , "default": "False" } @@ -189,15 +178,15 @@ "allOf": [ { - "$ref": "#/definitions/input arguments" + "$ref": "#/definitions/inputs" }, { - "$ref": "#/definitions/run arguments" + "$ref": "#/definitions/outputs" }, { - "$ref": "#/definitions/output arguments" + "$ref": "#/definitions/options" }, { diff --git a/target/nextflow/samtools/samtools_fasta/.config.vsh.yaml b/target/nextflow/samtools/samtools_fasta/.config.vsh.yaml index 9ffd171f..db020266 100644 --- a/target/nextflow/samtools/samtools_fasta/.config.vsh.yaml +++ b/target/nextflow/samtools/samtools_fasta/.config.vsh.yaml @@ -433,7 +433,7 @@ build_info: output: "target/nextflow/samtools/samtools_fasta" executable: "target/nextflow/samtools/samtools_fasta/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/samtools/samtools_fasta/main.nf b/target/nextflow/samtools/samtools_fasta/main.nf index 1807ccff..f87fbf7c 100644 --- a/target/nextflow/samtools/samtools_fasta/main.nf +++ b/target/nextflow/samtools/samtools_fasta/main.nf @@ -3278,7 +3278,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/samtools/samtools_fasta", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { @@ -3370,11 +3370,18 @@ $( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" set -e -[[ "\\$par_no_suffix" == "false" ]] && unset par_no_suffix -[[ "\\$par_suffix" == "false" ]] && unset par_suffix -[[ "\\$par_use_oq" == "false" ]] && unset par_use_oq -[[ "\\$par_copy_tags" == "false" ]] && unset par_copy_tags -[[ "\\$par_casava" == "false" ]] && unset par_casava +unset_if_false=( + par_no_suffix + par_suffix + par_use_oq + par_copy_tags + par_casava +) + +for par in \\${unset_if_false[@]}; do + test_val="\\${!par}" + [[ "\\$test_val" == "false" ]] && unset \\$par +done if [[ "\\$meta_name" == "samtools_fasta" ]]; then subcommand=fasta diff --git a/target/nextflow/samtools/samtools_fastq/.config.vsh.yaml b/target/nextflow/samtools/samtools_fastq/.config.vsh.yaml index 9ef3efa3..33781464 100644 --- a/target/nextflow/samtools/samtools_fastq/.config.vsh.yaml +++ b/target/nextflow/samtools/samtools_fastq/.config.vsh.yaml @@ -433,7 +433,7 @@ build_info: output: "target/nextflow/samtools/samtools_fastq" executable: "target/nextflow/samtools/samtools_fastq/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/samtools/samtools_fastq/main.nf b/target/nextflow/samtools/samtools_fastq/main.nf index fe4f37ce..6f8c00f8 100644 --- a/target/nextflow/samtools/samtools_fastq/main.nf +++ b/target/nextflow/samtools/samtools_fastq/main.nf @@ -3278,7 +3278,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/samtools/samtools_fastq", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { @@ -3370,11 +3370,18 @@ $( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" set -e -[[ "\\$par_no_suffix" == "false" ]] && unset par_no_suffix -[[ "\\$par_suffix" == "false" ]] && unset par_suffix -[[ "\\$par_use_oq" == "false" ]] && unset par_use_oq -[[ "\\$par_copy_tags" == "false" ]] && unset par_copy_tags -[[ "\\$par_casava" == "false" ]] && unset par_casava +unset_if_false=( + par_no_suffix + par_suffix + par_use_oq + par_copy_tags + par_casava +) + +for par in \\${unset_if_false[@]}; do + test_val="\\${!par}" + [[ "\\$test_val" == "false" ]] && unset \\$par +done if [[ "\\$meta_name" == "samtools_fasta" ]]; then subcommand=fasta diff --git a/target/nextflow/samtools/samtools_fastq/nextflow_schema.json b/target/nextflow/samtools/samtools_fastq/nextflow_schema.json new file mode 100644 index 00000000..ecbf2b28 --- /dev/null +++ b/target/nextflow/samtools/samtools_fastq/nextflow_schema.json @@ -0,0 +1,348 @@ +{ +"$schema": "http://json-schema.org/draft-07/schema", +"title": "samtools_fastq", +"description": "Converts a SAM, BAM or CRAM to FASTQ format.", +"type": "object", +"definitions": { + + + + "inputs" : { + "title": "Inputs", + "type": "object", + "description": "No description", + "properties": { + + + "input": { + "type": + "string", + "description": "Type: `file`, required. input SAM/BAM/CRAM file", + "help_text": "Type: `file`, required. input SAM/BAM/CRAM file" + + } + + +} +}, + + + "outputs" : { + "title": "Outputs", + "type": "object", + "description": "No description", + "properties": { + + + "output": { + "type": + "string", + "description": "Type: `file`, required, default: `$id.$key.output.output`. output FASTQ file", + "help_text": "Type: `file`, required, default: `$id.$key.output.output`. output FASTQ file" + , + "default": "$id.$key.output.output" + } + + +} +}, + + + "options" : { + "title": "Options", + "type": "object", + "description": "No description", + "properties": { + + + "no_suffix": { + "type": + "boolean", + "description": "Type: `boolean_true`, default: `false`. By default, either \u0027/1\u0027 or \u0027/2\u0027 is added to the end of read names where the corresponding \nREAD1 or READ2 FLAG bit is set", + "help_text": "Type: `boolean_true`, default: `false`. By default, either \u0027/1\u0027 or \u0027/2\u0027 is added to the end of read names where the corresponding \nREAD1 or READ2 FLAG bit is set. Using -n causes read names to be left as they are.\n" + , + "default": "False" + } + + + , + "suffix": { + "type": + "boolean", + "description": "Type: `boolean_true`, default: `false`. Always add either \u0027/1\u0027 or \u0027/2\u0027 to the end of read names even when put into different files", + "help_text": "Type: `boolean_true`, default: `false`. Always add either \u0027/1\u0027 or \u0027/2\u0027 to the end of read names even when put into different files.\n" + , + "default": "False" + } + + + , + "use_oq": { + "type": + "boolean", + "description": "Type: `boolean_true`, default: `false`. Use quality values from OQ tags in preference to standard quality string if available", + "help_text": "Type: `boolean_true`, default: `false`. Use quality values from OQ tags in preference to standard quality string if available.\n" + , + "default": "False" + } + + + , + "singleton": { + "type": + "string", + "description": "Type: `file`. write singleton reads to FILE", + "help_text": "Type: `file`. write singleton reads to FILE." + + } + + + , + "copy_tags": { + "type": + "boolean", + "description": "Type: `boolean_true`, default: `false`. Copy RG, BC and QT tags to the FASTQ header line, if they exist", + "help_text": "Type: `boolean_true`, default: `false`. Copy RG, BC and QT tags to the FASTQ header line, if they exist.\n" + , + "default": "False" + } + + + , + "copy_tags_list": { + "type": + "string", + "description": "Type: `string`. Specify a comma-separated list of tags to copy to the FASTQ header line, if they exist", + "help_text": "Type: `string`. Specify a comma-separated list of tags to copy to the FASTQ header line, if they exist. \nTAGLIST can be blank or `*` to indicate all tags should be copied to the output. If using `*`, \nbe careful to quote it to avoid unwanted shell expansion.\n" + + } + + + , + "read1": { + "type": + "string", + "description": "Type: `file`, default: `$id.$key.read1.read1`. Write reads with the READ1 FLAG set (and READ2 not set) to FILE instead of outputting them", + "help_text": "Type: `file`, default: `$id.$key.read1.read1`. Write reads with the READ1 FLAG set (and READ2 not set) to FILE instead of outputting them. \nIf the -s option is used, only paired reads will be written to this file.\n" + , + "default": "$id.$key.read1.read1" + } + + + , + "read2": { + "type": + "string", + "description": "Type: `file`, default: `$id.$key.read2.read2`. Write reads with the READ2 FLAG set (and READ1 not set) to FILE instead of outputting them", + "help_text": "Type: `file`, default: `$id.$key.read2.read2`. Write reads with the READ2 FLAG set (and READ1 not set) to FILE instead of outputting them. \nIf the -s option is used, only paired reads will be written to this file.\n" + , + "default": "$id.$key.read2.read2" + } + + + , + "output_reads": { + "type": + "string", + "description": "Type: `file`, default: `$id.$key.output_reads.output_reads`. Write reads with either READ1 FLAG or READ2 flag set to FILE instead of outputting them to stdout", + "help_text": "Type: `file`, default: `$id.$key.output_reads.output_reads`. Write reads with either READ1 FLAG or READ2 flag set to FILE instead of outputting them to stdout. \nThis is equivalent to -1 FILE -2 FILE.\n" + , + "default": "$id.$key.output_reads.output_reads" + } + + + , + "output_reads_both": { + "type": + "string", + "description": "Type: `file`, default: `$id.$key.output_reads_both.output_reads_both`. Write reads where the READ1 and READ2 FLAG bits set are either both set or both unset to FILE \ninstead of outputting them", + "help_text": "Type: `file`, default: `$id.$key.output_reads_both.output_reads_both`. Write reads where the READ1 and READ2 FLAG bits set are either both set or both unset to FILE \ninstead of outputting them.\n" + , + "default": "$id.$key.output_reads_both.output_reads_both" + } + + + , + "filter_flags": { + "type": + "integer", + "description": "Type: `integer`, example: `0`. Only output alignments with all bits set in INT present in the FLAG field", + "help_text": "Type: `integer`, example: `0`. Only output alignments with all bits set in INT present in the FLAG field. INT can be specified \nin hex by beginning with \u00270x\u0027 (i.e. /^0x[0-9A-F]+/) or in octal by beginning with \u00270\u0027\n(i.e. /^0[0-7]+/). Default: `0`.\n" + + } + + + , + "excl_flags": { + "type": + "string", + "description": "Type: `string`, example: `0x900`. Do not output alignments with any bits set in INT present in the FLAG field", + "help_text": "Type: `string`, example: `0x900`. Do not output alignments with any bits set in INT present in the FLAG field. INT can be specified \nin hex by beginning with \u00270x\u0027 (i.e. /^0x[0-9A-F]+/) or in octal by beginning with \u00270\u0027 \n(i.e. /^0[0-7]+/). This defaults to 0x900 representing filtering of secondary and \nsupplementary alignments. Default: `0x900`.\n" + + } + + + , + "incl_flags": { + "type": + "string", + "description": "Type: `string`, example: `0`. Only output alignments with any bits set in INT present in the FLAG field", + "help_text": "Type: `string`, example: `0`. Only output alignments with any bits set in INT present in the FLAG field. INT can be specified \nin hex by beginning with \u00270x\u0027 (i.e. /^0x[0-9A-F]+/), in octal by beginning with \u00270\u0027\n(i.e. /^0[0-7]+/), as a decimal number not beginning with \u00270\u0027 or as a comma-separated list of \nflag names. Default: `0`.\n" + + } + + + , + "excl_flags_all": { + "type": + "integer", + "description": "Type: `integer`, example: `0`. Only EXCLUDE reads with all of the bits set in INT present in the FLAG field", + "help_text": "Type: `integer`, example: `0`. Only EXCLUDE reads with all of the bits set in INT present in the FLAG field. INT can be specified \nin hex by beginning with \u00270x\u0027 (i.e. /^0x[0-9A-F]+/) or in octal by beginning with \u00270\u0027 (i.e. /^0[0-7]+/).\nDefault: `0`.\n" + + } + + + , + "aux_tag": { + "type": + "string", + "description": "Type: `string`. Only output alignments containing an auxiliary tag matching both TAG and VAL", + "help_text": "Type: `string`. Only output alignments containing an auxiliary tag matching both TAG and VAL. If VAL is omitted \nthen any value is accepted. The tag types supported are i, f, Z, A and H. \"B\" arrays are not \nsupported. This is comparable to the method used in samtools view --tag. The option may be specified \nmultiple times and is equivalent to using the --aux_tag_file option.\n" + + } + + + , + "aux_tag_file": { + "type": + "string", + "description": "Type: `string`. Only output alignments containing an auxiliary tag matching TAG and having a value listed in FILE", + "help_text": "Type: `string`. Only output alignments containing an auxiliary tag matching TAG and having a value listed in FILE. \nThe format of the file is one line per value. This is equivalent to specifying --aux_tag multiple times.\n" + + } + + + , + "casava": { + "type": + "boolean", + "description": "Type: `boolean_true`, default: `false`. Add Illumina Casava 1", + "help_text": "Type: `boolean_true`, default: `false`. Add Illumina Casava 1.8 format entry to header, for example: `1:N:0:ATCACG`.\n" + , + "default": "False" + } + + + , + "compression": { + "type": + "integer", + "description": "Type: `integer`, example: `0`. set compression level when writing gz or bgzf fastq files", + "help_text": "Type: `integer`, example: `0`. set compression level when writing gz or bgzf fastq files." + + } + + + , + "index1": { + "type": + "string", + "description": "Type: `file`. write first index reads to FILE", + "help_text": "Type: `file`. write first index reads to FILE." + + } + + + , + "index2": { + "type": + "string", + "description": "Type: `file`. write second index reads to FILE", + "help_text": "Type: `file`. write second index reads to FILE." + + } + + + , + "barcode_tag": { + "type": + "string", + "description": "Type: `string`, example: `BC`. Auxiliary tag to find index reads in", + "help_text": "Type: `string`, example: `BC`. Auxiliary tag to find index reads in. Default: `BC`.\n" + + } + + + , + "quality_tag": { + "type": + "string", + "description": "Type: `string`, example: `QT`. Auxiliary tag to find index quality in", + "help_text": "Type: `string`, example: `QT`. Auxiliary tag to find index quality in. Default: `QT`.\n" + + } + + + , + "index_format": { + "type": + "string", + "description": "Type: `string`. string to describe how to parse the barcode and quality tags", + "help_text": "Type: `string`. string to describe how to parse the barcode and quality tags. For example:\n* `i14i8`: the first 14 characters are index 1, the next 8 characters are index 2.\n* `n8i14`: ignore the first 8 characters, and use the next 14 characters for index 1.\nIf the tag contains a separator, then the numeric part can be replaced with \u0027*\u0027 to mean \n\u0027read until the separator or end of tag\u0027, for example: `n*i*`.\n" + + } + + +} +}, + + + "nextflow input-output arguments" : { + "title": "Nextflow input-output arguments", + "type": "object", + "description": "Input/output parameters for Nextflow itself. Please note that both publishDir and publish_dir are supported but at least one has to be configured.", + "properties": { + + + "publish_dir": { + "type": + "string", + "description": "Type: `string`, required, example: `output/`. Path to an output directory", + "help_text": "Type: `string`, required, example: `output/`. Path to an output directory." + + } + + + , + "param_list": { + "type": + "string", + "description": "Type: `string`, example: `my_params.yaml`. Allows inputting multiple parameter sets to initialise a Nextflow channel", + "help_text": "Type: `string`, example: `my_params.yaml`. Allows inputting multiple parameter sets to initialise a Nextflow channel. A `param_list` can either be a list of maps, a csv file, a json file, a yaml file, or simply a yaml blob.\n\n* A list of maps (as-is) where the keys of each map corresponds to the arguments of the pipeline. Example: in a `nextflow.config` file: `param_list: [ [\u0027id\u0027: \u0027foo\u0027, \u0027input\u0027: \u0027foo.txt\u0027], [\u0027id\u0027: \u0027bar\u0027, \u0027input\u0027: \u0027bar.txt\u0027] ]`.\n* A csv file should have column names which correspond to the different arguments of this pipeline. Example: `--param_list data.csv` with columns `id,input`.\n* A json or a yaml file should be a list of maps, each of which has keys corresponding to the arguments of the pipeline. Example: `--param_list data.json` with contents `[ {\u0027id\u0027: \u0027foo\u0027, \u0027input\u0027: \u0027foo.txt\u0027}, {\u0027id\u0027: \u0027bar\u0027, \u0027input\u0027: \u0027bar.txt\u0027} ]`.\n* A yaml blob can also be passed directly as a string. Example: `--param_list \"[ {\u0027id\u0027: \u0027foo\u0027, \u0027input\u0027: \u0027foo.txt\u0027}, {\u0027id\u0027: \u0027bar\u0027, \u0027input\u0027: \u0027bar.txt\u0027} ]\"`.\n\nWhen passing a csv, json or yaml file, relative path names are relativized to the location of the parameter file. No relativation is performed when `param_list` is a list of maps (as-is) or a yaml blob.", + "hidden": true + + } + + +} +} +}, +"allOf": [ + + { + "$ref": "#/definitions/inputs" + }, + + { + "$ref": "#/definitions/outputs" + }, + + { + "$ref": "#/definitions/options" + }, + + { + "$ref": "#/definitions/nextflow input-output arguments" + } +] +} diff --git a/target/nextflow/samtools/samtools_flagstat/.config.vsh.yaml b/target/nextflow/samtools/samtools_flagstat/.config.vsh.yaml index 698bbbba..9efe148e 100644 --- a/target/nextflow/samtools/samtools_flagstat/.config.vsh.yaml +++ b/target/nextflow/samtools/samtools_flagstat/.config.vsh.yaml @@ -173,7 +173,7 @@ build_info: output: "target/nextflow/samtools/samtools_flagstat" executable: "target/nextflow/samtools/samtools_flagstat/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/samtools/samtools_flagstat/main.nf b/target/nextflow/samtools/samtools_flagstat/main.nf index 2b9c65e4..37621953 100644 --- a/target/nextflow/samtools/samtools_flagstat/main.nf +++ b/target/nextflow/samtools/samtools_flagstat/main.nf @@ -3002,7 +3002,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/samtools/samtools_flagstat", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { diff --git a/target/nextflow/busco/busco_list_datasets/nextflow_schema.json b/target/nextflow/samtools/samtools_flagstat/nextflow_schema.json similarity index 71% rename from target/nextflow/busco/busco_list_datasets/nextflow_schema.json rename to target/nextflow/samtools/samtools_flagstat/nextflow_schema.json index c2f65754..6c3cfd06 100644 --- a/target/nextflow/busco/busco_list_datasets/nextflow_schema.json +++ b/target/nextflow/samtools/samtools_flagstat/nextflow_schema.json @@ -1,12 +1,42 @@ { "$schema": "http://json-schema.org/draft-07/schema", -"title": "busco_list_datasets", -"description": "Lists the available busco datasets", +"title": "samtools_flagstat", +"description": "Counts the number of alignments in SAM/BAM/CRAM files for each FLAG type.", "type": "object", "definitions": { + "inputs" : { + "title": "Inputs", + "type": "object", + "description": "No description", + "properties": { + + + "bam": { + "type": + "string", + "description": "Type: `file`. BAM input files", + "help_text": "Type: `file`. BAM input files.\n" + + } + + + , + "bai": { + "type": + "string", + "description": "Type: `file`. BAM index file", + "help_text": "Type: `file`. BAM index file.\n" + + } + + +} +}, + + "outputs" : { "title": "Outputs", "type": "object", @@ -17,10 +47,10 @@ "output": { "type": "string", - "description": "Type: `file`, default: `$id.$key.output.txt`, example: `file.txt`. Output file of the available busco datasets\n", - "help_text": "Type: `file`, default: `$id.$key.output.txt`, example: `file.txt`. Output file of the available busco datasets\n" + "description": "Type: `file`, required, default: `$id.$key.output.flagstat`, example: `output.flagstat`. File containing samtools stats output", + "help_text": "Type: `file`, required, default: `$id.$key.output.flagstat`, example: `output.flagstat`. File containing samtools stats output.\n" , - "default": "$id.$key.output.txt" + "default": "$id.$key.output.flagstat" } @@ -60,6 +90,10 @@ }, "allOf": [ + { + "$ref": "#/definitions/inputs" + }, + { "$ref": "#/definitions/outputs" }, diff --git a/target/nextflow/samtools/samtools_idxstats/.config.vsh.yaml b/target/nextflow/samtools/samtools_idxstats/.config.vsh.yaml index ccfe6611..da949b68 100644 --- a/target/nextflow/samtools/samtools_idxstats/.config.vsh.yaml +++ b/target/nextflow/samtools/samtools_idxstats/.config.vsh.yaml @@ -183,7 +183,7 @@ build_info: output: "target/nextflow/samtools/samtools_idxstats" executable: "target/nextflow/samtools/samtools_idxstats/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/samtools/samtools_idxstats/main.nf b/target/nextflow/samtools/samtools_idxstats/main.nf index 243c5ba7..8bee0da7 100644 --- a/target/nextflow/samtools/samtools_idxstats/main.nf +++ b/target/nextflow/samtools/samtools_idxstats/main.nf @@ -3014,7 +3014,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/samtools/samtools_idxstats", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { diff --git a/target/nextflow/samtools/samtools_index/.config.vsh.yaml b/target/nextflow/samtools/samtools_index/.config.vsh.yaml index 4c915f1a..3cae8bb3 100644 --- a/target/nextflow/samtools/samtools_index/.config.vsh.yaml +++ b/target/nextflow/samtools/samtools_index/.config.vsh.yaml @@ -189,7 +189,7 @@ build_info: output: "target/nextflow/samtools/samtools_index" executable: "target/nextflow/samtools/samtools_index/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/samtools/samtools_index/main.nf b/target/nextflow/samtools/samtools_index/main.nf index a8b0a58c..b84216a2 100644 --- a/target/nextflow/samtools/samtools_index/main.nf +++ b/target/nextflow/samtools/samtools_index/main.nf @@ -3027,7 +3027,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/samtools/samtools_index", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { diff --git a/target/nextflow/samtools/samtools_sort/.config.vsh.yaml b/target/nextflow/samtools/samtools_sort/.config.vsh.yaml index 24e198bf..ce1e3474 100644 --- a/target/nextflow/samtools/samtools_sort/.config.vsh.yaml +++ b/target/nextflow/samtools/samtools_sort/.config.vsh.yaml @@ -332,7 +332,7 @@ build_info: output: "target/nextflow/samtools/samtools_sort" executable: "target/nextflow/samtools/samtools_sort/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/samtools/samtools_sort/main.nf b/target/nextflow/samtools/samtools_sort/main.nf index 68de2e1e..97e332b2 100644 --- a/target/nextflow/samtools/samtools_sort/main.nf +++ b/target/nextflow/samtools/samtools_sort/main.nf @@ -3199,7 +3199,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/samtools/samtools_sort", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { @@ -3287,15 +3287,22 @@ $( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" set -e -[[ "\\$par_uncompressed" == "false" ]] && unset par_uncompressed -[[ "\\$par_minimiser" == "false" ]] && unset par_minimiser -[[ "\\$par_not_reverse" == "false" ]] && unset par_not_reverse -[[ "\\$par_homopolymers" == "false" ]] && unset par_homopolymers -[[ "\\$par_natural_sort" == "false" ]] && unset par_natural_sort -[[ "\\$par_ascii_sort" == "false" ]] && unset par_ascii_sort -[[ "\\$par_template_coordinate" == "false" ]] && unset par_template_coordinate -[[ "\\$par_write_index" == "false" ]] && unset par_write_index -[[ "\\$par_no_PG" == "false" ]] && unset par_no_PG +unset_if_false=( + par_uncompressed + par_minimiser + par_not_reverse + par_homopolymers + par_natural_sort + par_ascii_sort + par_template_coordinate + par_write_index + par_no_PG +) + +for par in \\${unset_if_false[@]}; do + test_val="\\${!par}" + [[ "\\$test_val" == "false" ]] && unset \\$par +done samtools sort \\\\ diff --git a/target/nextflow/samtools/samtools_stats/.config.vsh.yaml b/target/nextflow/samtools/samtools_stats/.config.vsh.yaml index acec3d64..1c9c56a3 100644 --- a/target/nextflow/samtools/samtools_stats/.config.vsh.yaml +++ b/target/nextflow/samtools/samtools_stats/.config.vsh.yaml @@ -401,7 +401,7 @@ build_info: output: "target/nextflow/samtools/samtools_stats" executable: "target/nextflow/samtools/samtools_stats/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/samtools/samtools_stats/main.nf b/target/nextflow/samtools/samtools_stats/main.nf index d3c632c1..a35cc33c 100644 --- a/target/nextflow/samtools/samtools_stats/main.nf +++ b/target/nextflow/samtools/samtools_stats/main.nf @@ -3269,7 +3269,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/samtools/samtools_stats", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { diff --git a/target/nextflow/samtools/samtools_view/.config.vsh.yaml b/target/nextflow/samtools/samtools_view/.config.vsh.yaml index 5cc29f83..e5ca47ac 100644 --- a/target/nextflow/samtools/samtools_view/.config.vsh.yaml +++ b/target/nextflow/samtools/samtools_view/.config.vsh.yaml @@ -665,7 +665,7 @@ build_info: output: "target/nextflow/samtools/samtools_view" executable: "target/nextflow/samtools/samtools_view/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/samtools/samtools_view/main.nf b/target/nextflow/samtools/samtools_view/main.nf index 7e862b96..b759894c 100644 --- a/target/nextflow/samtools/samtools_view/main.nf +++ b/target/nextflow/samtools/samtools_view/main.nf @@ -3450,7 +3450,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/samtools/samtools_view", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { @@ -3562,21 +3562,29 @@ $( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" set -e -[[ "\\$par_bam" == "false" ]] && unset par_bam -[[ "\\$par_cram" == "false" ]] && unset par_cram -[[ "\\$par_fast" == "false" ]] && unset par_fast -[[ "\\$par_uncompressed" == "false" ]] && unset par_uncompressed -[[ "\\$par_with_header" == "false" ]] && unset par_with_header -[[ "\\$par_header_only" == "false" ]] && unset par_header_only -[[ "\\$par_no_header" == "false" ]] && unset par_no_header -[[ "\\$par_count" == "false" ]] && unset par_count -[[ "\\$par_unmap" == "false" ]] && unset par_unmap -[[ "\\$par_use_index" == "false" ]] && unset par_use_index -[[ "\\$par_fetch_pairs" == "false" ]] && unset par_fetch_pairs -[[ "\\$par_customized_index" == "false" ]] && unset par_customized_index -[[ "\\$par_no_PG" == "false" ]] && unset par_no_PG -[[ "\\$par_write_index" == "false" ]] && unset par_write_index -[[ "\\$par_remove_B" == "false" ]] && unset par_remove_B +unset_if_false=( + par_bam + par_cram + par_fast + par_uncompressed + par_with_header + par_header_only + par_no_header + par_count + par_unmap + par_use_index + par_fetch_pairs + par_customized_index + par_no_PG + par_write_index + par_remove_B +) + +for par in \\${unset_if_false[@]}; do + test_val="\\${!par}" + [[ "\\$test_val" == "false" ]] && unset \\$par +done + samtools view \\\\ \\${par_bam:+-b} \\\\ diff --git a/target/nextflow/seqtk/seqtk_sample/.config.vsh.yaml b/target/nextflow/seqtk/seqtk_sample/.config.vsh.yaml index f28aa87b..c4df2473 100644 --- a/target/nextflow/seqtk/seqtk_sample/.config.vsh.yaml +++ b/target/nextflow/seqtk/seqtk_sample/.config.vsh.yaml @@ -173,7 +173,7 @@ build_info: output: "target/nextflow/seqtk/seqtk_sample" executable: "target/nextflow/seqtk/seqtk_sample/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/seqtk/seqtk_sample/main.nf b/target/nextflow/seqtk/seqtk_sample/main.nf index 19343836..7a86d26e 100644 --- a/target/nextflow/seqtk/seqtk_sample/main.nf +++ b/target/nextflow/seqtk/seqtk_sample/main.nf @@ -3004,7 +3004,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/seqtk/seqtk_sample", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { diff --git a/target/nextflow/seqtk/seqtk_subseq/.config.vsh.yaml b/target/nextflow/seqtk/seqtk_subseq/.config.vsh.yaml index 4e1e0c62..7ffb233f 100644 --- a/target/nextflow/seqtk/seqtk_subseq/.config.vsh.yaml +++ b/target/nextflow/seqtk/seqtk_subseq/.config.vsh.yaml @@ -196,7 +196,7 @@ build_info: output: "target/nextflow/seqtk/seqtk_subseq" executable: "target/nextflow/seqtk/seqtk_subseq/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/seqtk/seqtk_subseq/main.nf b/target/nextflow/seqtk/seqtk_subseq/main.nf index 2dc043b5..90a9d159 100644 --- a/target/nextflow/seqtk/seqtk_subseq/main.nf +++ b/target/nextflow/seqtk/seqtk_subseq/main.nf @@ -3034,7 +3034,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/seqtk/seqtk_subseq", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { diff --git a/target/nextflow/star/star_align_reads/.config.vsh.yaml b/target/nextflow/star/star_align_reads/.config.vsh.yaml index f5ccc616..3fffef0c 100644 --- a/target/nextflow/star/star_align_reads/.config.vsh.yaml +++ b/target/nextflow/star/star_align_reads/.config.vsh.yaml @@ -2663,7 +2663,7 @@ build_info: output: "target/nextflow/star/star_align_reads" executable: "target/nextflow/star/star_align_reads/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/star/star_align_reads/main.nf b/target/nextflow/star/star_align_reads/main.nf index 83fd042b..f2cf1f06 100644 --- a/target/nextflow/star/star_align_reads/main.nf +++ b/target/nextflow/star/star_align_reads/main.nf @@ -5917,7 +5917,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/star/star_align_reads", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { diff --git a/target/nextflow/star/star_genome_generate/.config.vsh.yaml b/target/nextflow/star/star_genome_generate/.config.vsh.yaml index c1ce98cd..c57b3fbd 100644 --- a/target/nextflow/star/star_genome_generate/.config.vsh.yaml +++ b/target/nextflow/star/star_genome_generate/.config.vsh.yaml @@ -333,7 +333,7 @@ build_info: output: "target/nextflow/star/star_genome_generate" executable: "target/nextflow/star/star_genome_generate/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/star/star_genome_generate/main.nf b/target/nextflow/star/star_genome_generate/main.nf index 452c451f..7b51a94a 100644 --- a/target/nextflow/star/star_genome_generate/main.nf +++ b/target/nextflow/star/star_genome_generate/main.nf @@ -3169,7 +3169,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/star/star_genome_generate", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { diff --git a/target/nextflow/umi_tools/umi_tools_dedup/.config.vsh.yaml b/target/nextflow/umi_tools/umi_tools_dedup/.config.vsh.yaml index be9514c3..535e9990 100644 --- a/target/nextflow/umi_tools/umi_tools_dedup/.config.vsh.yaml +++ b/target/nextflow/umi_tools/umi_tools_dedup/.config.vsh.yaml @@ -611,7 +611,7 @@ build_info: output: "target/nextflow/umi_tools/umi_tools_dedup" executable: "target/nextflow/umi_tools/umi_tools_dedup/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/umi_tools/umi_tools_dedup/main.nf b/target/nextflow/umi_tools/umi_tools_dedup/main.nf index 01b70619..f5998763 100644 --- a/target/nextflow/umi_tools/umi_tools_dedup/main.nf +++ b/target/nextflow/umi_tools/umi_tools_dedup/main.nf @@ -3461,7 +3461,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/umi_tools/umi_tools_dedup", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { @@ -3577,19 +3577,26 @@ set -e test_dir="\\${metal_executable}/test_data" -[[ "\\$par_paired" == "false" ]] && unset par_paired -[[ "\\$par_in_sam" == "false" ]] && unset par_in_sam -[[ "\\$par_out_sam" == "false" ]] && unset par_out_sam -[[ "\\$par_spliced_is_unique" == "false" ]] && unset par_spliced_is_unique -[[ "\\$par_per_gene" == "false" ]] && unset par_per_gene -[[ "\\$par_per_contig" == "false" ]] && unset par_per_contig -[[ "\\$par_per_cell" == "false" ]] && unset par_per_cell -[[ "\\$par_no_sort_output" == "false" ]] && unset par_no_sort_output -[[ "\\$par_buffer_whole_contig" == "false" ]] && unset par_buffer_whole_contig -[[ "\\$par_ignore_umi" == "false" ]] && unset par_ignore_umi -[[ "\\$par_subset" == "false" ]] && unset par_subset -[[ "\\$par_log2stderr" == "false" ]] && unset par_log2stderr -[[ "\\$par_read_length" == "false" ]] && unset par_read_length +unset_if_false=( + par_paired + par_in_sam + par_out_sam + par_spliced_is_unique + par_per_gene + par_per_contig + par_per_cell + par_no_sort_output + par_buffer_whole_contig + par_ignore_umi + par_subset + par_log2stderr + par_read_length +) + +for par in \\${unset_if_false[@]}; do + test_val="\\${!par}" + [[ "\\$test_val" == "false" ]] && unset \\$par +done umi_tools dedup \\\\ --stdin "\\$par_input" \\\\ diff --git a/target/nextflow/umi_tools/umi_tools_dedup/nextflow_schema.json b/target/nextflow/umi_tools/umi_tools_dedup/nextflow_schema.json new file mode 100644 index 00000000..834b53ae --- /dev/null +++ b/target/nextflow/umi_tools/umi_tools_dedup/nextflow_schema.json @@ -0,0 +1,635 @@ +{ +"$schema": "http://json-schema.org/draft-07/schema", +"title": "umi_tools_dedup", +"description": "Deduplicate reads based on the mapping co-ordinate and the UMI attached to the read.\n", +"type": "object", +"definitions": { + + + + "inputs" : { + "title": "Inputs", + "type": "object", + "description": "No description", + "properties": { + + + "input": { + "type": + "string", + "description": "Type: `file`, required. Input BAM or SAM file", + "help_text": "Type: `file`, required. Input BAM or SAM file. Use --in_sam to specify SAM format." + + } + + + , + "in_sam": { + "type": + "boolean", + "description": "Type: `boolean_true`, default: `false`. By default, inputs are assumed to be in BAM format", + "help_text": "Type: `boolean_true`, default: `false`. By default, inputs are assumed to be in BAM format. Use this options to specify the use of SAM\nformat for input.\n" + , + "default": "False" + } + + + , + "bai": { + "type": + "string", + "description": "Type: `file`. BAM index", + "help_text": "Type: `file`. BAM index" + + } + + + , + "random_seed": { + "type": + "integer", + "description": "Type: `integer`. Random seed to initialize number generator with", + "help_text": "Type: `integer`. Random seed to initialize number generator with." + + } + + +} +}, + + + "outputs" : { + "title": "Outputs", + "type": "object", + "description": "No description", + "properties": { + + + "output": { + "type": + "string", + "description": "Type: `file`, required, default: `$id.$key.output.output`. Deduplicated BAM file", + "help_text": "Type: `file`, required, default: `$id.$key.output.output`. Deduplicated BAM file." + , + "default": "$id.$key.output.output" + } + + + , + "out_sam": { + "type": + "boolean", + "description": "Type: `boolean_true`, default: `false`. By default, outputa are written in BAM format", + "help_text": "Type: `boolean_true`, default: `false`. By default, outputa are written in BAM format. Use this options to specify the use of SAM format\nfor output.\n" + , + "default": "False" + } + + + , + "paired": { + "type": + "boolean", + "description": "Type: `boolean_true`, default: `false`. BAM is paired end - output both read pairs", + "help_text": "Type: `boolean_true`, default: `false`. BAM is paired end - output both read pairs. This will also force the use of the template length\nto determine reads with the same mapping coordinates.\n" + , + "default": "False" + } + + + , + "output_stats": { + "type": + "string", + "description": "Type: `string`. Generate files containing UMI based deduplication statistics files with this prefix in the file names", + "help_text": "Type: `string`. Generate files containing UMI based deduplication statistics files with this prefix in the file names.\n" + + } + + + , + "extract_umi_method": { + "type": + "string", + "description": "Type: `string`, example: `read_id`, choices: ``read_id`, `tag`, `umis``. Specify the method by which the barcodes were encoded in the read", + "help_text": "Type: `string`, example: `read_id`, choices: ``read_id`, `tag`, `umis``. Specify the method by which the barcodes were encoded in the read.\nThe options are:\n * read_id (default) \n * tag\n * umis\n", + "enum": ["read_id", "tag", "umis"] + + + } + + + , + "umi_tag": { + "type": + "string", + "description": "Type: `string`. The tag containing the UMI sequence", + "help_text": "Type: `string`. The tag containing the UMI sequence. This is only required if the extract_umi_method is set to tag.\n" + + } + + + , + "umi_separator": { + "type": + "string", + "description": "Type: `string`, example: `_`. The separator used to separate the UMI from the read sequence", + "help_text": "Type: `string`, example: `_`. The separator used to separate the UMI from the read sequence. This is only required if the\nextract_umi_method is set to id_read. Default: `_`.\n" + + } + + + , + "umi_tag_split": { + "type": + "string", + "description": "Type: `string`. Separate the UMI in tag by \u003cSPLIT\u003e and take the first element", + "help_text": "Type: `string`. Separate the UMI in tag by \u003cSPLIT\u003e and take the first element." + + } + + + , + "umi_tag_delimiter": { + "type": + "string", + "description": "Type: `string`. Separate the UMI in by \u003cDELIMITER\u003e and concatenate the elements", + "help_text": "Type: `string`. Separate the UMI in by \u003cDELIMITER\u003e and concatenate the elements." + + } + + + , + "cell_tag": { + "type": + "string", + "description": "Type: `string`. The tag containing the cell barcode sequence", + "help_text": "Type: `string`. The tag containing the cell barcode sequence. This is only required if the extract_umi_method\nis set to tag.\n" + + } + + + , + "cell_tag_split": { + "type": + "string", + "description": "Type: `string`. Separate the cell barcode in tag by \u003cSPLIT\u003e and take the first element", + "help_text": "Type: `string`. Separate the cell barcode in tag by \u003cSPLIT\u003e and take the first element." + + } + + + , + "cell_tag_delimiter": { + "type": + "string", + "description": "Type: `string`. Separate the cell barcode in by \u003cDELIMITER\u003e and concatenate the elements", + "help_text": "Type: `string`. Separate the cell barcode in by \u003cDELIMITER\u003e and concatenate the elements." + + } + + +} +}, + + + "grouping options" : { + "title": "Grouping Options", + "type": "object", + "description": "No description", + "properties": { + + + "method": { + "type": + "string", + "description": "Type: `string`, example: `directional`, choices: ``unique`, `percentile`, `cluster`, `adjacency`, `directional``. The method to use for grouping reads", + "help_text": "Type: `string`, example: `directional`, choices: ``unique`, `percentile`, `cluster`, `adjacency`, `directional``. The method to use for grouping reads. \nThe options are: \n * unique\n * percentile\n * cluster\n * adjacency\n * directional (default)\n", + "enum": ["unique", "percentile", "cluster", "adjacency", "directional"] + + + } + + + , + "edit_distance_threshold": { + "type": + "integer", + "description": "Type: `integer`, example: `1`. For the adjacency and cluster methods the threshold for the edit distance to connect two\nUMIs in the network can be increased", + "help_text": "Type: `integer`, example: `1`. For the adjacency and cluster methods the threshold for the edit distance to connect two\nUMIs in the network can be increased. The default value of 1 works best unless the UMI is\nvery long (\u003e14bp). Default: `1`.\n" + + } + + + , + "spliced_is_unique": { + "type": + "boolean", + "description": "Type: `boolean_true`, default: `false`. Causes two reads that start in the same position on the same strand and having the same UMI\nto be considered unique if one is spliced and the other is not", + "help_text": "Type: `boolean_true`, default: `false`. Causes two reads that start in the same position on the same strand and having the same UMI\nto be considered unique if one is spliced and the other is not. (Uses the \u0027N\u0027 cigar operation\nto test for splicing).\n" + , + "default": "False" + } + + + , + "soft_clip_threshold": { + "type": + "integer", + "description": "Type: `integer`, example: `4`. Mappers that soft clip will sometimes do so rather than mapping a spliced read if there is only\na small overhang over the exon junction", + "help_text": "Type: `integer`, example: `4`. Mappers that soft clip will sometimes do so rather than mapping a spliced read if there is only\na small overhang over the exon junction. By setting this option, you can treat reads with at\nleast this many bases soft-clipped at the 3\u0027 end as spliced. Default: `4`.\n" + + } + + + , + "multimapping_detection_method": { + "type": + "string", + "description": "Type: `string`. If the sam/bam contains tags to identify multimapping reads, you can specify for use when selecting\nthe best read at a given loci", + "help_text": "Type: `string`. If the sam/bam contains tags to identify multimapping reads, you can specify for use when selecting\nthe best read at a given loci. Supported tags are `NH`, `X0` and `XT`. If not specified, the read\nwith the highest mapping quality will be selected.\n" + + } + + + , + "read_length": { + "type": + "boolean", + "description": "Type: `boolean_true`, default: `false`. Use the read length as a criteria when deduping, for e", + "help_text": "Type: `boolean_true`, default: `false`. Use the read length as a criteria when deduping, for e.g. sRNA-Seq." + , + "default": "False" + } + + +} +}, + + + "single-cell rna-seq options" : { + "title": "Single-cell RNA-Seq Options", + "type": "object", + "description": "No description", + "properties": { + + + "per_gene": { + "type": + "boolean", + "description": "Type: `boolean_true`, default: `false`. Reads will be grouped together if they have the same gene", + "help_text": "Type: `boolean_true`, default: `false`. Reads will be grouped together if they have the same gene. This is useful if your library prep\ngenerates PCR duplicates with non identical alignment positions such as CEL-Seq. Note this option\nis hardcoded to be on with the count command. I.e. counting is always performed per-gene. Must be\ncombined with either --gene_tag or --per_contig option.\n" + , + "default": "False" + } + + + , + "gene_tag": { + "type": + "string", + "description": "Type: `string`. Deduplicate per gene", + "help_text": "Type: `string`. Deduplicate per gene. The gene information is encoded in the bam read tag specified.\n" + + } + + + , + "assigned_status_tag": { + "type": + "string", + "description": "Type: `string`. BAM tag which describes whether a read is assigned to a gene", + "help_text": "Type: `string`. BAM tag which describes whether a read is assigned to a gene. Defaults to the same value as given\nfor --gene_tag.\n" + + } + + + , + "skip_tags_regex": { + "type": + "string", + "description": "Type: `string`. Use in conjunction with the --assigned_status_tag option to skip any reads where the tag matches\nthis regex", + "help_text": "Type: `string`. Use in conjunction with the --assigned_status_tag option to skip any reads where the tag matches\nthis regex. Default (\"^[__|Unassigned]\") matches anything which starts with \"__\" or \"Unassigned\".\n" + + } + + + , + "per_contig": { + "type": + "boolean", + "description": "Type: `boolean_true`, default: `false`. Deduplicate per contig (field 3 in BAM; RNAME)", + "help_text": "Type: `boolean_true`, default: `false`. Deduplicate per contig (field 3 in BAM; RNAME). All reads with the sam contig will be considered to\nhave the same alignment position. This is useful if you have aligned to a reference transcriptome\nwith one transcript per gene. If you have aligned to a transcriptome with more than one transcript\nper gene, you can supply a map between transcripts and gene using the --gene_transcript_map option.\n" + , + "default": "False" + } + + + , + "gene_transcript_map": { + "type": + "string", + "description": "Type: `file`. A file containing a mapping between gene names and transcript names", + "help_text": "Type: `file`. A file containing a mapping between gene names and transcript names. The file should be tab\nseparated with the gene name in the first column and the transcript name in the second column.\n" + + } + + + , + "per_cell": { + "type": + "boolean", + "description": "Type: `boolean_true`, default: `false`. Reads will only be grouped together if they have the same cell barcode", + "help_text": "Type: `boolean_true`, default: `false`. Reads will only be grouped together if they have the same cell barcode. Can be combined with\n--per_gene.\n" + , + "default": "False" + } + + +} +}, + + + "sam/bam options" : { + "title": "SAM/BAM Options", + "type": "object", + "description": "No description", + "properties": { + + + "mapping_quality": { + "type": + "integer", + "description": "Type: `integer`, example: `0`. Minimium mapping quality (MAPQ) for a read to be retained", + "help_text": "Type: `integer`, example: `0`. Minimium mapping quality (MAPQ) for a read to be retained. Default: `0`.\n" + + } + + + , + "unmapped_reads": { + "type": + "string", + "description": "Type: `string`, example: `discard`. How unmapped reads should be handled", + "help_text": "Type: `string`, example: `discard`. How unmapped reads should be handled. \nThe options are:\n * \"discard\": Discard all unmapped reads. (default)\n * \"use\": If read2 is unmapped, deduplicate using read1 only. Requires --paired.\n * \"output\": Output unmapped reads/read pairs without UMI grouping/deduplication. Only available in umi_tools group.\n" + + } + + + , + "chimeric_pairs": { + "type": + "string", + "description": "Type: `string`, example: `use`, choices: ``discard`, `use`, `output``. How chimeric pairs should be handled", + "help_text": "Type: `string`, example: `use`, choices: ``discard`, `use`, `output``. How chimeric pairs should be handled. \nThe options are:\n * \"discard\": Discard all chimeric read pairs.\n * \"use\": Deduplicate using read1 only. (default)\n * \"output\": Output chimeric pairs without UMI grouping/deduplication. Only available in\n umi_tools group.\n", + "enum": ["discard", "use", "output"] + + + } + + + , + "unpaired_reads": { + "type": + "string", + "description": "Type: `string`, example: `use`, choices: ``discard`, `use`, `output``. How unpaired reads should be handled", + "help_text": "Type: `string`, example: `use`, choices: ``discard`, `use`, `output``. How unpaired reads should be handled. \nThe options are: \n * \"discard\": Discard all unmapped reads.\n * \"use\": If read2 is unmapped, deduplicate using read1 only. Requires --paired. (default)\n * \"output\": Output unmapped reads/read pairs without UMI grouping/deduplication. Only available\n in umi_tools group.\n", + "enum": ["discard", "use", "output"] + + + } + + + , + "ignore_umi": { + "type": + "boolean", + "description": "Type: `boolean_true`, default: `false`. Ignore the UMI and group reads using mapping coordinates only", + "help_text": "Type: `boolean_true`, default: `false`. Ignore the UMI and group reads using mapping coordinates only." + , + "default": "False" + } + + + , + "subset": { + "type": + "number", + "description": "Type: `double`. Only consider a fraction of the reads, chosen at random", + "help_text": "Type: `double`. Only consider a fraction of the reads, chosen at random. This is useful for doing saturation\nanalyses.\n" + + } + + + , + "chrom": { + "type": + "string", + "description": "Type: `string`. Only consider a single chromosome", + "help_text": "Type: `string`. Only consider a single chromosome. This is useful for debugging/testing purposes." + + } + + +} +}, + + + "group/dedup options" : { + "title": "Group/Dedup Options", + "type": "object", + "description": "No description", + "properties": { + + + "no_sort_output": { + "type": + "boolean", + "description": "Type: `boolean_true`, default: `false`. By default, output is sorted", + "help_text": "Type: `boolean_true`, default: `false`. By default, output is sorted. This involves the use of a temporary unsorted file (saved in\n--temp_dir). Use this option to turn off sorting.\n" + , + "default": "False" + } + + + , + "buffer_whole_contig": { + "type": + "boolean", + "description": "Type: `boolean_true`, default: `false`. Forces dedup to parse an entire contig before yielding any reads for deduplication", + "help_text": "Type: `boolean_true`, default: `false`. Forces dedup to parse an entire contig before yielding any reads for deduplication. This is the\nonly way to absolutely guarantee that all reads with the same start position are grouped together\nfor deduplication since dedup uses the start position of the read, not the alignment coordinate on\nwhich the reads are sorted. However, by default, dedup reads for another 1000bp before outputting\nread groups which will avoid any reads being missed with short read sequencing (\u003c1000bp).\n" + , + "default": "False" + } + + +} +}, + + + "common options" : { + "title": "Common Options", + "type": "object", + "description": "No description", + "properties": { + + + "log": { + "type": + "string", + "description": "Type: `file`. File with logging information", + "help_text": "Type: `file`. File with logging information." + + } + + + , + "log2stderr": { + "type": + "boolean", + "description": "Type: `boolean_true`, default: `false`. Send logging information to stderr", + "help_text": "Type: `boolean_true`, default: `false`. Send logging information to stderr." + , + "default": "False" + } + + + , + "verbose": { + "type": + "integer", + "description": "Type: `integer`, example: `0`. Log level", + "help_text": "Type: `integer`, example: `0`. Log level. The higher, the more output. Default: `0`.\n" + + } + + + , + "error": { + "type": + "string", + "description": "Type: `file`. File with error information", + "help_text": "Type: `file`. File with error information." + + } + + + , + "temp_dir": { + "type": + "string", + "description": "Type: `string`. Directory for temporary files", + "help_text": "Type: `string`. Directory for temporary files. If not set, the bash environmental variable TMPDIR is used.\n" + + } + + + , + "compresslevel": { + "type": + "integer", + "description": "Type: `integer`, example: `6`. Level of Gzip compression to use", + "help_text": "Type: `integer`, example: `6`. Level of Gzip compression to use. Default=6 matches GNU gzip rather than python gzip default.\nDefault: `6`.\n" + + } + + + , + "timeit": { + "type": + "string", + "description": "Type: `file`. Store timing information in file", + "help_text": "Type: `file`. Store timing information in file." + + } + + + , + "timeit_name": { + "type": + "string", + "description": "Type: `string`, example: `all`. Name in timing file for this class of jobs", + "help_text": "Type: `string`, example: `all`. Name in timing file for this class of jobs. Default: `all`.\n" + + } + + + , + "timeit_header": { + "type": + "string", + "description": "Type: `string`. Add header for timing information", + "help_text": "Type: `string`. Add header for timing information." + + } + + +} +}, + + + "nextflow input-output arguments" : { + "title": "Nextflow input-output arguments", + "type": "object", + "description": "Input/output parameters for Nextflow itself. Please note that both publishDir and publish_dir are supported but at least one has to be configured.", + "properties": { + + + "publish_dir": { + "type": + "string", + "description": "Type: `string`, required, example: `output/`. Path to an output directory", + "help_text": "Type: `string`, required, example: `output/`. Path to an output directory." + + } + + + , + "param_list": { + "type": + "string", + "description": "Type: `string`, example: `my_params.yaml`. Allows inputting multiple parameter sets to initialise a Nextflow channel", + "help_text": "Type: `string`, example: `my_params.yaml`. Allows inputting multiple parameter sets to initialise a Nextflow channel. A `param_list` can either be a list of maps, a csv file, a json file, a yaml file, or simply a yaml blob.\n\n* A list of maps (as-is) where the keys of each map corresponds to the arguments of the pipeline. Example: in a `nextflow.config` file: `param_list: [ [\u0027id\u0027: \u0027foo\u0027, \u0027input\u0027: \u0027foo.txt\u0027], [\u0027id\u0027: \u0027bar\u0027, \u0027input\u0027: \u0027bar.txt\u0027] ]`.\n* A csv file should have column names which correspond to the different arguments of this pipeline. Example: `--param_list data.csv` with columns `id,input`.\n* A json or a yaml file should be a list of maps, each of which has keys corresponding to the arguments of the pipeline. Example: `--param_list data.json` with contents `[ {\u0027id\u0027: \u0027foo\u0027, \u0027input\u0027: \u0027foo.txt\u0027}, {\u0027id\u0027: \u0027bar\u0027, \u0027input\u0027: \u0027bar.txt\u0027} ]`.\n* A yaml blob can also be passed directly as a string. Example: `--param_list \"[ {\u0027id\u0027: \u0027foo\u0027, \u0027input\u0027: \u0027foo.txt\u0027}, {\u0027id\u0027: \u0027bar\u0027, \u0027input\u0027: \u0027bar.txt\u0027} ]\"`.\n\nWhen passing a csv, json or yaml file, relative path names are relativized to the location of the parameter file. No relativation is performed when `param_list` is a list of maps (as-is) or a yaml blob.", + "hidden": true + + } + + +} +} +}, +"allOf": [ + + { + "$ref": "#/definitions/inputs" + }, + + { + "$ref": "#/definitions/outputs" + }, + + { + "$ref": "#/definitions/grouping options" + }, + + { + "$ref": "#/definitions/single-cell rna-seq options" + }, + + { + "$ref": "#/definitions/sam/bam options" + }, + + { + "$ref": "#/definitions/group/dedup options" + }, + + { + "$ref": "#/definitions/common options" + }, + + { + "$ref": "#/definitions/nextflow input-output arguments" + } +] +} diff --git a/target/nextflow/umi_tools/umi_tools_extract/.config.vsh.yaml b/target/nextflow/umi_tools/umi_tools_extract/.config.vsh.yaml index 17ab11b5..5749c250 100644 --- a/target/nextflow/umi_tools/umi_tools_extract/.config.vsh.yaml +++ b/target/nextflow/umi_tools/umi_tools_extract/.config.vsh.yaml @@ -449,7 +449,7 @@ build_info: output: "target/nextflow/umi_tools/umi_tools_extract" executable: "target/nextflow/umi_tools/umi_tools_extract/main.nf" viash_version: "0.9.0-RC6" - git_commit: "4aa0a893d2f8be5f0d03797afc15a04c53664367" + git_commit: "923a6da3898a832df96a0e17c8a3b74c2806d939" git_remote: "https://github.com/viash-hub/biobox" package_config: name: "biobox" diff --git a/target/nextflow/umi_tools/umi_tools_extract/main.nf b/target/nextflow/umi_tools/umi_tools_extract/main.nf index 5613117d..1677555e 100644 --- a/target/nextflow/umi_tools/umi_tools_extract/main.nf +++ b/target/nextflow/umi_tools/umi_tools_extract/main.nf @@ -3290,7 +3290,7 @@ meta = [ "engine" : "docker|native", "output" : "target/nextflow/umi_tools/umi_tools_extract", "viash_version" : "0.9.0-RC6", - "git_commit" : "4aa0a893d2f8be5f0d03797afc15a04c53664367", + "git_commit" : "923a6da3898a832df96a0e17c8a3b74c2806d939", "git_remote" : "https://github.com/viash-hub/biobox" }, "package_config" : { @@ -3388,14 +3388,19 @@ $( if [ ! -z ${VIASH_META_MEMORY_PIB+x} ]; then echo "${VIASH_META_MEMORY_PIB}" set -exo pipefail -test_dir="\\${metal_executable}/test_data" +unset_if_false=( + par_error_correct_cell + par_reconcile_pairs + par_three_prime + par_ignore_read_pair_suffixes + par_timeit_header + par_log2stderr +) -[[ "\\$par_error_correct_cell" == "false" ]] && unset par_error_correct_cell -[[ "\\$par_reconcile_pairs" == "false" ]] && unset par_reconcile_pairs -[[ "\\$par_three_prime" == "false" ]] && unset par_three_prime -[[ "\\$par_ignore_read_pair_suffixes" == "false" ]] && unset par_ignore_read_pair_suffixes -[[ "\\$par_timeit_header" == "false" ]] && unset par_timeit_header -[[ "\\$par_log2stderr" == "false" ]] && unset par_log2stderr +for par in \\${unset_if_false[@]}; do + test_val="\\${!par}" + [[ "\\$test_val" == "false" ]] && unset \\$par +done # Check if we have the correct number of input files and patterns for paired-end or single-end reads