Buckets:
| import random | |
| from contextlib import ExitStack | |
| from pathlib import Path | |
| from loguru import logger | |
| from bioflow_sim.core.io import ( | |
| fastq_writer, | |
| prepare_output_directory, | |
| read_fasta, | |
| validate_sample_name, | |
| write_fastq_record, | |
| write_json, | |
| write_tsv, | |
| ) | |
| from bioflow_sim.generators.methylation import ( | |
| convert_unmethylated_cytosines, | |
| generate_cpg_methylation, | |
| sample_template_around_cpg, | |
| ) | |
| from bioflow_sim.generators.random_values import sample_positive_normal | |
| from bioflow_sim.generators.read_models import TECHNOLOGIES, introduce_errors | |
| from bioflow_sim.generators.sequences import reverse_complement | |
| METHYLATION_PROTOCOLS = ('wgbs', 'emseq') | |
| def simulate_methylation( | |
| *, | |
| reference: Path, | |
| output_dir: Path, | |
| sample: str, | |
| protocol: str, | |
| reads: int, | |
| sites: int, | |
| methylation_rate: float, | |
| conversion_rate: float, | |
| read_length: int, | |
| fragment_mean: int, | |
| fragment_sd: int, | |
| seed: int, | |
| ) -> dict[str, object]: | |
| if reads < 1: | |
| raise ValueError('reads must be positive') | |
| validate_sample_name(sample) | |
| sequences = [(name, sequence) for name, _, sequence in read_fasta(reference)] | |
| rng = random.Random(seed) | |
| truth_sites = generate_cpg_methylation(rng, sequences, sites, methylation_rate) | |
| site_lookup = {(site.contig, site.position): site for site in truth_sites} | |
| prepare_output_directory(output_dir) | |
| raw_dir = output_dir / 'raw' | |
| r1_path = raw_dir / f'{sample}_R1.fastq.gz' | |
| r2_path = raw_dir / f'{sample}_R2.fastq.gz' | |
| illumina = TECHNOLOGIES['illumina-pe'] | |
| read_truth: list[list[object]] = [] | |
| with ExitStack() as stack: | |
| r1 = stack.enter_context(fastq_writer(r1_path)) | |
| r2 = stack.enter_context(fastq_writer(r2_path)) | |
| for ordinal in range(1, reads + 1): | |
| fragment_length = sample_positive_normal( | |
| rng, | |
| fragment_mean, | |
| fragment_sd, | |
| read_length * 2, | |
| max(len(sequence) for _, sequence in sequences), | |
| ) | |
| template, focal_site = sample_template_around_cpg(rng, sequences, truth_sites, fragment_length) | |
| converted, conversions = convert_unmethylated_cytosines(rng, template, site_lookup, conversion_rate) | |
| read1, s1, i1, d1 = introduce_errors(converted[:read_length], rng, illumina) | |
| read2, s2, i2, d2 = introduce_errors(reverse_complement(converted[-read_length:]), rng, illumina) | |
| read_id = f'{sample}:{ordinal:09d}' | |
| write_fastq_record(r1, f'{read_id}/1', read1, 'I' * len(read1)) | |
| write_fastq_record(r2, f'{read_id}/2', read2, 'I' * len(read2)) | |
| read_truth.append( | |
| [ | |
| read_id, | |
| template.source_id, | |
| template.start, | |
| template.end, | |
| template.strand, | |
| focal_site.position, | |
| conversions, | |
| s1 + s2, | |
| i1 + i2, | |
| d1 + d2, | |
| ] | |
| ) | |
| write_tsv( | |
| raw_dir / 'library.tsv', | |
| ['sample_id', 'protocol', 'layout', 'conversion_rate'], | |
| [[sample, protocol, 'paired-end', conversion_rate]], | |
| ) | |
| write_tsv( | |
| output_dir / 'truth' / 'methylation.tsv', | |
| ['contig', 'position_0based', 'context', 'methylated'], | |
| ([site.contig, site.position, 'CG', int(site.methylated)] for site in truth_sites), | |
| ) | |
| write_tsv( | |
| output_dir / 'truth' / 'reads.tsv', | |
| [ | |
| 'read_id', | |
| 'contig', | |
| 'start_0based', | |
| 'end_0based_exclusive', | |
| 'strand', | |
| 'focal_cpg_0based', | |
| 'conversions', | |
| 'substitutions', | |
| 'insertions', | |
| 'deletions', | |
| ], | |
| read_truth, | |
| ) | |
| metadata: dict[str, object] = { | |
| 'schema_version': 1, | |
| 'assay': protocol, | |
| 'sample': sample, | |
| 'reference': str(reference.resolve()), | |
| 'seed': seed, | |
| 'read_pairs': reads, | |
| 'output_files': [ | |
| str(r1_path.relative_to(output_dir)), | |
| str(r2_path.relative_to(output_dir)), | |
| 'raw/library.tsv', | |
| ], | |
| 'truth_files': ['truth/methylation.tsv', 'truth/reads.tsv'], | |
| 'parameters': { | |
| 'sites': sites, | |
| 'methylation_rate': methylation_rate, | |
| 'conversion_rate': conversion_rate, | |
| 'read_length': read_length, | |
| 'fragment_mean': fragment_mean, | |
| 'fragment_sd': fragment_sd, | |
| 'unlisted_cytosines': 'treated as methylated', | |
| }, | |
| } | |
| write_json(output_dir / 'manifest.json', metadata) | |
| logger.success('Generated {} {} read pairs in {}', reads, protocol, output_dir) | |
| return metadata | |
Xet Storage Details
- Size:
- 4.85 kB
- Xet hash:
- 3849f5a9b24f335064de9c36c839afa3f57c771cc99cd524b6f540332dd529bc
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.