aboutsummaryrefslogtreecommitdiff
path: root/utils/index.py
blob: 3e3aef68dee36b619ea6ad3695d9cfef00658ba1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#!/usr/bin/env python
# Copyright (c) 2019, Anthony Latorre <tlatorre at uchicago>
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <https://www.gnu.org/licenses/>.

"""
This is a script to calculate the index of refraction of water as a function of
wavelength, temperature, and pressure and fit it to a linear approximation in a
wavelength region where the PMTs are sensitive to. The data comes from [1].

[1] "Refractive index of Water and Steam as Function of Wavelength, Temperature, and Density". Schiebener et al. 1989.
"""
from __future__ import print_function, division
import numpy as np

A0 = 0.243905091
A1 = 9.53518094e-3
A2 = -3.64358110e-3
A3 = 2.65666426e-4
A4 = 1.59189325e-3
A5 = 2.45733798e-3
A6 = 0.897478251
A7 = -1.63066183e-2
UV = 0.2292020
IR = 5.432937

def get_index(p, wavelength, T):
    """
    Returns the index of pure water for a given density, wavelength, and
    temperature. The density should be in units of kg/m^3, the wavelength in nm,
    and the temperature in Celsius.
    """
    # normalize the density, temperature, and pressure
    p = p/1000.0
    wavelength = wavelength/589.0
    T = (T+273.15)/273.15

    # first we compute the right hand side of Equation 7
    c = A0 + A1*p + A2*T + A3*wavelength**2*T + A4/wavelength**2 + A5/(wavelength**2-UV**2) + A6/(wavelength**2-IR**2) + A7*p**2
    c *= p

    return np.sqrt((2*c+1)/(1-c))

def approximate_index(x, a, b):
    """
    Returns the index of refraction using the approximation:

    n = a + b/x**2
    """
    return a + b/x**2

def chi2(pars, x, data):
    """
    Returns the squares of the difference between the data and the model for
    the inverse of the index of refraction, i.e.

    1/n = lambda**2/(a*lambda**2+b)
    """
    a, b = pars
    return np.sum((approximate_index(x,a,b)-data)**2)

if __name__ == '__main__':
    import matplotlib.pyplot as plt
    import argparse
    from scipy.optimize import fmin

    parser = argparse.ArgumentParser("fit for an approximation to the inverse of the index of refraction of water")
    parser.add_argument("--temperature", type=float, default=10.0)
    parser.add_argument("--density", type=float, default=1000.0)
    parser.add_argument("--low", type=float, default=300.0)
    parser.add_argument("--high", type=float, default=600.0)
    args = parser.parse_args()

    x = np.linspace(args.low,args.high,1000)
    n = get_index(args.density,x,args.temperature)
    xmin = fmin(chi2,[1,1],args=(x,1/n))

    print(xmin)

    a, b = xmin
    y = approximate_index(x,a,b)

    plt.plot(x,1/n,label="data")
    plt.plot(x,y,label="fit")
    plt.xlabel("Wavelength (nm)")
    plt.ylabel("1/n")
    plt.title("Index of Refraction of Water at 273.15 K")
    plt.legend()
    plt.show()