radphen-iadpython 0.7.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
iadpython/grid.py ADDED
@@ -0,0 +1,125 @@
1
+ """Class for doing inverse adding-doubling calculations for a sample.
2
+
3
+ Example::
4
+
5
+ >>> import iadpython
6
+
7
+ >>> exp = iadpython.Experiment(0.5, 0.1, default_g=0.5)
8
+ >>> grid = iadpython.Grid()
9
+ >>> grid.calc(exp)
10
+ >>> print(grid)
11
+ """
12
+
13
+ import numpy as np
14
+
15
+
16
+ class Grid:
17
+ """Class to track pre-calculated R & T values.
18
+
19
+ There is a long story associated with these routines. I spent a lot of time
20
+ trying to find an empirical function to allow a guess at a starting value for
21
+ the inversion routine. Basically nothing worked very well. There were
22
+ too many special cases and what not. So I decided to calculate a whole bunch
23
+ of reflection and transmission values and keep their associated optical
24
+ properties linked nearby.
25
+ """
26
+
27
+ def __init__(self, search=None, default=None, N=21):
28
+ """Object initialization."""
29
+ self.search = search
30
+ self.default = default
31
+ self.N = N
32
+ self.a = np.zeros((N, N))
33
+ self.b = np.zeros((N, N))
34
+ self.g = np.zeros((N, N))
35
+ self.ur1 = np.zeros((N, N))
36
+ self.ut1 = np.zeros((N, N))
37
+
38
+ def __str__(self):
39
+ """Return basic details as a string for printing."""
40
+ s = "---------------- Grid ---------------\n"
41
+ if self.search is None:
42
+ s += "search = None\n"
43
+ else:
44
+ s += "search = %s\n" % self.search
45
+
46
+ if self.default is None:
47
+ s += "default = None\n"
48
+ else:
49
+ s += "default = %.5f\n" % self.default
50
+
51
+ s += matrix_as_string(self.a, "a")
52
+ s += matrix_as_string(self.b, "b")
53
+ s += matrix_as_string(self.g, "g")
54
+ s += matrix_as_string(self.ur1, "ur1")
55
+ s += matrix_as_string(self.ut1, "ut1")
56
+
57
+ return s
58
+
59
+ def calc(self, exp, default=None):
60
+ """Precalculate a grid."""
61
+ if default is not None:
62
+ self.default = default
63
+
64
+ a = np.linspace(0, 1, self.N)
65
+ b = np.linspace(0, 10, self.N)
66
+ g = np.linspace(-0.99, 0.99, self.N)
67
+
68
+ self.search = exp.search
69
+
70
+ if self.search == "find_ab":
71
+ self.g = np.full((self.N, self.N), self.default)
72
+ self.a, self.b = np.meshgrid(a, b)
73
+
74
+ if self.search == "find_ag":
75
+ self.b = np.full((self.N, self.N), self.default)
76
+ self.a, self.g = np.meshgrid(a, g)
77
+
78
+ if self.search == "find_bg":
79
+ self.a = np.full((self.N, self.N), self.default)
80
+ self.b, self.g = np.meshgrid(b, g)
81
+
82
+ for i in range(self.N):
83
+ for j in range(self.N):
84
+ exp.sample.a = self.a[i, j]
85
+ exp.sample.b = self.b[i, j]
86
+ exp.sample.g = self.g[i, j]
87
+ self.ur1[i, j], self.ut1[i, j], _, _ = exp.sample.rt()
88
+
89
+ def min_abg(self, mr, mt):
90
+ """Find closest a, b, g closest to mr and mt."""
91
+ if self.ur1 is None:
92
+ raise ValueError("Grid.calc(exp) must be called before Grid.min_abg")
93
+
94
+ A = np.abs(mr - self.ur1) + np.abs(mt - self.ut1)
95
+ ii_flat = A.argmin()
96
+ i, j = ii_flat // A.shape[1], ii_flat % A.shape[1]
97
+ return self.a[i, j], self.b[i, j], self.g[i, j]
98
+
99
+ def is_stale(self, default):
100
+ """Decide if current grid is still useful."""
101
+ if self.default is None:
102
+ return True
103
+ if self.default != default:
104
+ return True
105
+ return False
106
+
107
+
108
+ def matrix_as_string(x, label=""):
109
+ """Return matrix as a string."""
110
+ if x is None:
111
+ return ""
112
+
113
+ n, m = x.shape
114
+
115
+ ndashes = (80 - len(label) - 2) // 2
116
+ s = "\n"
117
+ s += "-" * ndashes + " " + label + " " + "-" * ndashes
118
+ s += "\n[\n"
119
+ for i in range(n):
120
+ s += "["
121
+ for j in range(m):
122
+ s += "%6.3f, " % x[i, j]
123
+ s += "], \n"
124
+ s += "]\n"
125
+ return s