Skip to content

Commit 5e8664b

Browse files
authored
Merge pull request #2 from Jimmy-INL/cleaningGQR
Cleaning GQR and generating unit tests
2 parents 5671ebb + 9f1d5e6 commit 5e8664b

File tree

7 files changed

+257
-119
lines changed

7 files changed

+257
-119
lines changed

pysensors/basis/_base.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ def matrix_representation(self, n_basis_modes=None, copy=False):
4343
n_basis_modes = self._validate_input(n_basis_modes)
4444

4545
if copy:
46-
return self.basis_matrix_[:, :n_basis_modes].copy()
46+
return self.basis_matrix_[:, :n_basis_modes].copy()#self.original_data @
4747
else:
48-
return self.basis_matrix_[:, :n_basis_modes]
48+
return self.basis_matrix_[:, :n_basis_modes]#self.original_data @
4949

5050
def _validate_input(self, n_basis_modes):
5151
"""

pysensors/basis/_custom.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,7 @@
66

77
class Custom(InvertibleBasis, MatrixMixin):
88
"""
9-
<<<<<<< HEAD
10-
Use a custom transformation to maps input features to
11-
=======
12-
Generate a custom transformation which maps input features to
13-
>>>>>>> 1ccd23fafed0ca39dac6cde204efa228d133df1c
9+
Use a custom transformation to map input features to
1410
custom modes.
1511
1612
Assumes the data has already been centered (to have mean 0).

pysensors/basis/_identity.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from warnings import warn
77

88
from numpy import identity
9+
import numpy as np
910
from sklearn.base import BaseEstimator
1011
from sklearn.utils import check_array
1112

@@ -52,7 +53,6 @@ def fit(self, X):
5253
-------
5354
self : instance
5455
"""
55-
5656
# Note that we take a transpose here, so columns correspond to examples
5757
if self.n_basis_modes is None:
5858
self.basis_matrix_ = check_array(X).T.copy()
@@ -65,7 +65,7 @@ def fit(self, X):
6565
)
6666
)
6767

68-
self.basis_matrix_ = check_array(X)[: self.n_basis_modes, :].T.copy()
68+
self.basis_matrix_ = check_array(X)[: self.n_basis_modes, :].T.copy() # np.eye(X.shape[1])[:,:self.n_basis_modes]
6969

7070
if self.n_basis_modes < X.shape[0]:
7171
warn(f"Only the first {self.n_basis_modes} examples were retained.")

pysensors/optimizers/_gqr.py

Lines changed: 115 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@
1010

1111
import pysensors as ps
1212
from matplotlib.patches import Circle
13-
from pydmd import DMD
14-
13+
from pysensors.utils._norm_calc import returnInstance as normCalcReturnInstance
1514

1615
class GQR(QR):
1716
"""
@@ -30,7 +29,7 @@ class GQR(QR):
3029
3130
@ authors: Niharika Karnik (@nkarnik2999), Mohammad Abdo (@Jimmy-INL), and Krithika Manohar (@kmanohar)
3231
"""
33-
def __init__(self,idx_constrained,n_sensors,n_const_sensors,all_sensors,constraint_option,nx,ny,r):
32+
def __init__(self):#,idx_constrained,n_sensors,n_const_sensors,all_sensors,constraint_option,nx,ny,r
3433
"""
3534
Attributes
3635
----------
@@ -49,21 +48,18 @@ def __init__(self,idx_constrained,n_sensors,n_const_sensors,all_sensors,constrai
4948
exact_n_const_sensors : The number of sensors in the constrained region should be exactly equal to n_const_sensors.
5049
"""
5150
self.pivots_ = None
52-
self.optimality = None
53-
54-
self.constrainedIndices = idx_constrained
55-
self.nSensors = n_sensors
56-
self.nConstrainedSensors = n_const_sensors
57-
self.all_sensorloc = all_sensors
58-
self.constraint_option = constraint_option
59-
self._nx = nx
60-
self._ny = ny
61-
self._r = r
62-
63-
def fit(
64-
self,
65-
basis_matrix
66-
):
51+
# self.optimality = None
52+
53+
# self.constrainedIndices = idx_constrained
54+
# self.n_sensors = n_sensors
55+
# self.nConstrainedSensors = n_const_sensors
56+
# self.all_sensorloc = all_sensors
57+
# self.constraint_option = constraint_option
58+
# self._nx = nx
59+
# self._ny = ny
60+
# self._r = r
61+
62+
def fit(self,basis_matrix=None,**optimizer_kws):
6763
"""
6864
Parameters
6965
----------
@@ -77,16 +73,49 @@ def fit(
7773
-------
7874
self: a fitted :class:`pysensors.optimizers.QR` instance
7975
"""
76+
if 'idx_constrained' in optimizer_kws.keys():
77+
self.constrainedIndices = optimizer_kws['idx_constrained']
78+
else:
79+
self.constrainedIndices = []
80+
if 'n_sensors' in optimizer_kws.keys():
81+
self.n_sensors = optimizer_kws['n_sensors']
82+
else:
83+
self.n_sensors = np.shape(basis_matrix)[0]
84+
if 'n_const_sensors' in optimizer_kws.keys():
85+
self.nConstrainedSensors = optimizer_kws['n_const_sensors']
86+
else:
87+
self.nConstrainedSensors = None
88+
if 'all_sensors' in optimizer_kws.keys():
89+
self.all_sensors = optimizer_kws['all_sensors']
90+
else:
91+
self.all_sensors = None
92+
if 'constraint_option' in optimizer_kws.keys():
93+
self.constraint_option = optimizer_kws['constraint_option']
94+
self._norm_calc_Instance = normCalcReturnInstance(self,self.constraint_option)
95+
else:
96+
self.constraint_option = None
97+
if 'nx' in optimizer_kws.keys():
98+
self._nx = optimizer_kws['nx']
99+
else:
100+
self._nx = None
101+
if 'ny' in optimizer_kws.keys():
102+
self._ny = optimizer_kws['ny']
103+
else:
104+
self._ny = None
105+
if 'r' in optimizer_kws.keys():
106+
self._r = optimizer_kws['r']
107+
else:
108+
self._r = None
80109

81110
n_features, n_samples = basis_matrix.shape # We transpose basis_matrix below
82-
max_const_sensors = len(self.constrainedIndices) #Maximum number of sensors allowed in the constrained region
111+
max_const_sensors = len(self.constrainedIndices) # Maximum number of sensors allowed in the constrained region
83112

84113
## Assertions and checks:
85-
# if self.nSensors > n_features - max_const_sensors + self.nConstrainedSensors:
114+
# if self.n_sensors > n_features - max_const_sensors + self.nConstrainedSensors:
86115
# raise IOError ("n_sensors cannot be larger than n_features - all possible locations in the constrained area + allowed constrained sensors")
87-
# if self.nSensors > n_samples + self.nConstrainedSensors: ## Handling zero constraint?
116+
# if self.n_sensors > n_samples + self.nConstrainedSensors: ## Handling zero constraint?
88117
# raise IOError ("Currently n_sensors should be less than min(number of samples, number of modes) + number of constrained sensors,\
89-
# got: n_sensors = {}, n_samples + const_sensors = {} + {} = {}".format(self.nSensors,n_samples,self.nConstrainedSensors,n_samples+self.nConstrainedSensors))
118+
# got: n_sensors = {}, n_samples + const_sensors = {} + {} = {}".format(self.n_sensors,n_samples,self.nConstrainedSensors,n_samples+self.nConstrainedSensors))
90119

91120
# Initialize helper variables
92121
R = basis_matrix.conj().T.copy()
@@ -96,33 +125,40 @@ def fit(
96125

97126
for j in range(k):
98127
r = R[j:, j:]
128+
99129
# Norm of each column
100130
dlens = np.sqrt(np.sum(np.abs(r) ** 2, axis=0))
101-
if self.constraint_option == "max_n_const_sensors" :
102-
dlens_updated = ps.utils._norm_calc.norm_calc_max_n_const_sensors(self.constrainedIndices,dlens,p,j, self.nConstrainedSensors,self.all_sensorloc,self.nSensors)
103-
i_piv = np.argmax(dlens_updated)
104-
dlen = dlens_updated[i_piv]
105-
elif self.constraint_option == "exact_n_const_sensors" :
106-
dlens_updated = ps.utils._norm_calc.norm_calc_exact_n_const_sensors(self.constrainedIndices,dlens,p,j,self.nConstrainedSensors)
107-
i_piv = np.argmax(dlens_updated)
108-
dlen = dlens_updated[i_piv]
109-
elif self.constraint_option == "predetermined_end":
110-
dlens_updated = ps.utils._norm_calc.predetermined_norm_calc(self.constrainedIndices, dlens, p, j, self.nConstrainedSensors, self.nSensors)
111-
i_piv = np.argmax(dlens_updated)
112-
dlen = dlens_updated[i_piv]
113-
elif self.constraint_option == "radii_constraints":
114-
115-
if j == 0:
116-
i_piv = np.argmax(dlens)
117-
dlen = dlens[i_piv]
118-
dlens_old = dlens
119-
else:
120-
121-
dlens_updated = ps.utils._norm_calc.f_radii_constraint(j,dlens,dlens_old,p,self._nx,self._ny,self._r,self.all_sensorloc, self.nSensors) #( self.radius,self._nx,self._ny,self.all_sensorloc,dlens,p,j)
122-
i_piv = np.argmax(dlens_updated)
123-
dlen = dlens_updated[i_piv]
124-
dlens_old = dlens_updated
125-
131+
dlens_updated = self._norm_calc_Instance(self.constrainedIndices, dlens, p, j, self.nConstrainedSensors, all_sensors=self.all_sensors, n_sensors=self.n_sensors, nx=self._nx, ny=self._ny, r=self._r)
132+
i_piv = np.argmax(dlens_updated)
133+
dlen = dlens_updated[i_piv]
134+
# if self.constraint_option == "max_n_const_sensors" :
135+
# dlens_updated = ps.utils._norm_calc.norm_calc_max_n_const_sensors(self.constrainedIndices,dlens,p,j, self.nConstrainedSensors,self.all_sensorloc,self.n_sensors)
136+
# i_piv = np.argmax(dlens_updated)
137+
# dlen = dlens_updated[i_piv]
138+
# elif self.constraint_option == "exact_n_const_sensors" :
139+
# dlens_updated = ps.utils._norm_calc.norm_calc_exact_n_const_sensors(self.constrainedIndices,dlens,p,j,self.nConstrainedSensors)
140+
# i_piv = np.argmax(dlens_updated)
141+
# dlen = dlens_updated[i_piv]
142+
# elif self.constraint_option == "predetermined_end":
143+
# dlens_updated = ps.utils._norm_calc.predetermined_norm_calc(self.constrainedIndices, dlens, p, j, self.nConstrainedSensors, self.n_sensors)
144+
# i_piv = np.argmax(dlens_updated)
145+
# dlen = dlens_updated[i_piv]
146+
# elif self.constraint_option == "radii_constraints":
147+
148+
# if j == 0:
149+
# i_piv = np.argmax(dlens)
150+
# dlen = dlens[i_piv]
151+
# dlens_old = dlens
152+
# else:
153+
154+
# dlens_updated = ps.utils._norm_calc.f_radii_constraint(j,dlens,dlens_old,p,self._nx,self._ny,self._r,self.all_sensorloc, self.n_sensors) #( self.radius,self._nx,self._ny,self.all_sensorloc,dlens,p,j)
155+
# i_piv = np.argmax(dlens_updated)
156+
# dlen = dlens_updated[i_piv]
157+
# dlens_old = dlens_updated
158+
# else:
159+
# i_piv = np.argmax(dlens)
160+
# dlen = dlens[i_piv]
161+
126162
# Choose pivot
127163
# i_piv = np.argmax(dlens_updated)
128164

@@ -148,7 +184,6 @@ def fit(
148184
R[j + 1 :, j] = 0
149185

150186
self.pivots_ = p
151-
152187
return self
153188

154189
if __name__ == '__main__':
@@ -191,10 +226,10 @@ def plot_gallery(title, images, n_col=n_col, n_row=n_row, cmap=plt.cm.gray):
191226

192227
#Find all sensor locations using built in QR optimizer
193228
#max_const_sensors = 230
194-
n_const_sensors = 3
195-
n_sensors = 4
196-
n_modes = 40
197-
r = 2
229+
n_const_sensors = 0
230+
n_sensors = 10
231+
n_modes = 10
232+
r = 5
198233
# dmd = DMD(svd_rank=0,exact=True,opt=False)
199234
# dmd.fit(X.T)
200235
# U = dmd.modes.real
@@ -209,9 +244,9 @@ def plot_gallery(title, images, n_col=n_col, n_row=n_row, cmap=plt.cm.gray):
209244
# top_sensors_dmd_unconstrained = model_dmd_unconstrained.get_selected_sensors()
210245
# optimality_dmd = ps.utils._validation.determinant(top_sensors_dmd_unconstrained, n_features, basis_matrix_dmd)
211246
# print(optimality0)
212-
#basis = ps.basis.SVD(n_basis_modes=n_modes)
247+
basis = ps.basis.SVD(n_basis_modes=n_modes)
213248
optimizer = ps.optimizers.QR()
214-
model = ps.SSPOR(optimizer=optimizer, n_sensors=n_sensors)
249+
model = ps.SSPOR(optimizer=optimizer, n_sensors=n_sensors, basis=basis)
215250
model.fit(X_small)
216251
top_sensors0 = model.get_selected_sensors()
217252
all_sensors = model.get_all_sensors()
@@ -227,32 +262,32 @@ def plot_gallery(title, images, n_col=n_col, n_row=n_row, cmap=plt.cm.gray):
227262
# didx = np.isin(all_sensors,sensors_constrained,invert=False)
228263
# const_index = np.nonzero(didx)
229264
# j =
230-
231265

232266

233-
##Plotting the constrained region
234-
# ax = plt.subplot()
235-
# #Plot constrained space
236-
# img = np.zeros(n_features)
237-
# img[sensors_constrained] = 1
238-
# im = plt.imshow(img.reshape(image_shape),cmap=plt.cm.binary)
239-
# # create an axes on the right side of ax. The width of cax will be 5%
240-
# # of ax and the padding between cax and ax will be fixed at 0.05 inch.
241-
# divider = make_axes_locatable(ax)
242-
# cax = divider.append_axes("right", size="5%", pad=0.05)
243-
# plt.colorbar(im, cax=cax)
244-
# plt.title('Constrained region');
267+
268+
#Plotting the constrained region
269+
ax = plt.subplot()
270+
#Plot constrained space
271+
img = np.zeros(n_features)
272+
img[sensors_constrained] = 1
273+
im = plt.imshow(img.reshape(image_shape),cmap=plt.cm.binary)
274+
# create an axes on the right side of ax. The width of cax will be 5%
275+
# of ax and the padding between cax and ax will be fixed at 0.05 inch.
276+
divider = make_axes_locatable(ax)
277+
cax = divider.append_axes("right", size="5%", pad=0.05)
278+
plt.colorbar(im, cax=cax)
279+
plt.title('Constrained region')
245280

246281
## Fit the dataset with the optimizer GQR
247282
optimizer1 = GQR(sensors_constrained,n_sensors,n_const_sensors,all_sensors, constraint_option = "radii_constraints",nx = nx, ny = ny, r = r)
248-
model1 = ps.SSPOR( optimizer = optimizer1, n_sensors = n_sensors)
283+
model1 = ps.SSPOR( optimizer = optimizer1, n_sensors = n_sensors, basis=basis)
249284
model1.fit(X_small)
250285
all_sensors1 = model1.get_all_sensors()
251286
basis_matrix = model1.basis_matrix_
252287
top_sensors = model1.get_selected_sensors()
253288
print(top_sensors)
254-
# optimality = ps.utils._validation.determinant(top_sensors, n_features, basis_matrix)
255-
# print(optimality)
289+
optimality = ps.utils._validation.determinant(top_sensors, n_features, basis_matrix)
290+
print(optimality)
256291
# optimizer_dmd_constrained = ps.optimizers.GQR(sensors_constrained,n_sensors,n_const_sensors,all_sensors_dmd_unconstrained,constraint_option = "exact_n_const_sensors",nx = nx, ny = ny, r = r)
257292
# model_dmd_constrained = ps.SSPOR(n_sensors=n_sensors, basis=ps.basis.Custom(n_basis_modes=n_modes, U=U), optimizer = optimizer_dmd_constrained)
258293
# model_dmd_constrained.fit(X)
@@ -281,14 +316,21 @@ def plot_gallery(title, images, n_col=n_col, n_row=n_row, cmap=plt.cm.gray):
281316
img = np.zeros(n_features)
282317
img[top_sensors] = 16
283318
fig,ax = plt.subplots(1)
284-
ax.set_aspect('equal')
319+
285320
ax.imshow(img.reshape(image_shape),cmap=plt.cm.binary)
286321
print(top_sensors)
287322
top_sensors_grid = np.unravel_index(top_sensors, (nx,ny))
288323
# figure, axes = plt.subplots()
289324
for i in range(len(top_sensors_grid[0])):
290325
circ = Circle( (top_sensors_grid[1][i], top_sensors_grid[0][i]), r ,color='r',fill = False )
291326
ax.add_patch(circ)
327+
# ax.plot([xmin,xmin],[ymin,ymax],'-r')
328+
# ax.plot([xmax,xmax],[ymin,ymax],'-r')
329+
# ax.plot([xmin,xmax],[ymin,ymin],'-r')
330+
# ax.plot([xmin,xmax],[ymax,ymax],'-r')
331+
ax.set_aspect('equal')
332+
# ax.set_xlim([0,64])
333+
# ax.set_ylim([0,64])
292334
plt.show()
293-
294-
335+
336+

0 commit comments

Comments
 (0)