Package ca.eandb.jmist.framework.material.biospec

Source Code of ca.eandb.jmist.framework.material.biospec.BioSpecMaterial

/**
* Java Modular Image Synthesis Toolkit (JMIST)
* Copyright (C) 2008-2013 Bradley W. Kimmel
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package ca.eandb.jmist.framework.material.biospec;

import ca.eandb.jmist.framework.Function1;
import ca.eandb.jmist.framework.Material;
import ca.eandb.jmist.framework.ScatteredRay;
import ca.eandb.jmist.framework.SurfacePoint;
import ca.eandb.jmist.framework.color.ColorModel;
import ca.eandb.jmist.framework.color.WavelengthPacket;
import ca.eandb.jmist.framework.function.PiecewiseLinearFunction1;
import ca.eandb.jmist.framework.function.ScaledFunction1;
import ca.eandb.jmist.framework.function.SumFunction1;
import ca.eandb.jmist.framework.material.LambertianMaterial;
import ca.eandb.jmist.framework.material.OpaqueMaterial;
import ca.eandb.jmist.math.Vector3;
import ca.eandb.jmist.util.ArrayUtil;

/**
* A <code>Material</code> implementing the BioSpec algorithm.
* <p>
* The algorithm implemented here is described in:
* <blockquote>
*   A. Krishnaswamy, G.V.G. Baranoski,
*   <a href="http://www.npsg.uwaterloo.ca/resources/docs/eg04.pdf">
*     A biophysically-based spectral model of light interaction with human
*     skin</a>,
*   In Computer Graphics Forum 23(3):331-340, 2004.
* </blockquote>
*
* @author Brad Kimmel
* @see <a href="http://www.npsg.uwaterloo.ca/models/biospec.php">Run BioSpec Online</a>
*/
public final class BioSpecMaterial extends OpaqueMaterial {

  /** Serialization version ID. */
  private static final long serialVersionUID = 8769272864903029271L;

  //////////////////////////////////////////////////////////////////////////
  // Data tables from Bruls and Leun
  //////////////////////////////////////////////////////////////////////////

  private static final double[] exitant_angles =
  { 0.0, 2.5, 7.5, 12.5, 17.5, 22.5, 27.5, 32.5, 37.5, 42.5, 47.5, 52.5, 57.5, 62.5 };

  // These values represent the % of total light transmitted by the exitant angles in the array above

  // Stratum corneum values
  private static final double[] stratum_corneum_wavelengths =
  { 254.0, 302.0, 365.0, 436.0, 546.0 };

  private static final double[] stratum_corneum_254 =
  { 0.0, 9.3, 40.2, 59.2, 71.1, 79.2, 85.1, 89.3, 92.5, 95.0, 96.9, 98.4, 99.4, 100.0 };

  private static final double[] stratum_corneum_302 =
  { 0.0, 11.6, 45.1, 63.0, 73.7, 80.6, 85.6, 89.3, 92.2, 94.5, 96.5, 98.0, 99.2, 100.0 };

  private static final double[] stratum_corneum_365 =
  { 0.0, 14.8, 50.1, 66.8, 76.5, 82.3, 86.3, 89.4, 92.0, 94.1, 96.0, 97.6, 98.9, 100.0 };

  private static final double[] stratum_corneum_436 =
  { 0.0, 17.6, 55.2, 70.9, 79.1, 84.1, 87.6, 90.3, 92.5, 94.4, 96.1, 97.6, 99.0, 100.0 };

  private static final double[] stratum_corneum_546 =
  { 0.0, 20.6, 60.2, 75.2, 82.3, 86.5, 89.4, 91.5, 93.4, 95.0, 96.5, 97.8, 99.0, 100.0 };

  private static final double[][] stratum_corneum_perturb =
  { stratum_corneum_254, stratum_corneum_302, stratum_corneum_365, stratum_corneum_436,
  stratum_corneum_546 };

  // Epidermis values
  private static final double[] epidermis_wavelengths =
  { 302.0, 365.0, 436.0, 546.0 };

  private static final double[] epidermis_302 =
  { 0.0, 1.3, 9.4, 20.8, 33.2, 45.5, 56.9, 66.9, 75.7, 83.2, 89.3, 94.1, 97.7, 100.0 };

  private static final double[] epidermis_365 =
  { 0.0, 1.7, 11.9, 24.8, 37.5, 49.0, 59.8, 69.2, 77.4, 84.2, 89.8, 94.3, 97.8, 100.0 };

  private static final double[] epidermis_436 =
  { 0.0, 2.6, 16.1, 30.8, 43.6, 54.5, 63.9, 71.9, 79.0, 85.0, 90.1, 94.3, 97.8, 100.0 };

  private static final double[] epidermis_546 =
  { 0.0, 4.0, 22.5, 39.7, 52.2, 62.4, 70.2, 76.7, 82.4, 87.2, 91.4, 94.9, 97.9, 100.0 };

  private static final double[][] epidermis_perturb =
  { epidermis_302, epidermis_365, epidermis_436, epidermis_546 };


  //////////////////////////////////////////////////////////////////////////
  // Data from Oregon Medical Laser center
  // This is melanin data, found here:
  //   http://omlc.ogi.edu/spectra/melanin/extcoeff.html
  //////////////////////////////////////////////////////////////////////////

  /////////////////////////////////////////////////
  // Eumelanin data
  /////////////////////////////////////////////////

  // The wavelengths the data is for
  private static final double[] omlc_eumelanin_wavelengths =
  { 209.99, 212.21, 218.91, 223.36, 230.06, 239.00, 245.70, 261.38, 279.30, 294.99,
  312.92, 324.13, 342.06, 357.75, 382.42, 407.07, 431.74, 458.67, 483.36, 523.76,
  550.70, 588.87, 615.82, 642.77, 680.96, 712.41, 734.88, 764.09, 782.06, 804.53,
  820.26 };


  // The extinction co-efficient of eumelanin in cm^-1, mg/ml^1
  private static final double[] omlc_eumelanin_ext_mgml =
  { 41.900, 40.667, 39.082, 37.145, 35.383, 33.445, 31.507, 29.392, 27.277, 25.338,
  23.575, 22.517, 20.578, 18.639, 16.523, 13.878, 11.938, 10.173, 8.9370, 6.9950,
  5.7580, 4.5200, 3.9880, 3.2800, 2.7460, 2.2140, 2.0340, 1.8540, 1.6750, 1.4960,
  1.4940 };

  // The extinction co-efficient of eumelanin in cm^-1, mol/L^1
  private static final double[] omlc_eumelanin_ext_molL =
  { 7458.2, 7238.7, 6956.6, 6611.8, 6298.2, 5953.2, 5608.2, 5231.8, 4855.3, 4510.2,
  4196.4, 4008.0, 3662.9, 3317.7, 2941.1, 2470.3, 2125.0, 1810.8, 1590.8, 1245.1,
  1024.9, 804.56, 709.86, 583.84, 488.79, 394.09, 362.05, 330.01, 298.15, 266.29,
  265.93 };

  /////////////////////////////////////////////////
  // Pheomelanin data
  /////////////////////////////////////////////////

  // The wavelengths the data is for
  private static final double[] omlc_pheomelanin_wavelengths =
  { 213.54, 217.92, 222.25, 226.55, 228.59, 232.91, 234.95, 241.54, 243.61, 247.96,
  250.18, 256.82, 263.41, 270.05, 276.71, 285.60, 292.24, 298.88, 303.26, 312.08,
  323.18, 334.25, 343.05, 351.88, 360.76, 376.38, 387.50, 403.20, 418.85, 430.04,
  443.45, 459.17, 481.61, 501.83, 524.32, 549.09, 591.91, 600.98, 625.84, 652.98,
  675.59, 700.47, 720.81, 750.22, 770.62, 786.44, 802.28, 820.37, 829.42 };

  // The extinction co-efficient of pheomelanin in cm^-1, mg/ml^1
  private static final double[] omlc_pheomelanin_ext_mgml =
  { 47.193, 46.140, 44.738, 43.161, 41.586, 40.183, 38.608, 37.204, 35.803, 34.576,
  34.224, 33.170, 31.765, 30.711, 29.831, 28.599, 27.545, 26.490, 25.437, 23.856,
  22.273, 20.516, 18.760, 17.179, 15.947, 14.361, 12.952, 11.890, 10.478, 9.5940,
  8.3590, 7.4720, 6.0540, 4.9880, 3.9190, 3.0240, 1.5890, 1.7560, 1.3850, 1.1870,
  0.9930, 0.7970, 0.6050, 0.4050, 0.5620, 0.3740, 0.3610, 0.1700, 0.1630 };

  // The extinction co-efficient of pheomelanin in cm^-1, mol/L^1
  private static final double[] omlc_pheomelanin_ext_molL =
  { 13922, 13611, 13198, 12732, 12268, 11854, 11389, 10975, 10562, 10200, 10096, 9785.1,
  9370.7, 9059.7, 8800.1, 8436.7, 8125.8, 7814.5, 7503.9, 7037.5, 6570.5, 6052.2,
  5534.2, 5067.8, 4704.4, 4236.5, 3820.8, 3507.6, 3091.0, 2830.2, 2465.9, 2204.2,
  1785.9, 1471.5, 1156.1, 892.08, 468.76, 518.02, 408.58, 350.17, 292.93, 235.11,
  178.48, 119.47, 165.79, 110.33, 106.50, 50.150, 48.085 };

  //////////////////////////////////////////////////////////////////////////
  // Data from Oregon Medical Laser Center
  //   http://omlc.ogi.edu/spectra/hemoglobin/index.html
  //////////////////////////////////////////////////////////////////////////

  /////////////////////////////////////////////////
  // Scott Prahl best guess data
  //  To convert this data to absorbance A, multiply by the molar concentration and the pathlength.
  //  For example, if x is the number of grams per liter and a 1 cm cuvette is being used,
  //  then the absorbance is given by:
  //
  //      (e) [(1/cm)/(moles/liter)] (x) [g/liter] (1) [cm]
  //  A =  ---------------------------------------------------
  //                     66,500 [g/mole]
  //
  //  using 66,500 as the gram molecular weight of hemoglobin.
  /////////////////////////////////////////////////

  // Concentration of hemoglobin in whole blood
  private static final double hb_concen_whole_blood = 150.0;      // g / L for whole blood from OMLC site

  // The wavelengths the data is for
  private static final double[] omlc_prahl_hemoglobin_wavelengths = ArrayUtil.range(250e-9, 1000e-9, 376);
//  { 250, 252, 254, 256, 258, 260, 262, 264, 266, 268, 270, 272, 274, 276, 278, 280, 282,
//  284, 286, 288, 290, 292, 294, 296, 298, 300, 302, 304, 306, 308, 310, 312, 314, 316,
//  318, 320, 322, 324, 326, 328, 330, 332, 334, 336, 338, 340, 342, 344, 346, 348, 350,
//  352, 354, 356, 358, 360, 362, 364, 366, 368, 370, 372, 374, 376, 378, 380, 382, 384,
//  386, 388, 390, 392, 394, 396, 398, 400, 402, 404, 406, 408, 410, 412, 414, 416, 418,
//  420, 422, 424, 426, 428, 430, 432, 434, 436, 438, 440, 442, 444, 446, 448, 450, 452,
//  454, 456, 458, 460, 462, 464, 466, 468, 470, 472, 474, 476, 478, 480, 482, 484, 486,
//  488, 490, 492, 494, 496, 498, 500, 502, 504, 506, 508, 510, 512, 514, 516, 518, 520,
//  522, 524, 526, 528, 530, 532, 534, 536, 538, 540, 542, 544, 546, 548, 550, 552, 554,
//  556, 558, 560, 562, 564, 566, 568, 570, 572, 574, 576, 578, 580, 582, 584, 586, 588,
//  590, 592, 594, 596, 598, 600, 602, 604, 606, 608, 610, 612, 614, 616, 618, 620, 622,
//  624, 626, 628, 630, 632, 634, 636, 638, 640, 642, 644, 646, 648, 650, 652, 654, 656,
//  658, 660, 662, 664, 666, 668, 670, 672, 674, 676, 678, 680, 682, 684, 686, 688, 690,
//  692, 694, 696, 698, 700, 702, 704, 706, 708, 710, 712, 714, 716, 718, 720, 722, 724,
//  726, 728, 730, 732, 734, 736, 738, 740, 742, 744, 746, 748, 750, 752, 754, 756, 758,
//  760, 762, 764, 766, 768, 770, 772, 774, 776, 778, 780, 782, 784, 786, 788, 790, 792,
//  794, 796, 798, 800, 802, 804, 806, 808, 810, 812, 814, 816, 818, 820, 822, 824, 826,
//  828, 830, 832, 834, 836, 838, 840, 842, 844, 846, 848, 850, 852, 854, 856, 858, 860,
//  862, 864, 866, 868, 870, 872, 874, 876, 878, 880, 882, 884, 886, 888, 890, 892, 894,
//  896, 898, 900, 902, 904, 906, 908, 910, 912, 914, 916, 918, 920, 922, 924, 926, 928,
//  930, 932, 934, 936, 938, 940, 942, 944, 946, 948, 950, 952, 954, 956, 958, 960, 962,
//  964, 966, 968, 970, 972, 974, 976, 978, 980, 982, 984, 986, 988, 990, 992, 994, 996,
//  998, 1000 };

  // Data for oxy-hemoglobin
  private static final double[] omlc_prahl_oxyhemoglobin =
  { 106112, 105552, 107660, 109788, 112944, 116376, 120188, 124412, 128696, 133064, 136068,
  137232, 138408, 137424, 135820, 131936, 127720, 122280, 116508, 108484, 104752, 98936, 88136,
  79316, 70884, 65972, 63208, 61952, 62352, 62856, 63352, 65972, 69016, 72404, 75536, 78752,
  82256, 85972, 89796, 93768, 97512, 100964, 103504, 104968, 106452, 107884, 109060, 110092,
  109032, 107984, 106576, 105040, 103696, 101568, 97828, 94744, 92248, 89836, 88484, 87512, 88176,
  91592, 95140, 98936, 103432, 109564, 116968, 125420, 135132, 148100, 167748, 189740, 212060,
  231612, 248404, 266232, 284224, 308716, 354208, 422320, 466840, 500200, 524280, 521880, 515520,
  480360, 431880, 376236, 326032, 283112, 246072, 214120, 165332, 132820, 119140, 102580, 92780,
  81444, 76324, 67044, 62816, 58864, 53552, 49496, 47496, 44480, 41320, 39807.2, 37073.2, 34870.8,
  33209.2, 31620, 30113.6, 28850.8, 27718, 26629.2, 25701.6, 25180.4, 24669.6, 24174.8, 23684.4,
  23086.8, 22457.6, 21850.4, 21260, 20932.8, 20596.4, 20418, 19946, 19996, 20035.2, 20150.4,
  20429.2, 21001.6, 22509.6, 24202.4, 26450.4, 29269.2, 32496.4, 35990, 39956.8, 43876, 46924,
  49752, 51712, 53236, 53292, 52096, 49868, 46660, 43016, 39675.2, 36815.2, 34476.8, 33456,
  32613.2, 32620, 33915.6, 36495.2, 40172, 44496, 49172, 53308, 55540, 54728, 50104, 43304,
  34639.6, 26600.4, 19763.2, 14400.8, 10468.4, 7678.8, 5683.6, 4504.4, 3200, 2664, 2128, 1789.2,
  1647.6, 1506, 1364.4, 1222.8, 1110, 1026, 942, 858, 774, 707.6, 658.8, 610, 561.2, 512.4, 478.8,
  460.4, 442, 423.6, 405.2, 390.4, 379.2, 368, 356.8, 345.6, 335.2, 325.6, 319.6, 314, 308.4,
  302.8, 298, 294, 290, 285.6, 282, 279.2, 277.6, 276, 274.4, 272.8, 274.4, 276, 277.6, 279.2,
  282, 286, 290, 294, 298, 302.8, 308.4, 314, 319.6, 325.2, 332, 340, 348, 356, 364, 372.4, 381.2,
  390, 398.8, 407.6, 418.8, 432.4, 446, 459.6, 473.2, 487.6, 502.8, 518, 533.2, 548.4, 562, 574,
  586, 598, 610, 622.8, 636.4, 650, 663.6, 677.2, 689.2, 699.6, 710, 720.4, 730.8, 740, 748, 756,
  764, 772, 786.4, 807.2, 816, 828, 836, 844, 856, 864, 872, 880, 887.2, 901.6, 916, 930.4, 944.8,
  956.4, 965.2, 974, 982.8, 991.6, 1001.2, 1011.6, 1022, 1032.4, 1042.8, 1050, 1054, 1058, 1062, 1066,
  1072.8, 1082.4, 1092, 1101.6, 1111.2, 1118.4, 1123.2, 1128, 1132.8, 1137.6, 1142.8, 1148.4, 1154,
  1159.6, 1165.2, 1170, 1174, 1178, 1182, 1186, 1190, 1194, 1198, 1202, 1206, 1209.2, 1211.6, 1214,
  1216.4, 1218.8, 1220.8, 1222.4, 1224, 1225.6, 1227.2, 1226.8, 1224.4, 1222, 1219.6, 1217.2, 1215.6,
  1214.8, 1214, 1213.2, 1212.4, 1210.4, 1207.2, 1204, 1200.8, 1197.6, 1194, 1190, 1186, 1182, 1178,
  1173.2, 1167.6, 1162, 1156.4, 1150.8, 1144, 1136, 1128, 1120, 1112, 1102.4, 1091.2, 1080, 1068.8,
  1057.6, 1046.4, 1035.2, 1024 };

  // Data for deoxy-hemoglobin
  private static final double[] omlc_prahl_deoxyhemoglobin =
  { 112736, 112736, 112736, 113824, 115040, 116296, 117564, 118876, 120208, 121544, 122880, 123096,
  121952, 120808, 119840, 118872, 117628, 114820, 112008, 107140, 98364, 91636, 85820, 77100, 69444,
  64440, 61300, 58828, 56908, 57620, 59156, 62248, 65344, 68312, 71208, 74508, 78284, 82060, 85592,
  88516, 90856, 93192, 95532, 99792, 104476, 108472, 110996, 113524, 116052, 118752, 122092, 125436,
  128776, 132120, 133632, 134940, 136044, 136972, 137900, 138856, 139968, 141084, 142196, 143312,
  144424, 145232, 145232, 148668, 153908, 159544, 167780, 180004, 191540, 202124, 212712, 223296,
  236188, 253368, 270548, 287356, 303956, 321344, 342596, 363848, 385680, 407560, 429880, 461200,
  481840, 500840, 528600, 552160, 552160, 547040, 501560, 413280, 363240, 282724, 237224, 173320,
  103292, 62640, 36170, 30698.8, 25886.4, 23388.8, 20891.2, 19260.8, 18142.4, 17025.6, 16156.4, 15310,
  15048.4, 14792.8, 14657.2, 14550, 14881.2, 15212.4, 15543.6, 15898, 16684, 17469.6, 18255.6, 19041.2,
  19891.2, 20862, 21832.8, 22803.6, 23774.4, 24745.2, 25773.6, 26936.8, 28100, 29263.2, 30426.4,
  31589.6, 32851.2, 34397.6, 35944, 37490, 39036.4, 40584, 42088, 43592, 45092, 46592, 48148, 49708,
  51268, 52496, 53412, 54080, 54520, 54540, 54164, 53788, 52276, 50572, 48828, 46948, 45072, 43340,
  41716, 40092, 38467.6, 37020, 35676.4, 34332.8, 32851.6, 31075.2, 28324.4, 25470, 22574.8, 19800,
  17058.4, 14677.2, 13622.4, 12567.6, 11513.2, 10477.6, 9443.6, 8591.2, 7762, 7344.8, 6927.2, 6509.6,
  6193.2, 5906.8, 5620, 5366.8, 5148.8, 4930.8, 4730.8, 4602.4, 4473.6, 4345.2, 4216.8, 4088.4, 3965.08,
  3857.6, 3750.12, 3642.64, 3535.16, 3427.68, 3320.2, 3226.56, 3140.28, 3053.96, 2967.68, 2881.4,
  2795.12, 2708.84, 2627.64, 2554.4, 2481.16, 2407.92, 2334.68, 2261.48, 2188.24, 2115, 2051.96, 2000.48,
  1949.04, 1897.56, 1846.08, 1794.28, 1741, 1687.76, 1634.48, 1583.52, 1540.48, 1497.4, 1454.36, 1411.32,
  1368.28, 1325.88, 1285.16, 1244.44, 1203.68, 1152.8, 1102.2, 1102.2, 1102.2, 1101.76, 1100.48, 1115.88,
  1161.64, 1207.4, 1266.04, 1333.24, 1405.24, 1515.32, 1541.76, 1560.48, 1560.48, 1548.52, 1508.44,
  1459.56, 1410.52, 1361.32, 1311.88, 1262.44, 1213, 1163.56, 1114.8, 1075.44, 1036.08, 996.72, 957.36,
  921.8, 890.8, 859.8, 828.8, 802.96, 782.36, 761.72, 743.84, 737.08, 730.28, 723.52, 717.08, 711.84,
  706.6, 701.32, 696.08, 693.76, 693.6, 693.48, 693.32, 693.2, 693.04, 692.92, 692.76, 692.64, 692.48,
  692.36, 692.2, 691.96, 691.76, 691.52, 691.32, 691.08, 690.88, 690.64, 692.44, 694.32, 696.2, 698.04,
  699.92, 701.8, 705.84, 709.96, 714.08, 718.2, 722.32, 726.44, 729.84, 733.2, 736.6, 739.96, 743.6, 747.24,
  750.88, 754.52, 758.16, 761.84, 765.04, 767.44, 769.8, 772.16, 774.56, 776.92, 778.4, 778.04, 777.72,
  777.36, 777.04, 776.64, 772.36, 768.08, 763.84, 752.28, 737.56, 722.88, 708.16, 693.44, 678.72, 660.52,
  641.08, 621.64, 602.24, 583.4, 568.92, 554.48, 540.04, 525.56, 511.12, 495.36, 473.32, 451.32, 429.32,
  415.28, 402.28, 389.288, 374.944, 359.656, 344.372, 329.084, 313.796, 298.508, 283.22, 267.932, 252.648,
  237.36, 222.072, 206.784 };

  //////////////////////////////////////////////////////////////////////////
  // Data from Oregon Medical Laser Center
  //   http://omlc.ogi.edu/spectra/PhotochemCAD/html/bilirubin.html
  //////////////////////////////////////////////////////////////////////////

  /////////////////////////////////////////////////
  // Scott Prahl best guess data
  //   To convert this data to absorbance A=-log10(T),
  //   multiply by the molar concentration and the pathlength in centimeters
  /////////////////////////////////////////////////

  // Concentration of bilirubin in whole blood
  private static final double bilirubin_concen_whole_blood = 0.05// g / L for whole blood
                                // Biologically plausible range goes from 0.005 - 5

  // The wavelengths the data is for
  private static final double[] omlc_prahl_bilirubin_wavelengths = ArrayUtil.range(239.75e-9, 700.00e-9, 1842);
//  { 239.75, 240, 240.25, 240.5, 240.75, 241, 241.25, 241.5, 241.75, 242, 242.25, 242.5, 242.75, 243, 243.25, 243.5, 243.75,
//  244, 244.25, 244.5, 244.75, 245, 245.25, 245.5, 245.75, 246, 246.25, 246.5, 246.75, 247, 247.25, 247.5, 247.75, 248,
//  248.25, 248.5, 248.75, 249, 249.25, 249.5, 249.75, 250, 250.25, 250.5, 250.75, 251, 251.25, 251.5, 251.75, 252, 252.25,
//  252.5, 252.75, 253, 253.25, 253.5, 253.75, 254, 254.25, 254.5, 254.75, 255, 255.25, 255.5, 255.75, 256, 256.25, 256.5,
//  256.75, 257, 257.25, 257.5, 257.75, 258, 258.25, 258.5, 258.75, 259, 259.25, 259.5, 259.75, 260, 260.25, 260.5, 260.75,
//  261, 261.25, 261.5, 261.75, 262, 262.25, 262.5, 262.75, 263, 263.25, 263.5, 263.75, 264, 264.25, 264.5, 264.75, 265, 265.25,
//  265.5, 265.75, 266, 266.25, 266.5, 266.75, 267, 267.25, 267.5, 267.75, 268, 268.25, 268.5, 268.75, 269, 269.25, 269.5, 269.75,
//  270, 270.25, 270.5, 270.75, 271, 271.25, 271.5, 271.75, 272, 272.25, 272.5, 272.75, 273, 273.25, 273.5, 273.75, 274, 274.25,
//  274.5, 274.75, 275, 275.25, 275.5, 275.75, 276, 276.25, 276.5, 276.75, 277, 277.25, 277.5, 277.75, 278, 278.25, 278.5, 278.75,
//  279, 279.25, 279.5, 279.75, 280, 280.25, 280.5, 280.75, 281, 281.25, 281.5, 281.75, 282, 282.25, 282.5, 282.75, 283, 283.25,
//  283.5, 283.75, 284, 284.25, 284.5, 284.75, 285, 285.25, 285.5, 285.75, 286, 286.25, 286.5, 286.75, 287, 287.25, 287.5, 287.75,
//  288, 288.25, 288.5, 288.75, 289, 289.25, 289.5, 289.75, 290, 290.25, 290.5, 290.75, 291, 291.25, 291.5, 291.75, 292, 292.25, 292.5,
//  292.75, 293, 293.25, 293.5, 293.75, 294, 294.25, 294.5, 294.75, 295, 295.25, 295.5, 295.75, 296, 296.25, 296.5, 296.75, 297,
//  297.25, 297.5, 297.75, 298, 298.25, 298.5, 298.75, 299, 299.25, 299.5, 299.75, 300, 300.25, 300.5, 300.75, 301, 301.25, 301.5,
//  301.75, 302, 302.25, 302.5, 302.75, 303, 303.25, 303.5, 303.75, 304, 304.25, 304.5, 304.75, 305, 305.25, 305.5, 305.75, 306, 306.25,
//  306.5, 306.75, 307, 307.25, 307.5, 307.75, 308, 308.25, 308.5, 308.75, 309, 309.25, 309.5, 309.75, 310, 310.25, 310.5, 310.75,
//  311, 311.25, 311.5, 311.75, 312, 312.25, 312.5, 312.75, 313, 313.25, 313.5, 313.75, 314, 314.25, 314.5, 314.75, 315, 315.25, 315.5,
//  315.75, 316, 316.25, 316.5, 316.75, 317, 317.25, 317.5, 317.75, 318, 318.25, 318.5, 318.75, 319, 319.25, 319.5, 319.75, 320,
//  320.25, 320.5, 320.75, 321, 321.25, 321.5, 321.75, 322, 322.25, 322.5, 322.75, 323, 323.25, 323.5, 323.75, 324, 324.25, 324.5, 324.75,
//  325, 325.25, 325.5, 325.75, 326, 326.25, 326.5, 326.75, 327, 327.25, 327.5, 327.75, 328, 328.25, 328.5, 328.75, 329, 329.25, 329.5,
//  329.75, 330, 330.25, 330.5, 330.75, 331, 331.25, 331.5, 331.75, 332, 332.25, 332.5, 332.75, 333, 333.25, 333.5, 333.75, 334, 334.25,
//  334.5, 334.75, 335, 335.25, 335.5, 335.75, 336, 336.25, 336.5, 336.75, 337, 337.25, 337.5, 337.75, 338, 338.25, 338.5, 338.75, 339,
//  339.25, 339.5, 339.75, 340, 340.25, 340.5, 340.75, 341, 341.25, 341.5, 341.75, 342, 342.25, 342.5, 342.75, 343, 343.25, 343.5, 343.75,
//  344, 344.25, 344.5, 344.75, 345, 345.25, 345.5, 345.75, 346, 346.25, 346.5, 346.75, 347, 347.25, 347.5, 347.75, 348, 348.25, 348.5,
//  348.75, 349, 349.25, 349.5, 349.75, 350, 350.25, 350.5, 350.75, 351, 351.25, 351.5, 351.75, 352, 352.25, 352.5, 352.75, 353, 353.25,
//  353.5, 353.75, 354, 354.25, 354.5, 354.75, 355, 355.25, 355.5, 355.75, 356, 356.25, 356.5, 356.75, 357, 357.25, 357.5, 357.75, 358,
//  358.25, 358.5, 358.75, 359, 359.25, 359.5, 359.75, 360, 360.25, 360.5, 360.75, 361, 361.25, 361.5, 361.75, 362, 362.25, 362.5, 362.75,
//  363, 363.25, 363.5, 363.75, 364, 364.25, 364.5, 364.75, 365, 365.25, 365.5, 365.75, 366, 366.25, 366.5, 366.75, 367, 367.25, 367.5, 367.75,
//  368, 368.25, 368.5, 368.75, 369, 369.25, 369.5, 369.75, 370, 370.25, 370.5, 370.75, 371, 371.25, 371.5, 371.75, 372, 372.25, 372.5, 372.75,
//  373, 373.25, 373.5, 373.75, 374, 374.25, 374.5, 374.75, 375, 375.25, 375.5, 375.75, 376, 376.25, 376.5, 376.75, 377, 377.25, 377.5, 377.75,
//  378, 378.25, 378.5, 378.75, 379, 379.25, 379.5, 379.75, 380, 380.25, 380.5, 380.75, 381, 381.25, 381.5, 381.75, 382, 382.25, 382.5, 382.75,
//  383, 383.25, 383.5, 383.75, 384, 384.25, 384.5, 384.75, 385, 385.25, 385.5, 385.75, 386, 386.25, 386.5, 386.75, 387, 387.25, 387.5, 387.75,
//  388, 388.25, 388.5, 388.75, 389, 389.25, 389.5, 389.75, 390, 390.25, 390.5, 390.75, 391, 391.25, 391.5, 391.75, 392, 392.25, 392.5, 392.75,
//  393, 393.25, 393.5, 393.75, 394, 394.25, 394.5, 394.75, 395, 395.25, 395.5, 395.75, 396, 396.25, 396.5, 396.75, 397, 397.25, 397.5, 397.75,
//  398, 398.25, 398.5, 398.75, 399, 399.25, 399.5, 399.75, 400, 400.25, 400.5, 400.75, 401, 401.25, 401.5, 401.75, 402, 402.25, 402.5, 402.75,
//  403, 403.25, 403.5, 403.75, 404, 404.25, 404.5, 404.75, 405, 405.25, 405.5, 405.75, 406, 406.25, 406.5, 406.75, 407, 407.25, 407.5, 407.75,
//  408, 408.25, 408.5, 408.75, 409, 409.25, 409.5, 409.75, 410, 410.25, 410.5, 410.75, 411, 411.25, 411.5, 411.75, 412, 412.25, 412.5, 412.75,
//  413, 413.25, 413.5, 413.75, 414, 414.25, 414.5, 414.75, 415, 415.25, 415.5, 415.75, 416, 416.25, 416.5, 416.75, 417, 417.25, 417.5, 417.75,
//  418, 418.25, 418.5, 418.75, 419, 419.25, 419.5, 419.75, 420, 420.25, 420.5, 420.75, 421, 421.25, 421.5, 421.75, 422, 422.25, 422.5, 422.75,
//  423, 423.25, 423.5, 423.75, 424, 424.25, 424.5, 424.75, 425, 425.25, 425.5, 425.75, 426, 426.25, 426.5, 426.75, 427, 427.25, 427.5, 427.75,
//  428, 428.25, 428.5, 428.75, 429, 429.25, 429.5, 429.75, 430, 430.25, 430.5, 430.75, 431, 431.25, 431.5, 431.75, 432, 432.25, 432.5, 432.75,
//  433, 433.25, 433.5, 433.75, 434, 434.25, 434.5, 434.75, 435, 435.25, 435.5, 435.75, 436, 436.25, 436.5, 436.75, 437, 437.25, 437.5, 437.75,
//  438, 438.25, 438.5, 438.75, 439, 439.25, 439.5, 439.75, 440, 440.25, 440.5, 440.75, 441, 441.25, 441.5, 441.75, 442, 442.25, 442.5, 442.75,
//  443, 443.25, 443.5, 443.75, 444, 444.25, 444.5, 444.75, 445, 445.25, 445.5, 445.75, 446, 446.25, 446.5, 446.75, 447, 447.25, 447.5, 447.75,
//  448, 448.25, 448.5, 448.75, 449, 449.25, 449.5, 449.75, 450, 450.25, 450.5, 450.75, 451, 451.25, 451.5, 451.75, 452, 452.25, 452.5, 452.75,
//  453, 453.25, 453.5, 453.75, 454, 454.25, 454.5, 454.75, 455, 455.25, 455.5, 455.75, 456, 456.25, 456.5, 456.75, 457, 457.25, 457.5, 457.75,
//  458, 458.25, 458.5, 458.75, 459, 459.25, 459.5, 459.75, 460, 460.25, 460.5, 460.75, 461, 461.25, 461.5, 461.75, 462, 462.25, 462.5, 462.75,
//  463, 463.25, 463.5, 463.75, 464, 464.25, 464.5, 464.75, 465, 465.25, 465.5, 465.75, 466, 466.25, 466.5, 466.75, 467, 467.25, 467.5, 467.75,
//  468, 468.25, 468.5, 468.75, 469, 469.25, 469.5, 469.75, 470, 470.25, 470.5, 470.75, 471, 471.25, 471.5, 471.75, 472, 472.25, 472.5, 472.75,
//  473, 473.25, 473.5, 473.75, 474, 474.25, 474.5, 474.75, 475, 475.25, 475.5, 475.75, 476, 476.25, 476.5, 476.75, 477, 477.25, 477.5, 477.75,
//  478, 478.25, 478.5, 478.75, 479, 479.25, 479.5, 479.75, 480, 480.25, 480.5, 480.75, 481, 481.25, 481.5, 481.75, 482, 482.25, 482.5, 482.75,
//  483, 483.25, 483.5, 483.75, 484, 484.25, 484.5, 484.75, 485, 485.25, 485.5, 485.75, 486, 486.25, 486.5, 486.75, 487, 487.25, 487.5, 487.75,
//  488, 488.25, 488.5, 488.75, 489, 489.25, 489.5, 489.75, 490, 490.25, 490.5, 490.75, 491, 491.25, 491.5, 491.75, 492, 492.25, 492.5, 492.75,
//  493, 493.25, 493.5, 493.75, 494, 494.25, 494.5, 494.75, 495, 495.25, 495.5, 495.75, 496, 496.25, 496.5, 496.75, 497, 497.25, 497.5, 497.75,
//  498, 498.25, 498.5, 498.75, 499, 499.25, 499.5, 499.75, 500, 500.25, 500.5, 500.75, 501, 501.25, 501.5, 501.75, 502, 502.25, 502.5, 502.75,
//  503, 503.25, 503.5, 503.75, 504, 504.25, 504.5, 504.75, 505, 505.25, 505.5, 505.75, 506, 506.25, 506.5, 506.75, 507, 507.25, 507.5, 507.75,
//  508, 508.25, 508.5, 508.75, 509, 509.25, 509.5, 509.75, 510, 510.25, 510.5, 510.75, 511, 511.25, 511.5, 511.75, 512, 512.25, 512.5, 512.75,
//  513, 513.25, 513.5, 513.75, 514, 514.25, 514.5, 514.75, 515, 515.25, 515.5, 515.75, 516, 516.25, 516.5, 516.75, 517, 517.25, 517.5, 517.75,
//  518, 518.25, 518.5, 518.75, 519, 519.25, 519.5, 519.75, 520, 520.25, 520.5, 520.75, 521, 521.25, 521.5, 521.75, 522, 522.25, 522.5, 522.75,
//  523, 523.25, 523.5, 523.75, 524, 524.25, 524.5, 524.75, 525, 525.25, 525.5, 525.75, 526, 526.25, 526.5, 526.75, 527, 527.25, 527.5, 527.75,
//  528, 528.25, 528.5, 528.75, 529, 529.25, 529.5, 529.75, 530, 530.25, 530.5, 530.75, 531, 531.25, 531.5, 531.75, 532, 532.25, 532.5, 532.75,
//  533, 533.25, 533.5, 533.75, 534, 534.25, 534.5, 534.75, 535, 535.25, 535.5, 535.75, 536, 536.25, 536.5, 536.75, 537, 537.25, 537.5, 537.75,
//  538, 538.25, 538.5, 538.75, 539, 539.25, 539.5, 539.75, 540, 540.25, 540.5, 540.75, 541, 541.25, 541.5, 541.75, 542, 542.25, 542.5, 542.75,
//  543, 543.25, 543.5, 543.75, 544, 544.25, 544.5, 544.75, 545, 545.25, 545.5, 545.75, 546, 546.25, 546.5, 546.75, 547, 547.25, 547.5, 547.75,
//  548, 548.25, 548.5, 548.75, 549, 549.25, 549.5, 549.75, 550, 550.25, 550.5, 550.75, 551, 551.25, 551.5, 551.75, 552, 552.25, 552.5, 552.75,
//  553, 553.25, 553.5, 553.75, 554, 554.25, 554.5, 554.75, 555, 555.25, 555.5, 555.75, 556, 556.25, 556.5, 556.75, 557, 557.25, 557.5, 557.75,
//  558, 558.25, 558.5, 558.75, 559, 559.25, 559.5, 559.75, 560, 560.25, 560.5, 560.75, 561, 561.25, 561.5, 561.75, 562, 562.25, 562.5, 562.75,
//  563, 563.25, 563.5, 563.75, 564, 564.25, 564.5, 564.75, 565, 565.25, 565.5, 565.75, 566, 566.25, 566.5, 566.75, 567, 567.25, 567.5, 567.75,
//  568, 568.25, 568.5, 568.75, 569, 569.25, 569.5, 569.75, 570, 570.25, 570.5, 570.75, 571, 571.25, 571.5, 571.75, 572, 572.25, 572.5, 572.75,
//  573, 573.25, 573.5, 573.75, 574, 574.25, 574.5, 574.75, 575, 575.25, 575.5, 575.75, 576, 576.25, 576.5, 576.75, 577, 577.25, 577.5, 577.75,
//  578, 578.25, 578.5, 578.75, 579, 579.25, 579.5, 579.75, 580, 580.25, 580.5, 580.75, 581, 581.25, 581.5, 581.75, 582, 582.25, 582.5, 582.75,
//  583, 583.25, 583.5, 583.75, 584, 584.25, 584.5, 584.75, 585, 585.25, 585.5, 585.75, 586, 586.25, 586.5, 586.75, 587, 587.25, 587.5, 587.75,
//  588, 588.25, 588.5, 588.75, 589, 589.25, 589.5, 589.75, 590, 590.25, 590.5, 590.75, 591, 591.25, 591.5, 591.75, 592, 592.25, 592.5, 592.75,
//  593, 593.25, 593.5, 593.75, 594, 594.25, 594.5, 594.75, 595, 595.25, 595.5, 595.75, 596, 596.25, 596.5, 596.75, 597, 597.25, 597.5, 597.75,
//  598, 598.25, 598.5, 598.75, 599, 599.25, 599.5, 599.75, 600, 600.25, 600.5, 600.75, 601, 601.25, 601.5, 601.75, 602, 602.25, 602.5, 602.75,
//  603, 603.25, 603.5, 603.75, 604, 604.25, 604.5, 604.75, 605, 605.25, 605.5, 605.75, 606, 606.25, 606.5, 606.75, 607, 607.25, 607.5, 607.75,
//  608, 608.25, 608.5, 608.75, 609, 609.25, 609.5, 609.75, 610, 610.25, 610.5, 610.75, 611, 611.25, 611.5, 611.75, 612, 612.25, 612.5, 612.75,
//  613, 613.25, 613.5, 613.75, 614, 614.25, 614.5, 614.75, 615, 615.25, 615.5, 615.75, 616, 616.25, 616.5, 616.75, 617, 617.25, 617.5, 617.75,
//  618, 618.25, 618.5, 618.75, 619, 619.25, 619.5, 619.75, 620, 620.25, 620.5, 620.75, 621, 621.25, 621.5, 621.75, 622, 622.25, 622.5, 622.75,
//  623, 623.25, 623.5, 623.75, 624, 624.25, 624.5, 624.75, 625, 625.25, 625.5, 625.75, 626, 626.25, 626.5, 626.75, 627, 627.25, 627.5, 627.75,
//  628, 628.25, 628.5, 628.75, 629, 629.25, 629.5, 629.75, 630, 630.25, 630.5, 630.75, 631, 631.25, 631.5, 631.75, 632, 632.25, 632.5, 632.75,
//  633, 633.25, 633.5, 633.75, 634, 634.25, 634.5, 634.75, 635, 635.25, 635.5, 635.75, 636, 636.25, 636.5, 636.75, 637, 637.25, 637.5, 637.75,
//  638, 638.25, 638.5, 638.75, 639, 639.25, 639.5, 639.75, 640, 640.25, 640.5, 640.75, 641, 641.25, 641.5, 641.75, 642, 642.25, 642.5, 642.75,
//  643, 643.25, 643.5, 643.75, 644, 644.25, 644.5, 644.75, 645, 645.25, 645.5, 645.75, 646, 646.25, 646.5, 646.75, 647, 647.25, 647.5, 647.75,
//  648, 648.25, 648.5, 648.75, 649, 649.25, 649.5, 649.75, 650, 650.25, 650.5, 650.75, 651, 651.25, 651.5, 651.75, 652, 652.25, 652.5, 652.75,
//  653, 653.25, 653.5, 653.75, 654, 654.25, 654.5, 654.75, 655, 655.25, 655.5, 655.75, 656, 656.25, 656.5, 656.75, 657, 657.25, 657.5, 657.75,
//  658, 658.25, 658.5, 658.75, 659, 659.25, 659.5, 659.75, 660, 660.25, 660.5, 660.75, 661, 661.25, 661.5, 661.75, 662, 662.25, 662.5, 662.75,
//  663, 663.25, 663.5, 663.75, 664, 664.25, 664.5, 664.75, 665, 665.25, 665.5, 665.75, 666, 666.25, 666.5, 666.75, 667, 667.25, 667.5, 667.75,
//  668, 668.25, 668.5, 668.75, 669, 669.25, 669.5, 669.75, 670, 670.25, 670.5, 670.75, 671, 671.25, 671.5, 671.75, 672, 672.25, 672.5, 672.75,
//  673, 673.25, 673.5, 673.75, 674, 674.25, 674.5, 674.75, 675, 675.25, 675.5, 675.75, 676, 676.25, 676.5, 676.75, 677, 677.25, 677.5, 677.75,
//  678, 678.25, 678.5, 678.75, 679, 679.25, 679.5, 679.75, 680, 680.25, 680.5, 680.75, 681, 681.25, 681.5, 681.75, 682, 682.25, 682.5, 682.75,
//  683, 683.25, 683.5, 683.75, 684, 684.25, 684.5, 684.75, 685, 685.25, 685.5, 685.75, 686, 686.25, 686.5, 686.75, 687, 687.25, 687.5, 687.75,
//  688, 688.25, 688.5, 688.75, 689, 689.25, 689.5, 689.75, 690, 690.25, 690.5, 690.75, 691, 691.25, 691.5, 691.75, 692, 692.25, 692.5, 692.75,
//  693, 693.25, 693.5, 693.75, 694, 694.25, 694.5, 694.75, 695, 695.25, 695.5, 695.75, 696, 696.25, 696.5, 696.75, 697, 697.25, 697.5, 697.75,
//  698, 698.25, 698.5, 698.75, 699, 699.25, 699.5, 699.75, 700 };

  // Data for bilirubin
  private static final double[] omlc_prahl_bilirubin =
  { 17201, 16068, 18569, 16903, 17803, 17777, 17727, 18609, 17730, 17525, 17575, 17601, 17134, 17096, 16660, 16587, 16104, 16569, 15957, 15464, 15799, 15298, 15237, 15224, 14719, 14475,
  14582, 14448, 13997, 14146, 13946, 13730, 13750, 13526, 13226, 13349, 13221, 12850, 13251, 12845, 12552, 12249, 12282, 12169, 12227, 11836, 11768, 11571, 11241, 11227, 11161, 11017,
  11029, 11063, 10785, 10687, 10564, 10473, 10337, 10342, 10025, 10160, 10052, 9966, 9862, 9941, 9760, 9628, 9777, 9667, 9522, 9219, 9092, 9217, 9308, 9142, 9135, 8952, 8980, 8858, 8930,
  8887, 8893, 8813, 8980, 8771, 8836, 8733, 8676, 8716, 8870, 8774, 8682, 8623, 8729, 8524, 8568, 8647, 8809, 8611, 8598, 8608, 8685, 8509, 8495, 8695, 8551, 8476, 8446, 8557, 8541, 8533,
  8445, 8467, 8571, 8516, 8577, 8515, 8457, 8511, 8613, 8616, 8678, 8433, 8505, 8569, 8523, 8470, 8540, 8588, 8512, 8534, 8692, 8547, 8544, 8593, 8541, 8432, 8692, 8468, 8557, 8723, 8628,
  8649, 8357, 8622, 8453, 8636, 8629, 8470, 8518, 8585, 8554, 8624, 8340, 8593, 8558, 8643, 8449, 8524, 8422, 8631, 8457, 8493, 8521, 8380, 8511, 8304, 8408, 8371, 8659, 8394, 8415, 8497,
  8562, 8224, 8283, 8579, 8331, 8301, 8217, 8310, 8208, 8299, 8223, 8231, 8468, 8202, 8310, 8255, 8234, 8231, 8207, 8101, 8200, 8266, 8135, 8027, 8060, 8100, 8116, 7871, 7967, 8078, 8065,
  8112, 7940, 7908, 7805, 7873, 7944, 7829, 8021, 7864, 7654, 7795, 7737, 7742, 7619, 7716, 7919, 7807, 7706, 7781, 7742, 7641, 7639, 7510, 7606, 7789, 7661, 7411, 7512, 7594, 7624, 7575,
  7625, 7566, 7372, 7426, 7465, 7367, 7446, 7329, 7589, 7371, 7211, 7482, 7447, 7279, 7227, 7326, 7069, 7345, 7132, 7222, 7297, 7396, 7222, 7241, 7206, 7083, 7034, 7254, 7150, 6987, 6792,
  7010, 6990, 7044, 7083, 6897, 6821, 6735, 6894, 6850, 7080, 6901, 6892, 6823, 6818, 6808, 6905, 6801, 6520, 6557, 6615, 6686, 6699, 6630, 6546, 6665, 6577, 6517, 6604, 6336, 6557, 6527,
  6383, 6423, 6344, 6455, 6316, 6258, 6210, 6275, 6174, 6217, 6360, 6158, 6302, 6068, 6198, 6175, 6106, 6031, 5909, 5862, 5948, 5993, 5899, 6008, 5813, 5751, 5994, 5884, 5828, 5814, 5625,
  5867, 5619, 5557, 5695, 5677, 5542, 5476, 5635, 5688, 5484, 5323, 5450, 5326, 5430, 5562, 5207, 5192, 5148, 5250, 5309, 5055, 5095, 5310, 5206, 5029, 4894, 5166, 5076, 4927, 5028, 4920,
  4864, 4850, 4969, 4963, 4755, 4829, 4922, 4577, 4745, 4800, 4653, 4735, 4793, 4820, 4697, 4699, 4651, 4350, 4607, 4521, 4421, 4572, 4882, 4721, 4336, 4558, 4592, 4805, 4530, 4440, 4468,
  4423, 4530, 4266, 4398, 4247, 4381, 4349, 4345, 4388, 4630, 4393, 4328, 4229, 4439, 4369, 4359, 4381, 4537, 4196, 4175, 4354, 4334, 4233, 4169, 4183, 4383, 4470, 4255, 4464, 4354, 4349,
  4554, 4297, 4224, 4507, 4500, 4555, 4383, 4370, 4532, 4384, 4627, 4395, 4667, 4686, 4252, 4564, 4803, 4685, 4723, 4637, 4569, 4542, 4736, 4799, 4727, 4912, 4841, 4824, 4960, 5067, 4861,
  4949, 5045, 5154, 5209, 5137, 4966, 5136, 5195, 5239, 5324, 5322, 5278, 5179, 5443, 5223, 5466, 5399, 5584, 5682, 5655, 5598, 5845, 5799, 5665, 5800, 5820, 5897, 6017, 5934, 5991, 6069,
  6069, 6132, 6220, 6194, 6217, 6383, 6340, 6460, 6447, 6668, 6543, 6719, 6661, 6675, 6707, 6862, 6762, 6969, 6995, 6989, 7076, 7223, 7157, 7292, 7438, 7389, 7441, 7482, 7601, 7715, 7724,
  7729, 7784, 8026, 7976, 8117, 8208, 8186, 8368, 8315, 8416, 8396, 8573, 8576, 8711, 8930, 8881, 8949, 8888, 9051, 9114, 9231, 9304, 9385, 9516, 9378, 9611, 9681, 9804, 9805, 10008, 9945,
  10161, 10156, 10357, 10414, 10523, 10583, 10716, 10791, 10828, 10927, 11095, 11348, 11245, 11376, 11483, 11546, 11688, 11776, 12013, 12021, 12153, 12148, 12316, 12372, 12537, 12556, 12909,
  12826, 12999, 13028, 13114, 13334, 13520, 13528, 13634, 13773, 13919, 14005, 14120, 14239, 14352, 14606, 14572, 14788, 14937, 14998, 15126, 15211, 15340, 15619, 15695, 15757, 15865, 16075,
  16192, 16328, 16611, 16743, 16916, 16890, 17146, 17356, 17299, 17501, 17638, 17940, 18070, 18298, 18353, 18556, 18673, 18939, 19070, 19249, 19378, 19595, 19810, 19832, 20010, 20297, 20528,
  20687, 20882, 21017, 21090, 21499, 21581, 21686, 22037, 22090, 22199, 22447, 22730, 22901, 23059, 23214, 23322, 23519, 23706, 23928, 24050, 24143, 24473, 24607, 24812, 24957, 25175, 25424,
  25594, 25568, 25920, 26115, 26383, 26457, 26624, 26726, 27045, 27218, 27439, 27845, 27854, 28165, 28128, 28455, 28628, 28734, 29131, 29156, 29514, 29624, 29845, 30037, 30289, 30556, 30632,
  30818, 30911, 31191, 31535, 31685, 31874, 32203, 32398, 32597, 32521, 32931, 32832, 33186, 33419, 33466, 33763, 34080, 34176, 34517, 34820, 34889, 35070, 35399, 35549, 35691, 35763, 36097,
  36416, 36580, 36878, 37123, 37271, 37543, 37571, 37941, 38196, 38459, 38624, 38886, 39028, 39276, 39629, 39658, 39869, 40219, 40282, 40881, 40959, 41128, 41191, 41421, 41641, 42006, 41919,
  42236, 42491, 42552, 42812, 42986, 43202, 43473, 43757, 43939, 44048, 44087, 44347, 44637, 44799, 44901, 45156, 45270, 45186, 45634, 45644, 46012, 45861, 46264, 46256, 46301, 46855, 46781,
  47014, 47163, 47139, 47477, 47718, 47603, 47924, 48048, 48024, 48460, 48532, 48434, 48774, 48961, 48803, 49340, 49314, 49541, 49343, 49775, 49809, 50174, 50037, 50059, 50450, 50221, 50191,
  50978, 50684, 50697, 51044, 51251, 51292, 51563, 51450, 51631, 51824, 51755, 51902, 52087, 52186, 52258, 52271, 52334, 52435, 52534, 52891, 52978, 52650, 52869, 52781, 53111, 52971, 53290,
  53476, 53547, 53354, 53704, 53567, 53443, 53308, 53527, 53832, 53922, 54077, 53780, 54020, 53705, 54182, 54297, 54300, 54313, 54341, 54175, 54422, 54570, 54646, 54547, 54791, 54865, 54993,
  54607, 55000, 54881, 54980, 54686, 54669, 54890, 54859, 54757, 54793, 54962, 54686, 54917, 54941, 54921, 54874, 54857, 54837, 54815, 54946, 54890, 54769, 54828, 54787, 54630, 54667, 54674,
  54476, 54388, 54356, 54433, 54453, 54484, 54295, 54156, 54345, 53959, 53753, 53846, 53840, 53743, 53665, 53590, 53399, 53140, 53197, 53051, 52783, 52621, 52633, 52275, 52324, 52103, 52102,
  51871, 51691, 51579, 51175, 51160, 50749, 50654, 50447, 50192, 50125, 49910, 49526, 49338, 49013, 48842, 48668, 48310, 47991, 47827, 47509, 47193, 47144, 46759, 46486, 46168, 45729, 45306,
  45040, 44690, 44294, 44085, 43963, 43419, 43033, 42703, 42352, 41971, 41716, 41225, 40771, 40478, 39926, 39677, 39243, 38749, 38201, 37878, 37452, 36965, 36495, 35988, 35519, 35141, 34631,
  34078, 33742, 33324, 32842, 32473, 31958, 31365, 30959, 30608, 30113, 29624, 29207, 28797, 28414, 27938, 27585, 27051, 26721, 26260, 25861, 25381, 24919, 24534, 24170, 23785, 23343, 22824,
  22523, 22114, 21584, 21324, 20944, 20402, 20077, 19763, 19378, 18932, 18556, 18204, 17820, 17426, 17145, 16787, 16448, 16029, 15685, 15361, 14989, 14672, 14357, 14019, 13745, 13410, 13098,
  12792, 12452, 12186, 11959, 11830, 11544, 11294, 11009, 10714, 10485, 10195, 9940, 9630, 9395, 9095, 8910, 8608, 8322, 8192, 7884, 7704, 7517, 7318, 7031, 6819, 6599, 6483, 6168, 6088, 5887,
  5719, 5506, 5399, 5180, 5066, 4891, 4766, 4532, 4460, 4284, 4202, 4052, 3874, 3752, 3653, 3486, 3412, 3332, 3150, 3150, 3036, 2898, 2793, 2746, 2654, 2529, 2502, 2359, 2326, 2210, 2143, 2030,
  2032, 2004, 1863, 1858, 1718, 1776, 1702, 1586, 1610, 1560, 1465, 1385, 1383, 1374, 1299, 1314, 1200, 1148, 1116, 1032, 1108, 995, 966, 941, 920, 908, 847, 848, 846, 737, 782, 724, 716, 704,
  624, 616, 574, 602, 582, 547, 507, 525, 486, 489, 487, 432, 397, 411, 418, 365, 401, 362, 376, 346, 340, 327, 357, 292, 306, 270, 273, 252, 212, 253, 285, 233, 251, 248, 236, 236, 214, 189,
  213, 202, 215, 170, 136, 183, 222, 148, 165, 134, 191, 177, 141, 157, 208, 180, 118, 117, 153, 122, 154, 179, 129, 103, 164, 118, 130, 83, 84, 99, 126, 153, 71, 109, 101, 72, 72, 114, 69, 72,
  90, 177, 107, 107, 81, 92, 122, 38, 15, 54, 120, 104, 60, 41, 82, 127, 102, 80, 67, 65, 33, 84, 67, 65, 93, 84, 59, 73, 14, 78, 9, 71, 40, 118, 57, 100, 90, 65, 61, 86, 69, 76, 47, 85, 71, 62,
  31, 69, 85, 69, 46, 94, 125, 33, 104, 70, 59, 33, 22, 2, 55, 42, 62, 76, 71, 81, 34, 64, 68, 57, 27, 62, 69, 45, 72, 90, 55, 105, 20, 47, 21, 11, 57, 77, 20, 57, 61, 106, 15, 8, 0, 69, 18, 48,
  6, 42, 28, 39, 13, 20, 42, 9, 53, 67, 39, 72, 41, 52, 73, 39, 0, 72, 64, 52, 109, 12, 50, 0, 10, 36, 60, 78, 15, 28, 52, 99, 10, 0, 40, 0, 17, 64, 82, 19, 29, 38, 7, 65, 36, 19, 18, 0, 46, 0,
  20, 12, 9, 0, 0, 3, 47, 40, 17, 34, 11, 33, 19, 30, 68, 52, 9, 21, 34, 24, 8, 0, 24, 32, 54, 19, 14, 12, 59, 32, 79, 0, 40, 0, 14, 22, 77, 26, 2, 0, 0, 0, 25, 0, 29, 0, 17, 0, 0, 52, 27, 0, 17,
  0, 0, 19, 22, 21, 0, 0, 49, 0, 5, 61, 30, 16, 55, 0, 16, 0, 0, 16, 47, 30, 0, 44, 0, 12, 57, 51, 44, 22, 46, 0, 60, 27, 78, 39, 74, 56, 0, 0, 26, 55, 18, 111, 18, 0, 11, 0, 0, 57, 6, 0, 52, 38,
  30, 24, 85, 28, 37, 3, 0, 67, 0, 8, 56, 71, 59, 40, 0, 6, 17, 9, 74, 91, 42, 3, 65, 0, 23, 56, 0, 6, 0, 0, 72, 25, 53, 8, 29, 37, 30, 0, 60, 12, 37, 8, 0, 0, 25, 69, 78, 65, 19, 7, 38, 82,
  54, 2, 30, 2, 0, 22, 48, 0, 32, 3, 39, 12, 12, 0, 50, 6, 0, 80, 19, 20, 86, 0, 29, 36, 85, 31, 15, 4, 85, 0, 46, 25, 0, 0, 0, 0, 0, 70, 30, 25, 0, 89, 0, 3, 62, 28, 29, 47, 55, 0, 49, 5, 51, 0,
  70, 0, 65, 0, 78, 0, 28, 0, 78, 58, 16, 41, 0, 0, 77, 0, 36, 2, 16, 0, 13, 14, 47, 0, 0, 34, 28, 43, 0, 0, 29, 51, 60, 45, 0, 51, 27, 71, 54, 61, 29, 91, 0, 12, 16, 14, 33, 75, 78, 0, 13, 48, 0,
  0, 0, 0, 29, 33, 0, 0, 6, 61, 36, 11, 27, 56, 5, 43, 16, 0, 0, 76, 32, 0, 0, 40, 20, 39, 0, 0, 0, 18, 0, 33, 54, 0, 0, 12, 91, 0, 0, 0, 0, 0, 94, 36, 0, 87, 35, 34, 0, 26, 0, 0, 0, 79, 86, 0, 0,
  77, 0, 36, 3, 0, 8, 19, 0, 0, 6, 24, 80, 7, 0, 0, 0, 61, 79, 0, 52, 0, 53, 94, 55, 0, 14, 99, 0, 42, 0, 53, 59, 74, 0, 54, 60, 0, 30, 25, 0, 8, 25, 68, 6, 47, 25, 0, 27, 106, 0, 62, 38, 81, 38,
  104, 18, 111, 0, 74, 52, 36, 0, 50, 44, 43, 55, 66, 48, 0, 48, 87, 68, 2, 31, 0, 16, 27, 87, 181, 87, 44, 107, 44, 89, 28, 14, 73, 7, 77, 44, 80, 14, 12, 33, 11, 5, 0, 0, 12, 0, 0, 48, 34, 0, 58,
  159, 46, 64, 17, 30, 0, 21, 0, 0, 6, 86, 37, 0, 0, 53, 6, 22, 41, 60, 39, 52, 8, 46, 43, 11, 12, 0, 8, 15, 0, 33, 33, 0, 33, 11, 25, 50, 0, 0, 0, 0, 0, 8, 0, 45, 0, 17, 12, 33, 0, 54, 35, 35,
  51, 19, 0, 0, 71, 0, 8, 22, 9, 41, 0, 0, 12, 21, 0, 49, 13, 24, 0, 0, 0, 3, 17, 0, 71, 32, 0, 0, 53, 12, 45, 50, 0, 5, 0, 8, 35, 0, 0, 103 };

  //////////////////////////////////////////////////////////////////////////
  // Data from Oregon Medical Laser Center
  //   http://omlc.ogi.edu/spectra/PhotochemCAD/abs_html/beta-carotene.html
  //////////////////////////////////////////////////////////////////////////

  /////////////////////////////////////////////////
  //   To convert this data to absorbance A=-log10(T),
  //   multiply by the molar concentration and the pathlength in centimeters
  /////////////////////////////////////////////////

  // Concentration of beta-carotene in epidermis
  private static final double betacarotene_concen_epidermis = 2.1e-4;    // g / L for epidermis

  // Concentration of beta-carotene in the dermis
  private static final double betacarotene_concen_dermis = 7.0e-5;    // g / L for dermis

  // The wavelengths the data is for
  private static final double[] omlc_prahl_betacarotene_wavelengths = ArrayUtil.range(219.75e-9, 700.00e-9, 1922);
//  { 219.75, 220, 220.25, 220.5, 220.75, 221, 221.25, 221.5, 221.75, 222, 222.25, 222.5, 222.75, 223, 223.25, 223.5, 223.75, 224, 224.25, 224.5, 224.75, 225, 225.25, 225.5, 225.75, 226, 226.25, 226.5, 226.75, 227,
//  227.25, 227.5, 227.75, 228, 228.25, 228.5, 228.75, 229, 229.25, 229.5, 229.75, 230, 230.25, 230.5, 230.75, 231, 231.25, 231.5, 231.75, 232, 232.25, 232.5, 232.75, 233, 233.25, 233.5, 233.75, 234, 234.25, 234.5,
//  234.75, 235, 235.25, 235.5, 235.75, 236, 236.25, 236.5, 236.75, 237, 237.25, 237.5, 237.75, 238, 238.25, 238.5, 238.75, 239, 239.25, 239.5, 239.75, 240, 240.25, 240.5, 240.75, 241, 241.25, 241.5, 241.75, 242,
//  242.25, 242.5, 242.75, 243, 243.25, 243.5, 243.75, 244, 244.25, 244.5, 244.75, 245, 245.25, 245.5, 245.75, 246, 246.25, 246.5, 246.75, 247, 247.25, 247.5, 247.75, 248, 248.25, 248.5, 248.75, 249, 249.25, 249.5,
//  249.75, 250, 250.25, 250.5, 250.75, 251, 251.25, 251.5, 251.75, 252, 252.25, 252.5, 252.75, 253, 253.25, 253.5, 253.75, 254, 254.25, 254.5, 254.75, 255, 255.25, 255.5, 255.75, 256, 256.25, 256.5, 256.75, 257,
//  257.25, 257.5, 257.75, 258, 258.25, 258.5, 258.75, 259, 259.25, 259.5, 259.75, 260, 260.25, 260.5, 260.75, 261, 261.25, 261.5, 261.75, 262, 262.25, 262.5, 262.75, 263, 263.25, 263.5, 263.75, 264, 264.25, 264.5,
//  264.75, 265, 265.25, 265.5, 265.75, 266, 266.25, 266.5, 266.75, 267, 267.25, 267.5, 267.75, 268, 268.25, 268.5, 268.75, 269, 269.25, 269.5, 269.75, 270, 270.25, 270.5, 270.75, 271, 271.25, 271.5, 271.75, 272,
//  272.25, 272.5, 272.75, 273, 273.25, 273.5, 273.75, 274, 274.25, 274.5, 274.75, 275, 275.25, 275.5, 275.75, 276, 276.25, 276.5, 276.75, 277, 277.25, 277.5, 277.75, 278, 278.25, 278.5, 278.75, 279, 279.25, 279.5,
//  279.75, 280, 280.25, 280.5, 280.75, 281, 281.25, 281.5, 281.75, 282, 282.25, 282.5, 282.75, 283, 283.25, 283.5, 283.75, 284, 284.25, 284.5, 284.75, 285, 285.25, 285.5, 285.75, 286, 286.25, 286.5, 286.75, 287,
//  287.25, 287.5, 287.75, 288, 288.25, 288.5, 288.75, 289, 289.25, 289.5, 289.75, 290, 290.25, 290.5, 290.75, 291, 291.25, 291.5, 291.75, 292, 292.25, 292.5, 292.75, 293, 293.25, 293.5, 293.75, 294, 294.25, 294.5,
//  294.75, 295, 295.25, 295.5, 295.75, 296, 296.25, 296.5, 296.75, 297, 297.25, 297.5, 297.75, 298, 298.25, 298.5, 298.75, 299, 299.25, 299.5, 299.75, 300, 300.25, 300.5, 300.75, 301, 301.25, 301.5, 301.75, 302,
//  302.25, 302.5, 302.75, 303, 303.25, 303.5, 303.75, 304, 304.25, 304.5, 304.75, 305, 305.25, 305.5, 305.75, 306, 306.25, 306.5, 306.75, 307, 307.25, 307.5, 307.75, 308, 308.25, 308.5, 308.75, 309, 309.25, 309.5,
//  309.75, 310, 310.25, 310.5, 310.75, 311, 311.25, 311.5, 311.75, 312, 312.25, 312.5, 312.75, 313, 313.25, 313.5, 313.75, 314, 314.25, 314.5, 314.75, 315, 315.25, 315.5, 315.75, 316, 316.25, 316.5, 316.75, 317,
//  317.25, 317.5, 317.75, 318, 318.25, 318.5, 318.75, 319, 319.25, 319.5, 319.75, 320, 320.25, 320.5, 320.75, 321, 321.25, 321.5, 321.75, 322, 322.25, 322.5, 322.75, 323, 323.25, 323.5, 323.75, 324, 324.25, 324.5,
//  324.75, 325, 325.25, 325.5, 325.75, 326, 326.25, 326.5, 326.75, 327, 327.25, 327.5, 327.75, 328, 328.25, 328.5, 328.75, 329, 329.25, 329.5, 329.75, 330, 330.25, 330.5, 330.75, 331, 331.25, 331.5, 331.75, 332,
//  332.25, 332.5, 332.75, 333, 333.25, 333.5, 333.75, 334, 334.25, 334.5, 334.75, 335, 335.25, 335.5, 335.75, 336, 336.25, 336.5, 336.75, 337, 337.25, 337.5, 337.75, 338, 338.25, 338.5, 338.75, 339, 339.25, 339.5,
//  339.75, 340, 340.25, 340.5, 340.75, 341, 341.25, 341.5, 341.75, 342, 342.25, 342.5, 342.75, 343, 343.25, 343.5, 343.75, 344, 344.25, 344.5, 344.75, 345, 345.25, 345.5, 345.75, 346, 346.25, 346.5, 346.75, 347,
//  347.25, 347.5, 347.75, 348, 348.25, 348.5, 348.75, 349, 349.25, 349.5, 349.75, 350, 350.25, 350.5, 350.75, 351, 351.25, 351.5, 351.75, 352, 352.25, 352.5, 352.75, 353, 353.25, 353.5, 353.75, 354, 354.25, 354.5,
//  354.75, 355, 355.25, 355.5, 355.75, 356, 356.25, 356.5, 356.75, 357, 357.25, 357.5, 357.75, 358, 358.25, 358.5, 358.75, 359, 359.25, 359.5, 359.75, 360, 360.25, 360.5, 360.75, 361, 361.25, 361.5, 361.75, 362,
//  362.25, 362.5, 362.75, 363, 363.25, 363.5, 363.75, 364, 364.25, 364.5, 364.75, 365, 365.25, 365.5, 365.75, 366, 366.25, 366.5, 366.75, 367, 367.25, 367.5, 367.75, 368, 368.25, 368.5, 368.75, 369, 369.25, 369.5,
//  369.75, 370, 370.25, 370.5, 370.75, 371, 371.25, 371.5, 371.75, 372, 372.25, 372.5, 372.75, 373, 373.25, 373.5, 373.75, 374, 374.25, 374.5, 374.75, 375, 375.25, 375.5, 375.75, 376, 376.25, 376.5, 376.75, 377,
//  377.25, 377.5, 377.75, 378, 378.25, 378.5, 378.75, 379, 379.25, 379.5, 379.75, 380, 380.25, 380.5, 380.75, 381, 381.25, 381.5, 381.75, 382, 382.25, 382.5, 382.75, 383, 383.25, 383.5, 383.75, 384, 384.25, 384.5,
//  384.75, 385, 385.25, 385.5, 385.75, 386, 386.25, 386.5, 386.75, 387, 387.25, 387.5, 387.75, 388, 388.25, 388.5, 388.75, 389, 389.25, 389.5, 389.75, 390, 390.25, 390.5, 390.75, 391, 391.25, 391.5, 391.75, 392,
//  392.25, 392.5, 392.75, 393, 393.25, 393.5, 393.75, 394, 394.25, 394.5, 394.75, 395, 395.25, 395.5, 395.75, 396, 396.25, 396.5, 396.75, 397, 397.25, 397.5, 397.75, 398, 398.25, 398.5, 398.75, 399, 399.25, 399.5,
//  399.75, 400, 400.25, 400.5, 400.75, 401, 401.25, 401.5, 401.75, 402, 402.25, 402.5, 402.75, 403, 403.25, 403.5, 403.75, 404, 404.25, 404.5, 404.75, 405, 405.25, 405.5, 405.75, 406, 406.25, 406.5, 406.75, 407,
//  407.25, 407.5, 407.75, 408, 408.25, 408.5, 408.75, 409, 409.25, 409.5, 409.75, 410, 410.25, 410.5, 410.75, 411, 411.25, 411.5, 411.75, 412, 412.25, 412.5, 412.75, 413, 413.25, 413.5, 413.75, 414, 414.25, 414.5,
//  414.75, 415, 415.25, 415.5, 415.75, 416, 416.25, 416.5, 416.75, 417, 417.25, 417.5, 417.75, 418, 418.25, 418.5, 418.75, 419, 419.25, 419.5, 419.75, 420, 420.25, 420.5, 420.75, 421, 421.25, 421.5, 421.75, 422,
//  422.25, 422.5, 422.75, 423, 423.25, 423.5, 423.75, 424, 424.25, 424.5, 424.75, 425, 425.25, 425.5, 425.75, 426, 426.25, 426.5, 426.75, 427, 427.25, 427.5, 427.75, 428, 428.25, 428.5, 428.75, 429, 429.25, 429.5,
//  429.75, 430, 430.25, 430.5, 430.75, 431, 431.25, 431.5, 431.75, 432, 432.25, 432.5, 432.75, 433, 433.25, 433.5, 433.75, 434, 434.25, 434.5, 434.75, 435, 435.25, 435.5, 435.75, 436, 436.25, 436.5, 436.75, 437,
//  437.25, 437.5, 437.75, 438, 438.25, 438.5, 438.75, 439, 439.25, 439.5, 439.75, 440, 440.25, 440.5, 440.75, 441, 441.25, 441.5, 441.75, 442, 442.25, 442.5, 442.75, 443, 443.25, 443.5, 443.75, 444, 444.25, 444.5,
//  444.75, 445, 445.25, 445.5, 445.75, 446, 446.25, 446.5, 446.75, 447, 447.25, 447.5, 447.75, 448, 448.25, 448.5, 448.75, 449, 449.25, 449.5, 449.75, 450, 450.25, 450.5, 450.75, 451, 451.25, 451.5, 451.75, 452,
//  452.25, 452.5, 452.75, 453, 453.25, 453.5, 453.75, 454, 454.25, 454.5, 454.75, 455, 455.25, 455.5, 455.75, 456, 456.25, 456.5, 456.75, 457, 457.25, 457.5, 457.75, 458, 458.25, 458.5, 458.75, 459, 459.25, 459.5,
//  459.75, 460, 460.25, 460.5, 460.75, 461, 461.25, 461.5, 461.75, 462, 462.25, 462.5, 462.75, 463, 463.25, 463.5, 463.75, 464, 464.25, 464.5, 464.75, 465, 465.25, 465.5, 465.75, 466, 466.25, 466.5, 466.75, 467,
//  467.25, 467.5, 467.75, 468, 468.25, 468.5, 468.75, 469, 469.25, 469.5, 469.75, 470, 470.25, 470.5, 470.75, 471, 471.25, 471.5, 471.75, 472, 472.25, 472.5, 472.75, 473, 473.25, 473.5, 473.75, 474, 474.25, 474.5,
//  474.75, 475, 475.25, 475.5, 475.75, 476, 476.25, 476.5, 476.75, 477, 477.25, 477.5, 477.75, 478, 478.25, 478.5, 478.75, 479, 479.25, 479.5, 479.75, 480, 480.25, 480.5, 480.75, 481, 481.25, 481.5, 481.75, 482,
//  482.25, 482.5, 482.75, 483, 483.25, 483.5, 483.75, 484, 484.25, 484.5, 484.75, 485, 485.25, 485.5, 485.75, 486, 486.25, 486.5, 486.75, 487, 487.25, 487.5, 487.75, 488, 488.25, 488.5, 488.75, 489, 489.25, 489.5,
//  489.75, 490, 490.25, 490.5, 490.75, 491, 491.25, 491.5, 491.75, 492, 492.25, 492.5, 492.75, 493, 493.25, 493.5, 493.75, 494, 494.25, 494.5, 494.75, 495, 495.25, 495.5, 495.75, 496, 496.25, 496.5, 496.75, 497,
//  497.25, 497.5, 497.75, 498, 498.25, 498.5, 498.75, 499, 499.25, 499.5, 499.75, 500, 500.25, 500.5, 500.75, 501, 501.25, 501.5, 501.75, 502, 502.25, 502.5, 502.75, 503, 503.25, 503.5, 503.75, 504, 504.25, 504.5,
//  504.75, 505, 505.25, 505.5, 505.75, 506, 506.25, 506.5, 506.75, 507, 507.25, 507.5, 507.75, 508, 508.25, 508.5, 508.75, 509, 509.25, 509.5, 509.75, 510, 510.25, 510.5, 510.75, 511, 511.25, 511.5, 511.75, 512,
//  512.25, 512.5, 512.75, 513, 513.25, 513.5, 513.75, 514, 514.25, 514.5, 514.75, 515, 515.25, 515.5, 515.75, 516, 516.25, 516.5, 516.75, 517, 517.25, 517.5, 517.75, 518, 518.25, 518.5, 518.75, 519, 519.25, 519.5,
//  519.75, 520, 520.25, 520.5, 520.75, 521, 521.25, 521.5, 521.75, 522, 522.25, 522.5, 522.75, 523, 523.25, 523.5, 523.75, 524, 524.25, 524.5, 524.75, 525, 525.25, 525.5, 525.75, 526, 526.25, 526.5, 526.75, 527,
//  527.25, 527.5, 527.75, 528, 528.25, 528.5, 528.75, 529, 529.25, 529.5, 529.75, 530, 530.25, 530.5, 530.75, 531, 531.25, 531.5, 531.75, 532, 532.25, 532.5, 532.75, 533, 533.25, 533.5, 533.75, 534, 534.25, 534.5,
//  534.75, 535, 535.25, 535.5, 535.75, 536, 536.25, 536.5, 536.75, 537, 537.25, 537.5, 537.75, 538, 538.25, 538.5, 538.75, 539, 539.25, 539.5, 539.75, 540, 540.25, 540.5, 540.75, 541, 541.25, 541.5, 541.75, 542,
//  542.25, 542.5, 542.75, 543, 543.25, 543.5, 543.75, 544, 544.25, 544.5, 544.75, 545, 545.25, 545.5, 545.75, 546, 546.25, 546.5, 546.75, 547, 547.25, 547.5, 547.75, 548, 548.25, 548.5, 548.75, 549, 549.25, 549.5,
//  549.75, 550, 550.25, 550.5, 550.75, 551, 551.25, 551.5, 551.75, 552, 552.25, 552.5, 552.75, 553, 553.25, 553.5, 553.75, 554, 554.25, 554.5, 554.75, 555, 555.25, 555.5, 555.75, 556, 556.25, 556.5, 556.75, 557,
//  557.25, 557.5, 557.75, 558, 558.25, 558.5, 558.75, 559, 559.25, 559.5, 559.75, 560, 560.25, 560.5, 560.75, 561, 561.25, 561.5, 561.75, 562, 562.25, 562.5, 562.75, 563, 563.25, 563.5, 563.75, 564, 564.25, 564.5,
//  564.75, 565, 565.25, 565.5, 565.75, 566, 566.25, 566.5, 566.75, 567, 567.25, 567.5, 567.75, 568, 568.25, 568.5, 568.75, 569, 569.25, 569.5, 569.75, 570, 570.25, 570.5, 570.75, 571, 571.25, 571.5, 571.75, 572,
//  572.25, 572.5, 572.75, 573, 573.25, 573.5, 573.75, 574, 574.25, 574.5, 574.75, 575, 575.25, 575.5, 575.75, 576, 576.25, 576.5, 576.75, 577, 577.25, 577.5, 577.75, 578, 578.25, 578.5, 578.75, 579, 579.25, 579.5,
//  579.75, 580, 580.25, 580.5, 580.75, 581, 581.25, 581.5, 581.75, 582, 582.25, 582.5, 582.75, 583, 583.25, 583.5, 583.75, 584, 584.25, 584.5, 584.75, 585, 585.25, 585.5, 585.75, 586, 586.25, 586.5, 586.75, 587,
//  587.25, 587.5, 587.75, 588, 588.25, 588.5, 588.75, 589, 589.25, 589.5, 589.75, 590, 590.25, 590.5, 590.75, 591, 591.25, 591.5, 591.75, 592, 592.25, 592.5, 592.75, 593, 593.25, 593.5, 593.75, 594, 594.25, 594.5,
//  594.75, 595, 595.25, 595.5, 595.75, 596, 596.25, 596.5, 596.75, 597, 597.25, 597.5, 597.75, 598, 598.25, 598.5, 598.75, 599, 599.25, 599.5, 599.75, 600, 600.25, 600.5, 600.75, 601, 601.25, 601.5, 601.75, 602,
//  602.25, 602.5, 602.75, 603, 603.25, 603.5, 603.75, 604, 604.25, 604.5, 604.75, 605, 605.25, 605.5, 605.75, 606, 606.25, 606.5, 606.75, 607, 607.25, 607.5, 607.75, 608, 608.25, 608.5, 608.75, 609, 609.25, 609.5,
//  609.75, 610, 610.25, 610.5, 610.75, 611, 611.25, 611.5, 611.75, 612, 612.25, 612.5, 612.75, 613, 613.25, 613.5, 613.75, 614, 614.25, 614.5, 614.75, 615, 615.25, 615.5, 615.75, 616, 616.25, 616.5, 616.75, 617,
//  617.25, 617.5, 617.75, 618, 618.25, 618.5, 618.75, 619, 619.25, 619.5, 619.75, 620, 620.25, 620.5, 620.75, 621, 621.25, 621.5, 621.75, 622, 622.25, 622.5, 622.75, 623, 623.25, 623.5, 623.75, 624, 624.25, 624.5,
//  624.75, 625, 625.25, 625.5, 625.75, 626, 626.25, 626.5, 626.75, 627, 627.25, 627.5, 627.75, 628, 628.25, 628.5, 628.75, 629, 629.25, 629.5, 629.75, 630, 630.25, 630.5, 630.75, 631, 631.25, 631.5, 631.75, 632,
//  632.25, 632.5, 632.75, 633, 633.25, 633.5, 633.75, 634, 634.25, 634.5, 634.75, 635, 635.25, 635.5, 635.75, 636, 636.25, 636.5, 636.75, 637, 637.25, 637.5, 637.75, 638, 638.25, 638.5, 638.75, 639, 639.25, 639.5,
//  639.75, 640, 640.25, 640.5, 640.75, 641, 641.25, 641.5, 641.75, 642, 642.25, 642.5, 642.75, 643, 643.25, 643.5, 643.75, 644, 644.25, 644.5, 644.75, 645, 645.25, 645.5, 645.75, 646, 646.25, 646.5, 646.75, 647,
//  647.25, 647.5, 647.75, 648, 648.25, 648.5, 648.75, 649, 649.25, 649.5, 649.75, 650, 650.25, 650.5, 650.75, 651, 651.25, 651.5, 651.75, 652, 652.25, 652.5, 652.75, 653, 653.25, 653.5, 653.75, 654, 654.25, 654.5,
//  654.75, 655, 655.25, 655.5, 655.75, 656, 656.25, 656.5, 656.75, 657, 657.25, 657.5, 657.75, 658, 658.25, 658.5, 658.75, 659, 659.25, 659.5, 659.75, 660, 660.25, 660.5, 660.75, 661, 661.25, 661.5, 661.75, 662,
//  662.25, 662.5, 662.75, 663, 663.25, 663.5, 663.75, 664, 664.25, 664.5, 664.75, 665, 665.25, 665.5, 665.75, 666, 666.25, 666.5, 666.75, 667, 667.25, 667.5, 667.75, 668, 668.25, 668.5, 668.75, 669, 669.25, 669.5,
//  669.75, 670, 670.25, 670.5, 670.75, 671, 671.25, 671.5, 671.75, 672, 672.25, 672.5, 672.75, 673, 673.25, 673.5, 673.75, 674, 674.25, 674.5, 674.75, 675, 675.25, 675.5, 675.75, 676, 676.25, 676.5, 676.75, 677,
//  677.25, 677.5, 677.75, 678, 678.25, 678.5, 678.75, 679, 679.25, 679.5, 679.75, 680, 680.25, 680.5, 680.75, 681, 681.25, 681.5, 681.75, 682, 682.25, 682.5, 682.75, 683, 683.25, 683.5, 683.75, 684, 684.25, 684.5,
//  684.75, 685, 685.25, 685.5, 685.75, 686, 686.25, 686.5, 686.75, 687, 687.25, 687.5, 687.75, 688, 688.25, 688.5, 688.75, 689, 689.25, 689.5, 689.75, 690, 690.25, 690.5, 690.75, 691, 691.25, 691.5, 691.75, 692,
//  692.25, 692.5, 692.75, 693, 693.25, 693.5, 693.75, 694, 694.25, 694.5, 694.75, 695, 695.25, 695.5, 695.75, 696, 696.25, 696.5, 696.75, 697, 697.25, 697.5, 697.75, 698, 698.25, 698.5, 698.75, 699, 699.25, 699.5,
//  699.75, 700
//  };

  // Data for beta-carotene
  private static final double[] omlc_prahl_betacarotene =
  { 860668, 866938, 873995, 887102, 901199, 914067, 931100, 952260, 984395, 1006829, 1032650, 1061133, 1081014, 1093143, 1101277, 1095588, 1087868, 1078608, 1055665, 1019648, 984278, 942522, 897947, 847467, 802919, 750520,
  704256, 657528, 612101, 568332, 522203, 483550, 445839, 410271, 376478, 346892, 317864, 291931, 267330, 244432, 224462, 206460, 189372, 174797, 162312, 149431, 139577, 129411, 119268, 111778, 104297, 97028, 91749, 85840,
  82467, 78359, 74180, 71820, 68532, 65721, 62361, 60073, 57993, 56889, 54353, 52962, 51795, 51444, 49052, 49363, 49201, 48552, 47755, 47755, 47872, 46494, 45877, 45503, 46845, 45571, 46489, 45823, 45152, 45629, 45233,
  45427, 44949, 45724, 45863, 44909, 45165, 45219, 44710, 45598, 44814, 45192, 45251, 44864, 44927, 44841, 44661, 44359, 44796, 44260, 45746, 45404, 45917, 45760, 46012, 45386, 45373, 46291, 45656, 46417, 46989, 46751,
  47615, 48034, 48314, 48296, 48777, 49602, 49818, 50291, 50169, 49971, 51047, 51475, 52313, 52552, 52417, 54020, 54169, 53989, 53583, 55038, 55214, 55308, 55155, 56299, 56547, 56470, 56547, 56930, 56641, 57727, 58510,
  58434, 58610, 58830, 59411, 60199, 59785, 61920, 62596, 63109, 64541, 63902, 64663, 65284, 66780, 66365, 67946, 67734, 69689, 70594, 71004, 72387, 74004, 75369, 75283, 75864, 75738, 77504, 76265, 77116, 77976, 78476,
  78828, 79215, 79841, 79247, 79341, 78886, 79652, 80958, 80697, 82030, 82215, 82201, 83273, 84102, 84791, 86502, 87196, 87480, 88029, 89853, 89642, 90925, 93335, 93983, 94416, 95136, 95952, 97046, 98483, 99924, 101248,
  101460, 102617, 104198, 104572, 103622, 104113, 103928, 103185, 102325, 103415, 102271, 100802, 100100, 98857, 97528, 98050, 96253, 96470, 97105, 97213, 97663, 98330, 98235, 98523, 98942, 100100, 99757, 101550, 101649,
  100933, 102689, 102865, 102743, 103266, 104221, 104018, 103748, 104797, 105248, 105878, 105955, 107324, 108333, 109680, 110400, 111179, 111332, 111499, 110324, 108968, 108432, 106148, 104653, 102906, 99717, 97735, 95681,
  92772, 90096, 88344, 85795, 83976, 83147, 80728, 79206, 79071, 78386, 77504, 78206, 77125, 78053, 76715, 77215, 77035, 77913, 77071, 77715, 76454, 76783, 74441, 75175, 73261, 72198, 71829, 71576, 71725, 71536, 70919, 70320,
  70306, 71036, 70603, 70896, 70797, 70784, 69068, 67987, 66658, 64875, 62600, 61177, 59317, 56191, 53763, 50912, 48413, 44382, 41995, 39297, 36734, 34342, 32924, 31888, 30667, 29343, 27352, 28384, 26834, 25902, 24853, 23952,
  23592, 22628, 22718, 22137, 21889, 22101, 22961, 21912, 20664, 20551, 20934, 19151, 20736, 19984, 21087, 20245, 18448, 18254, 17547, 16809, 16777, 16435, 16232, 17606, 16552, 17214, 16665, 16219, 16601, 16939, 16205, 19488,
  16412, 17714, 18520, 12224, 14417, 16669, 18119, 15633, 15872, 14016, 15962, 15457, 13570, 16809, 15669, 14422, 16034, 14642, 16385, 13471, 14872, 17218, 15944, 17723, 13057, 16376, 14219, 13444, 15043, 14809, 12494, 14142,
  13034, 11940, 13980, 15399, 12805, 14115, 14277, 15561, 16313, 14525, 13642, 11989, 13940, 14368, 14759, 12134, 13624, 14431, 8715, 14687, 13741, 11989, 10409, 12458, 13242, 12881, 12377, 13309, 14390, 12120, 13156, 12120,
  13552, 12597, 13300, 11823, 16075, 14097, 13498, 12624, 14426, 12291, 11823, 13106, 13863, 13057, 11062, 14422, 14417, 13084, 15079, 13692, 12201, 15858, 14129, 14903, 14728, 12435, 13052, 14660, 15223, 13521, 12003, 13656,
  14057, 13705, 12314, 14273, 14295, 16786, 14813, 13566, 15129, 14201, 14241, 13976, 12165, 12854, 16070, 12940, 14485, 14728, 16151, 16246, 14530, 15313, 15656, 13791, 13823, 16466, 14390, 15890, 13714, 12904, 11899, 13854,
  11629, 13814, 14854, 15475, 13944, 13638, 14530, 14057, 14467, 14958, 14079, 13953, 16088, 14678, 12854, 14944, 13219, 16070, 14557, 15282, 13998, 15043, 15039, 15566, 14723, 15165, 13660, 14003, 14480, 15579, 14678, 15786,
  15881, 16147, 14390, 15021, 15007, 15503, 14210, 16237, 16881, 14142, 14710, 15255, 14678, 16052, 15039, 13823, 15282, 14602, 14588, 16583, 15187, 16678, 15232, 15381, 15466, 17696, 15534, 17935, 17358, 16345, 15512, 15782,
  17137, 16813, 16588, 15665, 16674, 14530, 15412, 15412, 15714, 16863, 15723, 17908, 16574, 17502, 17295, 16674, 17142, 17795, 16178, 17646, 18047, 17975, 17390, 16786, 16746, 18615, 17331, 17687, 19191, 18858, 17056, 19529,
  20862, 18862, 19281, 19777, 20452, 19727, 19624, 18574, 21011, 19912, 20813, 20029, 22623, 22425, 21695, 21610, 21308, 22457, 21592, 21556, 22578, 22956, 23033, 23641, 24204, 24150, 24123, 25019, 23528, 23470, 25524, 25362,
  24299, 25069, 25244, 26555, 26762, 25353, 26244, 26452, 26654, 27352, 26591, 27451, 27424, 28519, 27893, 28577, 28339, 29059, 29298, 29929, 29253, 30091, 29847, 29757, 32072, 30329, 29325, 32433, 30365, 30424, 32014, 31068,
  32825, 32960, 34991, 31969, 33045, 33599, 34050, 34923, 33482, 34775, 36216, 35004, 36009, 35982, 36450, 35626, 36829, 36955, 38243, 37833, 37617, 38977, 38473, 38454, 39576, 38797, 40657, 40004, 40733, 40107, 42684, 41850,
  42098, 40932, 42792, 43976, 44220, 44247, 45836, 45904, 44571, 46881, 47949, 46850, 47449, 48187, 48863, 50926, 50723, 50917, 49692, 50151, 51165, 52340, 52097, 51624, 54218, 53326, 53754, 55421, 55466, 54529, 55632, 56407,
  57529, 57092, 56961, 59213, 58727, 59209, 59109, 58312, 60258, 60744, 60506, 61186, 62154, 61483, 61024, 62303, 61348, 61677, 62717, 62920, 62879, 64248, 63456, 63627, 65316, 64875, 65645, 66127, 65203, 66361, 65118, 66631,
  66334, 67063, 68005, 68117, 68063, 68108, 68748, 68189, 71153, 69270, 71000, 70135, 71612, 72414, 73072, 73202, 73180, 73873, 74963, 75463, 75207, 75806, 76260, 76634, 78287, 77485, 78657, 78693, 80233, 79859, 81251, 80427,
  82710, 83723, 83723, 82224, 83354, 83633, 85885, 86390, 86750, 88133, 88398, 88259, 90065, 89979, 90416, 91673, 92141, 93294, 92389, 94790, 94745, 95321, 96519, 97375, 97713, 97825, 98014, 99496, 99348, 99528, 99528, 100442,
  100955, 101784, 102153, 103176, 103428, 103626, 103469, 103338, 103757, 104739, 105297, 105923, 105757, 105820, 106126, 106094, 106166, 105086, 105712, 105775, 106162, 107072, 107081, 106824, 107193, 106770, 108270, 107216,
  107855, 107590, 107446, 106824, 107324, 107711, 109035, 107572, 108635, 108662, 107621, 109040, 108009, 108801, 109180, 109801, 109459, 109342, 110170, 110004, 110116, 109801, 111197, 111436, 110806, 112053, 111643, 113197,
  112742, 113008, 115215, 114129, 113994, 115436, 116111, 116147, 116593, 117701, 118205, 117944, 118453, 119908, 119530, 120966, 120948, 121295, 122556, 123367, 124088, 124380, 125105, 126781, 124200, 126961, 127038, 127835,
  128785, 127610, 129173, 130510, 130758, 130731, 131605, 132087, 132609, 132722, 132582, 135095, 135649, 133969, 134676, 135383, 136428, 135964, 136753, 136271, 137604, 138288, 137329, 136699, 137464, 139171, 139342, 138730,
  138243, 139356, 138590, 139500, 137541, 138509, 138342, 137401, 137888, 137820, 136518, 137572, 136654, 136000, 135915, 135550, 135437, 133577, 134037, 133122, 134001, 132424, 133253, 130983, 131816, 131920, 129028, 129479,
  129087, 129015, 126894, 126808, 125736, 125065, 125335, 124367, 123227, 122187, 121966, 121174, 119818, 119651, 119435, 118336, 118070, 116665, 116818, 116273, 114805, 114057, 113999, 113535, 113904, 112882, 111368, 112332,
  111233, 111436, 109504, 110148, 110387, 109990, 109432, 110161, 110139, 108369, 108981, 107995, 107450, 107446, 107662, 108432, 107621, 108797, 107518, 107608, 108378, 107977, 108252, 108427, 108792, 108900, 108157, 109283,
  109351, 109806, 109094, 109198, 109319, 109058, 109941, 110148, 110472, 110071, 111864, 111409, 110747, 111733, 111134, 112395, 112972, 112567, 112522, 111765, 111747, 111792, 112778, 110405, 112314, 112476, 113112, 112368,
  111850, 110445, 111517, 110711, 110828, 110382, 109873, 110769, 110166, 108936, 108427, 108409, 108837, 107270, 105716, 106765, 105491, 104712, 103712, 104356, 103198, 102942, 101518, 100163, 99802, 98492, 98960, 96758, 96249,
  95623, 94663, 95114, 93803, 91772, 91551, 89497, 89529, 85827, 86646, 85048, 85115, 83305, 81021, 80611, 80400, 79075, 77319, 76107, 74945, 74324, 72554, 71000, 71266, 70590, 68027, 66888, 65181, 64514, 63618, 62996, 59983,
  59380, 57790, 58560, 55605, 55024, 54200, 52736, 52376, 50372, 50219, 49926, 48696, 47143, 46526, 45332, 44391, 42031, 41454, 40459, 41260, 37599, 37045, 36338, 35968, 34622, 33730, 32662, 32135, 32658, 30181, 29933, 28100,
  27983, 27438, 26258, 24961, 25204, 24943, 24686, 23119, 22375, 21353, 20673, 19871, 20407, 18155, 19187, 19597, 17912, 16619, 16867, 16881, 15629, 15205, 15435, 14737, 13629, 13016, 13287, 13224, 13417, 12363, 11260, 11800,
  10607, 9760, 10985, 10440, 9751, 10278, 9891, 9287, 9683, 8846, 8040, 7296, 7193, 7215, 7994, 7449, 6850, 7004, 7148, 6652, 7490, 6342, 6540, 5130, 5085, 4207, 4963, 4860, 5558, 5490, 4585, 4828, 4279, 4301, 4351, 5098, 4562,
  4063, 4589, 3779, 3220, 3639, 3387, 3319, 2851, 3824, 4306, 3666, 3400, 1901, 4189, 2419, 3351, 2117, 2671, 3585, 2536, 3355, 1621, 2662, 2306, 2441, 2027, 1991, 2707, 2320, 1806, 2027, 3058, 2234, 320, 1874, 2815, 2837, 2000,
  1612, 2144, 1977, 3027, 1549, 1180, 1509, 2229, 2040, 824, 1608, 1563, 2261, 1158, 1194, 1811, 676, 1838, 802, 1802, 2405, 964, 743, 540, 1689, 1288, 1806, 455, 2054, 1603, 1896, 1185, 0, 1423, 1698, 986, 653, 248, 158, 0, 1022,
  797, 1495, 2063, 1000, 1635, 0, 2144, 572, 1797, 1275, 910, 1356, 1392, 1567, 1158, 856, 572, 811, 1230, 1130, 1036, 1198, 572, 1279, 320, 1284, 703, 775, 0, 1266, 964, 0, 820, 428, 1923, 495, 1239, 405, 1293, 883, 658, 567,
  901, 1851, 1203, 1374, 1369, 1757, 1153, 851, 1675, 730, 1279, 806, 0, 509, 545, 1013, 622, 230, 973, 1698, 234, 27, 1491, 369, 748, 1964, 586, 1757, 14, 1108, 0, 784, 1491, 0, 1860, 667, 459, 117, 977, 311, 1027, 0, 1576, 901,
  0, 775, 937, 360, 802, 0, 1581, 63, 1112, 572, 833, 284, 0, 1036, 252, 793, 0, 288, 540, 32, 1585, 0, 1428, 676, 1252, 1500, 0, 649, 0, 1549, 1090, 680, 0, 198, 878, 189, 194, 577, 1022, 631, 653, 482, 270, 216, 1216, 874, 0,
  1590, 176, 910, 0, 1135, 473, 1162, 1702, 36, 1027, 1130, 896, 1058, 973, 1108, 703, 1455, 1117, 1563, 707, 1130, 1576, 365, 18, 667, 176, 905, 365, 2162, 685, 1342, 131, 923, 833, 1117, 667, 27, 1189, 455, 140, 0, 482, 2022,
  743, 595, 658, 1027, 1630, 207, 320, 554, 1167, 716, 1108, 0, 815, 1383, 1446, 860, 536, 820, 356, 401, 626, 0, 1176, 1117, 788, 0, 1491, 1279, 0, 1049, 104, 482, 1153, 1396, 0, 1000, 365, 973, 892, 0, 811, 1171, 626, 959, 1144,
  297, 558, 0, 919, 504, 1022, 626, 212, 491, 1392, 221, 617, 261, 347, 829, 162, 122, 36, 185, 1360, 1022, 631, 1117, 1820, 0, 734, 522, 558, 887, 81, 1374, 297, 1428, 0, 81, 1351, 892, 635, 964, 0, 1058, 937, 1689, 0, 1342, 680,
  964, 567, 1171, 1239, 694, 1518, 527, 793, 437, 1509, 0, 0, 1567, 914, 703, 892, 536, 1261, 495, 1630, 486, 1117, 1275, 1130, 914, 1022, 1504, 441, 1216, 279, 730, 1693, 968, 1234, 851, 698, 874, 1040, 617, 685, 1473, 608, 779, 0,
  1851, 1392, 1540, 464, 1081, 450, 1058, 1067, 820, 784, 748, 604, 1455, 896, 1243, 1743, 536, 1608, 0, 1027, 536, 54, 1121, 432, 1243, 847, 919, 662, 2058, 207, 509, 869, 0, 1387, 950, 1779, 1018, 1369, 721, 347, 2076, 320, 1495,
  1203, 1275, 2175, 743, 1977, 680, 1293, 1234, 1914, 626, 27, 1883, 536, 1495, 1171, 721, 572, 1049, 680, 788, 1982, 739, 802, 986, 838, 1266, 1482, 1896, 739, 991, 730, 968, 1684, 964, 2311, 743, 1072, 1248, 617, 2139, 1689, 1432,
  1004, 788, 1234, 761, 806, 743, 1590, 1491, 2117, 1775, 937, 1612, 1194, 977, 721, 1239, 1657, 901, 1603, 761, 878, 599, 586, 1892, 1684, 2022, 1635, 874, 342, 1374, 347, 1775, 1108, 977, 1910, 468, 1171, 662, 1838, 275, 563, 932,
  622, 649, 815, 1221, 1022, 1067, 829, 374, 554, 829, 1117, 1752, 297, 2085, 45, 1103, 563, 1234, 540, 581, 401, 1288, 644, 423, 1473, 491, 685, 1572, 1094, 536, 198, 455, 667, 446, 234, 545, 1594, 806, 941, 797, 914, 234, 820, 874,
  36, 1482, 1306, 662, 455, 1013, 946, 0, 1504, 473, 1004, 392, 0, 649, 0, 869, 306, 1401, 1117, 887, 1040, 392, 378, 0, 667, 563, 113, 806, 545, 1509, 90, 212, 378, 0, 540, 486, 563, 0, 248, 423, 0, 225, 919, 1049, 1410, 549, 477,
  369, 284, 892, 171, 50, 387, 1009, 405, 68, 0, 905, 0, 558, 946, 959, 450, 509, 234, 297, 0, 0, 414, 383, 0, 1013, 640, 513, 0, 1662, 0, 41, 131, 640, 941, 0, 0, 180, 473, 766, 0, 1221, 685, 450, 234, 311, 0, 279, 261, 500, 0, 518,
  0, 95, 72, 680, 0, 279, 513, 0, 595, 126, 676, 104, 387, 928, 0, 365, 306, 757, 811, 725, 54, 41, 721, 410, 658, 315, 599, 374, 0, 491, 54, 540, 0, 0, 486, 788, 0, 0, 171, 410, 477, 0, 158, 99, 1072, 0, 0, 477, 221, 212, 0, 126,
  667, 167, 743, 387, 0, 716, 410, 5, 775, 1639, 252, 396, 0, 0, 1437
  };

  private static final double IOR_STRATUM_CORNEUM = 1.55;
  private static final double IOR_EPIDERMIS = 1.4;
  private static final double IOR_PAPILLARY_DERMIS = 1.36;
  private static final double IOR_RETICULAR_DERMIS = 1.38;
  private static final double IOR_COLLAGEN_FIBERS = 1.5;

  static {
    // convert everything to base SI units
    for (int i = 0; i < omlc_pheomelanin_wavelengths.length; i++) {
      omlc_pheomelanin_wavelengths[i] *= 1e-9;
    }
    for (int i = 0; i < omlc_eumelanin_wavelengths.length; i++) {
      omlc_eumelanin_wavelengths[i] *= 1e-9;
    }
    for (int i = 0; i < stratum_corneum_wavelengths.length; i++) {
      stratum_corneum_wavelengths[i] *= 1e-9;
    }
    for (int i = 0; i < epidermis_wavelengths.length; i++) {
      epidermis_wavelengths[i] *= 1e-9;
    }
    for (int i = 0; i < exitant_angles.length; i++) {
      exitant_angles[i] = Math.toRadians(exitant_angles[i]);
    }
    for (int i = 0; i < stratum_corneum_perturb.length; i++) {
      for (int j = 0; j < stratum_corneum_perturb[i].length; j++) {
        stratum_corneum_perturb[i][j] /= 100.0;
      }
    }
    for (int i = 0; i < epidermis_perturb.length; i++) {
      for (int j = 0; j < epidermis_perturb[i].length; j++) {
        epidermis_perturb[i][j] /= 100.0;
      }
    }
  }

  private static final Function1 OMLC_EUMELANIN_EXT_MGML = new PiecewiseLinearFunction1(
      omlc_eumelanin_wavelengths, omlc_eumelanin_ext_mgml);

  private static final Function1 OMLC_EUMELANIN_EXT_MOLL = new PiecewiseLinearFunction1(
      omlc_eumelanin_wavelengths, omlc_eumelanin_ext_molL);

  private static final Function1 OMLC_PHEOMELANIN_EXT_MGML = new PiecewiseLinearFunction1(
      omlc_pheomelanin_wavelengths, omlc_pheomelanin_ext_mgml);

  private static final Function1 OMLC_PHEOMELANIN_EXT_MOLL = new PiecewiseLinearFunction1(
      omlc_pheomelanin_wavelengths, omlc_pheomelanin_ext_molL);

  private static final Function1 OMLC_PRAHL_OXYHEMOGLOBIN = new PiecewiseLinearFunction1(
      omlc_prahl_hemoglobin_wavelengths, omlc_prahl_oxyhemoglobin);

  private static final Function1 OMLC_PRAHL_DEOXYHEMOGLOBIN = new PiecewiseLinearFunction1(
      omlc_prahl_hemoglobin_wavelengths, omlc_prahl_deoxyhemoglobin);

  private static final Function1 OMLC_PRAHL_BILIRUBIN = new PiecewiseLinearFunction1(
      omlc_prahl_bilirubin_wavelengths, omlc_prahl_bilirubin);

  private static final Function1 OMLC_PRAHL_BETACAROTENE = new PiecewiseLinearFunction1(
      omlc_prahl_betacarotene_wavelengths, omlc_prahl_betacarotene);

  private double collagenFiberRadius = 2.5e-8;
  private double thicknessStratumCorneum = 1e-3; // cm
  private double thicknessEpidermis = 1e-2; // cm
  private double thicknessPapillaryDermis = 2e-2; // cm
  private double thicknessReticularDermis = 1.8e-1; // cm
  private double concentrationEumelanin = 80;
  private double concentrationPheomelanin = 12;
  private double concentrationBetaCaroteneInStratumCorneum = 2.1e-4;
  private double concentrationBetaCaroteneInEpidermis = 2.1e-4;
  private double concentrationBetaCaroteneInBlood = 7e-5;
  private double concentrationHemoglobinInBlood = 150;
  private double concentrationBilirubinInBlood = 5e-2;
  private double pctMelanosomesInEpidermis = 0.052;
  private double pctWholeBloodInPapillaryDermis = 0.012;
  private double pctWholeBloodInReticularDermis = 0.0091;
  private double ratioOxyDeoxyHemoglobin = 0.75;
  private double foldsAspectRatio = 0.75;

  private final ColorModel colorModel;

  private Material subsurface = null;

  public BioSpecMaterial(ColorModel colorModel) {
    this.colorModel = colorModel;
  }

  private void build() {
    ColorModel cm = colorModel;

    subsurface = new LayeredMaterial()
      .addLayerToBottom( // air / stratum corneum interface
        new TrowbridgeReitzMaterial(foldsAspectRatio, IOR_STRATUM_CORNEUM, 1.0))
      .addLayerToBottom( // stratum corneum
        new SequentialMaterial()
          .addScatterer(new TabularPerturbingMaterial(exitant_angles, stratum_corneum_546, 1000))
          .addScatterer(new AbsorbingMaterial(
            cm.getContinuous(new ScaledFunction1(
              concentrationBetaCaroteneInStratumCorneum / 537.0,
              OMLC_PRAHL_BETACAROTENE)),
            thicknessStratumCorneum)))
      .addLayerToBottom( // stratum corneum / epidermis interface
        new FresnelMaterial(IOR_EPIDERMIS, IOR_STRATUM_CORNEUM))
      .addLayerToBottom( // epidermis
        new SequentialMaterial()
          .addScatterer(new TabularPerturbingMaterial(exitant_angles, epidermis_546, 1000))
          .addScatterer(new AbsorbingMaterial(
            cm.getContinuous(new SumFunction1()
              .addChild(new ScaledFunction1(
                pctMelanosomesInEpidermis * concentrationEumelanin,
                OMLC_EUMELANIN_EXT_MGML))
              .addChild(new ScaledFunction1(
                pctMelanosomesInEpidermis * concentrationPheomelanin,
                OMLC_PHEOMELANIN_EXT_MGML))
              .addChild(new ScaledFunction1(
                (1.0 - pctMelanosomesInEpidermis) * concentrationBetaCaroteneInEpidermis / 537.0,
                OMLC_PRAHL_BETACAROTENE))),
            thicknessEpidermis)))
      .addLayerToBottom( // epidermis / papillary dermis interface
        new FresnelMaterial(IOR_PAPILLARY_DERMIS, IOR_EPIDERMIS))
      .addLayerToBottom( // papillary dermis
        new SequentialMaterial()
          .addScatterer(new DiffusingMaterial())
          .addScatterer(new AbsorbingMaterial(
            cm.getContinuous(new SumFunction1()
              .addChild(new ScaledFunction1(
                pctWholeBloodInPapillaryDermis * concentrationHemoglobinInBlood * ratioOxyDeoxyHemoglobin / 66500.0,
                OMLC_PRAHL_OXYHEMOGLOBIN))
              .addChild(new ScaledFunction1(
                pctWholeBloodInPapillaryDermis * concentrationHemoglobinInBlood * (1.0 - ratioOxyDeoxyHemoglobin) / 66500.0,
                OMLC_PRAHL_DEOXYHEMOGLOBIN))
              .addChild(new ScaledFunction1(
                pctWholeBloodInPapillaryDermis * concentrationBetaCaroteneInBlood / 537.0,
                OMLC_PRAHL_BETACAROTENE))
              .addChild(new ScaledFunction1(
                pctWholeBloodInPapillaryDermis * concentrationBilirubinInBlood / 585.0,
                OMLC_PRAHL_BILIRUBIN))),
            thicknessPapillaryDermis)))
      .addLayerToBottom( // papillary dermis / reticular dermis interface
        new FresnelMaterial(IOR_RETICULAR_DERMIS, IOR_PAPILLARY_DERMIS))
      .addLayerToBottom( // reticular dermis
        new SequentialMaterial()
          .addScatterer(new DiffusingMaterial())
          .addScatterer(new AbsorbingMaterial(
            cm.getContinuous(new SumFunction1()
              .addChild(new ScaledFunction1(
                pctWholeBloodInReticularDermis * concentrationHemoglobinInBlood * ratioOxyDeoxyHemoglobin / 66500.0,
                OMLC_PRAHL_OXYHEMOGLOBIN))
              .addChild(new ScaledFunction1(
                pctWholeBloodInReticularDermis * concentrationHemoglobinInBlood * (1.0 - ratioOxyDeoxyHemoglobin) / 66500.0,
                OMLC_PRAHL_DEOXYHEMOGLOBIN))
              .addChild(new ScaledFunction1(
                pctWholeBloodInReticularDermis * concentrationBetaCaroteneInBlood / 537.0,
                OMLC_PRAHL_BETACAROTENE))
              .addChild(new ScaledFunction1(
                pctWholeBloodInReticularDermis * concentrationBilirubinInBlood / 585.0,
                OMLC_PRAHL_BILIRUBIN))),
            thicknessReticularDermis)))
      .addLayerToBottom( // reticular dermis / hypodermis interface
        new LambertianMaterial(cm.getWhite()));
  }


  /**
   * @return the collagenFiberRadius
   */
  public double getCollagenFiberRadius() {
    return collagenFiberRadius;
  }


  /**
   * @param collagenFiberRadius the collagenFiberRadius to set
   */
  public void setCollagenFiberRadius(double collagenFiberRadius) {
    this.collagenFiberRadius = collagenFiberRadius;
    subsurface = null;
  }


  /**
   * @return the thicknessStratumCorneum
   */
  public double getThicknessStratumCorneum() {
    return thicknessStratumCorneum;
  }


  /**
   * @param thicknessStratumCorneum the thicknessStratumCorneum to set
   */
  public void setThicknessStratumCorneum(double thicknessStratumCorneum) {
    this.thicknessStratumCorneum = thicknessStratumCorneum;
    subsurface = null;
  }


  /**
   * @return the thicknessEpidermis
   */
  public double getThicknessEpidermis() {
    return thicknessEpidermis;
  }


  /**
   * @param thicknessEpidermis the thicknessEpidermis to set
   */
  public void setThicknessEpidermis(double thicknessEpidermis) {
    this.thicknessEpidermis = thicknessEpidermis;
    subsurface = null;
  }


  /**
   * @return the thicknessPapillaryDermis
   */
  public double getThicknessPapillaryDermis() {
    return thicknessPapillaryDermis;
  }


  /**
   * @param thicknessPapillaryDermis the thicknessPapillaryDermis to set
   */
  public void setThicknessPapillaryDermis(double thicknessPapillaryDermis) {
    this.thicknessPapillaryDermis = thicknessPapillaryDermis;
    subsurface = null;
  }


  /**
   * @return the thicknessReticularDermis
   */
  public double getThicknessReticularDermis() {
    return thicknessReticularDermis;
  }


  /**
   * @param thicknessReticularDermis the thicknessReticularDermis to set
   */
  public void setThicknessReticularDermis(double thicknessReticularDermis) {
    this.thicknessReticularDermis = thicknessReticularDermis;
    subsurface = null;
  }


  /**
   * @return the concentrationEumelanin
   */
  public double getConcentrationEumelanin() {
    return concentrationEumelanin;
  }


  /**
   * @param concentrationEumelanin the concentrationEumelanin to set
   */
  public void setConcentrationEumelanin(double concentrationEumelanin) {
    this.concentrationEumelanin = concentrationEumelanin;
    subsurface = null;
  }


  /**
   * @return the concentrationPheomelanin
   */
  public double getConcentrationPheomelanin() {
    return concentrationPheomelanin;
  }


  /**
   * @param concentrationPheomelanin the concentrationPheomelanin to set
   */
  public void setConcentrationPheomelanin(double concentrationPheomelanin) {
    this.concentrationPheomelanin = concentrationPheomelanin;
    subsurface = null;
  }


  /**
   * @return the concentrationBetaCaroteneInStratumCorneum
   */
  public double getConcentrationBetaCaroteneInStratumCorneum() {
    return concentrationBetaCaroteneInStratumCorneum;
  }


  /**
   * @param concentrationBetaCaroteneInStratumCorneum the concentrationBetaCaroteneInStratumCorneum to set
   */
  public void setConcentrationBetaCaroteneInStratumCorneum(
      double concentrationBetaCaroteneInStratumCorneum) {
    this.concentrationBetaCaroteneInStratumCorneum = concentrationBetaCaroteneInStratumCorneum;
    subsurface = null;
  }


  /**
   * @return the concentrationBetaCaroteneInEpidermis
   */
  public double getConcentrationBetaCaroteneInEpidermis() {
    return concentrationBetaCaroteneInEpidermis;
  }


  /**
   * @param concentrationBetaCaroteneInEpidermis the concentrationBetaCaroteneInEpidermis to set
   */
  public void setConcentrationBetaCaroteneInEpidermis(
      double concentrationBetaCaroteneInEpidermis) {
    this.concentrationBetaCaroteneInEpidermis = concentrationBetaCaroteneInEpidermis;
    subsurface = null;
  }


  /**
   * @return the concentrationBetaCaroteneInBlood
   */
  public double getConcentrationBetaCaroteneInBlood() {
    return concentrationBetaCaroteneInBlood;
  }


  /**
   * @param concentrationBetaCaroteneInBlood the concentrationBetaCaroteneInBlood to set
   */
  public void setConcentrationBetaCaroteneInBlood(
      double concentrationBetaCaroteneInBlood) {
    this.concentrationBetaCaroteneInBlood = concentrationBetaCaroteneInBlood;
    subsurface = null;
  }


  /**
   * @return the concentrationHemoglobinInBlood
   */
  public double getConcentrationHemoglobinInBlood() {
    return concentrationHemoglobinInBlood;
  }


  /**
   * @param concentrationHemoglobinInBlood the concentrationHemoglobinInBlood to set
   */
  public void setConcentrationHemoglobinInBlood(
      double concentrationHemoglobinInBlood) {
    this.concentrationHemoglobinInBlood = concentrationHemoglobinInBlood;
    subsurface = null;
  }


  /**
   * @return the concentrationBilirubinInBlood
   */
  public double getConcentrationBilirubinInBlood() {
    return concentrationBilirubinInBlood;
  }


  /**
   * @param concentrationBilirubinInBlood the concentrationBilirubinInBlood to set
   */
  public void setConcentrationBilirubinInBlood(
      double concentrationBilirubinInBlood) {
    this.concentrationBilirubinInBlood = concentrationBilirubinInBlood;
    subsurface = null;
  }


  /**
   * @return the pctMelanosomesInEpidermis
   */
  public double getPctMelanosomesInEpidermis() {
    return pctMelanosomesInEpidermis;
  }


  /**
   * @param pctMelanosomesInEpidermis the pctMelanosomesInEpidermis to set
   */
  public void setPctMelanosomesInEpidermis(double pctMelanosomesInEpidermis) {
    this.pctMelanosomesInEpidermis = pctMelanosomesInEpidermis;
    subsurface = null;
  }


  /**
   * @return the pctWholeBloodInPapillaryDermis
   */
  public double getPctWholeBloodInPapillaryDermis() {
    return pctWholeBloodInPapillaryDermis;
  }


  /**
   * @param pctWholeBloodInPapillaryDermis the pctWholeBloodInPapillaryDermis to set
   */
  public void setPctWholeBloodInPapillaryDermis(
      double pctWholeBloodInPapillaryDermis) {
    this.pctWholeBloodInPapillaryDermis = pctWholeBloodInPapillaryDermis;
    subsurface = null;
  }


  /**
   * @return the pctWholeBloodInReticularDermis
   */
  public double getPctWholeBloodInReticularDermis() {
    return pctWholeBloodInReticularDermis;
  }


  /**
   * @param pctWholeBloodInReticularDermis the pctWholeBloodInReticularDermis to set
   */
  public void setPctWholeBloodInReticularDermis(
      double pctWholeBloodInReticularDermis) {
    this.pctWholeBloodInReticularDermis = pctWholeBloodInReticularDermis;
    subsurface = null;
  }


  /**
   * @return the ratioOxyDeoxyHemoglobin
   */
  public double getRatioOxyDeoxyHemoglobin() {
    return ratioOxyDeoxyHemoglobin;
  }


  /**
   * @param ratioOxyDeoxyHemoglobin the ratioOxyDeoxyHemoglobin to set
   */
  public void setRatioOxyDeoxyHemoglobin(double ratioOxyDeoxyHemoglobin) {
    this.ratioOxyDeoxyHemoglobin = ratioOxyDeoxyHemoglobin;
    subsurface = null;
  }


  /**
   * @return the foldsAspectRatio
   */
  public double getFoldsAspectRatio() {
    return foldsAspectRatio;
  }


  /**
   * @param foldsAspectRatio the foldsAspectRatio to set
   */
  public void setFoldsAspectRatio(double foldsAspectRatio) {
    this.foldsAspectRatio = foldsAspectRatio;
    subsurface = null;
  }

  /* (non-Javadoc)
   * @see ca.eandb.jmist.framework.material.AbstractMaterial#scatter(ca.eandb.jmist.framework.SurfacePoint, ca.eandb.jmist.math.Vector3, boolean, ca.eandb.jmist.framework.color.WavelengthPacket, double, double, double)
   */
  @Override
  public ScatteredRay scatter(SurfacePoint x, Vector3 v, boolean adjoint,
      WavelengthPacket lambda, double ru, double rv, double rj) {
    if (subsurface == null) {
      synchronized (this) {
        if (subsurface == null) {
          build();
        }
      }
    }

    return subsurface.scatter(x, v, adjoint, lambda, ru, rv, rj);
  }

}
TOP

Related Classes of ca.eandb.jmist.framework.material.biospec.BioSpecMaterial

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.