1 /* $RCSfile$
2  * $Author: hansonr $
3  * $Date: 2007-03-30 11:40:16 -0500 (Fri, 30 Mar 2007) $
4  * $Revision: 7273 $
5  *
6  * Copyright (C) 2007 Miguel, Bob, Jmol Development
7  *
8  * Contact: hansonr@stolaf.edu
9  *
10  *  This library is free software; you can redistribute it and/or
11  *  modify it under the terms of the GNU Lesser General Public
12  *  License as published by the Free Software Foundation; either
13  *  version 2.1 of the License, or (at your option) any later version.
14  *
15  *  This library is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  *  Lesser General Public License for more details.
19  *
20  *  You should have received a copy of the GNU Lesser General Public
21  *  License along with this library; if not, write to the Free Software
22  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
23  */
24 
25 /*
26 
27  * The JVXL file format
28  * --------------------
29  *
30  * as of 3/29/07 this code is COMPLETELY untested. It was hacked out of the
31  * Jmol code, so there is probably more here than is needed.
32  *
33  *
34  *
35  * see http://www.stolaf.edu/academics/chemapps/jmol/docs/misc/JVXL-format.pdf
36  *
37  * The JVXL (Jmol VoXeL) format is a file format specifically designed
38  * to encode an isosurface or planar slice through a set of 3D scalar values
39  * in lieu of a that set. A JVXL file can contain coordinates, and in fact
40  * it must contain at least one coordinate, but additional coordinates are
41  * optional. The file can contain any finite number of encoded surfaces.
42  * However, the compression of 300-500:1 is based on the reduction of the
43  * data to a SINGLE surface.
44  *
45  *
46  * The original Marching Cubes code was written by Miguel Howard in 2005.
47  * The classes Parser, ArrayUtil, and TextFormat are condensed versions
48  * of the classes found in org.jmol.util.
49  *
50  * All code relating to JVXL format is copyrighted 2006/2007 and invented by
51  * Robert M. Hanson,
52  * Professor of Chemistry,
53  * St. Olaf College,
54  * 1520 St. Olaf Ave.
55  * Northfield, MN. 55057.
56  *
57  * Implementations of the JVXL format should reference
58  * "Robert M. Hanson, St. Olaf College" and the opensource Jmol project.
59  *
60  *
61  * implementing marching squares; see
62  * http://www.secam.ex.ac.uk/teaching/ug/studyres/COM3404/COM3404-2006-Lecture15.pdf
63  *
64  * lines through coordinates are identical to CUBE files
65  * after that, we have a line that starts with a negative number to indicate this
66  * is a JVXL file:
67  *
68  * line1:  (int)-nSurfaces  (int)edgeFractionBase (int)edgeFractionRange
69  * (nSurface lines): (float)cutoff (int)nBytesData (int)nBytesFractions
70  *
71  * definition1
72  * edgedata1
73  * fractions1
74  * colordata1
75  * ....
76  * definition2
77  * edgedata2
78  * fractions2
79  * colordata2
80  * ....
81  *
82  * definitions: a line with detail about what sort of compression follows
83  *
84  * edgedata: a list of the count of vertices ouside and inside the cutoff, whatever
85  * that may be, ordered by nested for loops for(x){for(y){for(z)}}}.
86  *
87  * nOutside nInside nOutside nInside...
88  *
89  * fractions: an ascii list of characters represting the fraction of distance each
90  * encountered surface point is along each voxel cube edge found to straddle the
91  * surface. The order written is dictated by the reader algorithm and is not trivial
92  * to describe. Each ascii character is constructed by taking a base character and
93  * adding onto it the fraction times a range. This gives a character that can be
94  * quoted EXCEPT for backslash, which MAY be substituted for by '!'. Jmol uses the
95  * range # - | (35 - 124), reserving ! and } for special meanings.
96  *
97  * colordata: same deal here, but with possibility of "double precision" using two bytes.
98  *
99  *
100  *
101  * THIS READER
102  * -----------
103  *
104  * This is a first attempt at a generic JVXL file reader and writer class.
105  * It is an extraction of Jmol org.jmol.viewer.Isosurface.Java and related pieces.
106  *
107  * The goal of the reader is to be able to read CUBE-like data and
108  * convert that data to JVXL file data.
109  *
110  *
111  */
112 
113 package org.jmol.jvxl.readers;
114 
115 
116 import javajs.util.Lst;
117 import java.util.Hashtable;
118 
119 import java.util.Map;
120 
121 import org.jmol.atomdata.RadiusData;
122 import javajs.util.BS;
123 import org.jmol.jvxl.data.VolumeData;
124 import org.jmol.util.ColorEncoder;
125 import org.jmol.util.ContactPair;
126 import org.jmol.util.Escape;
127 import org.jmol.util.Logger;
128 
129 import javajs.util.A4;
130 import javajs.util.M3;
131 import javajs.util.M4;
132 import javajs.util.P3;
133 import javajs.util.P4;
134 import javajs.util.PT;
135 import javajs.util.SB;
136 import javajs.util.V3;
137 
138 import org.jmol.viewer.JC;
139 
140 public class Parameters {
141 
142   public final static int STATE_UNINITIALIZED = 0;
143   public final static int STATE_INITIALIZED = 1;
144   public final static int STATE_DATA_READ = 2;
145   public final static int STATE_DATA_COLORED = 3;
146 
147 
148   public int state = STATE_UNINITIALIZED;
149 
150   public int testFlags = 0;
151   boolean logMessages = false;
152   boolean logCompression = false;
153   boolean logCube = false;
154   public boolean isSilent = false;
155 
156   float assocCutoff = 0.3f; // fraction along the edge to use as a cutoff for averaging of normals
157 
158   final static int NO_ANISOTROPY = 1 << 5;
159   final static int IS_SILENT = 1 << 6;
160   final public static int IS_SOLVENTTYPE = 1 << 7;
161   final static int HAS_MAXGRID = 1 << 8;
162   final static int IS_POINTMAPPABLE = 1 << 9;
163   final static int IS_SLABBABLE = 1 << 10;
164 
165   public int dataType;
166   int surfaceType;
167 
168   final static int SURFACE_NONE = 0;
169 
170   //getSurface only:
171   final static int SURFACE_SPHERE = 1 | IS_SILENT;
172   final static int SURFACE_ELLIPSOID2 = 2 | IS_SILENT;
173   final static int SURFACE_ELLIPSOID3 = 3 | IS_SILENT;
174   final static int SURFACE_LOBE = 4 | IS_SILENT;
175   final static int SURFACE_LCAOCARTOON = 5 | IS_SILENT;
176   final static public int SURFACE_LONEPAIR = 6 | IS_SILENT;
177   final static public int SURFACE_RADICAL = 7 | IS_SILENT;
178   final static int SURFACE_FUNCTIONXY = 8;
179   final static int SURFACE_FUNCTIONXYZ = 9;
180   final static int SURFACE_GEODESIC = 10 | IS_SILENT;
181 
182   // getSurface or mapColor:
183   final static int SURFACE_SOLVENT = 11 | IS_SOLVENTTYPE | NO_ANISOTROPY | IS_SLABBABLE ;
184   final static int SURFACE_SASURFACE = 12 | IS_SOLVENTTYPE | NO_ANISOTROPY | IS_SLABBABLE;
185   final static int SURFACE_MOLECULARORBITAL = 13 | NO_ANISOTROPY | HAS_MAXGRID | IS_POINTMAPPABLE | IS_SLABBABLE;
186   final static int SURFACE_ATOMICORBITAL = 14 | HAS_MAXGRID | IS_SLABBABLE;
187   final static int SURFACE_MEP = 16 | NO_ANISOTROPY | HAS_MAXGRID | IS_SLABBABLE;
188   final static int SURFACE_MLP = 17 | NO_ANISOTROPY | HAS_MAXGRID | IS_SLABBABLE;
189   final static int SURFACE_MOLECULAR = 19 | IS_SOLVENTTYPE | NO_ANISOTROPY | IS_SLABBABLE;
190   final static int SURFACE_NCI = 20 | NO_ANISOTROPY | HAS_MAXGRID | IS_POINTMAPPABLE | IS_SLABBABLE;
191   final static int SURFACE_INTERSECT_ATOM = 21 | NO_ANISOTROPY | HAS_MAXGRID | IS_SLABBABLE;
192   final static int SURFACE_INTERSECT_FILE = 22 | NO_ANISOTROPY | HAS_MAXGRID | IS_SLABBABLE;
193 
194   // mapColor only:
195 
196   final static int SURFACE_NOMAP = 23 | IS_SOLVENTTYPE | NO_ANISOTROPY | IS_SLABBABLE;
197   final static int SURFACE_PROPERTY = 24 | IS_SOLVENTTYPE | NO_ANISOTROPY | IS_SLABBABLE;
198 
initialize()199   void initialize() {
200     addHydrogens = false;
201     allowVolumeRender = true;
202     atomRadiusData = null;
203     atomIndex = -1;
204     blockCubeData = false; // Gaussian standard, but we allow for multiple surfaces one per data block
205     boundingBox = null;
206     bsExcluded = new BS[4];
207     bsIgnore = null;
208     bsSelected = null;
209     bsSolvent = null;
210     calculationType = "";
211     center = new P3();
212     resetForMapping(true);
213     colorBySign = colorByPhase = colorBySets = false;
214     colorEncoder = null;
215     colorNeg = defaultColorNegative;
216     colorNegLCAO = defaultColorNegativeLCAO;
217     colorPos = defaultColorPositive;
218     colorPosLCAO = defaultColorPositiveLCAO;
219     colorRgb = Integer.MIN_VALUE;
220     colorSchemeTranslucent = false;
221     contactPair = null;
222     contourIncrements = null;
223     contoursDiscrete = null;
224     contourColixes = null;
225     contourFromZero = true;
226     cutoff = Float.MAX_VALUE;
227     cutoffAutomatic = true;
228     dataXYReversed = false;
229     distance = Float.MAX_VALUE;
230     doFullMolecular = false;
231     envelopeRadius = 10f;
232     extendGrid = 0;
233     fileIndex = 1;
234     readAllData = true;
235     fileName = "";
236     filesData = null;
237     fullyLit = false;
238     functionInfo = null;
239     iAddGridPoints = false;
240     insideOut = false;
241     isAngstroms = false;
242     isBicolorMap = isCutoffAbsolute = isPositiveOnly = false;
243     isCavity = false;
244     isColorReversed = false;
245     isModelConnected = false;
246     isSquared = false;
247     isSquaredLinear = false;
248     isContoured = false;
249     isEccentric = false;
250     isMapped = false;
251     isPeriodic = false;
252     isSilent = false;
253     logCube = logCompression = false;
254     logMessages = Logger.debugging;
255     mapLattice = null;
256     mep_calcType = -1;
257     minSet = 0;
258     modelIndex = -1;
259     modelInvRotation = null;
260     nContours = 0;
261     pocket = null;
262     pointSize = Float.NaN;
263     probes = null;
264     probeValues = null;
265     propertyDistanceMax = Integer.MAX_VALUE;
266     propertySmoothing = false;
267     propertySmoothingPower = 4;
268     rangeDefined = false;
269     rangeAll = false;
270     rangeSelected = false;
271     resolution = Float.MAX_VALUE;
272     scale = Float.NaN;
273     scale3d = 0;
274     sigma = Float.NaN;
275     slabInfo = null;
276     solventExtendedAtomRadius = 0;
277     state = STATE_INITIALIZED;
278     testFlags = 0;
279     thePlane = null;
280     theProperty = null;
281     thisContour = -1;
282     title = null;
283     usePropertyForColorRange = true; // except for MEP and MLP
284     vertexSource = null;
285   }
286 
287   /**
288    * reset some parameters at the "MAP" keyword or initially
289    *
290    * @param haveSurface
291    */
resetForMapping(boolean haveSurface)292   public void resetForMapping(boolean haveSurface) {
293     if (!haveSurface)
294       state = Parameters.STATE_DATA_READ;
295     center.x = Float.NaN;
296     colorDensity = false;
297     func = null;
298     intersection = null;
299     isAnisotropic = false;
300     isMapped = true;
301     mappedDataMin = Float.MAX_VALUE;
302     origin = null;
303     parameters = null;
304     points = null;
305     qmOrbitalType = QM_TYPE_UNKNOWN;
306     steps = null;
307     volumeData = null;
308   }
309 
310   String calculationType = "";
311 
312   //solvent/molecular-related:
313   public RadiusData atomRadiusData;
314   boolean addHydrogens;
315   float solventRadius;
316   float solventExtendedAtomRadius;
317   boolean propertySmoothing;
318   int propertySmoothingPower = 4;
319   float envelopeRadius;
320   float cavityRadius;
321   boolean isCavity;
322   Boolean pocket; //three states: TRUE, FALSE, and NULL
323   int minSet;
324   public Lst<Object[]> slabInfo;
325   float slabPlaneOffset = Float.NaN;
326 
327   float[] theProperty;
328   ///// solvent-accessible, solvent-excluded surface //////
329 
330   float solvent_ptsPerAngstrom = 4f;
331   int solvent_gridMax = 60;
332 
333   float plane_ptsPerAngstrom = 4f;
334   int plane_gridMax = 81;
335 
336   //defaults
337 
338   final static float ANGSTROMS_PER_BOHR = JC.ANGSTROMS_PER_BOHR;
339   final static int defaultEdgeFractionBase = 35; //#$%.......
340   final static int defaultEdgeFractionRange = 90;
341   final static int defaultColorFractionBase = 35;
342   final static int defaultColorFractionRange = 90;
343   final static float defaultMappedDataMin = 0f;
344   final static float defaultMappedDataMax = 1.0f;
345   final static float defaultCutoff = 0.02f;
346   final static float defaultOrbitalCutoff = 0.04f;
347   final static float defaultLobeCutoff = 0.14f;
348   final static float defaultOrbitalCutoffOld = 0.14f;
349   public final static float defaultQMOrbitalCutoff = 0.050f; // WebMO
350   final static float defaultQMElectronDensityCutoff = 0.010f;
351   final static int defaultContourCount = 11; //odd is better
352   final static int nContourMax = 100;
353   final static int defaultColorNegative = 0xFFFF0000; //red
354   final static int defaultColorPositive =  0xFF0000FF; //blue
355   final static int defaultColorNegativeLCAO = 0xFF800080; //purple
356   final static int defaultColorPositiveLCAO = 0xFFFFA500; //orange
357   final static float defaultSolventRadius = 1.2f;
358   final static float defaultMepCutoff = 0.1f;
359   final static float defaultMepMin = -0.1f;
360   final static float defaultMepMax = 0.1f;
361 
362   //color
363 
364   boolean colorBySign;
365   boolean colorByPhase;
366   boolean colorBySets;
367   public int colorRgb;
368   public int colorNeg;
369   public int colorPos;
370   int colorPosLCAO;
371   int colorNegLCAO;
372   int colorPhase;
373   public boolean colorDensity;
374 
375 
376   //special effects
377   public boolean iAddGridPoints;
378 
379   /////////////////////////////
380 
381   int atomIndex; //for lcaoCartoons
382 
383   boolean isAngstroms;
384   float scale;
385   public float scale3d;
386 
387   float[] anisotropy = new float[3];
388   boolean isAnisotropic;
389 
setAnisotropy(P3 pt)390   void setAnisotropy(P3 pt) {
391       anisotropy[0] = pt.x;
392       anisotropy[1] = pt.y;
393       anisotropy[2] = pt.z;
394       isAnisotropic = true;
395       if (Float.isNaN(center.x))
396         center.set(0, 0, 0);
397   }
398 
399   M3 eccentricityMatrix;
400   M3 eccentricityMatrixInverse;
401   boolean isEccentric;
402   float eccentricityScale;
403   float eccentricityRatio;
404   float[] aniosU;
405 
setEccentricity(P4 info)406   void setEccentricity(P4 info) {
407     /*
408      * {cx cy cz fab/c}
409      *
410      * 1) set ecc = {cx cy cz}
411      * 2) normalize
412      * 3) add z and normalize again. This gives the vector about which a 180-degree
413      *    rotation turns {0 0 1} into ecc.
414      *
415      */
416     V3 ecc = V3.new3(info.x, info.y, info.z);
417     float c = (scale > 0 ? scale : info.w < 0 ? 1f : ecc.length());
418     float fab_c = Math.abs(info.w);
419     ecc.normalize();
420     V3 z = V3.new3(0, 0, 1);
421     ecc.add(z);
422     ecc.normalize();
423     if (Float.isNaN(ecc.x)) // was exactly {0 0 -1} -- just rotate about x
424       ecc.set(1, 0, 0);
425     eccentricityMatrixInverse = new M3();
426     eccentricityMatrixInverse.invertM(eccentricityMatrix = new M3().setAA(A4.newVA(ecc, (float) Math.PI)));
427     isEccentric = isAnisotropic = true;
428     eccentricityScale = c;
429     eccentricityRatio = fab_c;
430     if (fab_c > 1)
431       eccentricityScale *= fab_c;
432     anisotropy[0] = fab_c * c;
433     anisotropy[1] = fab_c * c;
434     anisotropy[2] = c;
435     if (Float.isNaN(center.x))
436       center.set(0, 0, 0);
437   }
438 
setPlane(P4 plane)439   void setPlane(P4 plane) {
440     thePlane = plane;
441     if (thePlane.x == 0 && thePlane.y == 0
442         && thePlane.z == 0)
443       thePlane.z = 1; //{0 0 0 w} becomes {0 0 1 w}
444     isContoured = true;
445   }
446 
setSphere(float radius, boolean isGeodesic)447   void setSphere(float radius, boolean isGeodesic) {
448     dataType = (isGeodesic ? SURFACE_GEODESIC : SURFACE_SPHERE);
449     distance = radius;
450     setEccentricity(P4.new4(0, 0, 1, 1));
451     cutoff = PT.FLOAT_MIN_SAFE;
452     isCutoffAbsolute = false;
453     isSilent = !logMessages;
454     script = getScriptParams() + " SPHERE " + radius + ";";
455   }
456 
setEllipsoidP4(P4 v)457   void setEllipsoidP4(P4 v) {
458     dataType = SURFACE_ELLIPSOID2;
459     distance = 1f;
460     setEccentricity(v);
461     cutoff = PT.FLOAT_MIN_SAFE;
462     isCutoffAbsolute = false;
463     isSilent = !logMessages;
464     //script = " center " + Escape.escape(center)
465       //  + (Float.isNaN(scale) ? "" : " scale " + scale) + " ELLIPSOID {" + v.x
466         //+ " " + v.y + " " + v.z + " " + v.w + "};";
467   }
468 
469   float[] anisoB;
setEllipsoidAF(float[] bList)470   public void setEllipsoidAF(float[] bList) {
471     anisoB = bList;
472     //for (int i = 0; i < 6; i++)System.out.print(bList[i] + " ");System.out.println( " in Parameters setEllipsoid" + center);
473     dataType = SURFACE_ELLIPSOID3;
474     distance = 0.3f * (Float.isNaN(scale) ? 1f : scale);
475     cutoff = PT.FLOAT_MIN_SAFE;
476     isCutoffAbsolute = false;
477     isSilent = !logMessages;
478     if (Float.isNaN(center.x))
479       center.set(0, 0, 0);
480     if (resolution == Float.MAX_VALUE)
481       resolution = 6;
482     //script = " center " + Escape.escape(center)
483       //  + (Float.isNaN(scale) ? "" : " scale " + scale) + " ELLIPSOID {" + bList[0]
484         //+ " " + bList[1] + " " + bList[2] + " " + bList[3] + " " + bList[4] + " " + bList[5] + "};";
485   }
486 
setLobe(P4 v)487   void setLobe(P4 v) {
488     dataType = SURFACE_LOBE;
489     setEccentricity(v);
490     if (cutoff == Float.MAX_VALUE) {
491       cutoff = defaultLobeCutoff;
492       if (isSquared)
493         cutoff = cutoff * cutoff;
494     }
495     isSilent = !logMessages;
496     script = getScriptParams() + " LOBE {" + v.x + " "
497         + v.y + " " + v.z + " " + v.w + "};";
498   }
499 
getScriptParams()500   private String getScriptParams() {
501     return " center "
502         + Escape.eP(center) + (Float.isNaN(scale) ? "" : " scale " + scale);
503   }
504 
setLp(P4 v)505   void setLp(P4 v) {
506     dataType = SURFACE_LONEPAIR;
507     setEccentricity(v);
508     if (cutoff == Float.MAX_VALUE) {
509       cutoff = defaultLobeCutoff;
510       if (isSquared)
511         cutoff = cutoff * cutoff;
512     }
513     isSilent = !logMessages;
514     script = " center " + Escape.eP(center)
515         + (Float.isNaN(scale) ? "" : " scale " + scale) + " LP {" + v.x + " "
516         + v.y + " " + v.z + " " + v.w + "};";
517   }
518 
setRadical(P4 v)519   void setRadical(P4 v) {
520     dataType = SURFACE_RADICAL;
521     setEccentricity(v);
522     if (cutoff == Float.MAX_VALUE) {
523       cutoff = defaultLobeCutoff;
524       if (isSquared)
525         cutoff = cutoff * cutoff;
526     }
527     isSilent = !logMessages;
528     script = " center " + Escape.eP(center)
529         + (Float.isNaN(scale) ? "" : " scale " + scale) + " RAD {" + v.x + " "
530         + v.y + " " + v.z + " " + v.w + "};";
531   }
532 
533   String lcaoType;
534 
setLcao(String type, int colorPtr)535   void setLcao(String type, int colorPtr) {
536     lcaoType = type;
537     if (colorPtr == 1)
538       colorPosLCAO = colorNegLCAO;
539     isSilent = !logMessages;
540   }
541 
setSolvent(String propertyName, float radius)542   void setSolvent(String propertyName, float radius) {
543     isEccentric = isAnisotropic = false;
544     //anisotropy[0] = anisotropy[1] = anisotropy[2] = 1f;
545     solventRadius = Math.abs(radius);
546     dataType = (intersection != null ? SURFACE_INTERSECT_ATOM
547         : "nomap" == propertyName ? SURFACE_NOMAP
548             : "molecular" == propertyName ? SURFACE_MOLECULAR
549                 : "sasurface" == propertyName || solventRadius == 0f ? SURFACE_SASURFACE
550                     : SURFACE_SOLVENT);
551 
552     if (state < Parameters.STATE_DATA_READ
553         && (cutoffAutomatic || !colorDensity)
554         && (intersection == null || cutoff == Float.MAX_VALUE))
555       cutoff = 0.0f;
556 
557     switch (dataType) {
558     case Parameters.SURFACE_INTERSECT_ATOM:
559       calculationType = "VDW intersection";
560       break;
561     case Parameters.SURFACE_NOMAP:
562       calculationType = "unmapped plane";
563       break;
564     case Parameters.SURFACE_MOLECULAR:
565       calculationType = "molecular surface with radius " + solventRadius;
566       if (minSet == 0)
567         minSet = 50;
568       break;
569     case Parameters.SURFACE_SOLVENT:
570       calculationType = "solvent-excluded surface with radius " + solventRadius;
571       if (minSet == 0)
572         minSet = 50;
573       break;
574     case Parameters.SURFACE_SASURFACE:
575       calculationType = "solvent-accessible surface with radius "
576           + solventRadius;
577       if (minSet == 0)
578         minSet = 50;
579       break;
580     }
581 
582     switch (dataType) {
583     case SURFACE_NOMAP:
584       solventExtendedAtomRadius = solventRadius;
585       solventRadius = 0f;
586       isContoured = false;
587       break;
588     case SURFACE_MOLECULAR:
589       solventExtendedAtomRadius = 0f;
590       break;
591     case SURFACE_SOLVENT:
592       solventExtendedAtomRadius = 0f;
593       if (bsIgnore == null)
594         bsIgnore = bsSolvent;
595       else if (bsSolvent != null)
596         bsIgnore.or(bsSolvent);
597       break;
598     case SURFACE_SASURFACE:
599       solventExtendedAtomRadius = solventRadius;
600       solventRadius = 0f;
601       if (bsIgnore == null)
602         bsIgnore = bsSolvent;
603       else if (bsSolvent != null)
604         bsIgnore.or(bsSolvent);
605       break;
606     }
607   }
608 
609   public Lst<Object> functionInfo;
610 
setFunctionXY(Lst<Object> value)611   void setFunctionXY(Lst<Object> value) {
612     dataType = SURFACE_FUNCTIONXY;
613     functionInfo = value;
614     cutoff = PT.FLOAT_MIN_SAFE;
615     isEccentric = isAnisotropic = false;
616   }
617 
setFunctionXYZ(Lst<Object> value)618   void setFunctionXYZ(Lst<Object> value) {
619     dataType = SURFACE_FUNCTIONXYZ;
620     functionInfo = value;
621     if (cutoff == Float.MAX_VALUE)
622       cutoff = PT.FLOAT_MIN_SAFE;
623     isEccentric = isAnisotropic = false;
624   }
625 
626   int psi_n = 2;
627   int psi_l = 1;
628   int psi_m = 1;
629   float psi_Znuc = 1; // hydrogen
630   float psi_ptsPerAngstrom = 5f;
631   public int psi_monteCarloCount = 0;
632 
setAtomicOrbital(float[] nlmZprs)633   boolean setAtomicOrbital(float[] nlmZprs) {
634     dataType = SURFACE_ATOMICORBITAL;
635     setEccentricity(P4.new4(0, 0, 1, 1));
636     psi_n = (int) nlmZprs[0];
637     psi_l = (int) nlmZprs[1];
638     psi_m = (int) nlmZprs[2];
639     psi_Znuc = nlmZprs[3];
640     psi_monteCarloCount = (int) nlmZprs[4];
641     distance = nlmZprs[5];
642     if (distance != 0 || thePlane != null)
643       allowVolumeRender = false;
644     randomSeed = (int) nlmZprs[6];
645     psi_ptsPerAngstrom = 10;
646     // quantum rule is abs(m) <= l < n
647     if (cutoff == Float.MAX_VALUE || cutoff == defaultOrbitalCutoffOld) {
648       cutoff = (psi_monteCarloCount > 0 ? 0 : defaultOrbitalCutoff);
649       if (isSquared)
650         cutoff = cutoff * cutoff;
651     }
652     isCutoffAbsolute = true;
653     if (state < STATE_DATA_READ && thePlane == null && colorBySign)
654       isBicolorMap = true;
655     return (psi_Znuc > 0 && Math.abs(psi_m) <= psi_l && psi_l < psi_n);
656   }
657 
658   public final static int MEP_MAX_GRID = 40;
659   int mep_gridMax = MEP_MAX_GRID;
660   float mep_ptsPerAngstrom = 3f;
661   float mep_marginAngstroms = 1f; // may have to adjust this
662   public int mep_calcType = -1;
663 
setMep(float[] charges, boolean isMLP)664   void setMep(float[] charges, boolean isMLP) {
665     dataType = (isMLP ? SURFACE_MLP : SURFACE_MEP);
666     theProperty = charges;
667     usePropertyForColorRange = false;
668     isEccentric = isAnisotropic = false;
669     if (cutoff == Float.MAX_VALUE) {
670       cutoff = defaultMepCutoff;
671       if (isSquared)
672         cutoff = cutoff * cutoff;
673     }
674     isCutoffAbsolute = (cutoff > 0 && !isPositiveOnly);
675     contourFromZero = false; // fills out the plane
676     //colorBySign = false;
677     //isBicolorMap = false;
678     if (state >= STATE_DATA_READ || thePlane != null) {
679       if (!rangeDefined && !rangeAll) {
680         valueMappedToRed = defaultMepMin;
681         valueMappedToBlue = defaultMepMax;
682         rangeDefined = true;
683       }
684     } else {
685       colorBySign = true;
686       //colorByPhase = true;
687       //colorPhase = 0;
688       isBicolorMap = true;
689     }
690   }
691 
692   int qmOrbitalType;
693   int qmOrbitalCount;
694 
695   final static int QM_TYPE_UNKNOWN = 0;
696   final static int QM_TYPE_GAUSSIAN = 1;
697   final static int QM_TYPE_SLATER = 2;
698   final static int QM_TYPE_NCI_PRO = 3;
699   final static int QM_TYPE_NCI_SCF = 4;
700   final static int QM_TYPE_VOLUME_DATA = 5;
701 
702   public Map<String, Object> moData;
703   public final static int MO_MAX_GRID = 80;
704   int qm_gridMax = MO_MAX_GRID;
705   float qm_ptsPerAngstrom = 10f;
706   float qm_marginAngstroms = 1f; // may have to adjust this
707   int qm_nAtoms;
708   int qm_moNumber = Integer.MAX_VALUE;
709   float[] qm_moLinearCombination = null;
710 
setNci(boolean isPromolecular)711   void setNci(boolean isPromolecular) {
712     fullyLit = true;
713     qm_gridMax = 200;
714     if (isPromolecular)
715       dataType = SURFACE_NCI;
716     qm_marginAngstroms = 2f;
717     qmOrbitalType = (isPromolecular ? QM_TYPE_NCI_PRO : QM_TYPE_NCI_SCF);
718 
719     if (isPromolecular) {
720       if (parameters == null || parameters.length < 2)
721         parameters = new float[] { cutoff, 2 }; // default intermolecular
722     }
723 
724     if (cutoff == Float.MAX_VALUE || cutoff == 0)
725       cutoff = 0.3f;
726     if (isSquared)
727       cutoff *= cutoff;
728 
729     if (title == null)
730       title = new String[0];
731     moData = new Hashtable<String, Object>();
732   }
733 
734   @SuppressWarnings("unchecked")
setMO(int iMo, float[] linearCombination)735   void setMO(int iMo, float[] linearCombination) {
736     isModelConnected = true;
737     qm_moLinearCombination = linearCombination;
738     qm_moNumber = (linearCombination == null ? Math.abs(iMo) : (int) linearCombination[1]);
739     qmOrbitalType = (moData.containsKey("haveVolumeData") ? QM_TYPE_VOLUME_DATA
740         : moData.containsKey("gaussians") ? QM_TYPE_GAUSSIAN
741         : moData.containsKey("slaters") ? QM_TYPE_SLATER : QM_TYPE_UNKNOWN);
742     boolean isElectronDensity = (iMo <= 0 && linearCombination == null);
743     if (qmOrbitalType == QM_TYPE_UNKNOWN) {
744       //TODO     value = moData; // must be generic surface info
745       Logger
746           .error("MO ERROR: No basis functions found in file for MO calculation. (GAUSSIAN 'gfprint' keyword may be missing?)");
747       title = new String[] {"no basis functions found in file"};
748     } else {
749       Lst<Object> mos = (Lst<Object>) moData.get("mos");
750       qmOrbitalCount = mos.size();
751       calculationType = (String) moData.get("calculationType");
752       calculationType = "Molecular orbital #" + qm_moNumber + "/"
753           + qmOrbitalCount + " "
754           + (calculationType == null ? "" : calculationType);
755       if (!isElectronDensity) {
756         // qm_moNumber < 0 means this is an RHF electron density calculation
757         // through orbital -qm_moNumber
758         if (title == null) {
759           title = new String[5];
760           title[0] = "%F";
761           title[1] = "Model %M  MO %I/%N %T";
762           title[2] = "?Energy = %E %U";
763           title[3] = "?Symmetry = %S";
764           title[4] = "?Occupancy = %O";
765         }
766       }
767     }
768     dataType = SURFACE_MOLECULARORBITAL;
769     //  colorBySign = false;
770     //  isBicolorMap = false;
771     if (cutoff == Float.MAX_VALUE) {
772       cutoff = (isElectronDensity ? defaultQMElectronDensityCutoff
773           : defaultQMOrbitalCutoff);
774     }
775     if (isSquared || isSquaredLinear)
776       cutoff = cutoff * cutoff;// * cutoff * cutoff;
777     isEccentric = isAnisotropic = false;
778     isCutoffAbsolute = (cutoff > 0 && !isPositiveOnly);
779     if (state >= STATE_DATA_READ || thePlane != null)
780       return;
781     colorBySign = true;
782     if (colorByPhase && colorPhase == 0)
783       colorByPhase = false;
784     isBicolorMap = true;
785   }
786 
787   P3 center, point;
788   float distance;
789   public boolean allowVolumeRender;
790 
791   public String script;
792 
793   public BS bsSelected;
794   public BS bsIgnore;
795   public BS bsSolvent;
796 
797   public Object func;
798 
799   public String[] title;
800   boolean blockCubeData;
801   boolean readAllData;
802   int fileIndex = -1; //one-based, although efvet reader uses 0 for "indicated color"
803   public String fileName;
804   public int modelIndex = -1; // zero-based
805   public M4 modelInvRotation = null; // MO calculations must be run using the ORIGINAL atom positions
806   public boolean isXLowToHigh;
807 
808   boolean insideOut;
809   boolean dataXYReversed;
810   public float cutoff = Float.MAX_VALUE;
811   public float sigma = Float.MAX_VALUE; // for MrcReader
812   boolean cutoffAutomatic = true;
813   public boolean isCutoffAbsolute;
814   public boolean isPositiveOnly;
815 
816   boolean rangeAll;
817   boolean rangeSelected;
818   public boolean rangeDefined;
819   float valueMappedToRed, valueMappedToBlue;
820   float mappedDataMin;
821   float mappedDataMax;
822   boolean isColorReversed;
823   public boolean isBicolorMap;
824   public boolean isSquared;
825   public boolean isSquaredLinear;
826 
827   public P4 thePlane;
828   public boolean isContoured;
829 
830   int nContours;
831   int thisContour;
832   boolean contourFromZero;
833   float[] parameters; // additional parameters
834 
835   public float resolution;
836   int downsampleFactor;
837   int maxSet;
838   public float[] contoursDiscrete;
839   public short[] contourColixes;
840   P3 contourIncrements;
841   public P3[] boundingBox;
842   public BS[] bsExcluded;
843   public int contourType;
844   public boolean colorSchemeTranslucent;
845   public ColorEncoder colorEncoder;
846   public boolean usePropertyForColorRange = true;
847   public boolean isPeriodic;
848   public boolean doFullMolecular;
849   public float propertyDistanceMax = Integer.MAX_VALUE;
850   public int randomSeed;
851   public boolean fullyLit;
852   public int[] vertexSource;
853   public BS[] intersection;
854   public P3 origin;
855   public P3 steps;
856   public P3 points;
857   public VolumeData volumeData; // can be set by Contact or MO reader
858   public ContactPair contactPair;
859   public P3 mapLattice;
860   public float extendGrid;
861   public boolean isMapped;
862   public boolean showTiming;
863   public float pointSize;
864   public P3[] probes;
865   public boolean isModelConnected;
866   public BS surfaceAtoms;
867   public Object[] filesData; // originally [ String[] names, float[] factors ]
868   public float[] probeValues;
869   public SB sbOut;
870 
setMapRanges(SurfaceReader surfaceReader, boolean haveData)871   void setMapRanges(SurfaceReader surfaceReader, boolean haveData) {
872     if (!colorDensity)
873       if (colorByPhase || colorBySign || (thePlane != null || isBicolorMap) && !isContoured) {
874       mappedDataMin = -1;
875       mappedDataMax = 1;
876     }
877     if (mappedDataMin == Float.MAX_VALUE || mappedDataMin == mappedDataMax) {
878       float[] minMax = surfaceReader.getMinMaxMappedValues(haveData);
879       System.out.println("parameters - setmapranges " + minMax[0] + " " + minMax[1]);
880       mappedDataMin = minMax[0];
881       mappedDataMax = minMax[1];
882     }
883     if (mappedDataMin == 0 && mappedDataMax == 0) {
884       //just set default -1/1 if there is no obvious data
885       mappedDataMin = -1;
886       mappedDataMax = 1;
887     }
888 
889     if (!rangeDefined) {
890       valueMappedToRed = mappedDataMin;
891       valueMappedToBlue = mappedDataMax;
892     }
893   }
894 
addSlabInfo(Object[] slabObject)895   public void addSlabInfo(Object[] slabObject) {
896     if (slabInfo == null)
897       slabInfo = new  Lst<Object[]>();
898     slabInfo.addLast(slabObject);
899   }
900 
isInsideOut()901   public boolean isInsideOut() {
902     return insideOut != dataXYReversed;
903   }
904 
isFullyLit()905   public boolean isFullyLit() {
906     return (thePlane != null || fullyLit);
907   }
908 
909 
910 }
911