레시피: 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}
"""여기에는 두 가지 특별한 구성 요소가 있습니다.
- Python 함수
calc_num_lines:wildcards객체를 매개변수로 받아wildcards.num_records값을 기반으로 하위 샘플링할 줄 수를 계산합니다. params:블록:calc_num_lines함수를 할당하여params.num_lines를 생성합니다. 이렇게 생성된 값은 셸 명령에서 바로 사용할 수 있습니다.
람다(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}
"""여기서 lambda는 wildcards라는 하나의 파라미터를 받아 wildcards.num_records에 4를 곱한 값을 반환하는 익명 함수를 생성합니다.
참고 문서: * Snakemake 공식 문서 - params 함수 * Python의 람다(lambda) 기초