Revision: 20258 http://sourceforge.net/p/jmol/code/20258 Author: hansonr Date: 2015-01-30 14:43:12 +0000 (Fri, 30 Jan 2015) Log Message: ----------- Jmol.___JmolVersion="14.3.12_2015.01.30"
new feature: MUTATE command -- operates only on last model present if multiple models are loaded -- replaces one or more amino acids group with others -- can read from RCSB or from user-specified file -- examples: mutate 33 lys // replace resno=33 with lysine mutate @3 arg // replaces group of atom 3 with arginine mutate @r gly // replaces groups in variable r with glycine mutate 22 "myfile.cif" // user-defined replacement mutate {1-3} ala // replace first three residues with alanine mutate {1-5} GLVAG // (sequence codes) replace residues 1-5 with gly-leu-val-ala-gly mutate {1-3} ~LYS // (force 1-character sequence codes) replace 1-3 with leu-tyr-ser mutate {1-3} A?L // replace 1 with ala, 3 with leu; skip 2 mutate {within(sequence, "GAT")} GYT // replace locations of GAT with GYT (needs testing) mutate 35 @fname // replaces resno=33 with file data (use "==XXX" for RCSB) mutate {r} his // same as above; r must be an atom selection bug fix: code fixes relating to calculate structure in 01.29 Modified Paths: -------------- trunk/Jmol/src/org/jmol/adapter/readers/more/Mol2Reader.java trunk/Jmol/src/org/jmol/api/JmolBioResolver.java trunk/Jmol/src/org/jmol/modelset/Model.java trunk/Jmol/src/org/jmol/modelsetbio/BioModel.java trunk/Jmol/src/org/jmol/modelsetbio/BioPolymer.java trunk/Jmol/src/org/jmol/modelsetbio/Resolver.java trunk/Jmol/src/org/jmol/scriptext/CmdExt.java trunk/Jmol/src/org/jmol/scriptext/MathExt.java trunk/Jmol/src/org/jmol/viewer/Jmol.properties Modified: trunk/Jmol/src/org/jmol/adapter/readers/more/Mol2Reader.java =================================================================== --- trunk/Jmol/src/org/jmol/adapter/readers/more/Mol2Reader.java 2015-01-30 03:05:59 UTC (rev 20257) +++ trunk/Jmol/src/org/jmol/adapter/readers/more/Mol2Reader.java 2015-01-30 14:43:12 UTC (rev 20258) @@ -229,7 +229,7 @@ int pt = getPDBGroupLength(atoms[i].group3); if (pt == 0 || pt > 3) break; - if (vwr.getJBR().isKnownPDBGroup(g3.substring(0, pt))) { + if (vwr.getJBR().isKnownPDBGroup(g3.substring(0, pt), Integer.MAX_VALUE)) { isPDB = this.isPDB = true; break; } Modified: trunk/Jmol/src/org/jmol/api/JmolBioResolver.java =================================================================== --- trunk/Jmol/src/org/jmol/api/JmolBioResolver.java 2015-01-30 03:05:59 UTC (rev 20257) +++ trunk/Jmol/src/org/jmol/api/JmolBioResolver.java 2015-01-30 14:43:12 UTC (rev 20258) @@ -41,7 +41,7 @@ public void setGroupLists(int ipt); - public boolean isKnownPDBGroup(String g3); + public boolean isKnownPDBGroup(String g3, int maxID); public boolean isHetero(String g3); @@ -56,7 +56,9 @@ public short getGroupID(String g3); - public boolean mutate(int iatom, String fileName); + public boolean mutate(BS bs, String fileName, String[] sequence); + + public String toStdAmino3(String sValue); } Modified: trunk/Jmol/src/org/jmol/modelset/Model.java =================================================================== --- trunk/Jmol/src/org/jmol/modelset/Model.java 2015-01-30 03:05:59 UTC (rev 20257) +++ trunk/Jmol/src/org/jmol/modelset/Model.java 2015-01-30 14:43:12 UTC (rev 20258) @@ -251,6 +251,12 @@ } protected void freezeM() { + for (int i = 0; i < chainCount; i++) + if (chains[i].groupCount == 0) { + for (int j = i + 1; j < chainCount; j++) + chains[j - 1] = chains[j]; + chainCount--; + } chains = (Chain[]) AU.arrayCopyObject(chains, chainCount); groupCount = -1; getGroupCount(); Modified: trunk/Jmol/src/org/jmol/modelsetbio/BioModel.java =================================================================== --- trunk/Jmol/src/org/jmol/modelsetbio/BioModel.java 2015-01-30 03:05:59 UTC (rev 20257) +++ trunk/Jmol/src/org/jmol/modelsetbio/BioModel.java 2015-01-30 14:43:12 UTC (rev 20258) @@ -81,6 +81,7 @@ private int bioPolymerCount = 0; public BioPolymer[] bioPolymers; + boolean isMutated; private String defaultStructure; private Viewer vwr; @@ -298,6 +299,10 @@ @Override public void calculateAllPolymers(Group[] groups, int groupCount, int baseGroupIndex, BS modelsExcluded) { + boolean checkConnections = !vwr.getBoolean(T.pdbsequential); + if (groupCount < 0) + groupCount = groups.length; + if (modelsExcluded != null) for (int j = 0; j < groupCount; ++j) { Group group = groups[j]; @@ -309,8 +314,22 @@ } for (int i = 0, mc = ms.mc; i < mc; i++) if ((modelsExcluded == null || !modelsExcluded.get(i)) - && ms.am[i].isBioModel) - calculateAllPolymers2(groups, groupCount, baseGroupIndex); + && ms.am[i].isBioModel) { + for (int j = baseGroupIndex; j < groupCount; ++j) { + Group g = groups[j]; + Model model = g.getModel(); + if (!model.isBioModel || !(g instanceof Monomer)) + continue; + boolean doCheck = checkConnections + && !ms.isJmolDataFrameForModel(ms.at[g.firstAtomIndex].mi); + BioPolymer bp = (((Monomer) g).bioPolymer == null ? Resolver + .allocateBioPolymer(groups, j, doCheck) : null); + if (bp == null || bp.monomerCount == 0) + continue; + ((BioModel) model).addBioPolymer(bp); + j += bp.monomerCount - 1; + } + } } @Override @@ -318,30 +337,9 @@ for (int i = 0; i < ms.mc; i++) if (ms.am[i].isBioModel && !bsModelsExcluded.get(i)) ((BioModel) ms.am[i]).clearBioPolymers(); - calculateAllPolymers2(groups, -1, 0); + calculateAllPolymers(groups, -1, 0, bsModelsExcluded); } - private void calculateAllPolymers2(Group[] groups, - int groupCount, int baseGroupIndex) { - boolean checkConnections = !vwr.getBoolean(T.pdbsequential); - if (groupCount < 0) - groupCount = groups.length; - for (int j = baseGroupIndex; j < groupCount; ++j) { - Group g = groups[j]; - Model model = g.getModel(); - if (!model.isBioModel || !(g instanceof Monomer)) - continue; - boolean doCheck = checkConnections - && !ms.isJmolDataFrameForModel(ms.at[g.firstAtomIndex].mi); - BioPolymer bp = (((Monomer) g).bioPolymer == null ? Resolver - .allocateBioPolymer(groups, j, doCheck) : null); - if (bp == null || bp.monomerCount == 0) - continue; - ((BioModel) model).addBioPolymer(bp); - j += bp.monomerCount - 1; - } - } - @Override public BS getGroupsWithinAll(int nResidues, BS bs) { BS bsResult = new BS(); @@ -976,7 +974,7 @@ // all biopolymer atoms... if (bs != bsAtoms) for (int i = 0; i < bioPolymerCount; i++) - bioPolymers[i].getRange(bs); + bioPolymers[i].getRange(bs, isMutated); if (bs.nextSetBit(0) < 0) return; // ...and not connected to backbone: @@ -986,7 +984,7 @@ } else { for (int i = 0; i < bioPolymerCount; i++) if (bioPolymers[i].getType() == BioPolymer.TYPE_NOBONDING) - bioPolymers[i].getRange(bs2); + bioPolymers[i].getRange(bs2, isMutated); } if (bs2.nextSetBit(0) >= 0) sb.append("select ").append(Escape.eBS(bs2)).append(";backbone only;"); @@ -1017,7 +1015,7 @@ BS bsBranch; for (int j = 0; j < bioPolymerCount; j++) { bsBranch = new BS(); - bioPolymers[j].getRange(bsBranch); + bioPolymers[j].getRange(bsBranch, isMutated); int iAtom = bsBranch.nextSetBit(0); if (iAtom >= 0) { if (biobranches == null) Modified: trunk/Jmol/src/org/jmol/modelsetbio/BioPolymer.java =================================================================== --- trunk/Jmol/src/org/jmol/modelsetbio/BioPolymer.java 2015-01-30 03:05:59 UTC (rev 20257) +++ trunk/Jmol/src/org/jmol/modelsetbio/BioPolymer.java 2015-01-30 14:43:12 UTC (rev 20258) @@ -103,13 +103,18 @@ monomers[i].setBioPolymer(this, i); model = monomers[0].getModel(); } - - public void getRange(BS bs) { + + public void getRange(BS bs, boolean isMutated) { // this is OK -- doesn't relate to added hydrogens if (monomerCount == 0) return; - bs.setBits(monomers[0].firstAtomIndex, - monomers[monomerCount - 1].lastAtomIndex + 1); + if (isMutated) { + for (int i = monomerCount; --i >= 0;) + monomers[i].setAtomBits(bs); + } else { + bs.setBits(monomers[0].firstAtomIndex, + monomers[monomerCount - 1].lastAtomIndex + 1); + } } public void clearStructures() { Modified: trunk/Jmol/src/org/jmol/modelsetbio/Resolver.java =================================================================== --- trunk/Jmol/src/org/jmol/modelsetbio/Resolver.java 2015-01-30 03:05:59 UTC (rev 20257) +++ trunk/Jmol/src/org/jmol/modelsetbio/Resolver.java 2015-01-30 14:43:12 UTC (rev 20258) @@ -871,11 +871,15 @@ } } + /** + * @param g3 + * @param max max ID (e.g. 20); can be Integer.MAX_VALUE to allow carbohydrate + * @return true if found + */ @Override - public boolean isKnownPDBGroup(String g3) { - // mol2 reader only - return knownGroupID(g3) >= 0 - || checkCarbohydrate(g3); + public boolean isKnownPDBGroup(String g3, int max) { + int pt = knownGroupID(g3); + return (pt > 0 ? pt < max : max == Integer.MAX_VALUE && checkCarbohydrate(g3)); } @Override @@ -1149,6 +1153,7 @@ int pt = Group.standardGroupList.indexOf(group3); return (pt < 0 || pt / 6 + 1 >= JC.GROUPID_WATER); } + public static short group3NameCount; private final static String[] predefinedGroup3Names = { // taken from PDB spec @@ -1215,8 +1220,35 @@ "SO4", // 47 sulphate ions "UNL", // 48 unknown ligand + }; - }; + /* + * Convert "AVG" to "ALA VAL GLY"; unknowns to UNK + * + */ + @Override + public String toStdAmino3(String g1) { + if (g1.length() == 0) + return ""; + SB s = new SB(); + int pt = knownGroupID("==A"); + if (pt < 0) { + // just the amino acids + for (int i = 1; i <= 20; i++) { + pt = knownGroupID(predefinedGroup3Names[i]); + htGroup.put("==" + predefinedGroup1Names[i], Short.valueOf((short) pt)); + } + } + for (int i = 0, n = g1.length(); i < n; i++) { + char ch = g1.charAt(i); + pt = knownGroupID("==" + ch); + if (pt < 0) + pt = 23; + s.append(" ").append(predefinedGroup3Names[pt]); + } + return s.toString().substring(1); + } + private static int getStandardPdbHydrogenCount(String group3) { int pt = knownGroupID(group3); return (pt < 0 || pt >= pdbHydrogenCount.length ? -1 : pdbHydrogenCount[pt]); @@ -1737,9 +1769,36 @@ } @Override - public boolean mutate(int iatom, String fileName) { + public boolean mutate(BS bs, String group, String[] sequence) { + + int i0 = bs.nextSetBit(0); + if (sequence == null) + return mutateAtom(i0, group); + boolean isFile = (group == null); + if (isFile) + group = sequence[0]; + Group lastGroup = null; + boolean isOK = true; + for (int i = i0, pt = 0; i >= 0; i = bs.nextSetBit(i + 1)) { + Group g = vwr.ms.at[i].group; + if (g == lastGroup) + continue; + lastGroup = g; + if (!isFile) { + group = sequence[pt++ % sequence.length]; + if (group.equals("UNK")) + continue; + group = "==" + group; + } + mutateAtom(i, group); + } + return isOK; + } + + private boolean mutateAtom(int iatom, String fileName) { // no mutating a trajectory. What would that mean??? - if (vwr.ms.isTrajectory(vwr.ms.at[iatom].mi)) + int iModel = vwr.ms.at[iatom].mi; + if (vwr.ms.isTrajectory(iModel)) return false; String[] info = vwr.fm.getFileInfo(); @@ -1749,6 +1808,7 @@ // get the initial group -- protein for now if (!(g instanceof AminoMonomer)) return false; + ((BioModel) vwr.ms.am[iModel]).isMutated = true; AminoMonomer res0 = (AminoMonomer) g; int ac = vwr.ms.ac; BS bsRes0 = new BS(); @@ -1757,34 +1817,41 @@ // just use a script -- it is much easier! - String script = "try{var atoms0 = {*}\n" - + "var res0 = " + BS.escape(bsRes0,'(',')') + "\n" - + "set appendNew false\n" - + "load append \""+fileName+"\"\n" - + "set appendNew " + b + "\n" - + "var res1 = {!atoms0};var r1 = res1[1];var r0 = res1[0]\n" - + "if ({r1 & within(group, r0)}){" - + "var haveHs = ({_H and connected(res0)} != 0)\n" - + "if (!haveHs) {delete _H and res1}\n" - + "var sm = '[*.N][*.CA][*.C][*.O]'\n" - + "var keyatoms = res1.find(sm)\n" - + "var x = compare(res1,res0,sm,'BONDS')\n" - + "if(x){\n" - + "rotate branch @x 1\n" - + "compare res1 res0 SMARTS @sm rotate translate 0\n" - + "var N2 = {*.N and !res0 && connected(res0)}\n" - + "var C0 = {*.C and !res0 && connected(res0)}\n" - + "delete res0\n" - + "if (N2) {\n" - + "delete *.OXT and res1\n" - + "connect {N2} {res1 & *.C}\n" - + "}\n" - + "if (C0) {\n" - + "connect {C0} {res1 & *.N}\n" - + "}\n" - + "}\n" - + "}}catch(e){print e}\n"; + fileName = PT.esc(fileName); + String script = "" + + "try{\n" + + " var atoms0 = {*}\n" + + " var res0 = " + BS.escape(bsRes0,'(',')') + "\n" + + " set appendNew false\n" + + " load append "+fileName+"\n" + + " set appendNew " + b + "\n" + + " var res1 = {!atoms0};var r1 = res1[1];var r0 = res1[0]\n" + + " if ({r1 & within(group, r0)}){" + + " var haveHs = ({_H and connected(res0)} != 0)\n" + + " if (!haveHs) {delete _H and res1}\n" + + " var sm = '[*.N][*.CA][*.C][*.O]'\n" + + " var keyatoms = res1.find(sm)\n" + + " var x = compare(res1,res0,sm,'BONDS')\n" + + " if(x){\n" + + " print 'mutating ' + res0[1].label('%n%r') + ' to ' + "+fileName+".trim('=')\n" + + " rotate branch @x\n" + + " compare res1 res0 SMARTS @sm rotate translate 0\n" + + " var N2 = {*.N and !res0 && connected(res0)}\n" + + " var C0 = {*.C and !res0 && connected(res0)}\n" + + " delete res0\n" + + " if (N2) {\n" + + " delete *.OXT and res1\n" + + " connect {N2} {res1 & *.C}\n" + + " }\n" + + " if (C0) {\n" + + " connect {C0} {res1 & *.N}\n" + + " }\n" + + " }\n" + + " }\n" + + "}catch(e){print e}\n"; try { + if (Logger.debugging) + Logger.debug(script); vwr.eval.runScript(script); } catch (ScriptException e) { // TODO @@ -1815,6 +1882,7 @@ BS bsExclude = BSUtil.newBitSet2(0, vwr.ms.mc); bsExclude.clear(res1.chain.model.modelIndex); res1.chain.model.groupCount = -1; + res1.chain.model.freeze(); vwr.ms.recalculatePolymers(bsExclude); //} catch (Exception e) { // System.out.println("" + e); Modified: trunk/Jmol/src/org/jmol/scriptext/CmdExt.java =================================================================== --- trunk/Jmol/src/org/jmol/scriptext/CmdExt.java 2015-01-30 03:05:59 UTC (rev 20257) +++ trunk/Jmol/src/org/jmol/scriptext/CmdExt.java 2015-01-30 14:43:12 UTC (rev 20258) @@ -2188,20 +2188,49 @@ private void mutate() throws ScriptException { // mutate {resno} "LYS" or "file identifier" - if (tokAt(1) == T.integer) - st[1] =T.o(T.string, "" + st[1].value); // allows @x - int iatom = atomExpressionAt(1).length() - 1; - + // mutate {1-3} ~GGGL + BS bs; + int i; + switch (tokAt(1)) { + case T.integer: + st[1] = T.o(T.string, "" + st[1].value); // allows @x and "*" + //$FALL-THROUGH$ + default: + bs = atomExpressionAt(1); + i = ++e.iToken; + break; + case T.times: + bs = vwr.getAllAtoms(); + i = 2; + break; + } + // check for last model - if (iatom < 0 || vwr.ms.mc != vwr.ms.at[iatom].mi + 1) + bs.and(vwr.getModelUndeletedAtomsBitSet(vwr.ms.mc - 1)); + int iatom = bs.length() - 1; + if (iatom < 0 || vwr.ms.at[iatom].mi + 1 != vwr.ms.mc + || vwr.ms.isTrajectory(vwr.ms.at[iatom].mi)) return; - int i = ++e.iToken; - String group = e.optParameterAsString(e.checkLast(i)); + String group = e.optParameterAsString(i); + e.checkLast(i); if (chk) return; - if (tokAt(i) != T.string) - group = "==" + group; - vwr.getJBR().mutate(iatom, group); + boolean isFile = (tokAt(i) == T.string); + String[] list = null; + if (isFile) { + list = new String[] { group }; + group = null; + } else { + group = PT.replaceAllCharacters(group, ",; \t\n", " ").trim() + .toUpperCase(); + if (group.startsWith("~") || group.length() != 3 + || !vwr.getJBR().isKnownPDBGroup(group, 20)) + group = vwr.getJBR().toStdAmino3(group); + } + list = PT.getTokens(group); + if (list.length == 0) + return; + vwr.getJBR().mutate(bs, group, list); } private void navigate() throws ScriptException { Modified: trunk/Jmol/src/org/jmol/scriptext/MathExt.java =================================================================== --- trunk/Jmol/src/org/jmol/scriptext/MathExt.java 2015-01-30 03:05:59 UTC (rev 20257) +++ trunk/Jmol/src/org/jmol/scriptext/MathExt.java 2015-01-30 14:43:12 UTC (rev 20258) @@ -884,7 +884,8 @@ // {*}.find("CF",true|false) // {*}.find("MF") // {*}.find("MF", "C2H4") - // {*}.find("SEQENCE") + // {*}.find("SEQUENCE") + // "AVA".find("SEQUENCE") // {*}.find("SMARTS", "CCCC") // "CCCC".find("SMARTS", "CC") // "CCCC".find("SMILES", "MF") @@ -1016,6 +1017,9 @@ } return mp.addXAS(listNew); } + if (isSequence) { + return mp.addXStr(vwr.getJBR().toStdAmino3(SV.sValue(x1))); + } return mp.addXInt(SV.sValue(x1).indexOf(sFind) + 1); } Modified: trunk/Jmol/src/org/jmol/viewer/Jmol.properties =================================================================== --- trunk/Jmol/src/org/jmol/viewer/Jmol.properties 2015-01-30 03:05:59 UTC (rev 20257) +++ trunk/Jmol/src/org/jmol/viewer/Jmol.properties 2015-01-30 14:43:12 UTC (rev 20258) @@ -15,6 +15,28 @@ TODO: remove HTML5 dependency on synchronous file loading (check SCRIPT command for problems) TODO: add 2D graphics panel for Ramachandran and NBO-style 2D graphics -- send to browser as data uri? +Jmol.___JmolVersion="14.3.12_2015.01.30" + +new feature: MUTATE command + -- operates only on last model present if multiple models are loaded + -- replaces one or more amino acids group with others + -- can read from RCSB or from user-specified file + -- examples: + mutate 33 lys // replace resno=33 with lysine + mutate @3 arg // replaces group of atom 3 with arginine + mutate @r gly // replaces groups in variable r with glycine + mutate 22 "myfile.cif" // user-defined replacement + mutate {1-3} ala // replace first three residues with alanine + mutate {1-5} GLVAG // (sequence codes) replace residues 1-5 with gly-leu-val-ala-gly + mutate {1-3} ~LYS // (force 1-character sequence codes) replace 1-3 with leu-tyr-ser + mutate {1-3} A?L // replace 1 with ala, 3 with leu; skip 2 + mutate {within(sequence, "GAT")} GYT // replace locations of GAT with GYT (needs testing) + mutate 35 @fname // replaces resno=33 with file data (use "==XXX" for RCSB) + mutate {r} his // same as above; r must be an atom selection + + +bug fix: code fixes relating to calculate structure in 01.29 + Jmol.___JmolVersion="14.3.12_2015.01.29" bug fix: 01.28 version does not write correct PDB CONECT records @@ -24,17 +46,6 @@ JmolVersion="14.3.12_2015.01.28" -new feature: MUTATE command - -- operates only on last model present if multiple models are loaded - -- replaces one amino acid group with another - -- can read from RCSB or from user-specified file - -- examples: - mutate 33 lys // uses last occurrence of resno=33 - mutate @@3 arg // replaces group of atom 3 in current model - mutate @r @fname // replaces resno in variable r with file data (use "==XXX" for RCSB) - mutate {r} his // same as above; r must be an atom selection - mutate 22 "myfile.cif" // user-defined replacement - bug fix: write "t.pdb" now correctly sequences groups and atoms, even after mutation new feature: resno is user settable This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------------ Dive into the World of Parallel Programming. The Go Parallel Website, sponsored by Intel and developed in partnership with Slashdot Media, is your hub for all things parallel software development, from weekly thought leadership blogs to news, videos, case studies, tutorials and more. Take a look and join the conversation now. http://goparallel.sourceforge.net/ _______________________________________________ Jmol-commits mailing list Jmol-commits@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jmol-commits