quickplot.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. # -*- coding: utf-8 -*-
  2. """
  3. Created on Fri Oct 23 14:34:23 2020
  4. @author: aura1
  5. """
  6. import numpy as np
  7. import matplotlib.pyplot as plt
  8. from scipy.optimize import curve_fit
  9. def powerlaw_offset(x, y0, a, n):
  10. return y0 + a*np.power(x,-n)
  11. def main():
  12. # lmax_vals = np.arange(1.5,8.5)
  13. # mass_gap = [1.040524324172413,
  14. # 1.0178373805628915,
  15. # 1.0099935792170385,
  16. # 1.0063845297691891,
  17. # 1.0064220663290975,
  18. # 1.0032526281598741,
  19. # 1.00326253048339]
  20. # lmax_vals = np.arange(1,9)
  21. # mass_gap = [1.907381620393867,
  22. # 1.715060177638449,
  23. # 1.6803744291157905,
  24. # 1.6682371927439341,
  25. # 1.6624323199995565,
  26. # 1.6591860781893892,
  27. # 1.6571824919878146,
  28. # 1.6558575904310047]
  29. lmax_vals = np.arange(1.5,6.5)
  30. mass_gap = [0.49520512225736013,
  31. 0.7468507382588818,
  32. 0.15955182112437782,
  33. 1.3509297514989633,
  34. 1.369775425072806]
  35. """
  36. Note: runtimes are <1 second up to lmax=3, and then 8.9
  37. seconds for lmax=4 and 39 seconds for lmax=5. Runtime
  38. increases to a little over 2 minutes for lmax=6
  39. (~134 seconds), and to about 8 minutes (467 seconds) for
  40. lmax=7. lmax=8 takes about half an hour to run.
  41. In the antiperiodic case, lmax=13/2 taks about 3 minutes (190 s) to run,
  42. and lmax=15/2 takes 8 minutes (475 s).
  43. """
  44. plt.xlabel("lmax")
  45. plt.ylabel("mass gap (m/g)")
  46. plt.title("g=1,L=2pi, antiperiodic case")
  47. plt.xticks(np.arange(0,lmax_vals[-1]+1,0.5))
  48. plt.scatter(lmax_vals,mass_gap)
  49. #plt.grid(True)
  50. # popt, pcov = curve_fit(powerlaw_offset, lmax_vals[1:], mass_gap[1:])
  51. # print(f"Non-linearized curve fit: {popt}")
  52. # plt.scatter(lmax_vals,np.array(mass_gap)-1)
  53. # fit_xvals = np.linspace(lmax_vals[0],lmax_vals[-1])
  54. # plt.loglog(fit_xvals,powerlaw_offset(fit_xvals,popt[0],popt[1],popt[2])-1,
  55. # label=f"Non-linearized fit: y={popt[0]:.2f}+{popt[1]:.2f}/x^{popt[2]:.2f}")
  56. # [y0, a, n] = gradient_curvefit(lmax_vals[1:], mass_gap[1:])
  57. # print(f"Gradient curve fit: {[y0,a,n]}")
  58. # plt.loglog(fit_xvals,powerlaw_offset(fit_xvals, y0, a, n)-1,
  59. # label=f"Linearized fit: y={y0:.2f}+{a:.2f}/x^{n:.2f}")
  60. # plt.legend()
  61. #plt.savefig('antiperiodic_mass_gap_with_fits_loglog_(Ian).pdf')
  62. plt.show()
  63. def gradient_curvefit(xdata,ydata):
  64. """
  65. Fits a power law by first taking the numerical derivative
  66. to get rid of a constant offset, then linearizing the data
  67. to extract the power law behavior. Given the exponent, run
  68. the fit on the original data to determine the limiting behavior.
  69. Parameters
  70. ----------
  71. xdata : array of float
  72. ydata : array of float
  73. Returns
  74. -------
  75. powerlaw_params : array of float
  76. An array of three numbers:
  77. y0, the overall vertical offset
  78. a, the prefactor of the power law dependence
  79. n, the exponent in a/x**n
  80. """
  81. # the data has the form a+bx^(-n)
  82. # so the gradient has the form -bn*x^(-n-1)
  83. grad_ydata = np.gradient(ydata,xdata,edge_order=2)
  84. # taking the log to linearize, we have log(-bn) + (-n-1)*x
  85. logx = np.log10(xdata[:-1])
  86. # note that since n is positive, we have to take the log of
  87. # +bn*x^(n-1) instead
  88. logy = np.log10(-grad_ydata[:-1])
  89. linear = lambda x, m, y0: y0 + m*x
  90. popt, pcov = curve_fit(linear, logx, logy)
  91. n = -(popt[0] + 1)
  92. a = np.power(10,popt[1]) / n
  93. #print(f"n={n},a={a}")
  94. powerlaw_offset = lambda x, offset: offset + a*x**(-n)
  95. popt, pcov = curve_fit(powerlaw_offset, xdata, ydata)
  96. y0 = popt[0]
  97. #print(f"y0={popt[0]}")
  98. return [y0, a, n]
  99. if __name__ == "__main__":
  100. main()