From fea6debdaf127764e614795ff47616e29ac24444 Mon Sep 17 00:00:00 2001
From: fjosw
Date: Tue, 20 Dec 2022 16:11:23 +0000
Subject: [PATCH] Documentation updated
---
docs/pyerrors/correlators.html | 6499 ++++++++++++++++----------------
1 file changed, 3245 insertions(+), 3254 deletions(-)
diff --git a/docs/pyerrors/correlators.html b/docs/pyerrors/correlators.html
index a02c18ba..f4a2c4c3 100644
--- a/docs/pyerrors/correlators.html
+++ b/docs/pyerrors/correlators.html
@@ -282,1248 +282,1245 @@
69
70 if isinstance(data_input, list):
71
- 72 if all([isinstance(item, (Obs, CObs)) for item in data_input]):
- 73 _assert_equal_properties(data_input)
- 74 self.content = [np.asarray([item]) for item in data_input]
- 75 if all([isinstance(item, (Obs, CObs)) or item is None for item in data_input]):
- 76 _assert_equal_properties([o for o in data_input if o is not None])
- 77 self.content = [np.asarray([item]) if item is not None else None for item in data_input]
- 78 self.N = 1
- 79
- 80 elif all([isinstance(item, np.ndarray) or item is None for item in data_input]) and any([isinstance(item, np.ndarray) for item in data_input]):
- 81 self.content = data_input
- 82 noNull = [a for a in self.content if not (a is None)] # To check if the matrices are correct for all undefined elements
- 83 self.N = noNull[0].shape[0]
- 84 if self.N > 1 and noNull[0].shape[0] != noNull[0].shape[1]:
- 85 raise Exception("Smearing matrices are not NxN")
- 86 if (not all([item.shape == noNull[0].shape for item in noNull])):
- 87 raise Exception("Items in data_input are not of identical shape." + str(noNull))
- 88 else:
- 89 raise Exception("data_input contains item of wrong type")
- 90 else:
- 91 raise Exception("Data input was not given as list or correct array")
- 92
- 93 self.tag = None
- 94
- 95 # An undefined timeslice is represented by the None object
- 96 self.content = [None] * padding[0] + self.content + [None] * padding[1]
- 97 self.T = len(self.content)
- 98 self.prange = prange
- 99
- 100 def __getitem__(self, idx):
- 101 """Return the content of timeslice idx"""
- 102 if self.content[idx] is None:
- 103 return None
- 104 elif len(self.content[idx]) == 1:
- 105 return self.content[idx][0]
- 106 else:
- 107 return self.content[idx]
- 108
- 109 @property
- 110 def reweighted(self):
- 111 bool_array = np.array([list(map(lambda x: x.reweighted, o)) for o in [x for x in self.content if x is not None]])
- 112 if np.all(bool_array == 1):
- 113 return True
- 114 elif np.all(bool_array == 0):
- 115 return False
- 116 else:
- 117 raise Exception("Reweighting status of correlator corrupted.")
- 118
- 119 def gamma_method(self, **kwargs):
- 120 """Apply the gamma method to the content of the Corr."""
- 121 for item in self.content:
- 122 if not (item is None):
- 123 if self.N == 1:
- 124 item[0].gamma_method(**kwargs)
- 125 else:
- 126 for i in range(self.N):
- 127 for j in range(self.N):
- 128 item[i, j].gamma_method(**kwargs)
+ 72 if all([isinstance(item, (Obs, CObs)) or item is None for item in data_input]):
+ 73 _assert_equal_properties([o for o in data_input if o is not None])
+ 74 self.content = [np.asarray([item]) if item is not None else None for item in data_input]
+ 75 self.N = 1
+ 76
+ 77 elif all([isinstance(item, np.ndarray) or item is None for item in data_input]) and any([isinstance(item, np.ndarray) for item in data_input]):
+ 78 self.content = data_input
+ 79 noNull = [a for a in self.content if not (a is None)] # To check if the matrices are correct for all undefined elements
+ 80 self.N = noNull[0].shape[0]
+ 81 if self.N > 1 and noNull[0].shape[0] != noNull[0].shape[1]:
+ 82 raise Exception("Smearing matrices are not NxN")
+ 83 if (not all([item.shape == noNull[0].shape for item in noNull])):
+ 84 raise Exception("Items in data_input are not of identical shape." + str(noNull))
+ 85 else:
+ 86 raise Exception("data_input contains item of wrong type")
+ 87 else:
+ 88 raise Exception("Data input was not given as list or correct array")
+ 89
+ 90 self.tag = None
+ 91
+ 92 # An undefined timeslice is represented by the None object
+ 93 self.content = [None] * padding[0] + self.content + [None] * padding[1]
+ 94 self.T = len(self.content)
+ 95 self.prange = prange
+ 96
+ 97 def __getitem__(self, idx):
+ 98 """Return the content of timeslice idx"""
+ 99 if self.content[idx] is None:
+ 100 return None
+ 101 elif len(self.content[idx]) == 1:
+ 102 return self.content[idx][0]
+ 103 else:
+ 104 return self.content[idx]
+ 105
+ 106 @property
+ 107 def reweighted(self):
+ 108 bool_array = np.array([list(map(lambda x: x.reweighted, o)) for o in [x for x in self.content if x is not None]])
+ 109 if np.all(bool_array == 1):
+ 110 return True
+ 111 elif np.all(bool_array == 0):
+ 112 return False
+ 113 else:
+ 114 raise Exception("Reweighting status of correlator corrupted.")
+ 115
+ 116 def gamma_method(self, **kwargs):
+ 117 """Apply the gamma method to the content of the Corr."""
+ 118 for item in self.content:
+ 119 if not (item is None):
+ 120 if self.N == 1:
+ 121 item[0].gamma_method(**kwargs)
+ 122 else:
+ 123 for i in range(self.N):
+ 124 for j in range(self.N):
+ 125 item[i, j].gamma_method(**kwargs)
+ 126
+ 127 def projected(self, vector_l=None, vector_r=None, normalize=False):
+ 128 """We need to project the Correlator with a Vector to get a single value at each timeslice.
129
- 130 def projected(self, vector_l=None, vector_r=None, normalize=False):
- 131 """We need to project the Correlator with a Vector to get a single value at each timeslice.
- 132
- 133 The method can use one or two vectors.
- 134 If two are specified it returns v1@G@v2 (the order might be very important.)
- 135 By default it will return the lowest source, which usually means unsmeared-unsmeared (0,0), but it does not have to
- 136 """
- 137 if self.N == 1:
- 138 raise Exception("Trying to project a Corr, that already has N=1.")
- 139
- 140 if vector_l is None:
- 141 vector_l, vector_r = np.asarray([1.] + (self.N - 1) * [0.]), np.asarray([1.] + (self.N - 1) * [0.])
- 142 elif (vector_r is None):
- 143 vector_r = vector_l
- 144 if isinstance(vector_l, list) and not isinstance(vector_r, list):
- 145 if len(vector_l) != self.T:
- 146 raise Exception("Length of vector list must be equal to T")
- 147 vector_r = [vector_r] * self.T
- 148 if isinstance(vector_r, list) and not isinstance(vector_l, list):
- 149 if len(vector_r) != self.T:
- 150 raise Exception("Length of vector list must be equal to T")
- 151 vector_l = [vector_l] * self.T
- 152
- 153 if not isinstance(vector_l, list):
- 154 if not vector_l.shape == vector_r.shape == (self.N,):
- 155 raise Exception("Vectors are of wrong shape!")
- 156 if normalize:
- 157 vector_l, vector_r = vector_l / np.sqrt((vector_l @ vector_l)), vector_r / np.sqrt(vector_r @ vector_r)
- 158 newcontent = [None if _check_for_none(self, item) else np.asarray([vector_l.T @ item @ vector_r]) for item in self.content]
- 159
- 160 else:
- 161 # There are no checks here yet. There are so many possible scenarios, where this can go wrong.
- 162 if normalize:
- 163 for t in range(self.T):
- 164 vector_l[t], vector_r[t] = vector_l[t] / np.sqrt((vector_l[t] @ vector_l[t])), vector_r[t] / np.sqrt(vector_r[t] @ vector_r[t])
+ 130 The method can use one or two vectors.
+ 131 If two are specified it returns v1@G@v2 (the order might be very important.)
+ 132 By default it will return the lowest source, which usually means unsmeared-unsmeared (0,0), but it does not have to
+ 133 """
+ 134 if self.N == 1:
+ 135 raise Exception("Trying to project a Corr, that already has N=1.")
+ 136
+ 137 if vector_l is None:
+ 138 vector_l, vector_r = np.asarray([1.] + (self.N - 1) * [0.]), np.asarray([1.] + (self.N - 1) * [0.])
+ 139 elif (vector_r is None):
+ 140 vector_r = vector_l
+ 141 if isinstance(vector_l, list) and not isinstance(vector_r, list):
+ 142 if len(vector_l) != self.T:
+ 143 raise Exception("Length of vector list must be equal to T")
+ 144 vector_r = [vector_r] * self.T
+ 145 if isinstance(vector_r, list) and not isinstance(vector_l, list):
+ 146 if len(vector_r) != self.T:
+ 147 raise Exception("Length of vector list must be equal to T")
+ 148 vector_l = [vector_l] * self.T
+ 149
+ 150 if not isinstance(vector_l, list):
+ 151 if not vector_l.shape == vector_r.shape == (self.N,):
+ 152 raise Exception("Vectors are of wrong shape!")
+ 153 if normalize:
+ 154 vector_l, vector_r = vector_l / np.sqrt((vector_l @ vector_l)), vector_r / np.sqrt(vector_r @ vector_r)
+ 155 newcontent = [None if _check_for_none(self, item) else np.asarray([vector_l.T @ item @ vector_r]) for item in self.content]
+ 156
+ 157 else:
+ 158 # There are no checks here yet. There are so many possible scenarios, where this can go wrong.
+ 159 if normalize:
+ 160 for t in range(self.T):
+ 161 vector_l[t], vector_r[t] = vector_l[t] / np.sqrt((vector_l[t] @ vector_l[t])), vector_r[t] / np.sqrt(vector_r[t] @ vector_r[t])
+ 162
+ 163 newcontent = [None if (_check_for_none(self, self.content[t]) or vector_l[t] is None or vector_r[t] is None) else np.asarray([vector_l[t].T @ self.content[t] @ vector_r[t]]) for t in range(self.T)]
+ 164 return Corr(newcontent)
165
- 166 newcontent = [None if (_check_for_none(self, self.content[t]) or vector_l[t] is None or vector_r[t] is None) else np.asarray([vector_l[t].T @ self.content[t] @ vector_r[t]]) for t in range(self.T)]
- 167 return Corr(newcontent)
+ 166 def item(self, i, j):
+ 167 """Picks the element [i,j] from every matrix and returns a correlator containing one Obs per timeslice.
168
- 169 def item(self, i, j):
- 170 """Picks the element [i,j] from every matrix and returns a correlator containing one Obs per timeslice.
- 171
- 172 Parameters
- 173 ----------
- 174 i : int
- 175 First index to be picked.
- 176 j : int
- 177 Second index to be picked.
- 178 """
- 179 if self.N == 1:
- 180 raise Exception("Trying to pick item from projected Corr")
- 181 newcontent = [None if (item is None) else item[i, j] for item in self.content]
- 182 return Corr(newcontent)
+ 169 Parameters
+ 170 ----------
+ 171 i : int
+ 172 First index to be picked.
+ 173 j : int
+ 174 Second index to be picked.
+ 175 """
+ 176 if self.N == 1:
+ 177 raise Exception("Trying to pick item from projected Corr")
+ 178 newcontent = [None if (item is None) else item[i, j] for item in self.content]
+ 179 return Corr(newcontent)
+ 180
+ 181 def plottable(self):
+ 182 """Outputs the correlator in a plotable format.
183
- 184 def plottable(self):
- 185 """Outputs the correlator in a plotable format.
- 186
- 187 Outputs three lists containing the timeslice index, the value on each
- 188 timeslice and the error on each timeslice.
- 189 """
- 190 if self.N != 1:
- 191 raise Exception("Can only make Corr[N=1] plottable")
- 192 x_list = [x for x in range(self.T) if not self.content[x] is None]
- 193 y_list = [y[0].value for y in self.content if y is not None]
- 194 y_err_list = [y[0].dvalue for y in self.content if y is not None]
- 195
- 196 return x_list, y_list, y_err_list
- 197
- 198 def symmetric(self):
- 199 """ Symmetrize the correlator around x0=0."""
- 200 if self.N != 1:
- 201 raise Exception('symmetric cannot be safely applied to multi-dimensional correlators.')
- 202 if self.T % 2 != 0:
- 203 raise Exception("Can not symmetrize odd T")
+ 184 Outputs three lists containing the timeslice index, the value on each
+ 185 timeslice and the error on each timeslice.
+ 186 """
+ 187 if self.N != 1:
+ 188 raise Exception("Can only make Corr[N=1] plottable")
+ 189 x_list = [x for x in range(self.T) if not self.content[x] is None]
+ 190 y_list = [y[0].value for y in self.content if y is not None]
+ 191 y_err_list = [y[0].dvalue for y in self.content if y is not None]
+ 192
+ 193 return x_list, y_list, y_err_list
+ 194
+ 195 def symmetric(self):
+ 196 """ Symmetrize the correlator around x0=0."""
+ 197 if self.N != 1:
+ 198 raise Exception('symmetric cannot be safely applied to multi-dimensional correlators.')
+ 199 if self.T % 2 != 0:
+ 200 raise Exception("Can not symmetrize odd T")
+ 201
+ 202 if np.argmax(np.abs(self.content)) != 0:
+ 203 warnings.warn("Correlator does not seem to be symmetric around x0=0.", RuntimeWarning)
204
- 205 if np.argmax(np.abs(self.content)) != 0:
- 206 warnings.warn("Correlator does not seem to be symmetric around x0=0.", RuntimeWarning)
- 207
- 208 newcontent = [self.content[0]]
- 209 for t in range(1, self.T):
- 210 if (self.content[t] is None) or (self.content[self.T - t] is None):
- 211 newcontent.append(None)
- 212 else:
- 213 newcontent.append(0.5 * (self.content[t] + self.content[self.T - t]))
- 214 if (all([x is None for x in newcontent])):
- 215 raise Exception("Corr could not be symmetrized: No redundant values")
- 216 return Corr(newcontent, prange=self.prange)
- 217
- 218 def anti_symmetric(self):
- 219 """Anti-symmetrize the correlator around x0=0."""
- 220 if self.N != 1:
- 221 raise Exception('anti_symmetric cannot be safely applied to multi-dimensional correlators.')
- 222 if self.T % 2 != 0:
- 223 raise Exception("Can not symmetrize odd T")
- 224
- 225 test = 1 * self
- 226 test.gamma_method()
- 227 if not all([o.is_zero_within_error(3) for o in test.content[0]]):
- 228 warnings.warn("Correlator does not seem to be anti-symmetric around x0=0.", RuntimeWarning)
- 229
- 230 newcontent = [self.content[0]]
- 231 for t in range(1, self.T):
- 232 if (self.content[t] is None) or (self.content[self.T - t] is None):
- 233 newcontent.append(None)
- 234 else:
- 235 newcontent.append(0.5 * (self.content[t] - self.content[self.T - t]))
- 236 if (all([x is None for x in newcontent])):
- 237 raise Exception("Corr could not be symmetrized: No redundant values")
- 238 return Corr(newcontent, prange=self.prange)
- 239
- 240 def is_matrix_symmetric(self):
- 241 """Checks whether a correlator matrices is symmetric on every timeslice."""
- 242 if self.N == 1:
- 243 raise Exception("Only works for correlator matrices.")
- 244 for t in range(self.T):
- 245 if self[t] is None:
- 246 continue
- 247 for i in range(self.N):
- 248 for j in range(i + 1, self.N):
- 249 if self[t][i, j] is self[t][j, i]:
- 250 continue
- 251 if hash(self[t][i, j]) != hash(self[t][j, i]):
- 252 return False
- 253 return True
- 254
- 255 def matrix_symmetric(self):
- 256 """Symmetrizes the correlator matrices on every timeslice."""
- 257 if self.N == 1:
- 258 raise Exception("Trying to symmetrize a correlator matrix, that already has N=1.")
- 259 if self.is_matrix_symmetric():
- 260 return 1.0 * self
- 261 else:
- 262 transposed = [None if _check_for_none(self, G) else G.T for G in self.content]
- 263 return 0.5 * (Corr(transposed) + self)
+ 205 newcontent = [self.content[0]]
+ 206 for t in range(1, self.T):
+ 207 if (self.content[t] is None) or (self.content[self.T - t] is None):
+ 208 newcontent.append(None)
+ 209 else:
+ 210 newcontent.append(0.5 * (self.content[t] + self.content[self.T - t]))
+ 211 if (all([x is None for x in newcontent])):
+ 212 raise Exception("Corr could not be symmetrized: No redundant values")
+ 213 return Corr(newcontent, prange=self.prange)
+ 214
+ 215 def anti_symmetric(self):
+ 216 """Anti-symmetrize the correlator around x0=0."""
+ 217 if self.N != 1:
+ 218 raise Exception('anti_symmetric cannot be safely applied to multi-dimensional correlators.')
+ 219 if self.T % 2 != 0:
+ 220 raise Exception("Can not symmetrize odd T")
+ 221
+ 222 test = 1 * self
+ 223 test.gamma_method()
+ 224 if not all([o.is_zero_within_error(3) for o in test.content[0]]):
+ 225 warnings.warn("Correlator does not seem to be anti-symmetric around x0=0.", RuntimeWarning)
+ 226
+ 227 newcontent = [self.content[0]]
+ 228 for t in range(1, self.T):
+ 229 if (self.content[t] is None) or (self.content[self.T - t] is None):
+ 230 newcontent.append(None)
+ 231 else:
+ 232 newcontent.append(0.5 * (self.content[t] - self.content[self.T - t]))
+ 233 if (all([x is None for x in newcontent])):
+ 234 raise Exception("Corr could not be symmetrized: No redundant values")
+ 235 return Corr(newcontent, prange=self.prange)
+ 236
+ 237 def is_matrix_symmetric(self):
+ 238 """Checks whether a correlator matrices is symmetric on every timeslice."""
+ 239 if self.N == 1:
+ 240 raise Exception("Only works for correlator matrices.")
+ 241 for t in range(self.T):
+ 242 if self[t] is None:
+ 243 continue
+ 244 for i in range(self.N):
+ 245 for j in range(i + 1, self.N):
+ 246 if self[t][i, j] is self[t][j, i]:
+ 247 continue
+ 248 if hash(self[t][i, j]) != hash(self[t][j, i]):
+ 249 return False
+ 250 return True
+ 251
+ 252 def matrix_symmetric(self):
+ 253 """Symmetrizes the correlator matrices on every timeslice."""
+ 254 if self.N == 1:
+ 255 raise Exception("Trying to symmetrize a correlator matrix, that already has N=1.")
+ 256 if self.is_matrix_symmetric():
+ 257 return 1.0 * self
+ 258 else:
+ 259 transposed = [None if _check_for_none(self, G) else G.T for G in self.content]
+ 260 return 0.5 * (Corr(transposed) + self)
+ 261
+ 262 def GEVP(self, t0, ts=None, sort="Eigenvalue", **kwargs):
+ 263 r'''Solve the generalized eigenvalue problem on the correlator matrix and returns the corresponding eigenvectors.
264
- 265 def GEVP(self, t0, ts=None, sort="Eigenvalue", **kwargs):
- 266 r'''Solve the generalized eigenvalue problem on the correlator matrix and returns the corresponding eigenvectors.
- 267
- 268 The eigenvectors are sorted according to the descending eigenvalues, the zeroth eigenvector(s) correspond to the
- 269 largest eigenvalue(s). The eigenvector(s) for the individual states can be accessed via slicing
- 270 ```python
- 271 C.GEVP(t0=2)[0] # Ground state vector(s)
- 272 C.GEVP(t0=2)[:3] # Vectors for the lowest three states
- 273 ```
- 274
- 275 Parameters
- 276 ----------
- 277 t0 : int
- 278 The time t0 for the right hand side of the GEVP according to $G(t)v_i=\lambda_i G(t_0)v_i$
- 279 ts : int
- 280 fixed time $G(t_s)v_i=\lambda_i G(t_0)v_i$ if sort=None.
- 281 If sort="Eigenvector" it gives a reference point for the sorting method.
- 282 sort : string
- 283 If this argument is set, a list of self.T vectors per state is returned. If it is set to None, only one vector is returned.
- 284 - "Eigenvalue": The eigenvector is chosen according to which eigenvalue it belongs individually on every timeslice.
- 285 - "Eigenvector": Use the method described in arXiv:2004.10472 to find the set of v(t) belonging to the state.
- 286 The reference state is identified by its eigenvalue at $t=t_s$.
- 287
- 288 Other Parameters
- 289 ----------------
- 290 state : int
- 291 Returns only the vector(s) for a specified state. The lowest state is zero.
- 292 '''
- 293
- 294 if self.N == 1:
- 295 raise Exception("GEVP methods only works on correlator matrices and not single correlators.")
- 296 if ts is not None:
- 297 if (ts <= t0):
- 298 raise Exception("ts has to be larger than t0.")
- 299
- 300 if "sorted_list" in kwargs:
- 301 warnings.warn("Argument 'sorted_list' is deprecated, use 'sort' instead.", DeprecationWarning)
- 302 sort = kwargs.get("sorted_list")
- 303
- 304 if self.is_matrix_symmetric():
- 305 symmetric_corr = self
- 306 else:
- 307 symmetric_corr = self.matrix_symmetric()
+ 265 The eigenvectors are sorted according to the descending eigenvalues, the zeroth eigenvector(s) correspond to the
+ 266 largest eigenvalue(s). The eigenvector(s) for the individual states can be accessed via slicing
+ 267 ```python
+ 268 C.GEVP(t0=2)[0] # Ground state vector(s)
+ 269 C.GEVP(t0=2)[:3] # Vectors for the lowest three states
+ 270 ```
+ 271
+ 272 Parameters
+ 273 ----------
+ 274 t0 : int
+ 275 The time t0 for the right hand side of the GEVP according to $G(t)v_i=\lambda_i G(t_0)v_i$
+ 276 ts : int
+ 277 fixed time $G(t_s)v_i=\lambda_i G(t_0)v_i$ if sort=None.
+ 278 If sort="Eigenvector" it gives a reference point for the sorting method.
+ 279 sort : string
+ 280 If this argument is set, a list of self.T vectors per state is returned. If it is set to None, only one vector is returned.
+ 281 - "Eigenvalue": The eigenvector is chosen according to which eigenvalue it belongs individually on every timeslice.
+ 282 - "Eigenvector": Use the method described in arXiv:2004.10472 to find the set of v(t) belonging to the state.
+ 283 The reference state is identified by its eigenvalue at $t=t_s$.
+ 284
+ 285 Other Parameters
+ 286 ----------------
+ 287 state : int
+ 288 Returns only the vector(s) for a specified state. The lowest state is zero.
+ 289 '''
+ 290
+ 291 if self.N == 1:
+ 292 raise Exception("GEVP methods only works on correlator matrices and not single correlators.")
+ 293 if ts is not None:
+ 294 if (ts <= t0):
+ 295 raise Exception("ts has to be larger than t0.")
+ 296
+ 297 if "sorted_list" in kwargs:
+ 298 warnings.warn("Argument 'sorted_list' is deprecated, use 'sort' instead.", DeprecationWarning)
+ 299 sort = kwargs.get("sorted_list")
+ 300
+ 301 if self.is_matrix_symmetric():
+ 302 symmetric_corr = self
+ 303 else:
+ 304 symmetric_corr = self.matrix_symmetric()
+ 305
+ 306 G0 = np.vectorize(lambda x: x.value)(symmetric_corr[t0])
+ 307 np.linalg.cholesky(G0) # Check if matrix G0 is positive-semidefinite.
308
- 309 G0 = np.vectorize(lambda x: x.value)(symmetric_corr[t0])
- 310 np.linalg.cholesky(G0) # Check if matrix G0 is positive-semidefinite.
- 311
- 312 if sort is None:
- 313 if (ts is None):
- 314 raise Exception("ts is required if sort=None.")
- 315 if (self.content[t0] is None) or (self.content[ts] is None):
- 316 raise Exception("Corr not defined at t0/ts.")
- 317 Gt = np.vectorize(lambda x: x.value)(symmetric_corr[ts])
- 318 reordered_vecs = _GEVP_solver(Gt, G0)
- 319
- 320 elif sort in ["Eigenvalue", "Eigenvector"]:
- 321 if sort == "Eigenvalue" and ts is not None:
- 322 warnings.warn("ts has no effect when sorting by eigenvalue is chosen.", RuntimeWarning)
- 323 all_vecs = [None] * (t0 + 1)
- 324 for t in range(t0 + 1, self.T):
- 325 try:
- 326 Gt = np.vectorize(lambda x: x.value)(symmetric_corr[t])
- 327 all_vecs.append(_GEVP_solver(Gt, G0))
- 328 except Exception:
- 329 all_vecs.append(None)
- 330 if sort == "Eigenvector":
- 331 if ts is None:
- 332 raise Exception("ts is required for the Eigenvector sorting method.")
- 333 all_vecs = _sort_vectors(all_vecs, ts)
- 334
- 335 reordered_vecs = [[v[s] if v is not None else None for v in all_vecs] for s in range(self.N)]
- 336 else:
- 337 raise Exception("Unkown value for 'sort'.")
- 338
- 339 if "state" in kwargs:
- 340 return reordered_vecs[kwargs.get("state")]
- 341 else:
- 342 return reordered_vecs
+ 309 if sort is None:
+ 310 if (ts is None):
+ 311 raise Exception("ts is required if sort=None.")
+ 312 if (self.content[t0] is None) or (self.content[ts] is None):
+ 313 raise Exception("Corr not defined at t0/ts.")
+ 314 Gt = np.vectorize(lambda x: x.value)(symmetric_corr[ts])
+ 315 reordered_vecs = _GEVP_solver(Gt, G0)
+ 316
+ 317 elif sort in ["Eigenvalue", "Eigenvector"]:
+ 318 if sort == "Eigenvalue" and ts is not None:
+ 319 warnings.warn("ts has no effect when sorting by eigenvalue is chosen.", RuntimeWarning)
+ 320 all_vecs = [None] * (t0 + 1)
+ 321 for t in range(t0 + 1, self.T):
+ 322 try:
+ 323 Gt = np.vectorize(lambda x: x.value)(symmetric_corr[t])
+ 324 all_vecs.append(_GEVP_solver(Gt, G0))
+ 325 except Exception:
+ 326 all_vecs.append(None)
+ 327 if sort == "Eigenvector":
+ 328 if ts is None:
+ 329 raise Exception("ts is required for the Eigenvector sorting method.")
+ 330 all_vecs = _sort_vectors(all_vecs, ts)
+ 331
+ 332 reordered_vecs = [[v[s] if v is not None else None for v in all_vecs] for s in range(self.N)]
+ 333 else:
+ 334 raise Exception("Unkown value for 'sort'.")
+ 335
+ 336 if "state" in kwargs:
+ 337 return reordered_vecs[kwargs.get("state")]
+ 338 else:
+ 339 return reordered_vecs
+ 340
+ 341 def Eigenvalue(self, t0, ts=None, state=0, sort="Eigenvalue"):
+ 342 """Determines the eigenvalue of the GEVP by solving and projecting the correlator
343
- 344 def Eigenvalue(self, t0, ts=None, state=0, sort="Eigenvalue"):
- 345 """Determines the eigenvalue of the GEVP by solving and projecting the correlator
- 346
- 347 Parameters
- 348 ----------
- 349 state : int
- 350 The state one is interested in ordered by energy. The lowest state is zero.
- 351
- 352 All other parameters are identical to the ones of Corr.GEVP.
- 353 """
- 354 vec = self.GEVP(t0, ts=ts, sort=sort)[state]
- 355 return self.projected(vec)
+ 344 Parameters
+ 345 ----------
+ 346 state : int
+ 347 The state one is interested in ordered by energy. The lowest state is zero.
+ 348
+ 349 All other parameters are identical to the ones of Corr.GEVP.
+ 350 """
+ 351 vec = self.GEVP(t0, ts=ts, sort=sort)[state]
+ 352 return self.projected(vec)
+ 353
+ 354 def Hankel(self, N, periodic=False):
+ 355 """Constructs an NxN Hankel matrix
356
- 357 def Hankel(self, N, periodic=False):
- 358 """Constructs an NxN Hankel matrix
- 359
- 360 C(t) c(t+1) ... c(t+n-1)
- 361 C(t+1) c(t+2) ... c(t+n)
- 362 .................
- 363 C(t+(n-1)) c(t+n) ... c(t+2(n-1))
- 364
- 365 Parameters
- 366 ----------
- 367 N : int
- 368 Dimension of the Hankel matrix
- 369 periodic : bool, optional
- 370 determines whether the matrix is extended periodically
- 371 """
+ 357 C(t) c(t+1) ... c(t+n-1)
+ 358 C(t+1) c(t+2) ... c(t+n)
+ 359 .................
+ 360 C(t+(n-1)) c(t+n) ... c(t+2(n-1))
+ 361
+ 362 Parameters
+ 363 ----------
+ 364 N : int
+ 365 Dimension of the Hankel matrix
+ 366 periodic : bool, optional
+ 367 determines whether the matrix is extended periodically
+ 368 """
+ 369
+ 370 if self.N != 1:
+ 371 raise Exception("Multi-operator Prony not implemented!")
372
- 373 if self.N != 1:
- 374 raise Exception("Multi-operator Prony not implemented!")
- 375
- 376 array = np.empty([N, N], dtype="object")
- 377 new_content = []
- 378 for t in range(self.T):
- 379 new_content.append(array.copy())
- 380
- 381 def wrap(i):
- 382 while i >= self.T:
- 383 i -= self.T
- 384 return i
- 385
- 386 for t in range(self.T):
- 387 for i in range(N):
- 388 for j in range(N):
- 389 if periodic:
- 390 new_content[t][i, j] = self.content[wrap(t + i + j)][0]
- 391 elif (t + i + j) >= self.T:
- 392 new_content[t] = None
- 393 else:
- 394 new_content[t][i, j] = self.content[t + i + j][0]
- 395
- 396 return Corr(new_content)
+ 373 array = np.empty([N, N], dtype="object")
+ 374 new_content = []
+ 375 for t in range(self.T):
+ 376 new_content.append(array.copy())
+ 377
+ 378 def wrap(i):
+ 379 while i >= self.T:
+ 380 i -= self.T
+ 381 return i
+ 382
+ 383 for t in range(self.T):
+ 384 for i in range(N):
+ 385 for j in range(N):
+ 386 if periodic:
+ 387 new_content[t][i, j] = self.content[wrap(t + i + j)][0]
+ 388 elif (t + i + j) >= self.T:
+ 389 new_content[t] = None
+ 390 else:
+ 391 new_content[t][i, j] = self.content[t + i + j][0]
+ 392
+ 393 return Corr(new_content)
+ 394
+ 395 def roll(self, dt):
+ 396 """Periodically shift the correlator by dt timeslices
397
- 398 def roll(self, dt):
- 399 """Periodically shift the correlator by dt timeslices
- 400
- 401 Parameters
- 402 ----------
- 403 dt : int
- 404 number of timeslices
- 405 """
- 406 return Corr(list(np.roll(np.array(self.content, dtype=object), dt)))
- 407
- 408 def reverse(self):
- 409 """Reverse the time ordering of the Corr"""
- 410 return Corr(self.content[:: -1])
+ 398 Parameters
+ 399 ----------
+ 400 dt : int
+ 401 number of timeslices
+ 402 """
+ 403 return Corr(list(np.roll(np.array(self.content, dtype=object), dt)))
+ 404
+ 405 def reverse(self):
+ 406 """Reverse the time ordering of the Corr"""
+ 407 return Corr(self.content[:: -1])
+ 408
+ 409 def thin(self, spacing=2, offset=0):
+ 410 """Thin out a correlator to suppress correlations
411
- 412 def thin(self, spacing=2, offset=0):
- 413 """Thin out a correlator to suppress correlations
- 414
- 415 Parameters
- 416 ----------
- 417 spacing : int
- 418 Keep only every 'spacing'th entry of the correlator
- 419 offset : int
- 420 Offset the equal spacing
- 421 """
- 422 new_content = []
- 423 for t in range(self.T):
- 424 if (offset + t) % spacing != 0:
- 425 new_content.append(None)
- 426 else:
- 427 new_content.append(self.content[t])
- 428 return Corr(new_content)
+ 412 Parameters
+ 413 ----------
+ 414 spacing : int
+ 415 Keep only every 'spacing'th entry of the correlator
+ 416 offset : int
+ 417 Offset the equal spacing
+ 418 """
+ 419 new_content = []
+ 420 for t in range(self.T):
+ 421 if (offset + t) % spacing != 0:
+ 422 new_content.append(None)
+ 423 else:
+ 424 new_content.append(self.content[t])
+ 425 return Corr(new_content)
+ 426
+ 427 def correlate(self, partner):
+ 428 """Correlate the correlator with another correlator or Obs
429
- 430 def correlate(self, partner):
- 431 """Correlate the correlator with another correlator or Obs
- 432
- 433 Parameters
- 434 ----------
- 435 partner : Obs or Corr
- 436 partner to correlate the correlator with.
- 437 Can either be an Obs which is correlated with all entries of the
- 438 correlator or a Corr of same length.
- 439 """
- 440 if self.N != 1:
- 441 raise Exception("Only one-dimensional correlators can be safely correlated.")
- 442 new_content = []
- 443 for x0, t_slice in enumerate(self.content):
- 444 if _check_for_none(self, t_slice):
- 445 new_content.append(None)
- 446 else:
- 447 if isinstance(partner, Corr):
- 448 if _check_for_none(partner, partner.content[x0]):
- 449 new_content.append(None)
- 450 else:
- 451 new_content.append(np.array([correlate(o, partner.content[x0][0]) for o in t_slice]))
- 452 elif isinstance(partner, Obs): # Should this include CObs?
- 453 new_content.append(np.array([correlate(o, partner) for o in t_slice]))
- 454 else:
- 455 raise Exception("Can only correlate with an Obs or a Corr.")
- 456
- 457 return Corr(new_content)
+ 430 Parameters
+ 431 ----------
+ 432 partner : Obs or Corr
+ 433 partner to correlate the correlator with.
+ 434 Can either be an Obs which is correlated with all entries of the
+ 435 correlator or a Corr of same length.
+ 436 """
+ 437 if self.N != 1:
+ 438 raise Exception("Only one-dimensional correlators can be safely correlated.")
+ 439 new_content = []
+ 440 for x0, t_slice in enumerate(self.content):
+ 441 if _check_for_none(self, t_slice):
+ 442 new_content.append(None)
+ 443 else:
+ 444 if isinstance(partner, Corr):
+ 445 if _check_for_none(partner, partner.content[x0]):
+ 446 new_content.append(None)
+ 447 else:
+ 448 new_content.append(np.array([correlate(o, partner.content[x0][0]) for o in t_slice]))
+ 449 elif isinstance(partner, Obs): # Should this include CObs?
+ 450 new_content.append(np.array([correlate(o, partner) for o in t_slice]))
+ 451 else:
+ 452 raise Exception("Can only correlate with an Obs or a Corr.")
+ 453
+ 454 return Corr(new_content)
+ 455
+ 456 def reweight(self, weight, **kwargs):
+ 457 """Reweight the correlator.
458
- 459 def reweight(self, weight, **kwargs):
- 460 """Reweight the correlator.
- 461
- 462 Parameters
- 463 ----------
- 464 weight : Obs
- 465 Reweighting factor. An Observable that has to be defined on a superset of the
- 466 configurations in obs[i].idl for all i.
- 467 all_configs : bool
- 468 if True, the reweighted observables are normalized by the average of
- 469 the reweighting factor on all configurations in weight.idl and not
- 470 on the configurations in obs[i].idl.
- 471 """
- 472 if self.N != 1:
- 473 raise Exception("Reweighting only implemented for one-dimensional correlators.")
- 474 new_content = []
- 475 for t_slice in self.content:
- 476 if _check_for_none(self, t_slice):
- 477 new_content.append(None)
- 478 else:
- 479 new_content.append(np.array(reweight(weight, t_slice, **kwargs)))
- 480 return Corr(new_content)
+ 459 Parameters
+ 460 ----------
+ 461 weight : Obs
+ 462 Reweighting factor. An Observable that has to be defined on a superset of the
+ 463 configurations in obs[i].idl for all i.
+ 464 all_configs : bool
+ 465 if True, the reweighted observables are normalized by the average of
+ 466 the reweighting factor on all configurations in weight.idl and not
+ 467 on the configurations in obs[i].idl.
+ 468 """
+ 469 if self.N != 1:
+ 470 raise Exception("Reweighting only implemented for one-dimensional correlators.")
+ 471 new_content = []
+ 472 for t_slice in self.content:
+ 473 if _check_for_none(self, t_slice):
+ 474 new_content.append(None)
+ 475 else:
+ 476 new_content.append(np.array(reweight(weight, t_slice, **kwargs)))
+ 477 return Corr(new_content)
+ 478
+ 479 def T_symmetry(self, partner, parity=+1):
+ 480 """Return the time symmetry average of the correlator and its partner
481
- 482 def T_symmetry(self, partner, parity=+1):
- 483 """Return the time symmetry average of the correlator and its partner
- 484
- 485 Parameters
- 486 ----------
- 487 partner : Corr
- 488 Time symmetry partner of the Corr
- 489 partity : int
- 490 Parity quantum number of the correlator, can be +1 or -1
- 491 """
- 492 if self.N != 1:
- 493 raise Exception("T_symmetry only implemented for one-dimensional correlators.")
- 494 if not isinstance(partner, Corr):
- 495 raise Exception("T partner has to be a Corr object.")
- 496 if parity not in [+1, -1]:
- 497 raise Exception("Parity has to be +1 or -1.")
- 498 T_partner = parity * partner.reverse()
- 499
- 500 t_slices = []
- 501 test = (self - T_partner)
- 502 test.gamma_method()
- 503 for x0, t_slice in enumerate(test.content):
- 504 if t_slice is not None:
- 505 if not t_slice[0].is_zero_within_error(5):
- 506 t_slices.append(x0)
- 507 if t_slices:
- 508 warnings.warn("T symmetry partners do not agree within 5 sigma on time slices " + str(t_slices) + ".", RuntimeWarning)
- 509
- 510 return (self + T_partner) / 2
+ 482 Parameters
+ 483 ----------
+ 484 partner : Corr
+ 485 Time symmetry partner of the Corr
+ 486 partity : int
+ 487 Parity quantum number of the correlator, can be +1 or -1
+ 488 """
+ 489 if self.N != 1:
+ 490 raise Exception("T_symmetry only implemented for one-dimensional correlators.")
+ 491 if not isinstance(partner, Corr):
+ 492 raise Exception("T partner has to be a Corr object.")
+ 493 if parity not in [+1, -1]:
+ 494 raise Exception("Parity has to be +1 or -1.")
+ 495 T_partner = parity * partner.reverse()
+ 496
+ 497 t_slices = []
+ 498 test = (self - T_partner)
+ 499 test.gamma_method()
+ 500 for x0, t_slice in enumerate(test.content):
+ 501 if t_slice is not None:
+ 502 if not t_slice[0].is_zero_within_error(5):
+ 503 t_slices.append(x0)
+ 504 if t_slices:
+ 505 warnings.warn("T symmetry partners do not agree within 5 sigma on time slices " + str(t_slices) + ".", RuntimeWarning)
+ 506
+ 507 return (self + T_partner) / 2
+ 508
+ 509 def deriv(self, variant="symmetric"):
+ 510 """Return the first derivative of the correlator with respect to x0.
511
- 512 def deriv(self, variant="symmetric"):
- 513 """Return the first derivative of the correlator with respect to x0.
- 514
- 515 Parameters
- 516 ----------
- 517 variant : str
- 518 decides which definition of the finite differences derivative is used.
- 519 Available choice: symmetric, forward, backward, improved, log, default: symmetric
- 520 """
- 521 if self.N != 1:
- 522 raise Exception("deriv only implemented for one-dimensional correlators.")
- 523 if variant == "symmetric":
- 524 newcontent = []
- 525 for t in range(1, self.T - 1):
- 526 if (self.content[t - 1] is None) or (self.content[t + 1] is None):
- 527 newcontent.append(None)
- 528 else:
- 529 newcontent.append(0.5 * (self.content[t + 1] - self.content[t - 1]))
- 530 if (all([x is None for x in newcontent])):
- 531 raise Exception('Derivative is undefined at all timeslices')
- 532 return Corr(newcontent, padding=[1, 1])
- 533 elif variant == "forward":
- 534 newcontent = []
- 535 for t in range(self.T - 1):
- 536 if (self.content[t] is None) or (self.content[t + 1] is None):
- 537 newcontent.append(None)
- 538 else:
- 539 newcontent.append(self.content[t + 1] - self.content[t])
- 540 if (all([x is None for x in newcontent])):
- 541 raise Exception("Derivative is undefined at all timeslices")
- 542 return Corr(newcontent, padding=[0, 1])
- 543 elif variant == "backward":
- 544 newcontent = []
- 545 for t in range(1, self.T):
- 546 if (self.content[t - 1] is None) or (self.content[t] is None):
- 547 newcontent.append(None)
- 548 else:
- 549 newcontent.append(self.content[t] - self.content[t - 1])
- 550 if (all([x is None for x in newcontent])):
- 551 raise Exception("Derivative is undefined at all timeslices")
- 552 return Corr(newcontent, padding=[1, 0])
- 553 elif variant == "improved":
- 554 newcontent = []
- 555 for t in range(2, self.T - 2):
- 556 if (self.content[t - 2] is None) or (self.content[t - 1] is None) or (self.content[t + 1] is None) or (self.content[t + 2] is None):
- 557 newcontent.append(None)
- 558 else:
- 559 newcontent.append((1 / 12) * (self.content[t - 2] - 8 * self.content[t - 1] + 8 * self.content[t + 1] - self.content[t + 2]))
- 560 if (all([x is None for x in newcontent])):
- 561 raise Exception('Derivative is undefined at all timeslices')
- 562 return Corr(newcontent, padding=[2, 2])
- 563 elif variant == 'log':
- 564 newcontent = []
- 565 for t in range(self.T):
- 566 if (self.content[t] is None) or (self.content[t] <= 0):
- 567 newcontent.append(None)
- 568 else:
- 569 newcontent.append(np.log(self.content[t]))
- 570 if (all([x is None for x in newcontent])):
- 571 raise Exception("Log is undefined at all timeslices")
- 572 logcorr = Corr(newcontent)
- 573 return self * logcorr.deriv('symmetric')
- 574 else:
- 575 raise Exception("Unknown variant.")
+ 512 Parameters
+ 513 ----------
+ 514 variant : str
+ 515 decides which definition of the finite differences derivative is used.
+ 516 Available choice: symmetric, forward, backward, improved, log, default: symmetric
+ 517 """
+ 518 if self.N != 1:
+ 519 raise Exception("deriv only implemented for one-dimensional correlators.")
+ 520 if variant == "symmetric":
+ 521 newcontent = []
+ 522 for t in range(1, self.T - 1):
+ 523 if (self.content[t - 1] is None) or (self.content[t + 1] is None):
+ 524 newcontent.append(None)
+ 525 else:
+ 526 newcontent.append(0.5 * (self.content[t + 1] - self.content[t - 1]))
+ 527 if (all([x is None for x in newcontent])):
+ 528 raise Exception('Derivative is undefined at all timeslices')
+ 529 return Corr(newcontent, padding=[1, 1])
+ 530 elif variant == "forward":
+ 531 newcontent = []
+ 532 for t in range(self.T - 1):
+ 533 if (self.content[t] is None) or (self.content[t + 1] is None):
+ 534 newcontent.append(None)
+ 535 else:
+ 536 newcontent.append(self.content[t + 1] - self.content[t])
+ 537 if (all([x is None for x in newcontent])):
+ 538 raise Exception("Derivative is undefined at all timeslices")
+ 539 return Corr(newcontent, padding=[0, 1])
+ 540 elif variant == "backward":
+ 541 newcontent = []
+ 542 for t in range(1, self.T):
+ 543 if (self.content[t - 1] is None) or (self.content[t] is None):
+ 544 newcontent.append(None)
+ 545 else:
+ 546 newcontent.append(self.content[t] - self.content[t - 1])
+ 547 if (all([x is None for x in newcontent])):
+ 548 raise Exception("Derivative is undefined at all timeslices")
+ 549 return Corr(newcontent, padding=[1, 0])
+ 550 elif variant == "improved":
+ 551 newcontent = []
+ 552 for t in range(2, self.T - 2):
+ 553 if (self.content[t - 2] is None) or (self.content[t - 1] is None) or (self.content[t + 1] is None) or (self.content[t + 2] is None):
+ 554 newcontent.append(None)
+ 555 else:
+ 556 newcontent.append((1 / 12) * (self.content[t - 2] - 8 * self.content[t - 1] + 8 * self.content[t + 1] - self.content[t + 2]))
+ 557 if (all([x is None for x in newcontent])):
+ 558 raise Exception('Derivative is undefined at all timeslices')
+ 559 return Corr(newcontent, padding=[2, 2])
+ 560 elif variant == 'log':
+ 561 newcontent = []
+ 562 for t in range(self.T):
+ 563 if (self.content[t] is None) or (self.content[t] <= 0):
+ 564 newcontent.append(None)
+ 565 else:
+ 566 newcontent.append(np.log(self.content[t]))
+ 567 if (all([x is None for x in newcontent])):
+ 568 raise Exception("Log is undefined at all timeslices")
+ 569 logcorr = Corr(newcontent)
+ 570 return self * logcorr.deriv('symmetric')
+ 571 else:
+ 572 raise Exception("Unknown variant.")
+ 573
+ 574 def second_deriv(self, variant="symmetric"):
+ 575 """Return the second derivative of the correlator with respect to x0.
576
- 577 def second_deriv(self, variant="symmetric"):
- 578 """Return the second derivative of the correlator with respect to x0.
- 579
- 580 Parameters
- 581 ----------
- 582 variant : str
- 583 decides which definition of the finite differences derivative is used.
- 584 Available choice: symmetric, improved, log, default: symmetric
- 585 """
- 586 if self.N != 1:
- 587 raise Exception("second_deriv only implemented for one-dimensional correlators.")
- 588 if variant == "symmetric":
- 589 newcontent = []
- 590 for t in range(1, self.T - 1):
- 591 if (self.content[t - 1] is None) or (self.content[t + 1] is None):
- 592 newcontent.append(None)
- 593 else:
- 594 newcontent.append((self.content[t + 1] - 2 * self.content[t] + self.content[t - 1]))
- 595 if (all([x is None for x in newcontent])):
- 596 raise Exception("Derivative is undefined at all timeslices")
- 597 return Corr(newcontent, padding=[1, 1])
- 598 elif variant == "improved":
- 599 newcontent = []
- 600 for t in range(2, self.T - 2):
- 601 if (self.content[t - 2] is None) or (self.content[t - 1] is None) or (self.content[t] is None) or (self.content[t + 1] is None) or (self.content[t + 2] is None):
- 602 newcontent.append(None)
- 603 else:
- 604 newcontent.append((1 / 12) * (-self.content[t + 2] + 16 * self.content[t + 1] - 30 * self.content[t] + 16 * self.content[t - 1] - self.content[t - 2]))
- 605 if (all([x is None for x in newcontent])):
- 606 raise Exception("Derivative is undefined at all timeslices")
- 607 return Corr(newcontent, padding=[2, 2])
- 608 elif variant == 'log':
- 609 newcontent = []
- 610 for t in range(self.T):
- 611 if (self.content[t] is None) or (self.content[t] <= 0):
- 612 newcontent.append(None)
- 613 else:
- 614 newcontent.append(np.log(self.content[t]))
- 615 if (all([x is None for x in newcontent])):
- 616 raise Exception("Log is undefined at all timeslices")
- 617 logcorr = Corr(newcontent)
- 618 return self * (logcorr.second_deriv('symmetric') + (logcorr.deriv('symmetric'))**2)
- 619 else:
- 620 raise Exception("Unknown variant.")
+ 577 Parameters
+ 578 ----------
+ 579 variant : str
+ 580 decides which definition of the finite differences derivative is used.
+ 581 Available choice: symmetric, improved, log, default: symmetric
+ 582 """
+ 583 if self.N != 1:
+ 584 raise Exception("second_deriv only implemented for one-dimensional correlators.")
+ 585 if variant == "symmetric":
+ 586 newcontent = []
+ 587 for t in range(1, self.T - 1):
+ 588 if (self.content[t - 1] is None) or (self.content[t + 1] is None):
+ 589 newcontent.append(None)
+ 590 else:
+ 591 newcontent.append((self.content[t + 1] - 2 * self.content[t] + self.content[t - 1]))
+ 592 if (all([x is None for x in newcontent])):
+ 593 raise Exception("Derivative is undefined at all timeslices")
+ 594 return Corr(newcontent, padding=[1, 1])
+ 595 elif variant == "improved":
+ 596 newcontent = []
+ 597 for t in range(2, self.T - 2):
+ 598 if (self.content[t - 2] is None) or (self.content[t - 1] is None) or (self.content[t] is None) or (self.content[t + 1] is None) or (self.content[t + 2] is None):
+ 599 newcontent.append(None)
+ 600 else:
+ 601 newcontent.append((1 / 12) * (-self.content[t + 2] + 16 * self.content[t + 1] - 30 * self.content[t] + 16 * self.content[t - 1] - self.content[t - 2]))
+ 602 if (all([x is None for x in newcontent])):
+ 603 raise Exception("Derivative is undefined at all timeslices")
+ 604 return Corr(newcontent, padding=[2, 2])
+ 605 elif variant == 'log':
+ 606 newcontent = []
+ 607 for t in range(self.T):
+ 608 if (self.content[t] is None) or (self.content[t] <= 0):
+ 609 newcontent.append(None)
+ 610 else:
+ 611 newcontent.append(np.log(self.content[t]))
+ 612 if (all([x is None for x in newcontent])):
+ 613 raise Exception("Log is undefined at all timeslices")
+ 614 logcorr = Corr(newcontent)
+ 615 return self * (logcorr.second_deriv('symmetric') + (logcorr.deriv('symmetric'))**2)
+ 616 else:
+ 617 raise Exception("Unknown variant.")
+ 618
+ 619 def m_eff(self, variant='log', guess=1.0):
+ 620 """Returns the effective mass of the correlator as correlator object
621
- 622 def m_eff(self, variant='log', guess=1.0):
- 623 """Returns the effective mass of the correlator as correlator object
- 624
- 625 Parameters
- 626 ----------
- 627 variant : str
- 628 log : uses the standard effective mass log(C(t) / C(t+1))
- 629 cosh, periodic : Use periodicitiy of the correlator by solving C(t) / C(t+1) = cosh(m * (t - T/2)) / cosh(m * (t + 1 - T/2)) for m.
- 630 sinh : Use anti-periodicitiy of the correlator by solving C(t) / C(t+1) = sinh(m * (t - T/2)) / sinh(m * (t + 1 - T/2)) for m.
- 631 See, e.g., arXiv:1205.5380
- 632 arccosh : Uses the explicit form of the symmetrized correlator (not recommended)
- 633 logsym: uses the symmetric effective mass log(C(t-1) / C(t+1))/2
- 634 guess : float
- 635 guess for the root finder, only relevant for the root variant
- 636 """
- 637 if self.N != 1:
- 638 raise Exception('Correlator must be projected before getting m_eff')
- 639 if variant == 'log':
- 640 newcontent = []
- 641 for t in range(self.T - 1):
- 642 if ((self.content[t] is None) or (self.content[t + 1] is None)) or (self.content[t + 1][0].value == 0):
- 643 newcontent.append(None)
- 644 elif self.content[t][0].value / self.content[t + 1][0].value < 0:
- 645 newcontent.append(None)
- 646 else:
- 647 newcontent.append(self.content[t] / self.content[t + 1])
- 648 if (all([x is None for x in newcontent])):
- 649 raise Exception('m_eff is undefined at all timeslices')
- 650
- 651 return np.log(Corr(newcontent, padding=[0, 1]))
- 652
- 653 elif variant == 'logsym':
- 654 newcontent = []
- 655 for t in range(1, self.T - 1):
- 656 if ((self.content[t - 1] is None) or (self.content[t + 1] is None)) or (self.content[t + 1][0].value == 0):
- 657 newcontent.append(None)
- 658 elif self.content[t - 1][0].value / self.content[t + 1][0].value < 0:
- 659 newcontent.append(None)
- 660 else:
- 661 newcontent.append(self.content[t - 1] / self.content[t + 1])
- 662 if (all([x is None for x in newcontent])):
- 663 raise Exception('m_eff is undefined at all timeslices')
- 664
- 665 return np.log(Corr(newcontent, padding=[1, 1])) / 2
- 666
- 667 elif variant in ['periodic', 'cosh', 'sinh']:
- 668 if variant in ['periodic', 'cosh']:
- 669 func = anp.cosh
- 670 else:
- 671 func = anp.sinh
+ 622 Parameters
+ 623 ----------
+ 624 variant : str
+ 625 log : uses the standard effective mass log(C(t) / C(t+1))
+ 626 cosh, periodic : Use periodicitiy of the correlator by solving C(t) / C(t+1) = cosh(m * (t - T/2)) / cosh(m * (t + 1 - T/2)) for m.
+ 627 sinh : Use anti-periodicitiy of the correlator by solving C(t) / C(t+1) = sinh(m * (t - T/2)) / sinh(m * (t + 1 - T/2)) for m.
+ 628 See, e.g., arXiv:1205.5380
+ 629 arccosh : Uses the explicit form of the symmetrized correlator (not recommended)
+ 630 logsym: uses the symmetric effective mass log(C(t-1) / C(t+1))/2
+ 631 guess : float
+ 632 guess for the root finder, only relevant for the root variant
+ 633 """
+ 634 if self.N != 1:
+ 635 raise Exception('Correlator must be projected before getting m_eff')
+ 636 if variant == 'log':
+ 637 newcontent = []
+ 638 for t in range(self.T - 1):
+ 639 if ((self.content[t] is None) or (self.content[t + 1] is None)) or (self.content[t + 1][0].value == 0):
+ 640 newcontent.append(None)
+ 641 elif self.content[t][0].value / self.content[t + 1][0].value < 0:
+ 642 newcontent.append(None)
+ 643 else:
+ 644 newcontent.append(self.content[t] / self.content[t + 1])
+ 645 if (all([x is None for x in newcontent])):
+ 646 raise Exception('m_eff is undefined at all timeslices')
+ 647
+ 648 return np.log(Corr(newcontent, padding=[0, 1]))
+ 649
+ 650 elif variant == 'logsym':
+ 651 newcontent = []
+ 652 for t in range(1, self.T - 1):
+ 653 if ((self.content[t - 1] is None) or (self.content[t + 1] is None)) or (self.content[t + 1][0].value == 0):
+ 654 newcontent.append(None)
+ 655 elif self.content[t - 1][0].value / self.content[t + 1][0].value < 0:
+ 656 newcontent.append(None)
+ 657 else:
+ 658 newcontent.append(self.content[t - 1] / self.content[t + 1])
+ 659 if (all([x is None for x in newcontent])):
+ 660 raise Exception('m_eff is undefined at all timeslices')
+ 661
+ 662 return np.log(Corr(newcontent, padding=[1, 1])) / 2
+ 663
+ 664 elif variant in ['periodic', 'cosh', 'sinh']:
+ 665 if variant in ['periodic', 'cosh']:
+ 666 func = anp.cosh
+ 667 else:
+ 668 func = anp.sinh
+ 669
+ 670 def root_function(x, d):
+ 671 return func(x * (t - self.T / 2)) / func(x * (t + 1 - self.T / 2)) - d
672
- 673 def root_function(x, d):
- 674 return func(x * (t - self.T / 2)) / func(x * (t + 1 - self.T / 2)) - d
- 675
- 676 newcontent = []
- 677 for t in range(self.T - 1):
- 678 if (self.content[t] is None) or (self.content[t + 1] is None) or (self.content[t + 1][0].value == 0):
- 679 newcontent.append(None)
- 680 # Fill the two timeslices in the middle of the lattice with their predecessors
- 681 elif variant == 'sinh' and t in [self.T / 2, self.T / 2 - 1]:
- 682 newcontent.append(newcontent[-1])
- 683 elif self.content[t][0].value / self.content[t + 1][0].value < 0:
- 684 newcontent.append(None)
- 685 else:
- 686 newcontent.append(np.abs(find_root(self.content[t][0] / self.content[t + 1][0], root_function, guess=guess)))
- 687 if (all([x is None for x in newcontent])):
- 688 raise Exception('m_eff is undefined at all timeslices')
- 689
- 690 return Corr(newcontent, padding=[0, 1])
- 691
- 692 elif variant == 'arccosh':
- 693 newcontent = []
- 694 for t in range(1, self.T - 1):
- 695 if (self.content[t] is None) or (self.content[t + 1] is None) or (self.content[t - 1] is None) or (self.content[t][0].value == 0):
- 696 newcontent.append(None)
- 697 else:
- 698 newcontent.append((self.content[t + 1] + self.content[t - 1]) / (2 * self.content[t]))
- 699 if (all([x is None for x in newcontent])):
- 700 raise Exception("m_eff is undefined at all timeslices")
- 701 return np.arccosh(Corr(newcontent, padding=[1, 1]))
+ 673 newcontent = []
+ 674 for t in range(self.T - 1):
+ 675 if (self.content[t] is None) or (self.content[t + 1] is None) or (self.content[t + 1][0].value == 0):
+ 676 newcontent.append(None)
+ 677 # Fill the two timeslices in the middle of the lattice with their predecessors
+ 678 elif variant == 'sinh' and t in [self.T / 2, self.T / 2 - 1]:
+ 679 newcontent.append(newcontent[-1])
+ 680 elif self.content[t][0].value / self.content[t + 1][0].value < 0:
+ 681 newcontent.append(None)
+ 682 else:
+ 683 newcontent.append(np.abs(find_root(self.content[t][0] / self.content[t + 1][0], root_function, guess=guess)))
+ 684 if (all([x is None for x in newcontent])):
+ 685 raise Exception('m_eff is undefined at all timeslices')
+ 686
+ 687 return Corr(newcontent, padding=[0, 1])
+ 688
+ 689 elif variant == 'arccosh':
+ 690 newcontent = []
+ 691 for t in range(1, self.T - 1):
+ 692 if (self.content[t] is None) or (self.content[t + 1] is None) or (self.content[t - 1] is None) or (self.content[t][0].value == 0):
+ 693 newcontent.append(None)
+ 694 else:
+ 695 newcontent.append((self.content[t + 1] + self.content[t - 1]) / (2 * self.content[t]))
+ 696 if (all([x is None for x in newcontent])):
+ 697 raise Exception("m_eff is undefined at all timeslices")
+ 698 return np.arccosh(Corr(newcontent, padding=[1, 1]))
+ 699
+ 700 else:
+ 701 raise Exception('Unknown variant.')
702
- 703 else:
- 704 raise Exception('Unknown variant.')
+ 703 def fit(self, function, fitrange=None, silent=False, **kwargs):
+ 704 r'''Fits function to the data
705
- 706 def fit(self, function, fitrange=None, silent=False, **kwargs):
- 707 r'''Fits function to the data
- 708
- 709 Parameters
- 710 ----------
- 711 function : obj
- 712 function to fit to the data. See fits.least_squares for details.
- 713 fitrange : list
- 714 Two element list containing the timeslices on which the fit is supposed to start and stop.
- 715 Caution: This range is inclusive as opposed to standard python indexing.
- 716 `fitrange=[4, 6]` corresponds to the three entries 4, 5 and 6.
- 717 If not specified, self.prange or all timeslices are used.
- 718 silent : bool
- 719 Decides whether output is printed to the standard output.
- 720 '''
- 721 if self.N != 1:
- 722 raise Exception("Correlator must be projected before fitting")
- 723
- 724 if fitrange is None:
- 725 if self.prange:
- 726 fitrange = self.prange
- 727 else:
- 728 fitrange = [0, self.T - 1]
- 729 else:
- 730 if not isinstance(fitrange, list):
- 731 raise Exception("fitrange has to be a list with two elements")
- 732 if len(fitrange) != 2:
- 733 raise Exception("fitrange has to have exactly two elements [fit_start, fit_stop]")
- 734
- 735 xs = [x for x in range(fitrange[0], fitrange[1] + 1) if not self.content[x] is None]
- 736 ys = [self.content[x][0] for x in range(fitrange[0], fitrange[1] + 1) if not self.content[x] is None]
- 737 result = least_squares(xs, ys, function, silent=silent, **kwargs)
- 738 return result
+ 706 Parameters
+ 707 ----------
+ 708 function : obj
+ 709 function to fit to the data. See fits.least_squares for details.
+ 710 fitrange : list
+ 711 Two element list containing the timeslices on which the fit is supposed to start and stop.
+ 712 Caution: This range is inclusive as opposed to standard python indexing.
+ 713 `fitrange=[4, 6]` corresponds to the three entries 4, 5 and 6.
+ 714 If not specified, self.prange or all timeslices are used.
+ 715 silent : bool
+ 716 Decides whether output is printed to the standard output.
+ 717 '''
+ 718 if self.N != 1:
+ 719 raise Exception("Correlator must be projected before fitting")
+ 720
+ 721 if fitrange is None:
+ 722 if self.prange:
+ 723 fitrange = self.prange
+ 724 else:
+ 725 fitrange = [0, self.T - 1]
+ 726 else:
+ 727 if not isinstance(fitrange, list):
+ 728 raise Exception("fitrange has to be a list with two elements")
+ 729 if len(fitrange) != 2:
+ 730 raise Exception("fitrange has to have exactly two elements [fit_start, fit_stop]")
+ 731
+ 732 xs = [x for x in range(fitrange[0], fitrange[1] + 1) if not self.content[x] is None]
+ 733 ys = [self.content[x][0] for x in range(fitrange[0], fitrange[1] + 1) if not self.content[x] is None]
+ 734 result = least_squares(xs, ys, function, silent=silent, **kwargs)
+ 735 return result
+ 736
+ 737 def plateau(self, plateau_range=None, method="fit", auto_gamma=False):
+ 738 """ Extract a plateau value from a Corr object
739
- 740 def plateau(self, plateau_range=None, method="fit", auto_gamma=False):
- 741 """ Extract a plateau value from a Corr object
- 742
- 743 Parameters
- 744 ----------
- 745 plateau_range : list
- 746 list with two entries, indicating the first and the last timeslice
- 747 of the plateau region.
- 748 method : str
- 749 method to extract the plateau.
- 750 'fit' fits a constant to the plateau region
- 751 'avg', 'average' or 'mean' just average over the given timeslices.
- 752 auto_gamma : bool
- 753 apply gamma_method with default parameters to the Corr. Defaults to None
- 754 """
- 755 if not plateau_range:
- 756 if self.prange:
- 757 plateau_range = self.prange
- 758 else:
- 759 raise Exception("no plateau range provided")
- 760 if self.N != 1:
- 761 raise Exception("Correlator must be projected before getting a plateau.")
- 762 if (all([self.content[t] is None for t in range(plateau_range[0], plateau_range[1] + 1)])):
- 763 raise Exception("plateau is undefined at all timeslices in plateaurange.")
- 764 if auto_gamma:
- 765 self.gamma_method()
- 766 if method == "fit":
- 767 def const_func(a, t):
- 768 return a[0]
- 769 return self.fit(const_func, plateau_range)[0]
- 770 elif method in ["avg", "average", "mean"]:
- 771 returnvalue = np.mean([item[0] for item in self.content[plateau_range[0]:plateau_range[1] + 1] if item is not None])
- 772 return returnvalue
+ 740 Parameters
+ 741 ----------
+ 742 plateau_range : list
+ 743 list with two entries, indicating the first and the last timeslice
+ 744 of the plateau region.
+ 745 method : str
+ 746 method to extract the plateau.
+ 747 'fit' fits a constant to the plateau region
+ 748 'avg', 'average' or 'mean' just average over the given timeslices.
+ 749 auto_gamma : bool
+ 750 apply gamma_method with default parameters to the Corr. Defaults to None
+ 751 """
+ 752 if not plateau_range:
+ 753 if self.prange:
+ 754 plateau_range = self.prange
+ 755 else:
+ 756 raise Exception("no plateau range provided")
+ 757 if self.N != 1:
+ 758 raise Exception("Correlator must be projected before getting a plateau.")
+ 759 if (all([self.content[t] is None for t in range(plateau_range[0], plateau_range[1] + 1)])):
+ 760 raise Exception("plateau is undefined at all timeslices in plateaurange.")
+ 761 if auto_gamma:
+ 762 self.gamma_method()
+ 763 if method == "fit":
+ 764 def const_func(a, t):
+ 765 return a[0]
+ 766 return self.fit(const_func, plateau_range)[0]
+ 767 elif method in ["avg", "average", "mean"]:
+ 768 returnvalue = np.mean([item[0] for item in self.content[plateau_range[0]:plateau_range[1] + 1] if item is not None])
+ 769 return returnvalue
+ 770
+ 771 else:
+ 772 raise Exception("Unsupported plateau method: " + method)
773
- 774 else:
- 775 raise Exception("Unsupported plateau method: " + method)
- 776
- 777 def set_prange(self, prange):
- 778 """Sets the attribute prange of the Corr object."""
- 779 if not len(prange) == 2:
- 780 raise Exception("prange must be a list or array with two values")
- 781 if not ((isinstance(prange[0], int)) and (isinstance(prange[1], int))):
- 782 raise Exception("Start and end point must be integers")
- 783 if not (0 <= prange[0] <= self.T and 0 <= prange[1] <= self.T and prange[0] < prange[1]):
- 784 raise Exception("Start and end point must define a range in the interval 0,T")
+ 774 def set_prange(self, prange):
+ 775 """Sets the attribute prange of the Corr object."""
+ 776 if not len(prange) == 2:
+ 777 raise Exception("prange must be a list or array with two values")
+ 778 if not ((isinstance(prange[0], int)) and (isinstance(prange[1], int))):
+ 779 raise Exception("Start and end point must be integers")
+ 780 if not (0 <= prange[0] <= self.T and 0 <= prange[1] <= self.T and prange[0] < prange[1]):
+ 781 raise Exception("Start and end point must define a range in the interval 0,T")
+ 782
+ 783 self.prange = prange
+ 784 return
785
- 786 self.prange = prange
- 787 return
+ 786 def show(self, x_range=None, comp=None, y_range=None, logscale=False, plateau=None, fit_res=None, ylabel=None, save=None, auto_gamma=False, hide_sigma=None, references=None, title=None):
+ 787 """Plots the correlator using the tag of the correlator as label if available.
788
- 789 def show(self, x_range=None, comp=None, y_range=None, logscale=False, plateau=None, fit_res=None, ylabel=None, save=None, auto_gamma=False, hide_sigma=None, references=None, title=None):
- 790 """Plots the correlator using the tag of the correlator as label if available.
- 791
- 792 Parameters
- 793 ----------
- 794 x_range : list
- 795 list of two values, determining the range of the x-axis e.g. [4, 8].
- 796 comp : Corr or list of Corr
- 797 Correlator or list of correlators which are plotted for comparison.
- 798 The tags of these correlators are used as labels if available.
- 799 logscale : bool
- 800 Sets y-axis to logscale.
- 801 plateau : Obs
- 802 Plateau value to be visualized in the figure.
- 803 fit_res : Fit_result
- 804 Fit_result object to be visualized.
- 805 ylabel : str
- 806 Label for the y-axis.
- 807 save : str
- 808 path to file in which the figure should be saved.
- 809 auto_gamma : bool
- 810 Apply the gamma method with standard parameters to all correlators and plateau values before plotting.
- 811 hide_sigma : float
- 812 Hides data points from the first value on which is consistent with zero within 'hide_sigma' standard errors.
- 813 references : list
- 814 List of floating point values that are displayed as horizontal lines for reference.
- 815 title : string
- 816 Optional title of the figure.
- 817 """
- 818 if self.N != 1:
- 819 raise Exception("Correlator must be projected before plotting")
+ 789 Parameters
+ 790 ----------
+ 791 x_range : list
+ 792 list of two values, determining the range of the x-axis e.g. [4, 8].
+ 793 comp : Corr or list of Corr
+ 794 Correlator or list of correlators which are plotted for comparison.
+ 795 The tags of these correlators are used as labels if available.
+ 796 logscale : bool
+ 797 Sets y-axis to logscale.
+ 798 plateau : Obs
+ 799 Plateau value to be visualized in the figure.
+ 800 fit_res : Fit_result
+ 801 Fit_result object to be visualized.
+ 802 ylabel : str
+ 803 Label for the y-axis.
+ 804 save : str
+ 805 path to file in which the figure should be saved.
+ 806 auto_gamma : bool
+ 807 Apply the gamma method with standard parameters to all correlators and plateau values before plotting.
+ 808 hide_sigma : float
+ 809 Hides data points from the first value on which is consistent with zero within 'hide_sigma' standard errors.
+ 810 references : list
+ 811 List of floating point values that are displayed as horizontal lines for reference.
+ 812 title : string
+ 813 Optional title of the figure.
+ 814 """
+ 815 if self.N != 1:
+ 816 raise Exception("Correlator must be projected before plotting")
+ 817
+ 818 if auto_gamma:
+ 819 self.gamma_method()
820
- 821 if auto_gamma:
- 822 self.gamma_method()
+ 821 if x_range is None:
+ 822 x_range = [0, self.T - 1]
823
- 824 if x_range is None:
- 825 x_range = [0, self.T - 1]
+ 824 fig = plt.figure()
+ 825 ax1 = fig.add_subplot(111)
826
- 827 fig = plt.figure()
- 828 ax1 = fig.add_subplot(111)
- 829
- 830 x, y, y_err = self.plottable()
- 831 if hide_sigma:
- 832 hide_from = np.argmax((hide_sigma * np.array(y_err[1:])) > np.abs(y[1:])) - 1
- 833 else:
- 834 hide_from = None
- 835 ax1.errorbar(x[:hide_from], y[:hide_from], y_err[:hide_from], label=self.tag)
- 836 if logscale:
- 837 ax1.set_yscale('log')
- 838 else:
- 839 if y_range is None:
- 840 try:
- 841 y_min = min([(x[0].value - x[0].dvalue) for x in self.content[x_range[0]: x_range[1] + 1] if (x is not None) and x[0].dvalue < 2 * np.abs(x[0].value)])
- 842 y_max = max([(x[0].value + x[0].dvalue) for x in self.content[x_range[0]: x_range[1] + 1] if (x is not None) and x[0].dvalue < 2 * np.abs(x[0].value)])
- 843 ax1.set_ylim([y_min - 0.1 * (y_max - y_min), y_max + 0.1 * (y_max - y_min)])
- 844 except Exception:
- 845 pass
- 846 else:
- 847 ax1.set_ylim(y_range)
- 848 if comp:
- 849 if isinstance(comp, (Corr, list)):
- 850 for corr in comp if isinstance(comp, list) else [comp]:
- 851 if auto_gamma:
- 852 corr.gamma_method()
- 853 x, y, y_err = corr.plottable()
- 854 if hide_sigma:
- 855 hide_from = np.argmax((hide_sigma * np.array(y_err[1:])) > np.abs(y[1:])) - 1
- 856 else:
- 857 hide_from = None
- 858 ax1.errorbar(x[:hide_from], y[:hide_from], y_err[:hide_from], label=corr.tag, mfc=plt.rcParams['axes.facecolor'])
- 859 else:
- 860 raise Exception("'comp' must be a correlator or a list of correlators.")
- 861
- 862 if plateau:
- 863 if isinstance(plateau, Obs):
- 864 if auto_gamma:
- 865 plateau.gamma_method()
- 866 ax1.axhline(y=plateau.value, linewidth=2, color=plt.rcParams['text.color'], alpha=0.6, marker=',', ls='--', label=str(plateau))
- 867 ax1.axhspan(plateau.value - plateau.dvalue, plateau.value + plateau.dvalue, alpha=0.25, color=plt.rcParams['text.color'], ls='-')
- 868 else:
- 869 raise Exception("'plateau' must be an Obs")
- 870
- 871 if references:
- 872 if isinstance(references, list):
- 873 for ref in references:
- 874 ax1.axhline(y=ref, linewidth=1, color=plt.rcParams['text.color'], alpha=0.6, marker=',', ls='--')
- 875 else:
- 876 raise Exception("'references' must be a list of floating pint values.")
- 877
- 878 if self.prange:
- 879 ax1.axvline(self.prange[0], 0, 1, ls='-', marker=',')
- 880 ax1.axvline(self.prange[1], 0, 1, ls='-', marker=',')
- 881
- 882 if fit_res:
- 883 x_samples = np.arange(x_range[0], x_range[1] + 1, 0.05)
- 884 ax1.plot(x_samples,
- 885 fit_res.fit_function([o.value for o in fit_res.fit_parameters], x_samples),
- 886 ls='-', marker=',', lw=2)
- 887
- 888 ax1.set_xlabel(r'$x_0 / a$')
- 889 if ylabel:
- 890 ax1.set_ylabel(ylabel)
- 891 ax1.set_xlim([x_range[0] - 0.5, x_range[1] + 0.5])
- 892
- 893 handles, labels = ax1.get_legend_handles_labels()
- 894 if labels:
- 895 ax1.legend()
+ 827 x, y, y_err = self.plottable()
+ 828 if hide_sigma:
+ 829 hide_from = np.argmax((hide_sigma * np.array(y_err[1:])) > np.abs(y[1:])) - 1
+ 830 else:
+ 831 hide_from = None
+ 832 ax1.errorbar(x[:hide_from], y[:hide_from], y_err[:hide_from], label=self.tag)
+ 833 if logscale:
+ 834 ax1.set_yscale('log')
+ 835 else:
+ 836 if y_range is None:
+ 837 try:
+ 838 y_min = min([(x[0].value - x[0].dvalue) for x in self.content[x_range[0]: x_range[1] + 1] if (x is not None) and x[0].dvalue < 2 * np.abs(x[0].value)])
+ 839 y_max = max([(x[0].value + x[0].dvalue) for x in self.content[x_range[0]: x_range[1] + 1] if (x is not None) and x[0].dvalue < 2 * np.abs(x[0].value)])
+ 840 ax1.set_ylim([y_min - 0.1 * (y_max - y_min), y_max + 0.1 * (y_max - y_min)])
+ 841 except Exception:
+ 842 pass
+ 843 else:
+ 844 ax1.set_ylim(y_range)
+ 845 if comp:
+ 846 if isinstance(comp, (Corr, list)):
+ 847 for corr in comp if isinstance(comp, list) else [comp]:
+ 848 if auto_gamma:
+ 849 corr.gamma_method()
+ 850 x, y, y_err = corr.plottable()
+ 851 if hide_sigma:
+ 852 hide_from = np.argmax((hide_sigma * np.array(y_err[1:])) > np.abs(y[1:])) - 1
+ 853 else:
+ 854 hide_from = None
+ 855 ax1.errorbar(x[:hide_from], y[:hide_from], y_err[:hide_from], label=corr.tag, mfc=plt.rcParams['axes.facecolor'])
+ 856 else:
+ 857 raise Exception("'comp' must be a correlator or a list of correlators.")
+ 858
+ 859 if plateau:
+ 860 if isinstance(plateau, Obs):
+ 861 if auto_gamma:
+ 862 plateau.gamma_method()
+ 863 ax1.axhline(y=plateau.value, linewidth=2, color=plt.rcParams['text.color'], alpha=0.6, marker=',', ls='--', label=str(plateau))
+ 864 ax1.axhspan(plateau.value - plateau.dvalue, plateau.value + plateau.dvalue, alpha=0.25, color=plt.rcParams['text.color'], ls='-')
+ 865 else:
+ 866 raise Exception("'plateau' must be an Obs")
+ 867
+ 868 if references:
+ 869 if isinstance(references, list):
+ 870 for ref in references:
+ 871 ax1.axhline(y=ref, linewidth=1, color=plt.rcParams['text.color'], alpha=0.6, marker=',', ls='--')
+ 872 else:
+ 873 raise Exception("'references' must be a list of floating pint values.")
+ 874
+ 875 if self.prange:
+ 876 ax1.axvline(self.prange[0], 0, 1, ls='-', marker=',')
+ 877 ax1.axvline(self.prange[1], 0, 1, ls='-', marker=',')
+ 878
+ 879 if fit_res:
+ 880 x_samples = np.arange(x_range[0], x_range[1] + 1, 0.05)
+ 881 ax1.plot(x_samples,
+ 882 fit_res.fit_function([o.value for o in fit_res.fit_parameters], x_samples),
+ 883 ls='-', marker=',', lw=2)
+ 884
+ 885 ax1.set_xlabel(r'$x_0 / a$')
+ 886 if ylabel:
+ 887 ax1.set_ylabel(ylabel)
+ 888 ax1.set_xlim([x_range[0] - 0.5, x_range[1] + 0.5])
+ 889
+ 890 handles, labels = ax1.get_legend_handles_labels()
+ 891 if labels:
+ 892 ax1.legend()
+ 893
+ 894 if title:
+ 895 plt.title(title)
896
- 897 if title:
- 898 plt.title(title)
- 899
- 900 plt.draw()
- 901
- 902 if save:
- 903 if isinstance(save, str):
- 904 fig.savefig(save, bbox_inches='tight')
- 905 else:
- 906 raise Exception("'save' has to be a string.")
+ 897 plt.draw()
+ 898
+ 899 if save:
+ 900 if isinstance(save, str):
+ 901 fig.savefig(save, bbox_inches='tight')
+ 902 else:
+ 903 raise Exception("'save' has to be a string.")
+ 904
+ 905 def spaghetti_plot(self, logscale=True):
+ 906 """Produces a spaghetti plot of the correlator suited to monitor exceptional configurations.
907
- 908 def spaghetti_plot(self, logscale=True):
- 909 """Produces a spaghetti plot of the correlator suited to monitor exceptional configurations.
- 910
- 911 Parameters
- 912 ----------
- 913 logscale : bool
- 914 Determines whether the scale of the y-axis is logarithmic or standard.
- 915 """
- 916 if self.N != 1:
- 917 raise Exception("Correlator needs to be projected first.")
+ 908 Parameters
+ 909 ----------
+ 910 logscale : bool
+ 911 Determines whether the scale of the y-axis is logarithmic or standard.
+ 912 """
+ 913 if self.N != 1:
+ 914 raise Exception("Correlator needs to be projected first.")
+ 915
+ 916 mc_names = list(set([item for sublist in [sum(map(o[0].e_content.get, o[0].mc_names), []) for o in self.content if o is not None] for item in sublist]))
+ 917 x0_vals = [n for (n, o) in zip(np.arange(self.T), self.content) if o is not None]
918
- 919 mc_names = list(set([item for sublist in [sum(map(o[0].e_content.get, o[0].mc_names), []) for o in self.content if o is not None] for item in sublist]))
- 920 x0_vals = [n for (n, o) in zip(np.arange(self.T), self.content) if o is not None]
+ 919 for name in mc_names:
+ 920 data = np.array([o[0].deltas[name] + o[0].r_values[name] for o in self.content if o is not None]).T
921
- 922 for name in mc_names:
- 923 data = np.array([o[0].deltas[name] + o[0].r_values[name] for o in self.content if o is not None]).T
- 924
- 925 fig = plt.figure()
- 926 ax = fig.add_subplot(111)
- 927 for dat in data:
- 928 ax.plot(x0_vals, dat, ls='-', marker='')
+ 922 fig = plt.figure()
+ 923 ax = fig.add_subplot(111)
+ 924 for dat in data:
+ 925 ax.plot(x0_vals, dat, ls='-', marker='')
+ 926
+ 927 if logscale is True:
+ 928 ax.set_yscale('log')
929
- 930 if logscale is True:
- 931 ax.set_yscale('log')
- 932
- 933 ax.set_xlabel(r'$x_0 / a$')
- 934 plt.title(name)
- 935 plt.draw()
- 936
- 937 def dump(self, filename, datatype="json.gz", **kwargs):
- 938 """Dumps the Corr into a file of chosen type
- 939 Parameters
- 940 ----------
- 941 filename : str
- 942 Name of the file to be saved.
- 943 datatype : str
- 944 Format of the exported file. Supported formats include
- 945 "json.gz" and "pickle"
- 946 path : str
- 947 specifies a custom path for the file (default '.')
- 948 """
- 949 if datatype == "json.gz":
- 950 from .input.json import dump_to_json
- 951 if 'path' in kwargs:
- 952 file_name = kwargs.get('path') + '/' + filename
- 953 else:
- 954 file_name = filename
- 955 dump_to_json(self, file_name)
- 956 elif datatype == "pickle":
- 957 dump_object(self, filename, **kwargs)
- 958 else:
- 959 raise Exception("Unknown datatype " + str(datatype))
+ 930 ax.set_xlabel(r'$x_0 / a$')
+ 931 plt.title(name)
+ 932 plt.draw()
+ 933
+ 934 def dump(self, filename, datatype="json.gz", **kwargs):
+ 935 """Dumps the Corr into a file of chosen type
+ 936 Parameters
+ 937 ----------
+ 938 filename : str
+ 939 Name of the file to be saved.
+ 940 datatype : str
+ 941 Format of the exported file. Supported formats include
+ 942 "json.gz" and "pickle"
+ 943 path : str
+ 944 specifies a custom path for the file (default '.')
+ 945 """
+ 946 if datatype == "json.gz":
+ 947 from .input.json import dump_to_json
+ 948 if 'path' in kwargs:
+ 949 file_name = kwargs.get('path') + '/' + filename
+ 950 else:
+ 951 file_name = filename
+ 952 dump_to_json(self, file_name)
+ 953 elif datatype == "pickle":
+ 954 dump_object(self, filename, **kwargs)
+ 955 else:
+ 956 raise Exception("Unknown datatype " + str(datatype))
+ 957
+ 958 def print(self, print_range=None):
+ 959 print(self.__repr__(print_range))
960
- 961 def print(self, print_range=None):
- 962 print(self.__repr__(print_range))
- 963
- 964 def __repr__(self, print_range=None):
- 965 if print_range is None:
- 966 print_range = [0, None]
+ 961 def __repr__(self, print_range=None):
+ 962 if print_range is None:
+ 963 print_range = [0, None]
+ 964
+ 965 content_string = ""
+ 966 content_string += "Corr T=" + str(self.T) + " N=" + str(self.N) + "\n" # +" filled with"+ str(type(self.content[0][0])) there should be a good solution here
967
- 968 content_string = ""
- 969 content_string += "Corr T=" + str(self.T) + " N=" + str(self.N) + "\n" # +" filled with"+ str(type(self.content[0][0])) there should be a good solution here
- 970
- 971 if self.tag is not None:
- 972 content_string += "Description: " + self.tag + "\n"
- 973 if self.N != 1:
- 974 return content_string
- 975
- 976 if print_range[1]:
- 977 print_range[1] += 1
- 978 content_string += 'x0/a\tCorr(x0/a)\n------------------\n'
- 979 for i, sub_corr in enumerate(self.content[print_range[0]:print_range[1]]):
- 980 if sub_corr is None:
- 981 content_string += str(i + print_range[0]) + '\n'
- 982 else:
- 983 content_string += str(i + print_range[0])
- 984 for element in sub_corr:
- 985 content_string += '\t' + ' ' * int(element >= 0) + str(element)
- 986 content_string += '\n'
- 987 return content_string
+ 968 if self.tag is not None:
+ 969 content_string += "Description: " + self.tag + "\n"
+ 970 if self.N != 1:
+ 971 return content_string
+ 972
+ 973 if print_range[1]:
+ 974 print_range[1] += 1
+ 975 content_string += 'x0/a\tCorr(x0/a)\n------------------\n'
+ 976 for i, sub_corr in enumerate(self.content[print_range[0]:print_range[1]]):
+ 977 if sub_corr is None:
+ 978 content_string += str(i + print_range[0]) + '\n'
+ 979 else:
+ 980 content_string += str(i + print_range[0])
+ 981 for element in sub_corr:
+ 982 content_string += '\t' + ' ' * int(element >= 0) + str(element)
+ 983 content_string += '\n'
+ 984 return content_string
+ 985
+ 986 def __str__(self):
+ 987 return self.__repr__()
988
- 989 def __str__(self):
- 990 return self.__repr__()
- 991
- 992 # We define the basic operations, that can be performed with correlators.
- 993 # While */+- get defined here, they only work for Corr*Obs and not Obs*Corr.
- 994 # This is because Obs*Corr checks Obs.__mul__ first and does not catch an exception.
- 995 # One could try and tell Obs to check if the y in __mul__ is a Corr and
- 996
- 997 def __add__(self, y):
- 998 if isinstance(y, Corr):
- 999 if ((self.N != y.N) or (self.T != y.T)):
-1000 raise Exception("Addition of Corrs with different shape")
-1001 newcontent = []
-1002 for t in range(self.T):
-1003 if _check_for_none(self, self.content[t]) or _check_for_none(y, y.content[t]):
-1004 newcontent.append(None)
-1005 else:
-1006 newcontent.append(self.content[t] + y.content[t])
-1007 return Corr(newcontent)
-1008
-1009 elif isinstance(y, (Obs, int, float, CObs)):
-1010 newcontent = []
-1011 for t in range(self.T):
-1012 if _check_for_none(self, self.content[t]):
-1013 newcontent.append(None)
-1014 else:
-1015 newcontent.append(self.content[t] + y)
-1016 return Corr(newcontent, prange=self.prange)
-1017 elif isinstance(y, np.ndarray):
-1018 if y.shape == (self.T,):
-1019 return Corr(list((np.array(self.content).T + y).T))
-1020 else:
-1021 raise ValueError("operands could not be broadcast together")
-1022 else:
-1023 raise TypeError("Corr + wrong type")
-1024
-1025 def __mul__(self, y):
-1026 if isinstance(y, Corr):
-1027 if not ((self.N == 1 or y.N == 1 or self.N == y.N) and self.T == y.T):
-1028 raise Exception("Multiplication of Corr object requires N=N or N=1 and T=T")
-1029 newcontent = []
-1030 for t in range(self.T):
-1031 if _check_for_none(self, self.content[t]) or _check_for_none(y, y.content[t]):
-1032 newcontent.append(None)
-1033 else:
-1034 newcontent.append(self.content[t] * y.content[t])
-1035 return Corr(newcontent)
-1036
-1037 elif isinstance(y, (Obs, int, float, CObs)):
-1038 newcontent = []
-1039 for t in range(self.T):
-1040 if _check_for_none(self, self.content[t]):
-1041 newcontent.append(None)
-1042 else:
-1043 newcontent.append(self.content[t] * y)
-1044 return Corr(newcontent, prange=self.prange)
-1045 elif isinstance(y, np.ndarray):
-1046 if y.shape == (self.T,):
-1047 return Corr(list((np.array(self.content).T * y).T))
-1048 else:
-1049 raise ValueError("operands could not be broadcast together")
-1050 else:
-1051 raise TypeError("Corr * wrong type")
-1052
-1053 def __truediv__(self, y):
-1054 if isinstance(y, Corr):
-1055 if not ((self.N == 1 or y.N == 1 or self.N == y.N) and self.T == y.T):
-1056 raise Exception("Multiplication of Corr object requires N=N or N=1 and T=T")
-1057 newcontent = []
-1058 for t in range(self.T):
-1059 if _check_for_none(self, self.content[t]) or _check_for_none(y, y.content[t]):
-1060 newcontent.append(None)
-1061 else:
-1062 newcontent.append(self.content[t] / y.content[t])
-1063 for t in range(self.T):
-1064 if _check_for_none(self, newcontent[t]):
-1065 continue
-1066 if np.isnan(np.sum(newcontent[t]).value):
-1067 newcontent[t] = None
-1068
-1069 if all([item is None for item in newcontent]):
-1070 raise Exception("Division returns completely undefined correlator")
-1071 return Corr(newcontent)
-1072
-1073 elif isinstance(y, (Obs, CObs)):
-1074 if isinstance(y, Obs):
-1075 if y.value == 0:
+ 989 # We define the basic operations, that can be performed with correlators.
+ 990 # While */+- get defined here, they only work for Corr*Obs and not Obs*Corr.
+ 991 # This is because Obs*Corr checks Obs.__mul__ first and does not catch an exception.
+ 992 # One could try and tell Obs to check if the y in __mul__ is a Corr and
+ 993
+ 994 def __add__(self, y):
+ 995 if isinstance(y, Corr):
+ 996 if ((self.N != y.N) or (self.T != y.T)):
+ 997 raise Exception("Addition of Corrs with different shape")
+ 998 newcontent = []
+ 999 for t in range(self.T):
+1000 if _check_for_none(self, self.content[t]) or _check_for_none(y, y.content[t]):
+1001 newcontent.append(None)
+1002 else:
+1003 newcontent.append(self.content[t] + y.content[t])
+1004 return Corr(newcontent)
+1005
+1006 elif isinstance(y, (Obs, int, float, CObs)):
+1007 newcontent = []
+1008 for t in range(self.T):
+1009 if _check_for_none(self, self.content[t]):
+1010 newcontent.append(None)
+1011 else:
+1012 newcontent.append(self.content[t] + y)
+1013 return Corr(newcontent, prange=self.prange)
+1014 elif isinstance(y, np.ndarray):
+1015 if y.shape == (self.T,):
+1016 return Corr(list((np.array(self.content).T + y).T))
+1017 else:
+1018 raise ValueError("operands could not be broadcast together")
+1019 else:
+1020 raise TypeError("Corr + wrong type")
+1021
+1022 def __mul__(self, y):
+1023 if isinstance(y, Corr):
+1024 if not ((self.N == 1 or y.N == 1 or self.N == y.N) and self.T == y.T):
+1025 raise Exception("Multiplication of Corr object requires N=N or N=1 and T=T")
+1026 newcontent = []
+1027 for t in range(self.T):
+1028 if _check_for_none(self, self.content[t]) or _check_for_none(y, y.content[t]):
+1029 newcontent.append(None)
+1030 else:
+1031 newcontent.append(self.content[t] * y.content[t])
+1032 return Corr(newcontent)
+1033
+1034 elif isinstance(y, (Obs, int, float, CObs)):
+1035 newcontent = []
+1036 for t in range(self.T):
+1037 if _check_for_none(self, self.content[t]):
+1038 newcontent.append(None)
+1039 else:
+1040 newcontent.append(self.content[t] * y)
+1041 return Corr(newcontent, prange=self.prange)
+1042 elif isinstance(y, np.ndarray):
+1043 if y.shape == (self.T,):
+1044 return Corr(list((np.array(self.content).T * y).T))
+1045 else:
+1046 raise ValueError("operands could not be broadcast together")
+1047 else:
+1048 raise TypeError("Corr * wrong type")
+1049
+1050 def __truediv__(self, y):
+1051 if isinstance(y, Corr):
+1052 if not ((self.N == 1 or y.N == 1 or self.N == y.N) and self.T == y.T):
+1053 raise Exception("Multiplication of Corr object requires N=N or N=1 and T=T")
+1054 newcontent = []
+1055 for t in range(self.T):
+1056 if _check_for_none(self, self.content[t]) or _check_for_none(y, y.content[t]):
+1057 newcontent.append(None)
+1058 else:
+1059 newcontent.append(self.content[t] / y.content[t])
+1060 for t in range(self.T):
+1061 if _check_for_none(self, newcontent[t]):
+1062 continue
+1063 if np.isnan(np.sum(newcontent[t]).value):
+1064 newcontent[t] = None
+1065
+1066 if all([item is None for item in newcontent]):
+1067 raise Exception("Division returns completely undefined correlator")
+1068 return Corr(newcontent)
+1069
+1070 elif isinstance(y, (Obs, CObs)):
+1071 if isinstance(y, Obs):
+1072 if y.value == 0:
+1073 raise Exception('Division by zero will return undefined correlator')
+1074 if isinstance(y, CObs):
+1075 if y.is_zero():
1076 raise Exception('Division by zero will return undefined correlator')
-1077 if isinstance(y, CObs):
-1078 if y.is_zero():
-1079 raise Exception('Division by zero will return undefined correlator')
-1080
-1081 newcontent = []
-1082 for t in range(self.T):
-1083 if _check_for_none(self, self.content[t]):
-1084 newcontent.append(None)
-1085 else:
-1086 newcontent.append(self.content[t] / y)
-1087 return Corr(newcontent, prange=self.prange)
-1088
-1089 elif isinstance(y, (int, float)):
-1090 if y == 0:
-1091 raise Exception('Division by zero will return undefined correlator')
-1092 newcontent = []
-1093 for t in range(self.T):
-1094 if _check_for_none(self, self.content[t]):
-1095 newcontent.append(None)
-1096 else:
-1097 newcontent.append(self.content[t] / y)
-1098 return Corr(newcontent, prange=self.prange)
-1099 elif isinstance(y, np.ndarray):
-1100 if y.shape == (self.T,):
-1101 return Corr(list((np.array(self.content).T / y).T))
-1102 else:
-1103 raise ValueError("operands could not be broadcast together")
-1104 else:
-1105 raise TypeError('Corr / wrong type')
-1106
-1107 def __neg__(self):
-1108 newcontent = [None if _check_for_none(self, item) else -1. * item for item in self.content]
-1109 return Corr(newcontent, prange=self.prange)
+1077
+1078 newcontent = []
+1079 for t in range(self.T):
+1080 if _check_for_none(self, self.content[t]):
+1081 newcontent.append(None)
+1082 else:
+1083 newcontent.append(self.content[t] / y)
+1084 return Corr(newcontent, prange=self.prange)
+1085
+1086 elif isinstance(y, (int, float)):
+1087 if y == 0:
+1088 raise Exception('Division by zero will return undefined correlator')
+1089 newcontent = []
+1090 for t in range(self.T):
+1091 if _check_for_none(self, self.content[t]):
+1092 newcontent.append(None)
+1093 else:
+1094 newcontent.append(self.content[t] / y)
+1095 return Corr(newcontent, prange=self.prange)
+1096 elif isinstance(y, np.ndarray):
+1097 if y.shape == (self.T,):
+1098 return Corr(list((np.array(self.content).T / y).T))
+1099 else:
+1100 raise ValueError("operands could not be broadcast together")
+1101 else:
+1102 raise TypeError('Corr / wrong type')
+1103
+1104 def __neg__(self):
+1105 newcontent = [None if _check_for_none(self, item) else -1. * item for item in self.content]
+1106 return Corr(newcontent, prange=self.prange)
+1107
+1108 def __sub__(self, y):
+1109 return self + (-y)
1110
-1111 def __sub__(self, y):
-1112 return self + (-y)
-1113
-1114 def __pow__(self, y):
-1115 if isinstance(y, (Obs, int, float, CObs)):
-1116 newcontent = [None if _check_for_none(self, item) else item**y for item in self.content]
-1117 return Corr(newcontent, prange=self.prange)
-1118 else:
-1119 raise TypeError('Type of exponent not supported')
-1120
-1121 def __abs__(self):
-1122 newcontent = [None if _check_for_none(self, item) else np.abs(item) for item in self.content]
-1123 return Corr(newcontent, prange=self.prange)
-1124
-1125 # The numpy functions:
-1126 def sqrt(self):
-1127 return self ** 0.5
-1128
-1129 def log(self):
-1130 newcontent = [None if _check_for_none(self, item) else np.log(item) for item in self.content]
-1131 return Corr(newcontent, prange=self.prange)
-1132
-1133 def exp(self):
-1134 newcontent = [None if _check_for_none(self, item) else np.exp(item) for item in self.content]
-1135 return Corr(newcontent, prange=self.prange)
-1136
-1137 def _apply_func_to_corr(self, func):
-1138 newcontent = [None if _check_for_none(self, item) else func(item) for item in self.content]
-1139 for t in range(self.T):
-1140 if _check_for_none(self, newcontent[t]):
-1141 continue
-1142 if np.isnan(np.sum(newcontent[t]).value):
-1143 newcontent[t] = None
-1144 if all([item is None for item in newcontent]):
-1145 raise Exception('Operation returns undefined correlator')
-1146 return Corr(newcontent)
+1111 def __pow__(self, y):
+1112 if isinstance(y, (Obs, int, float, CObs)):
+1113 newcontent = [None if _check_for_none(self, item) else item**y for item in self.content]
+1114 return Corr(newcontent, prange=self.prange)
+1115 else:
+1116 raise TypeError('Type of exponent not supported')
+1117
+1118 def __abs__(self):
+1119 newcontent = [None if _check_for_none(self, item) else np.abs(item) for item in self.content]
+1120 return Corr(newcontent, prange=self.prange)
+1121
+1122 # The numpy functions:
+1123 def sqrt(self):
+1124 return self ** 0.5
+1125
+1126 def log(self):
+1127 newcontent = [None if _check_for_none(self, item) else np.log(item) for item in self.content]
+1128 return Corr(newcontent, prange=self.prange)
+1129
+1130 def exp(self):
+1131 newcontent = [None if _check_for_none(self, item) else np.exp(item) for item in self.content]
+1132 return Corr(newcontent, prange=self.prange)
+1133
+1134 def _apply_func_to_corr(self, func):
+1135 newcontent = [None if _check_for_none(self, item) else func(item) for item in self.content]
+1136 for t in range(self.T):
+1137 if _check_for_none(self, newcontent[t]):
+1138 continue
+1139 if np.isnan(np.sum(newcontent[t]).value):
+1140 newcontent[t] = None
+1141 if all([item is None for item in newcontent]):
+1142 raise Exception('Operation returns undefined correlator')
+1143 return Corr(newcontent)
+1144
+1145 def sin(self):
+1146 return self._apply_func_to_corr(np.sin)
1147
-1148 def sin(self):
-1149 return self._apply_func_to_corr(np.sin)
+1148 def cos(self):
+1149 return self._apply_func_to_corr(np.cos)
1150
-1151 def cos(self):
-1152 return self._apply_func_to_corr(np.cos)
+1151 def tan(self):
+1152 return self._apply_func_to_corr(np.tan)
1153
-1154 def tan(self):
-1155 return self._apply_func_to_corr(np.tan)
+1154 def sinh(self):
+1155 return self._apply_func_to_corr(np.sinh)
1156
-1157 def sinh(self):
-1158 return self._apply_func_to_corr(np.sinh)
+1157 def cosh(self):
+1158 return self._apply_func_to_corr(np.cosh)
1159
-1160 def cosh(self):
-1161 return self._apply_func_to_corr(np.cosh)
+1160 def tanh(self):
+1161 return self._apply_func_to_corr(np.tanh)
1162
-1163 def tanh(self):
-1164 return self._apply_func_to_corr(np.tanh)
+1163 def arcsin(self):
+1164 return self._apply_func_to_corr(np.arcsin)
1165
-1166 def arcsin(self):
-1167 return self._apply_func_to_corr(np.arcsin)
+1166 def arccos(self):
+1167 return self._apply_func_to_corr(np.arccos)
1168
-1169 def arccos(self):
-1170 return self._apply_func_to_corr(np.arccos)
+1169 def arctan(self):
+1170 return self._apply_func_to_corr(np.arctan)
1171
-1172 def arctan(self):
-1173 return self._apply_func_to_corr(np.arctan)
+1172 def arcsinh(self):
+1173 return self._apply_func_to_corr(np.arcsinh)
1174
-1175 def arcsinh(self):
-1176 return self._apply_func_to_corr(np.arcsinh)
+1175 def arccosh(self):
+1176 return self._apply_func_to_corr(np.arccosh)
1177
-1178 def arccosh(self):
-1179 return self._apply_func_to_corr(np.arccosh)
+1178 def arctanh(self):
+1179 return self._apply_func_to_corr(np.arctanh)
1180
-1181 def arctanh(self):
-1182 return self._apply_func_to_corr(np.arctanh)
-1183
-1184 # Right hand side operations (require tweak in main module to work)
-1185 def __radd__(self, y):
-1186 return self + y
+1181 # Right hand side operations (require tweak in main module to work)
+1182 def __radd__(self, y):
+1183 return self + y
+1184
+1185 def __rsub__(self, y):
+1186 return -self + y
1187
-1188 def __rsub__(self, y):
-1189 return -self + y
+1188 def __rmul__(self, y):
+1189 return self * y
1190
-1191 def __rmul__(self, y):
-1192 return self * y
+1191 def __rtruediv__(self, y):
+1192 return (self / y) ** (-1)
1193
-1194 def __rtruediv__(self, y):
-1195 return (self / y) ** (-1)
-1196
-1197 @property
-1198 def real(self):
-1199 def return_real(obs_OR_cobs):
-1200 if isinstance(obs_OR_cobs, CObs):
-1201 return obs_OR_cobs.real
-1202 else:
-1203 return obs_OR_cobs
-1204
-1205 return self._apply_func_to_corr(return_real)
-1206
-1207 @property
-1208 def imag(self):
-1209 def return_imag(obs_OR_cobs):
-1210 if isinstance(obs_OR_cobs, CObs):
-1211 return obs_OR_cobs.imag
-1212 else:
-1213 return obs_OR_cobs * 0 # So it stays the right type
-1214
-1215 return self._apply_func_to_corr(return_imag)
+1194 @property
+1195 def real(self):
+1196 def return_real(obs_OR_cobs):
+1197 if isinstance(obs_OR_cobs, CObs):
+1198 return obs_OR_cobs.real
+1199 else:
+1200 return obs_OR_cobs
+1201
+1202 return self._apply_func_to_corr(return_real)
+1203
+1204 @property
+1205 def imag(self):
+1206 def return_imag(obs_OR_cobs):
+1207 if isinstance(obs_OR_cobs, CObs):
+1208 return obs_OR_cobs.imag
+1209 else:
+1210 return obs_OR_cobs * 0 # So it stays the right type
+1211
+1212 return self._apply_func_to_corr(return_imag)
+1213
+1214 def prune(self, Ntrunc, tproj=3, t0proj=2, basematrix=None):
+1215 r''' Project large correlation matrix to lowest states
1216
-1217 def prune(self, Ntrunc, tproj=3, t0proj=2, basematrix=None):
-1218 r''' Project large correlation matrix to lowest states
-1219
-1220 This method can be used to reduce the size of an (N x N) correlation matrix
-1221 to (Ntrunc x Ntrunc) by solving a GEVP at very early times where the noise
-1222 is still small.
-1223
-1224 Parameters
-1225 ----------
-1226 Ntrunc: int
-1227 Rank of the target matrix.
-1228 tproj: int
-1229 Time where the eigenvectors are evaluated, corresponds to ts in the GEVP method.
-1230 The default value is 3.
-1231 t0proj: int
-1232 Time where the correlation matrix is inverted. Choosing t0proj=1 is strongly
-1233 discouraged for O(a) improved theories, since the correctness of the procedure
-1234 cannot be granted in this case. The default value is 2.
-1235 basematrix : Corr
-1236 Correlation matrix that is used to determine the eigenvectors of the
-1237 lowest states based on a GEVP. basematrix is taken to be the Corr itself if
-1238 is is not specified.
-1239
-1240 Notes
-1241 -----
-1242 We have the basematrix $C(t)$ and the target matrix $G(t)$. We start by solving
-1243 the GEVP $$C(t) v_n(t, t_0) = \lambda_n(t, t_0) C(t_0) v_n(t, t_0)$$ where $t \equiv t_\mathrm{proj}$
-1244 and $t_0 \equiv t_{0, \mathrm{proj}}$. The target matrix is projected onto the subspace of the
-1245 resulting eigenvectors $v_n, n=1,\dots,N_\mathrm{trunc}$ via
-1246 $$G^\prime_{i, j}(t) = (v_i, G(t) v_j)$$. This allows to reduce the size of a large
-1247 correlation matrix and to remove some noise that is added by irrelevant operators.
-1248 This may allow to use the GEVP on $G(t)$ at late times such that the theoretically motivated
-1249 bound $t_0 \leq t/2$ holds, since the condition number of $G(t)$ is decreased, compared to $C(t)$.
-1250 '''
-1251
-1252 if self.N == 1:
-1253 raise Exception('Method cannot be applied to one-dimensional correlators.')
-1254 if basematrix is None:
-1255 basematrix = self
-1256 if Ntrunc >= basematrix.N:
-1257 raise Exception('Cannot truncate using Ntrunc <= %d' % (basematrix.N))
-1258 if basematrix.N != self.N:
-1259 raise Exception('basematrix and targetmatrix have to be of the same size.')
-1260
-1261 evecs = basematrix.GEVP(t0proj, tproj, sort=None)[:Ntrunc]
-1262
-1263 tmpmat = np.empty((Ntrunc, Ntrunc), dtype=object)
-1264 rmat = []
-1265 for t in range(basematrix.T):
-1266 for i in range(Ntrunc):
-1267 for j in range(Ntrunc):
-1268 tmpmat[i][j] = evecs[i].T @ self[t] @ evecs[j]
-1269 rmat.append(np.copy(tmpmat))
+1217 This method can be used to reduce the size of an (N x N) correlation matrix
+1218 to (Ntrunc x Ntrunc) by solving a GEVP at very early times where the noise
+1219 is still small.
+1220
+1221 Parameters
+1222 ----------
+1223 Ntrunc: int
+1224 Rank of the target matrix.
+1225 tproj: int
+1226 Time where the eigenvectors are evaluated, corresponds to ts in the GEVP method.
+1227 The default value is 3.
+1228 t0proj: int
+1229 Time where the correlation matrix is inverted. Choosing t0proj=1 is strongly
+1230 discouraged for O(a) improved theories, since the correctness of the procedure
+1231 cannot be granted in this case. The default value is 2.
+1232 basematrix : Corr
+1233 Correlation matrix that is used to determine the eigenvectors of the
+1234 lowest states based on a GEVP. basematrix is taken to be the Corr itself if
+1235 is is not specified.
+1236
+1237 Notes
+1238 -----
+1239 We have the basematrix $C(t)$ and the target matrix $G(t)$. We start by solving
+1240 the GEVP $$C(t) v_n(t, t_0) = \lambda_n(t, t_0) C(t_0) v_n(t, t_0)$$ where $t \equiv t_\mathrm{proj}$
+1241 and $t_0 \equiv t_{0, \mathrm{proj}}$. The target matrix is projected onto the subspace of the
+1242 resulting eigenvectors $v_n, n=1,\dots,N_\mathrm{trunc}$ via
+1243 $$G^\prime_{i, j}(t) = (v_i, G(t) v_j)$$. This allows to reduce the size of a large
+1244 correlation matrix and to remove some noise that is added by irrelevant operators.
+1245 This may allow to use the GEVP on $G(t)$ at late times such that the theoretically motivated
+1246 bound $t_0 \leq t/2$ holds, since the condition number of $G(t)$ is decreased, compared to $C(t)$.
+1247 '''
+1248
+1249 if self.N == 1:
+1250 raise Exception('Method cannot be applied to one-dimensional correlators.')
+1251 if basematrix is None:
+1252 basematrix = self
+1253 if Ntrunc >= basematrix.N:
+1254 raise Exception('Cannot truncate using Ntrunc <= %d' % (basematrix.N))
+1255 if basematrix.N != self.N:
+1256 raise Exception('basematrix and targetmatrix have to be of the same size.')
+1257
+1258 evecs = basematrix.GEVP(t0proj, tproj, sort=None)[:Ntrunc]
+1259
+1260 tmpmat = np.empty((Ntrunc, Ntrunc), dtype=object)
+1261 rmat = []
+1262 for t in range(basematrix.T):
+1263 for i in range(Ntrunc):
+1264 for j in range(Ntrunc):
+1265 tmpmat[i][j] = evecs[i].T @ self[t] @ evecs[j]
+1266 rmat.append(np.copy(tmpmat))
+1267
+1268 newcontent = [None if (self.content[t] is None) else rmat[t] for t in range(self.T)]
+1269 return Corr(newcontent)
1270
-1271 newcontent = [None if (self.content[t] is None) else rmat[t] for t in range(self.T)]
-1272 return Corr(newcontent)
-1273
-1274
-1275def _sort_vectors(vec_set, ts):
-1276 """Helper function used to find a set of Eigenvectors consistent over all timeslices"""
-1277 reference_sorting = np.array(vec_set[ts])
-1278 N = reference_sorting.shape[0]
-1279 sorted_vec_set = []
-1280 for t in range(len(vec_set)):
-1281 if vec_set[t] is None:
-1282 sorted_vec_set.append(None)
-1283 elif not t == ts:
-1284 perms = [list(o) for o in permutations([i for i in range(N)], N)]
-1285 best_score = 0
-1286 for perm in perms:
-1287 current_score = 1
-1288 for k in range(N):
-1289 new_sorting = reference_sorting.copy()
-1290 new_sorting[perm[k], :] = vec_set[t][k]
-1291 current_score *= abs(np.linalg.det(new_sorting))
-1292 if current_score > best_score:
-1293 best_score = current_score
-1294 best_perm = perm
-1295 sorted_vec_set.append([vec_set[t][k] for k in best_perm])
-1296 else:
-1297 sorted_vec_set.append(vec_set[t])
+1271
+1272def _sort_vectors(vec_set, ts):
+1273 """Helper function used to find a set of Eigenvectors consistent over all timeslices"""
+1274 reference_sorting = np.array(vec_set[ts])
+1275 N = reference_sorting.shape[0]
+1276 sorted_vec_set = []
+1277 for t in range(len(vec_set)):
+1278 if vec_set[t] is None:
+1279 sorted_vec_set.append(None)
+1280 elif not t == ts:
+1281 perms = [list(o) for o in permutations([i for i in range(N)], N)]
+1282 best_score = 0
+1283 for perm in perms:
+1284 current_score = 1
+1285 for k in range(N):
+1286 new_sorting = reference_sorting.copy()
+1287 new_sorting[perm[k], :] = vec_set[t][k]
+1288 current_score *= abs(np.linalg.det(new_sorting))
+1289 if current_score > best_score:
+1290 best_score = current_score
+1291 best_perm = perm
+1292 sorted_vec_set.append([vec_set[t][k] for k in best_perm])
+1293 else:
+1294 sorted_vec_set.append(vec_set[t])
+1295
+1296 return sorted_vec_set
+1297
1298
-1299 return sorted_vec_set
-1300
-1301
-1302def _check_for_none(corr, entry):
-1303 """Checks if entry for correlator corr is None"""
-1304 return len(list(filter(None, np.asarray(entry).flatten()))) < corr.N ** 2
-1305
+1299def _check_for_none(corr, entry):
+1300 """Checks if entry for correlator corr is None"""
+1301 return len(list(filter(None, np.asarray(entry).flatten()))) < corr.N ** 2
+1302
+1303
+1304def _GEVP_solver(Gt, G0):
+1305 """Helper function for solving the GEVP and sorting the eigenvectors.
1306
-1307def _GEVP_solver(Gt, G0):
-1308 """Helper function for solving the GEVP and sorting the eigenvectors.
-1309
-1310 The helper function assumes that both provided matrices are symmetric and
-1311 only processes the lower triangular part of both matrices. In case the matrices
-1312 are not symmetric the upper triangular parts are effectively discarded."""
-1313 return scipy.linalg.eigh(Gt, G0, lower=True)[1].T[::-1]
+1307 The helper function assumes that both provided matrices are symmetric and
+1308 only processes the lower triangular part of both matrices. In case the matrices
+1309 are not symmetric the upper triangular parts are effectively discarded."""
+1310 return scipy.linalg.eigh(Gt, G0, lower=True)[1].T[::-1]
@@ -1598,1207 +1595,1204 @@
70
71 if isinstance(data_input, list):
72
- 73 if all([isinstance(item, (Obs, CObs)) for item in data_input]):
- 74 _assert_equal_properties(data_input)
- 75 self.content = [np.asarray([item]) for item in data_input]
- 76 if all([isinstance(item, (Obs, CObs)) or item is None for item in data_input]):
- 77 _assert_equal_properties([o for o in data_input if o is not None])
- 78 self.content = [np.asarray([item]) if item is not None else None for item in data_input]
- 79 self.N = 1
- 80
- 81 elif all([isinstance(item, np.ndarray) or item is None for item in data_input]) and any([isinstance(item, np.ndarray) for item in data_input]):
- 82 self.content = data_input
- 83 noNull = [a for a in self.content if not (a is None)] # To check if the matrices are correct for all undefined elements
- 84 self.N = noNull[0].shape[0]
- 85 if self.N > 1 and noNull[0].shape[0] != noNull[0].shape[1]:
- 86 raise Exception("Smearing matrices are not NxN")
- 87 if (not all([item.shape == noNull[0].shape for item in noNull])):
- 88 raise Exception("Items in data_input are not of identical shape." + str(noNull))
- 89 else:
- 90 raise Exception("data_input contains item of wrong type")
- 91 else:
- 92 raise Exception("Data input was not given as list or correct array")
- 93
- 94 self.tag = None
- 95
- 96 # An undefined timeslice is represented by the None object
- 97 self.content = [None] * padding[0] + self.content + [None] * padding[1]
- 98 self.T = len(self.content)
- 99 self.prange = prange
- 100
- 101 def __getitem__(self, idx):
- 102 """Return the content of timeslice idx"""
- 103 if self.content[idx] is None:
- 104 return None
- 105 elif len(self.content[idx]) == 1:
- 106 return self.content[idx][0]
- 107 else:
- 108 return self.content[idx]
- 109
- 110 @property
- 111 def reweighted(self):
- 112 bool_array = np.array([list(map(lambda x: x.reweighted, o)) for o in [x for x in self.content if x is not None]])
- 113 if np.all(bool_array == 1):
- 114 return True
- 115 elif np.all(bool_array == 0):
- 116 return False
- 117 else:
- 118 raise Exception("Reweighting status of correlator corrupted.")
- 119
- 120 def gamma_method(self, **kwargs):
- 121 """Apply the gamma method to the content of the Corr."""
- 122 for item in self.content:
- 123 if not (item is None):
- 124 if self.N == 1:
- 125 item[0].gamma_method(**kwargs)
- 126 else:
- 127 for i in range(self.N):
- 128 for j in range(self.N):
- 129 item[i, j].gamma_method(**kwargs)
+ 73 if all([isinstance(item, (Obs, CObs)) or item is None for item in data_input]):
+ 74 _assert_equal_properties([o for o in data_input if o is not None])
+ 75 self.content = [np.asarray([item]) if item is not None else None for item in data_input]
+ 76 self.N = 1
+ 77
+ 78 elif all([isinstance(item, np.ndarray) or item is None for item in data_input]) and any([isinstance(item, np.ndarray) for item in data_input]):
+ 79 self.content = data_input
+ 80 noNull = [a for a in self.content if not (a is None)] # To check if the matrices are correct for all undefined elements
+ 81 self.N = noNull[0].shape[0]
+ 82 if self.N > 1 and noNull[0].shape[0] != noNull[0].shape[1]:
+ 83 raise Exception("Smearing matrices are not NxN")
+ 84 if (not all([item.shape == noNull[0].shape for item in noNull])):
+ 85 raise Exception("Items in data_input are not of identical shape." + str(noNull))
+ 86 else:
+ 87 raise Exception("data_input contains item of wrong type")
+ 88 else:
+ 89 raise Exception("Data input was not given as list or correct array")
+ 90
+ 91 self.tag = None
+ 92
+ 93 # An undefined timeslice is represented by the None object
+ 94 self.content = [None] * padding[0] + self.content + [None] * padding[1]
+ 95 self.T = len(self.content)
+ 96 self.prange = prange
+ 97
+ 98 def __getitem__(self, idx):
+ 99 """Return the content of timeslice idx"""
+ 100 if self.content[idx] is None:
+ 101 return None
+ 102 elif len(self.content[idx]) == 1:
+ 103 return self.content[idx][0]
+ 104 else:
+ 105 return self.content[idx]
+ 106
+ 107 @property
+ 108 def reweighted(self):
+ 109 bool_array = np.array([list(map(lambda x: x.reweighted, o)) for o in [x for x in self.content if x is not None]])
+ 110 if np.all(bool_array == 1):
+ 111 return True
+ 112 elif np.all(bool_array == 0):
+ 113 return False
+ 114 else:
+ 115 raise Exception("Reweighting status of correlator corrupted.")
+ 116
+ 117 def gamma_method(self, **kwargs):
+ 118 """Apply the gamma method to the content of the Corr."""
+ 119 for item in self.content:
+ 120 if not (item is None):
+ 121 if self.N == 1:
+ 122 item[0].gamma_method(**kwargs)
+ 123 else:
+ 124 for i in range(self.N):
+ 125 for j in range(self.N):
+ 126 item[i, j].gamma_method(**kwargs)
+ 127
+ 128 def projected(self, vector_l=None, vector_r=None, normalize=False):
+ 129 """We need to project the Correlator with a Vector to get a single value at each timeslice.
130
- 131 def projected(self, vector_l=None, vector_r=None, normalize=False):
- 132 """We need to project the Correlator with a Vector to get a single value at each timeslice.
- 133
- 134 The method can use one or two vectors.
- 135 If two are specified it returns v1@G@v2 (the order might be very important.)
- 136 By default it will return the lowest source, which usually means unsmeared-unsmeared (0,0), but it does not have to
- 137 """
- 138 if self.N == 1:
- 139 raise Exception("Trying to project a Corr, that already has N=1.")
- 140
- 141 if vector_l is None:
- 142 vector_l, vector_r = np.asarray([1.] + (self.N - 1) * [0.]), np.asarray([1.] + (self.N - 1) * [0.])
- 143 elif (vector_r is None):
- 144 vector_r = vector_l
- 145 if isinstance(vector_l, list) and not isinstance(vector_r, list):
- 146 if len(vector_l) != self.T:
- 147 raise Exception("Length of vector list must be equal to T")
- 148 vector_r = [vector_r] * self.T
- 149 if isinstance(vector_r, list) and not isinstance(vector_l, list):
- 150 if len(vector_r) != self.T:
- 151 raise Exception("Length of vector list must be equal to T")
- 152 vector_l = [vector_l] * self.T
- 153
- 154 if not isinstance(vector_l, list):
- 155 if not vector_l.shape == vector_r.shape == (self.N,):
- 156 raise Exception("Vectors are of wrong shape!")
- 157 if normalize:
- 158 vector_l, vector_r = vector_l / np.sqrt((vector_l @ vector_l)), vector_r / np.sqrt(vector_r @ vector_r)
- 159 newcontent = [None if _check_for_none(self, item) else np.asarray([vector_l.T @ item @ vector_r]) for item in self.content]
- 160
- 161 else:
- 162 # There are no checks here yet. There are so many possible scenarios, where this can go wrong.
- 163 if normalize:
- 164 for t in range(self.T):
- 165 vector_l[t], vector_r[t] = vector_l[t] / np.sqrt((vector_l[t] @ vector_l[t])), vector_r[t] / np.sqrt(vector_r[t] @ vector_r[t])
+ 131 The method can use one or two vectors.
+ 132 If two are specified it returns v1@G@v2 (the order might be very important.)
+ 133 By default it will return the lowest source, which usually means unsmeared-unsmeared (0,0), but it does not have to
+ 134 """
+ 135 if self.N == 1:
+ 136 raise Exception("Trying to project a Corr, that already has N=1.")
+ 137
+ 138 if vector_l is None:
+ 139 vector_l, vector_r = np.asarray([1.] + (self.N - 1) * [0.]), np.asarray([1.] + (self.N - 1) * [0.])
+ 140 elif (vector_r is None):
+ 141 vector_r = vector_l
+ 142 if isinstance(vector_l, list) and not isinstance(vector_r, list):
+ 143 if len(vector_l) != self.T:
+ 144 raise Exception("Length of vector list must be equal to T")
+ 145 vector_r = [vector_r] * self.T
+ 146 if isinstance(vector_r, list) and not isinstance(vector_l, list):
+ 147 if len(vector_r) != self.T:
+ 148 raise Exception("Length of vector list must be equal to T")
+ 149 vector_l = [vector_l] * self.T
+ 150
+ 151 if not isinstance(vector_l, list):
+ 152 if not vector_l.shape == vector_r.shape == (self.N,):
+ 153 raise Exception("Vectors are of wrong shape!")
+ 154 if normalize:
+ 155 vector_l, vector_r = vector_l / np.sqrt((vector_l @ vector_l)), vector_r / np.sqrt(vector_r @ vector_r)
+ 156 newcontent = [None if _check_for_none(self, item) else np.asarray([vector_l.T @ item @ vector_r]) for item in self.content]
+ 157
+ 158 else:
+ 159 # There are no checks here yet. There are so many possible scenarios, where this can go wrong.
+ 160 if normalize:
+ 161 for t in range(self.T):
+ 162 vector_l[t], vector_r[t] = vector_l[t] / np.sqrt((vector_l[t] @ vector_l[t])), vector_r[t] / np.sqrt(vector_r[t] @ vector_r[t])
+ 163
+ 164 newcontent = [None if (_check_for_none(self, self.content[t]) or vector_l[t] is None or vector_r[t] is None) else np.asarray([vector_l[t].T @ self.content[t] @ vector_r[t]]) for t in range(self.T)]
+ 165 return Corr(newcontent)
166
- 167 newcontent = [None if (_check_for_none(self, self.content[t]) or vector_l[t] is None or vector_r[t] is None) else np.asarray([vector_l[t].T @ self.content[t] @ vector_r[t]]) for t in range(self.T)]
- 168 return Corr(newcontent)
+ 167 def item(self, i, j):
+ 168 """Picks the element [i,j] from every matrix and returns a correlator containing one Obs per timeslice.
169
- 170 def item(self, i, j):
- 171 """Picks the element [i,j] from every matrix and returns a correlator containing one Obs per timeslice.
- 172
- 173 Parameters
- 174 ----------
- 175 i : int
- 176 First index to be picked.
- 177 j : int
- 178 Second index to be picked.
- 179 """
- 180 if self.N == 1:
- 181 raise Exception("Trying to pick item from projected Corr")
- 182 newcontent = [None if (item is None) else item[i, j] for item in self.content]
- 183 return Corr(newcontent)
+ 170 Parameters
+ 171 ----------
+ 172 i : int
+ 173 First index to be picked.
+ 174 j : int
+ 175 Second index to be picked.
+ 176 """
+ 177 if self.N == 1:
+ 178 raise Exception("Trying to pick item from projected Corr")
+ 179 newcontent = [None if (item is None) else item[i, j] for item in self.content]
+ 180 return Corr(newcontent)
+ 181
+ 182 def plottable(self):
+ 183 """Outputs the correlator in a plotable format.
184
- 185 def plottable(self):
- 186 """Outputs the correlator in a plotable format.
- 187
- 188 Outputs three lists containing the timeslice index, the value on each
- 189 timeslice and the error on each timeslice.
- 190 """
- 191 if self.N != 1:
- 192 raise Exception("Can only make Corr[N=1] plottable")
- 193 x_list = [x for x in range(self.T) if not self.content[x] is None]
- 194 y_list = [y[0].value for y in self.content if y is not None]
- 195 y_err_list = [y[0].dvalue for y in self.content if y is not None]
- 196
- 197 return x_list, y_list, y_err_list
- 198
- 199 def symmetric(self):
- 200 """ Symmetrize the correlator around x0=0."""
- 201 if self.N != 1:
- 202 raise Exception('symmetric cannot be safely applied to multi-dimensional correlators.')
- 203 if self.T % 2 != 0:
- 204 raise Exception("Can not symmetrize odd T")
+ 185 Outputs three lists containing the timeslice index, the value on each
+ 186 timeslice and the error on each timeslice.
+ 187 """
+ 188 if self.N != 1:
+ 189 raise Exception("Can only make Corr[N=1] plottable")
+ 190 x_list = [x for x in range(self.T) if not self.content[x] is None]
+ 191 y_list = [y[0].value for y in self.content if y is not None]
+ 192 y_err_list = [y[0].dvalue for y in self.content if y is not None]
+ 193
+ 194 return x_list, y_list, y_err_list
+ 195
+ 196 def symmetric(self):
+ 197 """ Symmetrize the correlator around x0=0."""
+ 198 if self.N != 1:
+ 199 raise Exception('symmetric cannot be safely applied to multi-dimensional correlators.')
+ 200 if self.T % 2 != 0:
+ 201 raise Exception("Can not symmetrize odd T")
+ 202
+ 203 if np.argmax(np.abs(self.content)) != 0:
+ 204 warnings.warn("Correlator does not seem to be symmetric around x0=0.", RuntimeWarning)
205
- 206 if np.argmax(np.abs(self.content)) != 0:
- 207 warnings.warn("Correlator does not seem to be symmetric around x0=0.", RuntimeWarning)
- 208
- 209 newcontent = [self.content[0]]
- 210 for t in range(1, self.T):
- 211 if (self.content[t] is None) or (self.content[self.T - t] is None):
- 212 newcontent.append(None)
- 213 else:
- 214 newcontent.append(0.5 * (self.content[t] + self.content[self.T - t]))
- 215 if (all([x is None for x in newcontent])):
- 216 raise Exception("Corr could not be symmetrized: No redundant values")
- 217 return Corr(newcontent, prange=self.prange)
- 218
- 219 def anti_symmetric(self):
- 220 """Anti-symmetrize the correlator around x0=0."""
- 221 if self.N != 1:
- 222 raise Exception('anti_symmetric cannot be safely applied to multi-dimensional correlators.')
- 223 if self.T % 2 != 0:
- 224 raise Exception("Can not symmetrize odd T")
- 225
- 226 test = 1 * self
- 227 test.gamma_method()
- 228 if not all([o.is_zero_within_error(3) for o in test.content[0]]):
- 229 warnings.warn("Correlator does not seem to be anti-symmetric around x0=0.", RuntimeWarning)
- 230
- 231 newcontent = [self.content[0]]
- 232 for t in range(1, self.T):
- 233 if (self.content[t] is None) or (self.content[self.T - t] is None):
- 234 newcontent.append(None)
- 235 else:
- 236 newcontent.append(0.5 * (self.content[t] - self.content[self.T - t]))
- 237 if (all([x is None for x in newcontent])):
- 238 raise Exception("Corr could not be symmetrized: No redundant values")
- 239 return Corr(newcontent, prange=self.prange)
- 240
- 241 def is_matrix_symmetric(self):
- 242 """Checks whether a correlator matrices is symmetric on every timeslice."""
- 243 if self.N == 1:
- 244 raise Exception("Only works for correlator matrices.")
- 245 for t in range(self.T):
- 246 if self[t] is None:
- 247 continue
- 248 for i in range(self.N):
- 249 for j in range(i + 1, self.N):
- 250 if self[t][i, j] is self[t][j, i]:
- 251 continue
- 252 if hash(self[t][i, j]) != hash(self[t][j, i]):
- 253 return False
- 254 return True
- 255
- 256 def matrix_symmetric(self):
- 257 """Symmetrizes the correlator matrices on every timeslice."""
- 258 if self.N == 1:
- 259 raise Exception("Trying to symmetrize a correlator matrix, that already has N=1.")
- 260 if self.is_matrix_symmetric():
- 261 return 1.0 * self
- 262 else:
- 263 transposed = [None if _check_for_none(self, G) else G.T for G in self.content]
- 264 return 0.5 * (Corr(transposed) + self)
+ 206 newcontent = [self.content[0]]
+ 207 for t in range(1, self.T):
+ 208 if (self.content[t] is None) or (self.content[self.T - t] is None):
+ 209 newcontent.append(None)
+ 210 else:
+ 211 newcontent.append(0.5 * (self.content[t] + self.content[self.T - t]))
+ 212 if (all([x is None for x in newcontent])):
+ 213 raise Exception("Corr could not be symmetrized: No redundant values")
+ 214 return Corr(newcontent, prange=self.prange)
+ 215
+ 216 def anti_symmetric(self):
+ 217 """Anti-symmetrize the correlator around x0=0."""
+ 218 if self.N != 1:
+ 219 raise Exception('anti_symmetric cannot be safely applied to multi-dimensional correlators.')
+ 220 if self.T % 2 != 0:
+ 221 raise Exception("Can not symmetrize odd T")
+ 222
+ 223 test = 1 * self
+ 224 test.gamma_method()
+ 225 if not all([o.is_zero_within_error(3) for o in test.content[0]]):
+ 226 warnings.warn("Correlator does not seem to be anti-symmetric around x0=0.", RuntimeWarning)
+ 227
+ 228 newcontent = [self.content[0]]
+ 229 for t in range(1, self.T):
+ 230 if (self.content[t] is None) or (self.content[self.T - t] is None):
+ 231 newcontent.append(None)
+ 232 else:
+ 233 newcontent.append(0.5 * (self.content[t] - self.content[self.T - t]))
+ 234 if (all([x is None for x in newcontent])):
+ 235 raise Exception("Corr could not be symmetrized: No redundant values")
+ 236 return Corr(newcontent, prange=self.prange)
+ 237
+ 238 def is_matrix_symmetric(self):
+ 239 """Checks whether a correlator matrices is symmetric on every timeslice."""
+ 240 if self.N == 1:
+ 241 raise Exception("Only works for correlator matrices.")
+ 242 for t in range(self.T):
+ 243 if self[t] is None:
+ 244 continue
+ 245 for i in range(self.N):
+ 246 for j in range(i + 1, self.N):
+ 247 if self[t][i, j] is self[t][j, i]:
+ 248 continue
+ 249 if hash(self[t][i, j]) != hash(self[t][j, i]):
+ 250 return False
+ 251 return True
+ 252
+ 253 def matrix_symmetric(self):
+ 254 """Symmetrizes the correlator matrices on every timeslice."""
+ 255 if self.N == 1:
+ 256 raise Exception("Trying to symmetrize a correlator matrix, that already has N=1.")
+ 257 if self.is_matrix_symmetric():
+ 258 return 1.0 * self
+ 259 else:
+ 260 transposed = [None if _check_for_none(self, G) else G.T for G in self.content]
+ 261 return 0.5 * (Corr(transposed) + self)
+ 262
+ 263 def GEVP(self, t0, ts=None, sort="Eigenvalue", **kwargs):
+ 264 r'''Solve the generalized eigenvalue problem on the correlator matrix and returns the corresponding eigenvectors.
265
- 266 def GEVP(self, t0, ts=None, sort="Eigenvalue", **kwargs):
- 267 r'''Solve the generalized eigenvalue problem on the correlator matrix and returns the corresponding eigenvectors.
- 268
- 269 The eigenvectors are sorted according to the descending eigenvalues, the zeroth eigenvector(s) correspond to the
- 270 largest eigenvalue(s). The eigenvector(s) for the individual states can be accessed via slicing
- 271 ```python
- 272 C.GEVP(t0=2)[0] # Ground state vector(s)
- 273 C.GEVP(t0=2)[:3] # Vectors for the lowest three states
- 274 ```
- 275
- 276 Parameters
- 277 ----------
- 278 t0 : int
- 279 The time t0 for the right hand side of the GEVP according to $G(t)v_i=\lambda_i G(t_0)v_i$
- 280 ts : int
- 281 fixed time $G(t_s)v_i=\lambda_i G(t_0)v_i$ if sort=None.
- 282 If sort="Eigenvector" it gives a reference point for the sorting method.
- 283 sort : string
- 284 If this argument is set, a list of self.T vectors per state is returned. If it is set to None, only one vector is returned.
- 285 - "Eigenvalue": The eigenvector is chosen according to which eigenvalue it belongs individually on every timeslice.
- 286 - "Eigenvector": Use the method described in arXiv:2004.10472 to find the set of v(t) belonging to the state.
- 287 The reference state is identified by its eigenvalue at $t=t_s$.
- 288
- 289 Other Parameters
- 290 ----------------
- 291 state : int
- 292 Returns only the vector(s) for a specified state. The lowest state is zero.
- 293 '''
- 294
- 295 if self.N == 1:
- 296 raise Exception("GEVP methods only works on correlator matrices and not single correlators.")
- 297 if ts is not None:
- 298 if (ts <= t0):
- 299 raise Exception("ts has to be larger than t0.")
- 300
- 301 if "sorted_list" in kwargs:
- 302 warnings.warn("Argument 'sorted_list' is deprecated, use 'sort' instead.", DeprecationWarning)
- 303 sort = kwargs.get("sorted_list")
- 304
- 305 if self.is_matrix_symmetric():
- 306 symmetric_corr = self
- 307 else:
- 308 symmetric_corr = self.matrix_symmetric()
+ 266 The eigenvectors are sorted according to the descending eigenvalues, the zeroth eigenvector(s) correspond to the
+ 267 largest eigenvalue(s). The eigenvector(s) for the individual states can be accessed via slicing
+ 268 ```python
+ 269 C.GEVP(t0=2)[0] # Ground state vector(s)
+ 270 C.GEVP(t0=2)[:3] # Vectors for the lowest three states
+ 271 ```
+ 272
+ 273 Parameters
+ 274 ----------
+ 275 t0 : int
+ 276 The time t0 for the right hand side of the GEVP according to $G(t)v_i=\lambda_i G(t_0)v_i$
+ 277 ts : int
+ 278 fixed time $G(t_s)v_i=\lambda_i G(t_0)v_i$ if sort=None.
+ 279 If sort="Eigenvector" it gives a reference point for the sorting method.
+ 280 sort : string
+ 281 If this argument is set, a list of self.T vectors per state is returned. If it is set to None, only one vector is returned.
+ 282 - "Eigenvalue": The eigenvector is chosen according to which eigenvalue it belongs individually on every timeslice.
+ 283 - "Eigenvector": Use the method described in arXiv:2004.10472 to find the set of v(t) belonging to the state.
+ 284 The reference state is identified by its eigenvalue at $t=t_s$.
+ 285
+ 286 Other Parameters
+ 287 ----------------
+ 288 state : int
+ 289 Returns only the vector(s) for a specified state. The lowest state is zero.
+ 290 '''
+ 291
+ 292 if self.N == 1:
+ 293 raise Exception("GEVP methods only works on correlator matrices and not single correlators.")
+ 294 if ts is not None:
+ 295 if (ts <= t0):
+ 296 raise Exception("ts has to be larger than t0.")
+ 297
+ 298 if "sorted_list" in kwargs:
+ 299 warnings.warn("Argument 'sorted_list' is deprecated, use 'sort' instead.", DeprecationWarning)
+ 300 sort = kwargs.get("sorted_list")
+ 301
+ 302 if self.is_matrix_symmetric():
+ 303 symmetric_corr = self
+ 304 else:
+ 305 symmetric_corr = self.matrix_symmetric()
+ 306
+ 307 G0 = np.vectorize(lambda x: x.value)(symmetric_corr[t0])
+ 308 np.linalg.cholesky(G0) # Check if matrix G0 is positive-semidefinite.
309
- 310 G0 = np.vectorize(lambda x: x.value)(symmetric_corr[t0])
- 311 np.linalg.cholesky(G0) # Check if matrix G0 is positive-semidefinite.
- 312
- 313 if sort is None:
- 314 if (ts is None):
- 315 raise Exception("ts is required if sort=None.")
- 316 if (self.content[t0] is None) or (self.content[ts] is None):
- 317 raise Exception("Corr not defined at t0/ts.")
- 318 Gt = np.vectorize(lambda x: x.value)(symmetric_corr[ts])
- 319 reordered_vecs = _GEVP_solver(Gt, G0)
- 320
- 321 elif sort in ["Eigenvalue", "Eigenvector"]:
- 322 if sort == "Eigenvalue" and ts is not None:
- 323 warnings.warn("ts has no effect when sorting by eigenvalue is chosen.", RuntimeWarning)
- 324 all_vecs = [None] * (t0 + 1)
- 325 for t in range(t0 + 1, self.T):
- 326 try:
- 327 Gt = np.vectorize(lambda x: x.value)(symmetric_corr[t])
- 328 all_vecs.append(_GEVP_solver(Gt, G0))
- 329 except Exception:
- 330 all_vecs.append(None)
- 331 if sort == "Eigenvector":
- 332 if ts is None:
- 333 raise Exception("ts is required for the Eigenvector sorting method.")
- 334 all_vecs = _sort_vectors(all_vecs, ts)
- 335
- 336 reordered_vecs = [[v[s] if v is not None else None for v in all_vecs] for s in range(self.N)]
- 337 else:
- 338 raise Exception("Unkown value for 'sort'.")
- 339
- 340 if "state" in kwargs:
- 341 return reordered_vecs[kwargs.get("state")]
- 342 else:
- 343 return reordered_vecs
+ 310 if sort is None:
+ 311 if (ts is None):
+ 312 raise Exception("ts is required if sort=None.")
+ 313 if (self.content[t0] is None) or (self.content[ts] is None):
+ 314 raise Exception("Corr not defined at t0/ts.")
+ 315 Gt = np.vectorize(lambda x: x.value)(symmetric_corr[ts])
+ 316 reordered_vecs = _GEVP_solver(Gt, G0)
+ 317
+ 318 elif sort in ["Eigenvalue", "Eigenvector"]:
+ 319 if sort == "Eigenvalue" and ts is not None:
+ 320 warnings.warn("ts has no effect when sorting by eigenvalue is chosen.", RuntimeWarning)
+ 321 all_vecs = [None] * (t0 + 1)
+ 322 for t in range(t0 + 1, self.T):
+ 323 try:
+ 324 Gt = np.vectorize(lambda x: x.value)(symmetric_corr[t])
+ 325 all_vecs.append(_GEVP_solver(Gt, G0))
+ 326 except Exception:
+ 327 all_vecs.append(None)
+ 328 if sort == "Eigenvector":
+ 329 if ts is None:
+ 330 raise Exception("ts is required for the Eigenvector sorting method.")
+ 331 all_vecs = _sort_vectors(all_vecs, ts)
+ 332
+ 333 reordered_vecs = [[v[s] if v is not None else None for v in all_vecs] for s in range(self.N)]
+ 334 else:
+ 335 raise Exception("Unkown value for 'sort'.")
+ 336
+ 337 if "state" in kwargs:
+ 338 return reordered_vecs[kwargs.get("state")]
+ 339 else:
+ 340 return reordered_vecs
+ 341
+ 342 def Eigenvalue(self, t0, ts=None, state=0, sort="Eigenvalue"):
+ 343 """Determines the eigenvalue of the GEVP by solving and projecting the correlator
344
- 345 def Eigenvalue(self, t0, ts=None, state=0, sort="Eigenvalue"):
- 346 """Determines the eigenvalue of the GEVP by solving and projecting the correlator
- 347
- 348 Parameters
- 349 ----------
- 350 state : int
- 351 The state one is interested in ordered by energy. The lowest state is zero.
- 352
- 353 All other parameters are identical to the ones of Corr.GEVP.
- 354 """
- 355 vec = self.GEVP(t0, ts=ts, sort=sort)[state]
- 356 return self.projected(vec)
+ 345 Parameters
+ 346 ----------
+ 347 state : int
+ 348 The state one is interested in ordered by energy. The lowest state is zero.
+ 349
+ 350 All other parameters are identical to the ones of Corr.GEVP.
+ 351 """
+ 352 vec = self.GEVP(t0, ts=ts, sort=sort)[state]
+ 353 return self.projected(vec)
+ 354
+ 355 def Hankel(self, N, periodic=False):
+ 356 """Constructs an NxN Hankel matrix
357
- 358 def Hankel(self, N, periodic=False):
- 359 """Constructs an NxN Hankel matrix
- 360
- 361 C(t) c(t+1) ... c(t+n-1)
- 362 C(t+1) c(t+2) ... c(t+n)
- 363 .................
- 364 C(t+(n-1)) c(t+n) ... c(t+2(n-1))
- 365
- 366 Parameters
- 367 ----------
- 368 N : int
- 369 Dimension of the Hankel matrix
- 370 periodic : bool, optional
- 371 determines whether the matrix is extended periodically
- 372 """
+ 358 C(t) c(t+1) ... c(t+n-1)
+ 359 C(t+1) c(t+2) ... c(t+n)
+ 360 .................
+ 361 C(t+(n-1)) c(t+n) ... c(t+2(n-1))
+ 362
+ 363 Parameters
+ 364 ----------
+ 365 N : int
+ 366 Dimension of the Hankel matrix
+ 367 periodic : bool, optional
+ 368 determines whether the matrix is extended periodically
+ 369 """
+ 370
+ 371 if self.N != 1:
+ 372 raise Exception("Multi-operator Prony not implemented!")
373
- 374 if self.N != 1:
- 375 raise Exception("Multi-operator Prony not implemented!")
- 376
- 377 array = np.empty([N, N], dtype="object")
- 378 new_content = []
- 379 for t in range(self.T):
- 380 new_content.append(array.copy())
- 381
- 382 def wrap(i):
- 383 while i >= self.T:
- 384 i -= self.T
- 385 return i
- 386
- 387 for t in range(self.T):
- 388 for i in range(N):
- 389 for j in range(N):
- 390 if periodic:
- 391 new_content[t][i, j] = self.content[wrap(t + i + j)][0]
- 392 elif (t + i + j) >= self.T:
- 393 new_content[t] = None
- 394 else:
- 395 new_content[t][i, j] = self.content[t + i + j][0]
- 396
- 397 return Corr(new_content)
+ 374 array = np.empty([N, N], dtype="object")
+ 375 new_content = []
+ 376 for t in range(self.T):
+ 377 new_content.append(array.copy())
+ 378
+ 379 def wrap(i):
+ 380 while i >= self.T:
+ 381 i -= self.T
+ 382 return i
+ 383
+ 384 for t in range(self.T):
+ 385 for i in range(N):
+ 386 for j in range(N):
+ 387 if periodic:
+ 388 new_content[t][i, j] = self.content[wrap(t + i + j)][0]
+ 389 elif (t + i + j) >= self.T:
+ 390 new_content[t] = None
+ 391 else:
+ 392 new_content[t][i, j] = self.content[t + i + j][0]
+ 393
+ 394 return Corr(new_content)
+ 395
+ 396 def roll(self, dt):
+ 397 """Periodically shift the correlator by dt timeslices
398
- 399 def roll(self, dt):
- 400 """Periodically shift the correlator by dt timeslices
- 401
- 402 Parameters
- 403 ----------
- 404 dt : int
- 405 number of timeslices
- 406 """
- 407 return Corr(list(np.roll(np.array(self.content, dtype=object), dt)))
- 408
- 409 def reverse(self):
- 410 """Reverse the time ordering of the Corr"""
- 411 return Corr(self.content[:: -1])
+ 399 Parameters
+ 400 ----------
+ 401 dt : int
+ 402 number of timeslices
+ 403 """
+ 404 return Corr(list(np.roll(np.array(self.content, dtype=object), dt)))
+ 405
+ 406 def reverse(self):
+ 407 """Reverse the time ordering of the Corr"""
+ 408 return Corr(self.content[:: -1])
+ 409
+ 410 def thin(self, spacing=2, offset=0):
+ 411 """Thin out a correlator to suppress correlations
412
- 413 def thin(self, spacing=2, offset=0):
- 414 """Thin out a correlator to suppress correlations
- 415
- 416 Parameters
- 417 ----------
- 418 spacing : int
- 419 Keep only every 'spacing'th entry of the correlator
- 420 offset : int
- 421 Offset the equal spacing
- 422 """
- 423 new_content = []
- 424 for t in range(self.T):
- 425 if (offset + t) % spacing != 0:
- 426 new_content.append(None)
- 427 else:
- 428 new_content.append(self.content[t])
- 429 return Corr(new_content)
+ 413 Parameters
+ 414 ----------
+ 415 spacing : int
+ 416 Keep only every 'spacing'th entry of the correlator
+ 417 offset : int
+ 418 Offset the equal spacing
+ 419 """
+ 420 new_content = []
+ 421 for t in range(self.T):
+ 422 if (offset + t) % spacing != 0:
+ 423 new_content.append(None)
+ 424 else:
+ 425 new_content.append(self.content[t])
+ 426 return Corr(new_content)
+ 427
+ 428 def correlate(self, partner):
+ 429 """Correlate the correlator with another correlator or Obs
430
- 431 def correlate(self, partner):
- 432 """Correlate the correlator with another correlator or Obs
- 433
- 434 Parameters
- 435 ----------
- 436 partner : Obs or Corr
- 437 partner to correlate the correlator with.
- 438 Can either be an Obs which is correlated with all entries of the
- 439 correlator or a Corr of same length.
- 440 """
- 441 if self.N != 1:
- 442 raise Exception("Only one-dimensional correlators can be safely correlated.")
- 443 new_content = []
- 444 for x0, t_slice in enumerate(self.content):
- 445 if _check_for_none(self, t_slice):
- 446 new_content.append(None)
- 447 else:
- 448 if isinstance(partner, Corr):
- 449 if _check_for_none(partner, partner.content[x0]):
- 450 new_content.append(None)
- 451 else:
- 452 new_content.append(np.array([correlate(o, partner.content[x0][0]) for o in t_slice]))
- 453 elif isinstance(partner, Obs): # Should this include CObs?
- 454 new_content.append(np.array([correlate(o, partner) for o in t_slice]))
- 455 else:
- 456 raise Exception("Can only correlate with an Obs or a Corr.")
- 457
- 458 return Corr(new_content)
+ 431 Parameters
+ 432 ----------
+ 433 partner : Obs or Corr
+ 434 partner to correlate the correlator with.
+ 435 Can either be an Obs which is correlated with all entries of the
+ 436 correlator or a Corr of same length.
+ 437 """
+ 438 if self.N != 1:
+ 439 raise Exception("Only one-dimensional correlators can be safely correlated.")
+ 440 new_content = []
+ 441 for x0, t_slice in enumerate(self.content):
+ 442 if _check_for_none(self, t_slice):
+ 443 new_content.append(None)
+ 444 else:
+ 445 if isinstance(partner, Corr):
+ 446 if _check_for_none(partner, partner.content[x0]):
+ 447 new_content.append(None)
+ 448 else:
+ 449 new_content.append(np.array([correlate(o, partner.content[x0][0]) for o in t_slice]))
+ 450 elif isinstance(partner, Obs): # Should this include CObs?
+ 451 new_content.append(np.array([correlate(o, partner) for o in t_slice]))
+ 452 else:
+ 453 raise Exception("Can only correlate with an Obs or a Corr.")
+ 454
+ 455 return Corr(new_content)
+ 456
+ 457 def reweight(self, weight, **kwargs):
+ 458 """Reweight the correlator.
459
- 460 def reweight(self, weight, **kwargs):
- 461 """Reweight the correlator.
- 462
- 463 Parameters
- 464 ----------
- 465 weight : Obs
- 466 Reweighting factor. An Observable that has to be defined on a superset of the
- 467 configurations in obs[i].idl for all i.
- 468 all_configs : bool
- 469 if True, the reweighted observables are normalized by the average of
- 470 the reweighting factor on all configurations in weight.idl and not
- 471 on the configurations in obs[i].idl.
- 472 """
- 473 if self.N != 1:
- 474 raise Exception("Reweighting only implemented for one-dimensional correlators.")
- 475 new_content = []
- 476 for t_slice in self.content:
- 477 if _check_for_none(self, t_slice):
- 478 new_content.append(None)
- 479 else:
- 480 new_content.append(np.array(reweight(weight, t_slice, **kwargs)))
- 481 return Corr(new_content)
+ 460 Parameters
+ 461 ----------
+ 462 weight : Obs
+ 463 Reweighting factor. An Observable that has to be defined on a superset of the
+ 464 configurations in obs[i].idl for all i.
+ 465 all_configs : bool
+ 466 if True, the reweighted observables are normalized by the average of
+ 467 the reweighting factor on all configurations in weight.idl and not
+ 468 on the configurations in obs[i].idl.
+ 469 """
+ 470 if self.N != 1:
+ 471 raise Exception("Reweighting only implemented for one-dimensional correlators.")
+ 472 new_content = []
+ 473 for t_slice in self.content:
+ 474 if _check_for_none(self, t_slice):
+ 475 new_content.append(None)
+ 476 else:
+ 477 new_content.append(np.array(reweight(weight, t_slice, **kwargs)))
+ 478 return Corr(new_content)
+ 479
+ 480 def T_symmetry(self, partner, parity=+1):
+ 481 """Return the time symmetry average of the correlator and its partner
482
- 483 def T_symmetry(self, partner, parity=+1):
- 484 """Return the time symmetry average of the correlator and its partner
- 485
- 486 Parameters
- 487 ----------
- 488 partner : Corr
- 489 Time symmetry partner of the Corr
- 490 partity : int
- 491 Parity quantum number of the correlator, can be +1 or -1
- 492 """
- 493 if self.N != 1:
- 494 raise Exception("T_symmetry only implemented for one-dimensional correlators.")
- 495 if not isinstance(partner, Corr):
- 496 raise Exception("T partner has to be a Corr object.")
- 497 if parity not in [+1, -1]:
- 498 raise Exception("Parity has to be +1 or -1.")
- 499 T_partner = parity * partner.reverse()
- 500
- 501 t_slices = []
- 502 test = (self - T_partner)
- 503 test.gamma_method()
- 504 for x0, t_slice in enumerate(test.content):
- 505 if t_slice is not None:
- 506 if not t_slice[0].is_zero_within_error(5):
- 507 t_slices.append(x0)
- 508 if t_slices:
- 509 warnings.warn("T symmetry partners do not agree within 5 sigma on time slices " + str(t_slices) + ".", RuntimeWarning)
- 510
- 511 return (self + T_partner) / 2
+ 483 Parameters
+ 484 ----------
+ 485 partner : Corr
+ 486 Time symmetry partner of the Corr
+ 487 partity : int
+ 488 Parity quantum number of the correlator, can be +1 or -1
+ 489 """
+ 490 if self.N != 1:
+ 491 raise Exception("T_symmetry only implemented for one-dimensional correlators.")
+ 492 if not isinstance(partner, Corr):
+ 493 raise Exception("T partner has to be a Corr object.")
+ 494 if parity not in [+1, -1]:
+ 495 raise Exception("Parity has to be +1 or -1.")
+ 496 T_partner = parity * partner.reverse()
+ 497
+ 498 t_slices = []
+ 499 test = (self - T_partner)
+ 500 test.gamma_method()
+ 501 for x0, t_slice in enumerate(test.content):
+ 502 if t_slice is not None:
+ 503 if not t_slice[0].is_zero_within_error(5):
+ 504 t_slices.append(x0)
+ 505 if t_slices:
+ 506 warnings.warn("T symmetry partners do not agree within 5 sigma on time slices " + str(t_slices) + ".", RuntimeWarning)
+ 507
+ 508 return (self + T_partner) / 2
+ 509
+ 510 def deriv(self, variant="symmetric"):
+ 511 """Return the first derivative of the correlator with respect to x0.
512
- 513 def deriv(self, variant="symmetric"):
- 514 """Return the first derivative of the correlator with respect to x0.
- 515
- 516 Parameters
- 517 ----------
- 518 variant : str
- 519 decides which definition of the finite differences derivative is used.
- 520 Available choice: symmetric, forward, backward, improved, log, default: symmetric
- 521 """
- 522 if self.N != 1:
- 523 raise Exception("deriv only implemented for one-dimensional correlators.")
- 524 if variant == "symmetric":
- 525 newcontent = []
- 526 for t in range(1, self.T - 1):
- 527 if (self.content[t - 1] is None) or (self.content[t + 1] is None):
- 528 newcontent.append(None)
- 529 else:
- 530 newcontent.append(0.5 * (self.content[t + 1] - self.content[t - 1]))
- 531 if (all([x is None for x in newcontent])):
- 532 raise Exception('Derivative is undefined at all timeslices')
- 533 return Corr(newcontent, padding=[1, 1])
- 534 elif variant == "forward":
- 535 newcontent = []
- 536 for t in range(self.T - 1):
- 537 if (self.content[t] is None) or (self.content[t + 1] is None):
- 538 newcontent.append(None)
- 539 else:
- 540 newcontent.append(self.content[t + 1] - self.content[t])
- 541 if (all([x is None for x in newcontent])):
- 542 raise Exception("Derivative is undefined at all timeslices")
- 543 return Corr(newcontent, padding=[0, 1])
- 544 elif variant == "backward":
- 545 newcontent = []
- 546 for t in range(1, self.T):
- 547 if (self.content[t - 1] is None) or (self.content[t] is None):
- 548 newcontent.append(None)
- 549 else:
- 550 newcontent.append(self.content[t] - self.content[t - 1])
- 551 if (all([x is None for x in newcontent])):
- 552 raise Exception("Derivative is undefined at all timeslices")
- 553 return Corr(newcontent, padding=[1, 0])
- 554 elif variant == "improved":
- 555 newcontent = []
- 556 for t in range(2, self.T - 2):
- 557 if (self.content[t - 2] is None) or (self.content[t - 1] is None) or (self.content[t + 1] is None) or (self.content[t + 2] is None):
- 558 newcontent.append(None)
- 559 else:
- 560 newcontent.append((1 / 12) * (self.content[t - 2] - 8 * self.content[t - 1] + 8 * self.content[t + 1] - self.content[t + 2]))
- 561 if (all([x is None for x in newcontent])):
- 562 raise Exception('Derivative is undefined at all timeslices')
- 563 return Corr(newcontent, padding=[2, 2])
- 564 elif variant == 'log':
- 565 newcontent = []
- 566 for t in range(self.T):
- 567 if (self.content[t] is None) or (self.content[t] <= 0):
- 568 newcontent.append(None)
- 569 else:
- 570 newcontent.append(np.log(self.content[t]))
- 571 if (all([x is None for x in newcontent])):
- 572 raise Exception("Log is undefined at all timeslices")
- 573 logcorr = Corr(newcontent)
- 574 return self * logcorr.deriv('symmetric')
- 575 else:
- 576 raise Exception("Unknown variant.")
+ 513 Parameters
+ 514 ----------
+ 515 variant : str
+ 516 decides which definition of the finite differences derivative is used.
+ 517 Available choice: symmetric, forward, backward, improved, log, default: symmetric
+ 518 """
+ 519 if self.N != 1:
+ 520 raise Exception("deriv only implemented for one-dimensional correlators.")
+ 521 if variant == "symmetric":
+ 522 newcontent = []
+ 523 for t in range(1, self.T - 1):
+ 524 if (self.content[t - 1] is None) or (self.content[t + 1] is None):
+ 525 newcontent.append(None)
+ 526 else:
+ 527 newcontent.append(0.5 * (self.content[t + 1] - self.content[t - 1]))
+ 528 if (all([x is None for x in newcontent])):
+ 529 raise Exception('Derivative is undefined at all timeslices')
+ 530 return Corr(newcontent, padding=[1, 1])
+ 531 elif variant == "forward":
+ 532 newcontent = []
+ 533 for t in range(self.T - 1):
+ 534 if (self.content[t] is None) or (self.content[t + 1] is None):
+ 535 newcontent.append(None)
+ 536 else:
+ 537 newcontent.append(self.content[t + 1] - self.content[t])
+ 538 if (all([x is None for x in newcontent])):
+ 539 raise Exception("Derivative is undefined at all timeslices")
+ 540 return Corr(newcontent, padding=[0, 1])
+ 541 elif variant == "backward":
+ 542 newcontent = []
+ 543 for t in range(1, self.T):
+ 544 if (self.content[t - 1] is None) or (self.content[t] is None):
+ 545 newcontent.append(None)
+ 546 else:
+ 547 newcontent.append(self.content[t] - self.content[t - 1])
+ 548 if (all([x is None for x in newcontent])):
+ 549 raise Exception("Derivative is undefined at all timeslices")
+ 550 return Corr(newcontent, padding=[1, 0])
+ 551 elif variant == "improved":
+ 552 newcontent = []
+ 553 for t in range(2, self.T - 2):
+ 554 if (self.content[t - 2] is None) or (self.content[t - 1] is None) or (self.content[t + 1] is None) or (self.content[t + 2] is None):
+ 555 newcontent.append(None)
+ 556 else:
+ 557 newcontent.append((1 / 12) * (self.content[t - 2] - 8 * self.content[t - 1] + 8 * self.content[t + 1] - self.content[t + 2]))
+ 558 if (all([x is None for x in newcontent])):
+ 559 raise Exception('Derivative is undefined at all timeslices')
+ 560 return Corr(newcontent, padding=[2, 2])
+ 561 elif variant == 'log':
+ 562 newcontent = []
+ 563 for t in range(self.T):
+ 564 if (self.content[t] is None) or (self.content[t] <= 0):
+ 565 newcontent.append(None)
+ 566 else:
+ 567 newcontent.append(np.log(self.content[t]))
+ 568 if (all([x is None for x in newcontent])):
+ 569 raise Exception("Log is undefined at all timeslices")
+ 570 logcorr = Corr(newcontent)
+ 571 return self * logcorr.deriv('symmetric')
+ 572 else:
+ 573 raise Exception("Unknown variant.")
+ 574
+ 575 def second_deriv(self, variant="symmetric"):
+ 576 """Return the second derivative of the correlator with respect to x0.
577
- 578 def second_deriv(self, variant="symmetric"):
- 579 """Return the second derivative of the correlator with respect to x0.
- 580
- 581 Parameters
- 582 ----------
- 583 variant : str
- 584 decides which definition of the finite differences derivative is used.
- 585 Available choice: symmetric, improved, log, default: symmetric
- 586 """
- 587 if self.N != 1:
- 588 raise Exception("second_deriv only implemented for one-dimensional correlators.")
- 589 if variant == "symmetric":
- 590 newcontent = []
- 591 for t in range(1, self.T - 1):
- 592 if (self.content[t - 1] is None) or (self.content[t + 1] is None):
- 593 newcontent.append(None)
- 594 else:
- 595 newcontent.append((self.content[t + 1] - 2 * self.content[t] + self.content[t - 1]))
- 596 if (all([x is None for x in newcontent])):
- 597 raise Exception("Derivative is undefined at all timeslices")
- 598 return Corr(newcontent, padding=[1, 1])
- 599 elif variant == "improved":
- 600 newcontent = []
- 601 for t in range(2, self.T - 2):
- 602 if (self.content[t - 2] is None) or (self.content[t - 1] is None) or (self.content[t] is None) or (self.content[t + 1] is None) or (self.content[t + 2] is None):
- 603 newcontent.append(None)
- 604 else:
- 605 newcontent.append((1 / 12) * (-self.content[t + 2] + 16 * self.content[t + 1] - 30 * self.content[t] + 16 * self.content[t - 1] - self.content[t - 2]))
- 606 if (all([x is None for x in newcontent])):
- 607 raise Exception("Derivative is undefined at all timeslices")
- 608 return Corr(newcontent, padding=[2, 2])
- 609 elif variant == 'log':
- 610 newcontent = []
- 611 for t in range(self.T):
- 612 if (self.content[t] is None) or (self.content[t] <= 0):
- 613 newcontent.append(None)
- 614 else:
- 615 newcontent.append(np.log(self.content[t]))
- 616 if (all([x is None for x in newcontent])):
- 617 raise Exception("Log is undefined at all timeslices")
- 618 logcorr = Corr(newcontent)
- 619 return self * (logcorr.second_deriv('symmetric') + (logcorr.deriv('symmetric'))**2)
- 620 else:
- 621 raise Exception("Unknown variant.")
+ 578 Parameters
+ 579 ----------
+ 580 variant : str
+ 581 decides which definition of the finite differences derivative is used.
+ 582 Available choice: symmetric, improved, log, default: symmetric
+ 583 """
+ 584 if self.N != 1:
+ 585 raise Exception("second_deriv only implemented for one-dimensional correlators.")
+ 586 if variant == "symmetric":
+ 587 newcontent = []
+ 588 for t in range(1, self.T - 1):
+ 589 if (self.content[t - 1] is None) or (self.content[t + 1] is None):
+ 590 newcontent.append(None)
+ 591 else:
+ 592 newcontent.append((self.content[t + 1] - 2 * self.content[t] + self.content[t - 1]))
+ 593 if (all([x is None for x in newcontent])):
+ 594 raise Exception("Derivative is undefined at all timeslices")
+ 595 return Corr(newcontent, padding=[1, 1])
+ 596 elif variant == "improved":
+ 597 newcontent = []
+ 598 for t in range(2, self.T - 2):
+ 599 if (self.content[t - 2] is None) or (self.content[t - 1] is None) or (self.content[t] is None) or (self.content[t + 1] is None) or (self.content[t + 2] is None):
+ 600 newcontent.append(None)
+ 601 else:
+ 602 newcontent.append((1 / 12) * (-self.content[t + 2] + 16 * self.content[t + 1] - 30 * self.content[t] + 16 * self.content[t - 1] - self.content[t - 2]))
+ 603 if (all([x is None for x in newcontent])):
+ 604 raise Exception("Derivative is undefined at all timeslices")
+ 605 return Corr(newcontent, padding=[2, 2])
+ 606 elif variant == 'log':
+ 607 newcontent = []
+ 608 for t in range(self.T):
+ 609 if (self.content[t] is None) or (self.content[t] <= 0):
+ 610 newcontent.append(None)
+ 611 else:
+ 612 newcontent.append(np.log(self.content[t]))
+ 613 if (all([x is None for x in newcontent])):
+ 614 raise Exception("Log is undefined at all timeslices")
+ 615 logcorr = Corr(newcontent)
+ 616 return self * (logcorr.second_deriv('symmetric') + (logcorr.deriv('symmetric'))**2)
+ 617 else:
+ 618 raise Exception("Unknown variant.")
+ 619
+ 620 def m_eff(self, variant='log', guess=1.0):
+ 621 """Returns the effective mass of the correlator as correlator object
622
- 623 def m_eff(self, variant='log', guess=1.0):
- 624 """Returns the effective mass of the correlator as correlator object
- 625
- 626 Parameters
- 627 ----------
- 628 variant : str
- 629 log : uses the standard effective mass log(C(t) / C(t+1))
- 630 cosh, periodic : Use periodicitiy of the correlator by solving C(t) / C(t+1) = cosh(m * (t - T/2)) / cosh(m * (t + 1 - T/2)) for m.
- 631 sinh : Use anti-periodicitiy of the correlator by solving C(t) / C(t+1) = sinh(m * (t - T/2)) / sinh(m * (t + 1 - T/2)) for m.
- 632 See, e.g., arXiv:1205.5380
- 633 arccosh : Uses the explicit form of the symmetrized correlator (not recommended)
- 634 logsym: uses the symmetric effective mass log(C(t-1) / C(t+1))/2
- 635 guess : float
- 636 guess for the root finder, only relevant for the root variant
- 637 """
- 638 if self.N != 1:
- 639 raise Exception('Correlator must be projected before getting m_eff')
- 640 if variant == 'log':
- 641 newcontent = []
- 642 for t in range(self.T - 1):
- 643 if ((self.content[t] is None) or (self.content[t + 1] is None)) or (self.content[t + 1][0].value == 0):
- 644 newcontent.append(None)
- 645 elif self.content[t][0].value / self.content[t + 1][0].value < 0:
- 646 newcontent.append(None)
- 647 else:
- 648 newcontent.append(self.content[t] / self.content[t + 1])
- 649 if (all([x is None for x in newcontent])):
- 650 raise Exception('m_eff is undefined at all timeslices')
- 651
- 652 return np.log(Corr(newcontent, padding=[0, 1]))
- 653
- 654 elif variant == 'logsym':
- 655 newcontent = []
- 656 for t in range(1, self.T - 1):
- 657 if ((self.content[t - 1] is None) or (self.content[t + 1] is None)) or (self.content[t + 1][0].value == 0):
- 658 newcontent.append(None)
- 659 elif self.content[t - 1][0].value / self.content[t + 1][0].value < 0:
- 660 newcontent.append(None)
- 661 else:
- 662 newcontent.append(self.content[t - 1] / self.content[t + 1])
- 663 if (all([x is None for x in newcontent])):
- 664 raise Exception('m_eff is undefined at all timeslices')
- 665
- 666 return np.log(Corr(newcontent, padding=[1, 1])) / 2
- 667
- 668 elif variant in ['periodic', 'cosh', 'sinh']:
- 669 if variant in ['periodic', 'cosh']:
- 670 func = anp.cosh
- 671 else:
- 672 func = anp.sinh
+ 623 Parameters
+ 624 ----------
+ 625 variant : str
+ 626 log : uses the standard effective mass log(C(t) / C(t+1))
+ 627 cosh, periodic : Use periodicitiy of the correlator by solving C(t) / C(t+1) = cosh(m * (t - T/2)) / cosh(m * (t + 1 - T/2)) for m.
+ 628 sinh : Use anti-periodicitiy of the correlator by solving C(t) / C(t+1) = sinh(m * (t - T/2)) / sinh(m * (t + 1 - T/2)) for m.
+ 629 See, e.g., arXiv:1205.5380
+ 630 arccosh : Uses the explicit form of the symmetrized correlator (not recommended)
+ 631 logsym: uses the symmetric effective mass log(C(t-1) / C(t+1))/2
+ 632 guess : float
+ 633 guess for the root finder, only relevant for the root variant
+ 634 """
+ 635 if self.N != 1:
+ 636 raise Exception('Correlator must be projected before getting m_eff')
+ 637 if variant == 'log':
+ 638 newcontent = []
+ 639 for t in range(self.T - 1):
+ 640 if ((self.content[t] is None) or (self.content[t + 1] is None)) or (self.content[t + 1][0].value == 0):
+ 641 newcontent.append(None)
+ 642 elif self.content[t][0].value / self.content[t + 1][0].value < 0:
+ 643 newcontent.append(None)
+ 644 else:
+ 645 newcontent.append(self.content[t] / self.content[t + 1])
+ 646 if (all([x is None for x in newcontent])):
+ 647 raise Exception('m_eff is undefined at all timeslices')
+ 648
+ 649 return np.log(Corr(newcontent, padding=[0, 1]))
+ 650
+ 651 elif variant == 'logsym':
+ 652 newcontent = []
+ 653 for t in range(1, self.T - 1):
+ 654 if ((self.content[t - 1] is None) or (self.content[t + 1] is None)) or (self.content[t + 1][0].value == 0):
+ 655 newcontent.append(None)
+ 656 elif self.content[t - 1][0].value / self.content[t + 1][0].value < 0:
+ 657 newcontent.append(None)
+ 658 else:
+ 659 newcontent.append(self.content[t - 1] / self.content[t + 1])
+ 660 if (all([x is None for x in newcontent])):
+ 661 raise Exception('m_eff is undefined at all timeslices')
+ 662
+ 663 return np.log(Corr(newcontent, padding=[1, 1])) / 2
+ 664
+ 665 elif variant in ['periodic', 'cosh', 'sinh']:
+ 666 if variant in ['periodic', 'cosh']:
+ 667 func = anp.cosh
+ 668 else:
+ 669 func = anp.sinh
+ 670
+ 671 def root_function(x, d):
+ 672 return func(x * (t - self.T / 2)) / func(x * (t + 1 - self.T / 2)) - d
673
- 674 def root_function(x, d):
- 675 return func(x * (t - self.T / 2)) / func(x * (t + 1 - self.T / 2)) - d
- 676
- 677 newcontent = []
- 678 for t in range(self.T - 1):
- 679 if (self.content[t] is None) or (self.content[t + 1] is None) or (self.content[t + 1][0].value == 0):
- 680 newcontent.append(None)
- 681 # Fill the two timeslices in the middle of the lattice with their predecessors
- 682 elif variant == 'sinh' and t in [self.T / 2, self.T / 2 - 1]:
- 683 newcontent.append(newcontent[-1])
- 684 elif self.content[t][0].value / self.content[t + 1][0].value < 0:
- 685 newcontent.append(None)
- 686 else:
- 687 newcontent.append(np.abs(find_root(self.content[t][0] / self.content[t + 1][0], root_function, guess=guess)))
- 688 if (all([x is None for x in newcontent])):
- 689 raise Exception('m_eff is undefined at all timeslices')
- 690
- 691 return Corr(newcontent, padding=[0, 1])
- 692
- 693 elif variant == 'arccosh':
- 694 newcontent = []
- 695 for t in range(1, self.T - 1):
- 696 if (self.content[t] is None) or (self.content[t + 1] is None) or (self.content[t - 1] is None) or (self.content[t][0].value == 0):
- 697 newcontent.append(None)
- 698 else:
- 699 newcontent.append((self.content[t + 1] + self.content[t - 1]) / (2 * self.content[t]))
- 700 if (all([x is None for x in newcontent])):
- 701 raise Exception("m_eff is undefined at all timeslices")
- 702 return np.arccosh(Corr(newcontent, padding=[1, 1]))
+ 674 newcontent = []
+ 675 for t in range(self.T - 1):
+ 676 if (self.content[t] is None) or (self.content[t + 1] is None) or (self.content[t + 1][0].value == 0):
+ 677 newcontent.append(None)
+ 678 # Fill the two timeslices in the middle of the lattice with their predecessors
+ 679 elif variant == 'sinh' and t in [self.T / 2, self.T / 2 - 1]:
+ 680 newcontent.append(newcontent[-1])
+ 681 elif self.content[t][0].value / self.content[t + 1][0].value < 0:
+ 682 newcontent.append(None)
+ 683 else:
+ 684 newcontent.append(np.abs(find_root(self.content[t][0] / self.content[t + 1][0], root_function, guess=guess)))
+ 685 if (all([x is None for x in newcontent])):
+ 686 raise Exception('m_eff is undefined at all timeslices')
+ 687
+ 688 return Corr(newcontent, padding=[0, 1])
+ 689
+ 690 elif variant == 'arccosh':
+ 691 newcontent = []
+ 692 for t in range(1, self.T - 1):
+ 693 if (self.content[t] is None) or (self.content[t + 1] is None) or (self.content[t - 1] is None) or (self.content[t][0].value == 0):
+ 694 newcontent.append(None)
+ 695 else:
+ 696 newcontent.append((self.content[t + 1] + self.content[t - 1]) / (2 * self.content[t]))
+ 697 if (all([x is None for x in newcontent])):
+ 698 raise Exception("m_eff is undefined at all timeslices")
+ 699 return np.arccosh(Corr(newcontent, padding=[1, 1]))
+ 700
+ 701 else:
+ 702 raise Exception('Unknown variant.')
703
- 704 else:
- 705 raise Exception('Unknown variant.')
+ 704 def fit(self, function, fitrange=None, silent=False, **kwargs):
+ 705 r'''Fits function to the data
706
- 707 def fit(self, function, fitrange=None, silent=False, **kwargs):
- 708 r'''Fits function to the data
- 709
- 710 Parameters
- 711 ----------
- 712 function : obj
- 713 function to fit to the data. See fits.least_squares for details.
- 714 fitrange : list
- 715 Two element list containing the timeslices on which the fit is supposed to start and stop.
- 716 Caution: This range is inclusive as opposed to standard python indexing.
- 717 `fitrange=[4, 6]` corresponds to the three entries 4, 5 and 6.
- 718 If not specified, self.prange or all timeslices are used.
- 719 silent : bool
- 720 Decides whether output is printed to the standard output.
- 721 '''
- 722 if self.N != 1:
- 723 raise Exception("Correlator must be projected before fitting")
- 724
- 725 if fitrange is None:
- 726 if self.prange:
- 727 fitrange = self.prange
- 728 else:
- 729 fitrange = [0, self.T - 1]
- 730 else:
- 731 if not isinstance(fitrange, list):
- 732 raise Exception("fitrange has to be a list with two elements")
- 733 if len(fitrange) != 2:
- 734 raise Exception("fitrange has to have exactly two elements [fit_start, fit_stop]")
- 735
- 736 xs = [x for x in range(fitrange[0], fitrange[1] + 1) if not self.content[x] is None]
- 737 ys = [self.content[x][0] for x in range(fitrange[0], fitrange[1] + 1) if not self.content[x] is None]
- 738 result = least_squares(xs, ys, function, silent=silent, **kwargs)
- 739 return result
+ 707 Parameters
+ 708 ----------
+ 709 function : obj
+ 710 function to fit to the data. See fits.least_squares for details.
+ 711 fitrange : list
+ 712 Two element list containing the timeslices on which the fit is supposed to start and stop.
+ 713 Caution: This range is inclusive as opposed to standard python indexing.
+ 714 `fitrange=[4, 6]` corresponds to the three entries 4, 5 and 6.
+ 715 If not specified, self.prange or all timeslices are used.
+ 716 silent : bool
+ 717 Decides whether output is printed to the standard output.
+ 718 '''
+ 719 if self.N != 1:
+ 720 raise Exception("Correlator must be projected before fitting")
+ 721
+ 722 if fitrange is None:
+ 723 if self.prange:
+ 724 fitrange = self.prange
+ 725 else:
+ 726 fitrange = [0, self.T - 1]
+ 727 else:
+ 728 if not isinstance(fitrange, list):
+ 729 raise Exception("fitrange has to be a list with two elements")
+ 730 if len(fitrange) != 2:
+ 731 raise Exception("fitrange has to have exactly two elements [fit_start, fit_stop]")
+ 732
+ 733 xs = [x for x in range(fitrange[0], fitrange[1] + 1) if not self.content[x] is None]
+ 734 ys = [self.content[x][0] for x in range(fitrange[0], fitrange[1] + 1) if not self.content[x] is None]
+ 735 result = least_squares(xs, ys, function, silent=silent, **kwargs)
+ 736 return result
+ 737
+ 738 def plateau(self, plateau_range=None, method="fit", auto_gamma=False):
+ 739 """ Extract a plateau value from a Corr object
740
- 741 def plateau(self, plateau_range=None, method="fit", auto_gamma=False):
- 742 """ Extract a plateau value from a Corr object
- 743
- 744 Parameters
- 745 ----------
- 746 plateau_range : list
- 747 list with two entries, indicating the first and the last timeslice
- 748 of the plateau region.
- 749 method : str
- 750 method to extract the plateau.
- 751 'fit' fits a constant to the plateau region
- 752 'avg', 'average' or 'mean' just average over the given timeslices.
- 753 auto_gamma : bool
- 754 apply gamma_method with default parameters to the Corr. Defaults to None
- 755 """
- 756 if not plateau_range:
- 757 if self.prange:
- 758 plateau_range = self.prange
- 759 else:
- 760 raise Exception("no plateau range provided")
- 761 if self.N != 1:
- 762 raise Exception("Correlator must be projected before getting a plateau.")
- 763 if (all([self.content[t] is None for t in range(plateau_range[0], plateau_range[1] + 1)])):
- 764 raise Exception("plateau is undefined at all timeslices in plateaurange.")
- 765 if auto_gamma:
- 766 self.gamma_method()
- 767 if method == "fit":
- 768 def const_func(a, t):
- 769 return a[0]
- 770 return self.fit(const_func, plateau_range)[0]
- 771 elif method in ["avg", "average", "mean"]:
- 772 returnvalue = np.mean([item[0] for item in self.content[plateau_range[0]:plateau_range[1] + 1] if item is not None])
- 773 return returnvalue
+ 741 Parameters
+ 742 ----------
+ 743 plateau_range : list
+ 744 list with two entries, indicating the first and the last timeslice
+ 745 of the plateau region.
+ 746 method : str
+ 747 method to extract the plateau.
+ 748 'fit' fits a constant to the plateau region
+ 749 'avg', 'average' or 'mean' just average over the given timeslices.
+ 750 auto_gamma : bool
+ 751 apply gamma_method with default parameters to the Corr. Defaults to None
+ 752 """
+ 753 if not plateau_range:
+ 754 if self.prange:
+ 755 plateau_range = self.prange
+ 756 else:
+ 757 raise Exception("no plateau range provided")
+ 758 if self.N != 1:
+ 759 raise Exception("Correlator must be projected before getting a plateau.")
+ 760 if (all([self.content[t] is None for t in range(plateau_range[0], plateau_range[1] + 1)])):
+ 761 raise Exception("plateau is undefined at all timeslices in plateaurange.")
+ 762 if auto_gamma:
+ 763 self.gamma_method()
+ 764 if method == "fit":
+ 765 def const_func(a, t):
+ 766 return a[0]
+ 767 return self.fit(const_func, plateau_range)[0]
+ 768 elif method in ["avg", "average", "mean"]:
+ 769 returnvalue = np.mean([item[0] for item in self.content[plateau_range[0]:plateau_range[1] + 1] if item is not None])
+ 770 return returnvalue
+ 771
+ 772 else:
+ 773 raise Exception("Unsupported plateau method: " + method)
774
- 775 else:
- 776 raise Exception("Unsupported plateau method: " + method)
- 777
- 778 def set_prange(self, prange):
- 779 """Sets the attribute prange of the Corr object."""
- 780 if not len(prange) == 2:
- 781 raise Exception("prange must be a list or array with two values")
- 782 if not ((isinstance(prange[0], int)) and (isinstance(prange[1], int))):
- 783 raise Exception("Start and end point must be integers")
- 784 if not (0 <= prange[0] <= self.T and 0 <= prange[1] <= self.T and prange[0] < prange[1]):
- 785 raise Exception("Start and end point must define a range in the interval 0,T")
+ 775 def set_prange(self, prange):
+ 776 """Sets the attribute prange of the Corr object."""
+ 777 if not len(prange) == 2:
+ 778 raise Exception("prange must be a list or array with two values")
+ 779 if not ((isinstance(prange[0], int)) and (isinstance(prange[1], int))):
+ 780 raise Exception("Start and end point must be integers")
+ 781 if not (0 <= prange[0] <= self.T and 0 <= prange[1] <= self.T and prange[0] < prange[1]):
+ 782 raise Exception("Start and end point must define a range in the interval 0,T")
+ 783
+ 784 self.prange = prange
+ 785 return
786
- 787 self.prange = prange
- 788 return
+ 787 def show(self, x_range=None, comp=None, y_range=None, logscale=False, plateau=None, fit_res=None, ylabel=None, save=None, auto_gamma=False, hide_sigma=None, references=None, title=None):
+ 788 """Plots the correlator using the tag of the correlator as label if available.
789
- 790 def show(self, x_range=None, comp=None, y_range=None, logscale=False, plateau=None, fit_res=None, ylabel=None, save=None, auto_gamma=False, hide_sigma=None, references=None, title=None):
- 791 """Plots the correlator using the tag of the correlator as label if available.
- 792
- 793 Parameters
- 794 ----------
- 795 x_range : list
- 796 list of two values, determining the range of the x-axis e.g. [4, 8].
- 797 comp : Corr or list of Corr
- 798 Correlator or list of correlators which are plotted for comparison.
- 799 The tags of these correlators are used as labels if available.
- 800 logscale : bool
- 801 Sets y-axis to logscale.
- 802 plateau : Obs
- 803 Plateau value to be visualized in the figure.
- 804 fit_res : Fit_result
- 805 Fit_result object to be visualized.
- 806 ylabel : str
- 807 Label for the y-axis.
- 808 save : str
- 809 path to file in which the figure should be saved.
- 810 auto_gamma : bool
- 811 Apply the gamma method with standard parameters to all correlators and plateau values before plotting.
- 812 hide_sigma : float
- 813 Hides data points from the first value on which is consistent with zero within 'hide_sigma' standard errors.
- 814 references : list
- 815 List of floating point values that are displayed as horizontal lines for reference.
- 816 title : string
- 817 Optional title of the figure.
- 818 """
- 819 if self.N != 1:
- 820 raise Exception("Correlator must be projected before plotting")
+ 790 Parameters
+ 791 ----------
+ 792 x_range : list
+ 793 list of two values, determining the range of the x-axis e.g. [4, 8].
+ 794 comp : Corr or list of Corr
+ 795 Correlator or list of correlators which are plotted for comparison.
+ 796 The tags of these correlators are used as labels if available.
+ 797 logscale : bool
+ 798 Sets y-axis to logscale.
+ 799 plateau : Obs
+ 800 Plateau value to be visualized in the figure.
+ 801 fit_res : Fit_result
+ 802 Fit_result object to be visualized.
+ 803 ylabel : str
+ 804 Label for the y-axis.
+ 805 save : str
+ 806 path to file in which the figure should be saved.
+ 807 auto_gamma : bool
+ 808 Apply the gamma method with standard parameters to all correlators and plateau values before plotting.
+ 809 hide_sigma : float
+ 810 Hides data points from the first value on which is consistent with zero within 'hide_sigma' standard errors.
+ 811 references : list
+ 812 List of floating point values that are displayed as horizontal lines for reference.
+ 813 title : string
+ 814 Optional title of the figure.
+ 815 """
+ 816 if self.N != 1:
+ 817 raise Exception("Correlator must be projected before plotting")
+ 818
+ 819 if auto_gamma:
+ 820 self.gamma_method()
821
- 822 if auto_gamma:
- 823 self.gamma_method()
+ 822 if x_range is None:
+ 823 x_range = [0, self.T - 1]
824
- 825 if x_range is None:
- 826 x_range = [0, self.T - 1]
+ 825 fig = plt.figure()
+ 826 ax1 = fig.add_subplot(111)
827
- 828 fig = plt.figure()
- 829 ax1 = fig.add_subplot(111)
- 830
- 831 x, y, y_err = self.plottable()
- 832 if hide_sigma:
- 833 hide_from = np.argmax((hide_sigma * np.array(y_err[1:])) > np.abs(y[1:])) - 1
- 834 else:
- 835 hide_from = None
- 836 ax1.errorbar(x[:hide_from], y[:hide_from], y_err[:hide_from], label=self.tag)
- 837 if logscale:
- 838 ax1.set_yscale('log')
- 839 else:
- 840 if y_range is None:
- 841 try:
- 842 y_min = min([(x[0].value - x[0].dvalue) for x in self.content[x_range[0]: x_range[1] + 1] if (x is not None) and x[0].dvalue < 2 * np.abs(x[0].value)])
- 843 y_max = max([(x[0].value + x[0].dvalue) for x in self.content[x_range[0]: x_range[1] + 1] if (x is not None) and x[0].dvalue < 2 * np.abs(x[0].value)])
- 844 ax1.set_ylim([y_min - 0.1 * (y_max - y_min), y_max + 0.1 * (y_max - y_min)])
- 845 except Exception:
- 846 pass
- 847 else:
- 848 ax1.set_ylim(y_range)
- 849 if comp:
- 850 if isinstance(comp, (Corr, list)):
- 851 for corr in comp if isinstance(comp, list) else [comp]:
- 852 if auto_gamma:
- 853 corr.gamma_method()
- 854 x, y, y_err = corr.plottable()
- 855 if hide_sigma:
- 856 hide_from = np.argmax((hide_sigma * np.array(y_err[1:])) > np.abs(y[1:])) - 1
- 857 else:
- 858 hide_from = None
- 859 ax1.errorbar(x[:hide_from], y[:hide_from], y_err[:hide_from], label=corr.tag, mfc=plt.rcParams['axes.facecolor'])
- 860 else:
- 861 raise Exception("'comp' must be a correlator or a list of correlators.")
- 862
- 863 if plateau:
- 864 if isinstance(plateau, Obs):
- 865 if auto_gamma:
- 866 plateau.gamma_method()
- 867 ax1.axhline(y=plateau.value, linewidth=2, color=plt.rcParams['text.color'], alpha=0.6, marker=',', ls='--', label=str(plateau))
- 868 ax1.axhspan(plateau.value - plateau.dvalue, plateau.value + plateau.dvalue, alpha=0.25, color=plt.rcParams['text.color'], ls='-')
- 869 else:
- 870 raise Exception("'plateau' must be an Obs")
- 871
- 872 if references:
- 873 if isinstance(references, list):
- 874 for ref in references:
- 875 ax1.axhline(y=ref, linewidth=1, color=plt.rcParams['text.color'], alpha=0.6, marker=',', ls='--')
- 876 else:
- 877 raise Exception("'references' must be a list of floating pint values.")
- 878
- 879 if self.prange:
- 880 ax1.axvline(self.prange[0], 0, 1, ls='-', marker=',')
- 881 ax1.axvline(self.prange[1], 0, 1, ls='-', marker=',')
- 882
- 883 if fit_res:
- 884 x_samples = np.arange(x_range[0], x_range[1] + 1, 0.05)
- 885 ax1.plot(x_samples,
- 886 fit_res.fit_function([o.value for o in fit_res.fit_parameters], x_samples),
- 887 ls='-', marker=',', lw=2)
- 888
- 889 ax1.set_xlabel(r'$x_0 / a$')
- 890 if ylabel:
- 891 ax1.set_ylabel(ylabel)
- 892 ax1.set_xlim([x_range[0] - 0.5, x_range[1] + 0.5])
- 893
- 894 handles, labels = ax1.get_legend_handles_labels()
- 895 if labels:
- 896 ax1.legend()
+ 828 x, y, y_err = self.plottable()
+ 829 if hide_sigma:
+ 830 hide_from = np.argmax((hide_sigma * np.array(y_err[1:])) > np.abs(y[1:])) - 1
+ 831 else:
+ 832 hide_from = None
+ 833 ax1.errorbar(x[:hide_from], y[:hide_from], y_err[:hide_from], label=self.tag)
+ 834 if logscale:
+ 835 ax1.set_yscale('log')
+ 836 else:
+ 837 if y_range is None:
+ 838 try:
+ 839 y_min = min([(x[0].value - x[0].dvalue) for x in self.content[x_range[0]: x_range[1] + 1] if (x is not None) and x[0].dvalue < 2 * np.abs(x[0].value)])
+ 840 y_max = max([(x[0].value + x[0].dvalue) for x in self.content[x_range[0]: x_range[1] + 1] if (x is not None) and x[0].dvalue < 2 * np.abs(x[0].value)])
+ 841 ax1.set_ylim([y_min - 0.1 * (y_max - y_min), y_max + 0.1 * (y_max - y_min)])
+ 842 except Exception:
+ 843 pass
+ 844 else:
+ 845 ax1.set_ylim(y_range)
+ 846 if comp:
+ 847 if isinstance(comp, (Corr, list)):
+ 848 for corr in comp if isinstance(comp, list) else [comp]:
+ 849 if auto_gamma:
+ 850 corr.gamma_method()
+ 851 x, y, y_err = corr.plottable()
+ 852 if hide_sigma:
+ 853 hide_from = np.argmax((hide_sigma * np.array(y_err[1:])) > np.abs(y[1:])) - 1
+ 854 else:
+ 855 hide_from = None
+ 856 ax1.errorbar(x[:hide_from], y[:hide_from], y_err[:hide_from], label=corr.tag, mfc=plt.rcParams['axes.facecolor'])
+ 857 else:
+ 858 raise Exception("'comp' must be a correlator or a list of correlators.")
+ 859
+ 860 if plateau:
+ 861 if isinstance(plateau, Obs):
+ 862 if auto_gamma:
+ 863 plateau.gamma_method()
+ 864 ax1.axhline(y=plateau.value, linewidth=2, color=plt.rcParams['text.color'], alpha=0.6, marker=',', ls='--', label=str(plateau))
+ 865 ax1.axhspan(plateau.value - plateau.dvalue, plateau.value + plateau.dvalue, alpha=0.25, color=plt.rcParams['text.color'], ls='-')
+ 866 else:
+ 867 raise Exception("'plateau' must be an Obs")
+ 868
+ 869 if references:
+ 870 if isinstance(references, list):
+ 871 for ref in references:
+ 872 ax1.axhline(y=ref, linewidth=1, color=plt.rcParams['text.color'], alpha=0.6, marker=',', ls='--')
+ 873 else:
+ 874 raise Exception("'references' must be a list of floating pint values.")
+ 875
+ 876 if self.prange:
+ 877 ax1.axvline(self.prange[0], 0, 1, ls='-', marker=',')
+ 878 ax1.axvline(self.prange[1], 0, 1, ls='-', marker=',')
+ 879
+ 880 if fit_res:
+ 881 x_samples = np.arange(x_range[0], x_range[1] + 1, 0.05)
+ 882 ax1.plot(x_samples,
+ 883 fit_res.fit_function([o.value for o in fit_res.fit_parameters], x_samples),
+ 884 ls='-', marker=',', lw=2)
+ 885
+ 886 ax1.set_xlabel(r'$x_0 / a$')
+ 887 if ylabel:
+ 888 ax1.set_ylabel(ylabel)
+ 889 ax1.set_xlim([x_range[0] - 0.5, x_range[1] + 0.5])
+ 890
+ 891 handles, labels = ax1.get_legend_handles_labels()
+ 892 if labels:
+ 893 ax1.legend()
+ 894
+ 895 if title:
+ 896 plt.title(title)
897
- 898 if title:
- 899 plt.title(title)
- 900
- 901 plt.draw()
- 902
- 903 if save:
- 904 if isinstance(save, str):
- 905 fig.savefig(save, bbox_inches='tight')
- 906 else:
- 907 raise Exception("'save' has to be a string.")
+ 898 plt.draw()
+ 899
+ 900 if save:
+ 901 if isinstance(save, str):
+ 902 fig.savefig(save, bbox_inches='tight')
+ 903 else:
+ 904 raise Exception("'save' has to be a string.")
+ 905
+ 906 def spaghetti_plot(self, logscale=True):
+ 907 """Produces a spaghetti plot of the correlator suited to monitor exceptional configurations.
908
- 909 def spaghetti_plot(self, logscale=True):
- 910 """Produces a spaghetti plot of the correlator suited to monitor exceptional configurations.
- 911
- 912 Parameters
- 913 ----------
- 914 logscale : bool
- 915 Determines whether the scale of the y-axis is logarithmic or standard.
- 916 """
- 917 if self.N != 1:
- 918 raise Exception("Correlator needs to be projected first.")
+ 909 Parameters
+ 910 ----------
+ 911 logscale : bool
+ 912 Determines whether the scale of the y-axis is logarithmic or standard.
+ 913 """
+ 914 if self.N != 1:
+ 915 raise Exception("Correlator needs to be projected first.")
+ 916
+ 917 mc_names = list(set([item for sublist in [sum(map(o[0].e_content.get, o[0].mc_names), []) for o in self.content if o is not None] for item in sublist]))
+ 918 x0_vals = [n for (n, o) in zip(np.arange(self.T), self.content) if o is not None]
919
- 920 mc_names = list(set([item for sublist in [sum(map(o[0].e_content.get, o[0].mc_names), []) for o in self.content if o is not None] for item in sublist]))
- 921 x0_vals = [n for (n, o) in zip(np.arange(self.T), self.content) if o is not None]
+ 920 for name in mc_names:
+ 921 data = np.array([o[0].deltas[name] + o[0].r_values[name] for o in self.content if o is not None]).T
922
- 923 for name in mc_names:
- 924 data = np.array([o[0].deltas[name] + o[0].r_values[name] for o in self.content if o is not None]).T
- 925
- 926 fig = plt.figure()
- 927 ax = fig.add_subplot(111)
- 928 for dat in data:
- 929 ax.plot(x0_vals, dat, ls='-', marker='')
+ 923 fig = plt.figure()
+ 924 ax = fig.add_subplot(111)
+ 925 for dat in data:
+ 926 ax.plot(x0_vals, dat, ls='-', marker='')
+ 927
+ 928 if logscale is True:
+ 929 ax.set_yscale('log')
930
- 931 if logscale is True:
- 932 ax.set_yscale('log')
- 933
- 934 ax.set_xlabel(r'$x_0 / a$')
- 935 plt.title(name)
- 936 plt.draw()
- 937
- 938 def dump(self, filename, datatype="json.gz", **kwargs):
- 939 """Dumps the Corr into a file of chosen type
- 940 Parameters
- 941 ----------
- 942 filename : str
- 943 Name of the file to be saved.
- 944 datatype : str
- 945 Format of the exported file. Supported formats include
- 946 "json.gz" and "pickle"
- 947 path : str
- 948 specifies a custom path for the file (default '.')
- 949 """
- 950 if datatype == "json.gz":
- 951 from .input.json import dump_to_json
- 952 if 'path' in kwargs:
- 953 file_name = kwargs.get('path') + '/' + filename
- 954 else:
- 955 file_name = filename
- 956 dump_to_json(self, file_name)
- 957 elif datatype == "pickle":
- 958 dump_object(self, filename, **kwargs)
- 959 else:
- 960 raise Exception("Unknown datatype " + str(datatype))
+ 931 ax.set_xlabel(r'$x_0 / a$')
+ 932 plt.title(name)
+ 933 plt.draw()
+ 934
+ 935 def dump(self, filename, datatype="json.gz", **kwargs):
+ 936 """Dumps the Corr into a file of chosen type
+ 937 Parameters
+ 938 ----------
+ 939 filename : str
+ 940 Name of the file to be saved.
+ 941 datatype : str
+ 942 Format of the exported file. Supported formats include
+ 943 "json.gz" and "pickle"
+ 944 path : str
+ 945 specifies a custom path for the file (default '.')
+ 946 """
+ 947 if datatype == "json.gz":
+ 948 from .input.json import dump_to_json
+ 949 if 'path' in kwargs:
+ 950 file_name = kwargs.get('path') + '/' + filename
+ 951 else:
+ 952 file_name = filename
+ 953 dump_to_json(self, file_name)
+ 954 elif datatype == "pickle":
+ 955 dump_object(self, filename, **kwargs)
+ 956 else:
+ 957 raise Exception("Unknown datatype " + str(datatype))
+ 958
+ 959 def print(self, print_range=None):
+ 960 print(self.__repr__(print_range))
961
- 962 def print(self, print_range=None):
- 963 print(self.__repr__(print_range))
- 964
- 965 def __repr__(self, print_range=None):
- 966 if print_range is None:
- 967 print_range = [0, None]
+ 962 def __repr__(self, print_range=None):
+ 963 if print_range is None:
+ 964 print_range = [0, None]
+ 965
+ 966 content_string = ""
+ 967 content_string += "Corr T=" + str(self.T) + " N=" + str(self.N) + "\n" # +" filled with"+ str(type(self.content[0][0])) there should be a good solution here
968
- 969 content_string = ""
- 970 content_string += "Corr T=" + str(self.T) + " N=" + str(self.N) + "\n" # +" filled with"+ str(type(self.content[0][0])) there should be a good solution here
- 971
- 972 if self.tag is not None:
- 973 content_string += "Description: " + self.tag + "\n"
- 974 if self.N != 1:
- 975 return content_string
- 976
- 977 if print_range[1]:
- 978 print_range[1] += 1
- 979 content_string += 'x0/a\tCorr(x0/a)\n------------------\n'
- 980 for i, sub_corr in enumerate(self.content[print_range[0]:print_range[1]]):
- 981 if sub_corr is None:
- 982 content_string += str(i + print_range[0]) + '\n'
- 983 else:
- 984 content_string += str(i + print_range[0])
- 985 for element in sub_corr:
- 986 content_string += '\t' + ' ' * int(element >= 0) + str(element)
- 987 content_string += '\n'
- 988 return content_string
+ 969 if self.tag is not None:
+ 970 content_string += "Description: " + self.tag + "\n"
+ 971 if self.N != 1:
+ 972 return content_string
+ 973
+ 974 if print_range[1]:
+ 975 print_range[1] += 1
+ 976 content_string += 'x0/a\tCorr(x0/a)\n------------------\n'
+ 977 for i, sub_corr in enumerate(self.content[print_range[0]:print_range[1]]):
+ 978 if sub_corr is None:
+ 979 content_string += str(i + print_range[0]) + '\n'
+ 980 else:
+ 981 content_string += str(i + print_range[0])
+ 982 for element in sub_corr:
+ 983 content_string += '\t' + ' ' * int(element >= 0) + str(element)
+ 984 content_string += '\n'
+ 985 return content_string
+ 986
+ 987 def __str__(self):
+ 988 return self.__repr__()
989
- 990 def __str__(self):
- 991 return self.__repr__()
- 992
- 993 # We define the basic operations, that can be performed with correlators.
- 994 # While */+- get defined here, they only work for Corr*Obs and not Obs*Corr.
- 995 # This is because Obs*Corr checks Obs.__mul__ first and does not catch an exception.
- 996 # One could try and tell Obs to check if the y in __mul__ is a Corr and
- 997
- 998 def __add__(self, y):
- 999 if isinstance(y, Corr):
-1000 if ((self.N != y.N) or (self.T != y.T)):
-1001 raise Exception("Addition of Corrs with different shape")
-1002 newcontent = []
-1003 for t in range(self.T):
-1004 if _check_for_none(self, self.content[t]) or _check_for_none(y, y.content[t]):
-1005 newcontent.append(None)
-1006 else:
-1007 newcontent.append(self.content[t] + y.content[t])
-1008 return Corr(newcontent)
-1009
-1010 elif isinstance(y, (Obs, int, float, CObs)):
-1011 newcontent = []
-1012 for t in range(self.T):
-1013 if _check_for_none(self, self.content[t]):
-1014 newcontent.append(None)
-1015 else:
-1016 newcontent.append(self.content[t] + y)
-1017 return Corr(newcontent, prange=self.prange)
-1018 elif isinstance(y, np.ndarray):
-1019 if y.shape == (self.T,):
-1020 return Corr(list((np.array(self.content).T + y).T))
-1021 else:
-1022 raise ValueError("operands could not be broadcast together")
-1023 else:
-1024 raise TypeError("Corr + wrong type")
-1025
-1026 def __mul__(self, y):
-1027 if isinstance(y, Corr):
-1028 if not ((self.N == 1 or y.N == 1 or self.N == y.N) and self.T == y.T):
-1029 raise Exception("Multiplication of Corr object requires N=N or N=1 and T=T")
-1030 newcontent = []
-1031 for t in range(self.T):
-1032 if _check_for_none(self, self.content[t]) or _check_for_none(y, y.content[t]):
-1033 newcontent.append(None)
-1034 else:
-1035 newcontent.append(self.content[t] * y.content[t])
-1036 return Corr(newcontent)
-1037
-1038 elif isinstance(y, (Obs, int, float, CObs)):
-1039 newcontent = []
-1040 for t in range(self.T):
-1041 if _check_for_none(self, self.content[t]):
-1042 newcontent.append(None)
-1043 else:
-1044 newcontent.append(self.content[t] * y)
-1045 return Corr(newcontent, prange=self.prange)
-1046 elif isinstance(y, np.ndarray):
-1047 if y.shape == (self.T,):
-1048 return Corr(list((np.array(self.content).T * y).T))
-1049 else:
-1050 raise ValueError("operands could not be broadcast together")
-1051 else:
-1052 raise TypeError("Corr * wrong type")
-1053
-1054 def __truediv__(self, y):
-1055 if isinstance(y, Corr):
-1056 if not ((self.N == 1 or y.N == 1 or self.N == y.N) and self.T == y.T):
-1057 raise Exception("Multiplication of Corr object requires N=N or N=1 and T=T")
-1058 newcontent = []
-1059 for t in range(self.T):
-1060 if _check_for_none(self, self.content[t]) or _check_for_none(y, y.content[t]):
-1061 newcontent.append(None)
-1062 else:
-1063 newcontent.append(self.content[t] / y.content[t])
-1064 for t in range(self.T):
-1065 if _check_for_none(self, newcontent[t]):
-1066 continue
-1067 if np.isnan(np.sum(newcontent[t]).value):
-1068 newcontent[t] = None
-1069
-1070 if all([item is None for item in newcontent]):
-1071 raise Exception("Division returns completely undefined correlator")
-1072 return Corr(newcontent)
-1073
-1074 elif isinstance(y, (Obs, CObs)):
-1075 if isinstance(y, Obs):
-1076 if y.value == 0:
+ 990 # We define the basic operations, that can be performed with correlators.
+ 991 # While */+- get defined here, they only work for Corr*Obs and not Obs*Corr.
+ 992 # This is because Obs*Corr checks Obs.__mul__ first and does not catch an exception.
+ 993 # One could try and tell Obs to check if the y in __mul__ is a Corr and
+ 994
+ 995 def __add__(self, y):
+ 996 if isinstance(y, Corr):
+ 997 if ((self.N != y.N) or (self.T != y.T)):
+ 998 raise Exception("Addition of Corrs with different shape")
+ 999 newcontent = []
+1000 for t in range(self.T):
+1001 if _check_for_none(self, self.content[t]) or _check_for_none(y, y.content[t]):
+1002 newcontent.append(None)
+1003 else:
+1004 newcontent.append(self.content[t] + y.content[t])
+1005 return Corr(newcontent)
+1006
+1007 elif isinstance(y, (Obs, int, float, CObs)):
+1008 newcontent = []
+1009 for t in range(self.T):
+1010 if _check_for_none(self, self.content[t]):
+1011 newcontent.append(None)
+1012 else:
+1013 newcontent.append(self.content[t] + y)
+1014 return Corr(newcontent, prange=self.prange)
+1015 elif isinstance(y, np.ndarray):
+1016 if y.shape == (self.T,):
+1017 return Corr(list((np.array(self.content).T + y).T))
+1018 else:
+1019 raise ValueError("operands could not be broadcast together")
+1020 else:
+1021 raise TypeError("Corr + wrong type")
+1022
+1023 def __mul__(self, y):
+1024 if isinstance(y, Corr):
+1025 if not ((self.N == 1 or y.N == 1 or self.N == y.N) and self.T == y.T):
+1026 raise Exception("Multiplication of Corr object requires N=N or N=1 and T=T")
+1027 newcontent = []
+1028 for t in range(self.T):
+1029 if _check_for_none(self, self.content[t]) or _check_for_none(y, y.content[t]):
+1030 newcontent.append(None)
+1031 else:
+1032 newcontent.append(self.content[t] * y.content[t])
+1033 return Corr(newcontent)
+1034
+1035 elif isinstance(y, (Obs, int, float, CObs)):
+1036 newcontent = []
+1037 for t in range(self.T):
+1038 if _check_for_none(self, self.content[t]):
+1039 newcontent.append(None)
+1040 else:
+1041 newcontent.append(self.content[t] * y)
+1042 return Corr(newcontent, prange=self.prange)
+1043 elif isinstance(y, np.ndarray):
+1044 if y.shape == (self.T,):
+1045 return Corr(list((np.array(self.content).T * y).T))
+1046 else:
+1047 raise ValueError("operands could not be broadcast together")
+1048 else:
+1049 raise TypeError("Corr * wrong type")
+1050
+1051 def __truediv__(self, y):
+1052 if isinstance(y, Corr):
+1053 if not ((self.N == 1 or y.N == 1 or self.N == y.N) and self.T == y.T):
+1054 raise Exception("Multiplication of Corr object requires N=N or N=1 and T=T")
+1055 newcontent = []
+1056 for t in range(self.T):
+1057 if _check_for_none(self, self.content[t]) or _check_for_none(y, y.content[t]):
+1058 newcontent.append(None)
+1059 else:
+1060 newcontent.append(self.content[t] / y.content[t])
+1061 for t in range(self.T):
+1062 if _check_for_none(self, newcontent[t]):
+1063 continue
+1064 if np.isnan(np.sum(newcontent[t]).value):
+1065 newcontent[t] = None
+1066
+1067 if all([item is None for item in newcontent]):
+1068 raise Exception("Division returns completely undefined correlator")
+1069 return Corr(newcontent)
+1070
+1071 elif isinstance(y, (Obs, CObs)):
+1072 if isinstance(y, Obs):
+1073 if y.value == 0:
+1074 raise Exception('Division by zero will return undefined correlator')
+1075 if isinstance(y, CObs):
+1076 if y.is_zero():
1077 raise Exception('Division by zero will return undefined correlator')
-1078 if isinstance(y, CObs):
-1079 if y.is_zero():
-1080 raise Exception('Division by zero will return undefined correlator')
-1081
-1082 newcontent = []
-1083 for t in range(self.T):
-1084 if _check_for_none(self, self.content[t]):
-1085 newcontent.append(None)
-1086 else:
-1087 newcontent.append(self.content[t] / y)
-1088 return Corr(newcontent, prange=self.prange)
-1089
-1090 elif isinstance(y, (int, float)):
-1091 if y == 0:
-1092 raise Exception('Division by zero will return undefined correlator')
-1093 newcontent = []
-1094 for t in range(self.T):
-1095 if _check_for_none(self, self.content[t]):
-1096 newcontent.append(None)
-1097 else:
-1098 newcontent.append(self.content[t] / y)
-1099 return Corr(newcontent, prange=self.prange)
-1100 elif isinstance(y, np.ndarray):
-1101 if y.shape == (self.T,):
-1102 return Corr(list((np.array(self.content).T / y).T))
-1103 else:
-1104 raise ValueError("operands could not be broadcast together")
-1105 else:
-1106 raise TypeError('Corr / wrong type')
-1107
-1108 def __neg__(self):
-1109 newcontent = [None if _check_for_none(self, item) else -1. * item for item in self.content]
-1110 return Corr(newcontent, prange=self.prange)
+1078
+1079 newcontent = []
+1080 for t in range(self.T):
+1081 if _check_for_none(self, self.content[t]):
+1082 newcontent.append(None)
+1083 else:
+1084 newcontent.append(self.content[t] / y)
+1085 return Corr(newcontent, prange=self.prange)
+1086
+1087 elif isinstance(y, (int, float)):
+1088 if y == 0:
+1089 raise Exception('Division by zero will return undefined correlator')
+1090 newcontent = []
+1091 for t in range(self.T):
+1092 if _check_for_none(self, self.content[t]):
+1093 newcontent.append(None)
+1094 else:
+1095 newcontent.append(self.content[t] / y)
+1096 return Corr(newcontent, prange=self.prange)
+1097 elif isinstance(y, np.ndarray):
+1098 if y.shape == (self.T,):
+1099 return Corr(list((np.array(self.content).T / y).T))
+1100 else:
+1101 raise ValueError("operands could not be broadcast together")
+1102 else:
+1103 raise TypeError('Corr / wrong type')
+1104
+1105 def __neg__(self):
+1106 newcontent = [None if _check_for_none(self, item) else -1. * item for item in self.content]
+1107 return Corr(newcontent, prange=self.prange)
+1108
+1109 def __sub__(self, y):
+1110 return self + (-y)
1111
-1112 def __sub__(self, y):
-1113 return self + (-y)
-1114
-1115 def __pow__(self, y):
-1116 if isinstance(y, (Obs, int, float, CObs)):
-1117 newcontent = [None if _check_for_none(self, item) else item**y for item in self.content]
-1118 return Corr(newcontent, prange=self.prange)
-1119 else:
-1120 raise TypeError('Type of exponent not supported')
-1121
-1122 def __abs__(self):
-1123 newcontent = [None if _check_for_none(self, item) else np.abs(item) for item in self.content]
-1124 return Corr(newcontent, prange=self.prange)
-1125
-1126 # The numpy functions:
-1127 def sqrt(self):
-1128 return self ** 0.5
-1129
-1130 def log(self):
-1131 newcontent = [None if _check_for_none(self, item) else np.log(item) for item in self.content]
-1132 return Corr(newcontent, prange=self.prange)
-1133
-1134 def exp(self):
-1135 newcontent = [None if _check_for_none(self, item) else np.exp(item) for item in self.content]
-1136 return Corr(newcontent, prange=self.prange)
-1137
-1138 def _apply_func_to_corr(self, func):
-1139 newcontent = [None if _check_for_none(self, item) else func(item) for item in self.content]
-1140 for t in range(self.T):
-1141 if _check_for_none(self, newcontent[t]):
-1142 continue
-1143 if np.isnan(np.sum(newcontent[t]).value):
-1144 newcontent[t] = None
-1145 if all([item is None for item in newcontent]):
-1146 raise Exception('Operation returns undefined correlator')
-1147 return Corr(newcontent)
+1112 def __pow__(self, y):
+1113 if isinstance(y, (Obs, int, float, CObs)):
+1114 newcontent = [None if _check_for_none(self, item) else item**y for item in self.content]
+1115 return Corr(newcontent, prange=self.prange)
+1116 else:
+1117 raise TypeError('Type of exponent not supported')
+1118
+1119 def __abs__(self):
+1120 newcontent = [None if _check_for_none(self, item) else np.abs(item) for item in self.content]
+1121 return Corr(newcontent, prange=self.prange)
+1122
+1123 # The numpy functions:
+1124 def sqrt(self):
+1125 return self ** 0.5
+1126
+1127 def log(self):
+1128 newcontent = [None if _check_for_none(self, item) else np.log(item) for item in self.content]
+1129 return Corr(newcontent, prange=self.prange)
+1130
+1131 def exp(self):
+1132 newcontent = [None if _check_for_none(self, item) else np.exp(item) for item in self.content]
+1133 return Corr(newcontent, prange=self.prange)
+1134
+1135 def _apply_func_to_corr(self, func):
+1136 newcontent = [None if _check_for_none(self, item) else func(item) for item in self.content]
+1137 for t in range(self.T):
+1138 if _check_for_none(self, newcontent[t]):
+1139 continue
+1140 if np.isnan(np.sum(newcontent[t]).value):
+1141 newcontent[t] = None
+1142 if all([item is None for item in newcontent]):
+1143 raise Exception('Operation returns undefined correlator')
+1144 return Corr(newcontent)
+1145
+1146 def sin(self):
+1147 return self._apply_func_to_corr(np.sin)
1148
-1149 def sin(self):
-1150 return self._apply_func_to_corr(np.sin)
+1149 def cos(self):
+1150 return self._apply_func_to_corr(np.cos)
1151
-1152 def cos(self):
-1153 return self._apply_func_to_corr(np.cos)
+1152 def tan(self):
+1153 return self._apply_func_to_corr(np.tan)
1154
-1155 def tan(self):
-1156 return self._apply_func_to_corr(np.tan)
+1155 def sinh(self):
+1156 return self._apply_func_to_corr(np.sinh)
1157
-1158 def sinh(self):
-1159 return self._apply_func_to_corr(np.sinh)
+1158 def cosh(self):
+1159 return self._apply_func_to_corr(np.cosh)
1160
-1161 def cosh(self):
-1162 return self._apply_func_to_corr(np.cosh)
+1161 def tanh(self):
+1162 return self._apply_func_to_corr(np.tanh)
1163
-1164 def tanh(self):
-1165 return self._apply_func_to_corr(np.tanh)
+1164 def arcsin(self):
+1165 return self._apply_func_to_corr(np.arcsin)
1166
-1167 def arcsin(self):
-1168 return self._apply_func_to_corr(np.arcsin)
+1167 def arccos(self):
+1168 return self._apply_func_to_corr(np.arccos)
1169
-1170 def arccos(self):
-1171 return self._apply_func_to_corr(np.arccos)
+1170 def arctan(self):
+1171 return self._apply_func_to_corr(np.arctan)
1172
-1173 def arctan(self):
-1174 return self._apply_func_to_corr(np.arctan)
+1173 def arcsinh(self):
+1174 return self._apply_func_to_corr(np.arcsinh)
1175
-1176 def arcsinh(self):
-1177 return self._apply_func_to_corr(np.arcsinh)
+1176 def arccosh(self):
+1177 return self._apply_func_to_corr(np.arccosh)
1178
-1179 def arccosh(self):
-1180 return self._apply_func_to_corr(np.arccosh)
+1179 def arctanh(self):
+1180 return self._apply_func_to_corr(np.arctanh)
1181
-1182 def arctanh(self):
-1183 return self._apply_func_to_corr(np.arctanh)
-1184
-1185 # Right hand side operations (require tweak in main module to work)
-1186 def __radd__(self, y):
-1187 return self + y
+1182 # Right hand side operations (require tweak in main module to work)
+1183 def __radd__(self, y):
+1184 return self + y
+1185
+1186 def __rsub__(self, y):
+1187 return -self + y
1188
-1189 def __rsub__(self, y):
-1190 return -self + y
+1189 def __rmul__(self, y):
+1190 return self * y
1191
-1192 def __rmul__(self, y):
-1193 return self * y
+1192 def __rtruediv__(self, y):
+1193 return (self / y) ** (-1)
1194
-1195 def __rtruediv__(self, y):
-1196 return (self / y) ** (-1)
-1197
-1198 @property
-1199 def real(self):
-1200 def return_real(obs_OR_cobs):
-1201 if isinstance(obs_OR_cobs, CObs):
-1202 return obs_OR_cobs.real
-1203 else:
-1204 return obs_OR_cobs
-1205
-1206 return self._apply_func_to_corr(return_real)
-1207
-1208 @property
-1209 def imag(self):
-1210 def return_imag(obs_OR_cobs):
-1211 if isinstance(obs_OR_cobs, CObs):
-1212 return obs_OR_cobs.imag
-1213 else:
-1214 return obs_OR_cobs * 0 # So it stays the right type
-1215
-1216 return self._apply_func_to_corr(return_imag)
+1195 @property
+1196 def real(self):
+1197 def return_real(obs_OR_cobs):
+1198 if isinstance(obs_OR_cobs, CObs):
+1199 return obs_OR_cobs.real
+1200 else:
+1201 return obs_OR_cobs
+1202
+1203 return self._apply_func_to_corr(return_real)
+1204
+1205 @property
+1206 def imag(self):
+1207 def return_imag(obs_OR_cobs):
+1208 if isinstance(obs_OR_cobs, CObs):
+1209 return obs_OR_cobs.imag
+1210 else:
+1211 return obs_OR_cobs * 0 # So it stays the right type
+1212
+1213 return self._apply_func_to_corr(return_imag)
+1214
+1215 def prune(self, Ntrunc, tproj=3, t0proj=2, basematrix=None):
+1216 r''' Project large correlation matrix to lowest states
1217
-1218 def prune(self, Ntrunc, tproj=3, t0proj=2, basematrix=None):
-1219 r''' Project large correlation matrix to lowest states
-1220
-1221 This method can be used to reduce the size of an (N x N) correlation matrix
-1222 to (Ntrunc x Ntrunc) by solving a GEVP at very early times where the noise
-1223 is still small.
-1224
-1225 Parameters
-1226 ----------
-1227 Ntrunc: int
-1228 Rank of the target matrix.
-1229 tproj: int
-1230 Time where the eigenvectors are evaluated, corresponds to ts in the GEVP method.
-1231 The default value is 3.
-1232 t0proj: int
-1233 Time where the correlation matrix is inverted. Choosing t0proj=1 is strongly
-1234 discouraged for O(a) improved theories, since the correctness of the procedure
-1235 cannot be granted in this case. The default value is 2.
-1236 basematrix : Corr
-1237 Correlation matrix that is used to determine the eigenvectors of the
-1238 lowest states based on a GEVP. basematrix is taken to be the Corr itself if
-1239 is is not specified.
-1240
-1241 Notes
-1242 -----
-1243 We have the basematrix $C(t)$ and the target matrix $G(t)$. We start by solving
-1244 the GEVP $$C(t) v_n(t, t_0) = \lambda_n(t, t_0) C(t_0) v_n(t, t_0)$$ where $t \equiv t_\mathrm{proj}$
-1245 and $t_0 \equiv t_{0, \mathrm{proj}}$. The target matrix is projected onto the subspace of the
-1246 resulting eigenvectors $v_n, n=1,\dots,N_\mathrm{trunc}$ via
-1247 $$G^\prime_{i, j}(t) = (v_i, G(t) v_j)$$. This allows to reduce the size of a large
-1248 correlation matrix and to remove some noise that is added by irrelevant operators.
-1249 This may allow to use the GEVP on $G(t)$ at late times such that the theoretically motivated
-1250 bound $t_0 \leq t/2$ holds, since the condition number of $G(t)$ is decreased, compared to $C(t)$.
-1251 '''
-1252
-1253 if self.N == 1:
-1254 raise Exception('Method cannot be applied to one-dimensional correlators.')
-1255 if basematrix is None:
-1256 basematrix = self
-1257 if Ntrunc >= basematrix.N:
-1258 raise Exception('Cannot truncate using Ntrunc <= %d' % (basematrix.N))
-1259 if basematrix.N != self.N:
-1260 raise Exception('basematrix and targetmatrix have to be of the same size.')
-1261
-1262 evecs = basematrix.GEVP(t0proj, tproj, sort=None)[:Ntrunc]
-1263
-1264 tmpmat = np.empty((Ntrunc, Ntrunc), dtype=object)
-1265 rmat = []
-1266 for t in range(basematrix.T):
-1267 for i in range(Ntrunc):
-1268 for j in range(Ntrunc):
-1269 tmpmat[i][j] = evecs[i].T @ self[t] @ evecs[j]
-1270 rmat.append(np.copy(tmpmat))
-1271
-1272 newcontent = [None if (self.content[t] is None) else rmat[t] for t in range(self.T)]
-1273 return Corr(newcontent)
+1218 This method can be used to reduce the size of an (N x N) correlation matrix
+1219 to (Ntrunc x Ntrunc) by solving a GEVP at very early times where the noise
+1220 is still small.
+1221
+1222 Parameters
+1223 ----------
+1224 Ntrunc: int
+1225 Rank of the target matrix.
+1226 tproj: int
+1227 Time where the eigenvectors are evaluated, corresponds to ts in the GEVP method.
+1228 The default value is 3.
+1229 t0proj: int
+1230 Time where the correlation matrix is inverted. Choosing t0proj=1 is strongly
+1231 discouraged for O(a) improved theories, since the correctness of the procedure
+1232 cannot be granted in this case. The default value is 2.
+1233 basematrix : Corr
+1234 Correlation matrix that is used to determine the eigenvectors of the
+1235 lowest states based on a GEVP. basematrix is taken to be the Corr itself if
+1236 is is not specified.
+1237
+1238 Notes
+1239 -----
+1240 We have the basematrix $C(t)$ and the target matrix $G(t)$. We start by solving
+1241 the GEVP $$C(t) v_n(t, t_0) = \lambda_n(t, t_0) C(t_0) v_n(t, t_0)$$ where $t \equiv t_\mathrm{proj}$
+1242 and $t_0 \equiv t_{0, \mathrm{proj}}$. The target matrix is projected onto the subspace of the
+1243 resulting eigenvectors $v_n, n=1,\dots,N_\mathrm{trunc}$ via
+1244 $$G^\prime_{i, j}(t) = (v_i, G(t) v_j)$$. This allows to reduce the size of a large
+1245 correlation matrix and to remove some noise that is added by irrelevant operators.
+1246 This may allow to use the GEVP on $G(t)$ at late times such that the theoretically motivated
+1247 bound $t_0 \leq t/2$ holds, since the condition number of $G(t)$ is decreased, compared to $C(t)$.
+1248 '''
+1249
+1250 if self.N == 1:
+1251 raise Exception('Method cannot be applied to one-dimensional correlators.')
+1252 if basematrix is None:
+1253 basematrix = self
+1254 if Ntrunc >= basematrix.N:
+1255 raise Exception('Cannot truncate using Ntrunc <= %d' % (basematrix.N))
+1256 if basematrix.N != self.N:
+1257 raise Exception('basematrix and targetmatrix have to be of the same size.')
+1258
+1259 evecs = basematrix.GEVP(t0proj, tproj, sort=None)[:Ntrunc]
+1260
+1261 tmpmat = np.empty((Ntrunc, Ntrunc), dtype=object)
+1262 rmat = []
+1263 for t in range(basematrix.T):
+1264 for i in range(Ntrunc):
+1265 for j in range(Ntrunc):
+1266 tmpmat[i][j] = evecs[i].T @ self[t] @ evecs[j]
+1267 rmat.append(np.copy(tmpmat))
+1268
+1269 newcontent = [None if (self.content[t] is None) else rmat[t] for t in range(self.T)]
+1270 return Corr(newcontent)
@@ -2870,33 +2864,30 @@ matrix at every timeslice. Other dependency (eg. spatial) are not supported.
70
71 if isinstance(data_input, list):
72
-73 if all([isinstance(item, (Obs, CObs)) for item in data_input]):
-74 _assert_equal_properties(data_input)
-75 self.content = [np.asarray([item]) for item in data_input]
-76 if all([isinstance(item, (Obs, CObs)) or item is None for item in data_input]):
-77 _assert_equal_properties([o for o in data_input if o is not None])
-78 self.content = [np.asarray([item]) if item is not None else None for item in data_input]
-79 self.N = 1
-80
-81 elif all([isinstance(item, np.ndarray) or item is None for item in data_input]) and any([isinstance(item, np.ndarray) for item in data_input]):
-82 self.content = data_input
-83 noNull = [a for a in self.content if not (a is None)] # To check if the matrices are correct for all undefined elements
-84 self.N = noNull[0].shape[0]
-85 if self.N > 1 and noNull[0].shape[0] != noNull[0].shape[1]:
-86 raise Exception("Smearing matrices are not NxN")
-87 if (not all([item.shape == noNull[0].shape for item in noNull])):
-88 raise Exception("Items in data_input are not of identical shape." + str(noNull))
-89 else:
-90 raise Exception("data_input contains item of wrong type")
-91 else:
-92 raise Exception("Data input was not given as list or correct array")
-93
-94 self.tag = None
-95
-96 # An undefined timeslice is represented by the None object
-97 self.content = [None] * padding[0] + self.content + [None] * padding[1]
-98 self.T = len(self.content)
-99 self.prange = prange
+73 if all([isinstance(item, (Obs, CObs)) or item is None for item in data_input]):
+74 _assert_equal_properties([o for o in data_input if o is not None])
+75 self.content = [np.asarray([item]) if item is not None else None for item in data_input]
+76 self.N = 1
+77
+78 elif all([isinstance(item, np.ndarray) or item is None for item in data_input]) and any([isinstance(item, np.ndarray) for item in data_input]):
+79 self.content = data_input
+80 noNull = [a for a in self.content if not (a is None)] # To check if the matrices are correct for all undefined elements
+81 self.N = noNull[0].shape[0]
+82 if self.N > 1 and noNull[0].shape[0] != noNull[0].shape[1]:
+83 raise Exception("Smearing matrices are not NxN")
+84 if (not all([item.shape == noNull[0].shape for item in noNull])):
+85 raise Exception("Items in data_input are not of identical shape." + str(noNull))
+86 else:
+87 raise Exception("data_input contains item of wrong type")
+88 else:
+89 raise Exception("Data input was not given as list or correct array")
+90
+91 self.tag = None
+92
+93 # An undefined timeslice is represented by the None object
+94 self.content = [None] * padding[0] + self.content + [None] * padding[1]
+95 self.T = len(self.content)
+96 self.prange = prange
@@ -2930,16 +2921,16 @@ region indentified for this correlator.
- 120 def gamma_method(self, **kwargs):
-121 """Apply the gamma method to the content of the Corr."""
-122 for item in self.content:
-123 if not (item is None):
-124 if self.N == 1:
-125 item[0].gamma_method(**kwargs)
-126 else:
-127 for i in range(self.N):
-128 for j in range(self.N):
-129 item[i, j].gamma_method(**kwargs)
+ 117 def gamma_method(self, **kwargs):
+118 """Apply the gamma method to the content of the Corr."""
+119 for item in self.content:
+120 if not (item is None):
+121 if self.N == 1:
+122 item[0].gamma_method(**kwargs)
+123 else:
+124 for i in range(self.N):
+125 for j in range(self.N):
+126 item[i, j].gamma_method(**kwargs)
@@ -2959,44 +2950,44 @@ region indentified for this correlator.
- 131 def projected(self, vector_l=None, vector_r=None, normalize=False):
-132 """We need to project the Correlator with a Vector to get a single value at each timeslice.
-133
-134 The method can use one or two vectors.
-135 If two are specified it returns v1@G@v2 (the order might be very important.)
-136 By default it will return the lowest source, which usually means unsmeared-unsmeared (0,0), but it does not have to
-137 """
-138 if self.N == 1:
-139 raise Exception("Trying to project a Corr, that already has N=1.")
-140
-141 if vector_l is None:
-142 vector_l, vector_r = np.asarray([1.] + (self.N - 1) * [0.]), np.asarray([1.] + (self.N - 1) * [0.])
-143 elif (vector_r is None):
-144 vector_r = vector_l
-145 if isinstance(vector_l, list) and not isinstance(vector_r, list):
-146 if len(vector_l) != self.T:
-147 raise Exception("Length of vector list must be equal to T")
-148 vector_r = [vector_r] * self.T
-149 if isinstance(vector_r, list) and not isinstance(vector_l, list):
-150 if len(vector_r) != self.T:
-151 raise Exception("Length of vector list must be equal to T")
-152 vector_l = [vector_l] * self.T
-153
-154 if not isinstance(vector_l, list):
-155 if not vector_l.shape == vector_r.shape == (self.N,):
-156 raise Exception("Vectors are of wrong shape!")
-157 if normalize:
-158 vector_l, vector_r = vector_l / np.sqrt((vector_l @ vector_l)), vector_r / np.sqrt(vector_r @ vector_r)
-159 newcontent = [None if _check_for_none(self, item) else np.asarray([vector_l.T @ item @ vector_r]) for item in self.content]
-160
-161 else:
-162 # There are no checks here yet. There are so many possible scenarios, where this can go wrong.
-163 if normalize:
-164 for t in range(self.T):
-165 vector_l[t], vector_r[t] = vector_l[t] / np.sqrt((vector_l[t] @ vector_l[t])), vector_r[t] / np.sqrt(vector_r[t] @ vector_r[t])
-166
-167 newcontent = [None if (_check_for_none(self, self.content[t]) or vector_l[t] is None or vector_r[t] is None) else np.asarray([vector_l[t].T @ self.content[t] @ vector_r[t]]) for t in range(self.T)]
-168 return Corr(newcontent)
+ 128 def projected(self, vector_l=None, vector_r=None, normalize=False):
+129 """We need to project the Correlator with a Vector to get a single value at each timeslice.
+130
+131 The method can use one or two vectors.
+132 If two are specified it returns v1@G@v2 (the order might be very important.)
+133 By default it will return the lowest source, which usually means unsmeared-unsmeared (0,0), but it does not have to
+134 """
+135 if self.N == 1:
+136 raise Exception("Trying to project a Corr, that already has N=1.")
+137
+138 if vector_l is None:
+139 vector_l, vector_r = np.asarray([1.] + (self.N - 1) * [0.]), np.asarray([1.] + (self.N - 1) * [0.])
+140 elif (vector_r is None):
+141 vector_r = vector_l
+142 if isinstance(vector_l, list) and not isinstance(vector_r, list):
+143 if len(vector_l) != self.T:
+144 raise Exception("Length of vector list must be equal to T")
+145 vector_r = [vector_r] * self.T
+146 if isinstance(vector_r, list) and not isinstance(vector_l, list):
+147 if len(vector_r) != self.T:
+148 raise Exception("Length of vector list must be equal to T")
+149 vector_l = [vector_l] * self.T
+150
+151 if not isinstance(vector_l, list):
+152 if not vector_l.shape == vector_r.shape == (self.N,):
+153 raise Exception("Vectors are of wrong shape!")
+154 if normalize:
+155 vector_l, vector_r = vector_l / np.sqrt((vector_l @ vector_l)), vector_r / np.sqrt(vector_r @ vector_r)
+156 newcontent = [None if _check_for_none(self, item) else np.asarray([vector_l.T @ item @ vector_r]) for item in self.content]
+157
+158 else:
+159 # There are no checks here yet. There are so many possible scenarios, where this can go wrong.
+160 if normalize:
+161 for t in range(self.T):
+162 vector_l[t], vector_r[t] = vector_l[t] / np.sqrt((vector_l[t] @ vector_l[t])), vector_r[t] / np.sqrt(vector_r[t] @ vector_r[t])
+163
+164 newcontent = [None if (_check_for_none(self, self.content[t]) or vector_l[t] is None or vector_r[t] is None) else np.asarray([vector_l[t].T @ self.content[t] @ vector_r[t]]) for t in range(self.T)]
+165 return Corr(newcontent)
@@ -3020,20 +3011,20 @@ By default it will return the lowest source, which usually means unsmeared-unsme
- 170 def item(self, i, j):
-171 """Picks the element [i,j] from every matrix and returns a correlator containing one Obs per timeslice.
-172
-173 Parameters
-174 ----------
-175 i : int
-176 First index to be picked.
-177 j : int
-178 Second index to be picked.
-179 """
-180 if self.N == 1:
-181 raise Exception("Trying to pick item from projected Corr")
-182 newcontent = [None if (item is None) else item[i, j] for item in self.content]
-183 return Corr(newcontent)
+ 167 def item(self, i, j):
+168 """Picks the element [i,j] from every matrix and returns a correlator containing one Obs per timeslice.
+169
+170 Parameters
+171 ----------
+172 i : int
+173 First index to be picked.
+174 j : int
+175 Second index to be picked.
+176 """
+177 if self.N == 1:
+178 raise Exception("Trying to pick item from projected Corr")
+179 newcontent = [None if (item is None) else item[i, j] for item in self.content]
+180 return Corr(newcontent)
@@ -3062,19 +3053,19 @@ Second index to be picked.
- 185 def plottable(self):
-186 """Outputs the correlator in a plotable format.
-187
-188 Outputs three lists containing the timeslice index, the value on each
-189 timeslice and the error on each timeslice.
-190 """
-191 if self.N != 1:
-192 raise Exception("Can only make Corr[N=1] plottable")
-193 x_list = [x for x in range(self.T) if not self.content[x] is None]
-194 y_list = [y[0].value for y in self.content if y is not None]
-195 y_err_list = [y[0].dvalue for y in self.content if y is not None]
-196
-197 return x_list, y_list, y_err_list
+ 182 def plottable(self):
+183 """Outputs the correlator in a plotable format.
+184
+185 Outputs three lists containing the timeslice index, the value on each
+186 timeslice and the error on each timeslice.
+187 """
+188 if self.N != 1:
+189 raise Exception("Can only make Corr[N=1] plottable")
+190 x_list = [x for x in range(self.T) if not self.content[x] is None]
+191 y_list = [y[0].value for y in self.content if y is not None]
+192 y_err_list = [y[0].dvalue for y in self.content if y is not None]
+193
+194 return x_list, y_list, y_err_list
@@ -3097,25 +3088,25 @@ timeslice and the error on each timeslice.
- 199 def symmetric(self):
-200 """ Symmetrize the correlator around x0=0."""
-201 if self.N != 1:
-202 raise Exception('symmetric cannot be safely applied to multi-dimensional correlators.')
-203 if self.T % 2 != 0:
-204 raise Exception("Can not symmetrize odd T")
+ 196 def symmetric(self):
+197 """ Symmetrize the correlator around x0=0."""
+198 if self.N != 1:
+199 raise Exception('symmetric cannot be safely applied to multi-dimensional correlators.')
+200 if self.T % 2 != 0:
+201 raise Exception("Can not symmetrize odd T")
+202
+203 if np.argmax(np.abs(self.content)) != 0:
+204 warnings.warn("Correlator does not seem to be symmetric around x0=0.", RuntimeWarning)
205
-206 if np.argmax(np.abs(self.content)) != 0:
-207 warnings.warn("Correlator does not seem to be symmetric around x0=0.", RuntimeWarning)
-208
-209 newcontent = [self.content[0]]
-210 for t in range(1, self.T):
-211 if (self.content[t] is None) or (self.content[self.T - t] is None):
-212 newcontent.append(None)
-213 else:
-214 newcontent.append(0.5 * (self.content[t] + self.content[self.T - t]))
-215 if (all([x is None for x in newcontent])):
-216 raise Exception("Corr could not be symmetrized: No redundant values")
-217 return Corr(newcontent, prange=self.prange)
+206 newcontent = [self.content[0]]
+207 for t in range(1, self.T):
+208 if (self.content[t] is None) or (self.content[self.T - t] is None):
+209 newcontent.append(None)
+210 else:
+211 newcontent.append(0.5 * (self.content[t] + self.content[self.T - t]))
+212 if (all([x is None for x in newcontent])):
+213 raise Exception("Corr could not be symmetrized: No redundant values")
+214 return Corr(newcontent, prange=self.prange)
@@ -3135,27 +3126,27 @@ timeslice and the error on each timeslice.
- 219 def anti_symmetric(self):
-220 """Anti-symmetrize the correlator around x0=0."""
-221 if self.N != 1:
-222 raise Exception('anti_symmetric cannot be safely applied to multi-dimensional correlators.')
-223 if self.T % 2 != 0:
-224 raise Exception("Can not symmetrize odd T")
-225
-226 test = 1 * self
-227 test.gamma_method()
-228 if not all([o.is_zero_within_error(3) for o in test.content[0]]):
-229 warnings.warn("Correlator does not seem to be anti-symmetric around x0=0.", RuntimeWarning)
-230
-231 newcontent = [self.content[0]]
-232 for t in range(1, self.T):
-233 if (self.content[t] is None) or (self.content[self.T - t] is None):
-234 newcontent.append(None)
-235 else:
-236 newcontent.append(0.5 * (self.content[t] - self.content[self.T - t]))
-237 if (all([x is None for x in newcontent])):
-238 raise Exception("Corr could not be symmetrized: No redundant values")
-239 return Corr(newcontent, prange=self.prange)
+ 216 def anti_symmetric(self):
+217 """Anti-symmetrize the correlator around x0=0."""
+218 if self.N != 1:
+219 raise Exception('anti_symmetric cannot be safely applied to multi-dimensional correlators.')
+220 if self.T % 2 != 0:
+221 raise Exception("Can not symmetrize odd T")
+222
+223 test = 1 * self
+224 test.gamma_method()
+225 if not all([o.is_zero_within_error(3) for o in test.content[0]]):
+226 warnings.warn("Correlator does not seem to be anti-symmetric around x0=0.", RuntimeWarning)
+227
+228 newcontent = [self.content[0]]
+229 for t in range(1, self.T):
+230 if (self.content[t] is None) or (self.content[self.T - t] is None):
+231 newcontent.append(None)
+232 else:
+233 newcontent.append(0.5 * (self.content[t] - self.content[self.T - t]))
+234 if (all([x is None for x in newcontent])):
+235 raise Exception("Corr could not be symmetrized: No redundant values")
+236 return Corr(newcontent, prange=self.prange)
@@ -3175,20 +3166,20 @@ timeslice and the error on each timeslice.
- 241 def is_matrix_symmetric(self):
-242 """Checks whether a correlator matrices is symmetric on every timeslice."""
-243 if self.N == 1:
-244 raise Exception("Only works for correlator matrices.")
-245 for t in range(self.T):
-246 if self[t] is None:
-247 continue
-248 for i in range(self.N):
-249 for j in range(i + 1, self.N):
-250 if self[t][i, j] is self[t][j, i]:
-251 continue
-252 if hash(self[t][i, j]) != hash(self[t][j, i]):
-253 return False
-254 return True
+ 238 def is_matrix_symmetric(self):
+239 """Checks whether a correlator matrices is symmetric on every timeslice."""
+240 if self.N == 1:
+241 raise Exception("Only works for correlator matrices.")
+242 for t in range(self.T):
+243 if self[t] is None:
+244 continue
+245 for i in range(self.N):
+246 for j in range(i + 1, self.N):
+247 if self[t][i, j] is self[t][j, i]:
+248 continue
+249 if hash(self[t][i, j]) != hash(self[t][j, i]):
+250 return False
+251 return True
@@ -3208,15 +3199,15 @@ timeslice and the error on each timeslice.
- 256 def matrix_symmetric(self):
-257 """Symmetrizes the correlator matrices on every timeslice."""
-258 if self.N == 1:
-259 raise Exception("Trying to symmetrize a correlator matrix, that already has N=1.")
-260 if self.is_matrix_symmetric():
-261 return 1.0 * self
-262 else:
-263 transposed = [None if _check_for_none(self, G) else G.T for G in self.content]
-264 return 0.5 * (Corr(transposed) + self)
+ 253 def matrix_symmetric(self):
+254 """Symmetrizes the correlator matrices on every timeslice."""
+255 if self.N == 1:
+256 raise Exception("Trying to symmetrize a correlator matrix, that already has N=1.")
+257 if self.is_matrix_symmetric():
+258 return 1.0 * self
+259 else:
+260 transposed = [None if _check_for_none(self, G) else G.T for G in self.content]
+261 return 0.5 * (Corr(transposed) + self)
@@ -3236,84 +3227,84 @@ timeslice and the error on each timeslice.
- 266 def GEVP(self, t0, ts=None, sort="Eigenvalue", **kwargs):
-267 r'''Solve the generalized eigenvalue problem on the correlator matrix and returns the corresponding eigenvectors.
-268
-269 The eigenvectors are sorted according to the descending eigenvalues, the zeroth eigenvector(s) correspond to the
-270 largest eigenvalue(s). The eigenvector(s) for the individual states can be accessed via slicing
-271 ```python
-272 C.GEVP(t0=2)[0] # Ground state vector(s)
-273 C.GEVP(t0=2)[:3] # Vectors for the lowest three states
-274 ```
-275
-276 Parameters
-277 ----------
-278 t0 : int
-279 The time t0 for the right hand side of the GEVP according to $G(t)v_i=\lambda_i G(t_0)v_i$
-280 ts : int
-281 fixed time $G(t_s)v_i=\lambda_i G(t_0)v_i$ if sort=None.
-282 If sort="Eigenvector" it gives a reference point for the sorting method.
-283 sort : string
-284 If this argument is set, a list of self.T vectors per state is returned. If it is set to None, only one vector is returned.
-285 - "Eigenvalue": The eigenvector is chosen according to which eigenvalue it belongs individually on every timeslice.
-286 - "Eigenvector": Use the method described in arXiv:2004.10472 to find the set of v(t) belonging to the state.
-287 The reference state is identified by its eigenvalue at $t=t_s$.
-288
-289 Other Parameters
-290 ----------------
-291 state : int
-292 Returns only the vector(s) for a specified state. The lowest state is zero.
-293 '''
-294
-295 if self.N == 1:
-296 raise Exception("GEVP methods only works on correlator matrices and not single correlators.")
-297 if ts is not None:
-298 if (ts <= t0):
-299 raise Exception("ts has to be larger than t0.")
-300
-301 if "sorted_list" in kwargs:
-302 warnings.warn("Argument 'sorted_list' is deprecated, use 'sort' instead.", DeprecationWarning)
-303 sort = kwargs.get("sorted_list")
-304
-305 if self.is_matrix_symmetric():
-306 symmetric_corr = self
-307 else:
-308 symmetric_corr = self.matrix_symmetric()
+ 263 def GEVP(self, t0, ts=None, sort="Eigenvalue", **kwargs):
+264 r'''Solve the generalized eigenvalue problem on the correlator matrix and returns the corresponding eigenvectors.
+265
+266 The eigenvectors are sorted according to the descending eigenvalues, the zeroth eigenvector(s) correspond to the
+267 largest eigenvalue(s). The eigenvector(s) for the individual states can be accessed via slicing
+268 ```python
+269 C.GEVP(t0=2)[0] # Ground state vector(s)
+270 C.GEVP(t0=2)[:3] # Vectors for the lowest three states
+271 ```
+272
+273 Parameters
+274 ----------
+275 t0 : int
+276 The time t0 for the right hand side of the GEVP according to $G(t)v_i=\lambda_i G(t_0)v_i$
+277 ts : int
+278 fixed time $G(t_s)v_i=\lambda_i G(t_0)v_i$ if sort=None.
+279 If sort="Eigenvector" it gives a reference point for the sorting method.
+280 sort : string
+281 If this argument is set, a list of self.T vectors per state is returned. If it is set to None, only one vector is returned.
+282 - "Eigenvalue": The eigenvector is chosen according to which eigenvalue it belongs individually on every timeslice.
+283 - "Eigenvector": Use the method described in arXiv:2004.10472 to find the set of v(t) belonging to the state.
+284 The reference state is identified by its eigenvalue at $t=t_s$.
+285
+286 Other Parameters
+287 ----------------
+288 state : int
+289 Returns only the vector(s) for a specified state. The lowest state is zero.
+290 '''
+291
+292 if self.N == 1:
+293 raise Exception("GEVP methods only works on correlator matrices and not single correlators.")
+294 if ts is not None:
+295 if (ts <= t0):
+296 raise Exception("ts has to be larger than t0.")
+297
+298 if "sorted_list" in kwargs:
+299 warnings.warn("Argument 'sorted_list' is deprecated, use 'sort' instead.", DeprecationWarning)
+300 sort = kwargs.get("sorted_list")
+301
+302 if self.is_matrix_symmetric():
+303 symmetric_corr = self
+304 else:
+305 symmetric_corr = self.matrix_symmetric()
+306
+307 G0 = np.vectorize(lambda x: x.value)(symmetric_corr[t0])
+308 np.linalg.cholesky(G0) # Check if matrix G0 is positive-semidefinite.
309
-310 G0 = np.vectorize(lambda x: x.value)(symmetric_corr[t0])
-311 np.linalg.cholesky(G0) # Check if matrix G0 is positive-semidefinite.
-312
-313 if sort is None:
-314 if (ts is None):
-315 raise Exception("ts is required if sort=None.")
-316 if (self.content[t0] is None) or (self.content[ts] is None):
-317 raise Exception("Corr not defined at t0/ts.")
-318 Gt = np.vectorize(lambda x: x.value)(symmetric_corr[ts])
-319 reordered_vecs = _GEVP_solver(Gt, G0)
-320
-321 elif sort in ["Eigenvalue", "Eigenvector"]:
-322 if sort == "Eigenvalue" and ts is not None:
-323 warnings.warn("ts has no effect when sorting by eigenvalue is chosen.", RuntimeWarning)
-324 all_vecs = [None] * (t0 + 1)
-325 for t in range(t0 + 1, self.T):
-326 try:
-327 Gt = np.vectorize(lambda x: x.value)(symmetric_corr[t])
-328 all_vecs.append(_GEVP_solver(Gt, G0))
-329 except Exception:
-330 all_vecs.append(None)
-331 if sort == "Eigenvector":
-332 if ts is None:
-333 raise Exception("ts is required for the Eigenvector sorting method.")
-334 all_vecs = _sort_vectors(all_vecs, ts)
-335
-336 reordered_vecs = [[v[s] if v is not None else None for v in all_vecs] for s in range(self.N)]
-337 else:
-338 raise Exception("Unkown value for 'sort'.")
-339
-340 if "state" in kwargs:
-341 return reordered_vecs[kwargs.get("state")]
-342 else:
-343 return reordered_vecs
+310 if sort is None:
+311 if (ts is None):
+312 raise Exception("ts is required if sort=None.")
+313 if (self.content[t0] is None) or (self.content[ts] is None):
+314 raise Exception("Corr not defined at t0/ts.")
+315 Gt = np.vectorize(lambda x: x.value)(symmetric_corr[ts])
+316 reordered_vecs = _GEVP_solver(Gt, G0)
+317
+318 elif sort in ["Eigenvalue", "Eigenvector"]:
+319 if sort == "Eigenvalue" and ts is not None:
+320 warnings.warn("ts has no effect when sorting by eigenvalue is chosen.", RuntimeWarning)
+321 all_vecs = [None] * (t0 + 1)
+322 for t in range(t0 + 1, self.T):
+323 try:
+324 Gt = np.vectorize(lambda x: x.value)(symmetric_corr[t])
+325 all_vecs.append(_GEVP_solver(Gt, G0))
+326 except Exception:
+327 all_vecs.append(None)
+328 if sort == "Eigenvector":
+329 if ts is None:
+330 raise Exception("ts is required for the Eigenvector sorting method.")
+331 all_vecs = _sort_vectors(all_vecs, ts)
+332
+333 reordered_vecs = [[v[s] if v is not None else None for v in all_vecs] for s in range(self.N)]
+334 else:
+335 raise Exception("Unkown value for 'sort'.")
+336
+337 if "state" in kwargs:
+338 return reordered_vecs[kwargs.get("state")]
+339 else:
+340 return reordered_vecs
@@ -3366,18 +3357,18 @@ Returns only the vector(s) for a specified state. The lowest state is zero.
- 345 def Eigenvalue(self, t0, ts=None, state=0, sort="Eigenvalue"):
-346 """Determines the eigenvalue of the GEVP by solving and projecting the correlator
-347
-348 Parameters
-349 ----------
-350 state : int
-351 The state one is interested in ordered by energy. The lowest state is zero.
-352
-353 All other parameters are identical to the ones of Corr.GEVP.
-354 """
-355 vec = self.GEVP(t0, ts=ts, sort=sort)[state]
-356 return self.projected(vec)
+ 342 def Eigenvalue(self, t0, ts=None, state=0, sort="Eigenvalue"):
+343 """Determines the eigenvalue of the GEVP by solving and projecting the correlator
+344
+345 Parameters
+346 ----------
+347 state : int
+348 The state one is interested in ordered by energy. The lowest state is zero.
+349
+350 All other parameters are identical to the ones of Corr.GEVP.
+351 """
+352 vec = self.GEVP(t0, ts=ts, sort=sort)[state]
+353 return self.projected(vec)
@@ -3405,46 +3396,46 @@ The state one is interested in ordered by energy. The lowest state is zero.
- 358 def Hankel(self, N, periodic=False):
-359 """Constructs an NxN Hankel matrix
-360
-361 C(t) c(t+1) ... c(t+n-1)
-362 C(t+1) c(t+2) ... c(t+n)
-363 .................
-364 C(t+(n-1)) c(t+n) ... c(t+2(n-1))
-365
-366 Parameters
-367 ----------
-368 N : int
-369 Dimension of the Hankel matrix
-370 periodic : bool, optional
-371 determines whether the matrix is extended periodically
-372 """
+ 355 def Hankel(self, N, periodic=False):
+356 """Constructs an NxN Hankel matrix
+357
+358 C(t) c(t+1) ... c(t+n-1)
+359 C(t+1) c(t+2) ... c(t+n)
+360 .................
+361 C(t+(n-1)) c(t+n) ... c(t+2(n-1))
+362
+363 Parameters
+364 ----------
+365 N : int
+366 Dimension of the Hankel matrix
+367 periodic : bool, optional
+368 determines whether the matrix is extended periodically
+369 """
+370
+371 if self.N != 1:
+372 raise Exception("Multi-operator Prony not implemented!")
373
-374 if self.N != 1:
-375 raise Exception("Multi-operator Prony not implemented!")
-376
-377 array = np.empty([N, N], dtype="object")
-378 new_content = []
-379 for t in range(self.T):
-380 new_content.append(array.copy())
-381
-382 def wrap(i):
-383 while i >= self.T:
-384 i -= self.T
-385 return i
-386
-387 for t in range(self.T):
-388 for i in range(N):
-389 for j in range(N):
-390 if periodic:
-391 new_content[t][i, j] = self.content[wrap(t + i + j)][0]
-392 elif (t + i + j) >= self.T:
-393 new_content[t] = None
-394 else:
-395 new_content[t][i, j] = self.content[t + i + j][0]
-396
-397 return Corr(new_content)
+374 array = np.empty([N, N], dtype="object")
+375 new_content = []
+376 for t in range(self.T):
+377 new_content.append(array.copy())
+378
+379 def wrap(i):
+380 while i >= self.T:
+381 i -= self.T
+382 return i
+383
+384 for t in range(self.T):
+385 for i in range(N):
+386 for j in range(N):
+387 if periodic:
+388 new_content[t][i, j] = self.content[wrap(t + i + j)][0]
+389 elif (t + i + j) >= self.T:
+390 new_content[t] = None
+391 else:
+392 new_content[t][i, j] = self.content[t + i + j][0]
+393
+394 return Corr(new_content)
@@ -3478,15 +3469,15 @@ determines whether the matrix is extended periodically
- 399 def roll(self, dt):
-400 """Periodically shift the correlator by dt timeslices
-401
-402 Parameters
-403 ----------
-404 dt : int
-405 number of timeslices
-406 """
-407 return Corr(list(np.roll(np.array(self.content, dtype=object), dt)))
+ 396 def roll(self, dt):
+397 """Periodically shift the correlator by dt timeslices
+398
+399 Parameters
+400 ----------
+401 dt : int
+402 number of timeslices
+403 """
+404 return Corr(list(np.roll(np.array(self.content, dtype=object), dt)))
@@ -3513,9 +3504,9 @@ number of timeslices
- 409 def reverse(self):
-410 """Reverse the time ordering of the Corr"""
-411 return Corr(self.content[:: -1])
+ 406 def reverse(self):
+407 """Reverse the time ordering of the Corr"""
+408 return Corr(self.content[:: -1])
@@ -3535,23 +3526,23 @@ number of timeslices
- 413 def thin(self, spacing=2, offset=0):
-414 """Thin out a correlator to suppress correlations
-415
-416 Parameters
-417 ----------
-418 spacing : int
-419 Keep only every 'spacing'th entry of the correlator
-420 offset : int
-421 Offset the equal spacing
-422 """
-423 new_content = []
-424 for t in range(self.T):
-425 if (offset + t) % spacing != 0:
-426 new_content.append(None)
-427 else:
-428 new_content.append(self.content[t])
-429 return Corr(new_content)
+ 410 def thin(self, spacing=2, offset=0):
+411 """Thin out a correlator to suppress correlations
+412
+413 Parameters
+414 ----------
+415 spacing : int
+416 Keep only every 'spacing'th entry of the correlator
+417 offset : int
+418 Offset the equal spacing
+419 """
+420 new_content = []
+421 for t in range(self.T):
+422 if (offset + t) % spacing != 0:
+423 new_content.append(None)
+424 else:
+425 new_content.append(self.content[t])
+426 return Corr(new_content)
@@ -3580,34 +3571,34 @@ Offset the equal spacing
- 431 def correlate(self, partner):
-432 """Correlate the correlator with another correlator or Obs
-433
-434 Parameters
-435 ----------
-436 partner : Obs or Corr
-437 partner to correlate the correlator with.
-438 Can either be an Obs which is correlated with all entries of the
-439 correlator or a Corr of same length.
-440 """
-441 if self.N != 1:
-442 raise Exception("Only one-dimensional correlators can be safely correlated.")
-443 new_content = []
-444 for x0, t_slice in enumerate(self.content):
-445 if _check_for_none(self, t_slice):
-446 new_content.append(None)
-447 else:
-448 if isinstance(partner, Corr):
-449 if _check_for_none(partner, partner.content[x0]):
-450 new_content.append(None)
-451 else:
-452 new_content.append(np.array([correlate(o, partner.content[x0][0]) for o in t_slice]))
-453 elif isinstance(partner, Obs): # Should this include CObs?
-454 new_content.append(np.array([correlate(o, partner) for o in t_slice]))
-455 else:
-456 raise Exception("Can only correlate with an Obs or a Corr.")
-457
-458 return Corr(new_content)
+ 428 def correlate(self, partner):
+429 """Correlate the correlator with another correlator or Obs
+430
+431 Parameters
+432 ----------
+433 partner : Obs or Corr
+434 partner to correlate the correlator with.
+435 Can either be an Obs which is correlated with all entries of the
+436 correlator or a Corr of same length.
+437 """
+438 if self.N != 1:
+439 raise Exception("Only one-dimensional correlators can be safely correlated.")
+440 new_content = []
+441 for x0, t_slice in enumerate(self.content):
+442 if _check_for_none(self, t_slice):
+443 new_content.append(None)
+444 else:
+445 if isinstance(partner, Corr):
+446 if _check_for_none(partner, partner.content[x0]):
+447 new_content.append(None)
+448 else:
+449 new_content.append(np.array([correlate(o, partner.content[x0][0]) for o in t_slice]))
+450 elif isinstance(partner, Obs): # Should this include CObs?
+451 new_content.append(np.array([correlate(o, partner) for o in t_slice]))
+452 else:
+453 raise Exception("Can only correlate with an Obs or a Corr.")
+454
+455 return Corr(new_content)
@@ -3636,28 +3627,28 @@ correlator or a Corr of same length.
- 460 def reweight(self, weight, **kwargs):
-461 """Reweight the correlator.
-462
-463 Parameters
-464 ----------
-465 weight : Obs
-466 Reweighting factor. An Observable that has to be defined on a superset of the
-467 configurations in obs[i].idl for all i.
-468 all_configs : bool
-469 if True, the reweighted observables are normalized by the average of
-470 the reweighting factor on all configurations in weight.idl and not
-471 on the configurations in obs[i].idl.
-472 """
-473 if self.N != 1:
-474 raise Exception("Reweighting only implemented for one-dimensional correlators.")
-475 new_content = []
-476 for t_slice in self.content:
-477 if _check_for_none(self, t_slice):
-478 new_content.append(None)
-479 else:
-480 new_content.append(np.array(reweight(weight, t_slice, **kwargs)))
-481 return Corr(new_content)
+ 457 def reweight(self, weight, **kwargs):
+458 """Reweight the correlator.
+459
+460 Parameters
+461 ----------
+462 weight : Obs
+463 Reweighting factor. An Observable that has to be defined on a superset of the
+464 configurations in obs[i].idl for all i.
+465 all_configs : bool
+466 if True, the reweighted observables are normalized by the average of
+467 the reweighting factor on all configurations in weight.idl and not
+468 on the configurations in obs[i].idl.
+469 """
+470 if self.N != 1:
+471 raise Exception("Reweighting only implemented for one-dimensional correlators.")
+472 new_content = []
+473 for t_slice in self.content:
+474 if _check_for_none(self, t_slice):
+475 new_content.append(None)
+476 else:
+477 new_content.append(np.array(reweight(weight, t_slice, **kwargs)))
+478 return Corr(new_content)
@@ -3689,35 +3680,35 @@ on the configurations in obs[i].idl.
- 483 def T_symmetry(self, partner, parity=+1):
-484 """Return the time symmetry average of the correlator and its partner
-485
-486 Parameters
-487 ----------
-488 partner : Corr
-489 Time symmetry partner of the Corr
-490 partity : int
-491 Parity quantum number of the correlator, can be +1 or -1
-492 """
-493 if self.N != 1:
-494 raise Exception("T_symmetry only implemented for one-dimensional correlators.")
-495 if not isinstance(partner, Corr):
-496 raise Exception("T partner has to be a Corr object.")
-497 if parity not in [+1, -1]:
-498 raise Exception("Parity has to be +1 or -1.")
-499 T_partner = parity * partner.reverse()
-500
-501 t_slices = []
-502 test = (self - T_partner)
-503 test.gamma_method()
-504 for x0, t_slice in enumerate(test.content):
-505 if t_slice is not None:
-506 if not t_slice[0].is_zero_within_error(5):
-507 t_slices.append(x0)
-508 if t_slices:
-509 warnings.warn("T symmetry partners do not agree within 5 sigma on time slices " + str(t_slices) + ".", RuntimeWarning)
-510
-511 return (self + T_partner) / 2
+ 480 def T_symmetry(self, partner, parity=+1):
+481 """Return the time symmetry average of the correlator and its partner
+482
+483 Parameters
+484 ----------
+485 partner : Corr
+486 Time symmetry partner of the Corr
+487 partity : int
+488 Parity quantum number of the correlator, can be +1 or -1
+489 """
+490 if self.N != 1:
+491 raise Exception("T_symmetry only implemented for one-dimensional correlators.")
+492 if not isinstance(partner, Corr):
+493 raise Exception("T partner has to be a Corr object.")
+494 if parity not in [+1, -1]:
+495 raise Exception("Parity has to be +1 or -1.")
+496 T_partner = parity * partner.reverse()
+497
+498 t_slices = []
+499 test = (self - T_partner)
+500 test.gamma_method()
+501 for x0, t_slice in enumerate(test.content):
+502 if t_slice is not None:
+503 if not t_slice[0].is_zero_within_error(5):
+504 t_slices.append(x0)
+505 if t_slices:
+506 warnings.warn("T symmetry partners do not agree within 5 sigma on time slices " + str(t_slices) + ".", RuntimeWarning)
+507
+508 return (self + T_partner) / 2
@@ -3746,70 +3737,70 @@ Parity quantum number of the correlator, can be +1 or -1
- 513 def deriv(self, variant="symmetric"):
-514 """Return the first derivative of the correlator with respect to x0.
-515
-516 Parameters
-517 ----------
-518 variant : str
-519 decides which definition of the finite differences derivative is used.
-520 Available choice: symmetric, forward, backward, improved, log, default: symmetric
-521 """
-522 if self.N != 1:
-523 raise Exception("deriv only implemented for one-dimensional correlators.")
-524 if variant == "symmetric":
-525 newcontent = []
-526 for t in range(1, self.T - 1):
-527 if (self.content[t - 1] is None) or (self.content[t + 1] is None):
-528 newcontent.append(None)
-529 else:
-530 newcontent.append(0.5 * (self.content[t + 1] - self.content[t - 1]))
-531 if (all([x is None for x in newcontent])):
-532 raise Exception('Derivative is undefined at all timeslices')
-533 return Corr(newcontent, padding=[1, 1])
-534 elif variant == "forward":
-535 newcontent = []
-536 for t in range(self.T - 1):
-537 if (self.content[t] is None) or (self.content[t + 1] is None):
-538 newcontent.append(None)
-539 else:
-540 newcontent.append(self.content[t + 1] - self.content[t])
-541 if (all([x is None for x in newcontent])):
-542 raise Exception("Derivative is undefined at all timeslices")
-543 return Corr(newcontent, padding=[0, 1])
-544 elif variant == "backward":
-545 newcontent = []
-546 for t in range(1, self.T):
-547 if (self.content[t - 1] is None) or (self.content[t] is None):
-548 newcontent.append(None)
-549 else:
-550 newcontent.append(self.content[t] - self.content[t - 1])
-551 if (all([x is None for x in newcontent])):
-552 raise Exception("Derivative is undefined at all timeslices")
-553 return Corr(newcontent, padding=[1, 0])
-554 elif variant == "improved":
-555 newcontent = []
-556 for t in range(2, self.T - 2):
-557 if (self.content[t - 2] is None) or (self.content[t - 1] is None) or (self.content[t + 1] is None) or (self.content[t + 2] is None):
-558 newcontent.append(None)
-559 else:
-560 newcontent.append((1 / 12) * (self.content[t - 2] - 8 * self.content[t - 1] + 8 * self.content[t + 1] - self.content[t + 2]))
-561 if (all([x is None for x in newcontent])):
-562 raise Exception('Derivative is undefined at all timeslices')
-563 return Corr(newcontent, padding=[2, 2])
-564 elif variant == 'log':
-565 newcontent = []
-566 for t in range(self.T):
-567 if (self.content[t] is None) or (self.content[t] <= 0):
-568 newcontent.append(None)
-569 else:
-570 newcontent.append(np.log(self.content[t]))
-571 if (all([x is None for x in newcontent])):
-572 raise Exception("Log is undefined at all timeslices")
-573 logcorr = Corr(newcontent)
-574 return self * logcorr.deriv('symmetric')
-575 else:
-576 raise Exception("Unknown variant.")
+ 510 def deriv(self, variant="symmetric"):
+511 """Return the first derivative of the correlator with respect to x0.
+512
+513 Parameters
+514 ----------
+515 variant : str
+516 decides which definition of the finite differences derivative is used.
+517 Available choice: symmetric, forward, backward, improved, log, default: symmetric
+518 """
+519 if self.N != 1:
+520 raise Exception("deriv only implemented for one-dimensional correlators.")
+521 if variant == "symmetric":
+522 newcontent = []
+523 for t in range(1, self.T - 1):
+524 if (self.content[t - 1] is None) or (self.content[t + 1] is None):
+525 newcontent.append(None)
+526 else:
+527 newcontent.append(0.5 * (self.content[t + 1] - self.content[t - 1]))
+528 if (all([x is None for x in newcontent])):
+529 raise Exception('Derivative is undefined at all timeslices')
+530 return Corr(newcontent, padding=[1, 1])
+531 elif variant == "forward":
+532 newcontent = []
+533 for t in range(self.T - 1):
+534 if (self.content[t] is None) or (self.content[t + 1] is None):
+535 newcontent.append(None)
+536 else:
+537 newcontent.append(self.content[t + 1] - self.content[t])
+538 if (all([x is None for x in newcontent])):
+539 raise Exception("Derivative is undefined at all timeslices")
+540 return Corr(newcontent, padding=[0, 1])
+541 elif variant == "backward":
+542 newcontent = []
+543 for t in range(1, self.T):
+544 if (self.content[t - 1] is None) or (self.content[t] is None):
+545 newcontent.append(None)
+546 else:
+547 newcontent.append(self.content[t] - self.content[t - 1])
+548 if (all([x is None for x in newcontent])):
+549 raise Exception("Derivative is undefined at all timeslices")
+550 return Corr(newcontent, padding=[1, 0])
+551 elif variant == "improved":
+552 newcontent = []
+553 for t in range(2, self.T - 2):
+554 if (self.content[t - 2] is None) or (self.content[t - 1] is None) or (self.content[t + 1] is None) or (self.content[t + 2] is None):
+555 newcontent.append(None)
+556 else:
+557 newcontent.append((1 / 12) * (self.content[t - 2] - 8 * self.content[t - 1] + 8 * self.content[t + 1] - self.content[t + 2]))
+558 if (all([x is None for x in newcontent])):
+559 raise Exception('Derivative is undefined at all timeslices')
+560 return Corr(newcontent, padding=[2, 2])
+561 elif variant == 'log':
+562 newcontent = []
+563 for t in range(self.T):
+564 if (self.content[t] is None) or (self.content[t] <= 0):
+565 newcontent.append(None)
+566 else:
+567 newcontent.append(np.log(self.content[t]))
+568 if (all([x is None for x in newcontent])):
+569 raise Exception("Log is undefined at all timeslices")
+570 logcorr = Corr(newcontent)
+571 return self * logcorr.deriv('symmetric')
+572 else:
+573 raise Exception("Unknown variant.")
@@ -3837,50 +3828,50 @@ Available choice: symmetric, forward, backward, improved, log, default: symmetri
- 578 def second_deriv(self, variant="symmetric"):
-579 """Return the second derivative of the correlator with respect to x0.
-580
-581 Parameters
-582 ----------
-583 variant : str
-584 decides which definition of the finite differences derivative is used.
-585 Available choice: symmetric, improved, log, default: symmetric
-586 """
-587 if self.N != 1:
-588 raise Exception("second_deriv only implemented for one-dimensional correlators.")
-589 if variant == "symmetric":
-590 newcontent = []
-591 for t in range(1, self.T - 1):
-592 if (self.content[t - 1] is None) or (self.content[t + 1] is None):
-593 newcontent.append(None)
-594 else:
-595 newcontent.append((self.content[t + 1] - 2 * self.content[t] + self.content[t - 1]))
-596 if (all([x is None for x in newcontent])):
-597 raise Exception("Derivative is undefined at all timeslices")
-598 return Corr(newcontent, padding=[1, 1])
-599 elif variant == "improved":
-600 newcontent = []
-601 for t in range(2, self.T - 2):
-602 if (self.content[t - 2] is None) or (self.content[t - 1] is None) or (self.content[t] is None) or (self.content[t + 1] is None) or (self.content[t + 2] is None):
-603 newcontent.append(None)
-604 else:
-605 newcontent.append((1 / 12) * (-self.content[t + 2] + 16 * self.content[t + 1] - 30 * self.content[t] + 16 * self.content[t - 1] - self.content[t - 2]))
-606 if (all([x is None for x in newcontent])):
-607 raise Exception("Derivative is undefined at all timeslices")
-608 return Corr(newcontent, padding=[2, 2])
-609 elif variant == 'log':
-610 newcontent = []
-611 for t in range(self.T):
-612 if (self.content[t] is None) or (self.content[t] <= 0):
-613 newcontent.append(None)
-614 else:
-615 newcontent.append(np.log(self.content[t]))
-616 if (all([x is None for x in newcontent])):
-617 raise Exception("Log is undefined at all timeslices")
-618 logcorr = Corr(newcontent)
-619 return self * (logcorr.second_deriv('symmetric') + (logcorr.deriv('symmetric'))**2)
-620 else:
-621 raise Exception("Unknown variant.")
+ 575 def second_deriv(self, variant="symmetric"):
+576 """Return the second derivative of the correlator with respect to x0.
+577
+578 Parameters
+579 ----------
+580 variant : str
+581 decides which definition of the finite differences derivative is used.
+582 Available choice: symmetric, improved, log, default: symmetric
+583 """
+584 if self.N != 1:
+585 raise Exception("second_deriv only implemented for one-dimensional correlators.")
+586 if variant == "symmetric":
+587 newcontent = []
+588 for t in range(1, self.T - 1):
+589 if (self.content[t - 1] is None) or (self.content[t + 1] is None):
+590 newcontent.append(None)
+591 else:
+592 newcontent.append((self.content[t + 1] - 2 * self.content[t] + self.content[t - 1]))
+593 if (all([x is None for x in newcontent])):
+594 raise Exception("Derivative is undefined at all timeslices")
+595 return Corr(newcontent, padding=[1, 1])
+596 elif variant == "improved":
+597 newcontent = []
+598 for t in range(2, self.T - 2):
+599 if (self.content[t - 2] is None) or (self.content[t - 1] is None) or (self.content[t] is None) or (self.content[t + 1] is None) or (self.content[t + 2] is None):
+600 newcontent.append(None)
+601 else:
+602 newcontent.append((1 / 12) * (-self.content[t + 2] + 16 * self.content[t + 1] - 30 * self.content[t] + 16 * self.content[t - 1] - self.content[t - 2]))
+603 if (all([x is None for x in newcontent])):
+604 raise Exception("Derivative is undefined at all timeslices")
+605 return Corr(newcontent, padding=[2, 2])
+606 elif variant == 'log':
+607 newcontent = []
+608 for t in range(self.T):
+609 if (self.content[t] is None) or (self.content[t] <= 0):
+610 newcontent.append(None)
+611 else:
+612 newcontent.append(np.log(self.content[t]))
+613 if (all([x is None for x in newcontent])):
+614 raise Exception("Log is undefined at all timeslices")
+615 logcorr = Corr(newcontent)
+616 return self * (logcorr.second_deriv('symmetric') + (logcorr.deriv('symmetric'))**2)
+617 else:
+618 raise Exception("Unknown variant.")
@@ -3908,89 +3899,89 @@ Available choice: symmetric, improved, log, default: symmetric
- 623 def m_eff(self, variant='log', guess=1.0):
-624 """Returns the effective mass of the correlator as correlator object
-625
-626 Parameters
-627 ----------
-628 variant : str
-629 log : uses the standard effective mass log(C(t) / C(t+1))
-630 cosh, periodic : Use periodicitiy of the correlator by solving C(t) / C(t+1) = cosh(m * (t - T/2)) / cosh(m * (t + 1 - T/2)) for m.
-631 sinh : Use anti-periodicitiy of the correlator by solving C(t) / C(t+1) = sinh(m * (t - T/2)) / sinh(m * (t + 1 - T/2)) for m.
-632 See, e.g., arXiv:1205.5380
-633 arccosh : Uses the explicit form of the symmetrized correlator (not recommended)
-634 logsym: uses the symmetric effective mass log(C(t-1) / C(t+1))/2
-635 guess : float
-636 guess for the root finder, only relevant for the root variant
-637 """
-638 if self.N != 1:
-639 raise Exception('Correlator must be projected before getting m_eff')
-640 if variant == 'log':
-641 newcontent = []
-642 for t in range(self.T - 1):
-643 if ((self.content[t] is None) or (self.content[t + 1] is None)) or (self.content[t + 1][0].value == 0):
-644 newcontent.append(None)
-645 elif self.content[t][0].value / self.content[t + 1][0].value < 0:
-646 newcontent.append(None)
-647 else:
-648 newcontent.append(self.content[t] / self.content[t + 1])
-649 if (all([x is None for x in newcontent])):
-650 raise Exception('m_eff is undefined at all timeslices')
-651
-652 return np.log(Corr(newcontent, padding=[0, 1]))
-653
-654 elif variant == 'logsym':
-655 newcontent = []
-656 for t in range(1, self.T - 1):
-657 if ((self.content[t - 1] is None) or (self.content[t + 1] is None)) or (self.content[t + 1][0].value == 0):
-658 newcontent.append(None)
-659 elif self.content[t - 1][0].value / self.content[t + 1][0].value < 0:
-660 newcontent.append(None)
-661 else:
-662 newcontent.append(self.content[t - 1] / self.content[t + 1])
-663 if (all([x is None for x in newcontent])):
-664 raise Exception('m_eff is undefined at all timeslices')
-665
-666 return np.log(Corr(newcontent, padding=[1, 1])) / 2
-667
-668 elif variant in ['periodic', 'cosh', 'sinh']:
-669 if variant in ['periodic', 'cosh']:
-670 func = anp.cosh
-671 else:
-672 func = anp.sinh
+ 620 def m_eff(self, variant='log', guess=1.0):
+621 """Returns the effective mass of the correlator as correlator object
+622
+623 Parameters
+624 ----------
+625 variant : str
+626 log : uses the standard effective mass log(C(t) / C(t+1))
+627 cosh, periodic : Use periodicitiy of the correlator by solving C(t) / C(t+1) = cosh(m * (t - T/2)) / cosh(m * (t + 1 - T/2)) for m.
+628 sinh : Use anti-periodicitiy of the correlator by solving C(t) / C(t+1) = sinh(m * (t - T/2)) / sinh(m * (t + 1 - T/2)) for m.
+629 See, e.g., arXiv:1205.5380
+630 arccosh : Uses the explicit form of the symmetrized correlator (not recommended)
+631 logsym: uses the symmetric effective mass log(C(t-1) / C(t+1))/2
+632 guess : float
+633 guess for the root finder, only relevant for the root variant
+634 """
+635 if self.N != 1:
+636 raise Exception('Correlator must be projected before getting m_eff')
+637 if variant == 'log':
+638 newcontent = []
+639 for t in range(self.T - 1):
+640 if ((self.content[t] is None) or (self.content[t + 1] is None)) or (self.content[t + 1][0].value == 0):
+641 newcontent.append(None)
+642 elif self.content[t][0].value / self.content[t + 1][0].value < 0:
+643 newcontent.append(None)
+644 else:
+645 newcontent.append(self.content[t] / self.content[t + 1])
+646 if (all([x is None for x in newcontent])):
+647 raise Exception('m_eff is undefined at all timeslices')
+648
+649 return np.log(Corr(newcontent, padding=[0, 1]))
+650
+651 elif variant == 'logsym':
+652 newcontent = []
+653 for t in range(1, self.T - 1):
+654 if ((self.content[t - 1] is None) or (self.content[t + 1] is None)) or (self.content[t + 1][0].value == 0):
+655 newcontent.append(None)
+656 elif self.content[t - 1][0].value / self.content[t + 1][0].value < 0:
+657 newcontent.append(None)
+658 else:
+659 newcontent.append(self.content[t - 1] / self.content[t + 1])
+660 if (all([x is None for x in newcontent])):
+661 raise Exception('m_eff is undefined at all timeslices')
+662
+663 return np.log(Corr(newcontent, padding=[1, 1])) / 2
+664
+665 elif variant in ['periodic', 'cosh', 'sinh']:
+666 if variant in ['periodic', 'cosh']:
+667 func = anp.cosh
+668 else:
+669 func = anp.sinh
+670
+671 def root_function(x, d):
+672 return func(x * (t - self.T / 2)) / func(x * (t + 1 - self.T / 2)) - d
673
-674 def root_function(x, d):
-675 return func(x * (t - self.T / 2)) / func(x * (t + 1 - self.T / 2)) - d
-676
-677 newcontent = []
-678 for t in range(self.T - 1):
-679 if (self.content[t] is None) or (self.content[t + 1] is None) or (self.content[t + 1][0].value == 0):
-680 newcontent.append(None)
-681 # Fill the two timeslices in the middle of the lattice with their predecessors
-682 elif variant == 'sinh' and t in [self.T / 2, self.T / 2 - 1]:
-683 newcontent.append(newcontent[-1])
-684 elif self.content[t][0].value / self.content[t + 1][0].value < 0:
-685 newcontent.append(None)
-686 else:
-687 newcontent.append(np.abs(find_root(self.content[t][0] / self.content[t + 1][0], root_function, guess=guess)))
-688 if (all([x is None for x in newcontent])):
-689 raise Exception('m_eff is undefined at all timeslices')
-690
-691 return Corr(newcontent, padding=[0, 1])
-692
-693 elif variant == 'arccosh':
-694 newcontent = []
-695 for t in range(1, self.T - 1):
-696 if (self.content[t] is None) or (self.content[t + 1] is None) or (self.content[t - 1] is None) or (self.content[t][0].value == 0):
-697 newcontent.append(None)
-698 else:
-699 newcontent.append((self.content[t + 1] + self.content[t - 1]) / (2 * self.content[t]))
-700 if (all([x is None for x in newcontent])):
-701 raise Exception("m_eff is undefined at all timeslices")
-702 return np.arccosh(Corr(newcontent, padding=[1, 1]))
-703
-704 else:
-705 raise Exception('Unknown variant.')
+674 newcontent = []
+675 for t in range(self.T - 1):
+676 if (self.content[t] is None) or (self.content[t + 1] is None) or (self.content[t + 1][0].value == 0):
+677 newcontent.append(None)
+678 # Fill the two timeslices in the middle of the lattice with their predecessors
+679 elif variant == 'sinh' and t in [self.T / 2, self.T / 2 - 1]:
+680 newcontent.append(newcontent[-1])
+681 elif self.content[t][0].value / self.content[t + 1][0].value < 0:
+682 newcontent.append(None)
+683 else:
+684 newcontent.append(np.abs(find_root(self.content[t][0] / self.content[t + 1][0], root_function, guess=guess)))
+685 if (all([x is None for x in newcontent])):
+686 raise Exception('m_eff is undefined at all timeslices')
+687
+688 return Corr(newcontent, padding=[0, 1])
+689
+690 elif variant == 'arccosh':
+691 newcontent = []
+692 for t in range(1, self.T - 1):
+693 if (self.content[t] is None) or (self.content[t + 1] is None) or (self.content[t - 1] is None) or (self.content[t][0].value == 0):
+694 newcontent.append(None)
+695 else:
+696 newcontent.append((self.content[t + 1] + self.content[t - 1]) / (2 * self.content[t]))
+697 if (all([x is None for x in newcontent])):
+698 raise Exception("m_eff is undefined at all timeslices")
+699 return np.arccosh(Corr(newcontent, padding=[1, 1]))
+700
+701 else:
+702 raise Exception('Unknown variant.')
@@ -4024,39 +4015,39 @@ guess for the root finder, only relevant for the root variant
- 707 def fit(self, function, fitrange=None, silent=False, **kwargs):
-708 r'''Fits function to the data
-709
-710 Parameters
-711 ----------
-712 function : obj
-713 function to fit to the data. See fits.least_squares for details.
-714 fitrange : list
-715 Two element list containing the timeslices on which the fit is supposed to start and stop.
-716 Caution: This range is inclusive as opposed to standard python indexing.
-717 `fitrange=[4, 6]` corresponds to the three entries 4, 5 and 6.
-718 If not specified, self.prange or all timeslices are used.
-719 silent : bool
-720 Decides whether output is printed to the standard output.
-721 '''
-722 if self.N != 1:
-723 raise Exception("Correlator must be projected before fitting")
-724
-725 if fitrange is None:
-726 if self.prange:
-727 fitrange = self.prange
-728 else:
-729 fitrange = [0, self.T - 1]
-730 else:
-731 if not isinstance(fitrange, list):
-732 raise Exception("fitrange has to be a list with two elements")
-733 if len(fitrange) != 2:
-734 raise Exception("fitrange has to have exactly two elements [fit_start, fit_stop]")
-735
-736 xs = [x for x in range(fitrange[0], fitrange[1] + 1) if not self.content[x] is None]
-737 ys = [self.content[x][0] for x in range(fitrange[0], fitrange[1] + 1) if not self.content[x] is None]
-738 result = least_squares(xs, ys, function, silent=silent, **kwargs)
-739 return result
+ 704 def fit(self, function, fitrange=None, silent=False, **kwargs):
+705 r'''Fits function to the data
+706
+707 Parameters
+708 ----------
+709 function : obj
+710 function to fit to the data. See fits.least_squares for details.
+711 fitrange : list
+712 Two element list containing the timeslices on which the fit is supposed to start and stop.
+713 Caution: This range is inclusive as opposed to standard python indexing.
+714 `fitrange=[4, 6]` corresponds to the three entries 4, 5 and 6.
+715 If not specified, self.prange or all timeslices are used.
+716 silent : bool
+717 Decides whether output is printed to the standard output.
+718 '''
+719 if self.N != 1:
+720 raise Exception("Correlator must be projected before fitting")
+721
+722 if fitrange is None:
+723 if self.prange:
+724 fitrange = self.prange
+725 else:
+726 fitrange = [0, self.T - 1]
+727 else:
+728 if not isinstance(fitrange, list):
+729 raise Exception("fitrange has to be a list with two elements")
+730 if len(fitrange) != 2:
+731 raise Exception("fitrange has to have exactly two elements [fit_start, fit_stop]")
+732
+733 xs = [x for x in range(fitrange[0], fitrange[1] + 1) if not self.content[x] is None]
+734 ys = [self.content[x][0] for x in range(fitrange[0], fitrange[1] + 1) if not self.content[x] is None]
+735 result = least_squares(xs, ys, function, silent=silent, **kwargs)
+736 return result
@@ -4090,42 +4081,42 @@ Decides whether output is printed to the standard output.
- 741 def plateau(self, plateau_range=None, method="fit", auto_gamma=False):
-742 """ Extract a plateau value from a Corr object
-743
-744 Parameters
-745 ----------
-746 plateau_range : list
-747 list with two entries, indicating the first and the last timeslice
-748 of the plateau region.
-749 method : str
-750 method to extract the plateau.
-751 'fit' fits a constant to the plateau region
-752 'avg', 'average' or 'mean' just average over the given timeslices.
-753 auto_gamma : bool
-754 apply gamma_method with default parameters to the Corr. Defaults to None
-755 """
-756 if not plateau_range:
-757 if self.prange:
-758 plateau_range = self.prange
-759 else:
-760 raise Exception("no plateau range provided")
-761 if self.N != 1:
-762 raise Exception("Correlator must be projected before getting a plateau.")
-763 if (all([self.content[t] is None for t in range(plateau_range[0], plateau_range[1] + 1)])):
-764 raise Exception("plateau is undefined at all timeslices in plateaurange.")
-765 if auto_gamma:
-766 self.gamma_method()
-767 if method == "fit":
-768 def const_func(a, t):
-769 return a[0]
-770 return self.fit(const_func, plateau_range)[0]
-771 elif method in ["avg", "average", "mean"]:
-772 returnvalue = np.mean([item[0] for item in self.content[plateau_range[0]:plateau_range[1] + 1] if item is not None])
-773 return returnvalue
-774
-775 else:
-776 raise Exception("Unsupported plateau method: " + method)
+ 738 def plateau(self, plateau_range=None, method="fit", auto_gamma=False):
+739 """ Extract a plateau value from a Corr object
+740
+741 Parameters
+742 ----------
+743 plateau_range : list
+744 list with two entries, indicating the first and the last timeslice
+745 of the plateau region.
+746 method : str
+747 method to extract the plateau.
+748 'fit' fits a constant to the plateau region
+749 'avg', 'average' or 'mean' just average over the given timeslices.
+750 auto_gamma : bool
+751 apply gamma_method with default parameters to the Corr. Defaults to None
+752 """
+753 if not plateau_range:
+754 if self.prange:
+755 plateau_range = self.prange
+756 else:
+757 raise Exception("no plateau range provided")
+758 if self.N != 1:
+759 raise Exception("Correlator must be projected before getting a plateau.")
+760 if (all([self.content[t] is None for t in range(plateau_range[0], plateau_range[1] + 1)])):
+761 raise Exception("plateau is undefined at all timeslices in plateaurange.")
+762 if auto_gamma:
+763 self.gamma_method()
+764 if method == "fit":
+765 def const_func(a, t):
+766 return a[0]
+767 return self.fit(const_func, plateau_range)[0]
+768 elif method in ["avg", "average", "mean"]:
+769 returnvalue = np.mean([item[0] for item in self.content[plateau_range[0]:plateau_range[1] + 1] if item is not None])
+770 return returnvalue
+771
+772 else:
+773 raise Exception("Unsupported plateau method: " + method)
@@ -4159,17 +4150,17 @@ apply gamma_method with default parameters to the Corr. Defaults to None
- 778 def set_prange(self, prange):
-779 """Sets the attribute prange of the Corr object."""
-780 if not len(prange) == 2:
-781 raise Exception("prange must be a list or array with two values")
-782 if not ((isinstance(prange[0], int)) and (isinstance(prange[1], int))):
-783 raise Exception("Start and end point must be integers")
-784 if not (0 <= prange[0] <= self.T and 0 <= prange[1] <= self.T and prange[0] < prange[1]):
-785 raise Exception("Start and end point must define a range in the interval 0,T")
-786
-787 self.prange = prange
-788 return
+ 775 def set_prange(self, prange):
+776 """Sets the attribute prange of the Corr object."""
+777 if not len(prange) == 2:
+778 raise Exception("prange must be a list or array with two values")
+779 if not ((isinstance(prange[0], int)) and (isinstance(prange[1], int))):
+780 raise Exception("Start and end point must be integers")
+781 if not (0 <= prange[0] <= self.T and 0 <= prange[1] <= self.T and prange[0] < prange[1]):
+782 raise Exception("Start and end point must define a range in the interval 0,T")
+783
+784 self.prange = prange
+785 return
@@ -4189,124 +4180,124 @@ apply gamma_method with default parameters to the Corr. Defaults to None
- 790 def show(self, x_range=None, comp=None, y_range=None, logscale=False, plateau=None, fit_res=None, ylabel=None, save=None, auto_gamma=False, hide_sigma=None, references=None, title=None):
-791 """Plots the correlator using the tag of the correlator as label if available.
-792
-793 Parameters
-794 ----------
-795 x_range : list
-796 list of two values, determining the range of the x-axis e.g. [4, 8].
-797 comp : Corr or list of Corr
-798 Correlator or list of correlators which are plotted for comparison.
-799 The tags of these correlators are used as labels if available.
-800 logscale : bool
-801 Sets y-axis to logscale.
-802 plateau : Obs
-803 Plateau value to be visualized in the figure.
-804 fit_res : Fit_result
-805 Fit_result object to be visualized.
-806 ylabel : str
-807 Label for the y-axis.
-808 save : str
-809 path to file in which the figure should be saved.
-810 auto_gamma : bool
-811 Apply the gamma method with standard parameters to all correlators and plateau values before plotting.
-812 hide_sigma : float
-813 Hides data points from the first value on which is consistent with zero within 'hide_sigma' standard errors.
-814 references : list
-815 List of floating point values that are displayed as horizontal lines for reference.
-816 title : string
-817 Optional title of the figure.
-818 """
-819 if self.N != 1:
-820 raise Exception("Correlator must be projected before plotting")
+ 787 def show(self, x_range=None, comp=None, y_range=None, logscale=False, plateau=None, fit_res=None, ylabel=None, save=None, auto_gamma=False, hide_sigma=None, references=None, title=None):
+788 """Plots the correlator using the tag of the correlator as label if available.
+789
+790 Parameters
+791 ----------
+792 x_range : list
+793 list of two values, determining the range of the x-axis e.g. [4, 8].
+794 comp : Corr or list of Corr
+795 Correlator or list of correlators which are plotted for comparison.
+796 The tags of these correlators are used as labels if available.
+797 logscale : bool
+798 Sets y-axis to logscale.
+799 plateau : Obs
+800 Plateau value to be visualized in the figure.
+801 fit_res : Fit_result
+802 Fit_result object to be visualized.
+803 ylabel : str
+804 Label for the y-axis.
+805 save : str
+806 path to file in which the figure should be saved.
+807 auto_gamma : bool
+808 Apply the gamma method with standard parameters to all correlators and plateau values before plotting.
+809 hide_sigma : float
+810 Hides data points from the first value on which is consistent with zero within 'hide_sigma' standard errors.
+811 references : list
+812 List of floating point values that are displayed as horizontal lines for reference.
+813 title : string
+814 Optional title of the figure.
+815 """
+816 if self.N != 1:
+817 raise Exception("Correlator must be projected before plotting")
+818
+819 if auto_gamma:
+820 self.gamma_method()
821
-822 if auto_gamma:
-823 self.gamma_method()
+822 if x_range is None:
+823 x_range = [0, self.T - 1]
824
-825 if x_range is None:
-826 x_range = [0, self.T - 1]
+825 fig = plt.figure()
+826 ax1 = fig.add_subplot(111)
827
-828 fig = plt.figure()
-829 ax1 = fig.add_subplot(111)
-830
-831 x, y, y_err = self.plottable()
-832 if hide_sigma:
-833 hide_from = np.argmax((hide_sigma * np.array(y_err[1:])) > np.abs(y[1:])) - 1
-834 else:
-835 hide_from = None
-836 ax1.errorbar(x[:hide_from], y[:hide_from], y_err[:hide_from], label=self.tag)
-837 if logscale:
-838 ax1.set_yscale('log')
-839 else:
-840 if y_range is None:
-841 try:
-842 y_min = min([(x[0].value - x[0].dvalue) for x in self.content[x_range[0]: x_range[1] + 1] if (x is not None) and x[0].dvalue < 2 * np.abs(x[0].value)])
-843 y_max = max([(x[0].value + x[0].dvalue) for x in self.content[x_range[0]: x_range[1] + 1] if (x is not None) and x[0].dvalue < 2 * np.abs(x[0].value)])
-844 ax1.set_ylim([y_min - 0.1 * (y_max - y_min), y_max + 0.1 * (y_max - y_min)])
-845 except Exception:
-846 pass
-847 else:
-848 ax1.set_ylim(y_range)
-849 if comp:
-850 if isinstance(comp, (Corr, list)):
-851 for corr in comp if isinstance(comp, list) else [comp]:
-852 if auto_gamma:
-853 corr.gamma_method()
-854 x, y, y_err = corr.plottable()
-855 if hide_sigma:
-856 hide_from = np.argmax((hide_sigma * np.array(y_err[1:])) > np.abs(y[1:])) - 1
-857 else:
-858 hide_from = None
-859 ax1.errorbar(x[:hide_from], y[:hide_from], y_err[:hide_from], label=corr.tag, mfc=plt.rcParams['axes.facecolor'])
-860 else:
-861 raise Exception("'comp' must be a correlator or a list of correlators.")
-862
-863 if plateau:
-864 if isinstance(plateau, Obs):
-865 if auto_gamma:
-866 plateau.gamma_method()
-867 ax1.axhline(y=plateau.value, linewidth=2, color=plt.rcParams['text.color'], alpha=0.6, marker=',', ls='--', label=str(plateau))
-868 ax1.axhspan(plateau.value - plateau.dvalue, plateau.value + plateau.dvalue, alpha=0.25, color=plt.rcParams['text.color'], ls='-')
-869 else:
-870 raise Exception("'plateau' must be an Obs")
-871
-872 if references:
-873 if isinstance(references, list):
-874 for ref in references:
-875 ax1.axhline(y=ref, linewidth=1, color=plt.rcParams['text.color'], alpha=0.6, marker=',', ls='--')
-876 else:
-877 raise Exception("'references' must be a list of floating pint values.")
-878
-879 if self.prange:
-880 ax1.axvline(self.prange[0], 0, 1, ls='-', marker=',')
-881 ax1.axvline(self.prange[1], 0, 1, ls='-', marker=',')
-882
-883 if fit_res:
-884 x_samples = np.arange(x_range[0], x_range[1] + 1, 0.05)
-885 ax1.plot(x_samples,
-886 fit_res.fit_function([o.value for o in fit_res.fit_parameters], x_samples),
-887 ls='-', marker=',', lw=2)
-888
-889 ax1.set_xlabel(r'$x_0 / a$')
-890 if ylabel:
-891 ax1.set_ylabel(ylabel)
-892 ax1.set_xlim([x_range[0] - 0.5, x_range[1] + 0.5])
-893
-894 handles, labels = ax1.get_legend_handles_labels()
-895 if labels:
-896 ax1.legend()
+828 x, y, y_err = self.plottable()
+829 if hide_sigma:
+830 hide_from = np.argmax((hide_sigma * np.array(y_err[1:])) > np.abs(y[1:])) - 1
+831 else:
+832 hide_from = None
+833 ax1.errorbar(x[:hide_from], y[:hide_from], y_err[:hide_from], label=self.tag)
+834 if logscale:
+835 ax1.set_yscale('log')
+836 else:
+837 if y_range is None:
+838 try:
+839 y_min = min([(x[0].value - x[0].dvalue) for x in self.content[x_range[0]: x_range[1] + 1] if (x is not None) and x[0].dvalue < 2 * np.abs(x[0].value)])
+840 y_max = max([(x[0].value + x[0].dvalue) for x in self.content[x_range[0]: x_range[1] + 1] if (x is not None) and x[0].dvalue < 2 * np.abs(x[0].value)])
+841 ax1.set_ylim([y_min - 0.1 * (y_max - y_min), y_max + 0.1 * (y_max - y_min)])
+842 except Exception:
+843 pass
+844 else:
+845 ax1.set_ylim(y_range)
+846 if comp:
+847 if isinstance(comp, (Corr, list)):
+848 for corr in comp if isinstance(comp, list) else [comp]:
+849 if auto_gamma:
+850 corr.gamma_method()
+851 x, y, y_err = corr.plottable()
+852 if hide_sigma:
+853 hide_from = np.argmax((hide_sigma * np.array(y_err[1:])) > np.abs(y[1:])) - 1
+854 else:
+855 hide_from = None
+856 ax1.errorbar(x[:hide_from], y[:hide_from], y_err[:hide_from], label=corr.tag, mfc=plt.rcParams['axes.facecolor'])
+857 else:
+858 raise Exception("'comp' must be a correlator or a list of correlators.")
+859
+860 if plateau:
+861 if isinstance(plateau, Obs):
+862 if auto_gamma:
+863 plateau.gamma_method()
+864 ax1.axhline(y=plateau.value, linewidth=2, color=plt.rcParams['text.color'], alpha=0.6, marker=',', ls='--', label=str(plateau))
+865 ax1.axhspan(plateau.value - plateau.dvalue, plateau.value + plateau.dvalue, alpha=0.25, color=plt.rcParams['text.color'], ls='-')
+866 else:
+867 raise Exception("'plateau' must be an Obs")
+868
+869 if references:
+870 if isinstance(references, list):
+871 for ref in references:
+872 ax1.axhline(y=ref, linewidth=1, color=plt.rcParams['text.color'], alpha=0.6, marker=',', ls='--')
+873 else:
+874 raise Exception("'references' must be a list of floating pint values.")
+875
+876 if self.prange:
+877 ax1.axvline(self.prange[0], 0, 1, ls='-', marker=',')
+878 ax1.axvline(self.prange[1], 0, 1, ls='-', marker=',')
+879
+880 if fit_res:
+881 x_samples = np.arange(x_range[0], x_range[1] + 1, 0.05)
+882 ax1.plot(x_samples,
+883 fit_res.fit_function([o.value for o in fit_res.fit_parameters], x_samples),
+884 ls='-', marker=',', lw=2)
+885
+886 ax1.set_xlabel(r'$x_0 / a$')
+887 if ylabel:
+888 ax1.set_ylabel(ylabel)
+889 ax1.set_xlim([x_range[0] - 0.5, x_range[1] + 0.5])
+890
+891 handles, labels = ax1.get_legend_handles_labels()
+892 if labels:
+893 ax1.legend()
+894
+895 if title:
+896 plt.title(title)
897
-898 if title:
-899 plt.title(title)
-900
-901 plt.draw()
-902
-903 if save:
-904 if isinstance(save, str):
-905 fig.savefig(save, bbox_inches='tight')
-906 else:
-907 raise Exception("'save' has to be a string.")
+898 plt.draw()
+899
+900 if save:
+901 if isinstance(save, str):
+902 fig.savefig(save, bbox_inches='tight')
+903 else:
+904 raise Exception("'save' has to be a string.")
@@ -4354,34 +4345,34 @@ Optional title of the figure.
- 909 def spaghetti_plot(self, logscale=True):
-910 """Produces a spaghetti plot of the correlator suited to monitor exceptional configurations.
-911
-912 Parameters
-913 ----------
-914 logscale : bool
-915 Determines whether the scale of the y-axis is logarithmic or standard.
-916 """
-917 if self.N != 1:
-918 raise Exception("Correlator needs to be projected first.")
+ 906 def spaghetti_plot(self, logscale=True):
+907 """Produces a spaghetti plot of the correlator suited to monitor exceptional configurations.
+908
+909 Parameters
+910 ----------
+911 logscale : bool
+912 Determines whether the scale of the y-axis is logarithmic or standard.
+913 """
+914 if self.N != 1:
+915 raise Exception("Correlator needs to be projected first.")
+916
+917 mc_names = list(set([item for sublist in [sum(map(o[0].e_content.get, o[0].mc_names), []) for o in self.content if o is not None] for item in sublist]))
+918 x0_vals = [n for (n, o) in zip(np.arange(self.T), self.content) if o is not None]
919
-920 mc_names = list(set([item for sublist in [sum(map(o[0].e_content.get, o[0].mc_names), []) for o in self.content if o is not None] for item in sublist]))
-921 x0_vals = [n for (n, o) in zip(np.arange(self.T), self.content) if o is not None]
+920 for name in mc_names:
+921 data = np.array([o[0].deltas[name] + o[0].r_values[name] for o in self.content if o is not None]).T
922
-923 for name in mc_names:
-924 data = np.array([o[0].deltas[name] + o[0].r_values[name] for o in self.content if o is not None]).T
-925
-926 fig = plt.figure()
-927 ax = fig.add_subplot(111)
-928 for dat in data:
-929 ax.plot(x0_vals, dat, ls='-', marker='')
+923 fig = plt.figure()
+924 ax = fig.add_subplot(111)
+925 for dat in data:
+926 ax.plot(x0_vals, dat, ls='-', marker='')
+927
+928 if logscale is True:
+929 ax.set_yscale('log')
930
-931 if logscale is True:
-932 ax.set_yscale('log')
-933
-934 ax.set_xlabel(r'$x_0 / a$')
-935 plt.title(name)
-936 plt.draw()
+931 ax.set_xlabel(r'$x_0 / a$')
+932 plt.title(name)
+933 plt.draw()
@@ -4408,29 +4399,29 @@ Determines whether the scale of the y-axis is logarithmic or standard.
- 938 def dump(self, filename, datatype="json.gz", **kwargs):
-939 """Dumps the Corr into a file of chosen type
-940 Parameters
-941 ----------
-942 filename : str
-943 Name of the file to be saved.
-944 datatype : str
-945 Format of the exported file. Supported formats include
-946 "json.gz" and "pickle"
-947 path : str
-948 specifies a custom path for the file (default '.')
-949 """
-950 if datatype == "json.gz":
-951 from .input.json import dump_to_json
-952 if 'path' in kwargs:
-953 file_name = kwargs.get('path') + '/' + filename
-954 else:
-955 file_name = filename
-956 dump_to_json(self, file_name)
-957 elif datatype == "pickle":
-958 dump_object(self, filename, **kwargs)
-959 else:
-960 raise Exception("Unknown datatype " + str(datatype))
+ 935 def dump(self, filename, datatype="json.gz", **kwargs):
+936 """Dumps the Corr into a file of chosen type
+937 Parameters
+938 ----------
+939 filename : str
+940 Name of the file to be saved.
+941 datatype : str
+942 Format of the exported file. Supported formats include
+943 "json.gz" and "pickle"
+944 path : str
+945 specifies a custom path for the file (default '.')
+946 """
+947 if datatype == "json.gz":
+948 from .input.json import dump_to_json
+949 if 'path' in kwargs:
+950 file_name = kwargs.get('path') + '/' + filename
+951 else:
+952 file_name = filename
+953 dump_to_json(self, file_name)
+954 elif datatype == "pickle":
+955 dump_object(self, filename, **kwargs)
+956 else:
+957 raise Exception("Unknown datatype " + str(datatype))
@@ -4462,8 +4453,8 @@ specifies a custom path for the file (default '.')
- 962 def print(self, print_range=None):
-963 print(self.__repr__(print_range))
+ 959 def print(self, print_range=None):
+960 print(self.__repr__(print_range))
@@ -4481,8 +4472,8 @@ specifies a custom path for the file (default '.')
- 1127 def sqrt(self):
-1128 return self ** 0.5
+ 1124 def sqrt(self):
+1125 return self ** 0.5
@@ -4500,9 +4491,9 @@ specifies a custom path for the file (default '.')
- 1130 def log(self):
-1131 newcontent = [None if _check_for_none(self, item) else np.log(item) for item in self.content]
-1132 return Corr(newcontent, prange=self.prange)
+ 1127 def log(self):
+1128 newcontent = [None if _check_for_none(self, item) else np.log(item) for item in self.content]
+1129 return Corr(newcontent, prange=self.prange)
@@ -4520,9 +4511,9 @@ specifies a custom path for the file (default '.')
- 1134 def exp(self):
-1135 newcontent = [None if _check_for_none(self, item) else np.exp(item) for item in self.content]
-1136 return Corr(newcontent, prange=self.prange)
+ 1131 def exp(self):
+1132 newcontent = [None if _check_for_none(self, item) else np.exp(item) for item in self.content]
+1133 return Corr(newcontent, prange=self.prange)
@@ -4540,8 +4531,8 @@ specifies a custom path for the file (default '.')
- 1149 def sin(self):
-1150 return self._apply_func_to_corr(np.sin)
+ 1146 def sin(self):
+1147 return self._apply_func_to_corr(np.sin)
@@ -4559,8 +4550,8 @@ specifies a custom path for the file (default '.')
- 1152 def cos(self):
-1153 return self._apply_func_to_corr(np.cos)
+ 1149 def cos(self):
+1150 return self._apply_func_to_corr(np.cos)
@@ -4578,8 +4569,8 @@ specifies a custom path for the file (default '.')
- 1155 def tan(self):
-1156 return self._apply_func_to_corr(np.tan)
+ 1152 def tan(self):
+1153 return self._apply_func_to_corr(np.tan)
@@ -4597,8 +4588,8 @@ specifies a custom path for the file (default '.')
- 1158 def sinh(self):
-1159 return self._apply_func_to_corr(np.sinh)
+ 1155 def sinh(self):
+1156 return self._apply_func_to_corr(np.sinh)
@@ -4616,8 +4607,8 @@ specifies a custom path for the file (default '.')
- 1161 def cosh(self):
-1162 return self._apply_func_to_corr(np.cosh)
+ 1158 def cosh(self):
+1159 return self._apply_func_to_corr(np.cosh)
@@ -4635,8 +4626,8 @@ specifies a custom path for the file (default '.')
- 1164 def tanh(self):
-1165 return self._apply_func_to_corr(np.tanh)
+ 1161 def tanh(self):
+1162 return self._apply_func_to_corr(np.tanh)
@@ -4654,8 +4645,8 @@ specifies a custom path for the file (default '.')
- 1167 def arcsin(self):
-1168 return self._apply_func_to_corr(np.arcsin)
+ 1164 def arcsin(self):
+1165 return self._apply_func_to_corr(np.arcsin)
@@ -4673,8 +4664,8 @@ specifies a custom path for the file (default '.')
- 1170 def arccos(self):
-1171 return self._apply_func_to_corr(np.arccos)
+ 1167 def arccos(self):
+1168 return self._apply_func_to_corr(np.arccos)
@@ -4692,8 +4683,8 @@ specifies a custom path for the file (default '.')
- 1173 def arctan(self):
-1174 return self._apply_func_to_corr(np.arctan)
+ 1170 def arctan(self):
+1171 return self._apply_func_to_corr(np.arctan)
@@ -4711,8 +4702,8 @@ specifies a custom path for the file (default '.')
- 1176 def arcsinh(self):
-1177 return self._apply_func_to_corr(np.arcsinh)
+ 1173 def arcsinh(self):
+1174 return self._apply_func_to_corr(np.arcsinh)
@@ -4730,8 +4721,8 @@ specifies a custom path for the file (default '.')
- 1179 def arccosh(self):
-1180 return self._apply_func_to_corr(np.arccosh)
+ 1176 def arccosh(self):
+1177 return self._apply_func_to_corr(np.arccosh)
@@ -4749,8 +4740,8 @@ specifies a custom path for the file (default '.')
- 1182 def arctanh(self):
-1183 return self._apply_func_to_corr(np.arctanh)
+ 1179 def arctanh(self):
+1180 return self._apply_func_to_corr(np.arctanh)
@@ -4768,62 +4759,62 @@ specifies a custom path for the file (default '.')
- 1218 def prune(self, Ntrunc, tproj=3, t0proj=2, basematrix=None):
-1219 r''' Project large correlation matrix to lowest states
-1220
-1221 This method can be used to reduce the size of an (N x N) correlation matrix
-1222 to (Ntrunc x Ntrunc) by solving a GEVP at very early times where the noise
-1223 is still small.
-1224
-1225 Parameters
-1226 ----------
-1227 Ntrunc: int
-1228 Rank of the target matrix.
-1229 tproj: int
-1230 Time where the eigenvectors are evaluated, corresponds to ts in the GEVP method.
-1231 The default value is 3.
-1232 t0proj: int
-1233 Time where the correlation matrix is inverted. Choosing t0proj=1 is strongly
-1234 discouraged for O(a) improved theories, since the correctness of the procedure
-1235 cannot be granted in this case. The default value is 2.
-1236 basematrix : Corr
-1237 Correlation matrix that is used to determine the eigenvectors of the
-1238 lowest states based on a GEVP. basematrix is taken to be the Corr itself if
-1239 is is not specified.
-1240
-1241 Notes
-1242 -----
-1243 We have the basematrix $C(t)$ and the target matrix $G(t)$. We start by solving
-1244 the GEVP $$C(t) v_n(t, t_0) = \lambda_n(t, t_0) C(t_0) v_n(t, t_0)$$ where $t \equiv t_\mathrm{proj}$
-1245 and $t_0 \equiv t_{0, \mathrm{proj}}$. The target matrix is projected onto the subspace of the
-1246 resulting eigenvectors $v_n, n=1,\dots,N_\mathrm{trunc}$ via
-1247 $$G^\prime_{i, j}(t) = (v_i, G(t) v_j)$$. This allows to reduce the size of a large
-1248 correlation matrix and to remove some noise that is added by irrelevant operators.
-1249 This may allow to use the GEVP on $G(t)$ at late times such that the theoretically motivated
-1250 bound $t_0 \leq t/2$ holds, since the condition number of $G(t)$ is decreased, compared to $C(t)$.
-1251 '''
-1252
-1253 if self.N == 1:
-1254 raise Exception('Method cannot be applied to one-dimensional correlators.')
-1255 if basematrix is None:
-1256 basematrix = self
-1257 if Ntrunc >= basematrix.N:
-1258 raise Exception('Cannot truncate using Ntrunc <= %d' % (basematrix.N))
-1259 if basematrix.N != self.N:
-1260 raise Exception('basematrix and targetmatrix have to be of the same size.')
-1261
-1262 evecs = basematrix.GEVP(t0proj, tproj, sort=None)[:Ntrunc]
-1263
-1264 tmpmat = np.empty((Ntrunc, Ntrunc), dtype=object)
-1265 rmat = []
-1266 for t in range(basematrix.T):
-1267 for i in range(Ntrunc):
-1268 for j in range(Ntrunc):
-1269 tmpmat[i][j] = evecs[i].T @ self[t] @ evecs[j]
-1270 rmat.append(np.copy(tmpmat))
-1271
-1272 newcontent = [None if (self.content[t] is None) else rmat[t] for t in range(self.T)]
-1273 return Corr(newcontent)
+ 1215 def prune(self, Ntrunc, tproj=3, t0proj=2, basematrix=None):
+1216 r''' Project large correlation matrix to lowest states
+1217
+1218 This method can be used to reduce the size of an (N x N) correlation matrix
+1219 to (Ntrunc x Ntrunc) by solving a GEVP at very early times where the noise
+1220 is still small.
+1221
+1222 Parameters
+1223 ----------
+1224 Ntrunc: int
+1225 Rank of the target matrix.
+1226 tproj: int
+1227 Time where the eigenvectors are evaluated, corresponds to ts in the GEVP method.
+1228 The default value is 3.
+1229 t0proj: int
+1230 Time where the correlation matrix is inverted. Choosing t0proj=1 is strongly
+1231 discouraged for O(a) improved theories, since the correctness of the procedure
+1232 cannot be granted in this case. The default value is 2.
+1233 basematrix : Corr
+1234 Correlation matrix that is used to determine the eigenvectors of the
+1235 lowest states based on a GEVP. basematrix is taken to be the Corr itself if
+1236 is is not specified.
+1237
+1238 Notes
+1239 -----
+1240 We have the basematrix $C(t)$ and the target matrix $G(t)$. We start by solving
+1241 the GEVP $$C(t) v_n(t, t_0) = \lambda_n(t, t_0) C(t_0) v_n(t, t_0)$$ where $t \equiv t_\mathrm{proj}$
+1242 and $t_0 \equiv t_{0, \mathrm{proj}}$. The target matrix is projected onto the subspace of the
+1243 resulting eigenvectors $v_n, n=1,\dots,N_\mathrm{trunc}$ via
+1244 $$G^\prime_{i, j}(t) = (v_i, G(t) v_j)$$. This allows to reduce the size of a large
+1245 correlation matrix and to remove some noise that is added by irrelevant operators.
+1246 This may allow to use the GEVP on $G(t)$ at late times such that the theoretically motivated
+1247 bound $t_0 \leq t/2$ holds, since the condition number of $G(t)$ is decreased, compared to $C(t)$.
+1248 '''
+1249
+1250 if self.N == 1:
+1251 raise Exception('Method cannot be applied to one-dimensional correlators.')
+1252 if basematrix is None:
+1253 basematrix = self
+1254 if Ntrunc >= basematrix.N:
+1255 raise Exception('Cannot truncate using Ntrunc <= %d' % (basematrix.N))
+1256 if basematrix.N != self.N:
+1257 raise Exception('basematrix and targetmatrix have to be of the same size.')
+1258
+1259 evecs = basematrix.GEVP(t0proj, tproj, sort=None)[:Ntrunc]
+1260
+1261 tmpmat = np.empty((Ntrunc, Ntrunc), dtype=object)
+1262 rmat = []
+1263 for t in range(basematrix.T):
+1264 for i in range(Ntrunc):
+1265 for j in range(Ntrunc):
+1266 tmpmat[i][j] = evecs[i].T @ self[t] @ evecs[j]
+1267 rmat.append(np.copy(tmpmat))
+1268
+1269 newcontent = [None if (self.content[t] is None) else rmat[t] for t in range(self.T)]
+1270 return Corr(newcontent)