tools.py 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. # -*- coding: utf-8 -*-
  2. """
  3. Created on Wed Aug 15 21:50:58 2018
  4. @author: USER
  5. """
  6. # Codes are free to use. Do whatever you want
  7. from __future__ import absolute_import
  8. """Read raw data"""
  9. ####################### LIBRARY #############################
  10. # exceptions library
  11. from exceptions import (Data_Format_Exception,
  12. Data_Match_Exception)
  13. # Python stdlib imports
  14. import datetime
  15. from math import factorial
  16. # data processing library
  17. import numpy as np
  18. # pyrod library
  19. ####################### CONSTANT ############################
  20. # constant
  21. ####################### FUNCTIONS ###########################
  22. '.......................optimise.........................'
  23. # f - fitting data
  24. # y - experiment data
  25. # mask - mask data
  26. def R_square(f, y, mask):
  27. if not len(f) == len(y) == len(mask):
  28. raise Data_Match_Exception('Please input equal length')
  29. def nplist(data):
  30. # check and transform data
  31. try:
  32. # check np array
  33. if isinstance(data, np.ndarray):
  34. pass
  35. # check list
  36. elif isinstance(data, list):
  37. rl = np.array(data)
  38. # check np mat
  39. elif isinstance(data, np.matrix):
  40. rl = np.asarray(data).reshape(-1)
  41. # for other unpoackable datatype
  42. else:
  43. # init a list first
  44. l = []
  45. # unpack raw data with for
  46. for e in data:
  47. l.append(e)
  48. # trans to np array
  49. rl = np.array(l)
  50. # unknown type
  51. except Data_Format_Exception:
  52. print('unknown data type')
  53. return rl
  54. # tranform to np array; apply mask
  55. rf, ry = nplist(f)*nplist(mask), nplist(y)*nplist(mask)
  56. # calculate r square
  57. ss_tot = np.sum((ry - np.sum(ry)/len(ry))**2)
  58. ss_res = np.sum((ry - rf)**2)
  59. r2 = 1 - ss_res/ss_tot
  60. return r2
  61. def opt_step_brute(func,x0_range,grid_size = 10,step = 2):
  62. """
  63. Brute method is much too slow and big.
  64. However, its usefull and simple. To improve it, we try to step it
  65. x0_range: range of variable, [x1-,x1+],[x2-,x2+]
  66. currently,only two axes are avaialble
  67. """
  68. # current step is 3
  69. step = 3
  70. # grid_size and step have to be integer
  71. try:
  72. grid_size = int(grid_size)
  73. step = int(step)
  74. except ValueError:
  75. raise ValueError("grid_size and step have to be of type int")
  76. # one dimensional step brute method
  77. if len(x0_range) == 1:
  78. # store func(grid_data) result
  79. grid_list0 = []
  80. x0 = np.linspace(x0_range[0][0],x0_range[0][1],grid_size)
  81. # func(grid_data)
  82. for px in range(grid_size):
  83. grid_list0.append(func(x0[px]))
  84. # store min in step1
  85. min_idx = np.argmin(grid_list0)
  86. # continue step2
  87. grid_list1 = []
  88. x1 = x0[min_idx]
  89. delta = (abs(x0_range[0][1] - x0_range[0][0]))/grid_size
  90. x2 = np.linspace(x1-delta,x1+delta,grid_size)
  91. for sx in range(grid_size):
  92. grid_list1.append(func(x2[sx]))
  93. min_step2 = x2[np.argmin(grid_list1)]
  94. elif len(x0_range) == 2:
  95. # step1: grid the x0_range
  96. min_step1 = []
  97. au = np.linspace(x0_range[0][0],x0_range[0][1],grid_size)
  98. av = np.linspace(x0_range[1][0],x0_range[1][1],grid_size)
  99. # find minimum in xu and xv grid
  100. def grid_min(xu,xv):
  101. x0_grid = np.meshgrid(xu, xv)
  102. #grid list
  103. grid_list = np.mat(np.zeros([grid_size**2,3]))
  104. idx = 0
  105. # pu-- for postion in u axes
  106. for pu in range(grid_size):
  107. # pv--for postion in v axes
  108. for pv in range(grid_size):
  109. grid_list[idx,0] = x0_grid[0][pu,pv]
  110. grid_list[idx,1] = x0_grid[1][pu,pv]
  111. grid_list[idx,2] = func([x0_grid[0][pu,pv],
  112. x0_grid[1][pu,pv]])
  113. idx = idx + 1
  114. # find the minimum in step1
  115. min_idx = np.argmin(grid_list[:,2])
  116. return grid_list[min_idx,:]
  117. # append the firt minimum before rocking
  118. min_step1.append(grid_min(au,av))
  119. # start rocking, try to avoid local minmum
  120. bu = au - (au[1]-au[0])/2
  121. bv = av - (av[1]-av[0])/2
  122. min_step1.append(grid_min(bu,bv))
  123. # step 2
  124. # step 2 new x range
  125. u_min = np.min([min_step1[0][0,0],
  126. min_step1[1][0,0]])
  127. u_max = np.max([min_step1[0][0,0],
  128. min_step1[1][0,0]])
  129. deta_u = u_max - u_min
  130. v_min = np.min([min_step1[0][0,1],
  131. min_step1[1][0,1]])
  132. v_max = np.max([min_step1[0][0,1],
  133. min_step1[1][0,1]])
  134. deta_v = v_max - v_min
  135. # new u and v
  136. cu = np.linspace(u_min-deta_u, u_min+deta_u, grid_size)
  137. cv = np.linspace(v_min-deta_v, v_min+deta_v, grid_size)
  138. min_step2 = grid_min(cu,cv).tolist()
  139. return min_step2
  140. '......................smooth.........................'
  141. def savitzky_golay(y, window_size, order, deriv=0, rate=1):
  142. """
  143. Smooth (and optionally differentiate) data with a Savitzky-Golay filter.
  144. The Savitzky-Golay filter removes high frequency noise from data.
  145. It has the advantage of preserving the original shape and
  146. features of the signal better than other types of filtering
  147. approaches, such as moving averages techniques.
  148. ----------
  149. .. [1] A. Savitzky, M. J. E. Golay, Smoothing and Differentiation of
  150. Data by Simplified Least Squares Procedures. Analytical
  151. Chemistry, 1964, 36 (8), pp 1627-1639.
  152. .. [2] Numerical Recipes 3rd Edition: The Art of Scientific Computing
  153. W.H. Press, S.A. Teukolsky, W.T. Vetterling, B.P. Flannery
  154. Cambridge University Press ISBN-13: 9780521880688
  155. """
  156. # integer value
  157. try:
  158. window_size = np.abs(np.int(window_size))
  159. order = np.abs(np.int(order))
  160. except ValueError:
  161. raise ValueError("window_size and order have to be of type int")
  162. if window_size % 2 != 1 or window_size < 1:
  163. raise TypeError("window_size size must be a positive odd number")
  164. if window_size < order + 2:
  165. raise TypeError("window_size is too small for the polynomials order")
  166. order_range = range(order+1)
  167. half_window = (window_size -1) // 2
  168. # precompute coefficients
  169. b = np.mat([[k**i for i in order_range] for k in range(-half_window, half_window+1)])
  170. m = np.linalg.pinv(b).A[deriv] * rate**deriv * factorial(deriv)
  171. # pad the signal at the extremes with
  172. # values taken from the signal itself
  173. firstvals = y[0] - np.abs( y[1:half_window+1][::-1] - y[0] )
  174. lastvals = y[-1] + np.abs(y[-half_window-1:-1][::-1] - y[-1])
  175. y = np.concatenate((firstvals, y, lastvals))
  176. return np.convolve( m[::-1], y, mode='valid')
  177. ######################## CLASSS #############################