#! /bin/env python # coding: utf8 import numpy as np import mms_tools_lib as mms import os import datetime import matplotlib.pyplot as plt import scipy.interpolate as scpinterp import scipy.optimize as scpopt class calc_harvey(object) : """ harvey algorithm routine setup with MMS initialization """ def __init__(self, orbit_files = None, data_files = None, orbite_vars = None, difftime_vars = None) : self.info = {} #self._init_default_info() if orbit_files.any : self.info['orbit_files'] = orbit_files if data_files.any : self.info['data_files'] = data_files if orbite_vars.any : self.info['orbite_vars'] = orbite_vars if difftime_vars.any : self.info['data_cross'] = difftime_vars self.satpostot = np.array([mms.donnee(fichier).get_data_as_field(varz = self.info['orbite_vars'], withtime = True) for fichier in self.info['orbit_files']]) def evaluate_harvey(self, ij = [0,0], td = None, tf = None) : if not td : td = mms.donnee(self.info['data_files'][0]).donnee['epoch'][0] if not tf : tf = mms.donnee(self.info['data_files'][0]).donnee['epoch'][-1] #ij = [0,0] def g2(ij) : t1 = td + datetime.timedelta(seconds = ij[0]) t2 = tf - datetime.timedelta(seconds = ij[1]) Btot = np.array([mms.donnee(Bsat).get_data_as_field(varz = self.info['data_cross'], t1 = t1, t2 = t2, withtime = True) for Bsat in self.info['data_files']]) res = harvey(pos_vel = self.satpostot, data_timing = Btot) return res self.harvey = g2(ij) self.results = self.harvey.results def optimize_crossing(self) : """ This function helps finding the best differential timings in order to estimate Harvey method NOTE : THIS IS TOTALLY NOT OPTIMIZED!! Many useless calls are made. and probably useless.... :( """ td = mms.donnee(self.info['data_files'][0]).donnee['epoch'][0] tf = mms.donnee(self.info['data_files'][0]).donnee['epoch'][-1] maxvar = (tf - td).total_seconds() def g(ij) : #input time in seconds to change the correlation interval, return max correlation coefficient t1 = td + datetime.timedelta(seconds = ij[0]) t2 = tf - datetime.timedelta(seconds = ij[1]) Btot = np.array([mms.donnee(Bsat).get_data_as_field(varz = self.info['data_cross'], t1 = t1, t2 = t2, withtime = True) for Bsat in self.info['data_files']]) res = harvey(data_timing = Btot, calc_harvey = False) return 1. - np.mean([max(corr) for corr in res.results['correlation_functions']]) ij = np.array([0,0]) #methodes = ['Powell' , 'L-BFGS-B', 'TNC', 'COBYLA', 'SLSQP', 'trust-ncg'] #for meth in methodes : #print 'calculating with ', meth #res = scpopt.minimize(g, ij, bounds = [(0., maxvar/2.), (0, maxvar/2.)] , method = meth) #print res self.corr = np.zeros([20,20]) for i1,i in enumerate(np.linspace(0,10,20)) : for j1,j in enumerate(np.linspace(0,10,20)) : print i1,j1 ij = [i,j] self.corr[i1,j1] = g(ij) #res = scpopt.basinhopping(g, ij, niter = 20, stepsize = 0.5) print self.corr def _init_default_info(self): self.info['orbite_vars'] = ['mec_rx_gse', 'mec_ry_gse', 'mec_rz_gse', 'mec_vx_gse', 'mec_vy_gse', 'mec_vz_gse'] self.info['data_cross'] = ['fgm_by_gse_brst_l2'] rep = 'time_table_20150908_100807_20150908_100844' baserep = os.curdir rep = os.path.join(baserep, rep) mecsat1 = os.path.join(rep, 'obj7.cef') mecsat2 = os.path.join(rep, 'obj8.cef') mecsat3 = os.path.join(rep, 'obj9.cef') mecsat4 = os.path.join(rep, 'obj10.cef') self.info['orbit_files'] = [mecsat1, mecsat2, mecsat3, mecsat4] Bsat1 = os.path.join(rep, 'obj3.cef') Bsat2 = os.path.join(rep, 'obj4.cef') Bsat3 = os.path.join(rep, 'obj5.cef') Bsat4 = os.path.join(rep, 'obj6.cef') self.info['data_files'] = [Bsat1, Bsat2, Bsat3, Bsat4] class harvey(object) : """ Differential timing calculation Input : Time + x,y,z satelite positions + vx,vy,vz satelite velocities (total = 7 columns) * 4 Satellites * N data This must be provided as a numpy array such as : pos_vel[0,:,:] provides data for satellite 1 pos_vel[2,:,3] provides all z positions of satellite 3. Structure: pos_vel = np.zeros([n_satellites ( = 4), data size, number of expected variables ( = 7)]) data_timing: set of data used to correlate the timing, for automatic differential timings deduction Structure: data_timing[1,:,1] provide all data for satellite 2 np.zeros([n_satellite (= 4), size of data, 2 (for time and data value)]) NOTE: RESULTS ARE PROVIDED IN SELF.RESULTS """ def __init__(self, pos_vel = np.zeros([4,10,7]), data_timing = np.zeros([4,10,2]), calc_harvey = True) : self.results = {} self._time_reference = data_timing[0][0,0] self.data_timing = data_timing self._find_crossing() if calc_harvey : self.pos_vel = pos_vel self._calc() def _calc(self) : """ Methodology : 1. for all spacecraft : interpolate the position of each spacecraft at t = timing 2. find mesocentre position 3. derive distance each SC from mesocentre 4. Build covariance matrix of delta_to_mesocentre 5. """ j = 0 #### USE ONLY FIRST LINE OF DATA : COULD BE IMPROVED! new_pos = np.zeros([4,3]) for i, sc_data in enumerate(self.pos_vel) : delta_t = (self.timing[i] - sc_data[:,0])[j].total_seconds() new_pos[i,:] = sc_data[j,1:4] + sc_data[j,4:7] * delta_t pos_vel_meso = new_pos.mean(axis = 0) #print 'pos mesocentre : ', '\n', pos_vel_meso #### à vérifier : calcul de delta_sc_pos : utiliser new pos ou old pos? delta_sc_pos = new_pos[:,:] - pos_vel_meso[:] #print 'delta sc to meso : ', '\n', delta_sc_pos matrice = np.mat(np.zeros([3,3])) for i in range(3) : for j in range(3) : matrice[i,j] = (delta_sc_pos[:,i] * delta_sc_pos[:,j]).mean() invr = np.linalg.inv(matrice) vect_base = np.zeros(3) for i in range(3) : for j in range(3) : vect_base[i] = vect_base[i] + (self.timing_seconds[:] * delta_sc_pos[:,j]).mean() * invr[i,j] self.results['normal_velocity'] = 1./np.linalg.norm(vect_base) self.results['normal_vector'] = vect_base * self.results['normal_velocity'] def _find_crossing(self, bestfit = False) : """ 1. interpolation des données de B2,3 et 4 sur abscisse de 1 2. Input data to self.getDiffTiming() """ data = np.zeros([4, len(self.data_timing[0][:,0])]) data[0,:] = self.data_timing[0][:,1] for i, sc_data in enumerate(self.data_timing[1:]): data[i+1,:] = mms.time_interpolation(self.data_timing[0][:,0], sc_data[:,0], sc_data[:,1]) if bestfit : ind = self.search_best_fit() self.getDiffTiming(time_axis = self.data_timing[0][ind:-ind,0], data = data[:,ind:-ind]) else : self.getDiffTiming(time_axis = self.data_timing[0][:,0], data = data) def getDiffTiming(self, time_axis = np.zeros(100), data = np.zeros([4,100])): """ Input time_axis = refence time abscisse Input data = all interpolated data for all spacecraft """ self.timing = [] self.results['differential_timings'] = [] self.results['correlation_functions'] = [] ord1 = self._normalize(data[0,:])/len(data[0,:]) for sc in data: res = np.correlate(ord1, sc, mode = 'same') self.timing.append(time_axis[res.argmax()]) self.results['correlation_functions'].append(res) self.results['differential_timings'] = np.array([(time - self.timing[0]).total_seconds() for time in self.timing]) self.timing_seconds = np.array([(time - self._time_reference).total_seconds() for time in self.timing]) #FOR SC position interpolation!! def _normalize(self, data) : return (data - data.mean())/data.std() def search_best_fit(self, n = 10): """ Search for best correlation coefficient Method: cut data into n time blocks 1st step: calculate correlation coefficient 2nd step: remove extreme left and right blocks -> recorrelate 3rd: repeat """ block = int(len(self.data_timing[0][:,0]) / (2.*n)) maxcorr = np.zeros([n,4]) # Set all data to same time axis (the one of Sat1): data = np.zeros([4, len(self.data_timing[0][:,0])]) data[0,:] = self.data_timing[0][:,1] for i, sc_data in enumerate(self.data_timing[1:]): data[i+1,:] = mms.time_interpolation(self.data_timing[0][:,0], sc_data[:,0], sc_data[:,1]) maxcorr[0,:] = [np.correlate(self._normalize(data[0,:])/len(data[0,:]), self._normalize(data[i,:])).max() for i in [0,1,2,3]] for j in range(1,n): d = block*j maxcorr[j,:] = [np.correlate(self._normalize(data[0, d:-d])/len(data[0,d:-d]), self._normalize(data[i, d:-d]), 'same').max() for i in [0,1,2,3]] best_indice = np.array([np.linalg.norm(i) for i in maxcorr]).argmax() return block*best_indice def plot(self) : plt.figure() barre = [self.data_timing[0][:,1].min(), self.data_timing[0][:,1].max()] for i, champ in enumerate(self.data_timing) : plt.plot(champ[:,0], champ[:,1], label = str(i)) plt.plot([self.timing[i], self.timing[i]], barre) plt.legend() plt.show() def plot_hodo(self) : champ2 = mms.time_interpolation(self.data_timing[0][:,0], self.data_timing[1][:,0], self.data_timing[1][:,1]) plt.figure() plt.plot(self.data_timing[0][:,1], champ2) plt.show() #def _find_crossing_old(self, val = 0) : #self.timing = np.array([sc_data[(sc_data[:,1] - val).argmin(), 0] for sc_data in self.data_timing]) #self.timing_seconds = np.array([(time - self.time_reference).total_seconds() for time in self.timing])