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

Reply via email to