Revision: 21188 http://sourceforge.net/p/jmol/code/21188 Author: hansonr Date: 2016-08-09 16:50:24 +0000 (Tue, 09 Aug 2016) Log Message: ----------- MMTF tweak to read entityList and to implement decoding types 12-15
Modified Paths: -------------- trunk/Jmol/src/org/jmol/adapter/readers/cif/CifReader.java trunk/Jmol/src/org/jmol/adapter/readers/cif/MMCifReader.java trunk/Jmol/src/org/jmol/adapter/readers/cif/MMTFReader.java Modified: trunk/Jmol/src/org/jmol/adapter/readers/cif/CifReader.java =================================================================== --- trunk/Jmol/src/org/jmol/adapter/readers/cif/CifReader.java 2016-08-09 06:58:10 UTC (rev 21187) +++ trunk/Jmol/src/org/jmol/adapter/readers/cif/CifReader.java 2016-08-09 16:50:24 UTC (rev 21188) @@ -533,6 +533,7 @@ private String processChemicalInfo(String type) throws Exception { if (type.equals("name")) { chemicalName = data = parser.fullTrim(data); + appendLoadNote(chemicalName); if (!data.equals("?")) asc.setInfo("modelLoadNote", data); } else if (type.equals("structuralFormula")) { Modified: trunk/Jmol/src/org/jmol/adapter/readers/cif/MMCifReader.java =================================================================== --- trunk/Jmol/src/org/jmol/adapter/readers/cif/MMCifReader.java 2016-08-09 06:58:10 UTC (rev 21187) +++ trunk/Jmol/src/org/jmol/adapter/readers/cif/MMCifReader.java 2016-08-09 16:50:24 UTC (rev 21188) @@ -666,7 +666,7 @@ while (parser.getData()) if (!isNull(groupName = getField(CHEM_COMP_ID)) && !isNull(hetName = getField(CHEM_COMP_NAME))) - addHetero(groupName, hetName, true); + addHetero(groupName, hetName, true, true); return true; } @@ -700,12 +700,12 @@ // return true; // } - protected void addHetero(String groupName, String hetName, boolean addNote) { - if (!vwr.getJBR().isHetero(groupName)) + protected void addHetero(String groupName, String hetName, boolean doCheck, boolean addNote) { + if (doCheck && !vwr.getJBR().isHetero(groupName)) return; if (htHetero == null) htHetero = new Hashtable<String, String>(); - if (htHetero.containsKey(groupName)) + if (doCheck && htHetero.containsKey(groupName)) return; htHetero.put(groupName, hetName); if (addNote) Modified: trunk/Jmol/src/org/jmol/adapter/readers/cif/MMTFReader.java =================================================================== --- trunk/Jmol/src/org/jmol/adapter/readers/cif/MMTFReader.java 2016-08-09 06:58:10 UTC (rev 21187) +++ trunk/Jmol/src/org/jmol/adapter/readers/cif/MMTFReader.java 2016-08-09 16:50:24 UTC (rev 21188) @@ -45,27 +45,35 @@ * * see https://github.com/rcsb/mmtf/blob/master/spec.md * - * /full/ specification as of 2016.4.18 is implemented,including: + * full specification Version: v0.2+dev (as of 2016.08.08) is + * implemented,including: * - * reading atoms, bonds, and DSSR secondary structure + * reading atoms, bonds, and DSSP 1.0 secondary structure * - * load =1f88.mmtf - * + * load =1f88.mmtf filter "DSSP1" * + * [Note that the filter "DSSP1" is required, since mmtf included DSSP 1.0 + * calculations, while the standard for Jmol itself is DSSP 2.0. These two + * calculations differ in their treating of helix kinks as one (1.0) or two + * (2.0) helices.] + * + * * reading space groups and unit cells, and using those as per other readers * - * load =1crn.mmtf {1 1 1} + * load =1crn.mmtf {1 1 1} * - * reading bioassemblies (biomolecules) and applying those transformations + * reading bioassemblies (biomolecules) and applying all symmetry + * transformations * - * load =1auy.mmtf FILTER "biomolecule 1;*.CA,*.P" + * load =1auy.mmtf FILTER "biomolecule 1;*.CA,*.P" * - * reading biomolecules and lattices, and loading course-grained + * reading both biomolecules and lattices, and loading course-grained using the + * filter "BYCHAIN" or "BYSYMOP" * - * load =1auy.mmtf {2 2 1} filter "biomolecule 1;bychain";spacefill 30.0; color property symop + * load =1auy.mmtf {2 2 1} filter "biomolecule 1;bychain";spacefill 30.0; color + * property symop * - * Note that the filter "DSSP1" indicates that mmtf included DSSP 1.0 calculation should be used. - * Otherwise Jmol will use DSSP 2.0 itself. + * Many thanks to the MMTF team at RCSB for assistance in this implementation. * */ @@ -78,12 +86,14 @@ /** * standard set up + * * @param fullPath * @param htParams * @param reader */ @Override - protected void setup(String fullPath, Map<String, Object> htParams, Object reader) { + protected void setup(String fullPath, Map<String, Object> htParams, + Object reader) { isBinary = true; isMMCIF = true; iHaveFractionalCoordinates = false; @@ -92,38 +102,318 @@ @Override protected void processBinaryDocument() throws Exception { + + // load xxx.mmtf filter "..." options + + // NODOUBLE -- standard PDB-like structures + // DSSP2 -- use Jmol's built-in DSSP 2.0, not file's DSSP 1.0 + boolean doDoubleBonds = (!isCourseGrained && !checkFilterKey("NODOUBLE")); - isDSSP1 = checkFilterKey("DSSP1"); + isDSSP1 = !checkFilterKey("DSSP2"); boolean mmtfImplementsDSSP2 = false; // so far! applySymmetryToBonds = true; map = (new MessagePackReader(binaryDoc, true)).readMap(); + entities = (Object[]) map.get("entityList"); if (Logger.debugging) { - for (String s: map.keySet()) + for (String s : map.keySet()) Logger.info(s); } asc.setInfo("noAutoBond", Boolean.TRUE); Logger.info("MMTF version " + map.get("mmtfVersion")); Logger.info("MMTF Producer " + map.get("mmtfProducer")); - appendLoadNote((String) map.get("title")); + String title = (String) map.get("title"); + if (title != null) + appendLoadNote(title); String id = (String) map.get("structureId"); - fileAtomCount = ((Integer)map.get("numAtoms")).intValue(); - int nBonds = ((Integer)map.get("numBonds")).intValue(); + if (id == null) + id = "?"; + fileAtomCount = ((Integer) map.get("numAtoms")).intValue(); + int nBonds = ((Integer) map.get("numBonds")).intValue(); Logger.info("id atoms bonds " + id + " " + fileAtomCount + " " + nBonds); - getAtoms(doDoubleBonds); + getMMTFAtoms(doDoubleBonds); if (!isCourseGrained) { - getBonds(doDoubleBonds); - if (isDSSP1 || mmtfImplementsDSSP2) + int[] bo = (int[]) decode("bondOrderList"); + int[] bi = (int[]) decode("bondAtomList"); + addMMTFBonds(bo, bi, 0, doDoubleBonds, true); + if (isDSSP1 || mmtfImplementsDSSP2) getStructure((int[]) decode("secStructList")); } - setSymmetry(); - getBioAssembly(); + setMMTFSymmetry(); + getMMTFBioAssembly(); setModelPDB(true); if (Logger.debuggingHigh) Logger.info(SV.getVariable(map).asString()); } -/////////////// MessagePack decoding /////////////// - + //////////////////////////////// MMTF-Specific ///////////////////////// + + private Map<String, Object> map; // input JSON-like map from MessagePack binary file + private int fileAtomCount; + private int opCount = 0; + private int[] groupModels; + private String[] labelAsymList; // created in getAtoms; used in getBioAssembly + private Atom[] atomMap; // necessary because some atoms may be deleted. + private Object[] entities; + + + // TODO - also consider mapping group indices + + /** + * set up all atoms, including bonding, within a group + * + * @param doMulti + * true to add double bonds + * + * @throws Exception + */ + @SuppressWarnings("unchecked") + private void getMMTFAtoms(boolean doMulti) throws Exception { + + // chains + int[] chainsPerModel = (int[]) map.get("chainsPerModel"); + int[] groupsPerChain = (int[]) map.get("groupsPerChain"); // note that this is label_asym, not auth_asym + labelAsymList = (String[]) decode("chainIdList"); // label_asym + String[] authAsymList = (String[]) decode("chainNameList"); // Auth_asym + + // groups + int[] groupTypeList = (int[]) decode("groupTypeList"); + int groupCount = groupTypeList.length; + groupModels = new int[groupCount]; + int[] groupIdList = (int[]) decode("groupIdList"); + Object[] groupList = (Object[]) map.get("groupList"); + char[] insCodes = (char[]) decode("insCodeList"); + + int[] atomId = (int[]) decode("atomIdList"); + boolean haveSerial = (atomId != null); + + char[] altloc = (char[]) decode("altLocList"); // rldecode32 + float[] occ = (float[]) decode("occupancyList"); + + float[] x = (float[]) decode("xCoordList");//getFloatsSplit("xCoord", 1000f); + float[] y = (float[]) decode("yCoordList"); + float[] z = (float[]) decode("zCoordList"); + float[] bf = (float[]) decode("bFactorList"); + int iatom = 0; + String[] nameList = (useAuthorChainID ? authAsymList : labelAsymList); + int iModel = -1; + int iChain = 0; + int nChain = 0; + int iGroup = 0; + int nGroup = 0; + int chainpt = 0; + int seqNo = 0; + String chainID = ""; + String authAsym = "", labelAsym = ""; + char insCode = '\0'; + atomMap = new Atom[fileAtomCount]; + for (int j = 0; j < groupCount; j++) { + int a0 = iatom; + if (insCodes != null) + insCode = insCodes[j]; + seqNo = groupIdList[j]; + if (++iGroup >= nGroup) { + chainID = nameList[chainpt]; + authAsym = authAsymList[chainpt]; + labelAsym = labelAsymList[chainpt]; + nGroup = groupsPerChain[chainpt++]; + iGroup = 0; + if (++iChain >= nChain) { + groupModels[j] = ++iModel; + nChain = chainsPerModel[iModel]; + iChain = 0; + setModelPDB(true); + incrementModel(iModel + 1); + nAtoms0 = asc.ac; + } + } + Map<String, Object> g = (Map<String, Object>) groupList[groupTypeList[j]]; + String group3 = (String) g.get("groupName"); + if (vwr.getJBR().isHetero(group3)) { + // looking for CHEM_COMP_NAME here... "IRON/SULFUR CLUSTER" for SF4 in 1blu + String hetName = "" + g.get("chemCompType"); + if (htHetero == null || !htHetero.containsKey(group3)) { + + // this is not ideal -- see 1a37.mmtf, where PSE is LSQRQRST(PSE)TPNVHM + // (actually that should be phosphoserine, SPE...) + // It is still listed as NON-POLYMER even though it is just a modified AA. + + if (entities != null && hetName.equals("NON-POLYMER")) + out: for (int i = entities.length; --i >= 0;) { + Map<String, Object> entity = (Map<String, Object>) entities[i]; + int[] chainList = (int[]) entity.get("chainIndexList"); + for (int k = chainList.length; --k >= 0;) + if (chainList[k] == iChain) { + hetName = "a component of the entity \"" + entity.get("description") + "\""; + break out; + } + } + addHetero(group3, hetName, false, true); + } + } + String[] atomNameList = (String[]) g.get("atomNameList"); + String[] elementList = (String[]) g.get("elementList"); + int len = atomNameList.length; + for (int ia = 0, pt = 0; ia < len; ia++, iatom++) { + Atom a = new Atom(); + if (insCode != 0) + a.insertionCode = insCode; + setAtomCoordXYZ(a, x[iatom], y[iatom], z[iatom]); + a.elementSymbol = elementList[pt]; + a.atomName = atomNameList[pt++]; + if (seqNo >= 0) + maxSerial = Math.max(maxSerial, a.sequenceNumber = seqNo); + a.group3 = group3; + setChainID(a, chainID); + if (bf != null) + a.bfactor = bf[iatom]; + if (altloc != null) + a.altLoc = altloc[iatom]; + if (occ != null) + a.foccupancy = occ[iatom]; + if (haveSerial) + a.atomSerial = atomId[iatom]; + if (!filterAtom(a, -1) || !processSubclassAtom(a, labelAsym, authAsym)) + continue; + if (haveSerial) { + asc.addAtomWithMappedSerialNumber(a); + } else { + asc.addAtom(a); + } + atomMap[iatom] = a; + ++ac; + } + if (!isCourseGrained) { + int[] bo = (int[]) g.get("bondOrderList"); + int[] bi = (int[]) g.get("bondAtomList"); + addMMTFBonds(bo, bi, a0, doMulti, false); + } + } + } + + private void addMMTFBonds(int[] bo, int[] bi, int a0, boolean doMulti, boolean isInter) { + if (bi == null) + return; + doMulti &= (bo != null); + for (int bj = 0, pt = 0, nj = bi.length / 2; bj < nj; bj++) { + Atom a1 = atomMap[bi[pt++] + a0]; + Atom a2 = atomMap[bi[pt++] + a0]; + if (a1 != null && a2 != null) { + Bond bond = new Bond(a1.index, a2.index, doMulti ? bo[bj] : 1); + asc.addBond(bond); + if (Logger.debugging && isInter) { + Logger.info("inter-group bond " + a1.group3 + a1.sequenceNumber + "." + a1.atomName + + " - " + a2.group3 + a2.sequenceNumber + "." + a2.atomName + " " + + bond.order); + } + } + } + } + + private void setMMTFSymmetry() { + setSpaceGroupName((String) map.get("spaceGroup")); + float[] o = (float[]) map.get("unitCell"); + if (o != null) + for (int i = 0; i < 6; i++) + setUnitCellItem(i, o[i]); + } + + @SuppressWarnings("unchecked") + private void getMMTFBioAssembly() { + Object[] o = (Object[]) map.get("bioAssemblyList"); + if (o == null) + return; + if (vBiomolecules == null) + vBiomolecules = new Lst<Map<String, Object>>(); + + for (int i = o.length; --i >= 0;) { + Map<String, Object> info = new Hashtable<String, Object>(); + vBiomolecules.addLast(info); + int iMolecule = i + 1; + checkFilterAssembly("" + iMolecule, info); + info.put("name", "biomolecule " + iMolecule); + info.put("molecule", Integer.valueOf(iMolecule)); + Lst<String> assemb = new Lst<String>(); + Lst<String> ops = new Lst<String>(); + info.put("biomts", new Lst<M4>()); + info.put("chains", new Lst<String>()); + info.put("assemblies", assemb); + info.put("operators", ops); + // need to add NCS here. + Map<String, Object> m = (Map<String, Object>) o[i]; + Object[] tlist = (Object[]) m.get("transformList"); + SB chlist = new SB(); + + for (int j = 0, n = tlist.length; j < n; j++) { + + Map<String, Object> t = (Map<String, Object>) tlist[j]; + + // for every transformation... + + chlist.setLength(0); + + // for compatibility with the mmCIF reader, we create + // string lists of the chains in the form $A$B$C... + + int[] chainList = (int[]) t.get("chainIndexList"); + for (int k = 0, kn = chainList.length; k < kn; k++) + chlist.append("$").append(labelAsymList[chainList[k]]); + assemb.addLast(chlist.append("$").toString()); + + // now save the 4x4 matrix transform for this operation + + String id = "" + (++opCount); + addMatrix(id, M4.newA16((float[]) t.get("matrix")), false); + ops.addLast(id); + } + } + } + + // Code Name + // 0* pi helix + // 1 bend (ignored) + // 2* alpha helix + // 3* extended (sheet) + // 4* 3-10 helix + // 5 bridge (ignored) + // 6* turn + // 7 coil (ignored) + // -1 undefined + + // 1F88: "secStructList": [7713371173311776617777666177444172222222222222222222222222222222166771222222222222222222262222222222617662222222222222222222222222222222222177111777722222222222222222221222261173333666633337717776666222222222226622222222222226611771777 + // DSSP (Jmol): ...EE....EE....TT.....TTT...GGG..HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH.TT...HHHHHHHHHHHHHHHHHHHTHHHHHHHHHHT..TTHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH..........HHHHHHHHHHHHHHHHHHH.HHHHT...EEEETTTTEEEE......TTTTHHHHHHHHHHHTTHHHHHHHHHHHHHTT........ + + /** + * Get and translate the DSSP string from digit format + * + * @param a + * input data + */ + private void getStructure(int[] a) { + BS[] bsStructures = new BS[] { new BS(), null, new BS(), new BS(), + new BS(), null, new BS() }; + if (Logger.debugging) + Logger.info(PT.toJSON("secStructList", a)); + int lastGroup = -1; + for (int i = 0; i < a.length; i++) { + int type = a[i]; + switch (type) { + case 0: // PI + case 2: // alpha + case 3: // sheet + case 4: // 3-10 + case 6: // turn + bsStructures[type].set(i); + lastGroup = i; + } + } + + int n = (isDSSP1 ? asc.iSet : groupModels[lastGroup]); + if (lastGroup >= 0) + asc.addStructure(new Structure(n, null, null, null, 0, 0, bsStructures)); + } + + /////////////// MessagePack decoding /////////////// + private Object decode(String key) { byte[] b = (byte[]) map.get(key); int type = BC.bytesToInt(b, 0, true); @@ -132,9 +422,9 @@ switch (type) { case 1: return getFloats(b, 4, 1); - case 2: - case 3: - case 4: + case 2: // 1-byte + case 3: // 2-byte + case 4: // 4-byte return getInts(b, 1 << (type - 2)); case 5: return rldecode32ToStr(b); @@ -145,12 +435,18 @@ case 8: return rldecode32Delta(b, n); case 9: - return rldecode32f(b, n, param); + return rldecodef(b, n, param); case 10: - return recursiveIndex16Deltaf(b, n, param); + return unpack16Deltaf(b, n, param); case 11: return getFloats(b, 2, param); - } + case 12: // two-byte + case 13: // one-byte + return unpackf(b, 14 - type, n, param); + case 14: // two-byte + case 15: // one-byte + return unpack(b, 16 - type, n); + } return null; } @@ -158,19 +454,19 @@ * mmtf type 1 and 11 * * byte[4] to float32 - * + * * @param b - * @param n - * @param divisor + * @param n + * @param divisor * @return float[] - */ + */ protected float[] getFloats(byte[] b, int n, float divisor) { if (b == null) return null; int len = (b.length - 12) / n; float[] a = new float[len]; try { - switch (n) { + switch (n) { case 2: for (int i = 0, j = 12; i < len; i++, j += 2) a[i] = BC.bytesToShort(b, j, false) / divisor; @@ -184,14 +480,15 @@ } return a; } - + /** * mmtf types 2-4 * * Decode a byte array into a byte, short, or int array. - * + * * @param b - * @param nbytes 1 (byte), 2 (int16), or 4 (int32) + * @param nbytes + * 1 (byte), 2 (int16), or 4 (int32) * @return int array */ protected int[] getInts(byte[] b, int nbytes) { @@ -215,14 +512,15 @@ } return a; } - + /** - * mmtf type 5 + * mmtf type 5 * - * Decode each four bytes as a 1- to 4-character string label - * where a 0 byte indicates end-of-string. - * - * @param b a byte array + * Decode each four bytes as a 1- to 4-character string label where a 0 byte + * indicates end-of-string. + * + * @param b + * a byte array * @return String[] */ protected String[] rldecode32ToStr(byte[] b) { @@ -241,16 +539,15 @@ id[i] = sb.toString(); continue; } - } - } + } + } return id; } /** - * mmtf type 6 + * mmtf type 6 * - * Decode an array of int32 using run-length decoding to one - * char per int. + * Decode an array of int32 using run-length decoding to one char per int. * * @param b * @param n @@ -260,16 +557,16 @@ if (b == null) return null; char[] ret = new char[n]; - for (int i = 0, pt = 2; i < n;) { - char val = (char) b[(++pt) << 2]; - for (int j = BC.bytesToInt(b, (++pt) << 2, true); --j >= 0;) - ret[i++] = val; + for (int i = 0, pt = 3; i < n;) { + char val = (char) b[(pt++) << 2]; + for (int j = BC.bytesToInt(b, (pt++) << 2, true); --j >= 0;) + ret[i++] = val; } return ret; } /** - * mmtf type 7 + * mmtf type 7 * * Decode an array of int32 using run-length decoding. * @@ -281,10 +578,10 @@ if (b == null) return null; int[] ret = new int[n]; - for (int i = 0, pt = 2; i < n;) { - int val = BC.bytesToInt(b, (++pt) << 2, true); - for (int j = BC.bytesToInt(b, (++pt) << 2, true); --j >= 0;) - ret[i++] = val; + for (int i = 0, pt = 3; i < n;) { + int val = BC.bytesToInt(b, (pt++) << 2, true); + for (int j = BC.bytesToInt(b, (pt++) << 2, true); --j >= 0;) + ret[i++] = val; } return ret; } @@ -292,8 +589,7 @@ /** * mmtf type 8 * - * Decode an array of int32 using run-length decoding - * of a difference array. + * Decode an array of int32 using run-length decoding of a difference array. * * @param b * @param n @@ -310,47 +606,47 @@ } return ret; } - + /** - * mmtf type 9 + * mmtf type 9 * * Decode an array of int32 using run-length decoding. * * @param b * @param n - * @param divisor + * @param divisor * @return array of floats */ - protected float[] rldecode32f(byte[] b, int n, float divisor) { + protected float[] rldecodef(byte[] b, int n, float divisor) { if (b == null) return null; float[] ret = new float[n]; - for (int i = 0, pt = 2; i < n;) { - int val = BC.bytesToInt(b, (++pt) << 2, true); - for (int j = BC.bytesToInt(b, (++pt) << 2, true); --j >= 0;) - ret[i++] = val / divisor; + for (int i = 0, pt = 3; i < n;) { + int val = BC.bytesToInt(b, (pt++) << 2, true); + for (int j = BC.bytesToInt(b, (pt++) << 2, true); --j >= 0;) + ret[i++] = val / divisor; } return ret; } /** * - * mmtf type 10 (first part) + * mmtf type 10 * * Decode an array of int16 using run-length decoding of a difference array. * * @param b * @param n - * @param divisor + * @param divisor * @return array of integers */ - protected float[] recursiveIndex16Deltaf(byte[] b, int n, float divisor) { + protected float[] unpack16Deltaf(byte[] b, int n, float divisor) { if (b == null) return null; float[] ret = new float[n]; for (int i = 0, pt = 6, val = 0, buf = 0; i < n;) { int diff = BC.bytesToShort(b, (pt++) << 1, true); - if (diff == 32767 || diff == -32768) { + if (diff == Short.MAX_VALUE || diff == Short.MIN_VALUE) { buf += diff; } else { ret[i++] = (val = val + diff + buf) / divisor; @@ -360,323 +656,154 @@ return ret; } -// /** -// * Decode an array of int16 using run-length decoding -// * of a difference array. -// * -// * @param b -// * @param n -// * @param i0 -// * @return array of integers -// */ -// protected int[] rldecode16Delta(byte[] b, int n, int i0) { -// if (b == null) -// return null; -// int[] ret = new int[n]; -// for (int i = 0, pt = i0 / 2, val = 0; i < n;) { -// int diff = BC.bytesToShort(b, (pt++) << 1, true); -// for (int j = BC.bytesToShort(b, (pt++) << 1, true); --j >= 0;) -// ret[i++] = (val = val + diff); -// } -// return ret; -// } - - -// /** -// * Do a split delta to a float[] array -// * @param xyz label "x", "y", "z", or "bFactor" -// * @param factor for dividing in the end -- 1000f or 100f -// * @return float[] -// * -// */ -// protected float[] getFloatsSplit(String xyz, float factor) { -// byte[] big = (byte[]) map.get(xyz + "Big"); -// return (big == null ? null : splitDelta(big, -// (byte[]) map.get(xyz + "Small"), fileAtomCount, factor)); -// } - -// /** -// * Do a split delta to a float[] array -// * -// * @param big -// * [n m n m n m...] where n is a "big delta" and m is a number of -// * "small deltas -// * @param small -// * array containing the small deltas -// * @param n -// * the size of the final array -// * @param factor -// * to divide the final result by -- 1000f or 100f here -// * @return float[] -// */ -// protected float[] splitDelta(byte[] big, byte[] small, int n, float factor) { -// float[] ret = new float[n]; -// for (int i = 0, smallpt = 0, val = 0, datapt = 0, len = big.length >> 2; i < len; i++) { -// ret[datapt++] = (val = val + BC.bytesToInt(big, i << 2, true)) / factor; -// if (++i < len) -// for (int j = BC.bytesToInt(big, i << 2, true); --j >= 0; smallpt++) -// ret[datapt++] = (val = val + BC.bytesToShort(small, smallpt << 1, true)) -// / factor; -// } -// return ret; -// } -// - -//////////////////////////////// MMTF-Specific ///////////////////////// - - private Map<String, Object> map; // input JSON-like map from MessagePack binary file - private int fileAtomCount; - private int opCount = 0; - private int[] groupModels; - - private String[] labelAsymList; // created in getAtoms; used in getBioAssembly - private Atom[] atomMap; // necessary because some atoms may be deleted. - - // TODO - also consider mapping group indices - /** - * set up all atoms, including bonding within a group * - * @param doMulti - * true to add double bonds + * mmtf type 12 and 13 * - * @throws Exception + * Unpack an array of int8 or int16 to int32 and divide to give a float32. + * + * untested + * + * @param b + * @param nBytes + * @param n + * @param divisor + * @return array of integers */ - @SuppressWarnings("unchecked") - private void getAtoms(boolean doMulti) throws Exception { - - // chains - int[] chainsPerModel = (int[]) map.get("chainsPerModel"); - int[] groupsPerChain = (int[]) map.get("groupsPerChain"); // note that this is label_asym, not auth_asym - labelAsymList = (String[]) decode("chainIdList"); // label_asym - String[] authAsymList = (String[]) decode("chainNameList"); // Auth_asym - - // groups - int[] groupTypeList = (int[]) decode("groupTypeList"); - int groupCount = groupTypeList.length; - groupModels = new int[groupCount]; - int[] groupIdList = (int[]) decode("groupIdList"); - Object[] groupList = (Object[]) map.get("groupList"); - char[] insCodes = (char[]) decode("insCodeList"); - - //o = map.get("entityList"); - //o = map.get("altLabelList"); - // 1crn: [7, 3, 3, 7, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 1, 7, 3, 3, 7, 1, 1, 1, 7, 7, 7, 4, 4, 4, 7, 7] - - int[] atomId = (int[]) decode("atomIdList"); - boolean haveSerial = (atomId != null); - - char[] altloc = (char[]) decode("altLocList"); // rldecode32 - float[] occ = (float[]) decode("occupancyList"); - - float[] x = (float[]) decode("xCoordList");//getFloatsSplit("xCoord", 1000f); - float[] y = (float[]) decode("yCoordList"); - float[] z = (float[]) decode("zCoordList"); - float[] bf = (float[]) decode("bFactorList"); - int iatom = 0; - String[] nameList = (useAuthorChainID ? authAsymList : labelAsymList); - int iModel = -1; - int iChain = 0; - int nChain = 0; - int iGroup = 0; - int nGroup = 0; - int chainpt = 0; - int seqNo = 0; - String chainID = ""; - String authAsym = "", labelAsym = ""; - char insCode = '\0'; - atomMap = new Atom[fileAtomCount]; - for (int j = 0; j < groupCount; j++) { - int a0 = iatom; - if (insCodes != null) - insCode = insCodes[j]; - seqNo = groupIdList[j]; - if (++iGroup >= nGroup) { - chainID = nameList[chainpt]; - authAsym = authAsymList[chainpt]; - labelAsym = labelAsymList[chainpt]; - nGroup = groupsPerChain[chainpt++]; - iGroup = 0; - if (++iChain >= nChain) { - groupModels[j] = ++iModel; - nChain = chainsPerModel[iModel]; - iChain = 0; - setModelPDB(true); - incrementModel(iModel + 1); - - nAtoms0 = asc.ac; + protected float[] unpackf(byte[] b, int nBytes, int n, float divisor) { + if (b == null) + return null; + float[] ret = new float[n]; + switch (nBytes) { + case 1: + for (int i = 0, pt = 12, offset = 0; i < n;) { + int val = b[pt++]; + if (val == Byte.MAX_VALUE || val == Byte.MIN_VALUE) { + offset += val; + } else { + ret[i++] = (val + offset) / divisor; + offset = 0; } } - Map<String, Object> g = (Map<String, Object>) groupList[groupTypeList[j]]; - String group3 = (String) g.get("groupName"); - addHetero(group3, "" + g.get("chemCompType"), true); - //System.out.println(group3 + " " + g.get("chemCompType")); - String[] atomNameList = (String[]) g.get("atomNameList"); - String[] elementList = (String[]) g.get("elementList"); - int len = atomNameList.length; - for (int ia = 0, pt = 0; ia < len; ia++, iatom++) { - Atom a = new Atom(); - if (insCode != 0) - a.insertionCode = insCode; - setAtomCoordXYZ(a, x[iatom], y[iatom], z[iatom]); - a.elementSymbol = elementList[pt]; - a.atomName = atomNameList[pt++]; - if (seqNo >= 0) - maxSerial = Math.max(maxSerial, a.sequenceNumber = seqNo); - a.group3 = group3; - setChainID(a, chainID); - if (bf != null) - a.bfactor = bf[iatom]; - if (altloc != null) - a.altLoc = altloc[iatom]; - if (occ != null) - a.foccupancy = occ[iatom]; - if (haveSerial) - a.atomSerial = atomId[iatom]; - if (!filterAtom(a, -1) || !processSubclassAtom(a, labelAsym, authAsym)) - continue; - if (haveSerial) { - asc.addAtomWithMappedSerialNumber(a); + break; + case 2: + for (int i = 0, pt = 6, offset = 0; i < n;) { + int val = BC.bytesToShort(b, (pt++) << 1, true); + if (val == Short.MAX_VALUE || val == Short.MIN_VALUE) { + offset += val; } else { - asc.addAtom(a); + ret[i++] = (val + offset) / divisor; + offset = 0; } - atomMap[iatom] = a; - ++ac; } - if (!isCourseGrained) { - int[] bo = (int[]) g.get("bondOrderList"); - if (bo != null) { - int[] bi = (int[]) g.get("bondAtomList"); - for (int bj = 0, pt = 0, nj = bo.length; bj < nj; bj++) { - Atom a1 = atomMap[bi[pt++] + a0]; - Atom a2 = atomMap[bi[pt++] + a0]; - if (a1 != null && a2 != null) - addBond(new Bond(a1.index, a2.index, doMulti ? bo[bj] : 1), false); - } - } - } + break; } + return ret; } - private void addBond(Bond bond, boolean isInter) { - asc.addBond(bond); - if (Logger.debugging && isInter) { - Atom a1 = asc.atoms[bond.atomIndex1]; - Atom a2 = asc.atoms[bond.atomIndex2]; - Logger.info("bond " +a1.group3 + a1.sequenceNumber + "." + a1.atomName - + " " + a2.group3 + a2.sequenceNumber + "." + a2.atomName + " " + bond.order); + /** + * + * mmtf type 14 and 15 + * + * Unpack an array of int8 or int16 to int32. + * + * untested + * + * @param b + * @param nBytes + * @param n + * @return array of integers + */ + protected int[] unpack(byte[] b, int nBytes, int n) { + if (b == null) + return null; + int[] ret = new int[n]; + switch (nBytes) { + case 1: + for (int i = 0, pt = 12, offset = 0; i < n;) { + int val = b[pt++]; + if (val == Byte.MAX_VALUE || val == Byte.MIN_VALUE) { + offset += val; + } else { + ret[i++] = val + offset; + offset = 0; + } + } + break; + case 2: + for (int i = 0, pt = 6, offset = 0; i < n;) { + int val = BC.bytesToShort(b, (pt++) << 1, true); + if (val == Short.MAX_VALUE || val == Short.MIN_VALUE) { + offset += val; + } else { + ret[i++] = val + offset; + offset = 0; + } + } + break; } + return ret; } - private void getBonds(boolean doMulti) { - int[] b = (int[]) decode("bondOrderList"); - int[] bi = (int[]) decode("bondAtomList"); - for (int i = 0, pt = 0, n = b.length; i < n; i++) { - Atom a1 = atomMap[bi[pt++]]; - Atom a2 = atomMap[bi[pt++]]; - if (a1 != null && a2 != null) - addBond(new Bond(a1.index, a2.index, doMulti ? b[i] : 1), true); - } - } + ///** + //* Decode an array of int16 using run-length decoding + //* of a difference array. + //* + //* @param b + //* @param n + //* @param i0 + //* @return array of integers + //*/ + //protected int[] rldecode16Delta(byte[] b, int n, int i0) { + //if (b == null) + //return null; + //int[] ret = new int[n]; + //for (int i = 0, pt = i0 / 2, val = 0; i < n;) { + //int diff = BC.bytesToShort(b, (pt++) << 1, true); + //for (int j = BC.bytesToShort(b, (pt++) << 1, true); --j >= 0;) + //ret[i++] = (val = val + diff); + //} + //return ret; + //} - private void setSymmetry() { - setSpaceGroupName((String) map.get("spaceGroup")); - float[] o = (float[]) map.get("unitCell"); - if (o != null) - for (int i = 0; i < 6; i++) - setUnitCellItem(i, o[i]); - } + ///** + //* Do a split delta to a float[] array + //* @param xyz label "x", "y", "z", or "bFactor" + //* @param factor for dividing in the end -- 1000f or 100f + //* @return float[] + //* + //*/ + //protected float[] getFloatsSplit(String xyz, float factor) { + //byte[] big = (byte[]) map.get(xyz + "Big"); + //return (big == null ? null : splitDelta(big, + //(byte[]) map.get(xyz + "Small"), fileAtomCount, factor)); + //} - @SuppressWarnings("unchecked") - private void getBioAssembly() { - Object[] o = (Object[]) map.get("bioAssemblyList"); - if (vBiomolecules == null) - vBiomolecules = new Lst<Map<String, Object>>(); + ///** + //* Do a split delta to a float[] array + //* + //* @param big + //* [n m n m n m...] where n is a "big delta" and m is a number of + //* "small deltas + //* @param small + //* array containing the small deltas + //* @param n + //* the size of the final array + //* @param factor + //* to divide the final result by -- 1000f or 100f here + //* @return float[] + //*/ + //protected float[] splitDelta(byte[] big, byte[] small, int n, float factor) { + //float[] ret = new float[n]; + //for (int i = 0, smallpt = 0, val = 0, datapt = 0, len = big.length >> 2; i < len; i++) { + //ret[datapt++] = (val = val + BC.bytesToInt(big, i << 2, true)) / factor; + //if (++i < len) + //for (int j = BC.bytesToInt(big, i << 2, true); --j >= 0; smallpt++) + //ret[datapt++] = (val = val + BC.bytesToShort(small, smallpt << 1, true)) + // / factor; + //} + //return ret; + //} + // - for (int i = o.length; --i >= 0;) { - Map<String, Object> info = new Hashtable<String, Object>(); - vBiomolecules.addLast(info); - int iMolecule = i + 1; - checkFilterAssembly("" + iMolecule, info); - info.put("name", "biomolecule " + iMolecule); - info.put("molecule", Integer.valueOf(iMolecule)); - Lst<String> assemb = new Lst<String>(); - Lst<String> ops = new Lst<String>(); - info.put("biomts", new Lst<M4>()); - info.put("chains", new Lst<String>()); - info.put("assemblies", assemb); - info.put("operators", ops); - // need to add NCS here. - Map<String, Object> m = (Map<String, Object>) o[i]; - Object[] tlist = (Object[]) m.get("transformList"); - SB chlist = new SB(); - - for (int j = 0, n = tlist.length; j < n; j++) { - - Map<String, Object> t = (Map<String, Object>) tlist[j]; - - // for every transformation... - - chlist.setLength(0); - - // for compatibility with the mmCIF reader, we create - // string lists of the chains in the form $A$B$C... - - int[] chainList = (int[]) t.get("chainIndexList"); - for (int k = 0, kn = chainList.length; k < kn; k++) - chlist.append("$").append(labelAsymList[chainList[k]]); - assemb.addLast(chlist.append("$").toString()); - - // now save the 4x4 matrix transform for this operation - - String id = "" + (++opCount); - addMatrix(id, M4.newA16((float[]) t.get("matrix")), false); - ops.addLast(id); - } - } - } - - // Code Name - // 0* pi helix - // 1 bend (ignored) - // 2* alpha helix - // 3* extended (sheet) - // 4* 3-10 helix - // 5 bridge (ignored) - // 6* turn - // 7 coil (ignored) - // -1 undefined - - // 1F88: "secStructList": [7713371173311776617777666177444172222222222222222222222222222222166771222222222222222222262222222222617662222222222222222222222222222222222177111777722222222222222222221222261173333666633337717776666222222222226622222222222226611771777 - // DSSP (Jmol): ...EE....EE....TT.....TTT...GGG..HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH.TT...HHHHHHHHHHHHHHHHHHHTHHHHHHHHHHT..TTHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH..........HHHHHHHHHHHHHHHHHHH.HHHHT...EEEETTTTEEEE......TTTTHHHHHHHHHHHTTHHHHHHHHHHHHHTT........ - - /** - * Get and translate the DSSP string from digit format - * - * @param a input data - */ - private void getStructure(int[] a) { - BS[] bsStructures = new BS[] { new BS(), null, new BS(), new BS(), new BS(), null, new BS() }; - if (Logger.debugging) - Logger.info(PT.toJSON("secStructList", a)); - int lastGroup = -1; - for (int i = 0; i < a.length; i++) { - int type = a[i]; - switch (type) { - case 0: // PI - case 2: // alpha - case 3: // sheet - case 4: // 3-10 - case 6: // turn - bsStructures[type].set(i); - lastGroup = i; - } - } - - int n = (isDSSP1 ? asc.iSet : groupModels[lastGroup]); - if (lastGroup >= 0) - asc.addStructure(new Structure(n, null, null, null, 0, 0, bsStructures)); - } - } - This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------------ What NetFlow Analyzer can do for you? Monitors network bandwidth and traffic patterns at an interface-level. Reveals which users, apps, and protocols are consuming the most bandwidth. Provides multi-vendor support for NetFlow, J-Flow, sFlow and other flows. Make informed decisions using capacity planning reports. http://sdm.link/zohodev2dev _______________________________________________ Jmol-commits mailing list Jmol-commits@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jmol-commits