From 0fbebca81faa433797113f11eeff0fda1c950664 Mon Sep 17 00:00:00 2001
From: fjosw
Date: Tue, 3 May 2022 09:52:21 +0000
Subject: [PATCH] Documentation updated
---
docs/pyerrors/correlators.html | 5082 ++++++++++++++++----------------
1 file changed, 2547 insertions(+), 2535 deletions(-)
diff --git a/docs/pyerrors/correlators.html b/docs/pyerrors/correlators.html
index 3ee8379c..e5a8d81c 100644
--- a/docs/pyerrors/correlators.html
+++ b/docs/pyerrors/correlators.html
@@ -471,963 +471,967 @@
258 "Eigenvector" - Use the method described in arXiv:2004.10472 [hep-lat] to find the set of v(t) belonging to the state.
259 The reference state is identified by its eigenvalue at t=ts
260 """
- 261 symmetric_corr = self.matrix_symmetric()
- 262 if sorted_list is None:
- 263 if (ts is None):
- 264 raise Exception("ts is required if sorted_list=None")
- 265 if (self.content[t0] is None) or (self.content[ts] is None):
- 266 raise Exception("Corr not defined at t0/ts")
- 267 G0, Gt = np.empty([self.N, self.N], dtype="double"), np.empty([self.N, self.N], dtype="double")
- 268 for i in range(self.N):
- 269 for j in range(self.N):
- 270 G0[i, j] = symmetric_corr[t0][i, j].value
- 271 Gt[i, j] = symmetric_corr[ts][i, j].value
- 272
- 273 sp_vecs = _GEVP_solver(Gt, G0)
- 274 sp_vec = sp_vecs[state]
- 275 return sp_vec
- 276 elif sorted_list in ["Eigenvalue", "Eigenvector"]:
- 277 all_vecs = []
- 278 for t in range(self.T):
- 279 try:
- 280 G0, Gt = np.empty([self.N, self.N], dtype="double"), np.empty([self.N, self.N], dtype="double")
- 281 for i in range(self.N):
- 282 for j in range(self.N):
- 283 G0[i, j] = symmetric_corr[t0][i, j].value
- 284 Gt[i, j] = symmetric_corr[t][i, j].value
- 285
- 286 sp_vecs = _GEVP_solver(Gt, G0)
- 287 if sorted_list == "Eigenvalue":
- 288 sp_vec = sp_vecs[state]
- 289 all_vecs.append(sp_vec)
- 290 else:
- 291 all_vecs.append(sp_vecs)
- 292 except Exception:
- 293 all_vecs.append(None)
- 294 if sorted_list == "Eigenvector":
- 295 if (ts is None):
- 296 raise Exception("ts is required for the Eigenvector sorting method.")
- 297 all_vecs = _sort_vectors(all_vecs, ts)
- 298 all_vecs = [a[state] for a in all_vecs]
- 299 else:
- 300 raise Exception("Unkown value for 'sorted_list'.")
- 301
- 302 return all_vecs
- 303
- 304 def Eigenvalue(self, t0, ts=None, state=0, sorted_list=None):
- 305 """Determines the eigenvalue of the GEVP by solving and projecting the correlator
- 306
- 307 Parameters
- 308 ----------
- 309 t0 : int
- 310 The time t0 for G(t)v= lambda G(t_0)v
- 311 ts : int
- 312 fixed time G(t_s)v= lambda G(t_0)v if return_list=False
- 313 If return_list=True and sorting=Eigenvector it gives a reference point for the sorting method.
- 314 state : int
- 315 The state one is interested in ordered by energy. The lowest state is zero.
- 316 sorted_list : string
- 317 if this argument is set, a list of vectors (len=self.T) is returned. If it is left as None, only one vector is returned.
- 318 "Eigenvalue" - The eigenvector is chosen according to which eigenvalue it belongs individually on every timeslice.
- 319 "Eigenvector" - Use the method described in arXiv:2004.10472 [hep-lat] to find the set of v(t) belonging to the state.
- 320 The reference state is identified by its eigenvalue at t=ts
- 321 """
- 322 vec = self.GEVP(t0, ts=ts, state=state, sorted_list=sorted_list)
- 323 return self.projected(vec)
- 324
- 325 def Hankel(self, N, periodic=False):
- 326 """Constructs an NxN Hankel matrix
- 327
- 328 C(t) c(t+1) ... c(t+n-1)
- 329 C(t+1) c(t+2) ... c(t+n)
- 330 .................
- 331 C(t+(n-1)) c(t+n) ... c(t+2(n-1))
- 332
- 333 Parameters
- 334 ----------
- 335 N : int
- 336 Dimension of the Hankel matrix
- 337 periodic : bool, optional
- 338 determines whether the matrix is extended periodically
- 339 """
- 340
- 341 if self.N != 1:
- 342 raise Exception("Multi-operator Prony not implemented!")
- 343
- 344 array = np.empty([N, N], dtype="object")
- 345 new_content = []
- 346 for t in range(self.T):
- 347 new_content.append(array.copy())
- 348
- 349 def wrap(i):
- 350 while i >= self.T:
- 351 i -= self.T
- 352 return i
- 353
- 354 for t in range(self.T):
- 355 for i in range(N):
- 356 for j in range(N):
- 357 if periodic:
- 358 new_content[t][i, j] = self.content[wrap(t + i + j)][0]
- 359 elif (t + i + j) >= self.T:
- 360 new_content[t] = None
- 361 else:
- 362 new_content[t][i, j] = self.content[t + i + j][0]
- 363
- 364 return Corr(new_content)
- 365
- 366 def roll(self, dt):
- 367 """Periodically shift the correlator by dt timeslices
- 368
- 369 Parameters
- 370 ----------
- 371 dt : int
- 372 number of timeslices
- 373 """
- 374 return Corr(list(np.roll(np.array(self.content, dtype=object), dt)))
- 375
- 376 def reverse(self):
- 377 """Reverse the time ordering of the Corr"""
- 378 return Corr(self.content[:: -1])
+ 261
+ 262 if self.N == 1:
+ 263 raise Exception("GEVP methods only works on correlator matrices and not single correlators.")
+ 264
+ 265 symmetric_corr = self.matrix_symmetric()
+ 266 if sorted_list is None:
+ 267 if (ts is None):
+ 268 raise Exception("ts is required if sorted_list=None")
+ 269 if (self.content[t0] is None) or (self.content[ts] is None):
+ 270 raise Exception("Corr not defined at t0/ts")
+ 271 G0, Gt = np.empty([self.N, self.N], dtype="double"), np.empty([self.N, self.N], dtype="double")
+ 272 for i in range(self.N):
+ 273 for j in range(self.N):
+ 274 G0[i, j] = symmetric_corr[t0][i, j].value
+ 275 Gt[i, j] = symmetric_corr[ts][i, j].value
+ 276
+ 277 sp_vecs = _GEVP_solver(Gt, G0)
+ 278 sp_vec = sp_vecs[state]
+ 279 return sp_vec
+ 280 elif sorted_list in ["Eigenvalue", "Eigenvector"]:
+ 281 all_vecs = []
+ 282 for t in range(self.T):
+ 283 try:
+ 284 G0, Gt = np.empty([self.N, self.N], dtype="double"), np.empty([self.N, self.N], dtype="double")
+ 285 for i in range(self.N):
+ 286 for j in range(self.N):
+ 287 G0[i, j] = symmetric_corr[t0][i, j].value
+ 288 Gt[i, j] = symmetric_corr[t][i, j].value
+ 289
+ 290 sp_vecs = _GEVP_solver(Gt, G0)
+ 291 if sorted_list == "Eigenvalue":
+ 292 sp_vec = sp_vecs[state]
+ 293 all_vecs.append(sp_vec)
+ 294 else:
+ 295 all_vecs.append(sp_vecs)
+ 296 except Exception:
+ 297 all_vecs.append(None)
+ 298 if sorted_list == "Eigenvector":
+ 299 if (ts is None):
+ 300 raise Exception("ts is required for the Eigenvector sorting method.")
+ 301 all_vecs = _sort_vectors(all_vecs, ts)
+ 302 all_vecs = [a[state] for a in all_vecs]
+ 303 else:
+ 304 raise Exception("Unkown value for 'sorted_list'.")
+ 305
+ 306 return all_vecs
+ 307
+ 308 def Eigenvalue(self, t0, ts=None, state=0, sorted_list=None):
+ 309 """Determines the eigenvalue of the GEVP by solving and projecting the correlator
+ 310
+ 311 Parameters
+ 312 ----------
+ 313 t0 : int
+ 314 The time t0 for G(t)v= lambda G(t_0)v
+ 315 ts : int
+ 316 fixed time G(t_s)v= lambda G(t_0)v if return_list=False
+ 317 If return_list=True and sorting=Eigenvector it gives a reference point for the sorting method.
+ 318 state : int
+ 319 The state one is interested in ordered by energy. The lowest state is zero.
+ 320 sorted_list : string
+ 321 if this argument is set, a list of vectors (len=self.T) is returned. If it is left as None, only one vector is returned.
+ 322 "Eigenvalue" - The eigenvector is chosen according to which eigenvalue it belongs individually on every timeslice.
+ 323 "Eigenvector" - Use the method described in arXiv:2004.10472 [hep-lat] to find the set of v(t) belonging to the state.
+ 324 The reference state is identified by its eigenvalue at t=ts
+ 325 """
+ 326 vec = self.GEVP(t0, ts=ts, state=state, sorted_list=sorted_list)
+ 327 return self.projected(vec)
+ 328
+ 329 def Hankel(self, N, periodic=False):
+ 330 """Constructs an NxN Hankel matrix
+ 331
+ 332 C(t) c(t+1) ... c(t+n-1)
+ 333 C(t+1) c(t+2) ... c(t+n)
+ 334 .................
+ 335 C(t+(n-1)) c(t+n) ... c(t+2(n-1))
+ 336
+ 337 Parameters
+ 338 ----------
+ 339 N : int
+ 340 Dimension of the Hankel matrix
+ 341 periodic : bool, optional
+ 342 determines whether the matrix is extended periodically
+ 343 """
+ 344
+ 345 if self.N != 1:
+ 346 raise Exception("Multi-operator Prony not implemented!")
+ 347
+ 348 array = np.empty([N, N], dtype="object")
+ 349 new_content = []
+ 350 for t in range(self.T):
+ 351 new_content.append(array.copy())
+ 352
+ 353 def wrap(i):
+ 354 while i >= self.T:
+ 355 i -= self.T
+ 356 return i
+ 357
+ 358 for t in range(self.T):
+ 359 for i in range(N):
+ 360 for j in range(N):
+ 361 if periodic:
+ 362 new_content[t][i, j] = self.content[wrap(t + i + j)][0]
+ 363 elif (t + i + j) >= self.T:
+ 364 new_content[t] = None
+ 365 else:
+ 366 new_content[t][i, j] = self.content[t + i + j][0]
+ 367
+ 368 return Corr(new_content)
+ 369
+ 370 def roll(self, dt):
+ 371 """Periodically shift the correlator by dt timeslices
+ 372
+ 373 Parameters
+ 374 ----------
+ 375 dt : int
+ 376 number of timeslices
+ 377 """
+ 378 return Corr(list(np.roll(np.array(self.content, dtype=object), dt)))
379
- 380 def thin(self, spacing=2, offset=0):
- 381 """Thin out a correlator to suppress correlations
- 382
- 383 Parameters
- 384 ----------
- 385 spacing : int
- 386 Keep only every 'spacing'th entry of the correlator
- 387 offset : int
- 388 Offset the equal spacing
- 389 """
- 390 new_content = []
- 391 for t in range(self.T):
- 392 if (offset + t) % spacing != 0:
- 393 new_content.append(None)
- 394 else:
- 395 new_content.append(self.content[t])
- 396 return Corr(new_content)
- 397
- 398 def correlate(self, partner):
- 399 """Correlate the correlator with another correlator or Obs
- 400
- 401 Parameters
- 402 ----------
- 403 partner : Obs or Corr
- 404 partner to correlate the correlator with.
- 405 Can either be an Obs which is correlated with all entries of the
- 406 correlator or a Corr of same length.
- 407 """
- 408 new_content = []
- 409 for x0, t_slice in enumerate(self.content):
- 410 if t_slice is None:
- 411 new_content.append(None)
- 412 else:
- 413 if isinstance(partner, Corr):
- 414 if partner.content[x0] is None:
- 415 new_content.append(None)
- 416 else:
- 417 new_content.append(np.array([correlate(o, partner.content[x0][0]) for o in t_slice]))
- 418 elif isinstance(partner, Obs): # Should this include CObs?
- 419 new_content.append(np.array([correlate(o, partner) for o in t_slice]))
- 420 else:
- 421 raise Exception("Can only correlate with an Obs or a Corr.")
- 422
- 423 return Corr(new_content)
- 424
- 425 def reweight(self, weight, **kwargs):
- 426 """Reweight the correlator.
- 427
- 428 Parameters
- 429 ----------
- 430 weight : Obs
- 431 Reweighting factor. An Observable that has to be defined on a superset of the
- 432 configurations in obs[i].idl for all i.
- 433 all_configs : bool
- 434 if True, the reweighted observables are normalized by the average of
- 435 the reweighting factor on all configurations in weight.idl and not
- 436 on the configurations in obs[i].idl.
- 437 """
- 438 new_content = []
- 439 for t_slice in self.content:
- 440 if t_slice is None:
- 441 new_content.append(None)
- 442 else:
- 443 new_content.append(np.array(reweight(weight, t_slice, **kwargs)))
- 444 return Corr(new_content)
- 445
- 446 def T_symmetry(self, partner, parity=+1):
- 447 """Return the time symmetry average of the correlator and its partner
- 448
- 449 Parameters
- 450 ----------
- 451 partner : Corr
- 452 Time symmetry partner of the Corr
- 453 partity : int
- 454 Parity quantum number of the correlator, can be +1 or -1
- 455 """
- 456 if not isinstance(partner, Corr):
- 457 raise Exception("T partner has to be a Corr object.")
- 458 if parity not in [+1, -1]:
- 459 raise Exception("Parity has to be +1 or -1.")
- 460 T_partner = parity * partner.reverse()
- 461
- 462 t_slices = []
- 463 test = (self - T_partner)
- 464 test.gamma_method()
- 465 for x0, t_slice in enumerate(test.content):
- 466 if t_slice is not None:
- 467 if not t_slice[0].is_zero_within_error(5):
- 468 t_slices.append(x0)
- 469 if t_slices:
- 470 warnings.warn("T symmetry partners do not agree within 5 sigma on time slices " + str(t_slices) + ".", RuntimeWarning)
- 471
- 472 return (self + T_partner) / 2
- 473
- 474 def deriv(self, variant="symmetric"):
- 475 """Return the first derivative of the correlator with respect to x0.
- 476
- 477 Parameters
- 478 ----------
- 479 variant : str
- 480 decides which definition of the finite differences derivative is used.
- 481 Available choice: symmetric, forward, backward, improved, default: symmetric
- 482 """
- 483 if variant == "symmetric":
- 484 newcontent = []
- 485 for t in range(1, self.T - 1):
- 486 if (self.content[t - 1] is None) or (self.content[t + 1] is None):
- 487 newcontent.append(None)
- 488 else:
- 489 newcontent.append(0.5 * (self.content[t + 1] - self.content[t - 1]))
- 490 if(all([x is None for x in newcontent])):
- 491 raise Exception('Derivative is undefined at all timeslices')
- 492 return Corr(newcontent, padding=[1, 1])
- 493 elif variant == "forward":
- 494 newcontent = []
- 495 for t in range(self.T - 1):
- 496 if (self.content[t] is None) or (self.content[t + 1] is None):
- 497 newcontent.append(None)
- 498 else:
- 499 newcontent.append(self.content[t + 1] - self.content[t])
- 500 if(all([x is None for x in newcontent])):
- 501 raise Exception("Derivative is undefined at all timeslices")
- 502 return Corr(newcontent, padding=[0, 1])
- 503 elif variant == "backward":
- 504 newcontent = []
- 505 for t in range(1, self.T):
- 506 if (self.content[t - 1] is None) or (self.content[t] is None):
- 507 newcontent.append(None)
- 508 else:
- 509 newcontent.append(self.content[t] - self.content[t - 1])
- 510 if(all([x is None for x in newcontent])):
- 511 raise Exception("Derivative is undefined at all timeslices")
- 512 return Corr(newcontent, padding=[1, 0])
- 513 elif variant == "improved":
- 514 newcontent = []
- 515 for t in range(2, self.T - 2):
- 516 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):
- 517 newcontent.append(None)
- 518 else:
- 519 newcontent.append((1 / 12) * (self.content[t - 2] - 8 * self.content[t - 1] + 8 * self.content[t + 1] - self.content[t + 2]))
- 520 if(all([x is None for x in newcontent])):
- 521 raise Exception('Derivative is undefined at all timeslices')
- 522 return Corr(newcontent, padding=[2, 2])
- 523 else:
- 524 raise Exception("Unknown variant.")
- 525
- 526 def second_deriv(self, variant="symmetric"):
- 527 """Return the second derivative of the correlator with respect to x0.
- 528
- 529 Parameters
- 530 ----------
- 531 variant : str
- 532 decides which definition of the finite differences derivative is used.
- 533 Available choice: symmetric, improved, default: symmetric
- 534 """
- 535 if variant == "symmetric":
- 536 newcontent = []
- 537 for t in range(1, self.T - 1):
- 538 if (self.content[t - 1] is None) or (self.content[t + 1] is None):
- 539 newcontent.append(None)
- 540 else:
- 541 newcontent.append((self.content[t + 1] - 2 * self.content[t] + self.content[t - 1]))
- 542 if(all([x is None for x in newcontent])):
- 543 raise Exception("Derivative is undefined at all timeslices")
- 544 return Corr(newcontent, padding=[1, 1])
- 545 elif variant == "improved":
- 546 newcontent = []
- 547 for t in range(2, self.T - 2):
- 548 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):
- 549 newcontent.append(None)
- 550 else:
- 551 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]))
- 552 if(all([x is None for x in newcontent])):
- 553 raise Exception("Derivative is undefined at all timeslices")
- 554 return Corr(newcontent, padding=[2, 2])
- 555 else:
- 556 raise Exception("Unknown variant.")
- 557
- 558 def m_eff(self, variant='log', guess=1.0):
- 559 """Returns the effective mass of the correlator as correlator object
- 560
- 561 Parameters
- 562 ----------
- 563 variant : str
- 564 log : uses the standard effective mass log(C(t) / C(t+1))
- 565 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.
- 566 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.
- 567 See, e.g., arXiv:1205.5380
- 568 arccosh : Uses the explicit form of the symmetrized correlator (not recommended)
- 569 guess : float
- 570 guess for the root finder, only relevant for the root variant
- 571 """
- 572 if self.N != 1:
- 573 raise Exception('Correlator must be projected before getting m_eff')
- 574 if variant == 'log':
- 575 newcontent = []
- 576 for t in range(self.T - 1):
- 577 if (self.content[t] is None) or (self.content[t + 1] is None):
- 578 newcontent.append(None)
- 579 else:
- 580 newcontent.append(self.content[t] / self.content[t + 1])
- 581 if(all([x is None for x in newcontent])):
- 582 raise Exception('m_eff is undefined at all timeslices')
- 583
- 584 return np.log(Corr(newcontent, padding=[0, 1]))
- 585
- 586 elif variant in ['periodic', 'cosh', 'sinh']:
- 587 if variant in ['periodic', 'cosh']:
- 588 func = anp.cosh
- 589 else:
- 590 func = anp.sinh
- 591
- 592 def root_function(x, d):
- 593 return func(x * (t - self.T / 2)) / func(x * (t + 1 - self.T / 2)) - d
- 594
- 595 newcontent = []
- 596 for t in range(self.T - 1):
- 597 if (self.content[t] is None) or (self.content[t + 1] is None):
- 598 newcontent.append(None)
- 599 # Fill the two timeslices in the middle of the lattice with their predecessors
- 600 elif variant == 'sinh' and t in [self.T / 2, self.T / 2 - 1]:
- 601 newcontent.append(newcontent[-1])
- 602 else:
- 603 newcontent.append(np.abs(find_root(self.content[t][0] / self.content[t + 1][0], root_function, guess=guess)))
- 604 if(all([x is None for x in newcontent])):
- 605 raise Exception('m_eff is undefined at all timeslices')
- 606
- 607 return Corr(newcontent, padding=[0, 1])
- 608
- 609 elif variant == 'arccosh':
- 610 newcontent = []
- 611 for t in range(1, self.T - 1):
- 612 if (self.content[t] is None) or (self.content[t + 1] is None) or (self.content[t - 1] is None):
- 613 newcontent.append(None)
- 614 else:
- 615 newcontent.append((self.content[t + 1] + self.content[t - 1]) / (2 * self.content[t]))
- 616 if(all([x is None for x in newcontent])):
- 617 raise Exception("m_eff is undefined at all timeslices")
- 618 return np.arccosh(Corr(newcontent, padding=[1, 1]))
- 619
- 620 else:
- 621 raise Exception('Unknown variant.')
- 622
- 623 def fit(self, function, fitrange=None, silent=False, **kwargs):
- 624 r'''Fits function to the data
- 625
- 626 Parameters
- 627 ----------
- 628 function : obj
- 629 function to fit to the data. See fits.least_squares for details.
- 630 fitrange : list
- 631 Two element list containing the timeslices on which the fit is supposed to start and stop.
- 632 Caution: This range is inclusive as opposed to standard python indexing.
- 633 `fitrange=[4, 6]` corresponds to the three entries 4, 5 and 6.
- 634 If not specified, self.prange or all timeslices are used.
- 635 silent : bool
- 636 Decides whether output is printed to the standard output.
- 637 '''
- 638 if self.N != 1:
- 639 raise Exception("Correlator must be projected before fitting")
- 640
- 641 if fitrange is None:
- 642 if self.prange:
- 643 fitrange = self.prange
- 644 else:
- 645 fitrange = [0, self.T - 1]
- 646 else:
- 647 if not isinstance(fitrange, list):
- 648 raise Exception("fitrange has to be a list with two elements")
- 649 if len(fitrange) != 2:
- 650 raise Exception("fitrange has to have exactly two elements [fit_start, fit_stop]")
- 651
- 652 xs = [x for x in range(fitrange[0], fitrange[1] + 1) if not self.content[x] is None]
- 653 ys = [self.content[x][0] for x in range(fitrange[0], fitrange[1] + 1) if not self.content[x] is None]
- 654 result = least_squares(xs, ys, function, silent=silent, **kwargs)
- 655 return result
- 656
- 657 def plateau(self, plateau_range=None, method="fit", auto_gamma=False):
- 658 """ Extract a plateau value from a Corr object
- 659
- 660 Parameters
- 661 ----------
- 662 plateau_range : list
- 663 list with two entries, indicating the first and the last timeslice
- 664 of the plateau region.
- 665 method : str
- 666 method to extract the plateau.
- 667 'fit' fits a constant to the plateau region
- 668 'avg', 'average' or 'mean' just average over the given timeslices.
- 669 auto_gamma : bool
- 670 apply gamma_method with default parameters to the Corr. Defaults to None
- 671 """
- 672 if not plateau_range:
- 673 if self.prange:
- 674 plateau_range = self.prange
- 675 else:
- 676 raise Exception("no plateau range provided")
- 677 if self.N != 1:
- 678 raise Exception("Correlator must be projected before getting a plateau.")
- 679 if(all([self.content[t] is None for t in range(plateau_range[0], plateau_range[1] + 1)])):
- 680 raise Exception("plateau is undefined at all timeslices in plateaurange.")
- 681 if auto_gamma:
- 682 self.gamma_method()
- 683 if method == "fit":
- 684 def const_func(a, t):
- 685 return a[0]
- 686 return self.fit(const_func, plateau_range)[0]
- 687 elif method in ["avg", "average", "mean"]:
- 688 returnvalue = np.mean([item[0] for item in self.content[plateau_range[0]:plateau_range[1] + 1] if item is not None])
- 689 return returnvalue
- 690
- 691 else:
- 692 raise Exception("Unsupported plateau method: " + method)
- 693
- 694 def set_prange(self, prange):
- 695 """Sets the attribute prange of the Corr object."""
- 696 if not len(prange) == 2:
- 697 raise Exception("prange must be a list or array with two values")
- 698 if not ((isinstance(prange[0], int)) and (isinstance(prange[1], int))):
- 699 raise Exception("Start and end point must be integers")
- 700 if not (0 <= prange[0] <= self.T and 0 <= prange[1] <= self.T and prange[0] < prange[1]):
- 701 raise Exception("Start and end point must define a range in the interval 0,T")
- 702
- 703 self.prange = prange
- 704 return
- 705
- 706 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):
- 707 """Plots the correlator using the tag of the correlator as label if available.
- 708
- 709 Parameters
- 710 ----------
- 711 x_range : list
- 712 list of two values, determining the range of the x-axis e.g. [4, 8]
- 713 comp : Corr or list of Corr
- 714 Correlator or list of correlators which are plotted for comparison.
- 715 The tags of these correlators are used as labels if available.
- 716 logscale : bool
- 717 Sets y-axis to logscale
- 718 plateau : Obs
- 719 Plateau value to be visualized in the figure
- 720 fit_res : Fit_result
- 721 Fit_result object to be visualized
- 722 ylabel : str
- 723 Label for the y-axis
- 724 save : str
- 725 path to file in which the figure should be saved
- 726 auto_gamma : bool
- 727 Apply the gamma method with standard parameters to all correlators and plateau values before plotting.
- 728 hide_sigma : float
- 729 Hides data points from the first value on which is consistent with zero within 'hide_sigma' standard errors.
- 730 references : list
- 731 List of floating point values that are displayed as horizontal lines for reference.
- 732 """
- 733 if self.N != 1:
- 734 raise Exception("Correlator must be projected before plotting")
- 735
- 736 if auto_gamma:
- 737 self.gamma_method()
- 738
- 739 if x_range is None:
- 740 x_range = [0, self.T - 1]
- 741
- 742 fig = plt.figure()
- 743 ax1 = fig.add_subplot(111)
- 744
- 745 x, y, y_err = self.plottable()
- 746 if hide_sigma:
- 747 hide_from = np.argmax((hide_sigma * np.array(y_err)) > np.abs(y)) - 1
- 748 else:
- 749 hide_from = None
- 750 ax1.errorbar(x[:hide_from], y[:hide_from], y_err[:hide_from], label=self.tag)
- 751 if logscale:
- 752 ax1.set_yscale('log')
- 753 else:
- 754 if y_range is None:
- 755 try:
- 756 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)])
- 757 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)])
- 758 ax1.set_ylim([y_min - 0.1 * (y_max - y_min), y_max + 0.1 * (y_max - y_min)])
- 759 except Exception:
- 760 pass
- 761 else:
- 762 ax1.set_ylim(y_range)
- 763 if comp:
- 764 if isinstance(comp, (Corr, list)):
- 765 for corr in comp if isinstance(comp, list) else [comp]:
- 766 if auto_gamma:
- 767 corr.gamma_method()
- 768 x, y, y_err = corr.plottable()
- 769 if hide_sigma:
- 770 hide_from = np.argmax((hide_sigma * np.array(y_err)) > np.abs(y)) - 1
- 771 else:
- 772 hide_from = None
- 773 plt.errorbar(x[:hide_from], y[:hide_from], y_err[:hide_from], label=corr.tag, mfc=plt.rcParams['axes.facecolor'])
- 774 else:
- 775 raise Exception("'comp' must be a correlator or a list of correlators.")
- 776
- 777 if plateau:
- 778 if isinstance(plateau, Obs):
- 779 if auto_gamma:
- 780 plateau.gamma_method()
- 781 ax1.axhline(y=plateau.value, linewidth=2, color=plt.rcParams['text.color'], alpha=0.6, marker=',', ls='--', label=str(plateau))
- 782 ax1.axhspan(plateau.value - plateau.dvalue, plateau.value + plateau.dvalue, alpha=0.25, color=plt.rcParams['text.color'], ls='-')
- 783 else:
- 784 raise Exception("'plateau' must be an Obs")
- 785
- 786 if references:
- 787 if isinstance(references, list):
- 788 for ref in references:
- 789 ax1.axhline(y=ref, linewidth=1, color=plt.rcParams['text.color'], alpha=0.6, marker=',', ls='--')
- 790 else:
- 791 raise Exception("'references' must be a list of floating pint values.")
- 792
- 793 if self.prange:
- 794 ax1.axvline(self.prange[0], 0, 1, ls='-', marker=',')
- 795 ax1.axvline(self.prange[1], 0, 1, ls='-', marker=',')
+ 380 def reverse(self):
+ 381 """Reverse the time ordering of the Corr"""
+ 382 return Corr(self.content[:: -1])
+ 383
+ 384 def thin(self, spacing=2, offset=0):
+ 385 """Thin out a correlator to suppress correlations
+ 386
+ 387 Parameters
+ 388 ----------
+ 389 spacing : int
+ 390 Keep only every 'spacing'th entry of the correlator
+ 391 offset : int
+ 392 Offset the equal spacing
+ 393 """
+ 394 new_content = []
+ 395 for t in range(self.T):
+ 396 if (offset + t) % spacing != 0:
+ 397 new_content.append(None)
+ 398 else:
+ 399 new_content.append(self.content[t])
+ 400 return Corr(new_content)
+ 401
+ 402 def correlate(self, partner):
+ 403 """Correlate the correlator with another correlator or Obs
+ 404
+ 405 Parameters
+ 406 ----------
+ 407 partner : Obs or Corr
+ 408 partner to correlate the correlator with.
+ 409 Can either be an Obs which is correlated with all entries of the
+ 410 correlator or a Corr of same length.
+ 411 """
+ 412 new_content = []
+ 413 for x0, t_slice in enumerate(self.content):
+ 414 if t_slice is None:
+ 415 new_content.append(None)
+ 416 else:
+ 417 if isinstance(partner, Corr):
+ 418 if partner.content[x0] is None:
+ 419 new_content.append(None)
+ 420 else:
+ 421 new_content.append(np.array([correlate(o, partner.content[x0][0]) for o in t_slice]))
+ 422 elif isinstance(partner, Obs): # Should this include CObs?
+ 423 new_content.append(np.array([correlate(o, partner) for o in t_slice]))
+ 424 else:
+ 425 raise Exception("Can only correlate with an Obs or a Corr.")
+ 426
+ 427 return Corr(new_content)
+ 428
+ 429 def reweight(self, weight, **kwargs):
+ 430 """Reweight the correlator.
+ 431
+ 432 Parameters
+ 433 ----------
+ 434 weight : Obs
+ 435 Reweighting factor. An Observable that has to be defined on a superset of the
+ 436 configurations in obs[i].idl for all i.
+ 437 all_configs : bool
+ 438 if True, the reweighted observables are normalized by the average of
+ 439 the reweighting factor on all configurations in weight.idl and not
+ 440 on the configurations in obs[i].idl.
+ 441 """
+ 442 new_content = []
+ 443 for t_slice in self.content:
+ 444 if t_slice is None:
+ 445 new_content.append(None)
+ 446 else:
+ 447 new_content.append(np.array(reweight(weight, t_slice, **kwargs)))
+ 448 return Corr(new_content)
+ 449
+ 450 def T_symmetry(self, partner, parity=+1):
+ 451 """Return the time symmetry average of the correlator and its partner
+ 452
+ 453 Parameters
+ 454 ----------
+ 455 partner : Corr
+ 456 Time symmetry partner of the Corr
+ 457 partity : int
+ 458 Parity quantum number of the correlator, can be +1 or -1
+ 459 """
+ 460 if not isinstance(partner, Corr):
+ 461 raise Exception("T partner has to be a Corr object.")
+ 462 if parity not in [+1, -1]:
+ 463 raise Exception("Parity has to be +1 or -1.")
+ 464 T_partner = parity * partner.reverse()
+ 465
+ 466 t_slices = []
+ 467 test = (self - T_partner)
+ 468 test.gamma_method()
+ 469 for x0, t_slice in enumerate(test.content):
+ 470 if t_slice is not None:
+ 471 if not t_slice[0].is_zero_within_error(5):
+ 472 t_slices.append(x0)
+ 473 if t_slices:
+ 474 warnings.warn("T symmetry partners do not agree within 5 sigma on time slices " + str(t_slices) + ".", RuntimeWarning)
+ 475
+ 476 return (self + T_partner) / 2
+ 477
+ 478 def deriv(self, variant="symmetric"):
+ 479 """Return the first derivative of the correlator with respect to x0.
+ 480
+ 481 Parameters
+ 482 ----------
+ 483 variant : str
+ 484 decides which definition of the finite differences derivative is used.
+ 485 Available choice: symmetric, forward, backward, improved, default: symmetric
+ 486 """
+ 487 if variant == "symmetric":
+ 488 newcontent = []
+ 489 for t in range(1, self.T - 1):
+ 490 if (self.content[t - 1] is None) or (self.content[t + 1] is None):
+ 491 newcontent.append(None)
+ 492 else:
+ 493 newcontent.append(0.5 * (self.content[t + 1] - self.content[t - 1]))
+ 494 if(all([x is None for x in newcontent])):
+ 495 raise Exception('Derivative is undefined at all timeslices')
+ 496 return Corr(newcontent, padding=[1, 1])
+ 497 elif variant == "forward":
+ 498 newcontent = []
+ 499 for t in range(self.T - 1):
+ 500 if (self.content[t] is None) or (self.content[t + 1] is None):
+ 501 newcontent.append(None)
+ 502 else:
+ 503 newcontent.append(self.content[t + 1] - self.content[t])
+ 504 if(all([x is None for x in newcontent])):
+ 505 raise Exception("Derivative is undefined at all timeslices")
+ 506 return Corr(newcontent, padding=[0, 1])
+ 507 elif variant == "backward":
+ 508 newcontent = []
+ 509 for t in range(1, self.T):
+ 510 if (self.content[t - 1] is None) or (self.content[t] is None):
+ 511 newcontent.append(None)
+ 512 else:
+ 513 newcontent.append(self.content[t] - self.content[t - 1])
+ 514 if(all([x is None for x in newcontent])):
+ 515 raise Exception("Derivative is undefined at all timeslices")
+ 516 return Corr(newcontent, padding=[1, 0])
+ 517 elif variant == "improved":
+ 518 newcontent = []
+ 519 for t in range(2, self.T - 2):
+ 520 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):
+ 521 newcontent.append(None)
+ 522 else:
+ 523 newcontent.append((1 / 12) * (self.content[t - 2] - 8 * self.content[t - 1] + 8 * self.content[t + 1] - self.content[t + 2]))
+ 524 if(all([x is None for x in newcontent])):
+ 525 raise Exception('Derivative is undefined at all timeslices')
+ 526 return Corr(newcontent, padding=[2, 2])
+ 527 else:
+ 528 raise Exception("Unknown variant.")
+ 529
+ 530 def second_deriv(self, variant="symmetric"):
+ 531 """Return the second derivative of the correlator with respect to x0.
+ 532
+ 533 Parameters
+ 534 ----------
+ 535 variant : str
+ 536 decides which definition of the finite differences derivative is used.
+ 537 Available choice: symmetric, improved, default: symmetric
+ 538 """
+ 539 if variant == "symmetric":
+ 540 newcontent = []
+ 541 for t in range(1, self.T - 1):
+ 542 if (self.content[t - 1] is None) or (self.content[t + 1] is None):
+ 543 newcontent.append(None)
+ 544 else:
+ 545 newcontent.append((self.content[t + 1] - 2 * self.content[t] + self.content[t - 1]))
+ 546 if(all([x is None for x in newcontent])):
+ 547 raise Exception("Derivative is undefined at all timeslices")
+ 548 return Corr(newcontent, padding=[1, 1])
+ 549 elif variant == "improved":
+ 550 newcontent = []
+ 551 for t in range(2, self.T - 2):
+ 552 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):
+ 553 newcontent.append(None)
+ 554 else:
+ 555 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]))
+ 556 if(all([x is None for x in newcontent])):
+ 557 raise Exception("Derivative is undefined at all timeslices")
+ 558 return Corr(newcontent, padding=[2, 2])
+ 559 else:
+ 560 raise Exception("Unknown variant.")
+ 561
+ 562 def m_eff(self, variant='log', guess=1.0):
+ 563 """Returns the effective mass of the correlator as correlator object
+ 564
+ 565 Parameters
+ 566 ----------
+ 567 variant : str
+ 568 log : uses the standard effective mass log(C(t) / C(t+1))
+ 569 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.
+ 570 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.
+ 571 See, e.g., arXiv:1205.5380
+ 572 arccosh : Uses the explicit form of the symmetrized correlator (not recommended)
+ 573 guess : float
+ 574 guess for the root finder, only relevant for the root variant
+ 575 """
+ 576 if self.N != 1:
+ 577 raise Exception('Correlator must be projected before getting m_eff')
+ 578 if variant == 'log':
+ 579 newcontent = []
+ 580 for t in range(self.T - 1):
+ 581 if (self.content[t] is None) or (self.content[t + 1] is None):
+ 582 newcontent.append(None)
+ 583 else:
+ 584 newcontent.append(self.content[t] / self.content[t + 1])
+ 585 if(all([x is None for x in newcontent])):
+ 586 raise Exception('m_eff is undefined at all timeslices')
+ 587
+ 588 return np.log(Corr(newcontent, padding=[0, 1]))
+ 589
+ 590 elif variant in ['periodic', 'cosh', 'sinh']:
+ 591 if variant in ['periodic', 'cosh']:
+ 592 func = anp.cosh
+ 593 else:
+ 594 func = anp.sinh
+ 595
+ 596 def root_function(x, d):
+ 597 return func(x * (t - self.T / 2)) / func(x * (t + 1 - self.T / 2)) - d
+ 598
+ 599 newcontent = []
+ 600 for t in range(self.T - 1):
+ 601 if (self.content[t] is None) or (self.content[t + 1] is None):
+ 602 newcontent.append(None)
+ 603 # Fill the two timeslices in the middle of the lattice with their predecessors
+ 604 elif variant == 'sinh' and t in [self.T / 2, self.T / 2 - 1]:
+ 605 newcontent.append(newcontent[-1])
+ 606 else:
+ 607 newcontent.append(np.abs(find_root(self.content[t][0] / self.content[t + 1][0], root_function, guess=guess)))
+ 608 if(all([x is None for x in newcontent])):
+ 609 raise Exception('m_eff is undefined at all timeslices')
+ 610
+ 611 return Corr(newcontent, padding=[0, 1])
+ 612
+ 613 elif variant == 'arccosh':
+ 614 newcontent = []
+ 615 for t in range(1, self.T - 1):
+ 616 if (self.content[t] is None) or (self.content[t + 1] is None) or (self.content[t - 1] is None):
+ 617 newcontent.append(None)
+ 618 else:
+ 619 newcontent.append((self.content[t + 1] + self.content[t - 1]) / (2 * self.content[t]))
+ 620 if(all([x is None for x in newcontent])):
+ 621 raise Exception("m_eff is undefined at all timeslices")
+ 622 return np.arccosh(Corr(newcontent, padding=[1, 1]))
+ 623
+ 624 else:
+ 625 raise Exception('Unknown variant.')
+ 626
+ 627 def fit(self, function, fitrange=None, silent=False, **kwargs):
+ 628 r'''Fits function to the data
+ 629
+ 630 Parameters
+ 631 ----------
+ 632 function : obj
+ 633 function to fit to the data. See fits.least_squares for details.
+ 634 fitrange : list
+ 635 Two element list containing the timeslices on which the fit is supposed to start and stop.
+ 636 Caution: This range is inclusive as opposed to standard python indexing.
+ 637 `fitrange=[4, 6]` corresponds to the three entries 4, 5 and 6.
+ 638 If not specified, self.prange or all timeslices are used.
+ 639 silent : bool
+ 640 Decides whether output is printed to the standard output.
+ 641 '''
+ 642 if self.N != 1:
+ 643 raise Exception("Correlator must be projected before fitting")
+ 644
+ 645 if fitrange is None:
+ 646 if self.prange:
+ 647 fitrange = self.prange
+ 648 else:
+ 649 fitrange = [0, self.T - 1]
+ 650 else:
+ 651 if not isinstance(fitrange, list):
+ 652 raise Exception("fitrange has to be a list with two elements")
+ 653 if len(fitrange) != 2:
+ 654 raise Exception("fitrange has to have exactly two elements [fit_start, fit_stop]")
+ 655
+ 656 xs = [x for x in range(fitrange[0], fitrange[1] + 1) if not self.content[x] is None]
+ 657 ys = [self.content[x][0] for x in range(fitrange[0], fitrange[1] + 1) if not self.content[x] is None]
+ 658 result = least_squares(xs, ys, function, silent=silent, **kwargs)
+ 659 return result
+ 660
+ 661 def plateau(self, plateau_range=None, method="fit", auto_gamma=False):
+ 662 """ Extract a plateau value from a Corr object
+ 663
+ 664 Parameters
+ 665 ----------
+ 666 plateau_range : list
+ 667 list with two entries, indicating the first and the last timeslice
+ 668 of the plateau region.
+ 669 method : str
+ 670 method to extract the plateau.
+ 671 'fit' fits a constant to the plateau region
+ 672 'avg', 'average' or 'mean' just average over the given timeslices.
+ 673 auto_gamma : bool
+ 674 apply gamma_method with default parameters to the Corr. Defaults to None
+ 675 """
+ 676 if not plateau_range:
+ 677 if self.prange:
+ 678 plateau_range = self.prange
+ 679 else:
+ 680 raise Exception("no plateau range provided")
+ 681 if self.N != 1:
+ 682 raise Exception("Correlator must be projected before getting a plateau.")
+ 683 if(all([self.content[t] is None for t in range(plateau_range[0], plateau_range[1] + 1)])):
+ 684 raise Exception("plateau is undefined at all timeslices in plateaurange.")
+ 685 if auto_gamma:
+ 686 self.gamma_method()
+ 687 if method == "fit":
+ 688 def const_func(a, t):
+ 689 return a[0]
+ 690 return self.fit(const_func, plateau_range)[0]
+ 691 elif method in ["avg", "average", "mean"]:
+ 692 returnvalue = np.mean([item[0] for item in self.content[plateau_range[0]:plateau_range[1] + 1] if item is not None])
+ 693 return returnvalue
+ 694
+ 695 else:
+ 696 raise Exception("Unsupported plateau method: " + method)
+ 697
+ 698 def set_prange(self, prange):
+ 699 """Sets the attribute prange of the Corr object."""
+ 700 if not len(prange) == 2:
+ 701 raise Exception("prange must be a list or array with two values")
+ 702 if not ((isinstance(prange[0], int)) and (isinstance(prange[1], int))):
+ 703 raise Exception("Start and end point must be integers")
+ 704 if not (0 <= prange[0] <= self.T and 0 <= prange[1] <= self.T and prange[0] < prange[1]):
+ 705 raise Exception("Start and end point must define a range in the interval 0,T")
+ 706
+ 707 self.prange = prange
+ 708 return
+ 709
+ 710 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):
+ 711 """Plots the correlator using the tag of the correlator as label if available.
+ 712
+ 713 Parameters
+ 714 ----------
+ 715 x_range : list
+ 716 list of two values, determining the range of the x-axis e.g. [4, 8]
+ 717 comp : Corr or list of Corr
+ 718 Correlator or list of correlators which are plotted for comparison.
+ 719 The tags of these correlators are used as labels if available.
+ 720 logscale : bool
+ 721 Sets y-axis to logscale
+ 722 plateau : Obs
+ 723 Plateau value to be visualized in the figure
+ 724 fit_res : Fit_result
+ 725 Fit_result object to be visualized
+ 726 ylabel : str
+ 727 Label for the y-axis
+ 728 save : str
+ 729 path to file in which the figure should be saved
+ 730 auto_gamma : bool
+ 731 Apply the gamma method with standard parameters to all correlators and plateau values before plotting.
+ 732 hide_sigma : float
+ 733 Hides data points from the first value on which is consistent with zero within 'hide_sigma' standard errors.
+ 734 references : list
+ 735 List of floating point values that are displayed as horizontal lines for reference.
+ 736 """
+ 737 if self.N != 1:
+ 738 raise Exception("Correlator must be projected before plotting")
+ 739
+ 740 if auto_gamma:
+ 741 self.gamma_method()
+ 742
+ 743 if x_range is None:
+ 744 x_range = [0, self.T - 1]
+ 745
+ 746 fig = plt.figure()
+ 747 ax1 = fig.add_subplot(111)
+ 748
+ 749 x, y, y_err = self.plottable()
+ 750 if hide_sigma:
+ 751 hide_from = np.argmax((hide_sigma * np.array(y_err)) > np.abs(y)) - 1
+ 752 else:
+ 753 hide_from = None
+ 754 ax1.errorbar(x[:hide_from], y[:hide_from], y_err[:hide_from], label=self.tag)
+ 755 if logscale:
+ 756 ax1.set_yscale('log')
+ 757 else:
+ 758 if y_range is None:
+ 759 try:
+ 760 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)])
+ 761 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)])
+ 762 ax1.set_ylim([y_min - 0.1 * (y_max - y_min), y_max + 0.1 * (y_max - y_min)])
+ 763 except Exception:
+ 764 pass
+ 765 else:
+ 766 ax1.set_ylim(y_range)
+ 767 if comp:
+ 768 if isinstance(comp, (Corr, list)):
+ 769 for corr in comp if isinstance(comp, list) else [comp]:
+ 770 if auto_gamma:
+ 771 corr.gamma_method()
+ 772 x, y, y_err = corr.plottable()
+ 773 if hide_sigma:
+ 774 hide_from = np.argmax((hide_sigma * np.array(y_err)) > np.abs(y)) - 1
+ 775 else:
+ 776 hide_from = None
+ 777 plt.errorbar(x[:hide_from], y[:hide_from], y_err[:hide_from], label=corr.tag, mfc=plt.rcParams['axes.facecolor'])
+ 778 else:
+ 779 raise Exception("'comp' must be a correlator or a list of correlators.")
+ 780
+ 781 if plateau:
+ 782 if isinstance(plateau, Obs):
+ 783 if auto_gamma:
+ 784 plateau.gamma_method()
+ 785 ax1.axhline(y=plateau.value, linewidth=2, color=plt.rcParams['text.color'], alpha=0.6, marker=',', ls='--', label=str(plateau))
+ 786 ax1.axhspan(plateau.value - plateau.dvalue, plateau.value + plateau.dvalue, alpha=0.25, color=plt.rcParams['text.color'], ls='-')
+ 787 else:
+ 788 raise Exception("'plateau' must be an Obs")
+ 789
+ 790 if references:
+ 791 if isinstance(references, list):
+ 792 for ref in references:
+ 793 ax1.axhline(y=ref, linewidth=1, color=plt.rcParams['text.color'], alpha=0.6, marker=',', ls='--')
+ 794 else:
+ 795 raise Exception("'references' must be a list of floating pint values.")
796
- 797 if fit_res:
- 798 x_samples = np.arange(x_range[0], x_range[1] + 1, 0.05)
- 799 ax1.plot(x_samples,
- 800 fit_res.fit_function([o.value for o in fit_res.fit_parameters], x_samples),
- 801 ls='-', marker=',', lw=2)
- 802
- 803 ax1.set_xlabel(r'$x_0 / a$')
- 804 if ylabel:
- 805 ax1.set_ylabel(ylabel)
- 806 ax1.set_xlim([x_range[0] - 0.5, x_range[1] + 0.5])
- 807
- 808 handles, labels = ax1.get_legend_handles_labels()
- 809 if labels:
- 810 ax1.legend()
- 811 plt.draw()
- 812
- 813 if save:
- 814 if isinstance(save, str):
- 815 fig.savefig(save)
- 816 else:
- 817 raise Exception("'save' has to be a string.")
- 818
- 819 def spaghetti_plot(self, logscale=True):
- 820 """Produces a spaghetti plot of the correlator suited to monitor exceptional configurations.
- 821
- 822 Parameters
- 823 ----------
- 824 logscale : bool
- 825 Determines whether the scale of the y-axis is logarithmic or standard.
- 826 """
- 827 if self.N != 1:
- 828 raise Exception("Correlator needs to be projected first.")
- 829
- 830 mc_names = list(set([item for sublist in [o[0].mc_names for o in self.content if o is not None] for item in sublist]))
- 831 x0_vals = [n for (n, o) in zip(np.arange(self.T), self.content) if o is not None]
- 832
- 833 for name in mc_names:
- 834 data = np.array([o[0].deltas[name] + o[0].r_values[name] for o in self.content if o is not None]).T
- 835
- 836 fig = plt.figure()
- 837 ax = fig.add_subplot(111)
- 838 for dat in data:
- 839 ax.plot(x0_vals, dat, ls='-', marker='')
- 840
- 841 if logscale is True:
- 842 ax.set_yscale('log')
- 843
- 844 ax.set_xlabel(r'$x_0 / a$')
- 845 plt.title(name)
- 846 plt.draw()
+ 797 if self.prange:
+ 798 ax1.axvline(self.prange[0], 0, 1, ls='-', marker=',')
+ 799 ax1.axvline(self.prange[1], 0, 1, ls='-', marker=',')
+ 800
+ 801 if fit_res:
+ 802 x_samples = np.arange(x_range[0], x_range[1] + 1, 0.05)
+ 803 ax1.plot(x_samples,
+ 804 fit_res.fit_function([o.value for o in fit_res.fit_parameters], x_samples),
+ 805 ls='-', marker=',', lw=2)
+ 806
+ 807 ax1.set_xlabel(r'$x_0 / a$')
+ 808 if ylabel:
+ 809 ax1.set_ylabel(ylabel)
+ 810 ax1.set_xlim([x_range[0] - 0.5, x_range[1] + 0.5])
+ 811
+ 812 handles, labels = ax1.get_legend_handles_labels()
+ 813 if labels:
+ 814 ax1.legend()
+ 815 plt.draw()
+ 816
+ 817 if save:
+ 818 if isinstance(save, str):
+ 819 fig.savefig(save)
+ 820 else:
+ 821 raise Exception("'save' has to be a string.")
+ 822
+ 823 def spaghetti_plot(self, logscale=True):
+ 824 """Produces a spaghetti plot of the correlator suited to monitor exceptional configurations.
+ 825
+ 826 Parameters
+ 827 ----------
+ 828 logscale : bool
+ 829 Determines whether the scale of the y-axis is logarithmic or standard.
+ 830 """
+ 831 if self.N != 1:
+ 832 raise Exception("Correlator needs to be projected first.")
+ 833
+ 834 mc_names = list(set([item for sublist in [o[0].mc_names for o in self.content if o is not None] for item in sublist]))
+ 835 x0_vals = [n for (n, o) in zip(np.arange(self.T), self.content) if o is not None]
+ 836
+ 837 for name in mc_names:
+ 838 data = np.array([o[0].deltas[name] + o[0].r_values[name] for o in self.content if o is not None]).T
+ 839
+ 840 fig = plt.figure()
+ 841 ax = fig.add_subplot(111)
+ 842 for dat in data:
+ 843 ax.plot(x0_vals, dat, ls='-', marker='')
+ 844
+ 845 if logscale is True:
+ 846 ax.set_yscale('log')
847
- 848 def dump(self, filename, datatype="json.gz", **kwargs):
- 849 """Dumps the Corr into a file of chosen type
- 850 Parameters
- 851 ----------
- 852 filename : str
- 853 Name of the file to be saved.
- 854 datatype : str
- 855 Format of the exported file. Supported formats include
- 856 "json.gz" and "pickle"
- 857 path : str
- 858 specifies a custom path for the file (default '.')
- 859 """
- 860 if datatype == "json.gz":
- 861 from .input.json import dump_to_json
- 862 if 'path' in kwargs:
- 863 file_name = kwargs.get('path') + '/' + filename
- 864 else:
- 865 file_name = filename
- 866 dump_to_json(self, file_name)
- 867 elif datatype == "pickle":
- 868 dump_object(self, filename, **kwargs)
- 869 else:
- 870 raise Exception("Unknown datatype " + str(datatype))
- 871
- 872 def print(self, range=[0, None]):
- 873 print(self.__repr__(range))
- 874
- 875 def __repr__(self, range=[0, None]):
- 876 content_string = ""
- 877
- 878 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
- 879
- 880 if self.tag is not None:
- 881 content_string += "Description: " + self.tag + "\n"
- 882 if self.N != 1:
- 883 return content_string
- 884
- 885 if range[1]:
- 886 range[1] += 1
- 887 content_string += 'x0/a\tCorr(x0/a)\n------------------\n'
- 888 for i, sub_corr in enumerate(self.content[range[0]:range[1]]):
- 889 if sub_corr is None:
- 890 content_string += str(i + range[0]) + '\n'
- 891 else:
- 892 content_string += str(i + range[0])
- 893 for element in sub_corr:
- 894 content_string += '\t' + ' ' * int(element >= 0) + str(element)
- 895 content_string += '\n'
- 896 return content_string
- 897
- 898 def __str__(self):
- 899 return self.__repr__()
- 900
- 901 # We define the basic operations, that can be performed with correlators.
- 902 # While */+- get defined here, they only work for Corr*Obs and not Obs*Corr.
- 903 # This is because Obs*Corr checks Obs.__mul__ first and does not catch an exception.
- 904 # One could try and tell Obs to check if the y in __mul__ is a Corr and
- 905
- 906 def __add__(self, y):
- 907 if isinstance(y, Corr):
- 908 if ((self.N != y.N) or (self.T != y.T)):
- 909 raise Exception("Addition of Corrs with different shape")
- 910 newcontent = []
- 911 for t in range(self.T):
- 912 if (self.content[t] is None) or (y.content[t] is None):
- 913 newcontent.append(None)
- 914 else:
- 915 newcontent.append(self.content[t] + y.content[t])
- 916 return Corr(newcontent)
- 917
- 918 elif isinstance(y, (Obs, int, float, CObs)):
- 919 newcontent = []
- 920 for t in range(self.T):
- 921 if (self.content[t] is None):
- 922 newcontent.append(None)
- 923 else:
- 924 newcontent.append(self.content[t] + y)
- 925 return Corr(newcontent, prange=self.prange)
- 926 elif isinstance(y, np.ndarray):
- 927 if y.shape == (self.T,):
- 928 return Corr(list((np.array(self.content).T + y).T))
- 929 else:
- 930 raise ValueError("operands could not be broadcast together")
- 931 else:
- 932 raise TypeError("Corr + wrong type")
- 933
- 934 def __mul__(self, y):
- 935 if isinstance(y, Corr):
- 936 if not((self.N == 1 or y.N == 1 or self.N == y.N) and self.T == y.T):
- 937 raise Exception("Multiplication of Corr object requires N=N or N=1 and T=T")
- 938 newcontent = []
- 939 for t in range(self.T):
- 940 if (self.content[t] is None) or (y.content[t] is None):
- 941 newcontent.append(None)
- 942 else:
- 943 newcontent.append(self.content[t] * y.content[t])
- 944 return Corr(newcontent)
- 945
- 946 elif isinstance(y, (Obs, int, float, CObs)):
- 947 newcontent = []
- 948 for t in range(self.T):
- 949 if (self.content[t] is None):
- 950 newcontent.append(None)
- 951 else:
- 952 newcontent.append(self.content[t] * y)
- 953 return Corr(newcontent, prange=self.prange)
- 954 elif isinstance(y, np.ndarray):
- 955 if y.shape == (self.T,):
- 956 return Corr(list((np.array(self.content).T * y).T))
- 957 else:
- 958 raise ValueError("operands could not be broadcast together")
- 959 else:
- 960 raise TypeError("Corr * wrong type")
- 961
- 962 def __truediv__(self, y):
- 963 if isinstance(y, Corr):
- 964 if not((self.N == 1 or y.N == 1 or self.N == y.N) and self.T == y.T):
- 965 raise Exception("Multiplication of Corr object requires N=N or N=1 and T=T")
- 966 newcontent = []
- 967 for t in range(self.T):
- 968 if (self.content[t] is None) or (y.content[t] is None):
- 969 newcontent.append(None)
- 970 else:
- 971 newcontent.append(self.content[t] / y.content[t])
- 972 for t in range(self.T):
- 973 if newcontent[t] is None:
- 974 continue
- 975 if np.isnan(np.sum(newcontent[t]).value):
- 976 newcontent[t] = None
- 977
- 978 if all([item is None for item in newcontent]):
- 979 raise Exception("Division returns completely undefined correlator")
- 980 return Corr(newcontent)
+ 848 ax.set_xlabel(r'$x_0 / a$')
+ 849 plt.title(name)
+ 850 plt.draw()
+ 851
+ 852 def dump(self, filename, datatype="json.gz", **kwargs):
+ 853 """Dumps the Corr into a file of chosen type
+ 854 Parameters
+ 855 ----------
+ 856 filename : str
+ 857 Name of the file to be saved.
+ 858 datatype : str
+ 859 Format of the exported file. Supported formats include
+ 860 "json.gz" and "pickle"
+ 861 path : str
+ 862 specifies a custom path for the file (default '.')
+ 863 """
+ 864 if datatype == "json.gz":
+ 865 from .input.json import dump_to_json
+ 866 if 'path' in kwargs:
+ 867 file_name = kwargs.get('path') + '/' + filename
+ 868 else:
+ 869 file_name = filename
+ 870 dump_to_json(self, file_name)
+ 871 elif datatype == "pickle":
+ 872 dump_object(self, filename, **kwargs)
+ 873 else:
+ 874 raise Exception("Unknown datatype " + str(datatype))
+ 875
+ 876 def print(self, range=[0, None]):
+ 877 print(self.__repr__(range))
+ 878
+ 879 def __repr__(self, range=[0, None]):
+ 880 content_string = ""
+ 881
+ 882 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
+ 883
+ 884 if self.tag is not None:
+ 885 content_string += "Description: " + self.tag + "\n"
+ 886 if self.N != 1:
+ 887 return content_string
+ 888
+ 889 if range[1]:
+ 890 range[1] += 1
+ 891 content_string += 'x0/a\tCorr(x0/a)\n------------------\n'
+ 892 for i, sub_corr in enumerate(self.content[range[0]:range[1]]):
+ 893 if sub_corr is None:
+ 894 content_string += str(i + range[0]) + '\n'
+ 895 else:
+ 896 content_string += str(i + range[0])
+ 897 for element in sub_corr:
+ 898 content_string += '\t' + ' ' * int(element >= 0) + str(element)
+ 899 content_string += '\n'
+ 900 return content_string
+ 901
+ 902 def __str__(self):
+ 903 return self.__repr__()
+ 904
+ 905 # We define the basic operations, that can be performed with correlators.
+ 906 # While */+- get defined here, they only work for Corr*Obs and not Obs*Corr.
+ 907 # This is because Obs*Corr checks Obs.__mul__ first and does not catch an exception.
+ 908 # One could try and tell Obs to check if the y in __mul__ is a Corr and
+ 909
+ 910 def __add__(self, y):
+ 911 if isinstance(y, Corr):
+ 912 if ((self.N != y.N) or (self.T != y.T)):
+ 913 raise Exception("Addition of Corrs with different shape")
+ 914 newcontent = []
+ 915 for t in range(self.T):
+ 916 if (self.content[t] is None) or (y.content[t] is None):
+ 917 newcontent.append(None)
+ 918 else:
+ 919 newcontent.append(self.content[t] + y.content[t])
+ 920 return Corr(newcontent)
+ 921
+ 922 elif isinstance(y, (Obs, int, float, CObs)):
+ 923 newcontent = []
+ 924 for t in range(self.T):
+ 925 if (self.content[t] is None):
+ 926 newcontent.append(None)
+ 927 else:
+ 928 newcontent.append(self.content[t] + y)
+ 929 return Corr(newcontent, prange=self.prange)
+ 930 elif isinstance(y, np.ndarray):
+ 931 if y.shape == (self.T,):
+ 932 return Corr(list((np.array(self.content).T + y).T))
+ 933 else:
+ 934 raise ValueError("operands could not be broadcast together")
+ 935 else:
+ 936 raise TypeError("Corr + wrong type")
+ 937
+ 938 def __mul__(self, y):
+ 939 if isinstance(y, Corr):
+ 940 if not((self.N == 1 or y.N == 1 or self.N == y.N) and self.T == y.T):
+ 941 raise Exception("Multiplication of Corr object requires N=N or N=1 and T=T")
+ 942 newcontent = []
+ 943 for t in range(self.T):
+ 944 if (self.content[t] is None) or (y.content[t] is None):
+ 945 newcontent.append(None)
+ 946 else:
+ 947 newcontent.append(self.content[t] * y.content[t])
+ 948 return Corr(newcontent)
+ 949
+ 950 elif isinstance(y, (Obs, int, float, CObs)):
+ 951 newcontent = []
+ 952 for t in range(self.T):
+ 953 if (self.content[t] is None):
+ 954 newcontent.append(None)
+ 955 else:
+ 956 newcontent.append(self.content[t] * y)
+ 957 return Corr(newcontent, prange=self.prange)
+ 958 elif isinstance(y, np.ndarray):
+ 959 if y.shape == (self.T,):
+ 960 return Corr(list((np.array(self.content).T * y).T))
+ 961 else:
+ 962 raise ValueError("operands could not be broadcast together")
+ 963 else:
+ 964 raise TypeError("Corr * wrong type")
+ 965
+ 966 def __truediv__(self, y):
+ 967 if isinstance(y, Corr):
+ 968 if not((self.N == 1 or y.N == 1 or self.N == y.N) and self.T == y.T):
+ 969 raise Exception("Multiplication of Corr object requires N=N or N=1 and T=T")
+ 970 newcontent = []
+ 971 for t in range(self.T):
+ 972 if (self.content[t] is None) or (y.content[t] is None):
+ 973 newcontent.append(None)
+ 974 else:
+ 975 newcontent.append(self.content[t] / y.content[t])
+ 976 for t in range(self.T):
+ 977 if newcontent[t] is None:
+ 978 continue
+ 979 if np.isnan(np.sum(newcontent[t]).value):
+ 980 newcontent[t] = None
981
- 982 elif isinstance(y, (Obs, CObs)):
- 983 if isinstance(y, Obs):
- 984 if y.value == 0:
- 985 raise Exception('Division by zero will return undefined correlator')
- 986 if isinstance(y, CObs):
- 987 if y.is_zero():
- 988 raise Exception('Division by zero will return undefined correlator')
- 989
- 990 newcontent = []
- 991 for t in range(self.T):
- 992 if (self.content[t] is None):
- 993 newcontent.append(None)
- 994 else:
- 995 newcontent.append(self.content[t] / y)
- 996 return Corr(newcontent, prange=self.prange)
- 997
- 998 elif isinstance(y, (int, float)):
- 999 if y == 0:
-1000 raise Exception('Division by zero will return undefined correlator')
-1001 newcontent = []
-1002 for t in range(self.T):
-1003 if (self.content[t] is None):
-1004 newcontent.append(None)
-1005 else:
-1006 newcontent.append(self.content[t] / y)
-1007 return Corr(newcontent, prange=self.prange)
-1008 elif isinstance(y, np.ndarray):
-1009 if y.shape == (self.T,):
-1010 return Corr(list((np.array(self.content).T / y).T))
-1011 else:
-1012 raise ValueError("operands could not be broadcast together")
-1013 else:
-1014 raise TypeError('Corr / wrong type')
-1015
-1016 def __neg__(self):
-1017 newcontent = [None if (item is None) else -1. * item for item in self.content]
-1018 return Corr(newcontent, prange=self.prange)
+ 982 if all([item is None for item in newcontent]):
+ 983 raise Exception("Division returns completely undefined correlator")
+ 984 return Corr(newcontent)
+ 985
+ 986 elif isinstance(y, (Obs, CObs)):
+ 987 if isinstance(y, Obs):
+ 988 if y.value == 0:
+ 989 raise Exception('Division by zero will return undefined correlator')
+ 990 if isinstance(y, CObs):
+ 991 if y.is_zero():
+ 992 raise Exception('Division by zero will return undefined correlator')
+ 993
+ 994 newcontent = []
+ 995 for t in range(self.T):
+ 996 if (self.content[t] is None):
+ 997 newcontent.append(None)
+ 998 else:
+ 999 newcontent.append(self.content[t] / y)
+1000 return Corr(newcontent, prange=self.prange)
+1001
+1002 elif isinstance(y, (int, float)):
+1003 if y == 0:
+1004 raise Exception('Division by zero will return undefined correlator')
+1005 newcontent = []
+1006 for t in range(self.T):
+1007 if (self.content[t] is None):
+1008 newcontent.append(None)
+1009 else:
+1010 newcontent.append(self.content[t] / y)
+1011 return Corr(newcontent, prange=self.prange)
+1012 elif isinstance(y, np.ndarray):
+1013 if y.shape == (self.T,):
+1014 return Corr(list((np.array(self.content).T / y).T))
+1015 else:
+1016 raise ValueError("operands could not be broadcast together")
+1017 else:
+1018 raise TypeError('Corr / wrong type')
1019
-1020 def __sub__(self, y):
-1021 return self + (-y)
-1022
-1023 def __pow__(self, y):
-1024 if isinstance(y, (Obs, int, float, CObs)):
-1025 newcontent = [None if (item is None) else item**y for item in self.content]
-1026 return Corr(newcontent, prange=self.prange)
-1027 else:
-1028 raise TypeError('Type of exponent not supported')
-1029
-1030 def __abs__(self):
-1031 newcontent = [None if (item is None) else np.abs(item) for item in self.content]
-1032 return Corr(newcontent, prange=self.prange)
+1020 def __neg__(self):
+1021 newcontent = [None if (item is None) else -1. * item for item in self.content]
+1022 return Corr(newcontent, prange=self.prange)
+1023
+1024 def __sub__(self, y):
+1025 return self + (-y)
+1026
+1027 def __pow__(self, y):
+1028 if isinstance(y, (Obs, int, float, CObs)):
+1029 newcontent = [None if (item is None) else item**y for item in self.content]
+1030 return Corr(newcontent, prange=self.prange)
+1031 else:
+1032 raise TypeError('Type of exponent not supported')
1033
-1034 # The numpy functions:
-1035 def sqrt(self):
-1036 return self**0.5
+1034 def __abs__(self):
+1035 newcontent = [None if (item is None) else np.abs(item) for item in self.content]
+1036 return Corr(newcontent, prange=self.prange)
1037
-1038 def log(self):
-1039 newcontent = [None if (item is None) else np.log(item) for item in self.content]
-1040 return Corr(newcontent, prange=self.prange)
+1038 # The numpy functions:
+1039 def sqrt(self):
+1040 return self**0.5
1041
-1042 def exp(self):
-1043 newcontent = [None if (item is None) else np.exp(item) for item in self.content]
+1042 def log(self):
+1043 newcontent = [None if (item is None) else np.log(item) for item in self.content]
1044 return Corr(newcontent, prange=self.prange)
1045
-1046 def _apply_func_to_corr(self, func):
-1047 newcontent = [None if (item is None) else func(item) for item in self.content]
-1048 for t in range(self.T):
-1049 if newcontent[t] is None:
-1050 continue
-1051 if np.isnan(np.sum(newcontent[t]).value):
-1052 newcontent[t] = None
-1053 if all([item is None for item in newcontent]):
-1054 raise Exception('Operation returns undefined correlator')
-1055 return Corr(newcontent)
-1056
-1057 def sin(self):
-1058 return self._apply_func_to_corr(np.sin)
-1059
-1060 def cos(self):
-1061 return self._apply_func_to_corr(np.cos)
-1062
-1063 def tan(self):
-1064 return self._apply_func_to_corr(np.tan)
-1065
-1066 def sinh(self):
-1067 return self._apply_func_to_corr(np.sinh)
-1068
-1069 def cosh(self):
-1070 return self._apply_func_to_corr(np.cosh)
-1071
-1072 def tanh(self):
-1073 return self._apply_func_to_corr(np.tanh)
-1074
-1075 def arcsin(self):
-1076 return self._apply_func_to_corr(np.arcsin)
-1077
-1078 def arccos(self):
-1079 return self._apply_func_to_corr(np.arccos)
-1080
-1081 def arctan(self):
-1082 return self._apply_func_to_corr(np.arctan)
-1083
-1084 def arcsinh(self):
-1085 return self._apply_func_to_corr(np.arcsinh)
-1086
-1087 def arccosh(self):
-1088 return self._apply_func_to_corr(np.arccosh)
-1089
-1090 def arctanh(self):
-1091 return self._apply_func_to_corr(np.arctanh)
-1092
-1093 # Right hand side operations (require tweak in main module to work)
-1094 def __radd__(self, y):
-1095 return self + y
+1046 def exp(self):
+1047 newcontent = [None if (item is None) else np.exp(item) for item in self.content]
+1048 return Corr(newcontent, prange=self.prange)
+1049
+1050 def _apply_func_to_corr(self, func):
+1051 newcontent = [None if (item is None) else func(item) for item in self.content]
+1052 for t in range(self.T):
+1053 if newcontent[t] is None:
+1054 continue
+1055 if np.isnan(np.sum(newcontent[t]).value):
+1056 newcontent[t] = None
+1057 if all([item is None for item in newcontent]):
+1058 raise Exception('Operation returns undefined correlator')
+1059 return Corr(newcontent)
+1060
+1061 def sin(self):
+1062 return self._apply_func_to_corr(np.sin)
+1063
+1064 def cos(self):
+1065 return self._apply_func_to_corr(np.cos)
+1066
+1067 def tan(self):
+1068 return self._apply_func_to_corr(np.tan)
+1069
+1070 def sinh(self):
+1071 return self._apply_func_to_corr(np.sinh)
+1072
+1073 def cosh(self):
+1074 return self._apply_func_to_corr(np.cosh)
+1075
+1076 def tanh(self):
+1077 return self._apply_func_to_corr(np.tanh)
+1078
+1079 def arcsin(self):
+1080 return self._apply_func_to_corr(np.arcsin)
+1081
+1082 def arccos(self):
+1083 return self._apply_func_to_corr(np.arccos)
+1084
+1085 def arctan(self):
+1086 return self._apply_func_to_corr(np.arctan)
+1087
+1088 def arcsinh(self):
+1089 return self._apply_func_to_corr(np.arcsinh)
+1090
+1091 def arccosh(self):
+1092 return self._apply_func_to_corr(np.arccosh)
+1093
+1094 def arctanh(self):
+1095 return self._apply_func_to_corr(np.arctanh)
1096
-1097 def __rsub__(self, y):
-1098 return -self + y
-1099
-1100 def __rmul__(self, y):
-1101 return self * y
-1102
-1103 def __rtruediv__(self, y):
-1104 return (self / y) ** (-1)
-1105
-1106 @property
-1107 def real(self):
-1108 def return_real(obs_OR_cobs):
-1109 if isinstance(obs_OR_cobs, CObs):
-1110 return obs_OR_cobs.real
-1111 else:
-1112 return obs_OR_cobs
-1113
-1114 return self._apply_func_to_corr(return_real)
-1115
-1116 @property
-1117 def imag(self):
-1118 def return_imag(obs_OR_cobs):
-1119 if isinstance(obs_OR_cobs, CObs):
-1120 return obs_OR_cobs.imag
-1121 else:
-1122 return obs_OR_cobs * 0 # So it stays the right type
-1123
-1124 return self._apply_func_to_corr(return_imag)
-1125
-1126 def prune(self, Ntrunc, tproj=3, t0proj=2, basematrix=None):
-1127 r''' Project large correlation matrix to lowest states
-1128
-1129 This method can be used to reduce the size of an (N x N) correlation matrix
-1130 to (Ntrunc x Ntrunc) by solving a GEVP at very early times where the noise
-1131 is still small.
+1097 # Right hand side operations (require tweak in main module to work)
+1098 def __radd__(self, y):
+1099 return self + y
+1100
+1101 def __rsub__(self, y):
+1102 return -self + y
+1103
+1104 def __rmul__(self, y):
+1105 return self * y
+1106
+1107 def __rtruediv__(self, y):
+1108 return (self / y) ** (-1)
+1109
+1110 @property
+1111 def real(self):
+1112 def return_real(obs_OR_cobs):
+1113 if isinstance(obs_OR_cobs, CObs):
+1114 return obs_OR_cobs.real
+1115 else:
+1116 return obs_OR_cobs
+1117
+1118 return self._apply_func_to_corr(return_real)
+1119
+1120 @property
+1121 def imag(self):
+1122 def return_imag(obs_OR_cobs):
+1123 if isinstance(obs_OR_cobs, CObs):
+1124 return obs_OR_cobs.imag
+1125 else:
+1126 return obs_OR_cobs * 0 # So it stays the right type
+1127
+1128 return self._apply_func_to_corr(return_imag)
+1129
+1130 def prune(self, Ntrunc, tproj=3, t0proj=2, basematrix=None):
+1131 r''' Project large correlation matrix to lowest states
1132
-1133 Parameters
-1134 ----------
-1135 Ntrunc: int
-1136 Rank of the target matrix.
-1137 tproj: int
-1138 Time where the eigenvectors are evaluated, corresponds to ts in the GEVP method.
-1139 The default value is 3.
-1140 t0proj: int
-1141 Time where the correlation matrix is inverted. Choosing t0proj=1 is strongly
-1142 discouraged for O(a) improved theories, since the correctness of the procedure
-1143 cannot be granted in this case. The default value is 2.
-1144 basematrix : Corr
-1145 Correlation matrix that is used to determine the eigenvectors of the
-1146 lowest states based on a GEVP. basematrix is taken to be the Corr itself if
-1147 is is not specified.
-1148
-1149 Notes
-1150 -----
-1151 We have the basematrix $C(t)$ and the target matrix $G(t)$. We start by solving
-1152 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}$
-1153 and $t_0 \equiv t_{0, \mathrm{proj}}$. The target matrix is projected onto the subspace of the
-1154 resulting eigenvectors $v_n, n=1,\dots,N_\mathrm{trunc}$ via
-1155 $$G^\prime_{i, j}(t) = (v_i, G(t) v_j)$$. This allows to reduce the size of a large
-1156 correlation matrix and to remove some noise that is added by irrelevant operators.
-1157 This may allow to use the GEVP on $G(t)$ at late times such that the theoretically motivated
-1158 bound $t_0 \leq t/2$ holds, since the condition number of $G(t)$ is decreased, compared to $C(t)$.
-1159 '''
-1160
-1161 if self.N == 1:
-1162 raise Exception('Method cannot be applied to one-dimensional correlators.')
-1163 if basematrix is None:
-1164 basematrix = self
-1165 if Ntrunc >= basematrix.N:
-1166 raise Exception('Cannot truncate using Ntrunc <= %d' % (basematrix.N))
-1167 if basematrix.N != self.N:
-1168 raise Exception('basematrix and targetmatrix have to be of the same size.')
-1169
-1170 evecs = []
-1171 for i in range(Ntrunc):
-1172 evecs.append(basematrix.GEVP(t0proj, tproj, state=i, sorted_list=None))
+1133 This method can be used to reduce the size of an (N x N) correlation matrix
+1134 to (Ntrunc x Ntrunc) by solving a GEVP at very early times where the noise
+1135 is still small.
+1136
+1137 Parameters
+1138 ----------
+1139 Ntrunc: int
+1140 Rank of the target matrix.
+1141 tproj: int
+1142 Time where the eigenvectors are evaluated, corresponds to ts in the GEVP method.
+1143 The default value is 3.
+1144 t0proj: int
+1145 Time where the correlation matrix is inverted. Choosing t0proj=1 is strongly
+1146 discouraged for O(a) improved theories, since the correctness of the procedure
+1147 cannot be granted in this case. The default value is 2.
+1148 basematrix : Corr
+1149 Correlation matrix that is used to determine the eigenvectors of the
+1150 lowest states based on a GEVP. basematrix is taken to be the Corr itself if
+1151 is is not specified.
+1152
+1153 Notes
+1154 -----
+1155 We have the basematrix $C(t)$ and the target matrix $G(t)$. We start by solving
+1156 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}$
+1157 and $t_0 \equiv t_{0, \mathrm{proj}}$. The target matrix is projected onto the subspace of the
+1158 resulting eigenvectors $v_n, n=1,\dots,N_\mathrm{trunc}$ via
+1159 $$G^\prime_{i, j}(t) = (v_i, G(t) v_j)$$. This allows to reduce the size of a large
+1160 correlation matrix and to remove some noise that is added by irrelevant operators.
+1161 This may allow to use the GEVP on $G(t)$ at late times such that the theoretically motivated
+1162 bound $t_0 \leq t/2$ holds, since the condition number of $G(t)$ is decreased, compared to $C(t)$.
+1163 '''
+1164
+1165 if self.N == 1:
+1166 raise Exception('Method cannot be applied to one-dimensional correlators.')
+1167 if basematrix is None:
+1168 basematrix = self
+1169 if Ntrunc >= basematrix.N:
+1170 raise Exception('Cannot truncate using Ntrunc <= %d' % (basematrix.N))
+1171 if basematrix.N != self.N:
+1172 raise Exception('basematrix and targetmatrix have to be of the same size.')
1173
-1174 tmpmat = np.empty((Ntrunc, Ntrunc), dtype=object)
-1175 rmat = []
-1176 for t in range(basematrix.T):
-1177 for i in range(Ntrunc):
-1178 for j in range(Ntrunc):
-1179 tmpmat[i][j] = evecs[i].T @ self[t] @ evecs[j]
-1180 rmat.append(np.copy(tmpmat))
-1181
-1182 newcontent = [None if (self.content[t] is None) else rmat[t] for t in range(self.T)]
-1183 return Corr(newcontent)
-1184
+1174 evecs = []
+1175 for i in range(Ntrunc):
+1176 evecs.append(basematrix.GEVP(t0proj, tproj, state=i, sorted_list=None))
+1177
+1178 tmpmat = np.empty((Ntrunc, Ntrunc), dtype=object)
+1179 rmat = []
+1180 for t in range(basematrix.T):
+1181 for i in range(Ntrunc):
+1182 for j in range(Ntrunc):
+1183 tmpmat[i][j] = evecs[i].T @ self[t] @ evecs[j]
+1184 rmat.append(np.copy(tmpmat))
1185
-1186def _sort_vectors(vec_set, ts):
-1187 """Helper function used to find a set of Eigenvectors consistent over all timeslices"""
-1188 reference_sorting = np.array(vec_set[ts])
-1189 N = reference_sorting.shape[0]
-1190 sorted_vec_set = []
-1191 for t in range(len(vec_set)):
-1192 if vec_set[t] is None:
-1193 sorted_vec_set.append(None)
-1194 elif not t == ts:
-1195 perms = [list(o) for o in permutations([i for i in range(N)], N)]
-1196 best_score = 0
-1197 for perm in perms:
-1198 current_score = 1
-1199 for k in range(N):
-1200 new_sorting = reference_sorting.copy()
-1201 new_sorting[perm[k], :] = vec_set[t][k]
-1202 current_score *= abs(np.linalg.det(new_sorting))
-1203 if current_score > best_score:
-1204 best_score = current_score
-1205 best_perm = perm
-1206 sorted_vec_set.append([vec_set[t][k] for k in best_perm])
-1207 else:
-1208 sorted_vec_set.append(vec_set[t])
-1209
-1210 return sorted_vec_set
-1211
-1212
-1213def _GEVP_solver(Gt, G0): # Just so normalization an sorting does not need to be repeated. Here we could later put in some checks
-1214 sp_val, sp_vecs = scipy.linalg.eigh(Gt, G0)
-1215 sp_vecs = [sp_vecs[:, np.argsort(sp_val)[-i]] for i in range(1, sp_vecs.shape[0] + 1)]
-1216 sp_vecs = [v / np.sqrt((v.T @ G0 @ v)) for v in sp_vecs]
-1217 return sp_vecs
+1186 newcontent = [None if (self.content[t] is None) else rmat[t] for t in range(self.T)]
+1187 return Corr(newcontent)
+1188
+1189
+1190def _sort_vectors(vec_set, ts):
+1191 """Helper function used to find a set of Eigenvectors consistent over all timeslices"""
+1192 reference_sorting = np.array(vec_set[ts])
+1193 N = reference_sorting.shape[0]
+1194 sorted_vec_set = []
+1195 for t in range(len(vec_set)):
+1196 if vec_set[t] is None:
+1197 sorted_vec_set.append(None)
+1198 elif not t == ts:
+1199 perms = [list(o) for o in permutations([i for i in range(N)], N)]
+1200 best_score = 0
+1201 for perm in perms:
+1202 current_score = 1
+1203 for k in range(N):
+1204 new_sorting = reference_sorting.copy()
+1205 new_sorting[perm[k], :] = vec_set[t][k]
+1206 current_score *= abs(np.linalg.det(new_sorting))
+1207 if current_score > best_score:
+1208 best_score = current_score
+1209 best_perm = perm
+1210 sorted_vec_set.append([vec_set[t][k] for k in best_perm])
+1211 else:
+1212 sorted_vec_set.append(vec_set[t])
+1213
+1214 return sorted_vec_set
+1215
+1216
+1217def _GEVP_solver(Gt, G0): # Just so normalization an sorting does not need to be repeated. Here we could later put in some checks
+1218 sp_val, sp_vecs = scipy.linalg.eigh(Gt, G0)
+1219 sp_vecs = [sp_vecs[:, np.argsort(sp_val)[-i]] for i in range(1, sp_vecs.shape[0] + 1)]
+1220 sp_vecs = [v / np.sqrt((v.T @ G0 @ v)) for v in sp_vecs]
+1221 return sp_vecs
@@ -1693,929 +1697,933 @@
259 "Eigenvector" - Use the method described in arXiv:2004.10472 [hep-lat] to find the set of v(t) belonging to the state.
260 The reference state is identified by its eigenvalue at t=ts
261 """
- 262 symmetric_corr = self.matrix_symmetric()
- 263 if sorted_list is None:
- 264 if (ts is None):
- 265 raise Exception("ts is required if sorted_list=None")
- 266 if (self.content[t0] is None) or (self.content[ts] is None):
- 267 raise Exception("Corr not defined at t0/ts")
- 268 G0, Gt = np.empty([self.N, self.N], dtype="double"), np.empty([self.N, self.N], dtype="double")
- 269 for i in range(self.N):
- 270 for j in range(self.N):
- 271 G0[i, j] = symmetric_corr[t0][i, j].value
- 272 Gt[i, j] = symmetric_corr[ts][i, j].value
- 273
- 274 sp_vecs = _GEVP_solver(Gt, G0)
- 275 sp_vec = sp_vecs[state]
- 276 return sp_vec
- 277 elif sorted_list in ["Eigenvalue", "Eigenvector"]:
- 278 all_vecs = []
- 279 for t in range(self.T):
- 280 try:
- 281 G0, Gt = np.empty([self.N, self.N], dtype="double"), np.empty([self.N, self.N], dtype="double")
- 282 for i in range(self.N):
- 283 for j in range(self.N):
- 284 G0[i, j] = symmetric_corr[t0][i, j].value
- 285 Gt[i, j] = symmetric_corr[t][i, j].value
- 286
- 287 sp_vecs = _GEVP_solver(Gt, G0)
- 288 if sorted_list == "Eigenvalue":
- 289 sp_vec = sp_vecs[state]
- 290 all_vecs.append(sp_vec)
- 291 else:
- 292 all_vecs.append(sp_vecs)
- 293 except Exception:
- 294 all_vecs.append(None)
- 295 if sorted_list == "Eigenvector":
- 296 if (ts is None):
- 297 raise Exception("ts is required for the Eigenvector sorting method.")
- 298 all_vecs = _sort_vectors(all_vecs, ts)
- 299 all_vecs = [a[state] for a in all_vecs]
- 300 else:
- 301 raise Exception("Unkown value for 'sorted_list'.")
- 302
- 303 return all_vecs
- 304
- 305 def Eigenvalue(self, t0, ts=None, state=0, sorted_list=None):
- 306 """Determines the eigenvalue of the GEVP by solving and projecting the correlator
- 307
- 308 Parameters
- 309 ----------
- 310 t0 : int
- 311 The time t0 for G(t)v= lambda G(t_0)v
- 312 ts : int
- 313 fixed time G(t_s)v= lambda G(t_0)v if return_list=False
- 314 If return_list=True and sorting=Eigenvector it gives a reference point for the sorting method.
- 315 state : int
- 316 The state one is interested in ordered by energy. The lowest state is zero.
- 317 sorted_list : string
- 318 if this argument is set, a list of vectors (len=self.T) is returned. If it is left as None, only one vector is returned.
- 319 "Eigenvalue" - The eigenvector is chosen according to which eigenvalue it belongs individually on every timeslice.
- 320 "Eigenvector" - Use the method described in arXiv:2004.10472 [hep-lat] to find the set of v(t) belonging to the state.
- 321 The reference state is identified by its eigenvalue at t=ts
- 322 """
- 323 vec = self.GEVP(t0, ts=ts, state=state, sorted_list=sorted_list)
- 324 return self.projected(vec)
- 325
- 326 def Hankel(self, N, periodic=False):
- 327 """Constructs an NxN Hankel matrix
- 328
- 329 C(t) c(t+1) ... c(t+n-1)
- 330 C(t+1) c(t+2) ... c(t+n)
- 331 .................
- 332 C(t+(n-1)) c(t+n) ... c(t+2(n-1))
- 333
- 334 Parameters
- 335 ----------
- 336 N : int
- 337 Dimension of the Hankel matrix
- 338 periodic : bool, optional
- 339 determines whether the matrix is extended periodically
- 340 """
- 341
- 342 if self.N != 1:
- 343 raise Exception("Multi-operator Prony not implemented!")
- 344
- 345 array = np.empty([N, N], dtype="object")
- 346 new_content = []
- 347 for t in range(self.T):
- 348 new_content.append(array.copy())
- 349
- 350 def wrap(i):
- 351 while i >= self.T:
- 352 i -= self.T
- 353 return i
- 354
- 355 for t in range(self.T):
- 356 for i in range(N):
- 357 for j in range(N):
- 358 if periodic:
- 359 new_content[t][i, j] = self.content[wrap(t + i + j)][0]
- 360 elif (t + i + j) >= self.T:
- 361 new_content[t] = None
- 362 else:
- 363 new_content[t][i, j] = self.content[t + i + j][0]
- 364
- 365 return Corr(new_content)
- 366
- 367 def roll(self, dt):
- 368 """Periodically shift the correlator by dt timeslices
- 369
- 370 Parameters
- 371 ----------
- 372 dt : int
- 373 number of timeslices
- 374 """
- 375 return Corr(list(np.roll(np.array(self.content, dtype=object), dt)))
- 376
- 377 def reverse(self):
- 378 """Reverse the time ordering of the Corr"""
- 379 return Corr(self.content[:: -1])
+ 262
+ 263 if self.N == 1:
+ 264 raise Exception("GEVP methods only works on correlator matrices and not single correlators.")
+ 265
+ 266 symmetric_corr = self.matrix_symmetric()
+ 267 if sorted_list is None:
+ 268 if (ts is None):
+ 269 raise Exception("ts is required if sorted_list=None")
+ 270 if (self.content[t0] is None) or (self.content[ts] is None):
+ 271 raise Exception("Corr not defined at t0/ts")
+ 272 G0, Gt = np.empty([self.N, self.N], dtype="double"), np.empty([self.N, self.N], dtype="double")
+ 273 for i in range(self.N):
+ 274 for j in range(self.N):
+ 275 G0[i, j] = symmetric_corr[t0][i, j].value
+ 276 Gt[i, j] = symmetric_corr[ts][i, j].value
+ 277
+ 278 sp_vecs = _GEVP_solver(Gt, G0)
+ 279 sp_vec = sp_vecs[state]
+ 280 return sp_vec
+ 281 elif sorted_list in ["Eigenvalue", "Eigenvector"]:
+ 282 all_vecs = []
+ 283 for t in range(self.T):
+ 284 try:
+ 285 G0, Gt = np.empty([self.N, self.N], dtype="double"), np.empty([self.N, self.N], dtype="double")
+ 286 for i in range(self.N):
+ 287 for j in range(self.N):
+ 288 G0[i, j] = symmetric_corr[t0][i, j].value
+ 289 Gt[i, j] = symmetric_corr[t][i, j].value
+ 290
+ 291 sp_vecs = _GEVP_solver(Gt, G0)
+ 292 if sorted_list == "Eigenvalue":
+ 293 sp_vec = sp_vecs[state]
+ 294 all_vecs.append(sp_vec)
+ 295 else:
+ 296 all_vecs.append(sp_vecs)
+ 297 except Exception:
+ 298 all_vecs.append(None)
+ 299 if sorted_list == "Eigenvector":
+ 300 if (ts is None):
+ 301 raise Exception("ts is required for the Eigenvector sorting method.")
+ 302 all_vecs = _sort_vectors(all_vecs, ts)
+ 303 all_vecs = [a[state] for a in all_vecs]
+ 304 else:
+ 305 raise Exception("Unkown value for 'sorted_list'.")
+ 306
+ 307 return all_vecs
+ 308
+ 309 def Eigenvalue(self, t0, ts=None, state=0, sorted_list=None):
+ 310 """Determines the eigenvalue of the GEVP by solving and projecting the correlator
+ 311
+ 312 Parameters
+ 313 ----------
+ 314 t0 : int
+ 315 The time t0 for G(t)v= lambda G(t_0)v
+ 316 ts : int
+ 317 fixed time G(t_s)v= lambda G(t_0)v if return_list=False
+ 318 If return_list=True and sorting=Eigenvector it gives a reference point for the sorting method.
+ 319 state : int
+ 320 The state one is interested in ordered by energy. The lowest state is zero.
+ 321 sorted_list : string
+ 322 if this argument is set, a list of vectors (len=self.T) is returned. If it is left as None, only one vector is returned.
+ 323 "Eigenvalue" - The eigenvector is chosen according to which eigenvalue it belongs individually on every timeslice.
+ 324 "Eigenvector" - Use the method described in arXiv:2004.10472 [hep-lat] to find the set of v(t) belonging to the state.
+ 325 The reference state is identified by its eigenvalue at t=ts
+ 326 """
+ 327 vec = self.GEVP(t0, ts=ts, state=state, sorted_list=sorted_list)
+ 328 return self.projected(vec)
+ 329
+ 330 def Hankel(self, N, periodic=False):
+ 331 """Constructs an NxN Hankel matrix
+ 332
+ 333 C(t) c(t+1) ... c(t+n-1)
+ 334 C(t+1) c(t+2) ... c(t+n)
+ 335 .................
+ 336 C(t+(n-1)) c(t+n) ... c(t+2(n-1))
+ 337
+ 338 Parameters
+ 339 ----------
+ 340 N : int
+ 341 Dimension of the Hankel matrix
+ 342 periodic : bool, optional
+ 343 determines whether the matrix is extended periodically
+ 344 """
+ 345
+ 346 if self.N != 1:
+ 347 raise Exception("Multi-operator Prony not implemented!")
+ 348
+ 349 array = np.empty([N, N], dtype="object")
+ 350 new_content = []
+ 351 for t in range(self.T):
+ 352 new_content.append(array.copy())
+ 353
+ 354 def wrap(i):
+ 355 while i >= self.T:
+ 356 i -= self.T
+ 357 return i
+ 358
+ 359 for t in range(self.T):
+ 360 for i in range(N):
+ 361 for j in range(N):
+ 362 if periodic:
+ 363 new_content[t][i, j] = self.content[wrap(t + i + j)][0]
+ 364 elif (t + i + j) >= self.T:
+ 365 new_content[t] = None
+ 366 else:
+ 367 new_content[t][i, j] = self.content[t + i + j][0]
+ 368
+ 369 return Corr(new_content)
+ 370
+ 371 def roll(self, dt):
+ 372 """Periodically shift the correlator by dt timeslices
+ 373
+ 374 Parameters
+ 375 ----------
+ 376 dt : int
+ 377 number of timeslices
+ 378 """
+ 379 return Corr(list(np.roll(np.array(self.content, dtype=object), dt)))
380
- 381 def thin(self, spacing=2, offset=0):
- 382 """Thin out a correlator to suppress correlations
- 383
- 384 Parameters
- 385 ----------
- 386 spacing : int
- 387 Keep only every 'spacing'th entry of the correlator
- 388 offset : int
- 389 Offset the equal spacing
- 390 """
- 391 new_content = []
- 392 for t in range(self.T):
- 393 if (offset + t) % spacing != 0:
- 394 new_content.append(None)
- 395 else:
- 396 new_content.append(self.content[t])
- 397 return Corr(new_content)
- 398
- 399 def correlate(self, partner):
- 400 """Correlate the correlator with another correlator or Obs
- 401
- 402 Parameters
- 403 ----------
- 404 partner : Obs or Corr
- 405 partner to correlate the correlator with.
- 406 Can either be an Obs which is correlated with all entries of the
- 407 correlator or a Corr of same length.
- 408 """
- 409 new_content = []
- 410 for x0, t_slice in enumerate(self.content):
- 411 if t_slice is None:
- 412 new_content.append(None)
- 413 else:
- 414 if isinstance(partner, Corr):
- 415 if partner.content[x0] is None:
- 416 new_content.append(None)
- 417 else:
- 418 new_content.append(np.array([correlate(o, partner.content[x0][0]) for o in t_slice]))
- 419 elif isinstance(partner, Obs): # Should this include CObs?
- 420 new_content.append(np.array([correlate(o, partner) for o in t_slice]))
- 421 else:
- 422 raise Exception("Can only correlate with an Obs or a Corr.")
- 423
- 424 return Corr(new_content)
- 425
- 426 def reweight(self, weight, **kwargs):
- 427 """Reweight the correlator.
- 428
- 429 Parameters
- 430 ----------
- 431 weight : Obs
- 432 Reweighting factor. An Observable that has to be defined on a superset of the
- 433 configurations in obs[i].idl for all i.
- 434 all_configs : bool
- 435 if True, the reweighted observables are normalized by the average of
- 436 the reweighting factor on all configurations in weight.idl and not
- 437 on the configurations in obs[i].idl.
- 438 """
- 439 new_content = []
- 440 for t_slice in self.content:
- 441 if t_slice is None:
- 442 new_content.append(None)
- 443 else:
- 444 new_content.append(np.array(reweight(weight, t_slice, **kwargs)))
- 445 return Corr(new_content)
- 446
- 447 def T_symmetry(self, partner, parity=+1):
- 448 """Return the time symmetry average of the correlator and its partner
- 449
- 450 Parameters
- 451 ----------
- 452 partner : Corr
- 453 Time symmetry partner of the Corr
- 454 partity : int
- 455 Parity quantum number of the correlator, can be +1 or -1
- 456 """
- 457 if not isinstance(partner, Corr):
- 458 raise Exception("T partner has to be a Corr object.")
- 459 if parity not in [+1, -1]:
- 460 raise Exception("Parity has to be +1 or -1.")
- 461 T_partner = parity * partner.reverse()
- 462
- 463 t_slices = []
- 464 test = (self - T_partner)
- 465 test.gamma_method()
- 466 for x0, t_slice in enumerate(test.content):
- 467 if t_slice is not None:
- 468 if not t_slice[0].is_zero_within_error(5):
- 469 t_slices.append(x0)
- 470 if t_slices:
- 471 warnings.warn("T symmetry partners do not agree within 5 sigma on time slices " + str(t_slices) + ".", RuntimeWarning)
- 472
- 473 return (self + T_partner) / 2
- 474
- 475 def deriv(self, variant="symmetric"):
- 476 """Return the first derivative of the correlator with respect to x0.
- 477
- 478 Parameters
- 479 ----------
- 480 variant : str
- 481 decides which definition of the finite differences derivative is used.
- 482 Available choice: symmetric, forward, backward, improved, default: symmetric
- 483 """
- 484 if variant == "symmetric":
- 485 newcontent = []
- 486 for t in range(1, self.T - 1):
- 487 if (self.content[t - 1] is None) or (self.content[t + 1] is None):
- 488 newcontent.append(None)
- 489 else:
- 490 newcontent.append(0.5 * (self.content[t + 1] - self.content[t - 1]))
- 491 if(all([x is None for x in newcontent])):
- 492 raise Exception('Derivative is undefined at all timeslices')
- 493 return Corr(newcontent, padding=[1, 1])
- 494 elif variant == "forward":
- 495 newcontent = []
- 496 for t in range(self.T - 1):
- 497 if (self.content[t] is None) or (self.content[t + 1] is None):
- 498 newcontent.append(None)
- 499 else:
- 500 newcontent.append(self.content[t + 1] - self.content[t])
- 501 if(all([x is None for x in newcontent])):
- 502 raise Exception("Derivative is undefined at all timeslices")
- 503 return Corr(newcontent, padding=[0, 1])
- 504 elif variant == "backward":
- 505 newcontent = []
- 506 for t in range(1, self.T):
- 507 if (self.content[t - 1] is None) or (self.content[t] is None):
- 508 newcontent.append(None)
- 509 else:
- 510 newcontent.append(self.content[t] - self.content[t - 1])
- 511 if(all([x is None for x in newcontent])):
- 512 raise Exception("Derivative is undefined at all timeslices")
- 513 return Corr(newcontent, padding=[1, 0])
- 514 elif variant == "improved":
- 515 newcontent = []
- 516 for t in range(2, self.T - 2):
- 517 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):
- 518 newcontent.append(None)
- 519 else:
- 520 newcontent.append((1 / 12) * (self.content[t - 2] - 8 * self.content[t - 1] + 8 * self.content[t + 1] - self.content[t + 2]))
- 521 if(all([x is None for x in newcontent])):
- 522 raise Exception('Derivative is undefined at all timeslices')
- 523 return Corr(newcontent, padding=[2, 2])
- 524 else:
- 525 raise Exception("Unknown variant.")
- 526
- 527 def second_deriv(self, variant="symmetric"):
- 528 """Return the second derivative of the correlator with respect to x0.
- 529
- 530 Parameters
- 531 ----------
- 532 variant : str
- 533 decides which definition of the finite differences derivative is used.
- 534 Available choice: symmetric, improved, default: symmetric
- 535 """
- 536 if variant == "symmetric":
- 537 newcontent = []
- 538 for t in range(1, self.T - 1):
- 539 if (self.content[t - 1] is None) or (self.content[t + 1] is None):
- 540 newcontent.append(None)
- 541 else:
- 542 newcontent.append((self.content[t + 1] - 2 * self.content[t] + self.content[t - 1]))
- 543 if(all([x is None for x in newcontent])):
- 544 raise Exception("Derivative is undefined at all timeslices")
- 545 return Corr(newcontent, padding=[1, 1])
- 546 elif variant == "improved":
- 547 newcontent = []
- 548 for t in range(2, self.T - 2):
- 549 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):
- 550 newcontent.append(None)
- 551 else:
- 552 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]))
- 553 if(all([x is None for x in newcontent])):
- 554 raise Exception("Derivative is undefined at all timeslices")
- 555 return Corr(newcontent, padding=[2, 2])
- 556 else:
- 557 raise Exception("Unknown variant.")
- 558
- 559 def m_eff(self, variant='log', guess=1.0):
- 560 """Returns the effective mass of the correlator as correlator object
- 561
- 562 Parameters
- 563 ----------
- 564 variant : str
- 565 log : uses the standard effective mass log(C(t) / C(t+1))
- 566 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.
- 567 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.
- 568 See, e.g., arXiv:1205.5380
- 569 arccosh : Uses the explicit form of the symmetrized correlator (not recommended)
- 570 guess : float
- 571 guess for the root finder, only relevant for the root variant
- 572 """
- 573 if self.N != 1:
- 574 raise Exception('Correlator must be projected before getting m_eff')
- 575 if variant == 'log':
- 576 newcontent = []
- 577 for t in range(self.T - 1):
- 578 if (self.content[t] is None) or (self.content[t + 1] is None):
- 579 newcontent.append(None)
- 580 else:
- 581 newcontent.append(self.content[t] / self.content[t + 1])
- 582 if(all([x is None for x in newcontent])):
- 583 raise Exception('m_eff is undefined at all timeslices')
- 584
- 585 return np.log(Corr(newcontent, padding=[0, 1]))
- 586
- 587 elif variant in ['periodic', 'cosh', 'sinh']:
- 588 if variant in ['periodic', 'cosh']:
- 589 func = anp.cosh
- 590 else:
- 591 func = anp.sinh
- 592
- 593 def root_function(x, d):
- 594 return func(x * (t - self.T / 2)) / func(x * (t + 1 - self.T / 2)) - d
- 595
- 596 newcontent = []
- 597 for t in range(self.T - 1):
- 598 if (self.content[t] is None) or (self.content[t + 1] is None):
- 599 newcontent.append(None)
- 600 # Fill the two timeslices in the middle of the lattice with their predecessors
- 601 elif variant == 'sinh' and t in [self.T / 2, self.T / 2 - 1]:
- 602 newcontent.append(newcontent[-1])
- 603 else:
- 604 newcontent.append(np.abs(find_root(self.content[t][0] / self.content[t + 1][0], root_function, guess=guess)))
- 605 if(all([x is None for x in newcontent])):
- 606 raise Exception('m_eff is undefined at all timeslices')
- 607
- 608 return Corr(newcontent, padding=[0, 1])
- 609
- 610 elif variant == 'arccosh':
- 611 newcontent = []
- 612 for t in range(1, self.T - 1):
- 613 if (self.content[t] is None) or (self.content[t + 1] is None) or (self.content[t - 1] is None):
- 614 newcontent.append(None)
- 615 else:
- 616 newcontent.append((self.content[t + 1] + self.content[t - 1]) / (2 * self.content[t]))
- 617 if(all([x is None for x in newcontent])):
- 618 raise Exception("m_eff is undefined at all timeslices")
- 619 return np.arccosh(Corr(newcontent, padding=[1, 1]))
- 620
- 621 else:
- 622 raise Exception('Unknown variant.')
- 623
- 624 def fit(self, function, fitrange=None, silent=False, **kwargs):
- 625 r'''Fits function to the data
- 626
- 627 Parameters
- 628 ----------
- 629 function : obj
- 630 function to fit to the data. See fits.least_squares for details.
- 631 fitrange : list
- 632 Two element list containing the timeslices on which the fit is supposed to start and stop.
- 633 Caution: This range is inclusive as opposed to standard python indexing.
- 634 `fitrange=[4, 6]` corresponds to the three entries 4, 5 and 6.
- 635 If not specified, self.prange or all timeslices are used.
- 636 silent : bool
- 637 Decides whether output is printed to the standard output.
- 638 '''
- 639 if self.N != 1:
- 640 raise Exception("Correlator must be projected before fitting")
- 641
- 642 if fitrange is None:
- 643 if self.prange:
- 644 fitrange = self.prange
- 645 else:
- 646 fitrange = [0, self.T - 1]
- 647 else:
- 648 if not isinstance(fitrange, list):
- 649 raise Exception("fitrange has to be a list with two elements")
- 650 if len(fitrange) != 2:
- 651 raise Exception("fitrange has to have exactly two elements [fit_start, fit_stop]")
- 652
- 653 xs = [x for x in range(fitrange[0], fitrange[1] + 1) if not self.content[x] is None]
- 654 ys = [self.content[x][0] for x in range(fitrange[0], fitrange[1] + 1) if not self.content[x] is None]
- 655 result = least_squares(xs, ys, function, silent=silent, **kwargs)
- 656 return result
- 657
- 658 def plateau(self, plateau_range=None, method="fit", auto_gamma=False):
- 659 """ Extract a plateau value from a Corr object
- 660
- 661 Parameters
- 662 ----------
- 663 plateau_range : list
- 664 list with two entries, indicating the first and the last timeslice
- 665 of the plateau region.
- 666 method : str
- 667 method to extract the plateau.
- 668 'fit' fits a constant to the plateau region
- 669 'avg', 'average' or 'mean' just average over the given timeslices.
- 670 auto_gamma : bool
- 671 apply gamma_method with default parameters to the Corr. Defaults to None
- 672 """
- 673 if not plateau_range:
- 674 if self.prange:
- 675 plateau_range = self.prange
- 676 else:
- 677 raise Exception("no plateau range provided")
- 678 if self.N != 1:
- 679 raise Exception("Correlator must be projected before getting a plateau.")
- 680 if(all([self.content[t] is None for t in range(plateau_range[0], plateau_range[1] + 1)])):
- 681 raise Exception("plateau is undefined at all timeslices in plateaurange.")
- 682 if auto_gamma:
- 683 self.gamma_method()
- 684 if method == "fit":
- 685 def const_func(a, t):
- 686 return a[0]
- 687 return self.fit(const_func, plateau_range)[0]
- 688 elif method in ["avg", "average", "mean"]:
- 689 returnvalue = np.mean([item[0] for item in self.content[plateau_range[0]:plateau_range[1] + 1] if item is not None])
- 690 return returnvalue
- 691
- 692 else:
- 693 raise Exception("Unsupported plateau method: " + method)
- 694
- 695 def set_prange(self, prange):
- 696 """Sets the attribute prange of the Corr object."""
- 697 if not len(prange) == 2:
- 698 raise Exception("prange must be a list or array with two values")
- 699 if not ((isinstance(prange[0], int)) and (isinstance(prange[1], int))):
- 700 raise Exception("Start and end point must be integers")
- 701 if not (0 <= prange[0] <= self.T and 0 <= prange[1] <= self.T and prange[0] < prange[1]):
- 702 raise Exception("Start and end point must define a range in the interval 0,T")
- 703
- 704 self.prange = prange
- 705 return
- 706
- 707 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):
- 708 """Plots the correlator using the tag of the correlator as label if available.
- 709
- 710 Parameters
- 711 ----------
- 712 x_range : list
- 713 list of two values, determining the range of the x-axis e.g. [4, 8]
- 714 comp : Corr or list of Corr
- 715 Correlator or list of correlators which are plotted for comparison.
- 716 The tags of these correlators are used as labels if available.
- 717 logscale : bool
- 718 Sets y-axis to logscale
- 719 plateau : Obs
- 720 Plateau value to be visualized in the figure
- 721 fit_res : Fit_result
- 722 Fit_result object to be visualized
- 723 ylabel : str
- 724 Label for the y-axis
- 725 save : str
- 726 path to file in which the figure should be saved
- 727 auto_gamma : bool
- 728 Apply the gamma method with standard parameters to all correlators and plateau values before plotting.
- 729 hide_sigma : float
- 730 Hides data points from the first value on which is consistent with zero within 'hide_sigma' standard errors.
- 731 references : list
- 732 List of floating point values that are displayed as horizontal lines for reference.
- 733 """
- 734 if self.N != 1:
- 735 raise Exception("Correlator must be projected before plotting")
- 736
- 737 if auto_gamma:
- 738 self.gamma_method()
- 739
- 740 if x_range is None:
- 741 x_range = [0, self.T - 1]
- 742
- 743 fig = plt.figure()
- 744 ax1 = fig.add_subplot(111)
- 745
- 746 x, y, y_err = self.plottable()
- 747 if hide_sigma:
- 748 hide_from = np.argmax((hide_sigma * np.array(y_err)) > np.abs(y)) - 1
- 749 else:
- 750 hide_from = None
- 751 ax1.errorbar(x[:hide_from], y[:hide_from], y_err[:hide_from], label=self.tag)
- 752 if logscale:
- 753 ax1.set_yscale('log')
- 754 else:
- 755 if y_range is None:
- 756 try:
- 757 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)])
- 758 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)])
- 759 ax1.set_ylim([y_min - 0.1 * (y_max - y_min), y_max + 0.1 * (y_max - y_min)])
- 760 except Exception:
- 761 pass
- 762 else:
- 763 ax1.set_ylim(y_range)
- 764 if comp:
- 765 if isinstance(comp, (Corr, list)):
- 766 for corr in comp if isinstance(comp, list) else [comp]:
- 767 if auto_gamma:
- 768 corr.gamma_method()
- 769 x, y, y_err = corr.plottable()
- 770 if hide_sigma:
- 771 hide_from = np.argmax((hide_sigma * np.array(y_err)) > np.abs(y)) - 1
- 772 else:
- 773 hide_from = None
- 774 plt.errorbar(x[:hide_from], y[:hide_from], y_err[:hide_from], label=corr.tag, mfc=plt.rcParams['axes.facecolor'])
- 775 else:
- 776 raise Exception("'comp' must be a correlator or a list of correlators.")
- 777
- 778 if plateau:
- 779 if isinstance(plateau, Obs):
- 780 if auto_gamma:
- 781 plateau.gamma_method()
- 782 ax1.axhline(y=plateau.value, linewidth=2, color=plt.rcParams['text.color'], alpha=0.6, marker=',', ls='--', label=str(plateau))
- 783 ax1.axhspan(plateau.value - plateau.dvalue, plateau.value + plateau.dvalue, alpha=0.25, color=plt.rcParams['text.color'], ls='-')
- 784 else:
- 785 raise Exception("'plateau' must be an Obs")
- 786
- 787 if references:
- 788 if isinstance(references, list):
- 789 for ref in references:
- 790 ax1.axhline(y=ref, linewidth=1, color=plt.rcParams['text.color'], alpha=0.6, marker=',', ls='--')
- 791 else:
- 792 raise Exception("'references' must be a list of floating pint values.")
- 793
- 794 if self.prange:
- 795 ax1.axvline(self.prange[0], 0, 1, ls='-', marker=',')
- 796 ax1.axvline(self.prange[1], 0, 1, ls='-', marker=',')
+ 381 def reverse(self):
+ 382 """Reverse the time ordering of the Corr"""
+ 383 return Corr(self.content[:: -1])
+ 384
+ 385 def thin(self, spacing=2, offset=0):
+ 386 """Thin out a correlator to suppress correlations
+ 387
+ 388 Parameters
+ 389 ----------
+ 390 spacing : int
+ 391 Keep only every 'spacing'th entry of the correlator
+ 392 offset : int
+ 393 Offset the equal spacing
+ 394 """
+ 395 new_content = []
+ 396 for t in range(self.T):
+ 397 if (offset + t) % spacing != 0:
+ 398 new_content.append(None)
+ 399 else:
+ 400 new_content.append(self.content[t])
+ 401 return Corr(new_content)
+ 402
+ 403 def correlate(self, partner):
+ 404 """Correlate the correlator with another correlator or Obs
+ 405
+ 406 Parameters
+ 407 ----------
+ 408 partner : Obs or Corr
+ 409 partner to correlate the correlator with.
+ 410 Can either be an Obs which is correlated with all entries of the
+ 411 correlator or a Corr of same length.
+ 412 """
+ 413 new_content = []
+ 414 for x0, t_slice in enumerate(self.content):
+ 415 if t_slice is None:
+ 416 new_content.append(None)
+ 417 else:
+ 418 if isinstance(partner, Corr):
+ 419 if partner.content[x0] is None:
+ 420 new_content.append(None)
+ 421 else:
+ 422 new_content.append(np.array([correlate(o, partner.content[x0][0]) for o in t_slice]))
+ 423 elif isinstance(partner, Obs): # Should this include CObs?
+ 424 new_content.append(np.array([correlate(o, partner) for o in t_slice]))
+ 425 else:
+ 426 raise Exception("Can only correlate with an Obs or a Corr.")
+ 427
+ 428 return Corr(new_content)
+ 429
+ 430 def reweight(self, weight, **kwargs):
+ 431 """Reweight the correlator.
+ 432
+ 433 Parameters
+ 434 ----------
+ 435 weight : Obs
+ 436 Reweighting factor. An Observable that has to be defined on a superset of the
+ 437 configurations in obs[i].idl for all i.
+ 438 all_configs : bool
+ 439 if True, the reweighted observables are normalized by the average of
+ 440 the reweighting factor on all configurations in weight.idl and not
+ 441 on the configurations in obs[i].idl.
+ 442 """
+ 443 new_content = []
+ 444 for t_slice in self.content:
+ 445 if t_slice is None:
+ 446 new_content.append(None)
+ 447 else:
+ 448 new_content.append(np.array(reweight(weight, t_slice, **kwargs)))
+ 449 return Corr(new_content)
+ 450
+ 451 def T_symmetry(self, partner, parity=+1):
+ 452 """Return the time symmetry average of the correlator and its partner
+ 453
+ 454 Parameters
+ 455 ----------
+ 456 partner : Corr
+ 457 Time symmetry partner of the Corr
+ 458 partity : int
+ 459 Parity quantum number of the correlator, can be +1 or -1
+ 460 """
+ 461 if not isinstance(partner, Corr):
+ 462 raise Exception("T partner has to be a Corr object.")
+ 463 if parity not in [+1, -1]:
+ 464 raise Exception("Parity has to be +1 or -1.")
+ 465 T_partner = parity * partner.reverse()
+ 466
+ 467 t_slices = []
+ 468 test = (self - T_partner)
+ 469 test.gamma_method()
+ 470 for x0, t_slice in enumerate(test.content):
+ 471 if t_slice is not None:
+ 472 if not t_slice[0].is_zero_within_error(5):
+ 473 t_slices.append(x0)
+ 474 if t_slices:
+ 475 warnings.warn("T symmetry partners do not agree within 5 sigma on time slices " + str(t_slices) + ".", RuntimeWarning)
+ 476
+ 477 return (self + T_partner) / 2
+ 478
+ 479 def deriv(self, variant="symmetric"):
+ 480 """Return the first derivative of the correlator with respect to x0.
+ 481
+ 482 Parameters
+ 483 ----------
+ 484 variant : str
+ 485 decides which definition of the finite differences derivative is used.
+ 486 Available choice: symmetric, forward, backward, improved, default: symmetric
+ 487 """
+ 488 if variant == "symmetric":
+ 489 newcontent = []
+ 490 for t in range(1, self.T - 1):
+ 491 if (self.content[t - 1] is None) or (self.content[t + 1] is None):
+ 492 newcontent.append(None)
+ 493 else:
+ 494 newcontent.append(0.5 * (self.content[t + 1] - self.content[t - 1]))
+ 495 if(all([x is None for x in newcontent])):
+ 496 raise Exception('Derivative is undefined at all timeslices')
+ 497 return Corr(newcontent, padding=[1, 1])
+ 498 elif variant == "forward":
+ 499 newcontent = []
+ 500 for t in range(self.T - 1):
+ 501 if (self.content[t] is None) or (self.content[t + 1] is None):
+ 502 newcontent.append(None)
+ 503 else:
+ 504 newcontent.append(self.content[t + 1] - self.content[t])
+ 505 if(all([x is None for x in newcontent])):
+ 506 raise Exception("Derivative is undefined at all timeslices")
+ 507 return Corr(newcontent, padding=[0, 1])
+ 508 elif variant == "backward":
+ 509 newcontent = []
+ 510 for t in range(1, self.T):
+ 511 if (self.content[t - 1] is None) or (self.content[t] is None):
+ 512 newcontent.append(None)
+ 513 else:
+ 514 newcontent.append(self.content[t] - self.content[t - 1])
+ 515 if(all([x is None for x in newcontent])):
+ 516 raise Exception("Derivative is undefined at all timeslices")
+ 517 return Corr(newcontent, padding=[1, 0])
+ 518 elif variant == "improved":
+ 519 newcontent = []
+ 520 for t in range(2, self.T - 2):
+ 521 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):
+ 522 newcontent.append(None)
+ 523 else:
+ 524 newcontent.append((1 / 12) * (self.content[t - 2] - 8 * self.content[t - 1] + 8 * self.content[t + 1] - self.content[t + 2]))
+ 525 if(all([x is None for x in newcontent])):
+ 526 raise Exception('Derivative is undefined at all timeslices')
+ 527 return Corr(newcontent, padding=[2, 2])
+ 528 else:
+ 529 raise Exception("Unknown variant.")
+ 530
+ 531 def second_deriv(self, variant="symmetric"):
+ 532 """Return the second derivative of the correlator with respect to x0.
+ 533
+ 534 Parameters
+ 535 ----------
+ 536 variant : str
+ 537 decides which definition of the finite differences derivative is used.
+ 538 Available choice: symmetric, improved, default: symmetric
+ 539 """
+ 540 if variant == "symmetric":
+ 541 newcontent = []
+ 542 for t in range(1, self.T - 1):
+ 543 if (self.content[t - 1] is None) or (self.content[t + 1] is None):
+ 544 newcontent.append(None)
+ 545 else:
+ 546 newcontent.append((self.content[t + 1] - 2 * 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, 1])
+ 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] 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] + 16 * self.content[t + 1] - 30 * self.content[t] + 16 * 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 else:
+ 561 raise Exception("Unknown variant.")
+ 562
+ 563 def m_eff(self, variant='log', guess=1.0):
+ 564 """Returns the effective mass of the correlator as correlator object
+ 565
+ 566 Parameters
+ 567 ----------
+ 568 variant : str
+ 569 log : uses the standard effective mass log(C(t) / C(t+1))
+ 570 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.
+ 571 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.
+ 572 See, e.g., arXiv:1205.5380
+ 573 arccosh : Uses the explicit form of the symmetrized correlator (not recommended)
+ 574 guess : float
+ 575 guess for the root finder, only relevant for the root variant
+ 576 """
+ 577 if self.N != 1:
+ 578 raise Exception('Correlator must be projected before getting m_eff')
+ 579 if variant == 'log':
+ 580 newcontent = []
+ 581 for t in range(self.T - 1):
+ 582 if (self.content[t] is None) or (self.content[t + 1] is None):
+ 583 newcontent.append(None)
+ 584 else:
+ 585 newcontent.append(self.content[t] / self.content[t + 1])
+ 586 if(all([x is None for x in newcontent])):
+ 587 raise Exception('m_eff is undefined at all timeslices')
+ 588
+ 589 return np.log(Corr(newcontent, padding=[0, 1]))
+ 590
+ 591 elif variant in ['periodic', 'cosh', 'sinh']:
+ 592 if variant in ['periodic', 'cosh']:
+ 593 func = anp.cosh
+ 594 else:
+ 595 func = anp.sinh
+ 596
+ 597 def root_function(x, d):
+ 598 return func(x * (t - self.T / 2)) / func(x * (t + 1 - self.T / 2)) - d
+ 599
+ 600 newcontent = []
+ 601 for t in range(self.T - 1):
+ 602 if (self.content[t] is None) or (self.content[t + 1] is None):
+ 603 newcontent.append(None)
+ 604 # Fill the two timeslices in the middle of the lattice with their predecessors
+ 605 elif variant == 'sinh' and t in [self.T / 2, self.T / 2 - 1]:
+ 606 newcontent.append(newcontent[-1])
+ 607 else:
+ 608 newcontent.append(np.abs(find_root(self.content[t][0] / self.content[t + 1][0], root_function, guess=guess)))
+ 609 if(all([x is None for x in newcontent])):
+ 610 raise Exception('m_eff is undefined at all timeslices')
+ 611
+ 612 return Corr(newcontent, padding=[0, 1])
+ 613
+ 614 elif variant == 'arccosh':
+ 615 newcontent = []
+ 616 for t in range(1, self.T - 1):
+ 617 if (self.content[t] is None) or (self.content[t + 1] is None) or (self.content[t - 1] is None):
+ 618 newcontent.append(None)
+ 619 else:
+ 620 newcontent.append((self.content[t + 1] + self.content[t - 1]) / (2 * self.content[t]))
+ 621 if(all([x is None for x in newcontent])):
+ 622 raise Exception("m_eff is undefined at all timeslices")
+ 623 return np.arccosh(Corr(newcontent, padding=[1, 1]))
+ 624
+ 625 else:
+ 626 raise Exception('Unknown variant.')
+ 627
+ 628 def fit(self, function, fitrange=None, silent=False, **kwargs):
+ 629 r'''Fits function to the data
+ 630
+ 631 Parameters
+ 632 ----------
+ 633 function : obj
+ 634 function to fit to the data. See fits.least_squares for details.
+ 635 fitrange : list
+ 636 Two element list containing the timeslices on which the fit is supposed to start and stop.
+ 637 Caution: This range is inclusive as opposed to standard python indexing.
+ 638 `fitrange=[4, 6]` corresponds to the three entries 4, 5 and 6.
+ 639 If not specified, self.prange or all timeslices are used.
+ 640 silent : bool
+ 641 Decides whether output is printed to the standard output.
+ 642 '''
+ 643 if self.N != 1:
+ 644 raise Exception("Correlator must be projected before fitting")
+ 645
+ 646 if fitrange is None:
+ 647 if self.prange:
+ 648 fitrange = self.prange
+ 649 else:
+ 650 fitrange = [0, self.T - 1]
+ 651 else:
+ 652 if not isinstance(fitrange, list):
+ 653 raise Exception("fitrange has to be a list with two elements")
+ 654 if len(fitrange) != 2:
+ 655 raise Exception("fitrange has to have exactly two elements [fit_start, fit_stop]")
+ 656
+ 657 xs = [x for x in range(fitrange[0], fitrange[1] + 1) if not self.content[x] is None]
+ 658 ys = [self.content[x][0] for x in range(fitrange[0], fitrange[1] + 1) if not self.content[x] is None]
+ 659 result = least_squares(xs, ys, function, silent=silent, **kwargs)
+ 660 return result
+ 661
+ 662 def plateau(self, plateau_range=None, method="fit", auto_gamma=False):
+ 663 """ Extract a plateau value from a Corr object
+ 664
+ 665 Parameters
+ 666 ----------
+ 667 plateau_range : list
+ 668 list with two entries, indicating the first and the last timeslice
+ 669 of the plateau region.
+ 670 method : str
+ 671 method to extract the plateau.
+ 672 'fit' fits a constant to the plateau region
+ 673 'avg', 'average' or 'mean' just average over the given timeslices.
+ 674 auto_gamma : bool
+ 675 apply gamma_method with default parameters to the Corr. Defaults to None
+ 676 """
+ 677 if not plateau_range:
+ 678 if self.prange:
+ 679 plateau_range = self.prange
+ 680 else:
+ 681 raise Exception("no plateau range provided")
+ 682 if self.N != 1:
+ 683 raise Exception("Correlator must be projected before getting a plateau.")
+ 684 if(all([self.content[t] is None for t in range(plateau_range[0], plateau_range[1] + 1)])):
+ 685 raise Exception("plateau is undefined at all timeslices in plateaurange.")
+ 686 if auto_gamma:
+ 687 self.gamma_method()
+ 688 if method == "fit":
+ 689 def const_func(a, t):
+ 690 return a[0]
+ 691 return self.fit(const_func, plateau_range)[0]
+ 692 elif method in ["avg", "average", "mean"]:
+ 693 returnvalue = np.mean([item[0] for item in self.content[plateau_range[0]:plateau_range[1] + 1] if item is not None])
+ 694 return returnvalue
+ 695
+ 696 else:
+ 697 raise Exception("Unsupported plateau method: " + method)
+ 698
+ 699 def set_prange(self, prange):
+ 700 """Sets the attribute prange of the Corr object."""
+ 701 if not len(prange) == 2:
+ 702 raise Exception("prange must be a list or array with two values")
+ 703 if not ((isinstance(prange[0], int)) and (isinstance(prange[1], int))):
+ 704 raise Exception("Start and end point must be integers")
+ 705 if not (0 <= prange[0] <= self.T and 0 <= prange[1] <= self.T and prange[0] < prange[1]):
+ 706 raise Exception("Start and end point must define a range in the interval 0,T")
+ 707
+ 708 self.prange = prange
+ 709 return
+ 710
+ 711 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):
+ 712 """Plots the correlator using the tag of the correlator as label if available.
+ 713
+ 714 Parameters
+ 715 ----------
+ 716 x_range : list
+ 717 list of two values, determining the range of the x-axis e.g. [4, 8]
+ 718 comp : Corr or list of Corr
+ 719 Correlator or list of correlators which are plotted for comparison.
+ 720 The tags of these correlators are used as labels if available.
+ 721 logscale : bool
+ 722 Sets y-axis to logscale
+ 723 plateau : Obs
+ 724 Plateau value to be visualized in the figure
+ 725 fit_res : Fit_result
+ 726 Fit_result object to be visualized
+ 727 ylabel : str
+ 728 Label for the y-axis
+ 729 save : str
+ 730 path to file in which the figure should be saved
+ 731 auto_gamma : bool
+ 732 Apply the gamma method with standard parameters to all correlators and plateau values before plotting.
+ 733 hide_sigma : float
+ 734 Hides data points from the first value on which is consistent with zero within 'hide_sigma' standard errors.
+ 735 references : list
+ 736 List of floating point values that are displayed as horizontal lines for reference.
+ 737 """
+ 738 if self.N != 1:
+ 739 raise Exception("Correlator must be projected before plotting")
+ 740
+ 741 if auto_gamma:
+ 742 self.gamma_method()
+ 743
+ 744 if x_range is None:
+ 745 x_range = [0, self.T - 1]
+ 746
+ 747 fig = plt.figure()
+ 748 ax1 = fig.add_subplot(111)
+ 749
+ 750 x, y, y_err = self.plottable()
+ 751 if hide_sigma:
+ 752 hide_from = np.argmax((hide_sigma * np.array(y_err)) > np.abs(y)) - 1
+ 753 else:
+ 754 hide_from = None
+ 755 ax1.errorbar(x[:hide_from], y[:hide_from], y_err[:hide_from], label=self.tag)
+ 756 if logscale:
+ 757 ax1.set_yscale('log')
+ 758 else:
+ 759 if y_range is None:
+ 760 try:
+ 761 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)])
+ 762 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)])
+ 763 ax1.set_ylim([y_min - 0.1 * (y_max - y_min), y_max + 0.1 * (y_max - y_min)])
+ 764 except Exception:
+ 765 pass
+ 766 else:
+ 767 ax1.set_ylim(y_range)
+ 768 if comp:
+ 769 if isinstance(comp, (Corr, list)):
+ 770 for corr in comp if isinstance(comp, list) else [comp]:
+ 771 if auto_gamma:
+ 772 corr.gamma_method()
+ 773 x, y, y_err = corr.plottable()
+ 774 if hide_sigma:
+ 775 hide_from = np.argmax((hide_sigma * np.array(y_err)) > np.abs(y)) - 1
+ 776 else:
+ 777 hide_from = None
+ 778 plt.errorbar(x[:hide_from], y[:hide_from], y_err[:hide_from], label=corr.tag, mfc=plt.rcParams['axes.facecolor'])
+ 779 else:
+ 780 raise Exception("'comp' must be a correlator or a list of correlators.")
+ 781
+ 782 if plateau:
+ 783 if isinstance(plateau, Obs):
+ 784 if auto_gamma:
+ 785 plateau.gamma_method()
+ 786 ax1.axhline(y=plateau.value, linewidth=2, color=plt.rcParams['text.color'], alpha=0.6, marker=',', ls='--', label=str(plateau))
+ 787 ax1.axhspan(plateau.value - plateau.dvalue, plateau.value + plateau.dvalue, alpha=0.25, color=plt.rcParams['text.color'], ls='-')
+ 788 else:
+ 789 raise Exception("'plateau' must be an Obs")
+ 790
+ 791 if references:
+ 792 if isinstance(references, list):
+ 793 for ref in references:
+ 794 ax1.axhline(y=ref, linewidth=1, color=plt.rcParams['text.color'], alpha=0.6, marker=',', ls='--')
+ 795 else:
+ 796 raise Exception("'references' must be a list of floating pint values.")
797
- 798 if fit_res:
- 799 x_samples = np.arange(x_range[0], x_range[1] + 1, 0.05)
- 800 ax1.plot(x_samples,
- 801 fit_res.fit_function([o.value for o in fit_res.fit_parameters], x_samples),
- 802 ls='-', marker=',', lw=2)
- 803
- 804 ax1.set_xlabel(r'$x_0 / a$')
- 805 if ylabel:
- 806 ax1.set_ylabel(ylabel)
- 807 ax1.set_xlim([x_range[0] - 0.5, x_range[1] + 0.5])
- 808
- 809 handles, labels = ax1.get_legend_handles_labels()
- 810 if labels:
- 811 ax1.legend()
- 812 plt.draw()
- 813
- 814 if save:
- 815 if isinstance(save, str):
- 816 fig.savefig(save)
- 817 else:
- 818 raise Exception("'save' has to be a string.")
- 819
- 820 def spaghetti_plot(self, logscale=True):
- 821 """Produces a spaghetti plot of the correlator suited to monitor exceptional configurations.
- 822
- 823 Parameters
- 824 ----------
- 825 logscale : bool
- 826 Determines whether the scale of the y-axis is logarithmic or standard.
- 827 """
- 828 if self.N != 1:
- 829 raise Exception("Correlator needs to be projected first.")
- 830
- 831 mc_names = list(set([item for sublist in [o[0].mc_names for o in self.content if o is not None] for item in sublist]))
- 832 x0_vals = [n for (n, o) in zip(np.arange(self.T), self.content) if o is not None]
- 833
- 834 for name in mc_names:
- 835 data = np.array([o[0].deltas[name] + o[0].r_values[name] for o in self.content if o is not None]).T
- 836
- 837 fig = plt.figure()
- 838 ax = fig.add_subplot(111)
- 839 for dat in data:
- 840 ax.plot(x0_vals, dat, ls='-', marker='')
- 841
- 842 if logscale is True:
- 843 ax.set_yscale('log')
- 844
- 845 ax.set_xlabel(r'$x_0 / a$')
- 846 plt.title(name)
- 847 plt.draw()
+ 798 if self.prange:
+ 799 ax1.axvline(self.prange[0], 0, 1, ls='-', marker=',')
+ 800 ax1.axvline(self.prange[1], 0, 1, ls='-', marker=',')
+ 801
+ 802 if fit_res:
+ 803 x_samples = np.arange(x_range[0], x_range[1] + 1, 0.05)
+ 804 ax1.plot(x_samples,
+ 805 fit_res.fit_function([o.value for o in fit_res.fit_parameters], x_samples),
+ 806 ls='-', marker=',', lw=2)
+ 807
+ 808 ax1.set_xlabel(r'$x_0 / a$')
+ 809 if ylabel:
+ 810 ax1.set_ylabel(ylabel)
+ 811 ax1.set_xlim([x_range[0] - 0.5, x_range[1] + 0.5])
+ 812
+ 813 handles, labels = ax1.get_legend_handles_labels()
+ 814 if labels:
+ 815 ax1.legend()
+ 816 plt.draw()
+ 817
+ 818 if save:
+ 819 if isinstance(save, str):
+ 820 fig.savefig(save)
+ 821 else:
+ 822 raise Exception("'save' has to be a string.")
+ 823
+ 824 def spaghetti_plot(self, logscale=True):
+ 825 """Produces a spaghetti plot of the correlator suited to monitor exceptional configurations.
+ 826
+ 827 Parameters
+ 828 ----------
+ 829 logscale : bool
+ 830 Determines whether the scale of the y-axis is logarithmic or standard.
+ 831 """
+ 832 if self.N != 1:
+ 833 raise Exception("Correlator needs to be projected first.")
+ 834
+ 835 mc_names = list(set([item for sublist in [o[0].mc_names for o in self.content if o is not None] for item in sublist]))
+ 836 x0_vals = [n for (n, o) in zip(np.arange(self.T), self.content) if o is not None]
+ 837
+ 838 for name in mc_names:
+ 839 data = np.array([o[0].deltas[name] + o[0].r_values[name] for o in self.content if o is not None]).T
+ 840
+ 841 fig = plt.figure()
+ 842 ax = fig.add_subplot(111)
+ 843 for dat in data:
+ 844 ax.plot(x0_vals, dat, ls='-', marker='')
+ 845
+ 846 if logscale is True:
+ 847 ax.set_yscale('log')
848
- 849 def dump(self, filename, datatype="json.gz", **kwargs):
- 850 """Dumps the Corr into a file of chosen type
- 851 Parameters
- 852 ----------
- 853 filename : str
- 854 Name of the file to be saved.
- 855 datatype : str
- 856 Format of the exported file. Supported formats include
- 857 "json.gz" and "pickle"
- 858 path : str
- 859 specifies a custom path for the file (default '.')
- 860 """
- 861 if datatype == "json.gz":
- 862 from .input.json import dump_to_json
- 863 if 'path' in kwargs:
- 864 file_name = kwargs.get('path') + '/' + filename
- 865 else:
- 866 file_name = filename
- 867 dump_to_json(self, file_name)
- 868 elif datatype == "pickle":
- 869 dump_object(self, filename, **kwargs)
- 870 else:
- 871 raise Exception("Unknown datatype " + str(datatype))
- 872
- 873 def print(self, range=[0, None]):
- 874 print(self.__repr__(range))
- 875
- 876 def __repr__(self, range=[0, None]):
- 877 content_string = ""
- 878
- 879 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
- 880
- 881 if self.tag is not None:
- 882 content_string += "Description: " + self.tag + "\n"
- 883 if self.N != 1:
- 884 return content_string
- 885
- 886 if range[1]:
- 887 range[1] += 1
- 888 content_string += 'x0/a\tCorr(x0/a)\n------------------\n'
- 889 for i, sub_corr in enumerate(self.content[range[0]:range[1]]):
- 890 if sub_corr is None:
- 891 content_string += str(i + range[0]) + '\n'
- 892 else:
- 893 content_string += str(i + range[0])
- 894 for element in sub_corr:
- 895 content_string += '\t' + ' ' * int(element >= 0) + str(element)
- 896 content_string += '\n'
- 897 return content_string
- 898
- 899 def __str__(self):
- 900 return self.__repr__()
- 901
- 902 # We define the basic operations, that can be performed with correlators.
- 903 # While */+- get defined here, they only work for Corr*Obs and not Obs*Corr.
- 904 # This is because Obs*Corr checks Obs.__mul__ first and does not catch an exception.
- 905 # One could try and tell Obs to check if the y in __mul__ is a Corr and
- 906
- 907 def __add__(self, y):
- 908 if isinstance(y, Corr):
- 909 if ((self.N != y.N) or (self.T != y.T)):
- 910 raise Exception("Addition of Corrs with different shape")
- 911 newcontent = []
- 912 for t in range(self.T):
- 913 if (self.content[t] is None) or (y.content[t] is None):
- 914 newcontent.append(None)
- 915 else:
- 916 newcontent.append(self.content[t] + y.content[t])
- 917 return Corr(newcontent)
- 918
- 919 elif isinstance(y, (Obs, int, float, CObs)):
- 920 newcontent = []
- 921 for t in range(self.T):
- 922 if (self.content[t] is None):
- 923 newcontent.append(None)
- 924 else:
- 925 newcontent.append(self.content[t] + y)
- 926 return Corr(newcontent, prange=self.prange)
- 927 elif isinstance(y, np.ndarray):
- 928 if y.shape == (self.T,):
- 929 return Corr(list((np.array(self.content).T + y).T))
- 930 else:
- 931 raise ValueError("operands could not be broadcast together")
- 932 else:
- 933 raise TypeError("Corr + wrong type")
- 934
- 935 def __mul__(self, y):
- 936 if isinstance(y, Corr):
- 937 if not((self.N == 1 or y.N == 1 or self.N == y.N) and self.T == y.T):
- 938 raise Exception("Multiplication of Corr object requires N=N or N=1 and T=T")
- 939 newcontent = []
- 940 for t in range(self.T):
- 941 if (self.content[t] is None) or (y.content[t] is None):
- 942 newcontent.append(None)
- 943 else:
- 944 newcontent.append(self.content[t] * y.content[t])
- 945 return Corr(newcontent)
- 946
- 947 elif isinstance(y, (Obs, int, float, CObs)):
- 948 newcontent = []
- 949 for t in range(self.T):
- 950 if (self.content[t] is None):
- 951 newcontent.append(None)
- 952 else:
- 953 newcontent.append(self.content[t] * y)
- 954 return Corr(newcontent, prange=self.prange)
- 955 elif isinstance(y, np.ndarray):
- 956 if y.shape == (self.T,):
- 957 return Corr(list((np.array(self.content).T * y).T))
- 958 else:
- 959 raise ValueError("operands could not be broadcast together")
- 960 else:
- 961 raise TypeError("Corr * wrong type")
- 962
- 963 def __truediv__(self, y):
- 964 if isinstance(y, Corr):
- 965 if not((self.N == 1 or y.N == 1 or self.N == y.N) and self.T == y.T):
- 966 raise Exception("Multiplication of Corr object requires N=N or N=1 and T=T")
- 967 newcontent = []
- 968 for t in range(self.T):
- 969 if (self.content[t] is None) or (y.content[t] is None):
- 970 newcontent.append(None)
- 971 else:
- 972 newcontent.append(self.content[t] / y.content[t])
- 973 for t in range(self.T):
- 974 if newcontent[t] is None:
- 975 continue
- 976 if np.isnan(np.sum(newcontent[t]).value):
- 977 newcontent[t] = None
- 978
- 979 if all([item is None for item in newcontent]):
- 980 raise Exception("Division returns completely undefined correlator")
- 981 return Corr(newcontent)
+ 849 ax.set_xlabel(r'$x_0 / a$')
+ 850 plt.title(name)
+ 851 plt.draw()
+ 852
+ 853 def dump(self, filename, datatype="json.gz", **kwargs):
+ 854 """Dumps the Corr into a file of chosen type
+ 855 Parameters
+ 856 ----------
+ 857 filename : str
+ 858 Name of the file to be saved.
+ 859 datatype : str
+ 860 Format of the exported file. Supported formats include
+ 861 "json.gz" and "pickle"
+ 862 path : str
+ 863 specifies a custom path for the file (default '.')
+ 864 """
+ 865 if datatype == "json.gz":
+ 866 from .input.json import dump_to_json
+ 867 if 'path' in kwargs:
+ 868 file_name = kwargs.get('path') + '/' + filename
+ 869 else:
+ 870 file_name = filename
+ 871 dump_to_json(self, file_name)
+ 872 elif datatype == "pickle":
+ 873 dump_object(self, filename, **kwargs)
+ 874 else:
+ 875 raise Exception("Unknown datatype " + str(datatype))
+ 876
+ 877 def print(self, range=[0, None]):
+ 878 print(self.__repr__(range))
+ 879
+ 880 def __repr__(self, range=[0, None]):
+ 881 content_string = ""
+ 882
+ 883 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
+ 884
+ 885 if self.tag is not None:
+ 886 content_string += "Description: " + self.tag + "\n"
+ 887 if self.N != 1:
+ 888 return content_string
+ 889
+ 890 if range[1]:
+ 891 range[1] += 1
+ 892 content_string += 'x0/a\tCorr(x0/a)\n------------------\n'
+ 893 for i, sub_corr in enumerate(self.content[range[0]:range[1]]):
+ 894 if sub_corr is None:
+ 895 content_string += str(i + range[0]) + '\n'
+ 896 else:
+ 897 content_string += str(i + range[0])
+ 898 for element in sub_corr:
+ 899 content_string += '\t' + ' ' * int(element >= 0) + str(element)
+ 900 content_string += '\n'
+ 901 return content_string
+ 902
+ 903 def __str__(self):
+ 904 return self.__repr__()
+ 905
+ 906 # We define the basic operations, that can be performed with correlators.
+ 907 # While */+- get defined here, they only work for Corr*Obs and not Obs*Corr.
+ 908 # This is because Obs*Corr checks Obs.__mul__ first and does not catch an exception.
+ 909 # One could try and tell Obs to check if the y in __mul__ is a Corr and
+ 910
+ 911 def __add__(self, y):
+ 912 if isinstance(y, Corr):
+ 913 if ((self.N != y.N) or (self.T != y.T)):
+ 914 raise Exception("Addition of Corrs with different shape")
+ 915 newcontent = []
+ 916 for t in range(self.T):
+ 917 if (self.content[t] is None) or (y.content[t] is None):
+ 918 newcontent.append(None)
+ 919 else:
+ 920 newcontent.append(self.content[t] + y.content[t])
+ 921 return Corr(newcontent)
+ 922
+ 923 elif isinstance(y, (Obs, int, float, CObs)):
+ 924 newcontent = []
+ 925 for t in range(self.T):
+ 926 if (self.content[t] is None):
+ 927 newcontent.append(None)
+ 928 else:
+ 929 newcontent.append(self.content[t] + y)
+ 930 return Corr(newcontent, prange=self.prange)
+ 931 elif isinstance(y, np.ndarray):
+ 932 if y.shape == (self.T,):
+ 933 return Corr(list((np.array(self.content).T + y).T))
+ 934 else:
+ 935 raise ValueError("operands could not be broadcast together")
+ 936 else:
+ 937 raise TypeError("Corr + wrong type")
+ 938
+ 939 def __mul__(self, y):
+ 940 if isinstance(y, Corr):
+ 941 if not((self.N == 1 or y.N == 1 or self.N == y.N) and self.T == y.T):
+ 942 raise Exception("Multiplication of Corr object requires N=N or N=1 and T=T")
+ 943 newcontent = []
+ 944 for t in range(self.T):
+ 945 if (self.content[t] is None) or (y.content[t] is None):
+ 946 newcontent.append(None)
+ 947 else:
+ 948 newcontent.append(self.content[t] * y.content[t])
+ 949 return Corr(newcontent)
+ 950
+ 951 elif isinstance(y, (Obs, int, float, CObs)):
+ 952 newcontent = []
+ 953 for t in range(self.T):
+ 954 if (self.content[t] is None):
+ 955 newcontent.append(None)
+ 956 else:
+ 957 newcontent.append(self.content[t] * y)
+ 958 return Corr(newcontent, prange=self.prange)
+ 959 elif isinstance(y, np.ndarray):
+ 960 if y.shape == (self.T,):
+ 961 return Corr(list((np.array(self.content).T * y).T))
+ 962 else:
+ 963 raise ValueError("operands could not be broadcast together")
+ 964 else:
+ 965 raise TypeError("Corr * wrong type")
+ 966
+ 967 def __truediv__(self, y):
+ 968 if isinstance(y, Corr):
+ 969 if not((self.N == 1 or y.N == 1 or self.N == y.N) and self.T == y.T):
+ 970 raise Exception("Multiplication of Corr object requires N=N or N=1 and T=T")
+ 971 newcontent = []
+ 972 for t in range(self.T):
+ 973 if (self.content[t] is None) or (y.content[t] is None):
+ 974 newcontent.append(None)
+ 975 else:
+ 976 newcontent.append(self.content[t] / y.content[t])
+ 977 for t in range(self.T):
+ 978 if newcontent[t] is None:
+ 979 continue
+ 980 if np.isnan(np.sum(newcontent[t]).value):
+ 981 newcontent[t] = None
982
- 983 elif isinstance(y, (Obs, CObs)):
- 984 if isinstance(y, Obs):
- 985 if y.value == 0:
- 986 raise Exception('Division by zero will return undefined correlator')
- 987 if isinstance(y, CObs):
- 988 if y.is_zero():
- 989 raise Exception('Division by zero will return undefined correlator')
- 990
- 991 newcontent = []
- 992 for t in range(self.T):
- 993 if (self.content[t] is None):
- 994 newcontent.append(None)
- 995 else:
- 996 newcontent.append(self.content[t] / y)
- 997 return Corr(newcontent, prange=self.prange)
- 998
- 999 elif isinstance(y, (int, float)):
-1000 if y == 0:
-1001 raise Exception('Division by zero will return undefined correlator')
-1002 newcontent = []
-1003 for t in range(self.T):
-1004 if (self.content[t] is None):
-1005 newcontent.append(None)
-1006 else:
-1007 newcontent.append(self.content[t] / y)
-1008 return Corr(newcontent, prange=self.prange)
-1009 elif isinstance(y, np.ndarray):
-1010 if y.shape == (self.T,):
-1011 return Corr(list((np.array(self.content).T / y).T))
-1012 else:
-1013 raise ValueError("operands could not be broadcast together")
-1014 else:
-1015 raise TypeError('Corr / wrong type')
-1016
-1017 def __neg__(self):
-1018 newcontent = [None if (item is None) else -1. * item for item in self.content]
-1019 return Corr(newcontent, prange=self.prange)
+ 983 if all([item is None for item in newcontent]):
+ 984 raise Exception("Division returns completely undefined correlator")
+ 985 return Corr(newcontent)
+ 986
+ 987 elif isinstance(y, (Obs, CObs)):
+ 988 if isinstance(y, Obs):
+ 989 if y.value == 0:
+ 990 raise Exception('Division by zero will return undefined correlator')
+ 991 if isinstance(y, CObs):
+ 992 if y.is_zero():
+ 993 raise Exception('Division by zero will return undefined correlator')
+ 994
+ 995 newcontent = []
+ 996 for t in range(self.T):
+ 997 if (self.content[t] is None):
+ 998 newcontent.append(None)
+ 999 else:
+1000 newcontent.append(self.content[t] / y)
+1001 return Corr(newcontent, prange=self.prange)
+1002
+1003 elif isinstance(y, (int, float)):
+1004 if y == 0:
+1005 raise Exception('Division by zero will return undefined correlator')
+1006 newcontent = []
+1007 for t in range(self.T):
+1008 if (self.content[t] is None):
+1009 newcontent.append(None)
+1010 else:
+1011 newcontent.append(self.content[t] / y)
+1012 return Corr(newcontent, prange=self.prange)
+1013 elif isinstance(y, np.ndarray):
+1014 if y.shape == (self.T,):
+1015 return Corr(list((np.array(self.content).T / y).T))
+1016 else:
+1017 raise ValueError("operands could not be broadcast together")
+1018 else:
+1019 raise TypeError('Corr / wrong type')
1020
-1021 def __sub__(self, y):
-1022 return self + (-y)
-1023
-1024 def __pow__(self, y):
-1025 if isinstance(y, (Obs, int, float, CObs)):
-1026 newcontent = [None if (item is None) else item**y for item in self.content]
-1027 return Corr(newcontent, prange=self.prange)
-1028 else:
-1029 raise TypeError('Type of exponent not supported')
-1030
-1031 def __abs__(self):
-1032 newcontent = [None if (item is None) else np.abs(item) for item in self.content]
-1033 return Corr(newcontent, prange=self.prange)
+1021 def __neg__(self):
+1022 newcontent = [None if (item is None) else -1. * item for item in self.content]
+1023 return Corr(newcontent, prange=self.prange)
+1024
+1025 def __sub__(self, y):
+1026 return self + (-y)
+1027
+1028 def __pow__(self, y):
+1029 if isinstance(y, (Obs, int, float, CObs)):
+1030 newcontent = [None if (item is None) else item**y for item in self.content]
+1031 return Corr(newcontent, prange=self.prange)
+1032 else:
+1033 raise TypeError('Type of exponent not supported')
1034
-1035 # The numpy functions:
-1036 def sqrt(self):
-1037 return self**0.5
+1035 def __abs__(self):
+1036 newcontent = [None if (item is None) else np.abs(item) for item in self.content]
+1037 return Corr(newcontent, prange=self.prange)
1038
-1039 def log(self):
-1040 newcontent = [None if (item is None) else np.log(item) for item in self.content]
-1041 return Corr(newcontent, prange=self.prange)
+1039 # The numpy functions:
+1040 def sqrt(self):
+1041 return self**0.5
1042
-1043 def exp(self):
-1044 newcontent = [None if (item is None) else np.exp(item) for item in self.content]
+1043 def log(self):
+1044 newcontent = [None if (item is None) else np.log(item) for item in self.content]
1045 return Corr(newcontent, prange=self.prange)
1046
-1047 def _apply_func_to_corr(self, func):
-1048 newcontent = [None if (item is None) else func(item) for item in self.content]
-1049 for t in range(self.T):
-1050 if newcontent[t] is None:
-1051 continue
-1052 if np.isnan(np.sum(newcontent[t]).value):
-1053 newcontent[t] = None
-1054 if all([item is None for item in newcontent]):
-1055 raise Exception('Operation returns undefined correlator')
-1056 return Corr(newcontent)
-1057
-1058 def sin(self):
-1059 return self._apply_func_to_corr(np.sin)
-1060
-1061 def cos(self):
-1062 return self._apply_func_to_corr(np.cos)
-1063
-1064 def tan(self):
-1065 return self._apply_func_to_corr(np.tan)
-1066
-1067 def sinh(self):
-1068 return self._apply_func_to_corr(np.sinh)
-1069
-1070 def cosh(self):
-1071 return self._apply_func_to_corr(np.cosh)
-1072
-1073 def tanh(self):
-1074 return self._apply_func_to_corr(np.tanh)
-1075
-1076 def arcsin(self):
-1077 return self._apply_func_to_corr(np.arcsin)
-1078
-1079 def arccos(self):
-1080 return self._apply_func_to_corr(np.arccos)
-1081
-1082 def arctan(self):
-1083 return self._apply_func_to_corr(np.arctan)
-1084
-1085 def arcsinh(self):
-1086 return self._apply_func_to_corr(np.arcsinh)
-1087
-1088 def arccosh(self):
-1089 return self._apply_func_to_corr(np.arccosh)
-1090
-1091 def arctanh(self):
-1092 return self._apply_func_to_corr(np.arctanh)
-1093
-1094 # Right hand side operations (require tweak in main module to work)
-1095 def __radd__(self, y):
-1096 return self + y
+1047 def exp(self):
+1048 newcontent = [None if (item is None) else np.exp(item) for item in self.content]
+1049 return Corr(newcontent, prange=self.prange)
+1050
+1051 def _apply_func_to_corr(self, func):
+1052 newcontent = [None if (item is None) else func(item) for item in self.content]
+1053 for t in range(self.T):
+1054 if newcontent[t] is None:
+1055 continue
+1056 if np.isnan(np.sum(newcontent[t]).value):
+1057 newcontent[t] = None
+1058 if all([item is None for item in newcontent]):
+1059 raise Exception('Operation returns undefined correlator')
+1060 return Corr(newcontent)
+1061
+1062 def sin(self):
+1063 return self._apply_func_to_corr(np.sin)
+1064
+1065 def cos(self):
+1066 return self._apply_func_to_corr(np.cos)
+1067
+1068 def tan(self):
+1069 return self._apply_func_to_corr(np.tan)
+1070
+1071 def sinh(self):
+1072 return self._apply_func_to_corr(np.sinh)
+1073
+1074 def cosh(self):
+1075 return self._apply_func_to_corr(np.cosh)
+1076
+1077 def tanh(self):
+1078 return self._apply_func_to_corr(np.tanh)
+1079
+1080 def arcsin(self):
+1081 return self._apply_func_to_corr(np.arcsin)
+1082
+1083 def arccos(self):
+1084 return self._apply_func_to_corr(np.arccos)
+1085
+1086 def arctan(self):
+1087 return self._apply_func_to_corr(np.arctan)
+1088
+1089 def arcsinh(self):
+1090 return self._apply_func_to_corr(np.arcsinh)
+1091
+1092 def arccosh(self):
+1093 return self._apply_func_to_corr(np.arccosh)
+1094
+1095 def arctanh(self):
+1096 return self._apply_func_to_corr(np.arctanh)
1097
-1098 def __rsub__(self, y):
-1099 return -self + y
-1100
-1101 def __rmul__(self, y):
-1102 return self * y
-1103
-1104 def __rtruediv__(self, y):
-1105 return (self / y) ** (-1)
-1106
-1107 @property
-1108 def real(self):
-1109 def return_real(obs_OR_cobs):
-1110 if isinstance(obs_OR_cobs, CObs):
-1111 return obs_OR_cobs.real
-1112 else:
-1113 return obs_OR_cobs
-1114
-1115 return self._apply_func_to_corr(return_real)
-1116
-1117 @property
-1118 def imag(self):
-1119 def return_imag(obs_OR_cobs):
-1120 if isinstance(obs_OR_cobs, CObs):
-1121 return obs_OR_cobs.imag
-1122 else:
-1123 return obs_OR_cobs * 0 # So it stays the right type
-1124
-1125 return self._apply_func_to_corr(return_imag)
-1126
-1127 def prune(self, Ntrunc, tproj=3, t0proj=2, basematrix=None):
-1128 r''' Project large correlation matrix to lowest states
-1129
-1130 This method can be used to reduce the size of an (N x N) correlation matrix
-1131 to (Ntrunc x Ntrunc) by solving a GEVP at very early times where the noise
-1132 is still small.
+1098 # Right hand side operations (require tweak in main module to work)
+1099 def __radd__(self, y):
+1100 return self + y
+1101
+1102 def __rsub__(self, y):
+1103 return -self + y
+1104
+1105 def __rmul__(self, y):
+1106 return self * y
+1107
+1108 def __rtruediv__(self, y):
+1109 return (self / y) ** (-1)
+1110
+1111 @property
+1112 def real(self):
+1113 def return_real(obs_OR_cobs):
+1114 if isinstance(obs_OR_cobs, CObs):
+1115 return obs_OR_cobs.real
+1116 else:
+1117 return obs_OR_cobs
+1118
+1119 return self._apply_func_to_corr(return_real)
+1120
+1121 @property
+1122 def imag(self):
+1123 def return_imag(obs_OR_cobs):
+1124 if isinstance(obs_OR_cobs, CObs):
+1125 return obs_OR_cobs.imag
+1126 else:
+1127 return obs_OR_cobs * 0 # So it stays the right type
+1128
+1129 return self._apply_func_to_corr(return_imag)
+1130
+1131 def prune(self, Ntrunc, tproj=3, t0proj=2, basematrix=None):
+1132 r''' Project large correlation matrix to lowest states
1133
-1134 Parameters
-1135 ----------
-1136 Ntrunc: int
-1137 Rank of the target matrix.
-1138 tproj: int
-1139 Time where the eigenvectors are evaluated, corresponds to ts in the GEVP method.
-1140 The default value is 3.
-1141 t0proj: int
-1142 Time where the correlation matrix is inverted. Choosing t0proj=1 is strongly
-1143 discouraged for O(a) improved theories, since the correctness of the procedure
-1144 cannot be granted in this case. The default value is 2.
-1145 basematrix : Corr
-1146 Correlation matrix that is used to determine the eigenvectors of the
-1147 lowest states based on a GEVP. basematrix is taken to be the Corr itself if
-1148 is is not specified.
-1149
-1150 Notes
-1151 -----
-1152 We have the basematrix $C(t)$ and the target matrix $G(t)$. We start by solving
-1153 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}$
-1154 and $t_0 \equiv t_{0, \mathrm{proj}}$. The target matrix is projected onto the subspace of the
-1155 resulting eigenvectors $v_n, n=1,\dots,N_\mathrm{trunc}$ via
-1156 $$G^\prime_{i, j}(t) = (v_i, G(t) v_j)$$. This allows to reduce the size of a large
-1157 correlation matrix and to remove some noise that is added by irrelevant operators.
-1158 This may allow to use the GEVP on $G(t)$ at late times such that the theoretically motivated
-1159 bound $t_0 \leq t/2$ holds, since the condition number of $G(t)$ is decreased, compared to $C(t)$.
-1160 '''
-1161
-1162 if self.N == 1:
-1163 raise Exception('Method cannot be applied to one-dimensional correlators.')
-1164 if basematrix is None:
-1165 basematrix = self
-1166 if Ntrunc >= basematrix.N:
-1167 raise Exception('Cannot truncate using Ntrunc <= %d' % (basematrix.N))
-1168 if basematrix.N != self.N:
-1169 raise Exception('basematrix and targetmatrix have to be of the same size.')
-1170
-1171 evecs = []
-1172 for i in range(Ntrunc):
-1173 evecs.append(basematrix.GEVP(t0proj, tproj, state=i, sorted_list=None))
+1134 This method can be used to reduce the size of an (N x N) correlation matrix
+1135 to (Ntrunc x Ntrunc) by solving a GEVP at very early times where the noise
+1136 is still small.
+1137
+1138 Parameters
+1139 ----------
+1140 Ntrunc: int
+1141 Rank of the target matrix.
+1142 tproj: int
+1143 Time where the eigenvectors are evaluated, corresponds to ts in the GEVP method.
+1144 The default value is 3.
+1145 t0proj: int
+1146 Time where the correlation matrix is inverted. Choosing t0proj=1 is strongly
+1147 discouraged for O(a) improved theories, since the correctness of the procedure
+1148 cannot be granted in this case. The default value is 2.
+1149 basematrix : Corr
+1150 Correlation matrix that is used to determine the eigenvectors of the
+1151 lowest states based on a GEVP. basematrix is taken to be the Corr itself if
+1152 is is not specified.
+1153
+1154 Notes
+1155 -----
+1156 We have the basematrix $C(t)$ and the target matrix $G(t)$. We start by solving
+1157 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}$
+1158 and $t_0 \equiv t_{0, \mathrm{proj}}$. The target matrix is projected onto the subspace of the
+1159 resulting eigenvectors $v_n, n=1,\dots,N_\mathrm{trunc}$ via
+1160 $$G^\prime_{i, j}(t) = (v_i, G(t) v_j)$$. This allows to reduce the size of a large
+1161 correlation matrix and to remove some noise that is added by irrelevant operators.
+1162 This may allow to use the GEVP on $G(t)$ at late times such that the theoretically motivated
+1163 bound $t_0 \leq t/2$ holds, since the condition number of $G(t)$ is decreased, compared to $C(t)$.
+1164 '''
+1165
+1166 if self.N == 1:
+1167 raise Exception('Method cannot be applied to one-dimensional correlators.')
+1168 if basematrix is None:
+1169 basematrix = self
+1170 if Ntrunc >= basematrix.N:
+1171 raise Exception('Cannot truncate using Ntrunc <= %d' % (basematrix.N))
+1172 if basematrix.N != self.N:
+1173 raise Exception('basematrix and targetmatrix have to be of the same size.')
1174
-1175 tmpmat = np.empty((Ntrunc, Ntrunc), dtype=object)
-1176 rmat = []
-1177 for t in range(basematrix.T):
-1178 for i in range(Ntrunc):
-1179 for j in range(Ntrunc):
-1180 tmpmat[i][j] = evecs[i].T @ self[t] @ evecs[j]
-1181 rmat.append(np.copy(tmpmat))
-1182
-1183 newcontent = [None if (self.content[t] is None) else rmat[t] for t in range(self.T)]
-1184 return Corr(newcontent)
+1175 evecs = []
+1176 for i in range(Ntrunc):
+1177 evecs.append(basematrix.GEVP(t0proj, tproj, state=i, sorted_list=None))
+1178
+1179 tmpmat = np.empty((Ntrunc, Ntrunc), dtype=object)
+1180 rmat = []
+1181 for t in range(basematrix.T):
+1182 for i in range(Ntrunc):
+1183 for j in range(Ntrunc):
+1184 tmpmat[i][j] = evecs[i].T @ self[t] @ evecs[j]
+1185 rmat.append(np.copy(tmpmat))
+1186
+1187 newcontent = [None if (self.content[t] is None) else rmat[t] for t in range(self.T)]
+1188 return Corr(newcontent)
@@ -3042,48 +3050,52 @@ timeslice and the error on each timeslice.
259 "Eigenvector" - Use the method described in arXiv:2004.10472 [hep-lat] to find the set of v(t) belonging to the state.
260 The reference state is identified by its eigenvalue at t=ts
261 """
-262 symmetric_corr = self.matrix_symmetric()
-263 if sorted_list is None:
-264 if (ts is None):
-265 raise Exception("ts is required if sorted_list=None")
-266 if (self.content[t0] is None) or (self.content[ts] is None):
-267 raise Exception("Corr not defined at t0/ts")
-268 G0, Gt = np.empty([self.N, self.N], dtype="double"), np.empty([self.N, self.N], dtype="double")
-269 for i in range(self.N):
-270 for j in range(self.N):
-271 G0[i, j] = symmetric_corr[t0][i, j].value
-272 Gt[i, j] = symmetric_corr[ts][i, j].value
-273
-274 sp_vecs = _GEVP_solver(Gt, G0)
-275 sp_vec = sp_vecs[state]
-276 return sp_vec
-277 elif sorted_list in ["Eigenvalue", "Eigenvector"]:
-278 all_vecs = []
-279 for t in range(self.T):
-280 try:
-281 G0, Gt = np.empty([self.N, self.N], dtype="double"), np.empty([self.N, self.N], dtype="double")
-282 for i in range(self.N):
-283 for j in range(self.N):
-284 G0[i, j] = symmetric_corr[t0][i, j].value
-285 Gt[i, j] = symmetric_corr[t][i, j].value
-286
-287 sp_vecs = _GEVP_solver(Gt, G0)
-288 if sorted_list == "Eigenvalue":
-289 sp_vec = sp_vecs[state]
-290 all_vecs.append(sp_vec)
-291 else:
-292 all_vecs.append(sp_vecs)
-293 except Exception:
-294 all_vecs.append(None)
-295 if sorted_list == "Eigenvector":
-296 if (ts is None):
-297 raise Exception("ts is required for the Eigenvector sorting method.")
-298 all_vecs = _sort_vectors(all_vecs, ts)
-299 all_vecs = [a[state] for a in all_vecs]
-300 else:
-301 raise Exception("Unkown value for 'sorted_list'.")
-302
-303 return all_vecs
+262
+263 if self.N == 1:
+264 raise Exception("GEVP methods only works on correlator matrices and not single correlators.")
+265
+266 symmetric_corr = self.matrix_symmetric()
+267 if sorted_list is None:
+268 if (ts is None):
+269 raise Exception("ts is required if sorted_list=None")
+270 if (self.content[t0] is None) or (self.content[ts] is None):
+271 raise Exception("Corr not defined at t0/ts")
+272 G0, Gt = np.empty([self.N, self.N], dtype="double"), np.empty([self.N, self.N], dtype="double")
+273 for i in range(self.N):
+274 for j in range(self.N):
+275 G0[i, j] = symmetric_corr[t0][i, j].value
+276 Gt[i, j] = symmetric_corr[ts][i, j].value
+277
+278 sp_vecs = _GEVP_solver(Gt, G0)
+279 sp_vec = sp_vecs[state]
+280 return sp_vec
+281 elif sorted_list in ["Eigenvalue", "Eigenvector"]:
+282 all_vecs = []
+283 for t in range(self.T):
+284 try:
+285 G0, Gt = np.empty([self.N, self.N], dtype="double"), np.empty([self.N, self.N], dtype="double")
+286 for i in range(self.N):
+287 for j in range(self.N):
+288 G0[i, j] = symmetric_corr[t0][i, j].value
+289 Gt[i, j] = symmetric_corr[t][i, j].value
+290
+291 sp_vecs = _GEVP_solver(Gt, G0)
+292 if sorted_list == "Eigenvalue":
+293 sp_vec = sp_vecs[state]
+294 all_vecs.append(sp_vec)
+295 else:
+296 all_vecs.append(sp_vecs)
+297 except Exception:
+298 all_vecs.append(None)
+299 if sorted_list == "Eigenvector":
+300 if (ts is None):
+301 raise Exception("ts is required for the Eigenvector sorting method.")
+302 all_vecs = _sort_vectors(all_vecs, ts)
+303 all_vecs = [a[state] for a in all_vecs]
+304 else:
+305 raise Exception("Unkown value for 'sorted_list'.")
+306
+307 return all_vecs
@@ -3120,26 +3132,26 @@ if this argument is set, a list of vectors (len=self.T) is returned. If it is le
View Source
- 305 def Eigenvalue(self, t0, ts=None, state=0, sorted_list=None):
-306 """Determines the eigenvalue of the GEVP by solving and projecting the correlator
-307
-308 Parameters
-309 ----------
-310 t0 : int
-311 The time t0 for G(t)v= lambda G(t_0)v
-312 ts : int
-313 fixed time G(t_s)v= lambda G(t_0)v if return_list=False
-314 If return_list=True and sorting=Eigenvector it gives a reference point for the sorting method.
-315 state : int
-316 The state one is interested in ordered by energy. The lowest state is zero.
-317 sorted_list : string
-318 if this argument is set, a list of vectors (len=self.T) is returned. If it is left as None, only one vector is returned.
-319 "Eigenvalue" - The eigenvector is chosen according to which eigenvalue it belongs individually on every timeslice.
-320 "Eigenvector" - Use the method described in arXiv:2004.10472 [hep-lat] to find the set of v(t) belonging to the state.
-321 The reference state is identified by its eigenvalue at t=ts
-322 """
-323 vec = self.GEVP(t0, ts=ts, state=state, sorted_list=sorted_list)
-324 return self.projected(vec)
+ 309 def Eigenvalue(self, t0, ts=None, state=0, sorted_list=None):
+310 """Determines the eigenvalue of the GEVP by solving and projecting the correlator
+311
+312 Parameters
+313 ----------
+314 t0 : int
+315 The time t0 for G(t)v= lambda G(t_0)v
+316 ts : int
+317 fixed time G(t_s)v= lambda G(t_0)v if return_list=False
+318 If return_list=True and sorting=Eigenvector it gives a reference point for the sorting method.
+319 state : int
+320 The state one is interested in ordered by energy. The lowest state is zero.
+321 sorted_list : string
+322 if this argument is set, a list of vectors (len=self.T) is returned. If it is left as None, only one vector is returned.
+323 "Eigenvalue" - The eigenvector is chosen according to which eigenvalue it belongs individually on every timeslice.
+324 "Eigenvector" - Use the method described in arXiv:2004.10472 [hep-lat] to find the set of v(t) belonging to the state.
+325 The reference state is identified by its eigenvalue at t=ts
+326 """
+327 vec = self.GEVP(t0, ts=ts, state=state, sorted_list=sorted_list)
+328 return self.projected(vec)
@@ -3176,46 +3188,46 @@ if this argument is set, a list of vectors (len=self.T) is returned. If it is le
View Source
- 326 def Hankel(self, N, periodic=False):
-327 """Constructs an NxN Hankel matrix
-328
-329 C(t) c(t+1) ... c(t+n-1)
-330 C(t+1) c(t+2) ... c(t+n)
-331 .................
-332 C(t+(n-1)) c(t+n) ... c(t+2(n-1))
-333
-334 Parameters
-335 ----------
-336 N : int
-337 Dimension of the Hankel matrix
-338 periodic : bool, optional
-339 determines whether the matrix is extended periodically
-340 """
-341
-342 if self.N != 1:
-343 raise Exception("Multi-operator Prony not implemented!")
-344
-345 array = np.empty([N, N], dtype="object")
-346 new_content = []
-347 for t in range(self.T):
-348 new_content.append(array.copy())
-349
-350 def wrap(i):
-351 while i >= self.T:
-352 i -= self.T
-353 return i
-354
-355 for t in range(self.T):
-356 for i in range(N):
-357 for j in range(N):
-358 if periodic:
-359 new_content[t][i, j] = self.content[wrap(t + i + j)][0]
-360 elif (t + i + j) >= self.T:
-361 new_content[t] = None
-362 else:
-363 new_content[t][i, j] = self.content[t + i + j][0]
-364
-365 return Corr(new_content)
+ 330 def Hankel(self, N, periodic=False):
+331 """Constructs an NxN Hankel matrix
+332
+333 C(t) c(t+1) ... c(t+n-1)
+334 C(t+1) c(t+2) ... c(t+n)
+335 .................
+336 C(t+(n-1)) c(t+n) ... c(t+2(n-1))
+337
+338 Parameters
+339 ----------
+340 N : int
+341 Dimension of the Hankel matrix
+342 periodic : bool, optional
+343 determines whether the matrix is extended periodically
+344 """
+345
+346 if self.N != 1:
+347 raise Exception("Multi-operator Prony not implemented!")
+348
+349 array = np.empty([N, N], dtype="object")
+350 new_content = []
+351 for t in range(self.T):
+352 new_content.append(array.copy())
+353
+354 def wrap(i):
+355 while i >= self.T:
+356 i -= self.T
+357 return i
+358
+359 for t in range(self.T):
+360 for i in range(N):
+361 for j in range(N):
+362 if periodic:
+363 new_content[t][i, j] = self.content[wrap(t + i + j)][0]
+364 elif (t + i + j) >= self.T:
+365 new_content[t] = None
+366 else:
+367 new_content[t][i, j] = self.content[t + i + j][0]
+368
+369 return Corr(new_content)
@@ -3249,15 +3261,15 @@ determines whether the matrix is extended periodically
View Source
- 367 def roll(self, dt):
-368 """Periodically shift the correlator by dt timeslices
-369
-370 Parameters
-371 ----------
-372 dt : int
-373 number of timeslices
-374 """
-375 return Corr(list(np.roll(np.array(self.content, dtype=object), dt)))
+ 371 def roll(self, dt):
+372 """Periodically shift the correlator by dt timeslices
+373
+374 Parameters
+375 ----------
+376 dt : int
+377 number of timeslices
+378 """
+379 return Corr(list(np.roll(np.array(self.content, dtype=object), dt)))
@@ -3284,9 +3296,9 @@ number of timeslices
View Source
- 377 def reverse(self):
-378 """Reverse the time ordering of the Corr"""
-379 return Corr(self.content[:: -1])
+ 381 def reverse(self):
+382 """Reverse the time ordering of the Corr"""
+383 return Corr(self.content[:: -1])
@@ -3306,23 +3318,23 @@ number of timeslices
View Source
- 381 def thin(self, spacing=2, offset=0):
-382 """Thin out a correlator to suppress correlations
-383
-384 Parameters
-385 ----------
-386 spacing : int
-387 Keep only every 'spacing'th entry of the correlator
-388 offset : int
-389 Offset the equal spacing
-390 """
-391 new_content = []
-392 for t in range(self.T):
-393 if (offset + t) % spacing != 0:
-394 new_content.append(None)
-395 else:
-396 new_content.append(self.content[t])
-397 return Corr(new_content)
+ 385 def thin(self, spacing=2, offset=0):
+386 """Thin out a correlator to suppress correlations
+387
+388 Parameters
+389 ----------
+390 spacing : int
+391 Keep only every 'spacing'th entry of the correlator
+392 offset : int
+393 Offset the equal spacing
+394 """
+395 new_content = []
+396 for t in range(self.T):
+397 if (offset + t) % spacing != 0:
+398 new_content.append(None)
+399 else:
+400 new_content.append(self.content[t])
+401 return Corr(new_content)
@@ -3351,32 +3363,32 @@ Offset the equal spacing
View Source
- 399 def correlate(self, partner):
-400 """Correlate the correlator with another correlator or Obs
-401
-402 Parameters
-403 ----------
-404 partner : Obs or Corr
-405 partner to correlate the correlator with.
-406 Can either be an Obs which is correlated with all entries of the
-407 correlator or a Corr of same length.
-408 """
-409 new_content = []
-410 for x0, t_slice in enumerate(self.content):
-411 if t_slice is None:
-412 new_content.append(None)
-413 else:
-414 if isinstance(partner, Corr):
-415 if partner.content[x0] is None:
-416 new_content.append(None)
-417 else:
-418 new_content.append(np.array([correlate(o, partner.content[x0][0]) for o in t_slice]))
-419 elif isinstance(partner, Obs): # Should this include CObs?
-420 new_content.append(np.array([correlate(o, partner) for o in t_slice]))
-421 else:
-422 raise Exception("Can only correlate with an Obs or a Corr.")
-423
-424 return Corr(new_content)
+ 403 def correlate(self, partner):
+404 """Correlate the correlator with another correlator or Obs
+405
+406 Parameters
+407 ----------
+408 partner : Obs or Corr
+409 partner to correlate the correlator with.
+410 Can either be an Obs which is correlated with all entries of the
+411 correlator or a Corr of same length.
+412 """
+413 new_content = []
+414 for x0, t_slice in enumerate(self.content):
+415 if t_slice is None:
+416 new_content.append(None)
+417 else:
+418 if isinstance(partner, Corr):
+419 if partner.content[x0] is None:
+420 new_content.append(None)
+421 else:
+422 new_content.append(np.array([correlate(o, partner.content[x0][0]) for o in t_slice]))
+423 elif isinstance(partner, Obs): # Should this include CObs?
+424 new_content.append(np.array([correlate(o, partner) for o in t_slice]))
+425 else:
+426 raise Exception("Can only correlate with an Obs or a Corr.")
+427
+428 return Corr(new_content)
@@ -3405,26 +3417,26 @@ correlator or a Corr of same length.
View Source
- 426 def reweight(self, weight, **kwargs):
-427 """Reweight the correlator.
-428
-429 Parameters
-430 ----------
-431 weight : Obs
-432 Reweighting factor. An Observable that has to be defined on a superset of the
-433 configurations in obs[i].idl for all i.
-434 all_configs : bool
-435 if True, the reweighted observables are normalized by the average of
-436 the reweighting factor on all configurations in weight.idl and not
-437 on the configurations in obs[i].idl.
-438 """
-439 new_content = []
-440 for t_slice in self.content:
-441 if t_slice is None:
-442 new_content.append(None)
-443 else:
-444 new_content.append(np.array(reweight(weight, t_slice, **kwargs)))
-445 return Corr(new_content)
+ 430 def reweight(self, weight, **kwargs):
+431 """Reweight the correlator.
+432
+433 Parameters
+434 ----------
+435 weight : Obs
+436 Reweighting factor. An Observable that has to be defined on a superset of the
+437 configurations in obs[i].idl for all i.
+438 all_configs : bool
+439 if True, the reweighted observables are normalized by the average of
+440 the reweighting factor on all configurations in weight.idl and not
+441 on the configurations in obs[i].idl.
+442 """
+443 new_content = []
+444 for t_slice in self.content:
+445 if t_slice is None:
+446 new_content.append(None)
+447 else:
+448 new_content.append(np.array(reweight(weight, t_slice, **kwargs)))
+449 return Corr(new_content)
@@ -3456,33 +3468,33 @@ on the configurations in obs[i].idl.
View Source
- 447 def T_symmetry(self, partner, parity=+1):
-448 """Return the time symmetry average of the correlator and its partner
-449
-450 Parameters
-451 ----------
-452 partner : Corr
-453 Time symmetry partner of the Corr
-454 partity : int
-455 Parity quantum number of the correlator, can be +1 or -1
-456 """
-457 if not isinstance(partner, Corr):
-458 raise Exception("T partner has to be a Corr object.")
-459 if parity not in [+1, -1]:
-460 raise Exception("Parity has to be +1 or -1.")
-461 T_partner = parity * partner.reverse()
-462
-463 t_slices = []
-464 test = (self - T_partner)
-465 test.gamma_method()
-466 for x0, t_slice in enumerate(test.content):
-467 if t_slice is not None:
-468 if not t_slice[0].is_zero_within_error(5):
-469 t_slices.append(x0)
-470 if t_slices:
-471 warnings.warn("T symmetry partners do not agree within 5 sigma on time slices " + str(t_slices) + ".", RuntimeWarning)
-472
-473 return (self + T_partner) / 2
+ 451 def T_symmetry(self, partner, parity=+1):
+452 """Return the time symmetry average of the correlator and its partner
+453
+454 Parameters
+455 ----------
+456 partner : Corr
+457 Time symmetry partner of the Corr
+458 partity : int
+459 Parity quantum number of the correlator, can be +1 or -1
+460 """
+461 if not isinstance(partner, Corr):
+462 raise Exception("T partner has to be a Corr object.")
+463 if parity not in [+1, -1]:
+464 raise Exception("Parity has to be +1 or -1.")
+465 T_partner = parity * partner.reverse()
+466
+467 t_slices = []
+468 test = (self - T_partner)
+469 test.gamma_method()
+470 for x0, t_slice in enumerate(test.content):
+471 if t_slice is not None:
+472 if not t_slice[0].is_zero_within_error(5):
+473 t_slices.append(x0)
+474 if t_slices:
+475 warnings.warn("T symmetry partners do not agree within 5 sigma on time slices " + str(t_slices) + ".", RuntimeWarning)
+476
+477 return (self + T_partner) / 2
@@ -3511,57 +3523,57 @@ Parity quantum number of the correlator, can be +1 or -1
View Source
- 475 def deriv(self, variant="symmetric"):
-476 """Return the first derivative of the correlator with respect to x0.
-477
-478 Parameters
-479 ----------
-480 variant : str
-481 decides which definition of the finite differences derivative is used.
-482 Available choice: symmetric, forward, backward, improved, default: symmetric
-483 """
-484 if variant == "symmetric":
-485 newcontent = []
-486 for t in range(1, self.T - 1):
-487 if (self.content[t - 1] is None) or (self.content[t + 1] is None):
-488 newcontent.append(None)
-489 else:
-490 newcontent.append(0.5 * (self.content[t + 1] - self.content[t - 1]))
-491 if(all([x is None for x in newcontent])):
-492 raise Exception('Derivative is undefined at all timeslices')
-493 return Corr(newcontent, padding=[1, 1])
-494 elif variant == "forward":
-495 newcontent = []
-496 for t in range(self.T - 1):
-497 if (self.content[t] is None) or (self.content[t + 1] is None):
-498 newcontent.append(None)
-499 else:
-500 newcontent.append(self.content[t + 1] - self.content[t])
-501 if(all([x is None for x in newcontent])):
-502 raise Exception("Derivative is undefined at all timeslices")
-503 return Corr(newcontent, padding=[0, 1])
-504 elif variant == "backward":
-505 newcontent = []
-506 for t in range(1, self.T):
-507 if (self.content[t - 1] is None) or (self.content[t] is None):
-508 newcontent.append(None)
-509 else:
-510 newcontent.append(self.content[t] - self.content[t - 1])
-511 if(all([x is None for x in newcontent])):
-512 raise Exception("Derivative is undefined at all timeslices")
-513 return Corr(newcontent, padding=[1, 0])
-514 elif variant == "improved":
-515 newcontent = []
-516 for t in range(2, self.T - 2):
-517 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):
-518 newcontent.append(None)
-519 else:
-520 newcontent.append((1 / 12) * (self.content[t - 2] - 8 * self.content[t - 1] + 8 * self.content[t + 1] - self.content[t + 2]))
-521 if(all([x is None for x in newcontent])):
-522 raise Exception('Derivative is undefined at all timeslices')
-523 return Corr(newcontent, padding=[2, 2])
-524 else:
-525 raise Exception("Unknown variant.")
+ 479 def deriv(self, variant="symmetric"):
+480 """Return the first derivative of the correlator with respect to x0.
+481
+482 Parameters
+483 ----------
+484 variant : str
+485 decides which definition of the finite differences derivative is used.
+486 Available choice: symmetric, forward, backward, improved, default: symmetric
+487 """
+488 if variant == "symmetric":
+489 newcontent = []
+490 for t in range(1, self.T - 1):
+491 if (self.content[t - 1] is None) or (self.content[t + 1] is None):
+492 newcontent.append(None)
+493 else:
+494 newcontent.append(0.5 * (self.content[t + 1] - self.content[t - 1]))
+495 if(all([x is None for x in newcontent])):
+496 raise Exception('Derivative is undefined at all timeslices')
+497 return Corr(newcontent, padding=[1, 1])
+498 elif variant == "forward":
+499 newcontent = []
+500 for t in range(self.T - 1):
+501 if (self.content[t] is None) or (self.content[t + 1] is None):
+502 newcontent.append(None)
+503 else:
+504 newcontent.append(self.content[t + 1] - self.content[t])
+505 if(all([x is None for x in newcontent])):
+506 raise Exception("Derivative is undefined at all timeslices")
+507 return Corr(newcontent, padding=[0, 1])
+508 elif variant == "backward":
+509 newcontent = []
+510 for t in range(1, self.T):
+511 if (self.content[t - 1] is None) or (self.content[t] is None):
+512 newcontent.append(None)
+513 else:
+514 newcontent.append(self.content[t] - self.content[t - 1])
+515 if(all([x is None for x in newcontent])):
+516 raise Exception("Derivative is undefined at all timeslices")
+517 return Corr(newcontent, padding=[1, 0])
+518 elif variant == "improved":
+519 newcontent = []
+520 for t in range(2, self.T - 2):
+521 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):
+522 newcontent.append(None)
+523 else:
+524 newcontent.append((1 / 12) * (self.content[t - 2] - 8 * self.content[t - 1] + 8 * self.content[t + 1] - self.content[t + 2]))
+525 if(all([x is None for x in newcontent])):
+526 raise Exception('Derivative is undefined at all timeslices')
+527 return Corr(newcontent, padding=[2, 2])
+528 else:
+529 raise Exception("Unknown variant.")
@@ -3589,37 +3601,37 @@ Available choice: symmetric, forward, backward, improved, default: symmetric
View Source
- 527 def second_deriv(self, variant="symmetric"):
-528 """Return the second derivative of the correlator with respect to x0.
-529
-530 Parameters
-531 ----------
-532 variant : str
-533 decides which definition of the finite differences derivative is used.
-534 Available choice: symmetric, improved, default: symmetric
-535 """
-536 if variant == "symmetric":
-537 newcontent = []
-538 for t in range(1, self.T - 1):
-539 if (self.content[t - 1] is None) or (self.content[t + 1] is None):
-540 newcontent.append(None)
-541 else:
-542 newcontent.append((self.content[t + 1] - 2 * self.content[t] + self.content[t - 1]))
-543 if(all([x is None for x in newcontent])):
-544 raise Exception("Derivative is undefined at all timeslices")
-545 return Corr(newcontent, padding=[1, 1])
-546 elif variant == "improved":
-547 newcontent = []
-548 for t in range(2, self.T - 2):
-549 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):
-550 newcontent.append(None)
-551 else:
-552 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]))
-553 if(all([x is None for x in newcontent])):
-554 raise Exception("Derivative is undefined at all timeslices")
-555 return Corr(newcontent, padding=[2, 2])
-556 else:
-557 raise Exception("Unknown variant.")
+ 531 def second_deriv(self, variant="symmetric"):
+532 """Return the second derivative of the correlator with respect to x0.
+533
+534 Parameters
+535 ----------
+536 variant : str
+537 decides which definition of the finite differences derivative is used.
+538 Available choice: symmetric, improved, default: symmetric
+539 """
+540 if variant == "symmetric":
+541 newcontent = []
+542 for t in range(1, self.T - 1):
+543 if (self.content[t - 1] is None) or (self.content[t + 1] is None):
+544 newcontent.append(None)
+545 else:
+546 newcontent.append((self.content[t + 1] - 2 * 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, 1])
+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] 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] + 16 * self.content[t + 1] - 30 * self.content[t] + 16 * 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 else:
+561 raise Exception("Unknown variant.")
@@ -3647,70 +3659,70 @@ Available choice: symmetric, improved, default: symmetric
View Source
- 559 def m_eff(self, variant='log', guess=1.0):
-560 """Returns the effective mass of the correlator as correlator object
-561
-562 Parameters
-563 ----------
-564 variant : str
-565 log : uses the standard effective mass log(C(t) / C(t+1))
-566 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.
-567 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.
-568 See, e.g., arXiv:1205.5380
-569 arccosh : Uses the explicit form of the symmetrized correlator (not recommended)
-570 guess : float
-571 guess for the root finder, only relevant for the root variant
-572 """
-573 if self.N != 1:
-574 raise Exception('Correlator must be projected before getting m_eff')
-575 if variant == 'log':
-576 newcontent = []
-577 for t in range(self.T - 1):
-578 if (self.content[t] is None) or (self.content[t + 1] is None):
-579 newcontent.append(None)
-580 else:
-581 newcontent.append(self.content[t] / self.content[t + 1])
-582 if(all([x is None for x in newcontent])):
-583 raise Exception('m_eff is undefined at all timeslices')
-584
-585 return np.log(Corr(newcontent, padding=[0, 1]))
-586
-587 elif variant in ['periodic', 'cosh', 'sinh']:
-588 if variant in ['periodic', 'cosh']:
-589 func = anp.cosh
-590 else:
-591 func = anp.sinh
-592
-593 def root_function(x, d):
-594 return func(x * (t - self.T / 2)) / func(x * (t + 1 - self.T / 2)) - d
-595
-596 newcontent = []
-597 for t in range(self.T - 1):
-598 if (self.content[t] is None) or (self.content[t + 1] is None):
-599 newcontent.append(None)
-600 # Fill the two timeslices in the middle of the lattice with their predecessors
-601 elif variant == 'sinh' and t in [self.T / 2, self.T / 2 - 1]:
-602 newcontent.append(newcontent[-1])
-603 else:
-604 newcontent.append(np.abs(find_root(self.content[t][0] / self.content[t + 1][0], root_function, guess=guess)))
-605 if(all([x is None for x in newcontent])):
-606 raise Exception('m_eff is undefined at all timeslices')
-607
-608 return Corr(newcontent, padding=[0, 1])
-609
-610 elif variant == 'arccosh':
-611 newcontent = []
-612 for t in range(1, self.T - 1):
-613 if (self.content[t] is None) or (self.content[t + 1] is None) or (self.content[t - 1] is None):
-614 newcontent.append(None)
-615 else:
-616 newcontent.append((self.content[t + 1] + self.content[t - 1]) / (2 * self.content[t]))
-617 if(all([x is None for x in newcontent])):
-618 raise Exception("m_eff is undefined at all timeslices")
-619 return np.arccosh(Corr(newcontent, padding=[1, 1]))
-620
-621 else:
-622 raise Exception('Unknown variant.')
+ 563 def m_eff(self, variant='log', guess=1.0):
+564 """Returns the effective mass of the correlator as correlator object
+565
+566 Parameters
+567 ----------
+568 variant : str
+569 log : uses the standard effective mass log(C(t) / C(t+1))
+570 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.
+571 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.
+572 See, e.g., arXiv:1205.5380
+573 arccosh : Uses the explicit form of the symmetrized correlator (not recommended)
+574 guess : float
+575 guess for the root finder, only relevant for the root variant
+576 """
+577 if self.N != 1:
+578 raise Exception('Correlator must be projected before getting m_eff')
+579 if variant == 'log':
+580 newcontent = []
+581 for t in range(self.T - 1):
+582 if (self.content[t] is None) or (self.content[t + 1] is None):
+583 newcontent.append(None)
+584 else:
+585 newcontent.append(self.content[t] / self.content[t + 1])
+586 if(all([x is None for x in newcontent])):
+587 raise Exception('m_eff is undefined at all timeslices')
+588
+589 return np.log(Corr(newcontent, padding=[0, 1]))
+590
+591 elif variant in ['periodic', 'cosh', 'sinh']:
+592 if variant in ['periodic', 'cosh']:
+593 func = anp.cosh
+594 else:
+595 func = anp.sinh
+596
+597 def root_function(x, d):
+598 return func(x * (t - self.T / 2)) / func(x * (t + 1 - self.T / 2)) - d
+599
+600 newcontent = []
+601 for t in range(self.T - 1):
+602 if (self.content[t] is None) or (self.content[t + 1] is None):
+603 newcontent.append(None)
+604 # Fill the two timeslices in the middle of the lattice with their predecessors
+605 elif variant == 'sinh' and t in [self.T / 2, self.T / 2 - 1]:
+606 newcontent.append(newcontent[-1])
+607 else:
+608 newcontent.append(np.abs(find_root(self.content[t][0] / self.content[t + 1][0], root_function, guess=guess)))
+609 if(all([x is None for x in newcontent])):
+610 raise Exception('m_eff is undefined at all timeslices')
+611
+612 return Corr(newcontent, padding=[0, 1])
+613
+614 elif variant == 'arccosh':
+615 newcontent = []
+616 for t in range(1, self.T - 1):
+617 if (self.content[t] is None) or (self.content[t + 1] is None) or (self.content[t - 1] is None):
+618 newcontent.append(None)
+619 else:
+620 newcontent.append((self.content[t + 1] + self.content[t - 1]) / (2 * self.content[t]))
+621 if(all([x is None for x in newcontent])):
+622 raise Exception("m_eff is undefined at all timeslices")
+623 return np.arccosh(Corr(newcontent, padding=[1, 1]))
+624
+625 else:
+626 raise Exception('Unknown variant.')
@@ -3743,39 +3755,39 @@ guess for the root finder, only relevant for the root variant
View Source
- 624 def fit(self, function, fitrange=None, silent=False, **kwargs):
-625 r'''Fits function to the data
-626
-627 Parameters
-628 ----------
-629 function : obj
-630 function to fit to the data. See fits.least_squares for details.
-631 fitrange : list
-632 Two element list containing the timeslices on which the fit is supposed to start and stop.
-633 Caution: This range is inclusive as opposed to standard python indexing.
-634 `fitrange=[4, 6]` corresponds to the three entries 4, 5 and 6.
-635 If not specified, self.prange or all timeslices are used.
-636 silent : bool
-637 Decides whether output is printed to the standard output.
-638 '''
-639 if self.N != 1:
-640 raise Exception("Correlator must be projected before fitting")
-641
-642 if fitrange is None:
-643 if self.prange:
-644 fitrange = self.prange
-645 else:
-646 fitrange = [0, self.T - 1]
-647 else:
-648 if not isinstance(fitrange, list):
-649 raise Exception("fitrange has to be a list with two elements")
-650 if len(fitrange) != 2:
-651 raise Exception("fitrange has to have exactly two elements [fit_start, fit_stop]")
-652
-653 xs = [x for x in range(fitrange[0], fitrange[1] + 1) if not self.content[x] is None]
-654 ys = [self.content[x][0] for x in range(fitrange[0], fitrange[1] + 1) if not self.content[x] is None]
-655 result = least_squares(xs, ys, function, silent=silent, **kwargs)
-656 return result
+ 628 def fit(self, function, fitrange=None, silent=False, **kwargs):
+629 r'''Fits function to the data
+630
+631 Parameters
+632 ----------
+633 function : obj
+634 function to fit to the data. See fits.least_squares for details.
+635 fitrange : list
+636 Two element list containing the timeslices on which the fit is supposed to start and stop.
+637 Caution: This range is inclusive as opposed to standard python indexing.
+638 `fitrange=[4, 6]` corresponds to the three entries 4, 5 and 6.
+639 If not specified, self.prange or all timeslices are used.
+640 silent : bool
+641 Decides whether output is printed to the standard output.
+642 '''
+643 if self.N != 1:
+644 raise Exception("Correlator must be projected before fitting")
+645
+646 if fitrange is None:
+647 if self.prange:
+648 fitrange = self.prange
+649 else:
+650 fitrange = [0, self.T - 1]
+651 else:
+652 if not isinstance(fitrange, list):
+653 raise Exception("fitrange has to be a list with two elements")
+654 if len(fitrange) != 2:
+655 raise Exception("fitrange has to have exactly two elements [fit_start, fit_stop]")
+656
+657 xs = [x for x in range(fitrange[0], fitrange[1] + 1) if not self.content[x] is None]
+658 ys = [self.content[x][0] for x in range(fitrange[0], fitrange[1] + 1) if not self.content[x] is None]
+659 result = least_squares(xs, ys, function, silent=silent, **kwargs)
+660 return result
@@ -3809,42 +3821,42 @@ Decides whether output is printed to the standard output.
View Source
- 658 def plateau(self, plateau_range=None, method="fit", auto_gamma=False):
-659 """ Extract a plateau value from a Corr object
-660
-661 Parameters
-662 ----------
-663 plateau_range : list
-664 list with two entries, indicating the first and the last timeslice
-665 of the plateau region.
-666 method : str
-667 method to extract the plateau.
-668 'fit' fits a constant to the plateau region
-669 'avg', 'average' or 'mean' just average over the given timeslices.
-670 auto_gamma : bool
-671 apply gamma_method with default parameters to the Corr. Defaults to None
-672 """
-673 if not plateau_range:
-674 if self.prange:
-675 plateau_range = self.prange
-676 else:
-677 raise Exception("no plateau range provided")
-678 if self.N != 1:
-679 raise Exception("Correlator must be projected before getting a plateau.")
-680 if(all([self.content[t] is None for t in range(plateau_range[0], plateau_range[1] + 1)])):
-681 raise Exception("plateau is undefined at all timeslices in plateaurange.")
-682 if auto_gamma:
-683 self.gamma_method()
-684 if method == "fit":
-685 def const_func(a, t):
-686 return a[0]
-687 return self.fit(const_func, plateau_range)[0]
-688 elif method in ["avg", "average", "mean"]:
-689 returnvalue = np.mean([item[0] for item in self.content[plateau_range[0]:plateau_range[1] + 1] if item is not None])
-690 return returnvalue
-691
-692 else:
-693 raise Exception("Unsupported plateau method: " + method)
+ 662 def plateau(self, plateau_range=None, method="fit", auto_gamma=False):
+663 """ Extract a plateau value from a Corr object
+664
+665 Parameters
+666 ----------
+667 plateau_range : list
+668 list with two entries, indicating the first and the last timeslice
+669 of the plateau region.
+670 method : str
+671 method to extract the plateau.
+672 'fit' fits a constant to the plateau region
+673 'avg', 'average' or 'mean' just average over the given timeslices.
+674 auto_gamma : bool
+675 apply gamma_method with default parameters to the Corr. Defaults to None
+676 """
+677 if not plateau_range:
+678 if self.prange:
+679 plateau_range = self.prange
+680 else:
+681 raise Exception("no plateau range provided")
+682 if self.N != 1:
+683 raise Exception("Correlator must be projected before getting a plateau.")
+684 if(all([self.content[t] is None for t in range(plateau_range[0], plateau_range[1] + 1)])):
+685 raise Exception("plateau is undefined at all timeslices in plateaurange.")
+686 if auto_gamma:
+687 self.gamma_method()
+688 if method == "fit":
+689 def const_func(a, t):
+690 return a[0]
+691 return self.fit(const_func, plateau_range)[0]
+692 elif method in ["avg", "average", "mean"]:
+693 returnvalue = np.mean([item[0] for item in self.content[plateau_range[0]:plateau_range[1] + 1] if item is not None])
+694 return returnvalue
+695
+696 else:
+697 raise Exception("Unsupported plateau method: " + method)
@@ -3878,17 +3890,17 @@ apply gamma_method with default parameters to the Corr. Defaults to None
View Source
- 695 def set_prange(self, prange):
-696 """Sets the attribute prange of the Corr object."""
-697 if not len(prange) == 2:
-698 raise Exception("prange must be a list or array with two values")
-699 if not ((isinstance(prange[0], int)) and (isinstance(prange[1], int))):
-700 raise Exception("Start and end point must be integers")
-701 if not (0 <= prange[0] <= self.T and 0 <= prange[1] <= self.T and prange[0] < prange[1]):
-702 raise Exception("Start and end point must define a range in the interval 0,T")
-703
-704 self.prange = prange
-705 return
+ 699 def set_prange(self, prange):
+700 """Sets the attribute prange of the Corr object."""
+701 if not len(prange) == 2:
+702 raise Exception("prange must be a list or array with two values")
+703 if not ((isinstance(prange[0], int)) and (isinstance(prange[1], int))):
+704 raise Exception("Start and end point must be integers")
+705 if not (0 <= prange[0] <= self.T and 0 <= prange[1] <= self.T and prange[0] < prange[1]):
+706 raise Exception("Start and end point must define a range in the interval 0,T")
+707
+708 self.prange = prange
+709 return
@@ -3921,118 +3933,118 @@ apply gamma_method with default parameters to the Corr. Defaults to None
View Source
- 707 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):
-708 """Plots the correlator using the tag of the correlator as label if available.
-709
-710 Parameters
-711 ----------
-712 x_range : list
-713 list of two values, determining the range of the x-axis e.g. [4, 8]
-714 comp : Corr or list of Corr
-715 Correlator or list of correlators which are plotted for comparison.
-716 The tags of these correlators are used as labels if available.
-717 logscale : bool
-718 Sets y-axis to logscale
-719 plateau : Obs
-720 Plateau value to be visualized in the figure
-721 fit_res : Fit_result
-722 Fit_result object to be visualized
-723 ylabel : str
-724 Label for the y-axis
-725 save : str
-726 path to file in which the figure should be saved
-727 auto_gamma : bool
-728 Apply the gamma method with standard parameters to all correlators and plateau values before plotting.
-729 hide_sigma : float
-730 Hides data points from the first value on which is consistent with zero within 'hide_sigma' standard errors.
-731 references : list
-732 List of floating point values that are displayed as horizontal lines for reference.
-733 """
-734 if self.N != 1:
-735 raise Exception("Correlator must be projected before plotting")
-736
-737 if auto_gamma:
-738 self.gamma_method()
-739
-740 if x_range is None:
-741 x_range = [0, self.T - 1]
-742
-743 fig = plt.figure()
-744 ax1 = fig.add_subplot(111)
-745
-746 x, y, y_err = self.plottable()
-747 if hide_sigma:
-748 hide_from = np.argmax((hide_sigma * np.array(y_err)) > np.abs(y)) - 1
-749 else:
-750 hide_from = None
-751 ax1.errorbar(x[:hide_from], y[:hide_from], y_err[:hide_from], label=self.tag)
-752 if logscale:
-753 ax1.set_yscale('log')
-754 else:
-755 if y_range is None:
-756 try:
-757 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)])
-758 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)])
-759 ax1.set_ylim([y_min - 0.1 * (y_max - y_min), y_max + 0.1 * (y_max - y_min)])
-760 except Exception:
-761 pass
-762 else:
-763 ax1.set_ylim(y_range)
-764 if comp:
-765 if isinstance(comp, (Corr, list)):
-766 for corr in comp if isinstance(comp, list) else [comp]:
-767 if auto_gamma:
-768 corr.gamma_method()
-769 x, y, y_err = corr.plottable()
-770 if hide_sigma:
-771 hide_from = np.argmax((hide_sigma * np.array(y_err)) > np.abs(y)) - 1
-772 else:
-773 hide_from = None
-774 plt.errorbar(x[:hide_from], y[:hide_from], y_err[:hide_from], label=corr.tag, mfc=plt.rcParams['axes.facecolor'])
-775 else:
-776 raise Exception("'comp' must be a correlator or a list of correlators.")
-777
-778 if plateau:
-779 if isinstance(plateau, Obs):
-780 if auto_gamma:
-781 plateau.gamma_method()
-782 ax1.axhline(y=plateau.value, linewidth=2, color=plt.rcParams['text.color'], alpha=0.6, marker=',', ls='--', label=str(plateau))
-783 ax1.axhspan(plateau.value - plateau.dvalue, plateau.value + plateau.dvalue, alpha=0.25, color=plt.rcParams['text.color'], ls='-')
-784 else:
-785 raise Exception("'plateau' must be an Obs")
-786
-787 if references:
-788 if isinstance(references, list):
-789 for ref in references:
-790 ax1.axhline(y=ref, linewidth=1, color=plt.rcParams['text.color'], alpha=0.6, marker=',', ls='--')
-791 else:
-792 raise Exception("'references' must be a list of floating pint values.")
-793
-794 if self.prange:
-795 ax1.axvline(self.prange[0], 0, 1, ls='-', marker=',')
-796 ax1.axvline(self.prange[1], 0, 1, ls='-', marker=',')
+ 711 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):
+712 """Plots the correlator using the tag of the correlator as label if available.
+713
+714 Parameters
+715 ----------
+716 x_range : list
+717 list of two values, determining the range of the x-axis e.g. [4, 8]
+718 comp : Corr or list of Corr
+719 Correlator or list of correlators which are plotted for comparison.
+720 The tags of these correlators are used as labels if available.
+721 logscale : bool
+722 Sets y-axis to logscale
+723 plateau : Obs
+724 Plateau value to be visualized in the figure
+725 fit_res : Fit_result
+726 Fit_result object to be visualized
+727 ylabel : str
+728 Label for the y-axis
+729 save : str
+730 path to file in which the figure should be saved
+731 auto_gamma : bool
+732 Apply the gamma method with standard parameters to all correlators and plateau values before plotting.
+733 hide_sigma : float
+734 Hides data points from the first value on which is consistent with zero within 'hide_sigma' standard errors.
+735 references : list
+736 List of floating point values that are displayed as horizontal lines for reference.
+737 """
+738 if self.N != 1:
+739 raise Exception("Correlator must be projected before plotting")
+740
+741 if auto_gamma:
+742 self.gamma_method()
+743
+744 if x_range is None:
+745 x_range = [0, self.T - 1]
+746
+747 fig = plt.figure()
+748 ax1 = fig.add_subplot(111)
+749
+750 x, y, y_err = self.plottable()
+751 if hide_sigma:
+752 hide_from = np.argmax((hide_sigma * np.array(y_err)) > np.abs(y)) - 1
+753 else:
+754 hide_from = None
+755 ax1.errorbar(x[:hide_from], y[:hide_from], y_err[:hide_from], label=self.tag)
+756 if logscale:
+757 ax1.set_yscale('log')
+758 else:
+759 if y_range is None:
+760 try:
+761 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)])
+762 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)])
+763 ax1.set_ylim([y_min - 0.1 * (y_max - y_min), y_max + 0.1 * (y_max - y_min)])
+764 except Exception:
+765 pass
+766 else:
+767 ax1.set_ylim(y_range)
+768 if comp:
+769 if isinstance(comp, (Corr, list)):
+770 for corr in comp if isinstance(comp, list) else [comp]:
+771 if auto_gamma:
+772 corr.gamma_method()
+773 x, y, y_err = corr.plottable()
+774 if hide_sigma:
+775 hide_from = np.argmax((hide_sigma * np.array(y_err)) > np.abs(y)) - 1
+776 else:
+777 hide_from = None
+778 plt.errorbar(x[:hide_from], y[:hide_from], y_err[:hide_from], label=corr.tag, mfc=plt.rcParams['axes.facecolor'])
+779 else:
+780 raise Exception("'comp' must be a correlator or a list of correlators.")
+781
+782 if plateau:
+783 if isinstance(plateau, Obs):
+784 if auto_gamma:
+785 plateau.gamma_method()
+786 ax1.axhline(y=plateau.value, linewidth=2, color=plt.rcParams['text.color'], alpha=0.6, marker=',', ls='--', label=str(plateau))
+787 ax1.axhspan(plateau.value - plateau.dvalue, plateau.value + plateau.dvalue, alpha=0.25, color=plt.rcParams['text.color'], ls='-')
+788 else:
+789 raise Exception("'plateau' must be an Obs")
+790
+791 if references:
+792 if isinstance(references, list):
+793 for ref in references:
+794 ax1.axhline(y=ref, linewidth=1, color=plt.rcParams['text.color'], alpha=0.6, marker=',', ls='--')
+795 else:
+796 raise Exception("'references' must be a list of floating pint values.")
797
-798 if fit_res:
-799 x_samples = np.arange(x_range[0], x_range[1] + 1, 0.05)
-800 ax1.plot(x_samples,
-801 fit_res.fit_function([o.value for o in fit_res.fit_parameters], x_samples),
-802 ls='-', marker=',', lw=2)
-803
-804 ax1.set_xlabel(r'$x_0 / a$')
-805 if ylabel:
-806 ax1.set_ylabel(ylabel)
-807 ax1.set_xlim([x_range[0] - 0.5, x_range[1] + 0.5])
-808
-809 handles, labels = ax1.get_legend_handles_labels()
-810 if labels:
-811 ax1.legend()
-812 plt.draw()
-813
-814 if save:
-815 if isinstance(save, str):
-816 fig.savefig(save)
-817 else:
-818 raise Exception("'save' has to be a string.")
+798 if self.prange:
+799 ax1.axvline(self.prange[0], 0, 1, ls='-', marker=',')
+800 ax1.axvline(self.prange[1], 0, 1, ls='-', marker=',')
+801
+802 if fit_res:
+803 x_samples = np.arange(x_range[0], x_range[1] + 1, 0.05)
+804 ax1.plot(x_samples,
+805 fit_res.fit_function([o.value for o in fit_res.fit_parameters], x_samples),
+806 ls='-', marker=',', lw=2)
+807
+808 ax1.set_xlabel(r'$x_0 / a$')
+809 if ylabel:
+810 ax1.set_ylabel(ylabel)
+811 ax1.set_xlim([x_range[0] - 0.5, x_range[1] + 0.5])
+812
+813 handles, labels = ax1.get_legend_handles_labels()
+814 if labels:
+815 ax1.legend()
+816 plt.draw()
+817
+818 if save:
+819 if isinstance(save, str):
+820 fig.savefig(save)
+821 else:
+822 raise Exception("'save' has to be a string.")
@@ -4078,34 +4090,34 @@ List of floating point values that are displayed as horizontal lines for referen
View Source
- 820 def spaghetti_plot(self, logscale=True):
-821 """Produces a spaghetti plot of the correlator suited to monitor exceptional configurations.
-822
-823 Parameters
-824 ----------
-825 logscale : bool
-826 Determines whether the scale of the y-axis is logarithmic or standard.
-827 """
-828 if self.N != 1:
-829 raise Exception("Correlator needs to be projected first.")
-830
-831 mc_names = list(set([item for sublist in [o[0].mc_names for o in self.content if o is not None] for item in sublist]))
-832 x0_vals = [n for (n, o) in zip(np.arange(self.T), self.content) if o is not None]
-833
-834 for name in mc_names:
-835 data = np.array([o[0].deltas[name] + o[0].r_values[name] for o in self.content if o is not None]).T
-836
-837 fig = plt.figure()
-838 ax = fig.add_subplot(111)
-839 for dat in data:
-840 ax.plot(x0_vals, dat, ls='-', marker='')
-841
-842 if logscale is True:
-843 ax.set_yscale('log')
-844
-845 ax.set_xlabel(r'$x_0 / a$')
-846 plt.title(name)
-847 plt.draw()
+ 824 def spaghetti_plot(self, logscale=True):
+825 """Produces a spaghetti plot of the correlator suited to monitor exceptional configurations.
+826
+827 Parameters
+828 ----------
+829 logscale : bool
+830 Determines whether the scale of the y-axis is logarithmic or standard.
+831 """
+832 if self.N != 1:
+833 raise Exception("Correlator needs to be projected first.")
+834
+835 mc_names = list(set([item for sublist in [o[0].mc_names for o in self.content if o is not None] for item in sublist]))
+836 x0_vals = [n for (n, o) in zip(np.arange(self.T), self.content) if o is not None]
+837
+838 for name in mc_names:
+839 data = np.array([o[0].deltas[name] + o[0].r_values[name] for o in self.content if o is not None]).T
+840
+841 fig = plt.figure()
+842 ax = fig.add_subplot(111)
+843 for dat in data:
+844 ax.plot(x0_vals, dat, ls='-', marker='')
+845
+846 if logscale is True:
+847 ax.set_yscale('log')
+848
+849 ax.set_xlabel(r'$x_0 / a$')
+850 plt.title(name)
+851 plt.draw()
@@ -4132,29 +4144,29 @@ Determines whether the scale of the y-axis is logarithmic or standard.
View Source
- 849 def dump(self, filename, datatype="json.gz", **kwargs):
-850 """Dumps the Corr into a file of chosen type
-851 Parameters
-852 ----------
-853 filename : str
-854 Name of the file to be saved.
-855 datatype : str
-856 Format of the exported file. Supported formats include
-857 "json.gz" and "pickle"
-858 path : str
-859 specifies a custom path for the file (default '.')
-860 """
-861 if datatype == "json.gz":
-862 from .input.json import dump_to_json
-863 if 'path' in kwargs:
-864 file_name = kwargs.get('path') + '/' + filename
-865 else:
-866 file_name = filename
-867 dump_to_json(self, file_name)
-868 elif datatype == "pickle":
-869 dump_object(self, filename, **kwargs)
-870 else:
-871 raise Exception("Unknown datatype " + str(datatype))
+ 853 def dump(self, filename, datatype="json.gz", **kwargs):
+854 """Dumps the Corr into a file of chosen type
+855 Parameters
+856 ----------
+857 filename : str
+858 Name of the file to be saved.
+859 datatype : str
+860 Format of the exported file. Supported formats include
+861 "json.gz" and "pickle"
+862 path : str
+863 specifies a custom path for the file (default '.')
+864 """
+865 if datatype == "json.gz":
+866 from .input.json import dump_to_json
+867 if 'path' in kwargs:
+868 file_name = kwargs.get('path') + '/' + filename
+869 else:
+870 file_name = filename
+871 dump_to_json(self, file_name)
+872 elif datatype == "pickle":
+873 dump_object(self, filename, **kwargs)
+874 else:
+875 raise Exception("Unknown datatype " + str(datatype))
@@ -4186,8 +4198,8 @@ specifies a custom path for the file (default '.')
View Source
- 873 def print(self, range=[0, None]):
-874 print(self.__repr__(range))
+ 877 def print(self, range=[0, None]):
+878 print(self.__repr__(range))
@@ -4205,8 +4217,8 @@ specifies a custom path for the file (default '.')
View Source
- 1036 def sqrt(self):
-1037 return self**0.5
+ 1040 def sqrt(self):
+1041 return self**0.5
@@ -4224,9 +4236,9 @@ specifies a custom path for the file (default '.')
View Source
- 1039 def log(self):
-1040 newcontent = [None if (item is None) else np.log(item) for item in self.content]
-1041 return Corr(newcontent, prange=self.prange)
+ 1043 def log(self):
+1044 newcontent = [None if (item is None) else np.log(item) for item in self.content]
+1045 return Corr(newcontent, prange=self.prange)
@@ -4244,9 +4256,9 @@ specifies a custom path for the file (default '.')
View Source
- 1043 def exp(self):
-1044 newcontent = [None if (item is None) else np.exp(item) for item in self.content]
-1045 return Corr(newcontent, prange=self.prange)
+ 1047 def exp(self):
+1048 newcontent = [None if (item is None) else np.exp(item) for item in self.content]
+1049 return Corr(newcontent, prange=self.prange)
@@ -4264,8 +4276,8 @@ specifies a custom path for the file (default '.')
View Source
- 1058 def sin(self):
-1059 return self._apply_func_to_corr(np.sin)
+ 1062 def sin(self):
+1063 return self._apply_func_to_corr(np.sin)
@@ -4283,8 +4295,8 @@ specifies a custom path for the file (default '.')
View Source
- 1061 def cos(self):
-1062 return self._apply_func_to_corr(np.cos)
+ 1065 def cos(self):
+1066 return self._apply_func_to_corr(np.cos)
@@ -4302,8 +4314,8 @@ specifies a custom path for the file (default '.')
View Source
- 1064 def tan(self):
-1065 return self._apply_func_to_corr(np.tan)
+ 1068 def tan(self):
+1069 return self._apply_func_to_corr(np.tan)
@@ -4321,8 +4333,8 @@ specifies a custom path for the file (default '.')
View Source
- 1067 def sinh(self):
-1068 return self._apply_func_to_corr(np.sinh)
+ 1071 def sinh(self):
+1072 return self._apply_func_to_corr(np.sinh)
@@ -4340,8 +4352,8 @@ specifies a custom path for the file (default '.')
View Source
- 1070 def cosh(self):
-1071 return self._apply_func_to_corr(np.cosh)
+ 1074 def cosh(self):
+1075 return self._apply_func_to_corr(np.cosh)
@@ -4359,8 +4371,8 @@ specifies a custom path for the file (default '.')
View Source
- 1073 def tanh(self):
-1074 return self._apply_func_to_corr(np.tanh)
+ 1077 def tanh(self):
+1078 return self._apply_func_to_corr(np.tanh)
@@ -4378,8 +4390,8 @@ specifies a custom path for the file (default '.')
View Source
- 1076 def arcsin(self):
-1077 return self._apply_func_to_corr(np.arcsin)
+ 1080 def arcsin(self):
+1081 return self._apply_func_to_corr(np.arcsin)
@@ -4397,8 +4409,8 @@ specifies a custom path for the file (default '.')
View Source
- 1079 def arccos(self):
-1080 return self._apply_func_to_corr(np.arccos)
+ 1083 def arccos(self):
+1084 return self._apply_func_to_corr(np.arccos)
@@ -4416,8 +4428,8 @@ specifies a custom path for the file (default '.')
View Source
- 1082 def arctan(self):
-1083 return self._apply_func_to_corr(np.arctan)
+ 1086 def arctan(self):
+1087 return self._apply_func_to_corr(np.arctan)
@@ -4435,8 +4447,8 @@ specifies a custom path for the file (default '.')
View Source
- 1085 def arcsinh(self):
-1086 return self._apply_func_to_corr(np.arcsinh)
+ 1089 def arcsinh(self):
+1090 return self._apply_func_to_corr(np.arcsinh)
@@ -4454,8 +4466,8 @@ specifies a custom path for the file (default '.')
View Source
- 1088 def arccosh(self):
-1089 return self._apply_func_to_corr(np.arccosh)
+ 1092 def arccosh(self):
+1093 return self._apply_func_to_corr(np.arccosh)
@@ -4473,8 +4485,8 @@ specifies a custom path for the file (default '.')
View Source
- 1091 def arctanh(self):
-1092 return self._apply_func_to_corr(np.arctanh)
+ 1095 def arctanh(self):
+1096 return self._apply_func_to_corr(np.arctanh)
@@ -4512,64 +4524,64 @@ specifies a custom path for the file (default '.')
View Source
- 1127 def prune(self, Ntrunc, tproj=3, t0proj=2, basematrix=None):
-1128 r''' Project large correlation matrix to lowest states
-1129
-1130 This method can be used to reduce the size of an (N x N) correlation matrix
-1131 to (Ntrunc x Ntrunc) by solving a GEVP at very early times where the noise
-1132 is still small.
+ 1131 def prune(self, Ntrunc, tproj=3, t0proj=2, basematrix=None):
+1132 r''' Project large correlation matrix to lowest states
1133
-1134 Parameters
-1135 ----------
-1136 Ntrunc: int
-1137 Rank of the target matrix.
-1138 tproj: int
-1139 Time where the eigenvectors are evaluated, corresponds to ts in the GEVP method.
-1140 The default value is 3.
-1141 t0proj: int
-1142 Time where the correlation matrix is inverted. Choosing t0proj=1 is strongly
-1143 discouraged for O(a) improved theories, since the correctness of the procedure
-1144 cannot be granted in this case. The default value is 2.
-1145 basematrix : Corr
-1146 Correlation matrix that is used to determine the eigenvectors of the
-1147 lowest states based on a GEVP. basematrix is taken to be the Corr itself if
-1148 is is not specified.
-1149
-1150 Notes
-1151 -----
-1152 We have the basematrix $C(t)$ and the target matrix $G(t)$. We start by solving
-1153 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}$
-1154 and $t_0 \equiv t_{0, \mathrm{proj}}$. The target matrix is projected onto the subspace of the
-1155 resulting eigenvectors $v_n, n=1,\dots,N_\mathrm{trunc}$ via
-1156 $$G^\prime_{i, j}(t) = (v_i, G(t) v_j)$$. This allows to reduce the size of a large
-1157 correlation matrix and to remove some noise that is added by irrelevant operators.
-1158 This may allow to use the GEVP on $G(t)$ at late times such that the theoretically motivated
-1159 bound $t_0 \leq t/2$ holds, since the condition number of $G(t)$ is decreased, compared to $C(t)$.
-1160 '''
-1161
-1162 if self.N == 1:
-1163 raise Exception('Method cannot be applied to one-dimensional correlators.')
-1164 if basematrix is None:
-1165 basematrix = self
-1166 if Ntrunc >= basematrix.N:
-1167 raise Exception('Cannot truncate using Ntrunc <= %d' % (basematrix.N))
-1168 if basematrix.N != self.N:
-1169 raise Exception('basematrix and targetmatrix have to be of the same size.')
-1170
-1171 evecs = []
-1172 for i in range(Ntrunc):
-1173 evecs.append(basematrix.GEVP(t0proj, tproj, state=i, sorted_list=None))
+1134 This method can be used to reduce the size of an (N x N) correlation matrix
+1135 to (Ntrunc x Ntrunc) by solving a GEVP at very early times where the noise
+1136 is still small.
+1137
+1138 Parameters
+1139 ----------
+1140 Ntrunc: int
+1141 Rank of the target matrix.
+1142 tproj: int
+1143 Time where the eigenvectors are evaluated, corresponds to ts in the GEVP method.
+1144 The default value is 3.
+1145 t0proj: int
+1146 Time where the correlation matrix is inverted. Choosing t0proj=1 is strongly
+1147 discouraged for O(a) improved theories, since the correctness of the procedure
+1148 cannot be granted in this case. The default value is 2.
+1149 basematrix : Corr
+1150 Correlation matrix that is used to determine the eigenvectors of the
+1151 lowest states based on a GEVP. basematrix is taken to be the Corr itself if
+1152 is is not specified.
+1153
+1154 Notes
+1155 -----
+1156 We have the basematrix $C(t)$ and the target matrix $G(t)$. We start by solving
+1157 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}$
+1158 and $t_0 \equiv t_{0, \mathrm{proj}}$. The target matrix is projected onto the subspace of the
+1159 resulting eigenvectors $v_n, n=1,\dots,N_\mathrm{trunc}$ via
+1160 $$G^\prime_{i, j}(t) = (v_i, G(t) v_j)$$. This allows to reduce the size of a large
+1161 correlation matrix and to remove some noise that is added by irrelevant operators.
+1162 This may allow to use the GEVP on $G(t)$ at late times such that the theoretically motivated
+1163 bound $t_0 \leq t/2$ holds, since the condition number of $G(t)$ is decreased, compared to $C(t)$.
+1164 '''
+1165
+1166 if self.N == 1:
+1167 raise Exception('Method cannot be applied to one-dimensional correlators.')
+1168 if basematrix is None:
+1169 basematrix = self
+1170 if Ntrunc >= basematrix.N:
+1171 raise Exception('Cannot truncate using Ntrunc <= %d' % (basematrix.N))
+1172 if basematrix.N != self.N:
+1173 raise Exception('basematrix and targetmatrix have to be of the same size.')
1174
-1175 tmpmat = np.empty((Ntrunc, Ntrunc), dtype=object)
-1176 rmat = []
-1177 for t in range(basematrix.T):
-1178 for i in range(Ntrunc):
-1179 for j in range(Ntrunc):
-1180 tmpmat[i][j] = evecs[i].T @ self[t] @ evecs[j]
-1181 rmat.append(np.copy(tmpmat))
-1182
-1183 newcontent = [None if (self.content[t] is None) else rmat[t] for t in range(self.T)]
-1184 return Corr(newcontent)
+1175 evecs = []
+1176 for i in range(Ntrunc):
+1177 evecs.append(basematrix.GEVP(t0proj, tproj, state=i, sorted_list=None))
+1178
+1179 tmpmat = np.empty((Ntrunc, Ntrunc), dtype=object)
+1180 rmat = []
+1181 for t in range(basematrix.T):
+1182 for i in range(Ntrunc):
+1183 for j in range(Ntrunc):
+1184 tmpmat[i][j] = evecs[i].T @ self[t] @ evecs[j]
+1185 rmat.append(np.copy(tmpmat))
+1186
+1187 newcontent = [None if (self.content[t] is None) else rmat[t] for t in range(self.T)]
+1188 return Corr(newcontent)