/** * @param protein - mutation will be created from this protein * @param out - protein with low fitness. if mutation process is successful out will become the * result of the mutation, else out will be reset. * @param max_tries - max tries for creating a mutation. */ public void mutate(Protein protein, Protein out, int max_tries, int monomerIndex) { if (protein.size() < 10) throw new RuntimeException( "A protein of length " + protein.size() + " Shorter than the predefined mutations"); if (protein.getConformation().size() == 0) throw new RuntimeException("protein.conformation.size() == 0"); int nTries = 0; boolean success = false; int mutationLength; int mutationStartMonomer; int mutationLastMonomer; Vector3f representativeVector = new Vector3f(); Vector3f start, end; ArrayList<MutationLibraryEntry> list; if (originalConformationIn == null) // first time here originalConformationIn = new Conformation(protein.getConformation().size()); if (originalConformationOut == null) // first time here originalConformationOut = new Conformation(protein.getConformation().size()); int selectedMutationIndex; originalConformationIn.copy(protein.getConformation()); originalConformationOut.copy(out.getConformation()); if (originalConformationIn.size() == 0) throw new RuntimeException( "originalConformation.size() == 0 ; protein.size() = " + protein.size() + "; protein.conformation.size() = " + protein.getConformation().size()); MutationLibraryEntry entry; while (nTries < max_tries) { // upon success the method will return nTries++; out.reset(); if (monomerIndex > 0) { mutationLength = random.nextInt(Math.min(protein.size() - monomerIndex, mutationLibraries.length) - 2) + 2; } else { // Generate a number between [1..protein.size-2] mutationLength = random.nextInt(Math.min(protein.size() - 1, mutationLibraries.length) - 2) + 2; } // the start monomer may be between 1 and protein size- mutation // length if (monomerIndex > 0) mutationStartMonomer = monomerIndex; else mutationStartMonomer = random.nextInt(protein.size() - mutationLength - 1) + 1; mutationLastMonomer = mutationLength + mutationStartMonomer - 1; start = protein.get(mutationStartMonomer).getR(); // get position // vector of start monomer. end = protein.get(mutationLastMonomer).getR(); // get position // vector of end monomer. representativeVector.sub(end, start); // if start monomer and end monomer are on a straight line no // mutation is possible. if (representativeVector.length() + 1 == mutationLength) continue; mutationLibrary = mutationLibraries[mutationLength]; list = mutationLibrary.get(representativeVector); if (list == null) // list not found for given arguments throw new RuntimeException( "ERROR: \nstart vector:" + start + " \nend Vector" + end + "\nsub:" + representativeVector + "\n" + "Mutation length:" + mutationLength + "\n" + "Mutation Start Monomer:" + mutationStartMonomer + "\n" + "Mutation Last Monomer:" + mutationLastMonomer + "\n" + "Protein:" + protein.toString()); if (list.size() > 0) { /* Filter mutations - save only valid mutations */ // collect position of the protein before and after the // mutation. // save them not as absolut position but as offset from the star // of mutation, this // helps us compare them to the position needed by the mutation. proteinPositions.clear(); for (int i = 0; i < protein.size(); i++) { if ((i < mutationStartMonomer || i > mutationLastMonomer)) { // TODO: avoid creating a new vector. Vector3f vec = new Vector3f(protein.get(i).getR()); vec.sub(start); // Save position as an offset from start // of mutation. proteinPositions.add(vec); } } // Save in candidates only the mutations that do no overlap with // already occupied position of the protein. // (the position collected in the previous loop) candidates.clear(); for (MutationLibraryEntry lib : list) { boolean found = false; for (Vector3f vec : lib.positionOffsets) { if ((found = proteinPositions.contains(vec))) break; } if (!found) candidates.add(lib); } if (candidates.isEmpty()) // if no candidates try new mutation. continue; // Select random mutation from candidates. selectedMutationIndex = selectMutationNumber(candidates); entry = candidates.get(selectedMutationIndex); success = activateMutationOnProtein( out, protein, entry, mutationStartMonomer, mutationLastMonomer, originalConformationIn); } if (success) return; } out.reset(); out.setConformation(originalConformationOut); }
/** * change protein by the mutation * * @param protein the protein the changes should be saved to * @param originalProtein the protein before the change * @param entry the MutationLibraryEntry * @param mutationStartMonomer for where we should start the change * @param mutationEndMonomer where the change should end * @param originalConformation the original protein confirmation * @return true upon success */ private boolean activateMutationOnProtein( Protein protein, Protein originalProtein, MutationLibraryEntry entry, int mutationStartMonomer, int mutationEndMonomer, Conformation originalConformation) { if (originalConformation.size() == 0) throw new RuntimeException("originalConformation.size() == 0"); numOfIterations++; int size = protein.size(); // originalConformation=originalProtein.conformation; MonomerDirection[] mutationArray = entry.getMutation().getConfomation(); Conformation newConformation = new Conformation(size); int monomerNumber; int temp, i; if (mutationEndMonomer >= size) throw new RuntimeException("mutation too long"); if (originalConformation.size() <= mutationStartMonomer) throw new RuntimeException( "original conformation may be corupted original conformation size =" + originalConformation.size() + "\n mutationStartMonomer=" + mutationStartMonomer + "\n mutationEndMonomer=" + mutationEndMonomer + "\n protain.size()=" + size + "\n" + originalConformation); // conformation before mutation will be added normally. for (monomerNumber = 0; monomerNumber <= mutationStartMonomer; monomerNumber++) newConformation.add(originalConformation.get(monomerNumber)); // First monomer after start of mutation. // The conformation(direction) of this momomer is not necessarily as // written in mutation conformation, // therefore we will calculate its direction according to position of 3 // vectors. Vector3f mutationStartPos = originalProtein.get(mutationStartMonomer).getR(); v1.set(originalProtein.get(mutationStartMonomer - 1).getR()); v2.set(mutationStartPos); v3.set(mutationStartPos); v3.add(entry.positionOffsets.get(1)); newConformation.add(matrixMan.getDirection(v1, v2, v3)); // Conformation of mutation i = 1; for (monomerNumber = mutationStartMonomer + 2; monomerNumber <= mutationEndMonomer; monomerNumber++, i++) { newConformation.add(mutationArray[i]); } ; // First monomer after end of mutation. // The conformation(direction) of this momomer is not necessarily as // written in mutation conformation, // therefore we will calculate its direction according to position of 3 // vectors. v1.set(mutationStartPos); v1.add(entry.positionOffsets.get(entry.positionOffsets.size() - 2)); v2.set(originalProtein.get(mutationEndMonomer).getR()); v3.set(originalProtein.get(mutationEndMonomer + 1).getR()); newConformation.add(matrixMan.getDirection(v1, v2, v3)); // Comformatino after mutation for (monomerNumber = mutationEndMonomer + 2; monomerNumber < size; monomerNumber++) newConformation.add(originalConformation.get(monomerNumber)); temp = protein.setConformation(newConformation); if (temp < mutationStartMonomer) throw new RuntimeException( "This is weird. This structure was already tested in the past, how come it failes now?"); if (temp < size) { numOfFailers++; return false; } return true; }