1 package jspecview.source; 2 3 import java.util.Hashtable; 4 import java.util.Map; 5 6 import org.jmol.util.Logger; 7 8 import javajs.util.DF; 9 import javajs.util.PT; 10 import jspecview.common.Annotation.AType; 11 import jspecview.common.Coordinate; 12 import jspecview.common.Integral; 13 import jspecview.common.Measurement; 14 import jspecview.common.Spectrum; 15 import jspecview.exception.JSVException; 16 17 /** 18 * spectrum data AS READ FROM FILE 19 * 20 * @author Bob Hanson 21 * 22 */ 23 public abstract class JDXDataObject extends JDXHeader { 24 25 /** 26 * Error number that is returned when a min value is undefined 27 */ 28 public static final double ERROR = Double.MAX_VALUE; 29 30 public static final int REF_TYPE_UNSPECIFIED = -1; 31 public static final int REF_TYPE_STANDARD = 0; 32 public static final int REF_TYPE_BRUKER = 1; 33 public static final int REF_TYPE_VARIAN = 2; 34 35 public String sourceID = ""; 36 public boolean isSimulation; 37 38 protected double blockID; // a random number generated in JDXFileReader 39 40 private String filePath; 41 private String filePathForwardSlash; 42 private String inlineData; 43 44 private double fileShiftRef = ERROR; // ##.Shift Reference 45 private int fileShiftRefType = REF_TYPE_UNSPECIFIED; // shiftRef = 0, bruker = 1, varian = 2 46 private int fileShiftRefDataPt = -1; 47 48 private double minX = Double.NaN, minY = Double.NaN; 49 private double maxX = Double.NaN, maxY = Double.NaN; 50 private double deltaX = Double.NaN; 51 52 /** 53 * array of x,y coordinates 54 */ 55 public Coordinate[] xyCoords; 56 private boolean continuous; 57 58 /** 59 * whether the x values were converted from HZ to PPM 60 */ 61 private boolean isHZtoPPM = false; 62 private boolean xIncreases = true; 63 64 // --Required JDX Parameters -- 65 66 /** 67 * JDXReader only 68 */ 69 public double fileFirstX = ERROR; 70 71 /** 72 * JDXReader only 73 */ 74 public double fileLastX = ERROR; 75 76 77 /** 78 * JDXReader only 79 */ 80 public int fileNPoints = -1; 81 82 /** 83 * Also used in JDXExport 84 */ 85 public double xFactor = ERROR; 86 87 /** 88 * Also used in JDXExport 89 */ 90 public double yFactor = ERROR; 91 92 // --Optional Spectral Parameters 93 94 public String nucleusX, nucleusY = "?"; 95 public double freq2dX = Double.NaN; 96 public double freq2dY = Double.NaN; 97 public String y2DUnits = ""; 98 99 protected Spectrum parent; 100 protected String xUnits = ""; 101 protected String yUnits = ""; 102 protected String xLabel = null; 103 protected String yLabel = null; 104 105 /** 106 * from JDXReader ##VARNAME 107 */ 108 String varName = ""; 109 110 111 /** 112 * for example, ^1H, ^13C 113 */ 114 private String observedNucl = ""; 115 private double observedFreq = ERROR; 116 private int numDim = 1; 117 private int nH; 118 private double y2D = Double.NaN; 119 setInlineData(String data)120 public void setInlineData(String data) { 121 inlineData = data; 122 123 } 124 getInlineData()125 public String getInlineData() { 126 return inlineData; 127 } 128 setFilePath(String filePath)129 public void setFilePath(String filePath) { 130 if (filePath != null) 131 filePathForwardSlash = (this.filePath = filePath.trim()).replace('\\','/'); 132 } 133 134 /** 135 * The path to the file 136 * @return path to file or [inline] (if loaded inline) 137 */ getFilePath()138 public String getFilePath() { 139 return filePath; 140 } 141 getFilePathForwardSlash()142 public String getFilePathForwardSlash() { 143 return filePathForwardSlash; 144 } 145 setBlockID(double id)146 public void setBlockID(double id) { 147 blockID = id; 148 } 149 150 /** 151 * for JDXReader only 152 * @throws JSVException 153 */ checkJDXRequiredTokens()154 public void checkJDXRequiredTokens() throws JSVException { 155 String missingTag = ( 156 fileFirstX == ERROR ? "##FIRSTX" 157 : fileLastX == ERROR ? "##LASTX" 158 : fileNPoints == -1 ? "##NPOINTS" 159 : xFactor == ERROR ? "##XFACTOR" 160 : yFactor == ERROR ? "##YFACTOR" 161 : null); 162 if (missingTag != null) 163 throw new JSVException("Error Reading Data Set: " + missingTag + " not found"); 164 } 165 166 /** 167 * Sets the original xfactor, from JDXReader and XMLReader 168 * 169 * @param xFactor 170 * the x factor 171 */ setXFactor(double xFactor)172 public void setXFactor(double xFactor) { 173 this.xFactor = xFactor; 174 } 175 176 /** 177 * Returns the original x factor 178 * 179 * @return the original x factor 180 */ getXFactor()181 public double getXFactor() { 182 return xFactor; 183 } 184 185 /** 186 * Sets the original y factor, from JDXReader and XMLReader 187 * 188 * @param yFactor 189 * the y factor 190 */ setYFactor(double yFactor)191 public void setYFactor(double yFactor) { 192 this.yFactor = yFactor; 193 } 194 195 /** 196 * Returns the original y factor 197 * 198 * @return the original y factor 199 */ getYFactor()200 public double getYFactor() { 201 return yFactor; 202 } 203 204 /** 205 * From ##VARNAME 206 * 207 * @param name 208 */ setVarName(String name)209 public void setVarName(String name) { 210 varName = name; 211 } 212 isImaginary()213 public boolean isImaginary() { 214 return varName.contains("IMAG"); 215 } 216 217 /** 218 * Sets the units for the x axis 219 * 220 * @param xUnits 221 * the x units 222 */ setXUnits(String xUnits)223 public void setXUnits(String xUnits) { 224 this.xUnits = xUnits; 225 } 226 227 /** 228 * Returns the units for x-axis when spectrum is displayed 229 * 230 * @return the units for x-axis when spectrum is displayed 231 */ getXUnits()232 public String getXUnits() { 233 return xUnits; 234 } 235 236 /** 237 * Sets the units for the y axis 238 * 239 * @param yUnits 240 * the y units 241 */ setYUnits(String yUnits)242 public void setYUnits(String yUnits) { 243 if (yUnits.equals("PPM")) 244 yUnits = "ARBITRARY UNITS"; // EPFL bug 245 this.yUnits = yUnits; 246 } 247 248 /** 249 * Returns the units for y-axis when spectrum is displayed 250 * 251 * @return the units for y-axis when spectrum is displayed 252 */ getYUnits()253 public String getYUnits() { 254 return yUnits; 255 } 256 setXLabel(String value)257 public void setXLabel(String value) { 258 xLabel = value; 259 } 260 setYLabel(String value)261 public void setYLabel(String value) { 262 yLabel = value; 263 } 264 265 setObservedNucleus(String value)266 public void setObservedNucleus(String value) { 267 observedNucl = value; 268 if (is1D()) 269 parent.nucleusX = nucleusX = fixNucleus(value); 270 } 271 272 /** 273 * ^1H, ^13C, for example 274 * 275 * @return observedNucl 276 */ getObservedNucleus()277 public String getObservedNucleus() { 278 return observedNucl; 279 } 280 281 /** 282 * Sets the Observed Frequency (for NMR Spectra) 283 * 284 * @param observedFreq 285 * the observed frequency 286 */ setObservedFreq(double observedFreq)287 public void setObservedFreq(double observedFreq) { 288 this.observedFreq = observedFreq; 289 } 290 291 /** 292 * Returns the observed frequency (for NMR Spectra) 293 * 294 * @return the observed frequency (for NMR Spectra) 295 */ getObservedFreq()296 public double getObservedFreq() { 297 return observedFreq; 298 } 299 setHydrogenCount(int nH)300 public void setHydrogenCount(int nH) { 301 this.nH = nH; 302 } 303 getHydrogenCount()304 public int getHydrogenCount() { 305 return nH; 306 } 307 is1D()308 public boolean is1D() { 309 return numDim == 1; 310 } 311 getNumDim()312 public int getNumDim() { 313 return numDim; 314 } 315 setNumDim(int n)316 public void setNumDim(int n) { 317 numDim = n; 318 } 319 320 // 2D nucleus calc 321 setY2D(double d)322 public void setY2D(double d) { 323 y2D = d; 324 } 325 getY2D()326 public double getY2D() { 327 return y2D; 328 } 329 setY2DUnits(String units)330 public void setY2DUnits(String units) { 331 y2DUnits = units; 332 } 333 getY2DPPM()334 public double getY2DPPM() { 335 double d = y2D; 336 if (y2DUnits.equals("HZ")) 337 d /= freq2dY; 338 return d; 339 } 340 setNucleusAndFreq(String nuc, boolean isX)341 public void setNucleusAndFreq(String nuc, boolean isX) { 342 nuc = fixNucleus(nuc); 343 if (isX) 344 nucleusX = nuc; 345 else 346 nucleusY = nuc; 347 double freq; 348 if (observedNucl.indexOf(nuc) >= 0) { 349 freq = observedFreq; 350 } else { 351 double g1 = getGyromagneticRatio(fixNucleus(observedNucl)); 352 double g2 = getGyromagneticRatio(nuc); 353 freq = observedFreq * g2 / g1; 354 } 355 if (isX) 356 freq2dX = freq; 357 else 358 freq2dY = freq; 359 Logger.info("Freq for " + nuc + " = " + freq); 360 } 361 362 363 /** 364 * Remove nonstandard marks to give simple nucleus 1H not ^1H 365 * @param nuc 366 * @return "1H", "13C", etc. 367 */ fixNucleus(String nuc)368 private String fixNucleus(String nuc) { 369 return PT.rep(PT.trim(nuc,"[]^<>"), "NUC_", ""); 370 } 371 372 /** 373 * source: http://www.mathworks.com/matlabcentral/fileexchange/11722-nmr-properties/content/isotopes.m 374 * % REFERENCES 375 % 1. "Nuclear spins, moments, and other data related to NMR spectroscopy" (9-93) 376 % CRC Handbook of Chemistry and Physics, 83th Ed., CRC Press, Boca Raton, FL, 377 % 2002. 378 % 2. Stone, N. J., <www.nndc.bnl.gov/nndc/stone_moments/> 379 % 3. http://www.hbcpnetbase.com/ 380 */ 381 382 /* '*' indicates 383 * from CODATA 2010 Physical Constants Task Group 384 1H 267.5222005 42.57748060 385 2H 41.0662791 6.53590131 386 13C 67.2828400 10.70839657 387 15N -27.1261804 -4.31726570 388 19F 251.8148000 40.07757016 389 23Na 70.8084930 11.26952167 390 31P 108.3940000 17.25144090 391 */ 392 393 private final static double[] gyroData = { 394 1, 42.5774806,//*H Hydrogen 1/2 395 2, 6.53590131,//*H Deuterium 1 396 3, 45.4148 , // H Tritium 1/2 397 3, 32.436 , // He Helium 1/2 398 6, 6.2661 , // Li Lithium 1 399 7, 16.5483 , // Li Lithium 3/2 400 9, 5.9842 , // Be Beryllium 3/2 401 10, 4.5752 , // B Boron 3 402 11, 13.663 , // B Boron 3/2 403 13, 10.70839657,//*C Carbon 1/2 404 14, 3.07770646,//*N Nitrogen 1 405 15, 4.31726570,//*N Nitrogen 1/2 406 17, 5.7742 , // O Oxygen 5/2 407 19, 40.07757016,//*F Fluorine 1/2 408 21, 3.3631 , // Ne Neon 3/2 409 23, 11.26952167,//*Na Sodium 3/2 410 25, 2.6083 , // Mg Magnesium 5/2 411 27, 11.1031 , // Al Aluminum 5/2 412 29, 8.4655 , // Si Silicon 1/2 413 31, 17.25144090,//*P Phosphorus 1/2 414 33, 3.2717 , // S Sulfur 3/2 415 35, 4.1765 , // Cl Chlorine 3/2 416 37, 3.4765 , // Cl Chlorine 3/2 417 37, 5.819 , // Ar Argone 3/2 418 39, 3.46 , // Ar Argone 7/2 419 39, 1.9893 , // K Potassium 3/2 420 40, 2.4737 , // K Potassium 4 421 41, 1.0919 , // K Potassium 3/2 422 43, 2.8688 , // Ca Calcium 7/2 423 45, 10.3591 , // Sc Scandium 7/2 424 47, 2.4041 , // Ti Titanium 5/2 425 49, 2.4048 , // Ti Titanium 7/2 426 50, 4.2505 , // V Vanadium 6 427 51, 11.2133 , // V Vanadium 7/2 428 53, 2.4115 , // Cr Chromium 3/2 429 55, 10.5763 , // Mn Manganese 5/2 430 57, 1.3816 , // Fe Iron 1/2 431 59, 10.077 , // Co Cobalt 7/2 432 61, 3.8114 , // Ni Nickel 3/2 433 63, 11.2982 , // Cu Copper 3/2 434 65, 12.103 , // Cu Copper 3/2 435 67, 2.6694 , // Zn Zinc 5/2 436 69, 10.2478 , // Ga Gallium 3/2 437 71, 13.0208 , // Ga Gallium 3/2 438 73, 1.4897 , // Ge Germanium 9/2 439 75, 7.315 , // As Arsenic 3/2 440 77, 8.1571 , // Se Selenium 1/2 441 79, 10.7042 , // Br Bromine 3/2 442 81, 11.5384 , // Br Bromine 3/2 443 83, 1.6442 , // Kr Krypton 9/2 444 85, 4.1254 , // Rb Rubidium 5/2 445 87, 13.9811 , // Rb Rubidium 3/2 446 87, 1.8525 , // Sr Strontium 9/2 447 89, 2.0949 , // Y Yttrium 1/2 448 91, 3.9748 , // Zr Zirconium 5/2 449 93, 10.4523 , // Nb Niobium 9/2 450 95, 2.7874 , // Mo Molybdenum 5/2 451 97, 2.8463 , // Mo Molybdenum 5/2 452 99, 9.6294 , // Tc Technetium 9/2 453 99, 1.9553 , // Ru Ruthenium 5/2 454 101, 2.1916 , // Ru Ruthenium 5/2 455 103, 1.3477 , // Rh Rhodium 1/2 456 105, 1.957 , // Pd Palladium 5/2 457 107, 1.7331 , // Ag Silver 1/2 458 109, 1.9924 , // Ag Silver 1/2 459 111, 9.0692 , // Cd Cadmium 1/2 460 113, 9.4871 , // Cd Cadmium 1/2 461 113, 9.3655 , // In Indium 9/2 462 115, 9.3856 , // In Indium 9/2 463 115, 14.0077 ,// Sn Tin 1/2 464 117, 15.261 , // Sn Tin 1/2 465 119, 15.966 , // Sn Tin 1/2 466 121, 10.2551 ,// Sb Antimony 5/2 467 123, 5.5532 , // Sb Antimony 7/2 468 123, 11.2349 ,// Te Tellurium 1/2 469 125, 13.5454 ,// Te Tellurium 1/2 470 127, 8.5778 , // I Iodine 5/2 471 129, 11.8604 ,// Xe Xenon 1/2 472 131, 3.5159 , // Xe Xenon 3/2 473 133, 5.6234 , // Cs Cesium 7/2 474 135, 4.2582 , // Ba Barium 3/2 475 137, 4.7634 , // Ba Barium 3/2 476 138, 5.6615 , // La Lanthanum 5 477 139, 6.0612 , // La Lanthanum 7/2 478 137, 4.88 , // Ce Cerium 3/2 479 139, 5.39 , // Ce Cerium 3/2 480 141, 2.37 , // Ce Cerium 7/2 481 141, 13.0359 ,// Pr Praseodymium 5/2 482 143, 2.319 , // Nd Neodymium 7/2 483 145, 1.429 , // Nd Neodymium 7/2 484 143, 11.59 , // Pm Promethium 5/2 485 147, 5.62 , // Pm Promethium 7/2 486 147, 1.7748 , // Sm Samarium 7/2 487 149, 14631 , // Sm Samarium 7/2 488 151, 10.5856 ,// Eu Europium 5/2 489 153, 4.6745 , // Eu Europium 5/2 490 155, 1.312 , // Gd Gadolinium 3/2 491 157, 1.72 , // Gd Gadolinium 3/2 492 159, 10.23 , // Tb Terbium 3/2 493 161, 1.4654 , // Dy Dysprosium 5/2 494 163, 2.0508 , // Dy Dysprosium 5/2 495 165, 9.0883 , // Ho Holmium 7/2 496 167, 1.2281 , // Er Erbium 7/2 497 169, 3.531 , // Tm Thulium 1/2 498 171, 7.5261 , // Yb Ytterbium 1/2 499 173, 2.073 , // Yb Ytterbium 5/2 500 175, 4.8626 , // Lu Lutetium 7/2 501 176, 3.451 , // Lu Lutetium 7 502 177, 1.7282 , // Hf Hafnium 7/2 503 179, 1.0856 , // Hf Hafnium 9/2 504 180, 4.087 , // Ta Tantalum 9 505 181, 5.1627 , // Ta Tantalum 7/2 506 183, 1.7957 , // W Tungsten 1/2 507 185, 9.7176 , // Re Rhenium 5/2 508 187, 9.817 , // Re Rhenium 5/2 509 187, 0.9856 , // Os Osmium 1/2 510 189, 3.3536 , // Os Osmium 3/2 511 191, 0.7658 , // Ir Iridium 3/2 512 191, 0.8319 , // Ir Iridium 3/2 513 195, 9.2922 , // Pt Platinum 1/2 514 197, 0.7406 , // Au Gold 3/2 515 199, 7.7123 , // Hg Mercury 1/2 516 201, 2.8469 , // Hg Mercury 3/2 517 203, 24.7316 ,// Tl Thallium 1/2 518 205, 24.9749 ,// Tl Thallium 1/2 519 207, 9.034 , // Pb Lead 1/2 520 209, 6.963 , // Bi Bismuth 9/2 521 209, 11.7 , // Po Polonium 1/2 522 211, 9.16 , // Rn Radon 1/2 523 223, 5.95 , // Fr Francium 3/2 524 223, 1.3746 , // Ra Radium 3/2 525 225, 11.187 , // Ra Radium 1/2 526 227, 5.6 , // Ac Actinium 3/2 527 229, 1.4 , // Th Thorium 5/2 528 231, 10.2 , // Pa Protactinium 3/2 529 235, 0.83 , // U Uranium 7/2 530 237, 9.57 , // Np Neptunium 5/2 531 239, 3.09 , // Pu Plutonium 1/2 532 243, 4.6 , // Am Americium 5/2 533 1E100 534 }; 535 536 final private static Map<String, Double> gyroMap = new Hashtable<String, Double>(); 537 538 static { 539 for (int i = 0, n = gyroData.length - 1; i < n; i += 2) 540 gyroMap.put("" + (int)gyroData[i], Double.valueOf(gyroData[i + 1])); 541 542 // System.out.println(getGyroMagneticRatio("13C")); 543 // System.out.println(getGyroMagneticRatio("1H")); 544 // System.out.println(getNominalSpecFreq("13C", 100.612769)); 545 } 546 getNominalSpecFreq(String nuc, double freq)547 public static int getNominalSpecFreq(String nuc, double freq) { 548 double d = freq * getGyromagneticRatio("1H") / getGyromagneticRatio(nuc); 549 int century = (int) Math.round(d / 100) * 100; 550 return (Double.isNaN(d) ? -1 : Math.abs(d - century) < 2 ? century : (int) Math.round(d)); 551 } 552 getGyromagneticRatio(String nuc)553 public static double getGyromagneticRatio(String nuc) { 554 Double v = null; 555 try { 556 v = gyroMap.get(nuc); 557 if (v != null) 558 return v.doubleValue(); 559 560 int pt = 0; 561 while (pt < nuc.length() && Character.isDigit(nuc.charAt(pt))) 562 pt++; 563 v = gyroMap.get(nuc.substring(0, pt)); 564 if (v != null) 565 gyroMap.put(nuc, v); 566 } catch (Exception e) { 567 /// ignore 568 } 569 return (v == null ? Double.NaN : v.doubleValue()); 570 // pt = PT.parseInt(nuc.substring(pt)); 571 // int i = 0; 572 // for (int n = gyroData.length - 1; i < n; i += 2) 573 // if (gyroData[i] >= pt) 574 // break; 575 // return (gyroData[i] == pt ? gyroData[i + 1] : Double.NaN); 576 } 577 578 579 580 //////////////// derived info ///////////// 581 isTransmittance()582 public boolean isTransmittance() { 583 String s = yUnits.toLowerCase(); 584 return (s.equals("transmittance") || s.contains("trans") || s.equals("t")); 585 } 586 isAbsorbance()587 public boolean isAbsorbance() { 588 String s = yUnits.toLowerCase(); 589 return (s.equals("absorbance") || s.contains("abs") || s.equals("a")); 590 } 591 canSaveAsJDX()592 public boolean canSaveAsJDX() { 593 return getDataClass().equals("XYDATA"); 594 } 595 canIntegrate()596 public boolean canIntegrate() { 597 return (continuous && (isHNMR() || isGC()) && is1D()); 598 } 599 isAutoOverlayFromJmolClick()600 public boolean isAutoOverlayFromJmolClick() { 601 return (isGC());// || isUVVis()); 602 } 603 isGC()604 public boolean isGC() { 605 return dataType.startsWith("GC") || dataType.startsWith("GAS"); 606 } 607 isMS()608 public boolean isMS() { 609 return dataType.startsWith("MASS") || dataType.startsWith("MS"); 610 } 611 isStackable()612 public boolean isStackable() { 613 return !isMS(); 614 } 615 isScalable()616 public boolean isScalable() { 617 return true; 618 } 619 620 getYRef()621 public double getYRef() { 622 return (!isTransmittance() ? 0.0 : Coordinate.getMaxY(xyCoords, 0, xyCoords.length - 1) < 2 ? 1.0 : 100.0); 623 } 624 isInverted()625 public boolean isInverted() { 626 return isTransmittance(); // IR 627 } 628 canConvertTransAbs()629 public boolean canConvertTransAbs() { 630 return (continuous && (yUnits.toLowerCase().contains("abs")) 631 || yUnits.toLowerCase().contains("trans")); 632 } 633 canShowSolutionColor()634 public boolean canShowSolutionColor() { 635 return (isContinuous() && canConvertTransAbs() 636 && (xUnits.toLowerCase().contains("nanometer") || xUnits.equalsIgnoreCase("nm")) 637 && getFirstX() < 401 && getLastX() > 699 && xyCoords.length >= 30); 638 } 639 640 /** 641 * Determines if the spectrum should be displayed with abscissa unit of Part 642 * Per Million (PPM) instead of Hertz (HZ) 643 * 644 * @return true if abscissa unit should be PPM 645 */ isHZtoPPM()646 public boolean isHZtoPPM() { 647 return isHZtoPPM; 648 } 649 650 /** 651 * Sets the value to true if the spectrum should be displayed with abscissa 652 * unit of Part Per Million (PPM) instead of Hertz (HZ) 653 * 654 * @param val 655 * true or false 656 */ setHZtoPPM(boolean val)657 public void setHZtoPPM(boolean val) { 658 isHZtoPPM = val; 659 } 660 661 /** 662 * Sets value to true if spectrum is increasing 663 * 664 * @param val 665 * true if spectrum is increasing 666 */ setIncreasing(boolean val)667 public void setIncreasing(boolean val) { 668 xIncreases = val; 669 } 670 671 /** 672 * Returns true if the spectrum is increasing; used by SVGExporter only 673 * 674 * @return true if the spectrum is increasing 675 */ isXIncreasing()676 public boolean isXIncreasing() { 677 return xIncreases; 678 } 679 680 /** 681 * Determines if the plot should be displayed decreasing by default 682 * 683 * @return true or false 684 */ shouldDisplayXAxisIncreasing()685 public boolean shouldDisplayXAxisIncreasing() { 686 String dt = dataType.toUpperCase(); 687 String xu = xUnits.toUpperCase(); 688 if (dt.contains("NMR") && !dt.contains("FID")) { 689 return false; 690 } else if (dt.contains("LINK") && xu.contains("CM")) { 691 return false; // I think this was because of a bug where BLOCK files kept type as LINK ? 692 } else if (dt.startsWith("IR") || dt.contains("INFRA") 693 && xu.contains("CM")) { 694 return false; 695 } else if (dt.contains("RAMAN") && xu.contains("CM")) { 696 return false; 697 } else if (dt.contains("VIS") && xu.contains("NANOMETERS")) { 698 return true; 699 } 700 return xIncreases; 701 } 702 703 /** 704 * Sets value to true if spectrum is continuous 705 * 706 * @param val 707 * true if spectrum is continuous 708 */ setContinuous(boolean val)709 public void setContinuous(boolean val) { 710 continuous = val; 711 } 712 713 /** 714 * Returns true if spectrum is continuous 715 * 716 * @return true if spectrum is continuous 717 */ isContinuous()718 public boolean isContinuous() { 719 return continuous; 720 } 721 722 // For AnIML IR/UV files: 723 724 // public double pathlength 725 726 // /** 727 // * Returns the pathlength of the sample (required for AnIML IR/UV files) 728 // * 729 // * @return the pathlength 730 // */ 731 // public String getPathlength() { 732 // return pathlength; 733 // } 734 getHeaderRowDataAsArray()735 public String[][] getHeaderRowDataAsArray() { 736 int n = 8; 737 if (observedFreq != ERROR) 738 n++; 739 if (observedNucl != "") 740 n++; 741 String[][] rowData = getHeaderRowDataAsArray(true, n); 742 int i = rowData.length - n; 743 if (observedFreq != ERROR) 744 rowData[i++] = new String[] { "##.OBSERVE FREQUENCY", "" + observedFreq }; 745 if (observedNucl != "") 746 rowData[i++] = new String[] { "##.OBSERVE NUCLEUS", observedNucl }; 747 rowData[i++] = new String[] { "##XUNITS", isHZtoPPM ? "HZ" : xUnits }; 748 rowData[i++] = new String[] { "##YUNITS", yUnits }; 749 double x = (xIncreases ? getFirstX() : getLastX()); 750 rowData[i++] = new String[] { "##FIRSTX", 751 String.valueOf(isHZtoPPM() ? x * observedFreq : x) }; 752 x = (xIncreases ? getLastX() : getFirstX()); 753 rowData[i++] = new String[] { "##FIRSTY", 754 String.valueOf(xIncreases ? getFirstY() : getLastY()) }; 755 rowData[i++] = new String[] { "##LASTX", 756 String.valueOf(isHZtoPPM() ? x * observedFreq : x) }; 757 rowData[i++] = new String[] { "##XFACTOR", String.valueOf(getXFactor()) }; 758 rowData[i++] = new String[] { "##YFACTOR", String.valueOf(getYFactor()) }; 759 rowData[i++] = new String[] { "##NPOINTS", 760 String.valueOf(xyCoords.length) }; 761 return rowData; 762 } 763 getDefaultUnitPrecision()764 public int getDefaultUnitPrecision() { 765 return 2; 766 } 767 setMeasurementText(Measurement m)768 public String setMeasurementText(Measurement m) { 769 double dx = m.getValue(); 770 if (Double.isNaN(dx)) 771 return ""; 772 int precision = 1; 773 String units = ""; 774 if (isNMR()) { 775 if (is1D()) { 776 boolean isIntegral = (m instanceof Integral); 777 if (isHNMR() || isIntegral) { 778 if (!isIntegral) { 779 dx *= observedFreq; 780 units = " Hz"; 781 } 782 } else { 783 units = " ppm"; 784 precision = 2; 785 } 786 } else { 787 return ""; 788 // 2D? 789 } 790 } 791 return (dx < 0.1 ? "" : DF.formatDecimalDbl(dx, precision) + units); 792 } 793 isNMR()794 public boolean isNMR() { 795 return (dataType.toUpperCase().indexOf("NMR") >= 0); 796 } 797 /** 798 * Determines if a spectrum is an HNMR spectrum 799 * @return true if an HNMR, false otherwise 800 */ isHNMR()801 public boolean isHNMR() { 802 return (isNMR() && observedNucl.toUpperCase().indexOf("H") >= 0); 803 } 804 805 /** 806 * Sets the array of coordinates 807 * 808 * @param coords 809 * the array of Coordinates 810 */ setXYCoords(Coordinate[] coords)811 public void setXYCoords(Coordinate[] coords) { 812 xyCoords = coords; 813 } 814 invertYAxis()815 public JDXDataObject invertYAxis() { 816 for (int i = xyCoords.length; --i >= 0;) { 817 xyCoords[i].setYVal(-xyCoords[i].getYVal()); 818 } 819 double d = minY; 820 minY = -maxY; 821 maxY = -d; 822 return this; 823 } 824 825 /** 826 * Returns the first X value 827 * 828 * @return the first X value 829 */ getFirstX()830 public double getFirstX() { 831 return xyCoords[0].getXVal(); 832 } 833 834 /** 835 * Returns the first Y value 836 * 837 * @return the first Y value 838 */ getFirstY()839 public double getFirstY() { 840 //if(isIncreasing()) 841 return xyCoords[0].getYVal(); 842 //else 843 // return xyCoords[getNumberOfPoints() - 1].getYVal(); 844 } 845 846 /** 847 * Returns the last X value 848 * 849 * @return the last X value 850 */ getLastX()851 public double getLastX() { 852 // if(isIncreasing()) 853 return xyCoords[xyCoords.length - 1].getXVal(); 854 // else 855 // return xyCoords[0].getXVal(); 856 } 857 858 /** 859 * Returns the last Y value 860 * 861 * @return the last Y value 862 */ getLastY()863 public double getLastY() { 864 return xyCoords[xyCoords.length - 1].getYVal(); 865 } 866 867 /** 868 * Calculates and returns the minimum x value in the list of coordinates 869 * Fairly expensive operation 870 * 871 * @return the minimum x value in the list of coordinates 872 */ getMinX()873 public double getMinX() { 874 return (Double.isNaN(minX) ? (minX = Coordinate.getMinX(xyCoords, 0, xyCoords.length - 1)) : minX); 875 } 876 877 /** 878 * Calculates and returns the minimum y value in the list of coordinates 879 * Fairly expensive operation 880 * 881 * @return the minimum x value in the list of coordinates 882 */ getMinY()883 public double getMinY() { 884 return (Double.isNaN(minY) ? (minY = Coordinate.getMinY(xyCoords, 0, xyCoords.length - 1)) : minY); 885 } 886 887 /** 888 * Calculates and returns the maximum x value in the list of coordinates 889 * Fairly expensive operation 890 * 891 * @return the maximum x value in the list of coordinates 892 */ getMaxX()893 public double getMaxX() { 894 return (Double.isNaN(maxX) ? (maxX = Coordinate.getMaxX(xyCoords, 0, xyCoords.length - 1)) : maxX); 895 } 896 897 /** 898 * Calculates and returns the maximum y value in the list of coordinates 899 * Fairly expensive operation 900 * 901 * @return the maximum y value in the list of coordinates 902 */ getMaxY()903 public double getMaxY() { 904 return (Double.isNaN(maxY) ? (maxY = Coordinate.getMaxY(xyCoords, 0, xyCoords.length - 1)) : maxY); 905 } 906 normalizeSimulation(double max)907 public void normalizeSimulation(double max) { 908 // for simulations 909 if (!isNMR() || !is1D()) 910 return; 911 double f = max / getMaxY(); 912 maxY = Double.NaN; 913 Coordinate.applyScale(xyCoords, 1, f); 914 Logger.info("Y values have been scaled by a factor of " + f); 915 } 916 917 /** 918 * Returns the delta X 919 * 920 * @return the delta X 921 */ getDeltaX()922 public double getDeltaX() { 923 return (Double.isNaN(deltaX) ? (deltaX = Coordinate.deltaX(getLastX(), getFirstX(), xyCoords.length)) : deltaX); 924 } 925 copyTo(JDXDataObject newObj)926 public void copyTo(JDXDataObject newObj) { 927 newObj.setTitle(title); 928 newObj.setJcampdx(jcampdx); 929 newObj.setOrigin(origin); 930 newObj.setOwner(owner); 931 newObj.setDataClass(dataClass); 932 newObj.setDataType(dataType); 933 newObj.setHeaderTable(headerTable); 934 935 newObj.setXFactor(xFactor); 936 newObj.setYFactor(yFactor); 937 newObj.setXUnits(xUnits); 938 newObj.setYUnits(yUnits); 939 newObj.setXLabel(xLabel); 940 newObj.setYLabel(yLabel); 941 942 //newSpectrum.setPathlength(getPathlength()); 943 newObj.setXYCoords(xyCoords); 944 newObj.setContinuous(continuous); 945 newObj.setIncreasing(xIncreases); 946 947 newObj.observedFreq = observedFreq; 948 newObj.observedNucl = observedNucl; 949 newObj.fileShiftRef = fileShiftRef; 950 newObj.fileShiftRefDataPt = fileShiftRefDataPt; 951 newObj.fileShiftRefType = fileShiftRefType; 952 newObj.isHZtoPPM = isHZtoPPM; 953 newObj.numDim = numDim; 954 newObj.nucleusX = nucleusX; 955 newObj.nucleusY = nucleusY; 956 newObj.freq2dX = freq2dX; 957 newObj.freq2dY = freq2dY; 958 newObj.setFilePath(filePath); 959 newObj.nH = nH; 960 961 } 962 getTypeLabel()963 public String getTypeLabel() { 964 return (isNMR() ? nucleusX + "NMR" : dataType); 965 } 966 getDefaultAnnotationInfo(AType type)967 public Object[] getDefaultAnnotationInfo(AType type) { 968 String[] s1; 969 int[] s2; 970 boolean isNMR = isNMR(); 971 switch (type) { 972 case Integration: 973 return new Object[] { null, new int[] { 1 }, null }; 974 case Measurements: 975 s1 = (isNMR ? new String[] { "Hz", "ppm" } : new String[] {""}); 976 s2 = (isHNMR() ? new int[] { 1, 4 } 977 : new int[] { 1, 3 }); 978 return new Object[] { s1, s2, Integer.valueOf(0) }; 979 case PeakList: 980 s1 = (isNMR ? new String[] { "Hz", "ppm" } : new String[] {""} ); 981 s2 = (isHNMR() ? new int[] { 1, 2 } : new int[] { 1, 1 }); 982 return new Object[] { s1, s2, Integer.valueOf(isNMR ? 1 : 0) }; 983 case NONE: 984 case OverlayLegend: 985 break; 986 case Views: 987 break; 988 } 989 return null; 990 } 991 getPeakListArray(Measurement m, double[]last, double maxY)992 public double[] getPeakListArray(Measurement m, double[]last, double maxY) { 993 double x = m.getXVal(); 994 double y = m.getYVal(); 995 if (isNMR()) 996 y /= maxY; 997 double dx = Math.abs(x - last[0]); 998 last[0] = x; 999 double ddx = dx + last[1]; 1000 last[1] = dx; 1001 double dddx = ddx + last[2]; 1002 last[2] = ddx; 1003 if (isNMR()) { 1004 return new double[] {x, y, x * observedFreq, (dx * observedFreq > 20 ? 0 : dx * observedFreq) 1005 , (ddx * observedFreq > 20 ? 0 : ddx * observedFreq) 1006 , (dddx * observedFreq > 20 ? 0 : dddx * observedFreq)}; 1007 } 1008 return new double[] { x, y }; 1009 } 1010 1011 /** 1012 * Called by JDXReader immediately after decompression. 1013 * 1014 */ finalizeCoordinates()1015 void finalizeCoordinates() { 1016 double freq = (Double.isNaN(freq2dX) ? observedFreq 1017 : freq2dX); 1018 // apply offset 1019 boolean isHz = (freq != ERROR 1020 && getXUnits().toUpperCase().equals("HZ")); 1021 if (fileShiftRef != ERROR && freq != ERROR 1022 && dataType.toUpperCase().contains("SPECTRUM") 1023 && jcampdx.indexOf("JEOL") < 0 // BH 2020.09.16 J Muzyka Centre College 1024 ) { 1025 applyShiftReference(isHz ? freq : 1, fileShiftRef); 1026 } 1027 if (fileFirstX > fileLastX) 1028 Coordinate.reverse(xyCoords); 1029 if (isHz) { 1030 Coordinate.applyScale(xyCoords, (1.0 / freq), 1); 1031 setXUnits("PPM"); 1032 setHZtoPPM(true); 1033 } 1034 } 1035 1036 /** 1037 * Set the shift, pt, and type for applyShiftReference() from processing 1038 * ##.SHIFTREFERENCE, ##$REFERENCEPOINT, or ##OFFSET 1039 * 1040 * @param shift 1041 * @param pt 1042 * @param type 1043 */ setShiftReference(double shift, int pt, int type)1044 void setShiftReference(double shift, int pt, int type) { 1045 fileShiftRef = shift; 1046 fileShiftRefDataPt = (pt > 0 ? pt : 1); 1047 fileShiftRefType = type; 1048 } 1049 isShiftTypeSpecified()1050 boolean isShiftTypeSpecified() { 1051 return (fileShiftRefType != JDXDataObject.REF_TYPE_UNSPECIFIED); 1052 } 1053 1054 /** 1055 * Applies the shift reference to all coordinates. Used by JDXReader only. 1056 * 1057 * @param referenceFreq 1058 * the observed frequency 1059 * @param shift 1060 */ applyShiftReference(double referenceFreq, double shift)1061 private void applyShiftReference(double referenceFreq, double shift) { 1062 1063 if (fileShiftRefDataPt > xyCoords.length || fileShiftRefDataPt < 0) 1064 return; 1065 1066 Coordinate coord; 1067 switch (fileShiftRefType) { 1068 case REF_TYPE_STANDARD: 1069 shift = xyCoords[fileShiftRefDataPt - 1].getXVal() - shift * referenceFreq; 1070 break; 1071 case REF_TYPE_BRUKER: 1072 shift = fileFirstX - shift * referenceFreq; 1073 break; 1074 case REF_TYPE_VARIAN: 1075 shift = fileLastX + shift; 1076 break; 1077 } 1078 1079 for (int index = 0; index < xyCoords.length; index++) { 1080 coord = xyCoords[index]; 1081 coord.setXVal(coord.getXVal() - shift); 1082 xyCoords[index] = coord; 1083 } 1084 1085 } 1086 1087 1088 } 1089