#!/usr/bin/env python
# -*- coding: utf-8 -*-
# ====================== GEFIT 0.1 (Golem EFIT) ======================================
# plama position calculation is based on the least square fit of the signal from mirnov coils a plasma current.
#A position and new plasma current are calculated from the furmula for loop wire is calculeted mag, filed in the coils and compared
#with measured values. It should by robust and it was tested on the poor data from mirnov coils.
#magnetic filed from external coils can be calculated by setting extCoilsPos and extCoilsCurr, however it was not tested yet.
#
# Autor: Tomáš Odstrčil tomasodstrcil@gmail.com
#TODO problémy: při velké disrupci dojde k tak masivnímu skoku že selže
#integrace a nastane integrační drift na některé z cívek. Udělá to chybu v signálu i 20%
import time
#t = time.time()
from numpy import *
from numpy.linalg import norm,lstsq
#from scipy.interpolate import interpolate
from scipy.optimize import minimize
from multiprocessing import Process, Pool, cpu_count
#from Deconvolution import *
from pygolem_lite.modules import deconvolveExp
import sys
from MagFieldCalc import *
#print 'import time PP:', time.time()-t
#constants
a = 0.085 #[m]
R_0 = 0.4 #[m]
#http://www.phy.uct.ac.za/courses/python/examples/fitresonance.py
#http://www.scipy.org/doc/api_docs/SciPy.optimize.minpack.html
def directConductorApprox(B):
R = (B[3]-B[1])/(B[3]+B[1])*-0.093
Z = (B[4]-B[2])/(B[4]+B[2])*-0.093
r = hypot(Z,R)
if r > a:
Z *= a/r
R *= a/r
R+= R_0
return R,Z
def fun(x,param,B_coils,y,Bout):
#print x.shape, param
B = Bloop_analytic(x[:,0],x[:,1],param[0]+R_0,param[1],Bout)*param[2]
B += B_coils #NOTE musí být správná orientace proudů! meřených flukama
B *= x[:,2:]
y[1:] = sqrt(sum(square(B),1))
y[0] = abs(param[2])
return y
def MainCycle((tvec,data,x,sigma,Bext,extCoilsCurr)):
#print data.shape
#data = double(data)
#x = double(x)
#tvec = double(tvec)
#sigma = double(sigma)
#Bext = double(Bext)
#extCoilsCurr = double(extCoilsCurr)
#print data.shape
#exit()
N = size(data,0)
n_det = size(data,1)
position = empty((N, 2))
retrofit = empty((N,n_det))
reziduum = empty(N)
I0 = median(data[:,0])
steps = 0
y = empty(size(x,0)+1)
Bout = empty((size(x,0),2))
for t in xrange(N):
#print t
#sys.stdout.write('\r'+str(t))
#sys.stdout.flush()
if all(isfinite(sigma)):
R,Z = directConductorApprox(data[t,:])
R+=0.04
else: R,Z = R_0,0
scale = 1/array((1,1,0.5/I0)) #1/a/2
params0 = array([R-R_0,Z,data[t,0]])
if Bext == None:
B_coils = 0
else:
B_coils = dot(Bext,extCoilsCurr[t,:])
T = time.time()
#def fitfun(params):
#retrofit = fun(x,params*scale, B_coils,y,Bout)
#retrofit-= data
#retrofit/= sigma
#retrofit *=retrofit
#res = norm(retrofit)**2
#res+= norm((params*scale)[:2]/(a*1.0))**50
##res = norm((data[t,:] - fun(x,params*scale, B_coils,y,Bout))/sigma)**2+norm((params*scale)[:2]/(a*1.0))**50
#return res
fitfun = lambda params : norm((data[t,:] - fun(x,params*scale, B_coils,y,Bout))/sigma)**2+norm((params*scale)[:2]/(a*1.0))**50
res = minimize(fitfun, params0/scale, method='Nelder-Mead',options={'xtol':1e-4, 'ftol' : 1e-2})
#res = minimize(fitfun, params0*scale, method='BFGS',options={'xtol':1e-4, 'ftol' : 1e-2})
#print '\n', time.time()-T
#exit()
#sys.stdout.write('\r'+str(time.time()-T))
#sys.stdout.flush()
if not res.success:
res.x[:] = params0
res.fun = 1e6
print 'position calculation failure in ', str(tvec[t]), 's'
else:
params0 = res.x*scale
position[t,:] = (res.x*scale)[:2]
position[t,0]+= R_0
steps+= res.nfev
retrofit[t,:] = fun(x,params0,B_coils,y,Bout)
reziduum[t] = res.fun +sum(isinf(sigma))*1e4
return (position,retrofit,reziduum)
#http://www.phy.uct.ac.za/courses/python/examples/fitresonance.py
#http://www.scipy.org/doc/api_docs/SciPy.optimize.minpack.html CalcPlasmaPosition(tvec_ds,detectorPos, detectorSignal_ds, detectorDriftError, Ip_ds,IpDriftError, shot_num = shot_num)
def CalcPlasmaPosition(tvec,detectorPos, detectorSignal,detectorDriftError,
Ip,IpDriftError,extCoilsPos = None,extCoilsCurr= None ):
#očekávám stejné časové rozdělení vstupního signálu, všechny položky jsou už absolutně kalibrované, jednotky SI
print 'CalcPlasmaPosition'
t1 = time.time()
n = len(tvec)
coil_perpend=detectorPos-mean(detectorPos,axis=0)
coil_perpend[:,1]*= -1
coil_perpend=coil_perpend[:,::-1]/hypot(coil_perpend[:,1],coil_perpend[:,0])[:,None]
x = hstack((detectorPos,coil_perpend))
data = vstack((Ip, detectorSignal.T)).T
sigma = hstack((IpDriftError, detectorDriftError))
if extCoilsPos == None or extCoilsCurr == None:
Bext = None
else:
Bext = zeros(shape(detectorPos)+(size(extCoilsPos,0),))
for i in arange(size(extCoilsPos,0)):
Bext[...,i] = Bloop_analytic(x[:,0],x[:,1],extCoilsPos[i,0],extCoilsPos[i,0])
#main calculation , multiprocess
n_cpu = cpu_count()
p = Pool(n_cpu)
#split_ind = array_split(range(n), n_cpu*4)
#print data.shape
#exit()
data_spl = array_split(data, n_cpu*4,axis=0)
tvec_spl = array_split(tvec, n_cpu*4)
inputs = [(tvec_spl[i],data_spl[i],x,sigma,Bext,extCoilsCurr) for i in range(n_cpu*4)]
list_data = p.map(MainCycle,inputs )
p.close()
p.join()
list_position = list()
#list_position_dc = list()
list_retrofit = list()
list_reziduum = list()
for (position,retrofit,reziduum) in list_data:
list_position.append(position)
#list_position_dc.append(position_dc)
list_retrofit.append(retrofit)
list_reziduum.append(reziduum)
position = vstack(list_position)
#position_dc = vstack(list_position_dc)
retrofit = vstack(list_retrofit)
reziduum = hstack(list_reziduum)
radius = a-sqrt((position[:,0]-0.4)**2+position[:,1]**2)
chi2 = mean((data-retrofit)**2,axis=0)/sigma**2
print 'position calculated in %g s' % (time.time()-t1)
print 'chi2: ', chi2,' total ', norm(chi2)
return tvec, position, radius, reziduum, retrofit, data,chi2
def RemoveDriftsAuto(signal, Bt,Uloop,plasma_start,plasma_end,Bt_trigger,E_trigger, Bt_crosstalk=True, Uloop_crosstalk=False, Stabil_crosstalk=False, Trafo_effect=True ):
n_det = size(signal, 1)-1
index = 2
t_max = min(Bt[-1,0],Uloop[-1,0],signal[-1,0]) # čas po který to ty diagnostiky berou
t_min = max(Bt[0,0],Uloop[0,0],signal[0,0])
dt = mean(diff(signal[:,0]))
signal = signal[:int(t_max/dt+1),:]
tvec = signal[:,0]
n = size(tvec)
#resample to the same resolution
if Uloop_crosstalk:
i_Uloop = index
index+=1
Uloop = interp(tvec, Uloop[:,0],Uloop[:,1], left=0, right=None)
if Bt_crosstalk:
i_Bt = index
index+=1
Bt = interp(tvec, Bt[:,0],Bt[:,1], left=0, right=None)
if Trafo_effect:
t_exp = 21.2e-3 #[s]
i_Traf_res = index
Bt_conv,retrofit = deconvolveExp(Bt,-t_exp, dt,0,0)
index+=1
if Stabil_crosstalk:
i_St = index
index+=1
Bt = interp(tvec, fluke[:,0],fluke[:,1], left=0, right=None)
if isnan(plasma_start) or isnan(plasma_end):
plasma_start = Bt_trigger
plasma_end = Bt_trigger
#if removePlasmaDrift:
#drift_error = mean(cumsum((diff(signal[:,1:], axis = 0))**2, axis = 0), axis = 1)
#drift_error = hstack((0,drift_error))
#plot(drift_error)
#show()
#plot(diff(signal[:,1:], axis = 0))
#show()
#i_drift = index
#index+=1
Bt_trigger_n = argmin(abs(tvec-Bt_trigger))
E_trigger_n = argmin(abs(tvec- E_trigger))
plasma_start_n = max(argmin(abs(tvec-plasma_start)),E_trigger_n)
plasma_end_n = max(argmin(abs(tvec-plasma_end)),E_trigger_n)
interval0 = range(int(t_min/dt),Bt_trigger_n) #clean area before any trigger
interval1 = range(Bt_trigger_n+int(0.5e-3/dt), E_trigger_n) # short time between Bt and CD trigger
interval2 = range(E_trigger_n,plasma_start_n) #interval between CD trigger and breakdown
interval3 = range(plasma_end_n,n ) # interval beween plasma end and torroidal field end tyristor
interval_plasma = range(plasma_start_n,plasma_end_n) #plasma
interval = interval1+interval2+interval3 #interval used for removing of the drift
#print i
mainBasis = zeros((n, index))
if Bt_crosstalk:
mainBasis[:,i_Bt] = Bt
if Uloop_crosstalk:
mainBasis[:,i_Uloop] = Uloop
if Trafo_effect:
mainBasis[:,i_Traf_res] = Bt_conv
if Stabil_crosstalk:
mainBasis[:,i_St] = fluke
#if removePlasmaDrift:
#mainBasis[:,i_drift] = drift_error
#offset, integration drift
offset = zeros(n)
offset[interval0] = 1
mainBasis[:,0] = cumsum(offset, out = offset)
offset = ones(n)
offset[interval0] = 0
mainBasis[:,1] = cumsum(offset, out = offset)
#offset = zeros(n)
#offset[interval_plasma] = 1
#mainBasis[:,2] = cumsum(offset, out = offset)
x,res,rank,s = lstsq(mainBasis[interval,:],signal[interval,1:])
corr_signal = signal[:,1:]-dot(mainBasis, x)
res = sum((corr_signal[interval,:])**2,0)
res*= 1e15/len(interval)
res = sqrt(res)
#prepare graph
frames = list()
vlines = list()
hlines = list()
rectangles = list()
vlines.append((plasma_end*1000,'--' ))
vlines.append((plasma_start*1000,'--' ))
hlines.append(( 0, '-.'))
for i_det in arange(n_det):
curves = list()
curves.append((single(1e6*signal[:,i_det+1]),'Original signal', '--' ))
curves.append((single(1e6*corr_signal[:,i_det]), 'Corrected signal', 'k-'))
curves.append((single(1e6*dot(mainBasis[:,:2],x[:2,i_det])),'Integration offset','-' ))
if Bt_crosstalk:
curves.append((single(1e6*mainBasis[:,i_Bt]*x[i_Bt,i_det]), 'Toroidal mag. field', '-'))
if Trafo_effect:
curves.append((single(1e6*mainBasis[:,i_Traf_res]*x[i_Traf_res,i_det]),'Trafo mag. field','-'))
if Uloop_crosstalk:
curves.append((single(1e6*mainBasis[:,i_Uloop]*x[i_Uloop,i_det]),'Uloop','-'))
frames.append((1000*tvec,curves,'mc'+str(i_det*4+1)+' [ mV$\cdot$ms]','$\\chi^2$ = %2.1f'%res[i_det]))
intervals = (interval1,interval2,interval3 )
for inter in intervals:
if len(inter) == 0:
continue
(x_min,x_max) = (tvec[inter][0]*1e3, tvec[inter][-1]*1e3)
rectangles.append((x_min,x_max))
AutoRemoveGraph = (frames, vlines,hlines,rectangles)
#save projection constants
proj_file = 'mc1\tmc5\tmc9\tmc13\n'
proj_file+='drift1 [V] '+str(x[0,:])+'\n'
proj_file+='drift2 [V] '+str(x[1,:])+'\n'
if Bt_crosstalk:
proj_file+='Bt crosstalk [V/T]\t'+str(x[i_Bt,:])+'\n'
if Trafo_effect:
proj_file+='Trafo crosstalk (respons time %1.1f ms)[V/T]\t'%(1000*t_exp) +str(x[i_Traf_res,:])+'\n'
if Uloop_crosstalk:
proj_file+='Uloop (residual) crosstalk [V/V]\t'+str(x[i_Uloop,:])+'\n'
f = open('./constants/projections.txt', 'w')
f.write(proj_file)
f.close()
return vstack((tvec,corr_signal.T)).T,res,AutoRemoveGraph