Source code :: deconvolution

[Return]
  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
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
#!/usr/bin/env python
# -*- coding: utf-8 -*-


# ================  HXR signal deconvolution algorithm  0.1 ============================================
#  algorithm based on the naive implementation of the blind deconvolution algorithm to increase response time of the HXR detector. 
# in the first step the peak positions are estimated by function peaksCounter
# in the second step a "back deconvolution" is done by function back_deconvolution  top find the system response function
# in the third step a really sophisticate algorithm is used for signal deconvolution. 
# in final step a function peaksCounter is used to identify peaks and prepare data for hystorogram.

# function: back_deconvolution;  data - signal from HXR detector,events_pos - some of the identified peaks,events_area - and their surface,
#	peak_width - estimated width of the response function support,lam - regularization parameter,upsample - upsampling parameter to increase resulution and precision, 
#  description - this function calculate inversion problem to the deconvolution. Therefore it is quite well conditioned. It also supports corrupted data in signal (nans), 

#function: deconvolution; data - signal from HXR detector,response  - response function of the system , 
#	win - width od the windows used for calculations,lam - regularization parameter , upsample- upsampling parameter to increase resulution and precision, 
#description - deconvolution algorithm based on minimum tikhonov information. It is nonlinear, weighted by size of the deconvoltioned signal. This way also a positiovity constrain is enforced. 
# this algorithm can deal with data currupted by nans (for example if DAS overcame its maximal range), moreover the constant offset over the window is threated. And finally an upsampling is supported. 

#Autor: Tomas Odstrcil 2012 tomasodstrcil at gmail.com


from numpy import *
from numpy import linalg
import time
from scipy import sparse
from numpy import linalg
import matplotlib
matplotlib.rcParams['backend'] = 'Qt4Agg' 
from matplotlib.pyplot import *
from scipy.interpolate import interp1d


from scikits.sparse.cholmod import cholesky, analyze, cholesky_AAt


from numpy.matlib import repmat
from numpy import *
from matplotlib.pyplot import *
from scipy.sparse import *
import time

MAD = lambda x: median(abs(x-median(x, axis = 0)), axis = 0)*1.48


def peaksCounter(signal, threshold_min,threshold_max ):
    
    """
identifikuje to peak jeden po druhém od největšího po nejmeší
    
    """
    signal = copy(signal)
        
    x0 = argmax(signal)
    peaks = list()
    std =  MAD(signal)
    signal-= median(signal)
 
    while(signal[x0] > threshold_min):
	a = signal[x0]
	
	
	xl= x0
	xr= x0
	while xl > 0 and signal[xl]>=signal[xl-1]:
	    xl-=1
	while xr+1 < len(signal) and signal[xr]>=signal[xr+1]:
	    xr+=1
		
	interv = arange(xl,xr+1)
	x0 -= (signal[x0+1]-signal[x0-1])/(signal[x0+1]-2*a+signal[x0-1])/2
	area = sum(signal[interv])
	#plot(signal[interv])
	#show()
	signal[interv] = 0
	x0 = argmax(signal)

	if a < threshold_max:	
	    peaks.append((x0,  area))
	
    return array(peaks, copy = False)
    
    
#z odhalých poloh to zkusí typnout konvoluční funkci
def back_deconvolution(  data,events_pos,events_area,peak_width,lam,upsample): #Vyřešit to nějak vážení?
    data = copy(data)
    i_nan = isnan(data)
    data-= median(data[~i_nan])
    

    n = len(data)   
    n_peaks = len(events_pos)
    lam = lam*upsample#*n_peaks**2

    npix = upsample*peak_width
    Events_matrix = sparse.lil_matrix(( n,npix))
    
    for i in range(n_peaks):
	l = max(int(events_pos[i]-20),0)
	r = min(int(events_pos[i]+80),n)
	s = int((events_pos[i]-floor(events_pos[i]))*upsample)

	for j in range(r-l):
	    Events_matrix[l+j,j*upsample+upsample-s-1] =  events_area[i]   
	    
	    
    nogaps = spdiags(int_(1-i_nan),0, n, n,format='csr')
    Events_matrix = nogaps*csc_matrix(Events_matrix)
    diag_data = ones((2,npix))
    diag_data[1,:]*=-1
    D = spdiags(diag_data, (0,1), npix, npix,format='csr')
    DD = D.T*D
    EE = Events_matrix.T*Events_matrix
    normEE = linalg.norm(EE.todense())
    
    #print lam, upsample, n_peaks, normEE/1e4

    factor = cholesky(Events_matrix.T*Events_matrix+lam*normEE/1e4*DD)
    g = squeeze(factor( Events_matrix.T*data))
    
    #plot(g)
    #show()
    #plot(data)
    #plot(Events_matrix*g)
    #show()
    return copy(g)
      
    
    
    





    
def deconvolution(data,response, win,lam,upsample):
    t_start = time.time()
    win = 2*(win/2)
    n = len(data)
    n_resp = len(response)#*upsample

    #fun = interp1d(arange(0,n_resp,upsample),response,kind='cubic',bounds_error = False,fill_value = 0)
    #response = fun(arange(n_resp))

    data-=median(data)
    response/= abs(sum(response))
    response*= upsample
    n_ext = (n/win+1)*win
    ext_signal = empty(n_ext)
    ext_signal[(n_ext-n)/2:-(n_ext-n)/2] = data
    ext_signal[:(n_ext-n)/2+1] = median(data[~isnan(data)][:win/2]) 
    ext_signal[-(n_ext-n)/2-1:] = median(data[~isnan(data)][win/2:]) 
    
    intervals = arange(0,n_ext+win/2, win/2)


    i_nan = isnan(ext_signal)
    ext_signal[i_nan] = 0

    deconv = zeros(n_ext*upsample)
    retrofit = zeros_like(ext_signal)

    
    npix = upsample*win
    diags = arange(argmax(response)-n_resp+1, argmax(response)+1)

    diag_data = repmat(response[::-1], npix,1).T
    
    
    ConvMatrix = spdiags(diag_data, diags, npix, npix,format='csc')
    
    
    ReductMatrix =  kron(eye(win,win),eye(1,upsample),format='csr')
    ConvMatrix = ReductMatrix*ConvMatrix

    #příprava dat do hlavného algoritmu na dekonvoluci, řeší se soustava Tg = f pomocí tichonovovy regularizace s nelineárním vážením bez shlazování (minimalizuje se norma g)

    T = ConvMatrix   
    f = ext_signal

    # tohle to upravuje signál tak aby se od něj automaticky odečítal konstantní offset
    a = hstack([sparse.csc_matrix(ones([win,1])), sparse.csc_matrix((win, npix-1))],format='csr')
    
    #T=T+a
    TT_ = T.T*T
    #TT = (T+a).T*(T+a)
    #factor = analyze(TT)

    
    
    g = zeros(npix)
    g = exp(-linspace(-1,1,npix )**2)
    #print sum(ConvMatrix*g), sum(g)
    #plot(g)
    #plot(ConvMatrix*g)
    #show()
    #exit()
    
    for i in range(len(intervals)-2):
	
	t0 = time.time()	

	W = ones(npix) #váhová matice
	i_nan_win = i_nan[intervals[i]:intervals[i+2]]

	gaps = spdiags(int_(i_nan_win),0, win, win,format='csr')
	
	t = time.time()
	#T0 = gaps*T
	#T0T = T0.T*T
	#dTT = T0T+T0T.T-T0.T*T0
	#TT_ = TT-dTT	
	
	#i_nan_g = hstack((i_nan_win,i_nan_win))
	#i_nan_g = reshape(i_nan_g, (1,-1))
	i_nan_g = repeat(i_nan_win, 2)
	#exit()
	factor = analyze(TT_+identity(npix,format='csc'))


	t = time.time()
	#print i
	for j in range(5):
	    #print shape(W), shape(i_nan[intervals[i]:intervals[i+2]])
	    #W[i_nan_g] = 0.001*mean(W)
	    W = sparse.spdiags(W,0, npix,npix)	    

	    factor.cholesky_inplace(TT_ +lam*W)
	    g = squeeze(factor(T.T*f[intervals[i]:intervals[i+2]]))

	    g_tmp = copy(g)
	    g_tmp[g_tmp < 0.01] = 0.01  # ořezání záporných bodů  (výsledek požadujeme jenom kladný)
	    #g_tmp[i_nan[intervals[i]:intervals[i+2]]] = 1000
	    W = mean(g_tmp)/(g_tmp)   # nová váhová matice do další iterace
	#print "time",  time.time() - t,  t-t0
	
	f_i = T*g
	if any(f_i > 0.2):
	    print sum(f_i-median(f_i))/sum(abs(f_i-median(f_i)))*2, sum(g), sum(abs(f_i-median(f_i)))

	    #plot(linspace(0,win,win),cumsum( f_i-median(f_i)))
	    #plot(linspace(0,win,win*upsample), cumsum(g*upsample))
	    #show()

	deconv[(intervals[i]+intervals[i+1])/2*upsample:(intervals[i+1]+intervals[i+2])/2*upsample] = g[len(g)/4:-len(g)/4]
	retrofit[(intervals[i]+intervals[i+1])/2:(intervals[i+1]+intervals[i+2])/2] = f_i[len(f_i)/4:-len(f_i)/4]
    print time.time()-t_start

    deconv = deconv[(n_ext-n)/2*upsample:-(n_ext-n)/2*upsample]
    retrofit = (retrofit)[(n_ext-n)/2:-(n_ext-n)/2]
    i_nan = (i_nan)[(n_ext-n)/2:-(n_ext-n)/2]

    plot(linspace(0,n,n*upsample),deconv*upsample, label = 'deconv')
    plot(linspace(0,n,n),data, label = 'raw')
    plot(linspace(0,n,n),retrofit, label = 'retrofit')
    plot(i_nan)
    legend()
    #savefig('retrofit.svgz', linewidth=0.3)
    #savefig('retrofit.png', linewidth=0.3)

    show()
    return deconv,retrofit
    
    
    
#TODO zabudovat plasma start, plasma end
    
#TODO   vážení peaků při jejich hledání, ignorování přepálených???
# spuštění algoritmu    
    
    
    

for shot_num in range(0,1):
    #data = loadtxt('HXR_')
    print 'shot_num', shot_num
    #data = loadtxt('HXR_Co.txt')
    try:
	data = loadtxt('./data/'+str(shot_num)+'/HXR_')

	
    except:
	continue
    try:
	plasma_start = loadtxt('./data/'+str(shot_num)+'/PlasmaStart')/1000
	plasma_end   = loadtxt('./data/'+str(shot_num)+'/PlasmaEnd'  )/1000
    except:
	plasma_start = 0
	plasma_end = 4e-2
	
    plasma_start_adv = max(plasma_start-1e-3,0)
    plasma_end_adv = min(plasma_end+1e-3,4e-2)

    dt  = 0.04/len(data)
    Bt_trigger = 5e-3
    data[int(Bt_trigger/dt)-100:int(Bt_trigger/dt)+200 ] = median(data[int(Bt_trigger/dt)-100:int(Bt_trigger/dt)+200 ])#remove trigger peak
 
 
 

    plot(arange(len(data))*dt, data)
    axvline(x = plasma_start)
    axvline(x = plasma_end)
    ylim(-1,10)
    data  = data[int(plasma_start_adv/dt):int(plasma_end_adv/dt) ]
    plot(arange(int(plasma_start_adv/dt), int(plasma_end_adv/dt))*dt,data)
    savefig('./graphs/'+str(shot_num)+'_data.png')
    close()
    
    
    win = 600
    upsample = 1
    peakwidth = 100
    DAS_limit = 10 #[V]
    regularization = 0.1


    peaks = peaksCounter(data,0.1,10)
    if len(peaks) == 0:
	print 'any radiation'
	continue
	
    hist(peaks[:,1],sqrt(len(peaks)))
    ylabel('counts [-]')
    xlabel('energy [keV]')
    xlim([0,amax(peaks[:,1])] )
    savefig('./graphs/'+str(shot_num)+'historogram_.png')
    #show()

    close()

    data[data > DAS_limit] = nan   #ořezané peaky
    response_fun = back_deconvolution(data,peaks[:,0],peaks[:,1],peakwidth,1e3,upsample)
    savetxt('response_fun', response_fun) 
    plot(response_fun)
    savefig('./graphs/'+str(shot_num)+'response_fun.png')  
    #show()
    close()
    savefig

    deconv,retrofit = deconvolution(data,response_fun, win,regularization,upsample)
    deconv/= upsample
    peaks = peaksCounter(deconv,0.2,10)

    hist(peaks[:,1],sqrt(len(peaks)))
    xlim([0,amax(peaks[:,1])] )
    savefig('./graphs/'+str(shot_num)+'historogram.png')
    close()

    
    #TODO vrátit číslo celkové plochy/ délkou plazmatu = průměrný vyzářený výkon

Navigation