Beispiel #1
0
def _run(args, base_dir, workflows_dir, config_path):
    """
    Run a complete workflow.
    """
    if not os.path.exists(config_path):
        sys.stdout.write(
            f"The config file: {config_path} does not exist.\nProvide a path to the config file with "
            f"--config or if you do not have a config file run:\n"
            f"seq2science init {args.workflow}\n")
        sys.exit(1)

    # parse the args
    parsed_args = {
        "snakefile":
        os.path.join(workflows_dir, args.workflow.replace("-", "_"),
                     "Snakefile"),
        "use_conda":
        True,
        "conda_frontend":
        conda_frontend,
        "conda_prefix":
        os.path.join(base_dir, ".snakemake"),
        "dryrun":
        args.dryrun,
        "printreason":
        args.reason,
        "keepgoing":
        args.keep_going,
        "unlock":
        args.unlock,
        "force_incomplete":
        args.rerun_incomplete
    }

    # get the additional snakemake options
    snakemake_options = args.snakemakeOptions if args.snakemakeOptions is not None else dict(
    )
    snakemake_options.setdefault("config", {}).update(
        {"rule_dir": os.path.join(base_dir, "rules")})

    # parse the profile
    snakemake_options["configfiles"] = [config_path]
    if args.profile is not None:
        profile_file = snakemake.get_profile_file(args.profile, "config.yaml")
        if profile_file is None:
            print("Error: profile given but no config.yaml found.")
            sys.exit(1)
        snakemake_options["configfiles"] += [profile_file]

    parsed_args.update(snakemake_options)

    # cores
    if args.cores:  # CLI
        parsed_args["cores"] = args.cores
    elif parsed_args.get("cores"):  # profile
        parsed_args["cores"] = int(parsed_args["cores"])
    elif parsed_args["dryrun"]:
        parsed_args["cores"] = 999
    else:
        parsed_args["cores"] = 0

    if parsed_args["cores"] < 2:
        # we need to raise an exception and catch it for a subjectively prettier message
        try:
            raise argparse.ArgumentError(core_arg,
                                         "specify at least two cores.")
        except argparse.ArgumentError as e:
            print()  # empty line
            print(e)
            sys.exit(1)

    core_parser(parsed_args)

    # run snakemake
    exit_code = snakemake.snakemake(**parsed_args)
    sys.exit(0) if exit_code else sys.exit(1)
Beispiel #2
0
def _explain(args, base_dir, workflows_dir, config_path):
    """
    Run a complete dryrun workflow, then return the explanations of each rule used.
    """
    if not os.path.exists(config_path):
        sys.stdout.write(
            f"The config file: {config_path} does not exist.\nProvide a path to the config file with "
            f"--config or if you do not have a config file run:\n"
            f"seq2science init {args.workflow}\n")
        sys.exit(1)

    # parse the args
    parsed_args = {
        "snakefile":
        os.path.join(workflows_dir, args.workflow.replace("-", "_"),
                     "Snakefile"),
        "dryrun":
        True,
        "forceall":
        True,
        "quiet":
        False
    }

    # get the additional snakemake options
    snakemake_options = args.snakemakeOptions if args.snakemakeOptions is not None else dict(
    )
    snakemake_options.setdefault("config", {}).update(
        {"rule_dir": os.path.join(base_dir, "rules")})

    # parse the profile
    snakemake_options["configfiles"] = [config_path]
    if args.profile is not None:
        profile_file = snakemake.get_profile_file(args.profile, "config.yaml")
        if profile_file is None:
            print("Error: profile given but no config.yaml found.")
            sys.exit(1)
        snakemake_options["configfiles"] += [profile_file]

    parsed_args.update(snakemake_options)

    # cores
    parsed_args["cores"] = 999

    # starting message
    rules_used = {
        "start":
        f"\nPreprocessing of reads was done automatically with workflow tool "
        f"seq2science v{seq2science.__version__} (https://doi.org/10.5281/zenodo.3921913)."
    }

    def log_handler(log):
        if log["level"] == "job_info" and "msg" in log and log[
                "msg"] is not None and log["name"] not in rules_used:
            rules_used[log["name"]] = log["msg"]

    parsed_args["log_handler"] = [log_handler]
    parsed_args["config"]["explain_rule"] = True

    # run snakemake (silently)
    with open(os.devnull, "w") as null:
        with contextlib.redirect_stdout(null), contextlib.redirect_stderr(
                null):
            exit_code = snakemake.snakemake(**parsed_args)

    print(" ".join(rules_used.values()))
    sys.exit(0) if exit_code else sys.exit(1)
Beispiel #3
0
def _run(args, base_dir, workflows_dir, config_path):
    """
    Run a complete workflow.
    """
    if not os.path.exists(config_path):
        sys.stdout.write(
            f"The config file: {config_path} does not exist.\nProvide a path to the config file with "
            f"--config or if you do not have a config file run:\n"
            f"seq2science init {args.workflow}\n")
        sys.exit(1)

    # parse the args
    parsed_args = {
        "snakefile":
        os.path.join(workflows_dir, args.workflow.replace("-", "_"),
                     "Snakefile"),
        "use_conda":
        True,
        "conda_frontend":
        conda_frontend,
        "conda_prefix":
        os.path.join(base_dir, ".snakemake"),
        "dryrun":
        args.dryrun,
        "printreason":
        args.reason,
        "keepgoing":
        args.keep_going,
        "unlock":
        args.unlock,
        "force_incomplete":
        args.rerun_incomplete
    }

    # get the additional snakemake options
    snakemake_options = args.snakemakeOptions if args.snakemakeOptions is not None else dict(
    )
    snakemake_options.setdefault("config", {}).update(
        {"rule_dir": os.path.join(base_dir, "rules")})
    snakemake_options["configfiles"] = [config_path]
    parsed_args.update(snakemake_options)

    # parse the profile
    if args.profile is not None:
        profile_file = snakemake.get_profile_file(args.profile, "config.yaml")
        if profile_file is None:
            subjectively_prettier_error(
                profile_arg, "profile given but no config.yaml found.")
        add_profile_args(profile_file, parsed_args)

    # cores
    if args.cores:  # CLI
        parsed_args["cores"] = args.cores
    elif parsed_args.get("cores"):  # profile
        parsed_args["cores"] = int(parsed_args["cores"])
    elif parsed_args["dryrun"]:
        parsed_args["cores"] = 999
    else:
        parsed_args["cores"] = 0

    if parsed_args["cores"] < 2:
        subjectively_prettier_error(core_arg, "specify at least two cores.")

    # when running on a cluster assume cores == nodes (just like snakemake does)
    if "cluster" in parsed_args and not "nodes" in parsed_args:
        parsed_args["nodes"] = parsed_args["cores"]

    core_parser(parsed_args)
    parsed_args["config"].update({"cores": parsed_args["cores"]})
    resource_parser(parsed_args)

    # run snakemake
    exit_code = snakemake.snakemake(**parsed_args)
    sys.exit(0) if exit_code else sys.exit(1)