const Genome * Mutator::mutate(const Genome &genome) const { Genome *newGenome = new Genome(genome.getCountOfBases() + basesGained,genome.getCountOfBases() + basesGained); int nPieces = genome.getNumPieces(); const Genome::Piece *pieces = genome.getPieces(); for (int i = 0; i < nPieces; ++i) { const Genome::Piece &piece = pieces[i]; unsigned start = piece.beginningOffset; unsigned end = i + 1 < nPieces ? pieces[i + 1].beginningOffset : genome.getCountOfBases(); unsigned size = end - start; const Base *bases = genome.getSubstring(start, size); const char *name = piece.name; // printf("DEBUG: mutating %s of size %u, from %u to %u\n", name, size, start, end); newGenome->startPiece(name); getOrElse(chromMutators, string(name)).mutate(bases, bases + size, newGenome); } return newGenome; }
// // Makes a copy of a Genome, but with only one of the sex chromosomes. // // The fate of the mitochondrion is that of the X chromosome. // Genome * Genome::copy(bool copyX, bool copyY, bool copyM) const { Genome *newCopy = new Genome(getCountOfBases(),getCountOfBases()); if (NULL == newCopy) { fprintf(stderr,"Genome::copy: failed to allocate space for copy.\n"); return NULL; } const Genome::Piece *currentPiece = NULL; const Genome::Piece *nextPiece = getPieceAtLocation(0); unsigned offsetInReference = 0; while (offsetInReference < getCountOfBases()) { if (NULL != nextPiece && offsetInReference >= nextPiece->beginningOffset) { // // Start of a new piece. See if we want to skip it. // currentPiece = nextPiece; nextPiece = getNextPieceAfterLocation(offsetInReference + 1); if ((!copyX && !strcmp(currentPiece->name,"chrX")) || (!copyY && !strcmp(currentPiece->name,"chrY")) || (!copyM && !strcmp(currentPiece->name,"chrM"))) { // // Yes, skip over this piece. // nextPiece = getNextPieceAfterLocation(offsetInReference + 1); if (NULL == nextPiece) { // // The chromosome that we're skipping was the last one, so we're done. // break; } else { offsetInReference = nextPiece->beginningOffset; continue; } } // If skipping this chromosome newCopy->startPiece(currentPiece->name); } // If new piece beginning const size_t maxCopySize = 10000; char dataBuffer[maxCopySize + 1]; unsigned amountToCopy = maxCopySize; if (nextPiece && nextPiece->beginningOffset < offsetInReference + amountToCopy) { amountToCopy = nextPiece->beginningOffset - offsetInReference; } if (getCountOfBases() < offsetInReference + amountToCopy) { amountToCopy = getCountOfBases() - offsetInReference; } memcpy(dataBuffer,getSubstring(offsetInReference,amountToCopy), amountToCopy); dataBuffer[amountToCopy] = '\0'; newCopy->addData(dataBuffer); offsetInReference += amountToCopy; } return newCopy; }