Skip to content
18 changes: 16 additions & 2 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,28 @@

### New components

- `maxbin2`: An automatic tool for binning metagenomic sequences
- `bowtie2`: Align short paired-end sequencing reads to long reference sequences
- `maxbin2`: An automatic tool for binning metagenomic sequences.
- `bowtie2`: Align short paired-end sequencing reads to long reference
sequences.

### New recipes

- `plasmids`: A recipe to perform mapping, mash screen on reads
and also mash dist for assembly based approaches (all to detect
plasmdis). This also includes annotation with abricate for the assembly.
- `plasmids_mapping`: A recipe to perfmorm mapping for plasmids.
- `plasmids_mash`: A recipe to perform mash screen for plasmids.
- `plasmids_assembly`: A recipe to perform mash dist for plasmid
assemblies.

### Minor/Other changes

- Added "smart" check when the user provides a typo in pipeline string
for a given process, outputting some "educated" guesses to the the
terminal.
- Added "-cr" option to show current recipe `pipeline_string`.
- Changed the way recipes were being parsed by `proc_collector` for the
usage of `-l` and `-L` options.

### Bug fixes

Expand Down
35 changes: 29 additions & 6 deletions flowcraft/flowcraft.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@
from __init__ import __version__, __build__
from generator.engine import NextflowGenerator, process_map
from generator.inspect import NextflowInspector
from generator.recipe import brew_recipe
from generator.recipe import brew_recipe, available_recipes
from generator.pipeline_parser import parse_pipeline, SanityError
from generator.process_details import proc_collector, colored_print
import generator.error_handling as eh
except ImportError:
from flowcraft import __version__, __build__
from flowcraft.generator.engine import NextflowGenerator, process_map
from flowcraft.generator.inspect import NextflowInspector
from flowcraft.generator.recipe import brew_recipe
from flowcraft.generator.recipe import brew_recipe, available_recipes
from flowcraft.generator.pipeline_parser import parse_pipeline, \
SanityError
from flowcraft.generator.process_details import proc_collector, \
Expand Down Expand Up @@ -77,6 +77,12 @@ def get_args(args=None):
"-l", "--short-list", action="store_const", dest="short_list",
const=True, help="Print a short list of the currently "
"available processes")
build_parser.add_argument("-cr", "--check-recipe", dest="check_recipe",
action="store_const", const=True,
help="Check tasks that the recipe contain and "
"their flow. This option might be useful "
"if a user wants to change some components "
"of a given recipe, by using the -t option.")

# GENERAL OPTIONS
parser.add_argument(
Expand Down Expand Up @@ -121,14 +127,18 @@ def get_args(args=None):

def validate_build_arguments(args):

if args.detailed_list or args.short_list:
return

if not args.tasks and not args.recipe and not args.check_only \
and not args.detailed_list and not args.short_list:
logger.error(colored_print(
"At least one of these options is required: -t, -r, -c, "
"-l, -L", "red_bold"))
sys.exit(1)

if (args.tasks or args.recipe) and not args.output_nf:
if (args.tasks or args.recipe) and not args.check_recipe \
and not args.output_nf:
logger.error(colored_print(
"Please provide the path and name of the pipeline file using the"
" -o option.", "red_bold"))
Expand Down Expand Up @@ -202,13 +212,26 @@ def build(args):
# If a recipe is specified, build pipeline based on the
# appropriate recipe
if args.recipe:
pipeline_string, list_processes = brew_recipe(args)
if args.recipe == "innuendo":
pipeline_string = brew_recipe(args, available_recipes)
else:
pipeline_string = available_recipes[args.recipe]
if args.tasks:
logger.warning(colored_print(
"-t parameter will be ignored for recipe: {}\n"
.format(args.recipe), "yellow_bold")
)

if args.check_recipe:
logger.info(colored_print("Pipeline string for recipe: {}"
.format(args.recipe), "purple_bold"))
logger.info(pipeline_string)
sys.exit(0)
else:
pipeline_string = args.tasks
list_processes = None

# used for lists print
proc_collector(process_map, args, list_processes)
proc_collector(process_map, args, pipeline_string)

logger.info(colored_print("Resulting pipeline string:\n"))
logger.info(colored_print(pipeline_string + "\n"))
Expand Down
26 changes: 13 additions & 13 deletions flowcraft/generator/process_details.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"white_bold": "1;38m",
"white_underline": "4;38m",
"blue_bold": "1;36m",
"purple_bold": "1;34m"
"purple_bold": "1;34m",
"yellow_bold": "1;93m"
}


Expand Down Expand Up @@ -75,7 +76,7 @@ def procs_dict_parser(procs_dict):
))


def proc_collector(process_map, args, processes_list=None):
def proc_collector(process_map, args, pipeline_string):
"""
Function that collects all processes available and stores a dictionary of
the required arguments of each process class to be passed to
Expand All @@ -89,9 +90,8 @@ def proc_collector(process_map, args, processes_list=None):
args: argparse.Namespace
The arguments passed through argparser that will be access to check the
type of list to be printed
processes_list: list
List with all the available processes of a recipe. In case no recipe
is passed, the list should come empty.
pipeline_string: str
the pipeline string

"""

Expand Down Expand Up @@ -120,16 +120,16 @@ def proc_collector(process_map, args, processes_list=None):
# loops between all process_map Processes
for name, cls in process_map.items():

if processes_list:
# Skip process if process_list is provided and name not in
# processes list
if name not in processes_list:
continue

# instantiates each Process class
cls_inst = cls(template=name)
d = {arg_key: vars(cls_inst)[arg_key] for arg_key in vars(cls_inst)
if arg_key in arguments_list}

# checks if recipe is provided
if pipeline_string:
if name not in pipeline_string:
continue

d = {arg_key: vars(cls_inst)[arg_key] for arg_key in
vars(cls_inst) if arg_key in arguments_list}
procs_dict[name] = d

procs_dict_parser(procs_dict)
Expand Down
29 changes: 17 additions & 12 deletions flowcraft/generator/recipe.py
Original file line number Diff line number Diff line change
Expand Up @@ -478,8 +478,8 @@ def run_auto_pipeline(self, tasks):

return self.pipeline_string

def get_process_info(self):
return list(self.process_descriptions.keys())
# def get_process_info(self):
# return list(self.process_descriptions.keys())


class Innuendo(Recipe):
Expand Down Expand Up @@ -512,17 +512,12 @@ def __init__(self, *args, **kwargs):
"mlst": [False, "pilon", "abricate|prokka|chewbbaca|sistr"],
"sistr": [True, "mlst", None],
"abricate": [True, "mlst", None],
"prokka": [True, "mlst", None],
#"prokka": [True, "mlst", None],
"chewbbaca": [True, "mlst", None]
}


available_recipes = {
"innuendo": Innuendo
}


def brew_recipe(args):
def brew_recipe(args, available_recipes):
"""Brews a given list of processes according to the recipe

Parameters
Expand Down Expand Up @@ -555,13 +550,23 @@ def brew_recipe(args):
else:
input_processes = args.tasks

# Get the list of processes for that recipe
list_processes = automatic_pipeline.get_process_info()
# Validate the provided pipeline processes
validated = automatic_pipeline.validate_pipeline(input_processes)
if not validated:
sys.exit(1)
# Get the final pipeline string
pipeline_string = automatic_pipeline.run_auto_pipeline(input_processes)

return pipeline_string, list_processes
return pipeline_string


# A dictionary of quick recipes
available_recipes = {
"innuendo": Innuendo,
"plasmids": "integrity_coverage fastqc_trimmomatic (spades pilon "
"(mash_dist | abricate) | mash_screen | mapping_patlas)",
"plasmids_mapping": "integrity_coverage fastqc_trimmomatic mapping_patlas",
"plasmids_assembly": "integrity_coverage fastqc_trimmomatic (spades pilon"
" mash_dist)",
"plasmids_mash": "integrity_coverage fastqc_trimmomatic mash_screen",
}
18 changes: 0 additions & 18 deletions flowcraft/tests/test_assemblerflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,6 @@ def tmp():
shutil.rmtree("temp")


def test_list_short():

sys.argv.append(1)
args = af.get_args(["build", "-l"])

with pytest.raises(SystemExit):
af.build(args)


def test_list_long():

sys.argv.append(1)
args = af.get_args(["build", "-L"])

with pytest.raises(SystemExit):
af.build(args)


def test_check():

sys.argv.append(1)
Expand Down
8 changes: 6 additions & 2 deletions flowcraft/tests/test_process_details.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,18 @@ def test_long_list():

arguments = af.get_args(["build", "-L"])

pipeline_string = "fastqc trimmomatic"

with pytest.raises(SystemExit):
pd.proc_collector(process_map, arguments)
pd.proc_collector(process_map, arguments, pipeline_string)


def test_short_list():

arguments = af.get_args(["build", "-l"])

pipeline_string = "fastqc trimmomatic"

with pytest.raises(SystemExit):
pd.proc_collector(process_map, arguments)
pd.proc_collector(process_map, arguments, pipeline_string)