@@ -21,6 +21,8 @@ def _interpolator_4cubic(grid, ws, idxs):
2121 ws: list of 4 weight arrays, each of shape (N, 4)
2222 idxs: list of 4 index arrays, each of shape (N, 4)
2323 """
24+ # 4D tensor-product cubic:
25+ # f=Σ_i Σ_j Σ_k Σ_l w0_i w1_j w2_k w3_l f(i,j,k,l)
2426 res = np .zeros (ws [0 ].shape [0 ])
2527 for i in range (4 ):
2628 w_i = ws [0 ][:, i ]
@@ -43,6 +45,8 @@ def _interpolator_5cubic(grid, ws, idxs):
4345 Perform 5D cubic interpolation for bolometric corrections.
4446 The dimensions are usually logTeff, logg, [Fe/H], [alpha/Fe], and Av.
4547 """
48+ # 5D tensor-product cubic:
49+ # f=Σ_i Σ_j Σ_k Σ_l Σ_m Π_d w_d * f(vertex)
4650 res = np .zeros (ws [0 ].shape [0 ])
4751 for i in range (4 ):
4852 w_i = ws [0 ][:, i ]
@@ -131,7 +135,7 @@ def read_bolom(filt, iprefix):
131135
132136class BCInterpolator :
133137
134- def __init__ (self , prefix , filts ):
138+ def __init__ (self , prefix , filts , linear = False ):
135139 filts = set (filts )
136140 vec = np .load (prefix + '/' + POINTS_NPY )
137141 ndim = vec .shape [0 ]
@@ -149,6 +153,7 @@ def __init__(self, prefix, filts):
149153 for a in itertools .product (* [[0 , 1 ]] * self .ndim ):
150154 self .box_list .append ((a ))
151155 self .box_list = np .array (self .box_list )
156+ self .linear = bool (linear )
152157 self ._warned_feh_floor = False
153158 for f in filts :
154159 curd = np .zeros (size ) - np .nan
@@ -170,6 +175,8 @@ def __call__(self, p):
170175 bad = np .zeros (p .shape [0 ], dtype = bool )
171176 ws = []
172177 idxs = []
178+ pos1 = np .zeros (p .shape , dtype = int )
179+ xs = np .zeros (p .shape )
173180 for i in range (self .ndim ):
174181 p_dim = p [:, i ]
175182 # For BC interpolation, clamp very metal-poor values to the BC
@@ -185,14 +192,26 @@ def __call__(self, p):
185192 p_dim = clipped
186193 pos = np .searchsorted (self .uvecs [i ], p_dim , 'right' ) - 1
187194 bad = bad | (pos < 0 ) | (pos >= (len (self .uvecs [i ]) - 1 ))
188- # Clip pos for cubic neighbors
189- pos_clipped = np .clip (pos , 0 , len (self .uvecs [i ]) - 2 )
190- w , idx = _get_cubic_coeffs (p_dim , self .uvecs [i ], pos_clipped )
191- ws .append (w )
192- idxs .append (idx )
195+ pos1 [:, i ] = np .clip (pos , 0 , len (self .uvecs [i ]) - 2 )
196+ xs [:, i ] = (p_dim - self .uvecs [i ][pos1 [:, i ]]) / (
197+ self .uvecs [i ][pos1 [:, i ] + 1 ] - self .uvecs [i ][pos1 [:, i ]])
198+ if not self .linear :
199+ w , idx = _get_cubic_coeffs (p_dim , self .uvecs [i ], pos1 [:, i ])
200+ ws .append (w )
201+ idxs .append (idx )
193202
194203 for f in self .filts :
195- if self .ndim == 4 :
204+ if self .linear :
205+ curinds = pos1 [None , :, :] + self .box_list [:, None , :]
206+ # N-D poly-linear interpolation over BC grid:
207+ # BC(p) = Σ_v [Π_d x_d^a_{v,d}(1-x_d)^(1-a_{v,d})] * BC(vertex_v)
208+ curcoeffs = (
209+ xs [None , :, :]** self .box_list [:, None , :] *
210+ (1 - xs [None , :, :])** (1 - self .box_list )[:, None , :]
211+ ).prod (axis = 2 )
212+ curinds1 = np .ravel_multi_index (curinds .T , self .dats [f ].shape )
213+ curres = (self .dats [f ].flat [curinds1 ] * curcoeffs .T ).sum (axis = 1 )
214+ elif self .ndim == 4 :
196215 curres = _interpolator_4cubic (self .dats [f ], ws , idxs )
197216 elif self .ndim == 5 :
198217 curres = _interpolator_5cubic (self .dats [f ], ws , idxs )
0 commit comments