11"""Covariance matrix analysis."""
2-
32import numpy as np
43
54
@@ -8,6 +7,10 @@ def rms_ellipsoid_volume(cov_matrix: np.ndarray) -> float:
87
98
109def projected_emittances (cov_matrix : np .ndarray ) -> tuple [float , ...]:
10+ ndim = cov_matrix .shape [0 ]
11+ if ndim == 2 :
12+ return rms_ellipsoid_volume (cov_matrix )
13+
1114 emittances = []
1215 for i in range (0 , cov_matrix .shape [0 ], 2 ):
1316 emittance = rms_ellipsoid_volume (cov_matrix [i : i + 2 , i : i + 2 ])
@@ -16,8 +19,15 @@ def projected_emittances(cov_matrix: np.ndarray) -> tuple[float, ...]:
1619
1720
1821def intrinsic_emittances (cov_matrix : np .ndarray ) -> tuple [float , ...]:
19- S = cov_matrix [:4 , :4 ].copy () # [to do]: expand to NxN
20- U = unit_symplectic_matrix (4 )
22+ ndim = cov_matrix .shape [0 ]
23+ if ndim > 4 :
24+ raise ValueError ("ndim > 4" )
25+
26+ if ndim == 2 :
27+ return rms_ellipsoid_volume (cov_matrix )
28+
29+ S = cov_matrix .copy () # [to do] expand to NxN using np.eig
30+ U = unit_symplectic_matrix (ndim )
2131 tr_SU2 = np .trace (np .linalg .matrix_power (np .matmul (S , U ), 2 ))
2232 det_S = np .linalg .det (S )
2333 eps_1 = 0.5 * np .sqrt (- tr_SU2 + np .sqrt (tr_SU2 ** 2 - 16.0 * det_S ))
@@ -26,11 +36,6 @@ def intrinsic_emittances(cov_matrix: np.ndarray) -> tuple[float, ...]:
2636
2737
2838def twiss_2d (cov_matrix : np .ndarray ) -> tuple [float , float , float ]:
29- """Compute twiss parameters from 2 x 2 covariance matrix.
30-
31- alpha = -<xx'> / sqrt(<xx><x'x'> - <xx'><xx'>)
32- beta = <xx> / sqrt(<xx><x'x'> - <xx'><xx'>)
33- """
3439 emittance = rms_ellipsoid_volume (cov_matrix )
3540 beta = cov_matrix [0 , 0 ] / emittance
3641 alpha = - cov_matrix [0 , 1 ] / emittance
@@ -128,16 +133,22 @@ def normalization_matrix(
128133 block_diag : bool
129134 If true, normalize only 2x2 block-diagonal elements (x-x', y-y', etc.).
130135 """
131- def _normalization_matrix (_cov_matrix : np .ndarray , scale : bool = False ) -> np .ndarray :
132- S = _cov_matrix .copy ()
136+ def _normalization_matrix (cov_matrix : np .ndarray , scale : bool = False ) -> np .ndarray :
137+ S = cov_matrix .copy ()
133138 U = unit_symplectic_matrix (S .shape [0 ])
134139 eigvals , eigvecs = np .linalg .eig (np .matmul (S , U ))
135140 eigvecs = normalize_eigvecs (eigvecs )
136141 V_inv = normalization_matrix_from_eigvecs (eigvecs )
137142
138143 if scale :
144+ ndim = S .shape [0 ]
139145 V = np .linalg .inv (V_inv )
140- A = np .sqrt (np .diag (np .repeat (intrinsic_emittances (S ), 2 )))
146+ A = np .eye (ndim )
147+ if ndim == 2 :
148+ emittance = np .sqrt (np .linalg .det (S ))
149+ A = np .diag (np .sqrt ([emittance , emittance ]))
150+ else :
151+ A = np .sqrt (np .diag (np .repeat (intrinsic_emittances (S ), 2 )))
141152 V = np .matmul (V , A )
142153 V_inv = np .linalg .inv (V )
143154
0 commit comments