Advertisement
Guest User

Untitled

a guest
Jun 20th, 2019
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.75 KB | None | 0 0
  1. import numpy as np
  2. import scipy.signal
  3. import scipy.optimize
  4.  
  5.  
  6. # Daniel Burk, Michigan State University
  7.  
  8. def periodrange(range): # range is a value between 1 and 3
  9. Period = []
  10. Period.append(np.concatenate((np.arange(30.0,5.0,-5.0),np.arange(9.0,2.5,-1.5),np.arange(2.5,1.0,-0.1),[0.75,0.666,0.5,0.333,0.25,0.2,0.125]),axis=None))
  11. Period.append(np.concatenate((np.arange(20.0,10.0,-2.5),np.arange(9.0,4.0,-1.5),np.arange(4.0,2.0,-0.5),np.arange(2.0,0.5,-0.1),[0.5,0.333,0.25,0.2,0.125]),axis=None))
  12. Period.append(np.concatenate((np.arange(10.0,4.0,-1.0),np.arange(4.0,2.0,-0.5),np.arange(2.0,0.5,-0.1),[0.5,0.333,0.25,0.2,0.125,0.01,0.005]),axis=None))
  13. frequencies = (1/np.array(Period[range-1]))
  14. return(Period[range-1],frequencies)
  15.  
  16. def pazto_freq_resp(freqs, zeros, poles, scale_fac):
  17. b, a = scipy.signal.ltisys.zpk2tf(zeros, poles, scale_fac)
  18. if not isinstance(a, np.ndarray) and a == 1.0:
  19. a = [1.0]
  20. return scipy.signal.freqs(b, a, freqs * 2 * np.pi)[1]
  21. # list element 0 is frequencies
  22. # list element 1 is the complex amplitudes
  23.  
  24. def phasecalc(testresponse): # Bring in a list of complex numbers and return the angle between 90 and 270 degrees
  25. testphase = []
  26. for t in testresponse:
  27. tp = np.arctan2(t.imag , t.real) * 180. / np.pi
  28. if tp > 90.:
  29. tp = tp-360.
  30. testphase.append(tp - 90.0) # adjust phase to better match what is seen in the real world calibrations
  31. return(testphase)
  32.  
  33.  
  34. # This is the function definition that is used in the scipy.minimize function.
  35. def minimize(_var): # Uses data found in frequencies, and in response.
  36. # Make sure phase and response tables use the same subset of frequencies.
  37. p1r, p1i, p3r, p4r, p5r,z1r,z2r,z3r, scale_fac = _var
  38. new_resp = pazto_freq_resp(
  39. freqs=frequencies,
  40. zeros=np.array([0.0 + 0.0 * 1j,
  41. 0.0 + 0.0 * 1j,
  42. z1r + 0.0 * 1j,
  43. z2r + 0.0 * 1j,
  44. z3r + 0.0 * 1j], dtype=np.complex128),
  45. poles=np.array([p1r + p1i * 1j,
  46. p1r - p1i * 1j,
  47. p3r + 0.0 * 1j,
  48. p4r + 0.0 * 1j,
  49. p5r + 0.0 * 1j], dtype=np.complex128),
  50. scale_fac=scale_fac)
  51. return ((np.abs(new_resp) - np.abs(response)) ** 2).sum()
  52.  
  53.  
  54.  
  55. def getpaz(frequencies,response,Phasedeg):
  56. # frequencies = np.array([])
  57. # response = np.array9[],dtype=np.float32)
  58. # Phasedeg = []
  59. evaluation = 1.0E+09 # For evaluating how close the solution is to the original curve
  60. paz = [] # The new poles and zeros for the channels
  61.  
  62. for z in range(0,32): # iterate 32 times to find the solution that best describes the phase response.
  63. initial_x=[]
  64. X0=np.random.random(9)
  65. # Using the minimize function, find the poles & zeros solution that best describes
  66. # the instrument response as found in responses, on frequencies breakpoint "frequencies"
  67. out = scipy.optimize.minimize(
  68. fun=minimize,
  69. method="BFGS",
  70. x0=X0,
  71. options={"eps": 1e-10, "maxiter": 1e8})
  72.  
  73. x = out.x
  74. new_poles = np.array([-abs(x[0]) + abs(x[1]) * 1j,
  75. -abs(x[0]) - abs(x[1]) * 1j,
  76. -abs(x[2]) + 0.0 * 1j,
  77. -abs(x[3]) + 0.0 * 1j,
  78. -abs(x[4]) + 0.0 * 1j],
  79. dtype=np.complex128)
  80.  
  81. new_zeros = np.array([ 0.0 + 0.0 * 1j,
  82. 0.0 + 0.0 * 1j,
  83. x[5] + 0.0 * 1j,
  84. x[6] + 0.0 * 1j,
  85. x[7] + 0.0 * 1j], dtype=np.complex128)
  86. new_scale_fac = x[8]
  87. # Create the response curve that results from this theoretical new poles and zeroes solution
  88. inverted_response = pazto_freq_resp(freqs=frequencies, zeros=new_zeros, poles=new_poles,scale_fac=new_scale_fac)
  89. inphase = phasecalc(inverted_response) # phase from inverted response, listed in degrees
  90. curvefit = np.sqrt(((np.array(Phasedeg) - np.array(inphase))**2).mean()) # rmse
  91. if (curvefit) < evaluation:
  92. final_iteration = z
  93. best_poles=new_poles
  94. best_zeros=new_zeros
  95. best_scale_fac=new_scale_fac
  96. print(f'Iteration # {z}: Phase misfit drops to {curvefit}')
  97. evaluation = curvefit
  98. return(best_poles,best_zeros,best_scale_fac,evaluation,z)
  99.  
  100. def paztest_fixed():
  101. #################################### test with def #################################
  102. Component = 'LM.NE8K.MHZ'
  103. Caldate = '05/15/2019'
  104. # Frequency breakpoints within the passband of the seismometer to simulate
  105. frequencies = np.array([0.05, 0.0571, 0.0667, 0.080, 0.111, 0.133, 0.167,
  106. 0.222, 0.250, 0.286, 0.333, 0.400, 0.500, 0.526,
  107. 0.555, 0.588, 0.625, 0.666, 0.714, 0.770, 0.833,
  108. 0.910, 1.000, 1.111, 1.250, 1.429, 1.667, 2.000,
  109. 3.000, 4.000, 5.000, 8.000])
  110.  
  111. # here are the gain values for the seismometer at the above frequencies
  112. response = np.array([3.00, 4.48, 7.11, 12.28, 32.81, 56.56, 110.00, 258.43,
  113. 366.09, 542.60, 852.84, 1451.12, 2764.14, 3201.37, 3734.65,
  114. 4390.91, 5205.66, 6225.33, 7508.61, 9123.91, 11134.60,
  115. 13556.01, 16267.16, 18911.45, 20951.61, 22004.53, 22120.93,
  116. 21630.53, 20132.44, 18990.64, 17947.77, 15053.22]) #,dtype=np.float32)
  117.  
  118. # phase delay of the light beam vs. ground motion in degrees at above frequencies
  119. Phasedeg = [-6.660, -7.714, -8.880, -10.800, -14.800, -18.000, -22.200,
  120. -30.000, -33.300, -37.543, -44.400, -52.560, -66.600,
  121. -69.158, -73.800, -78.353, -83.475, -89.520, -96.429,
  122. -104.677, -114.600, -126.654, -140.760, -157.600, -175.500,
  123. -193.886, -211.560, -228.024, -254.865, -269.640, -280.080,
  124. -300.528]
  125.  
  126. best_poles,best_zeros,best_scale_fac,evaluation,final_iteration = getpaz(frequencies,response,Phasedeg)
  127.  
  128. print("n========================================")
  129. print(f"Inverted values for {Component} on caldate of {Caldate}:")
  130. print("Poles =n", best_poles)
  131. print("Zeros =n", best_zeros)
  132. print("Scale_fac = ", best_scale_fac)
  133. print(f"Evaluated misfit of phase = {evaluation} on iteration # {final_iteration}n")
  134. print("========================================")
  135.  
  136.  
  137. ############################## RUN CODE AS A DEF ######################
  138. #Component = 'LM.NE8K.MHZ'
  139. paztest_fixed()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement