【问题标题】:'InputFiles' object has no attribute <X> when using a function as input for a snakemake rule当使用函数作为蛇形规则的输入时,'InputFiles' 对象没有属性 <X>
【发布时间】:2017-11-03 18:22:21
【问题描述】:

我有一个蛇形工作流程,其中一些规则具有复杂的功能作为输入:

def source_fold_data(wildcards):
    fold_type = wildcards.fold_type
    if fold_type in {"log2FoldChange", "lfcMLE"}:
        if hasattr(wildcards, "contrast_type"):
            # OPJ is os.path.join
            return expand(
                OPJ(output_dir, aligner, "mapped_C_elegans",
                    "deseq2_%s" % size_selected, "{contrast}",
                    "{contrast}_{{small_type}}_counts_and_res.txt"),
                contrast=contrasts_dict[wildcards.contrast_type])
        else:
            return rules.small_RNA_differential_expression.output.counts_and_res
    elif fold_type == "mean_log2_RPKM_fold":
        if hasattr(wildcards, "contrast_type"):
            # This is the branch used when I have the AttributeError
            #https://stackoverflow.com/a/26791923/1878788
            return [filename.format(wildcards) for filename in expand(
                OPJ(output_dir, aligner, "mapped_C_elegans",
                    "RPKM_folds_%s" % size_selected, "{contrast}",
                    "{contrast}_{{0.small_type}}_RPKM_folds.txt"),
                contrast=contrasts_dict[wildcards.contrast_type])]
        else:
            return rules.compute_RPKM_folds.output.fold_results
    else:
        raise NotImplementedError("Unknown fold type: %s" % fold_type)

上面的函数用作两个规则的输入:

rule make_gene_list_lfc_boxplots:
    input:
        data = source_fold_data,
    output:
        boxplots = OPJ(output_dir, "figures", "{contrast}",
            "{contrast}_{small_type}_{fold_type}_{gene_list}_boxplots.{fig_format}")
    params:
        id_lists = set_id_lists,
    run:
        data = pd.read_table(input.data, index_col="gene")
        lfcs = pd.DataFrame(
            {list_name : data.loc[set(id_list)][wildcards.fold_type] for (
                list_name, id_list) in params.id_lists.items()})
        save_plot(output.boxplots, plot_boxplots, lfcs, wildcards.fold_type)


rule make_contrast_lfc_boxplots:
    input:
        data = source_fold_data,
    output:
        boxplots = OPJ(output_dir, "figures", "all_{contrast_type}",
            "{contrast_type}_{small_type}_{fold_type}_{gene_list}_boxplots.{fig_format}")
    params:
        id_lists = set_id_lists,
    run:
        lfcs = pd.DataFrame(
            {f"{contrast}_{list_name}" : pd.read_table(filename, index_col="gene").loc[
                set(id_list)]["mean_log2_RPKM_fold"] for (
                    contrast, filename) in zip(contrasts_dict["ip"], input.data) for (
                        list_name, id_list) in params.id_lists.items()})
        save_plot(output.boxplots, plot_boxplots, lfcs, wildcards.fold_type)

第二个失败并显示'InputFiles' object has no attribute 'data',并且仅在某些情况下:我使用两个不同的配置文件运行相同的工作流,并且错误仅发生在两个配置文件中的一个中,尽管在两种情况下都执行了此规则,并且输入函数的相同分支被采用。

如果规则有:怎么会发生这种情况:

    input:
        data = ...

?

我想这与我的 source_fold_data 返回的内容有关,要么是另一个规则的显式输出,要么是“手动”构造的文件名列表。

【问题讨论】:

  • 将代码升级为minimal reproducible example。目前,没有足够的信息用于复制和诊断。
  • @ivan_pozdeev 我同意 100% 的最小可重现示例将有助于诊断问题。然而,这是一个相当复杂的工作流程,需要付出大量的努力和时间才能实现。同时,我希望这类问题可能会敲响比我更熟悉蛇形内部原理的人。
  • 嗯,那不是我,这是我第一次听说snakemake。这从未阻止我提供有用的答案,但前提是他们愿意提供足够的信息来重建正在发生的事情。事实证明,无论我是否了解产品,猜测都是一个相当低效的场所。
  • 我的猜测是在某些情况下该函数返回一个空列表。我会在 return 语句之前在变量中构造列表,然后打印它,然后返回它以查看是否可以缩小发生的范围。
  • @Colin 这是正确的猜测,谢谢。在错误的情况下,我的 contrasts_dict 有一个空列表作为键 wildcards.contrast_type 的条目。

标签: python snakemake


【解决方案1】:

正如 cmets 中的 @Colin 所建议的,当输入函数返回一个空列表时,就会出现问题。当contrasts_dict[wildcards.contrast_type] 是一个空列表时就是这种情况,这种情况表明尝试生成规则make_contrast_lfc_boxplots 的输出实际上没有意义。我通过修改规则all 的输入部分来避免这种情况,如下所示:

旧版本:

rule all:
    input:
        # [...]
        expand(OPJ(output_dir, "figures", "all_{contrast_type}", "{contrast_type}_{small_type}_{fold_type}_{gene_list}_boxplots.{fig_format}"), contrast_type=["ip"], small_type=IP_TYPES, fold_type=["mean_log2_RPKM_fold"], gene_list=BOXPLOT_GENE_LISTS, fig_format=FIG_FORMATS),
        # [...]

新版本:

if contrasts_dict["ip"]:
    ip_fold_boxplots = expand(OPJ(output_dir, "figures", "all_{contrast_type}", "{contrast_type}_{small_type}_{fold_type}_{gene_list}_boxplots.{fig_format}"), contrast_type=["ip"], small_type=IP_TYPES, fold_type=["mean_log2_RPKM_fold"], gene_list=BOXPLOT_GENE_LISTS, fig_format=FIG_FORMATS)
else:
    ip_fold_boxplots = []
rule all:
    input:
        # [...]
        ip_fold_boxplots,
        # [...]

snakemake/rules.py 的一些修改表明,在某些时候,Rule 名为 make_contrast_lfc_boxplots 的对象的 input 属性存在 data 属性,并且该属性仍然是 source_fold_data 函数.我想当它是一个空列表时,稍后会对其进行评估和删除,但我无法找到位置。

我想当snakemake构造规则之间的依赖图时,空输入不是问题。因此,该问题仅在规则执行期间发生。

【讨论】:

  • 谢谢!我陷入了一个具有相同输出的错误中几个小时。我可以确认,当您在规则中的脚本尝试访问输入文件时会发生此错误,但它会得到一个空列表。 contrasts_dict 是否与 defaultdict 对应?
  • @Geparada 我没有检查,但我不认为contrasts_dictdefaultdict。我认为它是从配置文件中读取的,其中的部分可能是一个空列表。
猜你喜欢
  • 1970-01-01
  • 2018-08-26
  • 2019-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多