30
30
... )
31
31
32
32
The variables are the horizontal displacement ``dx`` of all quadrupoles. The variable
33
- name is set to *dx_nnnn* where *nnnn* is the index of the quadruple in the lattice.
33
+ name is set to *dx_nnnn* where *nnnn* is the index of the quadrupole in the lattice.
34
34
The step is set to 0.0001 m.
35
35
36
36
Let's take the horizontal positions at all beam position monitors as observables:
@@ -228,8 +228,9 @@ class _SvdSolver(abc.ABC):
228
228
_obsmask : npt .NDArray [bool ]
229
229
_varmask : npt .NDArray [bool ]
230
230
_response : FloatArray | None = None
231
- v : FloatArray | None = None
232
- uh : FloatArray | None = None
231
+ _v : FloatArray | None = None
232
+ _uh : FloatArray | None = None
233
+ #: Singular values of the response matrix
233
234
singular_values : FloatArray | None = None
234
235
235
236
def __init__ (self , nobs : int , nvar : int ):
@@ -240,15 +241,15 @@ def __init__(self, nobs: int, nvar: int):
240
241
def reset_vars (self ):
241
242
"""Reset the variable exclusion mask: enable all variables"""
242
243
self ._varmask = np .ones (self .shape [1 ], dtype = bool )
243
- self .v = None
244
- self .uh = None
244
+ self ._v = None
245
+ self ._uh = None
245
246
self .singular_values = None
246
247
247
248
def reset_obs (self ):
248
249
"""Reset the observable exclusion mask: enable all observables"""
249
250
self ._obsmask = np .ones (self .shape [0 ], dtype = bool )
250
- self .v = None
251
- self .uh = None
251
+ self ._v = None
252
+ self ._uh = None
252
253
self .singular_values = None
253
254
254
255
@property
@@ -269,11 +270,11 @@ def solve(self) -> None:
269
270
resp = self .weighted_response
270
271
selected = np .ix_ (self ._obsmask , self ._varmask )
271
272
u , s , vh = np .linalg .svd (resp [selected ], full_matrices = False )
272
- self .v = vh .T * (1 / s ) * self .varweights [self ._varmask ].reshape (- 1 , 1 )
273
- self .uh = u .T / self .obsweights [self ._obsmask ]
273
+ self ._v = vh .T * (1 / s ) * self .varweights [self ._varmask ].reshape (- 1 , 1 )
274
+ self ._uh = u .T / self .obsweights [self ._obsmask ]
274
275
self .singular_values = s
275
276
276
- def check_norm (self ) -> tuple [np . ndarray , np . ndarray ]:
277
+ def check_norm (self ) -> tuple [FloatArray , FloatArray ]:
277
278
"""Display the norm of the rows and columns of the weighted response matrix.
278
279
279
280
Adjusting the variables and observable weights to equalize the norms
@@ -309,7 +310,7 @@ def response(self, response: FloatArray) -> None:
309
310
self ._response = response
310
311
311
312
@property
312
- def weighted_response (self ) -> np . ndarray :
313
+ def weighted_response (self ) -> FloatArray :
313
314
"""Weighted response matrix."""
314
315
return self .response * (self .varweights / self .obsweights .reshape (- 1 , 1 ))
315
316
@@ -329,11 +330,11 @@ def correction_matrix(self, nvals: int | None = None) -> FloatArray:
329
330
nvals = len (self .singular_values )
330
331
cormat = np .zeros (self ._shape [::- 1 ])
331
332
selected = np .ix_ (self ._varmask , self ._obsmask )
332
- cormat [selected ] = self .v [:, :nvals ] @ self .uh [:nvals , :]
333
+ cormat [selected ] = self ._v [:, :nvals ] @ self ._uh [:nvals , :]
333
334
return cormat
334
335
335
336
def get_correction (
336
- self , observed : np . ndarray , nvals : int | None = None
337
+ self , observed : FloatArray , nvals : int | None = None
337
338
) -> FloatArray :
338
339
"""Compute the correction of the given observation.
339
340
@@ -384,7 +385,7 @@ class ResponseMatrix(_SvdSolver):
384
385
ring : Lattice
385
386
variables : VariableList #: List of matrix :py:class:`Variable <.VariableBase>`\ s
386
387
observables : ObservableList #: List of matrix :py:class:`.Observable`\s
387
- eval_args : dict [str , Any ] = {}
388
+ _eval_args : dict [str , Any ] = {}
388
389
389
390
def __init__ (
390
391
self ,
@@ -433,7 +434,7 @@ def __str__(self):
433
434
return f"{ type (self ).__name__ } ({ no } observables, { nv } variables)"
434
435
435
436
@property
436
- def varweights (self ) -> np . ndarray :
437
+ def varweights (self ):
437
438
"""Variable weights."""
438
439
return self .variables .deltas
439
440
@@ -444,7 +445,7 @@ def obsweights(self) -> np.ndarray:
444
445
445
446
def correct (
446
447
self , ring : Lattice , nvals : int = None , niter : int = 1 , apply : bool = False
447
- ) -> np . ndarray :
448
+ ) -> FloatArray :
448
449
"""Compute and optionally apply the correction.
449
450
450
451
Args:
@@ -469,7 +470,7 @@ def correct(
469
470
sumcorr = np .array ([0.0 ])
470
471
for it , nv in zip (range (niter ), np .broadcast_to (nvals , (niter ,))):
471
472
print (f'step { it + 1 } , nvals = { nv } ' )
472
- obs .evaluate (ring , ** self .eval_args )
473
+ obs .evaluate (ring , ** self ._eval_args )
473
474
err = obs .flat_deviations
474
475
if np .any (np .isnan (err )):
475
476
raise AtError (
@@ -512,7 +513,7 @@ def build_tracking(
512
513
Returns:
513
514
response: Response matrix
514
515
"""
515
- self .eval_args = kwargs
516
+ self ._eval_args = kwargs
516
517
self .observables .evaluate (self .ring )
517
518
ring = self .ring .deepcopy ()
518
519
@@ -720,8 +721,8 @@ class OrbitResponseMatrix(ResponseMatrix):
720
721
... )
721
722
"""
722
723
723
- bpmrefs : Uint32Refpts
724
- steerrefs : Uint32Refpts
724
+ bpmrefs : Uint32Refpts #: location of position monitors
725
+ steerrefs : Uint32Refpts #: location of steerers
725
726
726
727
def __init__ (
727
728
self ,
@@ -731,7 +732,7 @@ def __init__(
731
732
steerrefs : Refpts = _orbit_correctors ,
732
733
* ,
733
734
cavrefs : Refpts = None ,
734
- bpmweight : float = 1.0 ,
735
+ bpmweight : float | Sequence [ float ] = 1.0 ,
735
736
bpmtarget : float | Sequence [float ] = 0.0 ,
736
737
steerdelta : float | Sequence [float ] = 0.0001 ,
737
738
cavdelta : float | None = None ,
@@ -761,8 +762,6 @@ def __init__(
761
762
is also the cavity weight. Default: automatically computed.
762
763
steerdelta: Step on steerers for matrix computation [rad]. This is
763
764
also the steerer weight. Must be broadcastable to the number of steerers.
764
- cavdelta: Step on RF frequency for matrix computation [Hz]. This
765
- is also the cavity weight
766
765
steersum: If :py:obj:`True`, the sum of steerers is appended to the
767
766
Observables.
768
767
stsumweight: Weight on steerer summation. Default: automatically computed.
@@ -980,39 +979,39 @@ def tauwj(muj, muw):
980
979
return resp
981
980
982
981
@property
983
- def bpmweight (self ) -> np . ndarray :
982
+ def bpmweight (self ) -> FloatArray :
984
983
"""Weight of position readings."""
985
984
return self .observables [0 ].weight
986
985
987
986
@bpmweight .setter
988
- def bpmweight (self , value ):
987
+ def bpmweight (self , value : npt . ArrayLike ):
989
988
self .observables [0 ].weight = value
990
989
991
990
@property
992
- def stsumweight (self ) -> np . ndarray :
991
+ def stsumweight (self ) -> FloatArray :
993
992
"""Weight of steerer summation."""
994
993
return self .observables [1 ].weight
995
994
996
995
@stsumweight .setter
997
- def stsumweight (self , value ):
996
+ def stsumweight (self , value : float ):
998
997
self .observables [1 ].weight = value
999
998
1000
999
@property
1001
- def steerdelta (self ) -> np . ndarray :
1000
+ def steerdelta (self ) -> FloatArray :
1002
1001
"""Step and weight of steerers."""
1003
1002
return self .variables [: self .nbsteers ].deltas
1004
1003
1005
1004
@steerdelta .setter
1006
- def steerdelta (self , value ):
1005
+ def steerdelta (self , value : npt . ArrayLike ):
1007
1006
self .variables [: self .nbsteers ].deltas = value
1008
1007
1009
1008
@property
1010
- def cavdelta (self ) -> np . ndarray :
1009
+ def cavdelta (self ) -> FloatArray :
1011
1010
"""Step and weight of RF frequency deviation."""
1012
1011
return self .variables [self .nbsteers ].delta
1013
1012
1014
1013
@cavdelta .setter
1015
- def cavdelta (self , value ):
1014
+ def cavdelta (self , value : float ):
1016
1015
self .variables [self .nbsteers ].delta = value
1017
1016
1018
1017
@@ -1111,7 +1110,7 @@ def build_analytical(self, **kwargs) -> FloatArray:
1111
1110
"""
1112
1111
ring = self .ring
1113
1112
pl = self .plane
1114
- twiss_in = self .eval_args .get ("twiss_in" , self ._default_twiss_in )
1113
+ twiss_in = self ._eval_args .get ("twiss_in" , self ._default_twiss_in )
1115
1114
_ , _ , elemdata = ring .linopt6 (All , twiss_in = twiss_in , ** kwargs )
1116
1115
dataj = elemdata [self .bpmrefs ]
1117
1116
dataw = elemdata [self .steerrefs ]
@@ -1178,12 +1177,12 @@ def exclude_vars(self, *varid: int | str, refpts: Refpts = None) -> None:
1178
1177
super ().exclude_vars (* varid , * names )
1179
1178
1180
1179
@property
1181
- def bpmweight (self ) -> np . ndarray :
1180
+ def bpmweight (self ) -> FloatArray :
1182
1181
"""Weight of position readings."""
1183
1182
return self .observables [0 ].weight
1184
1183
1185
1184
@bpmweight .setter
1186
- def bpmweight (self , value ):
1185
+ def bpmweight (self , value : npt . ArrayLike ):
1187
1186
self .observables [0 ].weight = value
1188
1187
1189
1188
@property
0 commit comments