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