Loading [MathJax]/extensions/TeX/AMSsymbols.js
LALPulsar 7.1.1.1-5e288d3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
basis_functions.py
Go to the documentation of this file.
1# Copyright (C) 2019--2023 Benjamin Grace
2#
3# This program is free software; you can redistribute it and/or modify it
4# under the terms of the GNU General Public License as published by the
5# Free Software Foundation; either version 2 of the License, or (at your
6# option) any later version.
7#
8# This program is distributed in the hope that it will be useful, but
9# WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
11# Public License for more details.
12#
13# You should have received a copy of the GNU General Public License along
14# with this program; if not, write to the Free Software Foundation, Inc.,
15# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16
17## \file
18## \ingroup lalpulsar_python_piecewise_model
19"""
20Build the methods required for creating the basis functions of our piecewise model.
21"""
22
23import logging
24
25import numpy as np
26
27# It is worth noting here that initially conditioning of the matrices used here
28# was undertaken. Initially this was necessary as when plotting the basis
29# functions all that was returned was numerical fuzz, however many months after
30# having written these methods, I cannot recover this behaviour and the
31# conditioning used here seems to increase the condition number of the matrices
32# built here. For now the conditioning methods in this module have been
33# commented out until a later time, however for now without conditioning the
34# results produced appear to be returned accurately despite the
35# ill-conditionedness of the problem.
36
37knotslist = [0.0]
38
39# Returns the value of the ith knot. If we are using the methods in the estimating_knots module, this method should
40# simply extract the ith element from the knotslist variable above.
41def p(i):
42
43 return knotslist[i]
44
45
46# Our basis function
47def u(t, i):
48 return (t - p(i)) / (p(i + 1) - p(i))
49
50
51# Builds the W matrix whose inverse is the coefficients of our basis function
52def w(i, s):
53 try:
54 from sympy import Symbol, diff, lambdify
55 except:
56 raise ImportError("Cannot import sympy")
57
58 t = Symbol("t")
59
60 ps = p(i)
61 pe = p(i + 1)
62
63 matrixupper = []
64 matrixlower = []
65
66 thisrowderivs = [u(t, i) ** m for m in range(2 * s)]
67
68 for row in range(s):
69
70 if row != 0:
71 for j, elem in enumerate(thisrowderivs):
72 thisrowderivs[j] = diff(elem, t, 1)
73
74 thisrows = []
75 thisrowe = []
76
77 for elem in thisrowderivs:
78 thiselem = lambdify(t, elem, "numpy")
79
80 thisrows.append(thiselem(ps))
81 thisrowe.append(thiselem(pe))
82
83 matrixupper.append(thisrows)
84 matrixlower.append(thisrowe)
85
86 return np.array(matrixupper + matrixlower)
87
88
89# Returns the pseudo inverse of a list to the given power
90def listpseudoinv(lst, pwr=1):
91 invlist = []
92
93 for elem in lst:
94 if elem != 0:
95 invlist.append(elem**-pwr)
96 else:
97 invlist.append(0)
98
99 return invlist
100
101
102# Builds a diagonal matrix with elements equal to the inverse of the diagonal elements of the given matrix
103def d(mat):
104 return np.diag(listpseudoinv(np.diagonal(mat)))
105
106
107# Returns the coefficients of our basis function in a 3D list. Reference elements by [ B or C ][ k ][ specific coeff ]
108def basiscoeffs(i, s, conditioning=True):
109 wmat = w(i, s)
110
111 if conditioning:
112 dmat = d(wmat)
113 dwmat = np.matmul(dmat, wmat)
114
115 else:
116 dmat = np.identity(len(wmat))
117 dwmat = wmat
118
119 try:
120 coeffs = np.transpose(np.linalg.solve(dwmat, dmat))
121 except np.linalg.LinAlgError as error:
122 logging.error(error)
123 logging.error(
124 "Error in calculating basis functions. Using Python LSTSQ method instead"
125 )
126 coeffs = np.linalg.lstsq(dwmat, dmat)[0]
127
128 blist = coeffs[0:s]
129 clist = coeffs[s : 2 * s]
130
131 return np.array([blist, clist])
132
133
134# Returns the coefficients of all basis functions in a 4D list. Reference elements by [ int ][ B or C][ k ][ specific
135# coeff ]
137 coeffs = [basiscoeffs(i, s) for i in range(len(knotslist) - 1)]
138
139 return np.array(coeffs)
140
141
142# allcoeffs(3, 10, 10000)
143
144# Returns the value of a specified basis function given the 4D list of coefficients coeffs.
145def basisfunctionvalue(t, i, borc, s, coeffs):
146 val = 0
147
148 if t < p(i) or p(i + 1) < t:
149 return 0
150
151 thesecoeffs = coeffs[i][borc][s]
152
153 for m, coeff in enumerate(thesecoeffs):
154 val += coeff * u(t, i) ** m
155
156 return val
def basisfunctionvalue(t, i, borc, s, coeffs)
def basiscoeffs(i, s, conditioning=True)