Skip to content

Commit 55a1005

Browse files
committed
Merge branch 'niharika-krithika-mohammad-regionConstraints' of https://github.com/niharika2999/pysensors into niharika-krithika-mohammad-regionConstraints
2 parents db7d378 + 5671ebb commit 55a1005

File tree

8 files changed

+914
-153
lines changed

8 files changed

+914
-153
lines changed

.pre-commit-config.yaml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11

22
fail_fast: false
33
repos:
4-
- repo: git://github.com/pre-commit/pre-commit-hooks
5-
rev: master
4+
- repo: https://github.com/pre-commit/pre-commit-hooks
5+
rev: v4.3.0
66
hooks:
77
- id: check-added-large-files
88
args: ["--maxkb=775"]
99
- id: check-merge-conflict
1010
- repo: https://github.com/asottile/reorder_python_imports
11-
rev: v1.0.1
11+
rev: v3.8.2
1212
hooks:
1313
- id: reorder-python-imports
1414
- repo: https://github.com/ambv/black
15-
rev: stable
15+
rev: 22.8.0
1616
hooks:
1717
- id: black
1818
- repo: https://gitlab.com/pycqa/flake8
19-
rev: master
19+
rev: 3.9.2
2020
hooks:
2121
- id: flake8
2222
args: ["--config=setup.cfg"]

examples/region_optimal.ipynb

Lines changed: 547 additions & 24 deletions
Large diffs are not rendered by default.

pysensors/classification/_sspoc.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ def fit(
259259

260260
if self.threshold is None:
261261
# Chosen as in Brunton et al. (2016)
262-
threshold = np.sqrt(np.sum(s ** 2)) / (
262+
threshold = np.sqrt(np.sum(s**2)) / (
263263
2 * self.basis_matrix_inverse_.shape[0] * n_classes
264264
)
265265
else:

pysensors/optimizers/_gqr.py

Lines changed: 115 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import numpy as np
2+
import pysensors
23

34
from pysensors.optimizers._qr import QR
45

@@ -8,6 +9,8 @@
89
from mpl_toolkits.axes_grid1 import make_axes_locatable
910

1011
import pysensors as ps
12+
from matplotlib.patches import Circle
13+
from pydmd import DMD
1114

1215

1316
class GQR(QR):
@@ -27,7 +30,7 @@ class GQR(QR):
2730
2831
@ authors: Niharika Karnik (@nkarnik2999), Mohammad Abdo (@Jimmy-INL), and Krithika Manohar (@kmanohar)
2932
"""
30-
def __init__(self,idx_constrained,n_sensors,n_const_sensors,all_sensors,constraint_option):
33+
def __init__(self,idx_constrained,n_sensors,n_const_sensors,all_sensors,constraint_option,nx,ny,r):
3134
"""
3235
Attributes
3336
----------
@@ -47,11 +50,15 @@ def __init__(self,idx_constrained,n_sensors,n_const_sensors,all_sensors,constrai
4750
"""
4851
self.pivots_ = None
4952
self.optimality = None
53+
5054
self.constrainedIndices = idx_constrained
5155
self.nSensors = n_sensors
5256
self.nConstrainedSensors = n_const_sensors
5357
self.all_sensorloc = all_sensors
5458
self.constraint_option = constraint_option
59+
self._nx = nx
60+
self._ny = ny
61+
self._r = r
5562

5663
def fit(
5764
self,
@@ -75,11 +82,11 @@ def fit(
7582
max_const_sensors = len(self.constrainedIndices) #Maximum number of sensors allowed in the constrained region
7683

7784
## Assertions and checks:
78-
if self.nSensors > n_features - max_const_sensors + self.nConstrainedSensors:
79-
raise IOError ("n_sensors cannot be larger than n_features - all possible locations in the constrained area + allowed constrained sensors")
80-
if self.nSensors > n_samples + self.nConstrainedSensors: ## Handling zero constraint?
81-
raise IOError ("Currently n_sensors should be less than min(number of samples, number of modes) + number of constrained sensors,\
82-
got: n_sensors = {}, n_samples + const_sensors = {} + {} = {}".format(self.nSensors,n_samples,self.nConstrainedSensors,n_samples+self.nConstrainedSensors))
85+
# if self.nSensors > n_features - max_const_sensors + self.nConstrainedSensors:
86+
# 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?
88+
# 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))
8390

8491
# Initialize helper variables
8592
R = basis_matrix.conj().T.copy()
@@ -92,14 +99,34 @@ def fit(
9299
# Norm of each column
93100
dlens = np.sqrt(np.sum(np.abs(r) ** 2, axis=0))
94101
if self.constraint_option == "max_n_const_sensors" :
95-
dlens_updated = norm_calc_max_n_const_sensors(self.constrainedIndices,dlens,p,j, self.nConstrainedSensors,self.all_sensorloc,self.nSensors)
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]
96105
elif self.constraint_option == "exact_n_const_sensors" :
97-
dlens_updated = norm_calc_exact_n_const_sensors(self.constrainedIndices,dlens,p,j,self.nConstrainedSensors)
98-
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+
99126
# Choose pivot
100-
i_piv = np.argmax(dlens_updated)
127+
# i_piv = np.argmax(dlens_updated)
101128

102-
dlen = dlens_updated[i_piv]
129+
# dlen = dlens_updated[i_piv]
103130

104131
if dlen > 0:
105132
u = r[:, i_piv] / dlen
@@ -121,108 +148,30 @@ def fit(
121148
R[j + 1 :, j] = 0
122149

123150
self.pivots_ = p
124-
self.optimality = np.trace(np.real(R))
125-
print("The trace(R) = {}".format(self.optimality))
126-
151+
127152
return self
128153

129-
## TODO: why not a part of the class?
130-
131-
#function for mapping sensor locations with constraints
132-
def norm_calc_exact_n_const_sensors(lin_idx, dlens, piv, j, n_const_sensors): ##Will first force sensors into constrained region
133-
#num_sensors should be fixed for each custom constraint (for now)
134-
#num_sensors must be <= size of constraint region
135-
"""
136-
Function for mapping constrained sensor locations with the QR procedure.
137-
138-
Parameters
139-
----------
140-
lin_idx: np.ndarray, shape [No. of constrained locations]
141-
Array which contains the constrained locationsof the grid in terms of column indices of basis_matrix.
142-
dlens: np.ndarray, shape [Variable based on j]
143-
Array which contains the norm of columns of basis matrix.
144-
piv: np.ndarray, shape [n_features]
145-
Ranked list of sensor locations.
146-
n_const_sensors: int,
147-
Number of sensors to be placed in the constrained area.
148-
j: int,
149-
Iterative variable in the QR algorithm.
150-
151-
Returns
152-
-------
153-
dlens : np.darray, shape [Variable based on j] with constraints mapped into it.
154-
"""
155-
if j < n_const_sensors: # force sensors into constraint region
156-
#idx = np.arange(dlens.shape[0])
157-
#dlens[np.delete(idx, lin_idx)] = 0
158-
159-
didx = np.isin(piv[j:],lin_idx,invert=True)
160-
dlens[didx] = 0
161-
else:
162-
didx = np.isin(piv[j:],lin_idx,invert=False)
163-
dlens[didx] = 0
164-
return dlens
165-
166-
def norm_calc_max_n_const_sensors(lin_idx, dlens, piv, j, const_sensors,all_sensors,n_sensors): ##Optimal sensor placement with constraints (will place sensors in the order of QR)
167-
"""
168-
Function for mapping constrained sensor locations with the QR procedure (Optimally).
169-
170-
Parameters
171-
----------
172-
lin_idx: np.ndarray, shape [No. of constrained locations]
173-
Array which contains the constrained locationsof the grid in terms of column indices of basis_matrix.
174-
dlens: np.ndarray, shape [Variable based on j]
175-
Array which contains the norm of columns of basis matrix.
176-
piv: np.ndarray, shape [n_features]
177-
Ranked list of sensor locations.
178-
j: int,
179-
Iterative variable in the QR algorithm.
180-
const_sensors: int,
181-
Number of sensors to be placed in the constrained area.
182-
all_sensors: np.ndarray, shape [n_features]
183-
Ranked list of sensor locations.
184-
n_sensors: integer,
185-
Total number of sensors
186-
187-
Returns
188-
-------
189-
dlens : np.darray, shape [Variable based on j] with constraints mapped into it.
190-
"""
191-
counter = 0
192-
mask = np.isin(all_sensors,lin_idx,invert=False)
193-
const_idx = all_sensors[mask]
194-
updated_lin_idx = const_idx[const_sensors:]
195-
for i in range(n_sensors):
196-
if np.isin(all_sensors[i],lin_idx,invert=False):
197-
counter += 1
198-
if counter < const_sensors:
199-
dlens = dlens
200-
else:
201-
didx = np.isin(piv[j:],updated_lin_idx,invert=False)
202-
dlens[didx] = 0
203-
return dlens
204-
205-
206-
207154
if __name__ == '__main__':
208155
faces = datasets.fetch_olivetti_faces(shuffle=True)
209156
X = faces.data
210157

211-
n_samples, n_features = X.shape
158+
# n_samples, n_features = X.shape
159+
X_small = X[:,:256]
160+
n_samples, n_features = X_small.shape
212161
print('Number of samples:', n_samples)
213162
print('Number of features (sensors):', n_features)
214163

215164
# Global centering
216-
X = X - X.mean(axis=0)
165+
X_small = X_small - X_small.mean(axis=0)
217166

218167
# Local centering
219-
X -= X.mean(axis=1).reshape(n_samples, -1)
168+
X_small -= X_small.mean(axis=1).reshape(n_samples, -1)
220169

221170
n_row, n_col = 2, 3
222171
n_components = n_row * n_col
223-
image_shape = (64, 64)
224-
nx = 64
225-
ny = 64
172+
image_shape = (16, 16)
173+
nx = 16
174+
ny = 16
226175

227176
def plot_gallery(title, images, n_col=n_col, n_row=n_row, cmap=plt.cm.gray):
228177
'''Function for plotting faces'''
@@ -241,25 +190,44 @@ def plot_gallery(title, images, n_col=n_col, n_row=n_row, cmap=plt.cm.gray):
241190
# plot_gallery("First few centered faces", X[:n_components])
242191

243192
#Find all sensor locations using built in QR optimizer
244-
max_const_sensors = 230
245-
n_const_sensors = 2
246-
n_sensors = 200
193+
#max_const_sensors = 230
194+
n_const_sensors = 3
195+
n_sensors = 4
196+
n_modes = 40
197+
r = 2
198+
# dmd = DMD(svd_rank=0,exact=True,opt=False)
199+
# dmd.fit(X.T)
200+
# U = dmd.modes.real
201+
# np.shape(U)
202+
# max_basis_modes = 200
203+
204+
# model_dmd_unconstrained = ps.SSPOR(n_sensors=n_sensors, basis=ps.basis.Custom(n_basis_modes=n_modes, U=U))
205+
# model_dmd_unconstrained.fit(X)
206+
# basis_matrix_dmd = model_dmd_unconstrained.basis_matrix_
207+
208+
# all_sensors_dmd_unconstrained = model_dmd_unconstrained.get_all_sensors()
209+
# top_sensors_dmd_unconstrained = model_dmd_unconstrained.get_selected_sensors()
210+
# optimality_dmd = ps.utils._validation.determinant(top_sensors_dmd_unconstrained, n_features, basis_matrix_dmd)
211+
# print(optimality0)
212+
#basis = ps.basis.SVD(n_basis_modes=n_modes)
247213
optimizer = ps.optimizers.QR()
248214
model = ps.SSPOR(optimizer=optimizer, n_sensors=n_sensors)
249-
model.fit(X)
250-
215+
model.fit(X_small)
216+
top_sensors0 = model.get_selected_sensors()
251217
all_sensors = model.get_all_sensors()
252-
218+
# basis_matrix0 = model.basis_matrix_
219+
# optimality0 = ps.utils._validation.determinant(top_sensors0, n_features, basis_matrix0)
220+
# print(optimality0)
253221
##Constrained sensor location on the grid:
254-
xmin = 20
255-
xmax = 40
256-
ymin = 25
257-
ymax = 45
222+
xmin = 0
223+
xmax = 64
224+
ymin = 10
225+
ymax = 30
258226
sensors_constrained = ps.utils._constraints.get_constraind_sensors_indices(xmin,xmax,ymin,ymax,nx,ny,all_sensors) #Constrained column indices
259-
260227
# didx = np.isin(all_sensors,sensors_constrained,invert=False)
261228
# const_index = np.nonzero(didx)
262229
# j =
230+
263231

264232

265233
##Plotting the constrained region
@@ -276,24 +244,51 @@ def plot_gallery(title, images, n_col=n_col, n_row=n_row, cmap=plt.cm.gray):
276244
# plt.title('Constrained region');
277245

278246
## Fit the dataset with the optimizer GQR
279-
optimizer1 = GQR(sensors_constrained,n_sensors,n_const_sensors,all_sensors, constraint_option = "exact_n_const_sensors")
280-
model1 = ps.SSPOR(optimizer = optimizer1, n_sensors = n_sensors)
281-
model1.fit(X)
247+
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)
249+
model1.fit(X_small)
282250
all_sensors1 = model1.get_all_sensors()
283-
251+
basis_matrix = model1.basis_matrix_
284252
top_sensors = model1.get_selected_sensors()
285253
print(top_sensors)
254+
# optimality = ps.utils._validation.determinant(top_sensors, n_features, basis_matrix)
255+
# print(optimality)
256+
# 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)
257+
# model_dmd_constrained = ps.SSPOR(n_sensors=n_sensors, basis=ps.basis.Custom(n_basis_modes=n_modes, U=U), optimizer = optimizer_dmd_constrained)
258+
# model_dmd_constrained.fit(X)
259+
# all_sensors_dmd_constrained = model_dmd_constrained.get_all_sensors()
260+
261+
# top_sensors_dmd_constrained = model_dmd_constrained.get_selected_sensors()
262+
# basis_matrix_dmd_constrained = model_dmd_constrained.basis_matrix_
263+
# optimality = ps.utils._validation.determinant(top_sensors_dmd_constrained, n_features, basis_matrix_dmd_constrained)
264+
# print(optimality)
265+
286266
## TODO: this can be done using ravel and unravel more elegantly
287267
#yConstrained = np.floor(top_sensors[:n_const_sensors]/np.sqrt(n_features))
288268
#xConstrained = np.mod(top_sensors[:n_const_sensors],np.sqrt(n_features))
289269

270+
# img = np.zeros(n_features)
271+
# img[top_sensors_dmd_constrained] = 16
272+
# #plt.plot(xConstrained,yConstrained,'*r')
273+
# plt.plot([xmin,xmin],[ymin,ymax],'r')
274+
# plt.plot([xmin,xmax],[ymax,ymax],'r')
275+
# plt.plot([xmax,xmax],[ymin,ymax],'r')
276+
# plt.plot([xmin,xmax],[ymin,ymin],'r')
277+
# plt.imshow(img.reshape(image_shape),cmap=plt.cm.binary)
278+
# plt.title('n_sensors = {}, n_constr_sensors = {}'.format(n_sensors,n_const_sensors))
279+
# plt.show()
280+
290281
img = np.zeros(n_features)
291282
img[top_sensors] = 16
292-
#plt.plot(xConstrained,yConstrained,'*r')
293-
plt.plot([xmin,xmin],[ymin,ymax],'r')
294-
plt.plot([xmin,xmax],[ymax,ymax],'r')
295-
plt.plot([xmax,xmax],[ymin,ymax],'r')
296-
plt.plot([xmin,xmax],[ymin,ymin],'r')
297-
plt.imshow(img.reshape(image_shape),cmap=plt.cm.binary)
298-
plt.title('n_sensors = {}, n_constr_sensors = {}'.format(n_sensors,n_const_sensors))
283+
fig,ax = plt.subplots(1)
284+
ax.set_aspect('equal')
285+
ax.imshow(img.reshape(image_shape),cmap=plt.cm.binary)
286+
print(top_sensors)
287+
top_sensors_grid = np.unravel_index(top_sensors, (nx,ny))
288+
# figure, axes = plt.subplots()
289+
for i in range(len(top_sensors_grid[0])):
290+
circ = Circle( (top_sensors_grid[1][i], top_sensors_grid[0][i]), r ,color='r',fill = False )
291+
ax.add_patch(circ)
299292
plt.show()
293+
294+

0 commit comments

Comments
 (0)