Revision: 21183
          http://sourceforge.net/p/jmol/code/21183
Author:   hansonr
Date:     2016-08-08 22:23:29 +0000 (Mon, 08 Aug 2016)
Log Message:
-----------
Jmol.___JmolVersion="14.7.1_2016.08.08"

new feature: Jmol reads PyMOL 1.8 PSE files with "set dump_binary, 1"

Modified Paths:
--------------
    trunk/Jmol/src/org/jmol/adapter/readers/pymol/PickleReader.java
    trunk/Jmol/src/org/jmol/adapter/readers/pymol/PyMOL.java
    trunk/Jmol/src/org/jmol/adapter/readers/pymol/PyMOLReader.java
    trunk/Jmol/src/org/jmol/adapter/readers/pymol/PyMOLScene.java
    trunk/Jmol/src/org/jmol/viewer/Jmol.properties

Modified: trunk/Jmol/src/org/jmol/adapter/readers/pymol/PickleReader.java
===================================================================
--- trunk/Jmol/src/org/jmol/adapter/readers/pymol/PickleReader.java     
2016-08-02 03:07:20 UTC (rev 21182)
+++ trunk/Jmol/src/org/jmol/adapter/readers/pymol/PickleReader.java     
2016-08-08 22:23:29 UTC (rev 21183)
@@ -1,11 +1,12 @@
 package org.jmol.adapter.readers.pymol;
 
+import java.io.UnsupportedEncodingException;
 import java.util.Hashtable;
 import java.util.Map;
 
 import javajs.api.GenericBinaryDocument;
+import javajs.util.AU;
 import javajs.util.Lst;
-import javajs.util.SB;
 
 import org.jmol.util.Logger;
 import org.jmol.viewer.Viewer;
@@ -35,12 +36,12 @@
   private Lst<Integer> marks = new Lst<Integer>();
   private Lst<Object> build = new Lst<Object>();
 
-  private Map<Integer, Object> memo = new Hashtable<Integer, Object>();
+  private Map<Object, Object> memo = new Hashtable<Object, Object>();
   
   private boolean logging;
   private int id;
   private int markCount;
-  private int filePt;
+  private int filePt; 
   private int emptyListPt;
   private Object thisSection;
   private boolean inMovie;
@@ -103,10 +104,13 @@
     vwr.log(s + "\0");
   }
   
+  private int ipt = 0;
+  public boolean haveBinaryString;
+
   @SuppressWarnings("unchecked")
-  Map<String, Object> getMap(boolean logging) throws Exception {
+  Map<String, Object> getMap(boolean logging)
+      throws Exception {
     this.logging = logging;
-    String s;
     byte b;
     int i, mark;
     double d;
@@ -114,12 +118,14 @@
     byte[] a;
     Map<String, Object> map;
     Lst<Object> l;
+    ipt = 0;
     boolean going = true;
 
     while (going) {
       b = binaryDoc.readByte();
+      ipt++;
       //if (logging)
-        //log(" " + b);
+      //log(" " + b);
       switch (b) {
       case EMPTY_DICT: //}
         push(new Hashtable<String, Object>());
@@ -130,9 +136,10 @@
         break;
       case APPENDS:
         l = getObjects(getMark());
-        if (inNames && markCount == 2){// && l.size() > 0 && l.get(0) == 
thisName) {
+        if (inNames && markCount == 2) {// && l.size() > 0 && l.get(0) == 
thisName) {
           int pt = (int) binaryDoc.getPosition();
-          System.out.println(" " + thisName + " " + filePt + " " + (pt - 
filePt));
+          System.out.println(" " + thisName + " " + filePt + " "
+              + (pt - filePt));
           Lst<Object> l2 = new Lst<Object>();
           l2.addLast(Integer.valueOf(filePt));
           l2.addLast(Integer.valueOf(pt - filePt));
@@ -172,48 +179,40 @@
       case LONG_BINGET:
         i = binaryDoc.readIntLE();
         o = getMemo(i);
-        if (o == null) {
-          Logger.error("did not find memo item for " + i);
-          push("LONG_BINGET" + (++id));
-        } else {
-          push(o);
-        }
-        
+        push(o == null ? "LONG_BINGET" + (++id) : o);
         break;
       case SHORT_BINSTRING:
         i = binaryDoc.readByte() & 0xff;
         a = new byte[i];
         binaryDoc.readByteArray(a, 0, i);
-        s = new String(a, "UTF-8");
         if (inNames && markCount == 3 && lastMark == stack.size()) {
-          thisName = s;
+          thisName = bytesToString(a);
           filePt = emptyListPt;
         }
-        push(s);
+        push(a);
         break;
       case BINSTRING:
         i = binaryDoc.readIntLE();
         a = new byte[i];
         binaryDoc.readByteArray(a, 0, i);
-        s = new String(a, "UTF-8");
-        push(s);
+        push(a);
+        haveBinaryString = true;
         break;
       case BINUNICODE:
         i = binaryDoc.readIntLE();
         a = new byte[i];
         binaryDoc.readByteArray(a, 0, i);
-        s = new String(a, "UTF-8");
-        push(s);
+        push(a);
         break;
       case EMPTY_LIST:
         emptyListPt = (int) binaryDoc.getPosition() - 1;
-        push(new  Lst<Object>());
+        push(new Lst<Object>());
         break;
       case GLOBAL:
         l = new Lst<Object>();
         l.addLast("global");
-        l.addLast(readString());
-        l.addLast(readString());
+        l.addLast(readStringAsBytes());
+        l.addLast(readStringAsBytes());
         push(l);
         break;
       case BUILD:
@@ -231,10 +230,8 @@
         break;
       case SETITEM:
         o = pop();
-        if (!(peek() instanceof String))
-          Logger.error(peek() + " is not a string");
-        s = (String) pop();
-        ((Map<String, Object>) peek()).put(s, o);
+        a = (byte[]) pop();
+        ((Map<String, Object>) peek()).put(bytesToString(a), o);
         break;
       case SETITEMS:
         mark = getMark();
@@ -244,13 +241,12 @@
           for (i = 0; i < l.size(); i++)
             ((Lst<Object>) o).addLast(l.get(i));
         } else {
-        map = (Map<String, Object>) o;
-        for (i = l.size(); --i >= 0;) {
-          o = l.get(i);
-          s = (String) l.get(--i);
-          map.put(s, o);
+          map = (Map<String, Object>) o;
+          for (i = l.size(); --i >= 0;) {
+            o = l.get(i);
+            map.put(bytesToString((byte[]) l.get(--i)), o);
+          }
         }
-        }
         break;
       case STOP:
         going = false;
@@ -260,8 +256,8 @@
         push(getObjects(getMark()));
         break;
       case INT:
-        /// 0x88000000 for instance
-        s = readString();
+        /// "0x88000000" for instance
+        String s = bytesToString(readStringAsBytes());
         try {
           push(Integer.valueOf(Integer.parseInt(s)));
         } catch (Exception e) {
@@ -351,25 +347,38 @@
     }
     if (logging)
       log("");
-    Logger.info("PyMOL Pickle reader cached " + memo.size() + " tokens; 
retrieved " + retrieveCount);
-    memo = null;
+    Logger.info("PyMOL Pickle reader cached " + memo.size()
+        + " tokens; retrieved " + retrieveCount);
+
     map = (Map<String, Object>) stack.remove(0);
     if (map.size() == 0)
       for (i = stack.size(); --i >= 0;) {
         o = stack.get(i--);
-        s = (String) stack.get(i);
-        map.put(s, o);
+        a = (byte[]) stack.get(i);
+        map.put(bytesToString(a), o);
       }
+    memo = null;
     return map;
   }
   
+  private String bytesToString(byte[] a) {
+    try {
+      return new String(a, "UTF-8");
+    } catch (UnsupportedEncodingException e) {
+      return "";
+    }
+  }
+
   private void putMemo(int i, boolean doCheck) {
     Object o = peek();
     if (o instanceof String) {
       if (doCheck && markCount >= 6 || markCount == 3 && inMovie)
         return;
       memo.put(Integer.valueOf(i), o);
-      //System.out.println("caching string " + o + " at " + 
binaryDoc.getPosition());
+      if (((String)o).indexOf('\0') >= 0)
+        System.out.println("caching byte["+((String)o).length() + "] at " + 
binaryDoc.getPosition() + " ipt " + ipt);
+      else
+        System.out.println("caching String \"" + o + "\" at " + 
binaryDoc.getPosition() + " ipt " + ipt);
     }
   }
 
@@ -397,16 +406,20 @@
   //    String s = readString();
   //    return s.getBytes();
   //  }
+  byte[] aTemp = new byte[16];
 
-  private String readString() throws Exception {
-    SB sb = new SB();
+  private byte[] readStringAsBytes() throws Exception {
+    int n = 0;
+    byte[] a = aTemp;
     while (true) {
       byte b = binaryDoc.readByte();
       if (b == 0xA)
         break;
-      sb.appendC((char) b);
+      if (n >= a.length)
+        a = aTemp = AU.arrayCopyByte(a, a.length * 2);
+      a[n++] = b;
     }
-    return sb.toString();
+    return AU.arrayCopyByte(a, n);
   }
 
   private void putMark(int i) {
@@ -416,10 +429,11 @@
     markCount++;
     switch (markCount) {
     case 2:
-      thisSection = stack.get(i - 2);
+      Object o = stack.get(i - 2);
       // BH: Note that JavaScript string == object first converts object to 
string, then checks. 
       // This can be very slow if the object is complex.
-      if (thisSection instanceof String) {
+      if (AU.isAB(o)) {
+        thisSection = bytesToString((byte[]) o);
         inMovie = "movie".equals(thisSection);
         inNames = "names".equals(thisSection);
       }

Modified: trunk/Jmol/src/org/jmol/adapter/readers/pymol/PyMOL.java
===================================================================
--- trunk/Jmol/src/org/jmol/adapter/readers/pymol/PyMOL.java    2016-08-02 
03:07:20 UTC (rev 21182)
+++ trunk/Jmol/src/org/jmol/adapter/readers/pymol/PyMOL.java    2016-08-08 
22:23:29 UTC (rev 21183)
@@ -297,6 +297,7 @@
   final static int dot_width                             =  77;
   final static int draw_frames                           = 436;
   final static int draw_mode                             = 614;
+  final static int dump_binary                           = 749;
   final static int dynamic_measures                      = 637;
   final static int dynamic_width                         = 610;
   final static int dynamic_width_factor                  = 611;
@@ -6300,6 +6301,7 @@
     case valence:
     case cgo_transparency:
     case cartoon_putty_transform:
+    case dump_binary:
     case orthoscopic:
     case ribbon_radius:
     case ribbon_smooth:

Modified: trunk/Jmol/src/org/jmol/adapter/readers/pymol/PyMOLReader.java
===================================================================
--- trunk/Jmol/src/org/jmol/adapter/readers/pymol/PyMOLReader.java      
2016-08-02 03:07:20 UTC (rev 21182)
+++ trunk/Jmol/src/org/jmol/adapter/readers/pymol/PyMOLReader.java      
2016-08-08 22:23:29 UTC (rev 21183)
@@ -26,6 +26,7 @@
 
 import javajs.util.Lst;
 
+import java.io.UnsupportedEncodingException;
 import java.util.Hashtable;
 import java.util.Map;
 
@@ -42,6 +43,8 @@
 import org.jmol.util.BoxInfo;
 import org.jmol.util.Logger;
 
+import javajs.util.AU;
+import javajs.util.BC;
 import javajs.util.P3;
 import javajs.util.PT;
 import javajs.util.V3;
@@ -83,7 +86,7 @@
 
 public class PyMOLReader extends PdbReader implements PymolAtomReader {
 
-  private static final int MIN_RESNO = -1000; // minimum allowed residue number
+  private final static int MIN_RESNO = -1000; // minimum allowed residue number
 
   private static String nucleic = " A C G T U ADE THY CYT GUA URI DA DC DG DT 
DU ";
 
@@ -140,6 +143,8 @@
 
   private int bondCount;
 
+  private boolean haveBinaryArrays;
+
   @Override
   protected void setup(String fullPath, Map<String, Object> htParams, Object 
reader) {
     isBinary = mustFinalizeModelSet = true;
@@ -197,6 +202,7 @@
 
     PickleReader reader = new PickleReader(binaryDoc, vwr);
     Map<String, Object> map = reader.getMap(logging && Logger.debuggingHigh);
+    haveBinaryArrays = reader.haveBinaryString;
     reader = null;
     process(map);
   }
@@ -270,12 +276,13 @@
     sceneOrder = getMapList(map, "scene_order");
     haveScenes = getFrameScenes(map);
     Lst<Object> file = listAt(settings, PyMOL.session_file);
-    if (file != null)
+    if (file != null && file.size() > 2)
       Logger.info("PyMOL session file: " + file.get(2));
     //asc.setAtomSetCollectionAuxiliaryInfo("settings", settings);
     setUniqueSettings(getMapList(map, "unique_settings"));
     pymolScene = new PyMOLScene(this, vwr, settings, uniqueSettings, 
         pymolVersion, haveScenes, baseAtomIndex, baseModelIndex, doCache, 
filePath);
+    //just doing this based on having binaryStrings. haveBinaryArrays = 
pymolScene.booleanSetting(PyMOL.dump_binary);
 
     // just log and display some information here
     String logFile = vwr.getLogFileName();
@@ -308,7 +315,7 @@
       for (int i = 1; i < names.size(); i++) {
         vwr.log("");
         Lst<Object> list = (Lst<Object>) names.get(i);
-        vwr.log(" =" + list.get(0).toString() + "=");
+        vwr.log(" =" + bytesToString(list.get(0)) + "=");
         try {
           vwr.log(PT.rep(list.toString(), "[", "\n["));
         } catch (Throwable e) {
@@ -545,7 +552,16 @@
         int ns = states.size();
         if (ns > stateCount)
           stateCount = ns;
-        int nAtoms = listAt(pymolObject, 7).size();
+        int nAtoms, nBonds;
+        if (haveBinaryArrays) {
+          nBonds = ((byte[]) listAt(pymolObject, 6).get(1)).length / 20;
+          nAtoms = ((byte[]) listAt(pymolObject, 7).get(1)).length / 120;
+          n += nAtoms;
+        } else {
+          nBonds = listAt(pymolObject, 6).size();
+          nAtoms = listAt(pymolObject, 7).size();
+        }
+        System.out.println("Object " + objectName + " nBonds=" + nBonds + ", 
nAtoms = " + nAtoms);
         for (int j = 0; j < ns; j++) {
           Lst<Object> state = listAt(states, j);
           Lst<Object> idxToAtm = listAt(state, 3);
@@ -844,7 +860,7 @@
   }
 
   /**
-   * Create everything necessary to generate a molecule in Jmol. 
+   * Create everything necessary to generate a molecule in Jmol.
    * 
    * @param pymolObject
    * @param iState
@@ -853,21 +869,46 @@
   private BS processMolecule(Lst<Object> pymolObject, int iState) {
     Lst<Object> states = listAt(pymolObject, 4);
     Lst<Object> state = listAt(states, iState);
-    Lst<Object> idxToAtm = listAt(state, 3);
-    int n = (idxToAtm == null ? 0 : idxToAtm.size());
+    Lst<Object> idxToAtm;
+    Lst<Object> coords;
+    Lst<Object> labelPositions;
+    int[] idxArray = null;
+    float[] coordsArray = null;
+    float[] labelArray = null;
+    int nBonds = intAt(pymolObject, 2);
+    int nAtoms = intAt(pymolObject, 3);
+    int n = nAtoms;
+    if (haveBinaryArrays && AU.isAB(state.get(3))) {
+      idxToAtm = coords = labelPositions = null;
+      idxArray = new int[nAtoms];
+      coordsArray = new float[nAtoms * 3];
+      fillFloatArrayFromBytes((byte[]) state.get(2), coordsArray);
+      fillIntArrayFromBytes((byte[]) state.get(3), idxArray);
+      byte[] b = (byte[]) state.get(8);
+      if (b != null) {
+        labelArray = new float[nAtoms * 7];
+        fillFloatArrayFromBytes(b, labelArray);
+      }
+
+    } else {
+      coords = listAt(state, 2);
+      idxToAtm = listAt(state, 3);
+      // atomToIdx = listAt(state, 4);
+      
+      labelPositions = listAt(state, 8);
+      if (idxToAtm != null)
+        n = idxToAtm.size();
+    }
     if (n == 0)
       return null;
 
     ac = ac0 = asc.ac;
-    int nAtoms = intAt(pymolObject, 3);
     if (nAtoms == 0)
       return null;
     ssMapSeq = new Hashtable<String, BS>();
     if (iState == 0)
       processMolCryst(listAt(pymolObject, 10));
     Lst<Bond> bonds = getBondList(listAt(pymolObject, 6));
-
-    
     Lst<Object> pymolAtoms = listAt(pymolObject, 7);
     atomMap = new int[nAtoms];
     BS bsAtoms = pymolScene.setAtomMap(atomMap, ac0);
@@ -876,14 +917,16 @@
 
     // TODO: Implement trajectory business here.
 
-
-    Lst<Object> coords = listAt(state, 2);
-    Lst<Object> labelPositions = listAt(state, 8);
     if (iState == 0 || !isTrajectory) {
       pymolScene.ensureCapacity(n);
+      String[] lexStr = (haveBinaryArrays ? 
getLexStr((byte[])pymolAtoms.get(2)) : null);
+      byte[] atomArray = (haveBinaryArrays ? (byte[])pymolAtoms.get(1) : null);
+      int[] vArray = (haveBinaryArrays ? getVArray(intAt(pymolAtoms,  0)) : 
null);
       for (int idx = 0; idx < n; idx++) {
-        P3 a = addAtom(pymolAtoms, intAt(idxToAtm, idx), idx, coords, 
-            labelPositions, bsAtoms, iState);
+        P3 a = addAtom(pymolAtoms, (idxToAtm != null ? intAt(idxToAtm, idx)
+            : idxArray != null ? idxArray[idx] : idx),
+            atomArray, vArray, lexStr, idx, coords,
+            coordsArray, labelPositions, labelArray, bsAtoms, iState);
         if (a != null)
           trajectoryStep[trajectoryPtr++] = a;
       }
@@ -895,11 +938,66 @@
       createShapeObjects();
     ssMapSeq = null;
 
-    Logger.info("reading " + (ac - ac0) + " atoms");
+    Logger.info("reading " + (ac - ac0) + " atoms and " + nBonds + " bonds");
     Logger.info("----------");
     return bsAtoms;
   }
 
+  private int[] getVArray(int version) {
+    int[] va = null;
+    int[] varray = null;
+    switch (version) {
+    case 181:
+      va = v181;
+      varray = new int[60];
+      break;
+    }
+    if (varray != null)
+      for (int i = 0; i < va.length;)
+        varray[va[i++]] = va[i++];
+    return varray;
+  }
+
+  private String[] getLexStr(byte[] lex) {
+    int pt = 0;
+    int n = BC.bytesToInt(lex, pt, false);
+    int[] index = new int[n];
+    int imax = 0;
+    for (int i = 0; i < n; i++) {
+      pt += 4;
+      int ipt = index[i] = BC.bytesToInt(lex, pt, false);
+      if (ipt > imax)
+        imax = ipt;
+    }
+    String[] tokens = new String[imax + 1];
+    tokens[0] = " ";
+    pt += 4;
+    for (int i = 0; i < n; i++) {
+      String s = tokens[index[i]] = getCStr(lex, pt);
+      pt += s.length() + 1;
+    }
+    return tokens;
+  }
+  
+  private String getCStr(byte[] lex, int pt) {
+    try {
+      byte[] a = aTemp;
+      int apt = 0;
+      byte b = 0;
+      while ((b = lex[pt++]) != 0) {
+        if (apt >= a.length)
+          a = aTemp = AU.doubleLengthByte(a);
+        a[apt++] = b;
+      }
+      return new String(AU.arrayCopyByte(a, apt), "UTF-8");
+    } catch (UnsupportedEncodingException e) {
+      return null;
+    }
+  }
+
+  byte[] aTemp = new byte[16];
+
+
   /**
    * Pick up the crystal data.
    * 
@@ -923,24 +1021,72 @@
    */
   private Lst<Bond> getBondList(Lst<Object> bonds) {
     boolean asSingle = pymolScene.booleanSetting(PyMOL.valence);
+    int[] array = null;
     int n = bonds.size();
+    if (haveBinaryArrays && n == 2) {
+      byte[] b = (byte[]) bonds.get(1);
+      n = b.length / 4 / 5;
+      array = new int[n * 5];
+      fillIntArrayFromBytes(b, array);
+    }
     Lst<Bond> bondList = new Lst<Bond>();
     bondList.ensureCapacity(n);
-    for (int i = 0; i < n; i++) {
-      Lst<Object> b = listAt(bonds, i);
-      int ia = intAt(b, 0);
-      int ib = intAt(b, 1);
-      int order = intAt(b, 2);
+    int ia, ib, order, uid = -1;
+    for (int i = 0, pt = 0; i < n; i++) {
+      if (haveBinaryArrays) {
+        
+//      typedef struct BondType {
+//      int index[2];
+//      int id;
+//      int unique_id;
+//    #ifdef _PYMOL_IP_EXTRAS
+//      int oldid;
+//    #endif
+//      signed char order;    // 0-4
+//      signed char temp1;    // bool? where used?
+//      signed char stereo;   // 0-6 Only for SDF (MOL) format in/out
+//      bool has_setting;     /* setting based on unique_id */
+//    } BondType;
+
+
+        ia = array[pt++];
+        ib = array[pt++];
+        pt++; // id
+        uid = array[pt++]; 
+        order = array[pt++] & 0xFF;
+      } else {
+        Lst<Object> b = listAt(bonds, i);
+        ia = intAt(b, 0);
+        ib = intAt(b, 1);
+        order = intAt(b, 2);
+        uid = (b.size() > 6 && intAt(b, 6) != 0 ? intAt(b, 5) : -1);
+      }
       if (order < 1 || order > 3)
         order = 1;
-      order |= (asSingle || order == 1 ? JmolAdapter.ORDER_PYMOL_SINGLE : 
JmolAdapter.ORDER_PYMOL_MULT);
+      order |= (asSingle || order == 1 ? JmolAdapter.ORDER_PYMOL_SINGLE
+          : JmolAdapter.ORDER_PYMOL_MULT);
       Bond bond = new Bond(ia, ib, order);
-      bond.uniqueID = (b.size() > 6 && intAt(b, 6) != 0 ? intAt(b, 5) : -1);
+      bond.uniqueID = uid;
       bondList.addLast(bond);
     }
     return bondList;
   }
+  private void fillIntArrayFromBytes(byte[] b, int[] array) {
+    for (int i = 0, pt = 0; i < b.length; i += 4)
+      array[pt++] = BC.bytesToInt(b, i, false);
+  }
 
+  private void fillFloatArrayFromBytes(byte[] b, float[] array) {
+    try {
+      for (int i = 0, pt = 0; i < b.length; i += 4)
+        array[pt++] = BC.bytesToFloat(b, i, false);
+    } catch (Exception e) {
+      // not possible?
+    }
+  }
+
+  
+
   // [0] Int        resv
   // [1] String     chain
   // [2] String     alt
@@ -989,6 +1135,192 @@
   // [45] Float     U13
   // [46] Float     U23
 
+
+//1.7.6 type
+//typedef struct AtomInfoType {
+// int resv;
+// int customType;
+// int priority;
+// float b, q, vdw, partialCharge;
+// int selEntry;
+// int color;
+// int id;                       // PDB ID
+// unsigned int flags;
+// int temp1;                    /* kludge fields - to remove */
+// int unique_id;                /* introduced in version 0.77 */
+// int discrete_state;           /* state+1 for atoms in discrete objects */
+// float elec_radius;            /* radius for PB calculations */
+// int rank;
+// int textType;
+// int custom;
+// int label;
+// int visRep;                   /* bitmask for all reps */
+//
+// /* be careful not to write at these as (int*) */
+//
+// signed char formalCharge;     // values typically in range -2..+2
+// signed char stereo;           /* for 2D representation */
+// signed char mmstereo;           /* from MMStereo */
+// signed char cartoon;          /* 0 = default which is auto (use ssType) */
+//
+// // boolean flags
+// signed char hetatm;
+// signed char bonded;
+// signed char chemFlag;         // 0,1,2
+// signed char geom;             // cAtomInfo*
+//
+// signed char valence;
+//
+// // boolean flags
+// signed char deleteFlag;
+// signed char masked;
+//
+// signed char protekted;        // 0,1,2
+//
+// signed char protons;          /* atomic number */
+//
+// // boolean flags
+// signed char hb_donor;
+// signed char hb_acceptor;
+// signed char has_setting;      /* setting based on unique_id */
+//
+// ov_word chain;
+// Chain alt;
+// ResIdent resi;
+// SegIdent segi;
+// ResName resn;
+// AtomName name;
+// ElemName elem;                // redundant with "protons" ?
+//
+// SSType ssType;                /* blank or 'L' = turn/loop, 'H' = helix, 'S' 
= beta-strand/sheet */
+//
+// // replace with pointer?
+// float U11, U22, U33, U12, U13, U23;
+// int oldid;
+//
+
+private final static int LEN = 0;
+private final static int RESV = 1;
+private final static int CUSTOMTYPE = 2;
+private final static int PRIORITY = 3;
+
+private final static int BFACTOR = 4;
+private final static int OCCUPANCY = 5;
+private final static int VDW = 6;
+private final static int PARTIALCHARGE = 7;
+
+//private final static int SELENTRY = 8;
+private final static int COLOR = 9;
+private final static int ID = 10;
+private final static int FLAGS = 11;
+//private final static int TEMP1 = 12;
+private final static int UNIQUEID = 13;
+private final static int DISCRETESTATE = 14;
+
+private final static int ELECRADIUS = 15;
+
+private final static int RANK = 16;
+private final static int TEXTTYPE = 17;
+private final static int CUSTOM = 18;
+private final static int LABEL = 19;
+private final static int VISREP = 20;
+
+private final static int HETATM = 21;
+private final static int BONDED = 22;
+//private final static int DELETEFLAG = 23;
+private final static int MASK = 24;
+private final static int HBDONOR = 25;
+private final static int HBACCEPT = 26;
+private final static int HASSETTING = 27;
+
+private final static int FORMALCHARGE = 28;
+private final static int MMSTEREO = 29;
+private final static int CARTOON = 30;
+private final static int GEOM = 31;
+private final static int VALENCE = 32;
+private final static int PROTONS = 33;
+
+private final static int CHAIN = 34;
+private final static int SEGI = 35;
+private final static int NAME = 36;
+private final static int ELEM = 37;
+private final static int RESI = 38;
+private final static int SSTYPE = 39;
+private final static int ALTLOC = 40;
+private final static int RESN = 41;
+private final static int INSCODE = 42;
+private final static int CHEMFLAG = 43;
+private final static int PROTEKTED = 44;
+private final static int ANISOU = 45;
+
+private final static int HETMASK = 46;
+private final static int BONMASK = 47;
+private final static int MASMASK = 48;
+private final static int HBDMASK = 49;
+private final static int HBAMASK = 50;
+private final static int SETMASK = 51;
+
+
+
+private final static int[] v181 = { LEN, 120,  
+//  struct AtomInfoType_1_8_1 {
+  
+ANISOU,       0,  //  short anisou[6];
+SEGI,        -12, //  lexidx_t segi;
+CHAIN,       -16, //  lexidx_t chain;
+RESN,        -20, //  lexidx_t resn;
+NAME,        -24, //  lexidx_t name;
+TEXTTYPE,    -28, //  lexidx_t textType;
+CUSTOM,      -32, //  lexidx_t custom;
+LABEL,       -36, //  lexidx_t label;
+
+RESV,         40, //  int resv;
+CUSTOMTYPE,   44, //  int customType;
+PRIORITY,     48, //  int priority;
+BFACTOR,      52, //  float b;
+OCCUPANCY,    56, //  float q;
+VDW,          60, //  float vdw;
+PARTIALCHARGE,64, //  float partialCharge;
+COLOR,        68, //  int color;
+ID,           72, //  int id;                       // PDB ID
+
+FLAGS,        76, //  unsigned int flags;
+UNIQUEID,     80, //  int unique_id;                /* introduced in version 
0.77 */
+DISCRETESTATE,84, //  int discrete_state;           /* state+1 for atoms in 
discrete objects */
+ELECRADIUS,   88, //  float elec_radius;            /* radius for PB 
calculations */
+RANK,         92, //  int rank;
+VISREP,       96, //  int visRep;                   /* bitmask for all reps */
+
+HETATM,      100, //  bool hetatm : 1;
+BONDED,      100, //  bool bonded : 1;
+MASK,        100, //  bool masked : 1;
+HBDONOR,     100, //  bool hb_donor : 1;
+HBACCEPT,    100, //  bool hb_acceptor : 1;
+HASSETTING,  100, //  bool has_setting : 1;      /* setting based on unique_id 
*/
+
+HETMASK,    0x01, 
+BONMASK,    0x02,
+MASMASK,    0x04,
+HBDMASK,    0x08,
+HBAMASK,    0x10,
+SETMASK,    0x20,
+
+FORMALCHARGE,101, //  signed char formalCharge;     // values typically in 
range -2..+2
+CARTOON,     102, //  signed char cartoon;          /* 0 = default which is 
auto (use ssType) */
+GEOM,        103, //  signed char geom;             // cAtomInfo*
+VALENCE,     104, //  signed char valence;          // 0-4
+PROTONS,     105, //  signed char protons;          /* atomic number */
+INSCODE,     106, //  char inscode;
+
+ELEM,        107, // [5] ElemName elem;               // redundant with 
"protons" ?
+SSTYPE,      112, // [2] SSType ssType;               /* blank or 'L' = 
turn/loop, 'H' = helix, 'S' = beta-strand/sheet */
+ALTLOC,      114, // [2] Chain alt;
+MMSTEREO,    116, //  unsigned char stereo : 2;     // 0-3 Only for SDF (MOL) 
format in/out
+CHEMFLAG,    117, //  unsigned char chemFlag : 2;   // 0,1,2
+PROTEKTED,   118, //  unsigned char protekted : 2;  // 0,1,2
+// empty byte?
+};
+
   /**
    * @param pymolAtoms
    *        list of atom details
@@ -1005,34 +1337,105 @@
    * @return true if successful
    * 
    */
-  private P3 addAtom(Lst<Object> pymolAtoms, int apt, int icoord,
-                     Lst<Object> coords, Lst<Object> labelPositions,
+  private P3 addAtom(Lst<Object> pymolAtoms, int apt, 
+                     byte[] atomArray, int[] vArray, String[] lexStr,
+                     int icoord,
+                     Lst<Object> coords, float[] coordArray, 
+                     Lst<Object> labelPositions, float[] labelArray,
                      BS bsState, int iState) {
     atomMap[apt] = -1;
-    Lst<Object> a = listAt(pymolAtoms, apt);
-    int seqNo = intAt(a, 0); // may be negative
-    String chainID = stringAt(a, 1); // may be more than one char.
-    String altLoc = stringAt(a, 2);
-    String insCode = " "; //?    
-    String name = stringAt(a, 6);
-    String group3 = stringAt(a, 5);
+    String chainID, altLoc, group3, name, sym, label, ssType, resi;
+    float bfactor, occupancy, radius, partialCharge;
+    int seqNo, intReps, formalCharge, atomColor, serNo, cartoonType, flags, 
uniqueID = -1;
+    boolean isHetero, bonded;
+    float[] anisou = null;
+    BS bsReps = null;
+    if (haveBinaryArrays) {
+      int pt = apt * vArray[LEN];
+      seqNo = atomInt(atomArray, pt, vArray[RESV]);
+      chainID = atomStr(atomArray, pt, vArray[CHAIN], lexStr);
+      resi =  atomStr(atomArray, pt, vArray[RESI], lexStr);
+      group3 = atomStr(atomArray, pt, vArray[RESN], lexStr).substring(0, 3);
+      name = atomStr(atomArray, pt, vArray[NAME], lexStr);
+      sym = atomStr(atomArray, pt, vArray[ELEM], lexStr);
+      label = atomStr(atomArray, pt, vArray[LABEL], lexStr);
+      ssType = atomStr(atomArray, pt, vArray[SSTYPE], null);
+      altLoc = atomStr(atomArray, pt, vArray[ALTLOC], null);
+      byte b = atomArray[pt + vArray[INSCODE]];
+      resi = (b == 0 ? "" : "xxx" + (char) b);
+      bfactor = atomFloat(atomArray, pt, vArray[BFACTOR]);
+      occupancy = atomFloat(atomArray, pt, vArray[OCCUPANCY]);
+      radius= atomFloat(atomArray, pt, vArray[VDW]);
+      partialCharge = atomFloat(atomArray, pt, vArray[PARTIALCHARGE]);
+      formalCharge = atomArray[pt + vArray[FORMALCHARGE]];
+      if (formalCharge > 125)
+        formalCharge -= 512;
+      intReps = atomInt(atomArray, pt, vArray[VISREP]);
+      atomColor = atomInt(atomArray, pt, vArray[COLOR]);
+      serNo = atomInt(atomArray, pt, vArray[ID]);
+      cartoonType = atomInt(atomArray, pt, vArray[CARTOON]);
+      flags = atomInt(atomArray, pt, vArray[FLAGS]);
+      uniqueID = atomInt(atomArray, pt, vArray[UNIQUEID]);
+      if (uniqueID == 0)
+        uniqueID = -1;
+      anisou = new float[8];
+      for (int i = 0; i < 6; i++)
+        anisou[i] = BC.bytesToShort(atomArray, pt + vArray[ANISOU] + i * 2, 
false);
+      bonded = atomBool(atomArray, pt, vArray[BONDED], vArray[BONMASK]);
+      isHetero = atomBool(atomArray, pt, vArray[HETATM], vArray[HETMASK]);
+    } else {
+      Lst<Object> a = listAt(pymolAtoms, apt);
+      seqNo = intAt(a, 0); // may be negative
+      chainID = stringAt(a, 1); // may be more than one char.
+      altLoc = stringAt(a, 2);
+      resi = stringAt(a, 3);
+      group3 = stringAt(a, 5);
+      name = stringAt(a, 6);
+      sym = stringAt(a, 7);
+      label = stringAt(a, 9);
+      ssType = stringAt(a, 10).substring(0, 1);
+      bfactor = floatAt(a, 14);
+      occupancy = floatAt(a, 15);
+      radius = floatAt(a, 16);
+      partialCharge = floatAt(a, 17);
+      formalCharge = intAt(a, 18);
+      isHetero = (intAt(a, 19) != 0);
+      bsReps = getBsReps(listAt(a, 20));
+      intReps = (bsReps == null ? intAt(a, 20) : 0); // Pymol 1.8      
+      atomColor = intAt(a, 21);
+      serNo = intAt(a, 22);
+      cartoonType = intAt(a, 23);
+      flags = intAt(a, 24);
+      bonded = (intAt(a, 25) != 0);
+      uniqueID = (a.size() > 40 && intAt(a, 40) == 1 ? intAt(a, 32) : -1);
+      if (a.size() > 46)
+        anisou = PyMOLScene.floatsAt(a, 41, new float[8], 6);
+    }
+
+    String insCode = (resi.length() > 3 ? resi.substring(3) : " ");
+
     if (group3.length() > 3)
       group3 = group3.substring(0, 3);
     if (group3.equals(" "))
       group3 = "UNK";
-    String sym = stringAt(a, 7);
     if (sym.equals("A"))
       sym = "C";
-    boolean isHetero = (intAt(a, 19) != 0);
     int ichain = vwr.getChainID(chainID, true);
     Atom atom = processAtom(new Atom(), name, altLoc.charAt(0), group3, 
         ichain, seqNo, insCode.charAt(0), isHetero, sym);
     if (!filterPDBAtom(atom, fileAtomIndex++))
       return null;
+    float x, y, z;
     icoord *= 3;
-    float x = floatAt(coords, icoord);
-    float y = floatAt(coords, ++icoord);
-    float z = floatAt(coords, ++icoord);
+    if (haveBinaryArrays) {
+      x = coordArray[icoord];
+      y = coordArray[++icoord];
+      z = coordArray[++icoord];
+    } else {
+      x = floatAt(coords, icoord);
+      y = floatAt(coords, ++icoord);
+      z = floatAt(coords, ++icoord);
+    }
     BoxInfo.addPointXYZ(x, y, z, xyzMin, xyzMax, 0);
     if (isTrajectory && iState > 0)
       return null;
@@ -1040,8 +1443,6 @@
     if (bsState != null)
       bsState.set(ac);
 
-    String label = stringAt(a, 9);
-    String ssType = stringAt(a, 10).substring(0, 1);
     if (seqNo >= MIN_RESNO
         && (!ssType.equals(" ") || name.equals("CA") || isNucleic)) {
       BS bs = ssMapSeq.get(ssType);
@@ -1054,33 +1455,16 @@
         ssMapSeq.put(ssType, bs = new BS());
       bs.set(seqNo - MIN_RESNO);
     }
-    atom.bfactor = floatAt(a, 14);
-    atom.foccupancy = floatAt(a, 15);
-    atom.radius = floatAt(a, 16);
+    atom.bfactor = bfactor;
+    atom.foccupancy = occupancy;
+    atom.radius = radius;
     if (atom.radius == 0)
       atom.radius = 1;
-    atom.partialCharge = floatAt(a, 17);
-    int formalCharge = intAt(a, 18);
-
-    BS bsReps = getBsReps(listAt(a, 20));
-    int intReps = (bsReps == null ? intAt(a, 20) : 0); // Pymol 1.8      
-    int atomColor = intAt(a, 21);
-    int serNo = intAt(a, 22);
-    int cartoonType = intAt(a, 23);
-    int flags = intAt(a, 24);
-    boolean bonded = (intAt(a, 25) != 0);
-    
+    atom.partialCharge = partialCharge;
     // repurposing vib; leaving Z = Float.NaN to disable actual vibrations
-    
-    int uniqueID = (a.size() > 40 && intAt(a, 40) == 1 ? intAt(a, 32) : -1);
-    atom.vib = V3.new3(uniqueID, cartoonType, Float.NaN);
-    if (a.size() > 46) {
-      float[] data = PyMOLScene.floatsAt(a, 41, new float[8], 6);
-      if (data[0] != 0)
-        asc.setAnisoBorU(atom, data, 12);
-    }
-    //if (uniqueID > 0)
-      //pymolScene.setUnique(uniqueID, atom);
+    atom.vib = V3.new3(uniqueID, cartoonType, Float.NaN);    
+    if (anisou != null && anisou[0] != 0)
+      asc.setAnisoBorU(atom, anisou, 12);
     pymolScene.setAtomColor(atomColor);
     processAtom2(atom, serNo, x, y, z, formalCharge);
 
@@ -1090,8 +1474,18 @@
       pymolScene.bsNonbonded.set(ac);
     if (!label.equals(" ")) {
       pymolScene.bsLabeled.set(ac);
-      Lst<Object> labelOffset = listAt(labelPositions, apt);
-      pymolScene.addLabel(ac, uniqueID, atomColor, labelOffset, label);
+      float[] labelPos = new float[7];
+      if (labelArray != null) {
+        for (int i = 0; i < 7; i++)
+          labelPos[i] = labelArray[apt * 7  + i];
+      } else {
+        Lst<Object> labelOffset = listAt(labelPositions, apt);
+        if (labelOffset != null) {
+          for (int i = 0; i < 7; i++)
+          labelPos[i] = floatAt(labelOffset, i);
+        }
+      }
+      pymolScene.addLabel(ac, uniqueID, atomColor, labelPos, label);
     }
     if (isHidden)
       pymolScene.bsHidden.set(ac);
@@ -1108,6 +1502,29 @@
     return null;
   }
 
+  private boolean atomBool(byte[] atomArray, int pt, int offset, int mask) {
+    return ((atomArray[pt + offset] & mask) != 0);
+  }
+
+  private float atomFloat(byte[] atomArray, int pt, int offset) {
+    try {
+      return BC.bytesToFloat(atomArray, pt + offset, false);
+    } catch (Exception e) {
+      return 0;
+    }
+  }
+
+  private String atomStr(byte[] atomArray, int pt, int offset, String[] 
lexStr) {
+    if (offset < 0)
+      return  lexStr[BC.bytesToInt(atomArray, pt - offset, false)];
+    String s = getCStr(atomArray, pt + offset);
+    return (s.length() == 0 ? " " : s);
+  }
+
+  private int atomInt(byte[] atomArray, int pt, int offset) {
+    return BC.bytesToInt(atomArray, pt + offset, false);
+  }
+
   private void addBonds(Lst<Bond> bonds) {
     int n = bonds.size();
     for (int i = 0; i < n; i++) {
@@ -1326,10 +1743,20 @@
   }
 
   private static String stringAt(Lst<Object> list, int i) {
-    String s = list.get(i).toString();
-    return (s.length() == 0 ? " " : s);
+    if (!AU.isAB(list.get(i)))
+      System.out.println("??");
+    byte[] a = (byte[]) list.get(i);
+    return (a.length == 0 ? " " : bytesToString(a));
   }
 
+  static String bytesToString(Object object) {
+    try {
+      return new String((byte[]) object, "UTF-8");
+    } catch (UnsupportedEncodingException e) {
+      return object.toString();
+    }
+  }
+
   @SuppressWarnings("unchecked")
   private static Lst<Object> getMapList(Map<String, Object> map, String key) {
     return (Lst<Object>) map.get(key);

Modified: trunk/Jmol/src/org/jmol/adapter/readers/pymol/PyMOLScene.java
===================================================================
--- trunk/Jmol/src/org/jmol/adapter/readers/pymol/PyMOLScene.java       
2016-08-02 03:07:20 UTC (rev 21182)
+++ trunk/Jmol/src/org/jmol/adapter/readers/pymol/PyMOLScene.java       
2016-08-08 22:23:29 UTC (rev 21183)
@@ -920,7 +920,7 @@
   }
 
   void addLabel(int atomIndex, int uniqueID, int atomColor,
-                Lst<Object> labelOffset, String label) {
+                float[] labelPos, String label) {
     int icolor = (int) getUniqueFloatDef(uniqueID, PyMOL.label_color,
         labelColor);
     if (icolor == PyMOL.COLOR_BACK || icolor == PyMOL.COLOR_FRONT) {
@@ -928,17 +928,13 @@
     } else if (icolor < 0) {
       icolor = atomColor;
     }
-    float[] labelPos = new float[7];
-    if (labelOffset == null) {
+    if (labelPos == null) {
       P3 offset = getUniquePoint(uniqueID, PyMOL.label_position, null);
       if (offset == null)
         offset = labelPosition;
       else
         offset.add(labelPosition);
       setLabelPosition(offset, labelPos);
-    } else {
-      for (int i = 0; i < 7; i++)
-        labelPos[i] = floatAt(labelOffset, i);
     }
     labels.put(Integer.valueOf(atomIndex), newTextLabel(label, labelPos,
         icolor, labelFontId, labelSize));
@@ -1693,7 +1689,7 @@
     for (int i = list.size(); --i >= 0;) {
       Lst<Object> item = PyMOLScene.listAt(list, i);
       if (item != null && item.size() > 0)
-        map.put((String) item.get(0), item);
+        map.put(PyMOLReader.bytesToString(item.get(0)), item);
     }
     return map;
   }

Modified: trunk/Jmol/src/org/jmol/viewer/Jmol.properties
===================================================================
--- trunk/Jmol/src/org/jmol/viewer/Jmol.properties      2016-08-02 03:07:20 UTC 
(rev 21182)
+++ trunk/Jmol/src/org/jmol/viewer/Jmol.properties      2016-08-08 22:23:29 UTC 
(rev 21183)
@@ -47,8 +47,13 @@
  -- sets the echo offset to a specific screen pixel offset
  -- TODO not saved in state
  
-Jmol.___JmolVersion="14.7.1_2016.07.29"
+ 
+Jmol.___JmolVersion="14.7.1_2016.08.08"
 
+new feature: Jmol reads PyMOL 1.8 PSE files with "set dump_binary, 1"
+
+JmolVersion="14.7.1_2016.07.29"
+
 bug fix: COMPARE command can fail if an atom has no bonds
 
 JmolVersion="14.7.1_2016.07.24"

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