레시피: FASTQ 파일을 정해진 레코드 수로 시각화하기 (params 함수 활용)

난이도: 중급

파일 하위 샘플링 레시피에서는 출력 파일 이름만을 기반으로 특정 줄 수만큼 파일을 생성하는 방법을 보여주었습니다. 만약 FASTQ 파일에서 특정 줄 수가 아니라 특정 레코드(record) 수를 샘플링하고 싶다면 어떻게 해야 할까요? FASTQ의 한 레코드는 4줄로 구성되므로, 와일드카드에 지정된 레코드 수를 실제 줄 수로 변환하는 과정이 필요합니다.

이를 위해 Snakemake는 params: 블록에서 Python 함수를 사용하는 것을 지원합니다. 다음 레시피에서는 num_records 와일드카드에 지정된 레코드 수를 기반으로 샘플링할 줄 수를 계산합니다.

def calc_num_lines(wildcards):
    # wildcards.num_records를 정수로 변환합니다.
    num_records = int(wildcards.num_records)

    # 줄 수를 계산합니다 (레코드당 4줄).
    num_lines = num_records * 4

    return num_lines

rule all:
    input:
        "big.subset25.fastq"

rule subset:
    input:
        "big.fastq"
    output:
        "big.subset{num_records}.fastq"
    params:
        num_lines = calc_num_lines
    shell: """
        head -{params.num_lines} {input} > {output}
    """

여기에는 두 가지 특별한 구성 요소가 있습니다.

람다(lambda) 함수 사용하기

위의 코드는 함수 정의 때문에 조금 길게 느껴질 수 있습니다. 무명 함수인 “람다(lambda)”를 사용하면 훨씬 짧고 간결한 Snakefile을 작성할 수 있습니다 (단, 가독성은 조금 떨어질 수 있습니다).

rule all:
    input:
        "big.subset25.fastq"

rule subset:
    input:
        "big.fastq"
    output:
        "big.subset{num_records}.fastq"
    params:
        num_lines = lambda wildcards: int(wildcards.num_records) * 4
    shell: """
        head -{params.num_lines} {input} > {output}
    """

여기서 lambdawildcards라는 하나의 파라미터를 받아 wildcards.num_records에 4를 곱한 값을 반환하는 익명 함수를 생성합니다.

참고 문서: * Snakemake 공식 문서 - params 함수 * Python의 람다(lambda) 기초