// Simulate single-end sequencing from a fragment. void SequencingSimulator::_simulateBSTreatment(seqan::Dna5String & methFragment, TFragment const & frag, MethylationLevels const & levels, bool reverse) { methFragment = frag; for (unsigned pos = 0; pos != length(frag); ++pos) { double level = reverse ? levels.levelR(pos + beginPosition(frag)) : levels.levelF(pos + beginPosition(frag)); if ((!reverse && methFragment[pos] != 'C') || (reverse && methFragment[pos] != 'G')) // Skip all non-cyteline chars { SEQAN_ASSERT_EQ_MSG(level, 0.0, "Methylation for non-C should be 0 (pos+beginPosition(frag)=%d, reverse=%u", pos + beginPosition(frag), reverse); continue; } // Decide whether methFragment[pos] is methylated. If this is the case then we leave it untouched. seqan::Pdf<seqan::Uniform<double> > pdf(0, 1); if (pickRandomNumber(methRng, pdf) < level) continue; // Otherwise, pick whether we will convert. if (pickRandomNumber(methRng, pdf) < seqOptions->bsSeqOptions.bsConversionRate) methFragment[pos] = reverse ? 'A' : 'T'; } }
// Simulate single-end sequencing from a fragment. void SequencingSimulator::simulateSingleEnd(TRead & seq, TQualities & quals, SequencingSimulationInfo & info, TFragment const & frag, MethylationLevels const * levels) { bool isForward; if (seqOptions->strands == SequencingOptions::BOTH) isForward = (pickRandomNumber(rng, seqan::Pdf<seqan::Uniform<int> >(0, 1)) == 1); else isForward = (seqOptions->strands == SequencingOptions::FORWARD); if (!seqOptions->bsSeqOptions.bsSimEnabled) { _simulateSingleEnd(seq, quals, info, frag, isForward); } else { SEQAN_ASSERT(levels); bool bsForward = isForward; // Re-pick strandedness of the BS-treated fragment. if (seqOptions->bsSeqOptions.bsProtocol != BSSeqOptions::DIRECTIONAL) bsForward = (pickRandomNumber(methRng, seqan::Pdf<seqan::Uniform<int> >(0, 1)) == 1); _simulateBSTreatment(methFrag, frag, *levels, !bsForward); _simulateSingleEnd(seq, quals, info, infix(methFrag, 0, length(methFrag)), isForward); } }
int simulateGenome(seqan::SequenceStream & stream, MasonSimulateGenomeOptions const & options) { // Initialize RNG and PDF. seqan::Rng<seqan::MersenneTwister> rng(options.seed); seqan::Pdf<seqan::Uniform<double> > pdf(0, 1); seqan::CharString id; seqan::Dna5String contig; for (unsigned i = 0; i < length(options.contigLengths); ++i) { clear(id); clear(contig); std::stringstream ss; ss << (i + 1); id = ss.str(); std::cerr << "contig " << id << " ..."; for (int j = 0; j < options.contigLengths[i];) { double x = pickRandomNumber(rng, pdf); if (x < 0.25) appendValue(contig, 'A'); else if (x < 0.5) appendValue(contig, 'C'); else if (x < 0.75) appendValue(contig, 'G'); else if (x < 1.0) appendValue(contig, 'T'); else continue; // Redraw. ++j; } if (writeRecord(stream, id, contig) != 0) { std::cerr << "\nERROR: Could not write contig " << id << " to output file.\n"; return 1; } std::cerr << " DONE\n"; } return 0; }