#!/usr/bin/env python
# -*- coding: utf-8 -*-
import matplotlib
#matplotlib.rcParams['backend'] = 'TkAgg'
#matplotlib.rcParams['backend'] = 'WXAgg'
#matplotlib.rcParams['backend'] = 'GTKAgg'
#matplotlib.rcParams['backend'] = 'QtAgg'
##matplotlib.rcParams['backend'] = 'Qt4Agg'
matplotlib.rcParams['backend'] = 'Agg'
#TODO vypočátávat raději crosscoherenci?
from matplotlib.pyplot import *
from numpy import *
import os
from scipy import signal
from scipy.signal import fftconvolve
from multiprocessing import Process, Pool, cpu_count
import time
from scipy.stats.mstats import mquantiles
import matplotlib.animation as manimation
import re
from CWT import cwt
from fftshift import fftshift
from SoundGenerator import soundGenerator
from numexpr import evaluate
global mirnov, ring
mirnov = True
ring=False
animation = False
RingCoilOrientation = {12000:(-1,1,1,1,-1,1,-1,-1,-1,1,-1,1,-1,-1,-1,-1),
0:(-1,-1,1,1,-1,1,-1,1,-1,1,-1,-1,-1,-1,-1,-1),
18000:(+1,+1,-1,-1,+1,-1,+1,-1,+1,-1,+1,+1,+1,+1,+1,-1) }
MirnovCoilOrientation = array((-1,-1,1,1))
MirnovEffectiveArea = array((1,1,1,1))
EffectiveArea = {12000:[ 0.00209134 , 0.00446023 , 0.00428289 ,0.00374073 , 0.00320856 , 0.00182771,
0.00267794, 0.00284156 , 0.00145525 ,0.00222005 ,0.00206269 , 0.00108452,
0.00054154 , 0.00078395 , 0.00186135 , 0.00274475],
18000:[ 0.00209134 , 0.00446023 , 0.00428289 ,0.00374073 , 0.00320856 , 0.00182771,
0.00267794, 0.00284156 , 0.00145525 ,0.00222005 ,0.00206269 , 0.00108452,
0.00054154 , 0.00078395 , 0.00186135 , 0.00274475],
1:[ 0.00209134 , 0.00446023 , 0.00428289 ,0.00374073 , 0.00320856 , 0.00252771,
0.00267794, 0.00284156 , 0.00145525 ,0.00222005 ,0.00206269 , 0.00005452,
0.00254154 , 0.00078395 , 0.00186135 , 0.00274475],
0:[ 2.45766087e-03 , 3.33461911e-03 , 3.21871869e-03 , 4.5e-03,
2.39870295e-03 , 3.99826880e-03 , 3.47274534e-03 , 3.93465853e-03,
2.25236901e-03 , 3.22086160e-03 , 3.27836414e-03 , 6.87539836e-05,
3.77966762e-03 , 1.78949877e-03 , 3.19212003e-03 , 3.50243652e-03]}
def smooth(x,window_len=11,window='hanning',axis=-1):
if not x.ndim in (1,2):
raise ValueError, "smooth only accepts 1 or 2 dimension arrays."
if x.shape[axis] < window_len:
raise ValueError, "Input vector needs to be bigger than window size."
if window_len < 3:
return x
x = atleast_2d(x)
x = swapaxes(x, -1, axis)
y = empty_like(x)
if isinstance(window, str) or type(window) is tuple:
w = signal.get_window(window, window_len)
else:
w = np.asarray(window)
if len(w.shape) != 1:
raise ValueError('window must be 1-D')
if w.shape[0] > x.shape[-1]:
raise ValueError('window is longer than x.')
window_len = w.shape[0]
for i in range(x.shape[0]):
s=r_[2*x[i,0]-x[i,window_len-1::-1],x[i,:],2*x[i,-1]-x[i,-1:-window_len:-1]]
y[i,:]=fftconvolve(s,w/w.sum(),mode='same')[window_len:-window_len+1]
y = swapaxes(y, -1, axis)
return squeeze(y)
class LogFormatterTeXExponent(LogFormatter, object):
"""Extends pylab.LogFormatter to use
tex notation for tick labels."""
def __init__(self, *args, **kwargs):
super(LogFormatterTeXExponent,
self).__init__(*args, **kwargs)
def __call__(self, *args, **kwargs):
"""Wrap call to parent class with
change to tex notation."""
label = super(LogFormatterTeXExponent,
self).__call__(*args, **kwargs)
label = label.replace('-','')
x = float(label)
if abs(log10(x)) >2:
label = re.sub(r'e(\S)0?(\d+)',r'\\cdot 10^{\1\2}',str(label))
label = "$" + label + "$"
else:
n = max(0,-int(log10(x)-1))
label = ('$%.'+str(n)+'f$')%x
return label
def mad(x,axis = -1):
#Median absolute deviation
m = np.median(x,axis=axis)
x = np.swapaxes(x, 0, axis)
s = np.median(abs(x-m),axis=0)*1.4826
return s
def DFT(x, y,nf):
Ftheta = arange(-nf/2,nf/2)
E = exp(-1j*outer(Ftheta,x))
#print y.shape, E.shape, nf, linalg.pinv(E).shape,Ftheta.shape, x.shape
Fx_ = dot(y,conj(linalg.pinv(E)))*nf
return Fx_
def LoadSignal2():
from pygolem_lite import Shot
from pygolem_lite.modules import list2array,deconvolveExp,save_adv,saveconst
global mirnov, ring
#print ring, mirnov
Data = Shot()
gd = Shot().get_data
Ring,Mirnov = None,None
#gd('any', return_channel = True)
#tvec, data = gd('NIoctopus', return_channel = False)
#print das
#print data
#exit()
try:
if ring:
tvec, Ring = gd('NIoctopus', return_channel = False)
#Ring = list2array( Data[das, range(16)] )
#tvec,Ring = Ring[:,0],Ring[:,1:]
except Exception as e:
ring = False
print 'No data from ring', e
#if mirnov:
#das, m1 = gd('any', 'mirnov_1', return_channel = True)
#das, m5 = gd('any', 'mirnov_5', return_channel = True)
#das, m9 = gd('any', 'mirnov_9', return_channel = True)
#das, m13 = gd('any', 'mirnov_13', return_channel = True)
#Mirnov = list2array( Data[das, [m1, m5, m9, m13]] )
##tve
#exit()
try:
if mirnov:
das, m1 = gd('any', 'mirnov_1', return_channel = True)
das, m5 = gd('any', 'mirnov_5', return_channel = True)
das, m9 = gd('any', 'mirnov_9', return_channel = True)
das, m13 = gd('any', 'mirnov_13', return_channel = True)
Mirnov = list2array( Data[das, [m1, m5, m9, m13]] )
tvec,Mirnov = Mirnov[:,0],Mirnov[:,1:]
Mirnov/= 0.0005
except:
mirnov = False
print 'no data from mirnov'
shot = Data.shot_num
if Ring!= None and Mirnov!= None:
data = c_[Ring, Mirnov]
elif Ring!= None:
data = Ring
else:
data = Mirnov
plasma = Data['plasma']
tstart = Data['plasma_start']
tend = Data['plasma_end']
print tvec
out = PrepareSignal(tvec, data,tstart,tend,shot)
return out
def LoadSignal(shot):
print 'loading'
from golem_data import golem_data
obj = golem_data(shot, 'niturbo')
data = obj.data
tvec = obj.tvec
tend = golem_data(shot, 'plasma_end').data
tstart = golem_data(shot, 'plasma_start').data
data2 = golem_data(shot, 'nistandard6132').data
data = c_[data, data2]/r_[ones(16),ones(4)*0.0005][None,:]
tvec, data = PrepareSignal(tvec, data,tstart,tend,shot)
return tvec, data
def PrepareSignal(tvec, data,tstart, tfinish,shot ):
print 'preparing'
if shot < 12000:
calib_shot = 0
elif shot < 18000:
calib_shot = 12000
else:
calib_shot = 18000
if shot > 12000:
if mirnov and ring:
AEff = r_[array(EffectiveArea[calib_shot]),MirnovEffectiveArea]
polarity = r_[array(RingCoilOrientation[calib_shot]),MirnovCoilOrientation]
elif mirnov:
AEff = MirnovEffectiveArea
polarity = MirnovCoilOrientation
else:
AEff = array(EffectiveArea[calib_shot])
polarity = array(RingCoilOrientation[calib_shot])
data/= (AEff*polarity)[None,:]
data = signal.detrend(data, axis=0)
data = cumsum(data, axis=0)*1e-6
N = 101
taps = signal.firwin(N, 1e3/(0.5*1e6) , window='hamming', pass_zero=True)
data -= smooth(data,window_len=101,window=taps,axis=0)
nstart = argmin(abs(tvec-tstart))
nend = argmin(abs(tvec-tfinish))
if nstart == nend: return tvec, data
data = data[nstart:nend,:]
data = signal.detrend(data, axis=0)
tvec = tvec[nstart:nend]
return tvec, data
def GenerateSound(mode_signal,modes):
#use only one "polarization" of the signal
mode_signal = real(mode_signal)
path = './mp3/'
if not os.path.exists(path): os.makedirs(path)
t2= time.time()
pool = Pool(cpu_count())
out = pool.map(soundGenerator,[(mode_signal[:,i],2000, path+'sound'+str(m)) for i,m in modes])
pool.close()
pool.join()
print 'generated sound', time.time()-t2
def PlotSpecrograms(freq, field, t, modes, logscale=True):
print 'PlotSpecrograms'
field = log(1+(field/std(field))**2)/2
vmin = amin(field)
vmax = amax(field)
fig = figure('spectrogram')
ax = fig.add_axes([0.1, 0.1, 0.8, 0.85])
if logscale:
ax.set_yscale('log', nonposy='clip')
ax.yaxis.set_minor_formatter(LogFormatterTeXExponent(base=10,
labelOnlyBase=False))
ax.yaxis.set_major_formatter(LogFormatterTeXExponent(base=10,
labelOnlyBase=False))
img = ax.imshow(zeros((1,1)), extent=[t[0]*1e3,t[-1]*1e3 ,freq[-1]/1e3, freq[0]/1e3], aspect='auto',vmin=vmin, vmax=vmax,interpolation='bicubic')
minorLocator = MultipleLocator(1)
ax.xaxis.set_minor_locator(minorLocator)
ax.axis([t[0]*1e3,t[-1]*1e3 ,amin(freq)/1e3, amax(freq)/1e3])
ax.set_xlabel('time [ms]')
ax.set_ylabel('Frequency [kHz]')
t = time.time()
for i,m in modes:
#print 'i:%d'%i
img.set_data((field[...,size(field,2)-i-1]))
fig.savefig('./graphs/spectrogram'+str(m)+'.png')
print 'plotted spectograms', time.time()-t
fig.clf()
def AnalyzeSpectrograms(spectrogram,tvec,fvec,fmin,fmax,log_scale=True):
print 'AnalyzeSpectrograms'
#max_freq = fvec[argmax(spectrogram, axis=0)]
#print spectrogram.shape
#exit()
n_modes = spectrogram.shape[2]
ind_freq = argmax(spectrogram, axis=0)
ind_freq = int_(signal.medfilt(ind_freq, (31,1)))
max_freq = fvec[ind_freq]
max_amplitude = amax(spectrogram, axis=0)
max_amplitude /= mean(max_amplitude)
fig = figure(figsize=(8,8))
subplots_adjust(hspace=0.05, wspace = 0)
modes = [-2, -1, 0, 1, 2]
ax = fig.add_subplot(211)
tvec_spec = linspace(tvec[0],tvec[-1], size(spectrogram,1))*1e3
#print range(min(5, n_modes-1),0,-1), max_amplitude.shape
plots = [ax.plot(tvec_spec,max_amplitude[:,i]*10)[0] for i in modes]
leg = ax.legend(plots, ['M=%d'%i for i in modes], loc='best', fancybox=True)
leg.get_frame().set_alpha(0.5)
ax.set_ylabel('Amplitude [a.u.]')
ax.xaxis.set_major_formatter(NullFormatter() )
ax.set_xlim(tvec[0]*1e3,tvec[-1]*1e3)
for label in leg.get_lines():
label.set_linewidth(3)
ax = fig.add_subplot(212)
if log_scale:
ax.set_yscale('log', nonposy='clip')
ax.yaxis.set_minor_formatter(LogFormatterTeXExponent(base=10,
labelOnlyBase=False))
ax.yaxis.set_major_formatter(LogFormatterTeXExponent(base=10,
labelOnlyBase=False))
#modes = range(min(5, n_modes-1),0,-1)
#print modes
#exit()
plots = [ax.plot(tvec_spec,max_freq[:,i]/1e3,linewidth=1)[0] for i in modes]
leg = ax.legend(plots, ['M=%d'%i for i in modes], loc='best', fancybox=True)
leg.get_frame().set_alpha(0.5)
for label in leg.get_lines():
label.set_linewidth(3)
ax.set_ylim((fmin-1)/1e3,(fmax+1)/1e3)
ax.set_xlabel('t [ms]')
ax.set_ylabel('Frequency [kHz]')
ax.set_xlim(tvec[0]*1e3,tvec[-1]*1e3)
fig.savefig('graphs/analyze.png')#,bbox_inches='tight'
close()
def AnimateSpectrogram(x,spectrogram,fvec,tvec,theta,nmods,
nch,framesamp,hopsamp,log_scale=True):
if not animation:
return
#plot animation
nt = size(x,0)
fig = figure(figsize=(10,5))
ax1 = fig.add_subplot(121)
ax2 = fig.add_subplot(122)
mag_img = ax1.imshow(zeros((framesamp,nmods/2+1 )),
extent=[fvec[0]/1e3,fvec[-1]/1e3,-nmods/2+0.5,nmods/2+0.5],aspect='auto',
animated=True,interpolation='nearest')
mag_img.set_cmap('YlOrBr')
plot2, = ax2.plot([],[], linewidth=0.3, animated=False)
ax2.set_ylim(-0.3,2*pi+0.1)
ax2.set_ylabel('poloidal angle [rad]')
ax2.axvline(x=0)
Dt = tvec[framesamp]-tvec[0]
ax2.set_xlim(-Dt/2*1e6, Dt/2*1e6)
ax2.set_xlabel('$\Delta$t [$\mu$s]')
ax1.set_xlabel('f [kHz]')
time_text = ax2.text(0.05, 0.9, '', transform=ax2.transAxes,animated=False)
ax1.yaxis.set_major_locator(MultipleLocator(1))
ax2.xaxis.grid(color='r', linestyle='-', linewidth=.2)
ax1.set_ylabel('Poloidal mode number M')
if log_scale:
ax1.set_xscale('log', nonposy='clip')
ax_format = LogFormatterTeXExponent(base=10,labelOnlyBase=False)
ax1.xaxis.set_minor_formatter(ax_format)
ax1.xaxis.set_major_formatter(ax_format)
def init():
plot2.set_data([],[])
return plot2,
t = 0
FFMpegWriter = manimation.writers['mencoder']
metadata = dict(title='NTM', artist='Matplotlib', comment='Animated CWT spectrogram')
writer = FFMpegWriter(fps=10, metadata=metadata,codec='mpeg4',bitrate=2000)
with writer.saving(fig, 'graphs/AnimCWT.mp4', 100):
for j in xrange(0, size(x,0)-framesamp, hopsamp):
i_spec = ((j+framesamp/2)*size(spectrogram,1))/nt
time_text.set_text('i=%d t=%.2fms'%(j+framesamp/2,1e3*tvec[j+framesamp/2]))
y = copy(x[j:j+framesamp, : ])
y/= mad(y,axis=0)[None,:]
image = spectrogram[:,i_spec,:].T
image = hypot(image/std(image), 1)
mag_img.set_data(image)
mag_img.set_clim(1,amax(image[nmods/2+2:,:]))
T = tile(tvec[:framesamp ]-tvec[:framesamp].mean(),(1,nch)).T
T[::framesamp] = nan
plot2.set_data(T*1e6, (y/8+theta[None,:]).T.ravel())
fps = 1/(time.time()-t)
t = time.time()
sys.stdout.write('\r plotting %2.1f%% fps:%2.1f'%(j*100./nt,fps))
sys.stdout.flush()
writer.grab_frame()
def multi_cwt(x, fs, framesz, hop,tvec=None):
framesamp = int(framesz*fs)
hopsamp = int(hop*fs)
if tvec == None:
tvec = arange(size(x,0))/fs
nt, nch = shape(x)
nmods = min(16, nch)
fmax = 8e4
fmin = 3e3
dj = 0.05 #frequency resolution of CWT
p = 10 #length of the wavelet
#calculate intensity envelope ma moving STD
filtered_std = sqrt(abs(smooth(x**2,window_len=1e3,window='hanning',axis=0)))
x /= filtered_std/mean(filtered_std,axis=1)[:,None]
#poloidal angles of the coils in the !magnetics! coordinates
global ring, mirnov
if ring and mirnov:
theta = load('phi.npy')
theta = median(theta,axis=0)
theta += 2*pi*r_[arange(16)/16.,arange(4)/4.]
elif mirnov:
theta = 2*pi*arange(4)/4.
elif ring:
theta = 2*pi*arange(16)/16.
#DFT over the channels with nonequidistant sampling
fx = DFT(theta, x,nmods)
print 'calc spectrograms'
pool = Pool(cpu_count())
out = pool.map(cwt,[(fx[:,i], 1/fs, dj, p ,nt/hopsamp, fmin,fmax) for i in range(nmods)])
pool.close()
pool.join()
freq = out[0][2][::-1]
spectrogram = [abs(out.pop()[0]) for i in range(nmods)]
spectrogram = dstack(spectrogram)
modes= zip(arange(nmods), arange(-nmods/2, nmods/2))
#create sound of the modes
GenerateSound(fx,modes)
#analyze the spectrograms
AnalyzeSpectrograms(spectrogram[::-1,...],tvec,freq,fmin,fmax )
spectrogram = spectrogram[::-1,:,::-1]
#plot spectrograms
PlotSpecrograms(freq,spectrogram,tvec,modes)
#plot animated 3d spectrograms
AnimateSpectrogram(x,spectrogram,freq,tvec,theta,nmods,nch,framesamp,hopsamp)
def calc_stft((y,w,nfmax,theta)):
y = y/mad(y,axis=0)[None,:]
#print y.shape
#exit()
fy = DFT(theta, y,16)
f = fft.fft(fy*w[:,None], axis=0)
#BUG RFFT from scipy.fftpack for singles is faster!!
#print f.shape, nfmax
return f[:nfmax,:]
def stft(x, fs, framesz, hop,tvec=None):
print 'stft'
nmods = 16
fmax = 8e4
nt, nch = x.shape
framesamp = int(2**np.ceil(np.log2(framesz*fs)))
hopsamp = int(hop*fs)
w = hamming(framesamp)
if tvec == None:
tvec = arange(size(x,0))/fs
nfmax = int(fmax/fs*framesamp)
theta = load('phi.npy')
theta = median(theta,axis=0)
theta += 2*pi*r_[arange(16)/16.,arange(4)/4.]
pool = Pool(cpu_count())
ind = xrange(0, size(x,0)-framesamp, hopsamp)
out = pool.map(calc_stft,[(x[i:i+framesamp,:],w,nfmax,theta) for i in ind])
pool.close()
pool.join()
spectrogram = [abs(out.pop()) for i in ind]
spectrogram = dstack(spectrogram)
spectrogram = swapaxes(dstack(spectrogram),0,2)
fvec = arange(framesamp)*fs/(2.*framesamp)
modes= zip(arange(nmods), arange(-nmods/2, nmods/2))
AnalyzeSpectrograms( spectrogram,tvec,fvec,0,fmax)
PlotSpecrograms([0,fmax],spectrogram[:,::-1,:], tvec,modes, logscale=False)
def LSQfit(tvec,data):
data = signal.detrend(data,axis=0)
data/= std(data,axis=0)
nch = size(data,1)
theta0 = 2*pi*r_[arange(16)/16.,arange(4)/4.]
#TODO pro každé jinou aplitudu a offset?
def Model(par,tvec,show_plt=False):
A = par[3]
f = par[0]
phi = par[1]
M = int(par[2])
if M != 0:
par[4:][par[4:] <-pi/2] +=pi/2
par[4:][par[4:] > pi/2] -=pi/2
Dtheta = par[4:]
Dtheta-= median(Dtheta)
theta = theta0[:nch]+Dtheta
model = sin(2*pi*(tvec *f)-theta[:,None]*M+phi)*A
if show_plt:
plot(model.T/2+theta0[None,:nch]/2*pi,'--',linewidth=0.3)
plot(data/2+theta0[None,:nch]/2*pi,linewidth=0.3)
return linalg.norm((model-data.T)/std(data,axis=0)[:,None])+linalg.norm(diff(Dtheta))
f = linspace(0,1e6/2, size(data,0)/2+1)
F = mean(abs(fft.rfft(data*hamming(size(data,0))[:,None],axis=0)),axis=1)
i = argmax(F)
f_max = sum((f*F)[i-1:i+2])/sum(F[i-1:i+2])
f_max = max(29000,f_max)
theta_ = median(load('phi2.npy'),axis=0)
theta__ = median(load('phi.npy'),axis=0)
x0 = r_[f_max,pi,-2,0.8,theta_[:nch]]
P, fopt, direc, _, _, warnflag = fmin_powell(Model, x0, args=(tvec,),maxiter=1e5,maxfun=1e6, xtol=1e-6, ftol=1e-6,full_output=True)
fig = figure()
title(fopt)
Model(P,tvec,show_plt=True)
fig.show()
fig =figure('phase')
plot(theta0[:16], P[4:20]-median(P[4:20]))
plot(theta0[:16], theta_[:16],':')
plot(theta0[:16], theta__[:16],'-.')
if nch == 20:
plot(theta0[16:], theta__[16:],'-.')
plot(theta0[16:20], P[20:24],'--')
xlim(0,2*pi)
fig.show()
pause(0.1)
return P[4:]
def main():
for path in ['graphs', 'mp3']:
if not os.path.exists(path):
os.mkdir(path)
if len(sys.argv)==1 or sys.argv[1] == "plots":
#tvec,sig = LoadSignal(12686)
tvec,sig = LoadSignal2()
hop = max((tvec[-1]- tvec[0])/800, 1e-5)
multi_cwt(sig, 1e6, 5e-4, hop, tvec = tvec)
from pygolem_lite.modules import saveconst
os.system('convert -resize 150x120\! graphs/spectrogram0.png icon.png')
saveconst('status', 0)
if __name__ == "__main__":
main()