/
TDO_ultrafast_par.py
executable file
·177 lines (144 loc) · 5.53 KB
/
TDO_ultrafast_par.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Created on Thu Apr 18 15:50:17 2013
@author: X. FABREGES
"""
from scipy import int16, arange, zeros, real, fft, argmax
from scipy import pi, savetxt, fromfile, floor
from scipy.fftpack import fftfreq
import sys
import pp
#import cProfile
# Methode des trapezes modifiee : constante supprimee
def local_trapz(yarr):
''' Trapezoidal integration optimized for speed '''
slice1 = [slice(None)]
slice2 = [slice(None)]
slice1[-1] = slice(1, None)
slice2[-1] = slice(None, -1)
return ((yarr[slice1]+yarr[slice2])).sum(axis=-1)
def tdo_fft(inputfile, outputfile):
''' Perform Fourier transform and return frequency evolution '''
# Input parameters
fourier_le = 1024 # Fourier length
time_le = 1024 # timewindow
dfmin = 0.01 # Frequency resolution
dt = 2e-8 # timestep of acquisition
load_balancing = 1
# Lecture du fichier
fid = open(inputfile, 'rb')
fid.seek(512) # Skip useless header
V = fromfile(fid, int16, -1, '')
fid.close()
pstart = 1 # First timewindow
pend = int(floor((len(V)-4*fourier_le)/time_le))+1 # Last timewindow
t = arange(0, fourier_le)*dt
# Approximation of main frequency
Vf = abs(real(fft(V[0:fourier_le])))
tf = fftfreq(fourier_le, dt)
fmax = zeros((pend+2-pstart, 2))
fmax[0, 1] = tf[argmax(Vf[0:int(fourier_le/2)])]
fmax[0, 0] = time_le*dt/2
# Calculation of constants
expon = -2j*pi*t
deltaf0 = tf[1]/1000
if deltaf0 < dfmin:
deltaf0 = 10*dfmin
# Start jobs
job_server = pp.Server()
ncpus = int(job_server.get_ncpus())
serv_jobs = []
# Load-balancing
# Last processes are faster
# If nprocess = ncpus, half of the core remains mostly idle
if load_balancing == 1:
nprocess = ncpus*4
else:
nprocess = ncpus
pstart_b = pstart
for i in range(0, nprocess):
if nprocess == 1:
pend_b = pend
else:
pend_b = int(pstart_b+floor(pend/nprocess))
print(pstart_b, pend_b)
args_tuple = (pstart_b, pend_b+1, \
V[pstart_b*time_le:(pend_b+1)*time_le+fourier_le], \
dt, dfmin, deltaf0, expon, fourier_le, time_le,)
serv_jobs.append(job_server.submit(find_freq, args_tuple, \
(local_trapz,)))
pstart_b = pend_b
pstart_b = pstart
for i in range(0, nprocess):
if nprocess == 1:
pend_b = pend
else:
pend_b = int(pstart_b+floor(pend/nprocess))
fmax[pstart_b:pend_b, :] = serv_jobs[i]()
pstart_b = pend_b
# Save calculation in file
savetxt(outputfile, fmax)
job_server.print_stats()
def find_freq(ps, pe, V, dt, dfmin, deltaf0, expon, fourier_le, time_le):
'''Perform DFT of signal and return main frequency'''
from scipy import zeros, real, fft, argmax, exp, arange , cos, pi, mean
from scipy.fftpack import fftfreq
Vf = abs(real(fft(V[0:fourier_le]-mean(V[0:fourier_le]))))
tf = fftfreq(fourier_le, dt)
fmax = zeros((pe-ps, 2))
fmax[0, 1] = tf[argmax(Vf[0:int(fourier_le/2)])]
fmax[0, 0] = (ps*time_le+fourier_le/2)*dt
# Rectangular
#window = ones(fourier_le)
# Cosinus
window = arange(0, fourier_le)
window = 1-cos(window*2*pi/(fourier_le-1))
for i in xrange(1, pe-ps):
# Utilisation de la dernière valeur comme point de depart
a = fmax[i-1, 1]
V_temp = window*V[i*time_le:i*time_le+fourier_le]
# Previous frequency spectral weight
# Complex exponential time consuming
# Need a smarter way to perform this calculations
deltaf = deltaf0
essaimax = abs(local_trapz(V_temp*exp(expon*a)))
# Calculation of local derivative of Fourier transform
# If derivative positive, then search for frequency in growing direction
if abs(local_trapz(V_temp*exp(expon*(a+deltaf)))) > essaimax:
while abs(deltaf)>dfmin:
F = abs(local_trapz(V_temp*exp(expon*(a+deltaf))))
if F > essaimax:
essaimax = F
a += deltaf
else:
deltaf = -deltaf/5
if (abs(deltaf) < dfmin) and (abs(deltaf) > dfmin*4.9):
deltaf=deltaf/abs(deltaf)*1.01*dfmin
# Store frequency
fmax[i, 0:2] = [((i+ps)*time_le+fourier_le/2)*dt, a-2.5*deltaf]
# Lower frequency otherwise
else:
while abs(deltaf)>dfmin:
F = abs(local_trapz(V_temp*exp(expon*(a-deltaf))))
if F > essaimax:
essaimax = F
a -= deltaf
else:
deltaf = -deltaf/5
if (abs(deltaf) < dfmin) and (abs(deltaf) > dfmin*4.9):
deltaf=deltaf/abs(deltaf)*1.01*dfmin
# Store frequency
fmax[i, 0:2] = [((i+ps)*time_le+fourier_le/2)*dt, a+2.5*deltaf]
return fmax[1:, :]
i = 0
while i < len(sys.argv):
# Scans to extract
if sys.argv[i] == '-i':
inputf = sys.argv[i+1]
elif sys.argv[i] == '-o':
outputf = sys.argv[i+1]
i += 1
#cProfile.runctx('tdo_fft(inputfile,outputfile)', globals(),\
#locals(), 'oupsss.txt')
tdo_fft(inputf, outputf)