Exemplo n.º 1
0
void ReflectedGroupItem::getChildValues(Variants &childValues) const
{
	if( groupObj_ == nullptr )
		return;

	auto object = getObject();
	if (object == nullptr)
		return;

	auto definitionManager = getDefinitionManager();
	if( definitionManager == nullptr )
		return;

	auto definition = object.getDefinition( *getDefinitionManager() );
	if( definition == nullptr )
		return;

	EnumerateVisibleProperties([&](IBasePropertyPtr property, const std::string & inplacePath){
		// Check if this property is a part of this group
		const auto groupObj = findFirstMetaData< MetaGroupObj >(*property, *definitionManager);
		if ( isSameGroup( groupObj ) )
		{
			auto path = inplacePath + property->getName();
			auto propertyAccessor = definition->bindProperty( path.c_str(), object );
			Variant value = getController()->getValue(propertyAccessor);
			childValues.emplace_back(value);
		}
		return true;
	});
}
Exemplo n.º 2
0
/** enqueue a set of variants */
void VariantCallsOnly::add(Variants const & v)
{
    if (_impl->buffered_variants.size() > 0 &&
        v.chr == _impl->buffered_variants.back().chr &&
        v.pos < _impl->buffered_variants.back().pos)
    {
        error("Variant added out of order at %s:%i / %i", v.chr.c_str(), v.pos, _impl->buffered_variants.back().pos);
    }
#ifdef DEBUG_VARIANTCALLSONLY
    std::cerr << "Variants added: " << v << "\n";
#endif
    if (v.anyHomref())
    {
        Variants non_hr = v;
        int n_non_hr = v.calls.size();
        for (size_t q = 0; q < v.calls.size(); ++q)
        {
            if(v.calls[q].isHomref())
            {
                non_hr.calls[q] = Call();
                _impl->homref_ivs.addInterval(v.pos, v.pos + v.len - 1, q);

                // remember dp
                if(q >= _impl->homref_dp.size())
                {
                    _impl->homref_dp.resize(q+1);
                }
                _impl->homref_dp[q].set(v.calls[q].dp, v.pos, v.pos + v.len - 1);

                // remember gq
                if(q >= _impl->homref_gq.size())
                {
                    _impl->homref_gq.resize(q+1);
                }
                _impl->homref_gq[q].set(v.calls[q].gq, v.pos, v.pos + v.len - 1);

                --n_non_hr;
            }
            else if(v.calls[q].isNocall())
            {
                --n_non_hr;
            }
        }
        if (n_non_hr || non_hr.anyAmbiguous())
        {
#ifdef DEBUG_VARIANTCALLSONLY
            std::cerr << "non-hr-add: " << v << "\n";
#endif
            _impl->buffered_variants.push_back(non_hr);
        }
    }
    else
    {
#ifdef DEBUG_VARIANTCALLSONLY
        std::cerr << "non-hr-pass-on: " << v << "\n";
#endif
        _impl->buffered_variants.push_back(v);
    }
}
Exemplo n.º 3
0
int VcfMaterializer::_loadVariantsForContig(Variants & variants, int rID)
{
    variants.clear();

    // Compute number of haplotypes.
    SEQAN_ASSERT_NOT(empty(vcfRecord.genotypeInfos));
    seqan::StringSet<seqan::CharString> xs;
    seqan::DirectionIterator<seqan::CharString const, seqan::Input>::Type inputIter =
            directionIterator(vcfRecord.genotypeInfos[0], seqan::Input());
    numHaplotypes = 1;
    for (; !atEnd(inputIter); ++inputIter)
        numHaplotypes += (*inputIter == '|' || *inputIter == '/');

    std::vector<seqan::VcfRecord> chunk;
    while (vcfRecord.rID != -1 && vcfRecord.rID <= rID)
    {
        // Translocations are the only SVs that are stored as breakends (BND).  We collect the BNDs in chunks of 6
        // which then represent a translocation.  Requiring that the BNDs are stored in adjacent chunks of 6 records
        // is a strong limitation but supporting more generic variations would be a bit too much here.
        if (contains(vcfRecord.info, "SVTYPE=BND"))
        {
            chunk.push_back(vcfRecord);
            if (chunk.size() == 6u)
            {
                _appendToVariantsBnd(variants, chunk);
                chunk.clear();
            }
        }
        else
        {
            SEQAN_CHECK(chunk.size() == 0u, "Found chunk of != 6 BND records!");
            _appendToVariants(variants, vcfRecord);
        }

        if (atEnd(vcfFileIn))
        {
            vcfRecord.rID = -1;
            continue;
        }
        readRecord(vcfRecord, vcfFileIn);
    }

    return 0;
}
Exemplo n.º 4
0
/** enqueue a set of variants */
void VariantAlleleNormalizer::add(Variants const & vs)
{
    bool all_homref = true;
    for(Call const & c : vs.calls)
    {
        if(!(c.isHomref() || c.isNocall()))
        {
            all_homref = false;
            break;
        }
    }

    for(auto const & x : vs.ambiguous_alleles)
    {
        if(!x.empty())
        {
            all_homref = false;
            break;
        }
    }

    if (all_homref && !_impl->homref)
    {
#ifdef DEBUG_VARIANTNORMALIZER
        std::cerr << "Skipping homref variant: " << vs << "\n";
#endif
        return;
    }

    // don't touch import fails
    if (vs.getInfoFlag("IMPORT_FAIL"))
    {
        _impl->buffered_variants.push(vs);
        return;
    }

    Variants nv(vs);
    size_t tmp = 0;
    _impl->current_maxpos.resize(std::max(_impl->current_maxpos.size(), nv.calls.size()), tmp);

#ifdef DEBUG_VARIANTNORMALIZER
    std::cerr << "before: " << nv << "\n";
#endif

    if(_impl->ref_fasta)
    {
        int64_t new_start = -1;
        int64_t new_end = -1;
        int64_t leftshift_limit = -1;

        if(_impl->limit >= 0)
        {
            leftshift_limit = nv.pos - _impl->limit;
        }

        for (size_t rvc = 0; rvc < nv.variation.size(); ++rvc)
        {
            int64_t this_leftshift_limit = leftshift_limit;
            if(nv.chr == _impl->maxpos_chr)
            {
                for(size_t j = 0; j < nv.calls.size(); ++j)
                {
                    for(size_t c = 0; c < nv.calls[j].ngt; ++c)
                    {
                        if(nv.calls[j].gt[c] - 1 == (int)rvc)
                        {
                            this_leftshift_limit = std::max(this_leftshift_limit, _impl->current_maxpos[j]);
                        }
                    }
                }
            }
#ifdef DEBUG_VARIANTNORMALIZER
            std::cerr << "leftshift limit for " << nv.variation[rvc] << " is " << this_leftshift_limit << "\n";
#endif
            leftShift(*(_impl->ref_fasta), nv.chr.c_str(), nv.variation[rvc], this_leftshift_limit);

            trimLeft(*(_impl->ref_fasta), nv.chr.c_str(), nv.variation[rvc], _impl->refpadding);
            trimRight(*(_impl->ref_fasta), nv.chr.c_str(), nv.variation[rvc], _impl->refpadding);
            if(new_start < 0 || new_start > nv.variation[rvc].start)
            {
                new_start = nv.variation[rvc].start;
            }
            if(new_end < 0 || new_end > nv.variation[rvc].end)
            {
                new_end = nv.variation[rvc].end;
            }
        }

        if (new_start > 0 && new_end > 0)
        {
            nv.pos = new_start;
            nv.len = new_end - new_start + 1;
            // handle insertions
            if (nv.len == 0)
            {
                --nv.pos;
                nv.len = 1;
            }
        }
    }
#ifdef DEBUG_VARIANTNORMALIZER
    std::cerr << "after: " << nv << "\n";
#endif
    if(_impl->maxpos_chr != nv.chr)
    {
        for(size_t j = 0; j < nv.calls.size(); ++j)
        {
            if(!nv.calls[j].isNocall() && !nv.calls[j].isHomref())
            {
                _impl->current_maxpos[j] = nv.pos + nv.len - 1;
            }
        }
    }
    else
    {
        for(size_t j = 0; j < nv.calls.size(); ++j)
        {
            if(!nv.calls[j].isNocall() && !nv.calls[j].isHomref())
            {
                _impl->current_maxpos[j] = std::max(nv.pos + nv.len - 1, _impl->current_maxpos[j]);
            }
        }
    }
    _impl->maxpos_chr = nv.chr;
#ifdef DEBUG_VARIANTNORMALIZER
    std::cerr << "new max-shifting pos on " << _impl->maxpos_chr << " : ";
    for(size_t s = 0; s < _impl->current_maxpos.size(); ++s)
    {
        std::cerr << " s" << s << ": " << _impl->current_maxpos[s] << "  ";
    }
    std::cerr << "\n";
#endif
    _impl->buffered_variants.push(nv);
}
Exemplo n.º 5
0
 bool test(Variants const & v) { return v.anyHomref(); }
Exemplo n.º 6
0
    Variant& StackMachine::evaluate(const VariableStore& store, const FunctionRegistry& functions)
    {
        reset();

        for(const auto& instruction : _instructions) {
            switch(instruction._opCode) {
                case NOP: {
                    break;
                }
                case PUSH: {
                    _valueStack.emplace(instruction._value);
                    break;
                }
                case PUSHVAR: {
                    if(instruction._value.getType() != INT) {
                        CSVSQLDB_THROW(StackMachineException, "expected an INT as variable index");
                    }

                    int64_t index = instruction._value.asInt();
                    _valueStack.emplace(store[static_cast<size_t>(index)]);
                    break;
                }
                case ADD:
                case SUB:
                case DIV:
                case MOD:
                case MUL:
                case EQ:
                case NEQ:
                case IS:
                case ISNOT:
                case GT:
                case GE:
                case LT:
                case LE:
                case AND:
                case OR:
                case CONCAT: {
                    const Variant lhs(getNextValue());
                    Variant& rhs(getTopValue());
                    rhs = binaryOperation(mapOpCodeToBinaryOperationType(instruction._opCode), lhs, rhs);
                    break;
                }
                case NOT: {
                    Variant& rhs(getTopValue());
                    rhs = unaryOperation(OP_NOT, BOOLEAN, rhs);
                    break;
                }
                case PLUS: {
                    // this is a nop, as the value will not change, so just leave it on the stack
                    break;
                }
                case MINUS: {
                    Variant& rhs = getTopValue();
                    rhs = unaryOperation(OP_MINUS, rhs.getType(), rhs);
                    break;
                }
                case BETWEEN: {
                    const Variant lhs = getNextValue();
                    const Variant from = getNextValue();
                    Variant& to = getTopValue();

                    Variant result(BOOLEAN);
                    if(not(lhs.isNull() || from.isNull() || to.isNull())) {
                        if(binaryOperation(OP_GE, to, from).asBool()) {
                            result = binaryOperation(OP_GE, lhs, from);
                            if(result.asBool()) {
                                result = binaryOperation(OP_LE, lhs, to);
                            }
                        } else {
                            result = binaryOperation(OP_GE, lhs, to);
                            if(result.asBool()) {
                                result = binaryOperation(OP_LE, lhs, from);
                            }
                        }
                    }
                    to = result;
                    break;
                }
                case FUNC: {
                    if(instruction._value.getType() != STRING) {
                        CSVSQLDB_THROW(StackMachineException, "expected a string as variable name");
                    }

                    std::string funcname = instruction._value.asString();
                    Function::Ptr func = functions.getFunction(funcname);
                    if(!func) {
                        CSVSQLDB_THROW(StackMachineException, "function '" << funcname << "' not found");
                    }
                    Variants parameter;
                    size_t count = func->getParameterTypes().size();
                    for(const auto& param : func->getParameterTypes()) {
                        Variant v = getNextValue();
                        if(param != v.getType()) {
                            try {
                                v = unaryOperation(OP_CAST, param, v);
                            } catch(const std::exception&) {
                                CSVSQLDB_THROW(StackMachineException,
                                               "calling function '" << funcname << "' with wrong parameter");
                            }
                        }
                        parameter.emplace(parameter.end(), v);
                        --count;
                    }
                    if(count) {
                        CSVSQLDB_THROW(StackMachineException, "too much parameters for function '" << funcname << "'");
                    }
                    _valueStack.emplace(func->call(parameter));
                    break;
                }
                case CAST: {
                    Variant& rhs = getTopValue();
                    rhs = unaryOperation(OP_CAST, instruction._value.getType(), rhs);
                    break;
                }
                case IN: {
                    size_t count = static_cast<size_t>(instruction._value.asInt());
                    const Variant lhs = getNextValue();
                    bool found(false);
                    for(size_t n = 0; n < count; ++n) {
                        Variant result = binaryOperation(OP_EQ, lhs, getNextValue());
                        if(result.asBool()) {
                            found = true;
                            ++n;
                            for(; n < count; ++n) {
                                // remove rest of the values from stack
                                _valueStack.pop();
                            }
                            break;
                        }
                    }
                    if(found) {
                        _valueStack.emplace(Variant(true));
                    } else {
                        _valueStack.emplace(Variant(false));
                    }
                    break;
                }
                case LIKE: {
                    if(!instruction._r) {
                        CSVSQLDB_THROW(StackMachineException, "expected a regexp in LIKE expression");
                    }
                    Variant lhs = getTopValue();
                    if(lhs.getType() != STRING) {
                        lhs = unaryOperation(OP_CAST, STRING, lhs);
                        CSVSQLDB_THROW(StackMachineException, "can only do like operations on strings");
                    }
                    if(instruction._r->match(lhs.asString())) {
                        _valueStack.emplace(Variant(true));
                    } else {
                        _valueStack.emplace(Variant(false));
                    }
                    break;
                }
            }
        }

        return _valueStack.top();
    }
Exemplo n.º 7
0
int VariantMaterializer::_materializeLargeVariants(
        seqan::Dna5String & seq,
        MethylationLevels * levelsLargeVariants,
        std::vector<SmallVarInfo> & varInfos,
        std::vector<std::pair<int, int> > & breakpoints,
        PositionMap & positionMap,
        TJournalEntries const & journal,
        seqan::Dna5String const & contig,
        std::vector<SmallVarInfo> const & smallVarInfos,
        Variants const & variants,
        MethylationLevels const * levels,
        int hId)
{
    if (methSimOptions)
    {
        SEQAN_ASSERT_EQ(methSimOptions->simulateMethylationLevels, (levelsLargeVariants != 0));
        SEQAN_ASSERT_EQ(methSimOptions->simulateMethylationLevels, (levels != 0));
    }

    // We will record all intervals for the positionMap.svIntervalTree in this String.
    seqan::String<GenomicInterval> intervals;

    // Clear output methylation levels->
    if (levelsLargeVariants)
        levelsLargeVariants->clear();
    // Store variation points.  We reuse the fixVariationLevels() function from small indel/snp simulation and thus
    // have to store a bool that is always set to false.
    seqan::String<std::pair<int, bool> > varPoints;

    // Track last position from contig appended to seq so far.
    int lastPos = 0;
    if (verbosity >= 3)
        std::cerr << __LINE__ << "\tlastPos == " << lastPos << "\n";

    // Pointer to the current small variant to write out translated to varInfo.
    std::vector<SmallVarInfo>::const_iterator itSmallVar = smallVarInfos.begin();

    // Number of bytes written out so far/current position in variant.
    unsigned currentPos = 0;

    for (unsigned i = 0; i < length(variants.svRecords); ++i)
    {
        if (variants.svRecords[i].haplotype != hId)  // Ignore all but the current contig.
            continue;
        // We obtain a copy of the current SV record since we translate its positions below.
        StructuralVariantRecord svRecord = variants.svRecords[i];

        // Translate positions and lengths of SV record.
        if (verbosity >= 2)
            std::cerr << "  Translating SvRecord\n  " << svRecord << '\n';
        svRecord.pos = hostToVirtualPosition(journal, svRecord.pos);
        SEQAN_ASSERT_LT(svRecord.pos, (int)length(contig));
        // We do not need to adjust the sizes for insertions.
        if (svRecord.kind != StructuralVariantRecord::INDEL || svRecord.size < 0)
            svRecord.size = hostToVirtualPosition(journal, svRecord.pos + svRecord.size) -
                    hostToVirtualPosition(journal, svRecord.pos);
        if (svRecord.targetPos != -1)
            svRecord.targetPos = hostToVirtualPosition(journal, svRecord.targetPos);
        if (verbosity >= 2)
            std::cerr << "  => " << svRecord << '\n';

        // Copy out small variant infos for interim chars.
        for (; itSmallVar != smallVarInfos.end() && itSmallVar->pos < svRecord.pos; ++itSmallVar)
        {
            int offset = (int)currentPos - lastPos;
            varInfos.push_back(*itSmallVar);
            varInfos.back().pos += offset;
        }

        // Copy from contig to seq with SVs.
        if (verbosity >= 3)
            std::cerr << "lastPos == " << lastPos << "\n";
        append(seq, infix(contig, lastPos, svRecord.pos));  // interim chars
        if (methSimOptions && methSimOptions->simulateMethylationLevels)
        {
            append(levelsLargeVariants->forward, infix(levels->forward, lastPos, svRecord.pos));
            append(levelsLargeVariants->reverse, infix(levels->reverse, lastPos, svRecord.pos));
            appendValue(varPoints, std::make_pair((int)length(seq), false));
        }
        if (currentPos != length(seq))
            appendValue(intervals, GenomicInterval(currentPos, length(seq), lastPos, svRecord.pos,
                                                   '+', GenomicInterval::NORMAL));
        currentPos = length(seq);
        if (verbosity >= 3)
            std::cerr << "append(seq, infix(contig, " << lastPos << ", " << svRecord.pos << ") " << __LINE__ << " (interim)\n";
        switch (svRecord.kind)
        {
            case StructuralVariantRecord::INDEL:
                {
                    if (svRecord.size > 0)  // insertion
                    {
                        SEQAN_ASSERT_EQ((int)length(svRecord.seq), svRecord.size);

                        // Simulate methylation levels for insertion.
                        MethylationLevels lvls;
                        if (methSimOptions && methSimOptions->simulateMethylationLevels)
                        {
                            MethylationLevelSimulator methSim(*rng, *methSimOptions);
                            methSim.run(lvls, svRecord.seq);
                        }

                        // Append novel sequence and methylation levels.
                        append(seq, svRecord.seq);
                        if (methSimOptions && methSimOptions->simulateMethylationLevels)
                        {
                            append(levelsLargeVariants->forward, lvls.forward);
                            append(levelsLargeVariants->reverse, lvls.reverse);
                            appendValue(varPoints, std::make_pair((int)length(seq), false));  // variation point after insertion
                        }
                        if (currentPos != length(seq))
                            appendValue(intervals, GenomicInterval(currentPos, length(seq), -1, -1,
                                                                   '+', GenomicInterval::INSERTED));
                        if (verbosity >= 3)
                            std::cerr << "append(seq, svRecord.seq (length == " << length(svRecord.seq) << ") " << __LINE__ << " (insertion)\n";
                        lastPos = svRecord.pos;
                        SEQAN_ASSERT_LT(lastPos, (int)length(contig));

                        // Copy out breakpoints.
                        breakpoints.push_back(std::make_pair(currentPos, variants.posToIdx(Variants::SV, i)));
                        breakpoints.push_back(std::make_pair((int)length(seq), variants.posToIdx(Variants::SV, i)));

                        currentPos = length(seq);
                    }
                    else  // deletion
                    {
                        lastPos = svRecord.pos - svRecord.size;
                        SEQAN_ASSERT_LT(lastPos, (int)length(contig));

                        // Copy out breakpoint.
                        breakpoints.push_back(std::make_pair(currentPos, variants.posToIdx(Variants::SV, i)));
                    }
                }
                break;
            case StructuralVariantRecord::INVERSION:
                {
                    unsigned oldLen = length(seq);
                    append(seq, infix(contig, svRecord.pos, svRecord.pos + svRecord.size));
                    if (methSimOptions && methSimOptions->simulateMethylationLevels)
                    {
                        appendValue(varPoints, std::make_pair((int)length(seq), false));  // variation point at deletion
                        append(levelsLargeVariants->forward, infix(levels->reverse, svRecord.pos, svRecord.pos + svRecord.size));
                        reverse(infix(levelsLargeVariants->forward, oldLen, length(levelsLargeVariants->forward)));
                        append(levelsLargeVariants->reverse, infix(levels->forward, svRecord.pos, svRecord.pos + svRecord.size));
                        reverse(infix(levelsLargeVariants->reverse, oldLen, length(levelsLargeVariants->reverse)));
                    }
                    if (currentPos != length(seq))
                        appendValue(intervals, GenomicInterval(currentPos, length(seq), svRecord.pos, svRecord.pos + svRecord.size,
                                                               '-', GenomicInterval::INVERTED));

                    // Copy out small variant infos for inversion.
                    for (; itSmallVar != smallVarInfos.end() && itSmallVar->pos < svRecord.pos + svRecord.size; ++itSmallVar)
                    {
                        varInfos.push_back(*itSmallVar);
                        varInfos.back().pos = currentPos + svRecord.size - (varInfos.back().pos - lastPos);
                    }

                    if (verbosity >= 3)
                        std::cerr << "append(seq, infix(contig, " << svRecord.pos << ", " << svRecord.pos + svRecord.size << ") " << __LINE__ << " (inversion)\n";
                    reverseComplement(infix(seq, oldLen, length(seq)));
                    lastPos = svRecord.pos + svRecord.size;
                    SEQAN_ASSERT_LT(lastPos, (int)length(contig));

                    // Copy out breakpoints.
                    breakpoints.push_back(std::make_pair(currentPos, variants.posToIdx(Variants::SV, i)));
                    breakpoints.push_back(std::make_pair((int)length(seq), variants.posToIdx(Variants::SV, i)));

                    currentPos = length(seq);
                }
                break;
            case StructuralVariantRecord::TRANSLOCATION:
                {
                    SEQAN_ASSERT_GEQ(svRecord.targetPos, svRecord.pos + svRecord.size);
                    append(seq, infix(contig, svRecord.pos + svRecord.size, svRecord.targetPos));
                    if (methSimOptions && methSimOptions->simulateMethylationLevels)
                    {
                        appendValue(varPoints, std::make_pair((int)length(seq), false));
                        append(levelsLargeVariants->forward, infix(levels->forward, svRecord.pos + svRecord.size, svRecord.targetPos));
                        append(levelsLargeVariants->reverse, infix(levels->reverse, svRecord.pos + svRecord.size, svRecord.targetPos));
                    }
                    if (currentPos != length(seq))
                        appendValue(intervals, GenomicInterval(currentPos, length(seq), svRecord.pos + svRecord.size, svRecord.targetPos,
                                                               '+', GenomicInterval::NORMAL));
                    unsigned tmpCurrentPos = length(seq);
                    append(seq, infix(contig, svRecord.pos, svRecord.pos + svRecord.size));
                    if (methSimOptions && methSimOptions->simulateMethylationLevels)
                    {
                        appendValue(varPoints, std::make_pair((int)length(seq), false));
                        append(levelsLargeVariants->forward, infix(levels->forward, svRecord.pos, svRecord.pos + svRecord.size));
                        append(levelsLargeVariants->reverse, infix(levels->reverse, svRecord.pos, svRecord.pos + svRecord.size));
                    }
                    if (tmpCurrentPos != length(seq))
                        appendValue(intervals, GenomicInterval(tmpCurrentPos, length(seq), svRecord.pos, svRecord.pos + svRecord.size,
                                                               '+', GenomicInterval::NORMAL));
                    if (verbosity >= 3)
                        std::cerr << "append(seq, infix(contig, " << svRecord.pos + svRecord.size << ", " << svRecord.targetPos << ") " << __LINE__ << " (translocation)\n"
                                  << "append(seq, infix(contig, " << svRecord.pos << ", " << svRecord.pos + svRecord.size << ") " << __LINE__ << "\n";
                    lastPos = svRecord.targetPos;
                    SEQAN_ASSERT_LT(lastPos, (int)length(contig));

                    // Copy out small variant infos for translocation, shift left to right and righ to left but keep
                    // center intact.
                    for (; itSmallVar != smallVarInfos.end() && itSmallVar->pos < svRecord.pos; ++itSmallVar)
                    {
                        int offset = (int)currentPos - lastPos;
                        varInfos.push_back(*itSmallVar);
                        varInfos.back().pos += offset;

                        int bpLeft = svRecord.pos + svRecord.size;
                        int bpRight = svRecord.targetPos;
                        if (itSmallVar->pos < bpLeft)
                            varInfos.back().pos -= (svRecord.targetPos - svRecord.pos);
                        else if (itSmallVar->pos >= bpRight)
                            varInfos.back().pos += (svRecord.targetPos - svRecord.pos);
                    }

                    // Copy out breakpoints.
                    breakpoints.push_back(std::make_pair(currentPos, variants.posToIdx(Variants::SV, i)));
                    breakpoints.push_back(std::make_pair(currentPos + svRecord.targetPos - svRecord.pos - svRecord.size, variants.posToIdx(Variants::SV, i)));
                    breakpoints.push_back(std::make_pair((int)length(seq), variants.posToIdx(Variants::SV, i)));

                    currentPos = length(seq);
                }
                break;
            case StructuralVariantRecord::DUPLICATION:
                {
                    append(seq, infix(contig, svRecord.pos, svRecord.pos + svRecord.size));
                    SEQAN_ASSERT_GEQ(svRecord.targetPos, svRecord.pos + svRecord.size);
                    if (methSimOptions && methSimOptions->simulateMethylationLevels)  // first copy
                    {
                        appendValue(varPoints, std::make_pair((int)length(seq), false));
                        append(levelsLargeVariants->forward, infix(levels->forward, svRecord.pos, svRecord.pos + svRecord.size));
                        append(levelsLargeVariants->reverse, infix(levels->reverse, svRecord.pos, svRecord.pos + svRecord.size));
                    }
                    if (currentPos != length(seq))
                        appendValue(intervals, GenomicInterval(currentPos, length(seq), svRecord.pos, svRecord.pos + svRecord.size,
                                                               '+', GenomicInterval::DUPLICATED));
                    unsigned tmpCurrentPos = length(seq);
                    append(seq, infix(contig, svRecord.pos + svRecord.size, svRecord.targetPos));
                    if (methSimOptions && methSimOptions->simulateMethylationLevels)
                    {
                        appendValue(varPoints, std::make_pair((int)length(seq), false));
                        append(levelsLargeVariants->forward, infix(levels->forward, svRecord.pos + svRecord.size, svRecord.targetPos));
                        append(levelsLargeVariants->reverse, infix(levels->reverse, svRecord.pos + svRecord.size, svRecord.targetPos));
                    }
                    if (tmpCurrentPos != length(seq))
                        appendValue(intervals, GenomicInterval(tmpCurrentPos, length(seq), svRecord.pos + svRecord.size, svRecord.targetPos,
                                                               '+', GenomicInterval::NORMAL));
                    tmpCurrentPos = length(seq);
                    append(seq, infix(contig, svRecord.pos, svRecord.pos + svRecord.size));
                    if (methSimOptions && methSimOptions->simulateMethylationLevels)  // second copy
                    {
                        appendValue(varPoints, std::make_pair((int)length(seq), false));
                        append(levelsLargeVariants->forward, infix(levels->forward, svRecord.pos, svRecord.pos + svRecord.size));
                        append(levelsLargeVariants->reverse, infix(levels->reverse, svRecord.pos, svRecord.pos + svRecord.size));
                    }
                    if (tmpCurrentPos != length(seq))
                        appendValue(intervals, GenomicInterval(tmpCurrentPos, length(seq), svRecord.pos, svRecord.pos + svRecord.size,
                                                               '+', GenomicInterval::NORMAL));
                    if (verbosity >= 3)
                        std::cerr << "append(seq, infix(contig, " << svRecord.pos << ", " << svRecord.pos + svRecord.size << ") " << __LINE__ << " (duplication)\n"
                                  << "append(seq, infix(contig, " << svRecord.pos + svRecord.size << ", " << svRecord.targetPos << ") " << __LINE__ << "\n"
                                  << "append(seq, infix(contig, " << svRecord.pos << ", " << svRecord.pos + svRecord.size << ") " << __LINE__ << "\n";
                    lastPos = svRecord.targetPos;
                    SEQAN_ASSERT_LT(lastPos, (int)length(contig));

                    // Write out small variant infos for duplication.
                    for (; itSmallVar != smallVarInfos.end() && itSmallVar->pos < svRecord.pos + svRecord.size; ++itSmallVar)
                    {
                        int offset = (int)currentPos - lastPos;
                        varInfos.push_back(*itSmallVar);
                        varInfos.back().pos += offset;

                        if (itSmallVar->pos < svRecord.pos + svRecord.size)
                        {
                            varInfos.push_back(*itSmallVar);
                            varInfos.back().pos += (svRecord.targetPos - svRecord.pos);
                        }
                    }

                    // Copy out breakpoints.
                    breakpoints.push_back(std::make_pair(currentPos, variants.posToIdx(Variants::SV, i)));
                    breakpoints.push_back(std::make_pair(currentPos + svRecord.pos + svRecord.size - svRecord.pos, variants.posToIdx(Variants::SV, i)));
                    breakpoints.push_back(std::make_pair(currentPos + svRecord.pos + svRecord.size - svRecord.pos + svRecord.targetPos - (svRecord.pos + svRecord.size), variants.posToIdx(Variants::SV, i)));
                    breakpoints.push_back(std::make_pair((int)length(seq), variants.posToIdx(Variants::SV, i)));

                    currentPos = length(seq);
                }
                break;
            default:
                return 1;
        }
    }
    if (verbosity >= 3)
        std::cerr << "append(seq, infix(contig, " << lastPos << ", " << length(contig) << ") "
                  << __LINE__ << " (last interim)\n";
    append(seq, infix(contig, lastPos, length(contig)));
    if (methSimOptions && methSimOptions->simulateMethylationLevels)
    {
        append(levelsLargeVariants->forward, infix(levels->forward, lastPos, length(contig)));
        append(levelsLargeVariants->reverse, infix(levels->reverse, lastPos, length(contig)));

        SEQAN_ASSERT_EQ(length(seq), length(levelsLargeVariants->forward));
        SEQAN_ASSERT_EQ(length(seq), length(levelsLargeVariants->reverse));

        fixVariationLevels(*levelsLargeVariants, *rng, seq, varPoints, *methSimOptions);
    }
    if (currentPos != length(seq))
        appendValue(intervals, GenomicInterval(currentPos, length(seq), lastPos, length(contig),
                                               '+', GenomicInterval::NORMAL));

    // Copy out small variant infos for trailing characters.
    for (; itSmallVar != smallVarInfos.end(); ++itSmallVar)
    {
        int offset = (int)currentPos - lastPos;
        varInfos.push_back(*itSmallVar);
        varInfos.back().pos += offset;
    }

    // Build the interval trees of the positionMap.
    seqan::String<PositionMap::TInterval> svIntervals, svIntervalsSTL;
    for (unsigned i = 0; i < length(intervals); ++i)
        appendValue(svIntervals, PositionMap::TInterval(
                intervals[i].svBeginPos, intervals[i].svEndPos, intervals[i]));
    for (unsigned i = 0; i < length(intervals); ++i)
        if (intervals[i].smallVarBeginPos != -1)  // ignore insertions
            appendValue(svIntervalsSTL, PositionMap::TInterval(
                    intervals[i].smallVarBeginPos, intervals[i].smallVarEndPos, intervals[i]));
    createIntervalTree(positionMap.svIntervalTree, svIntervals);
    createIntervalTree(positionMap.svIntervalTreeSTL, svIntervalsSTL);

    return 0;
}