Source code for irfpy.swim.wind

''' Module to handle WIND data

Simplest way of getting the data is using :class:`WindMoon`.

If you want to take the average key parameter of the solar wind
at the Moon position, use the following syntaxes.
This sample is to get the average between 03:15 and 03:20 on
10 May 2009.

>>> t0 = datetime.datetime(2009, 5, 10, 3, 15, 0)
>>> t1 = datetime.datetime(2009, 5, 10, 3, 20, 0)
>>> tarr, ave, var = WindMoon.get_average(t0, t1)
>>> print(len(tarr))
4
>>> label = WindMoon.label_array()
>>> print('%s %.2f (%.2f)' % (label[0], ave[0], var[0]))
N 2.22 (0.07)
>>> print('%s %.2f (%.2f)' % (label[1], ave[1], var[1]))
V 433.35 (28.05)
>>> print('%s %.2f (%.2f)' % (label[2], ave[2], var[2]))
Vth 27.49 (5.75)

The data file location should be specified by the ``.irfpyrc`` file
using the entry in ``swim`` section with a name of ``windmoonpath``.
The data file should be made beforehand using
``wind2moon.py`` script.

See also the document:
ftp://space.mit.edu/pub/plasma/wind/kp_files/000_README_WIND_P_FILES.TXT

There is an interface for ACE spacecraft.
See :mod:`irfpy.swim.ace`, while the usage is a little bit different.

'''
import os
import datetime
import dateutil.parser

import logging

import io
import numpy as np

import irfpy.util.irfpyrc
import irfpy.util.timeseriesdb

import irfpy.cy1orb.MoonPos

[docs]class WindRawDataTree: ''' WIND's raw data tree ''' def __init__(self): rc = irfpy.util.irfpyrc.Rc() self.rootpath = rc.get('swim', 'windrawpath') if self.rootpath is None: raise ValueError('No entry of "swim/windrawpath"') logging.debug('Rootpath = %s' % self.rootpath) if not os.path.isdir(self.rootpath): raise IOError('No path %s found.' % self.rootpath) self.db = self.__parse_folder(self.rootpath) def __parse_folder(self, root): ''' Parse the folder. ''' db = irfpy.util.timeseriesdb.DB() for path, dirs, files in os.walk(root): for f in files: if not f.startswith('rdP'): continue fullpath = os.path.join(path, f) tt = datetime.datetime(int(f[3:7]), 1, 1) tt = tt + datetime.timedelta(days=int(f[7:10])-1) logging.debug('%s > %s' % (fullpath, tt.strftime('%FT%T'))) db.append(fullpath, tt) return db
[docs]class WindMoon: ''' An user interface. ''' windmoondatatree = None @classmethod def __loadtree(cls): ''' Load a data tree. Called internally from other interface. ''' if cls.windmoondatatree is None: cls.windmoondatatree = WindMoonDataTree()
[docs] @classmethod def get_average(cls, t0, t1): ''' Get the average of the parameters. An interface to the :mod:`WindMoonDataTree.get_average_wind_data_between`. :returns: Tuple of three arrays. The returned is 0) the array of time used with shape of (N,) where N is the number of data in between the time range [t0 t1]; 1) the array of the average of the key parameters; and 2) the array of the variance of the key parameters. The order of the key parameters can be referred to :meth:`WindMoonData.label_array`. >>> t0 = datetime.datetime(2009, 5, 1, 23, 50) >>> t1 = datetime.datetime(2009, 5, 2, 4, 30) >>> tarr, average, variance = WindMoon.get_average(t0, t1) >>> print('N %.1f' % average[0]) N 7.7 >>> print('V %.1f' % average[1]) V 298.2 >>> print('Vth %.1f' % average[2]) Vth 22.4 >>> t0 = datetime.datetime(2009, 6, 15, 23, 59, 59) >>> t1 = datetime.datetime(2009, 6, 16, 0, 0, 1) >>> tarr, average, variance = WindMoon.get_average(t0, t1) >>> print(len(tarr)) 0 >>> print(len(average)) 7 >>> print(len(variance)) 7 >>> print(average[0]) nan ''' cls.__loadtree() return cls.windmoondatatree.get_average_wind_data_between(t0, t1)
[docs] @classmethod def label_array(cls): return WindMoonData.label_array()
[docs]class WindMoonDataTree: ''' WIND's Moon data tree ''' def __init__(self): rc = irfpy.util.irfpyrc.Rc() self.rootpath = rc.get('swim', 'windmoonpath') if self.rootpath is None: raise ValueError('No entry of "swim/windmoonpath"') logging.debug('Rootpath = %s' % self.rootpath) if not os.path.isdir(self.rootpath): raise IOError('No path %s found' % self.rootpath) self.db = self.__parse_folder(self.rootpath) self.cache = {}
[docs] def get_filename(self, t): return self.db.get(t)
[docs] def get_wind_data(self, filename): ''' Get the WIND data as dictionary. 1 day data returned. ''' if not (filename in self.cache): dat = self.__readwindmoonfile(filename) self.cache[filename] = dat return self.cache[filename]
[docs] def get_average_wind_data_between(self, t0, t1): ''' Get the WIND averaged key parameters. >>> winddata = WindMoonDataTree() >>> t0 = datetime.datetime(2009, 4, 30, 23, 50) >>> t1 = datetime.datetime(2009, 5, 2, 4, 30) >>> tarr, average, variance = winddata.get_average_wind_data_between(t0, t1) The returned is 0) the array of time used with shape of (N,) where N is the number of data in between the time range [t0 t1]; 1) the array of the average of the key parameters; and 2) the array of the variance of the key parameters. The order of the key parameters can be referred to :meth:`WindMoonData.label_array`. ''' tarr, darr = self.get_wind_data_between(t0, t1) if len(tarr) == 0: nans = [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan] return [], nans, nans # darr is an array containing WindMoonData. data_array = [] for d in darr: data_array.append(d.as_array()) data_array = np.array(data_array) mean = data_array.mean(0) var = data_array.var(0) return tarr, mean, var
[docs] def get_wind_data_between(self, t0, t1): ''' Get the WIND data in the interval between t0 and t1. Return the time array and the data array. Time array is the datetime instance array and the data array is the WindMoonData instance array. >>> winddata = WindMoonDataTree() >>> t0 = datetime.datetime(2009, 4, 30, 23, 50) >>> t1 = datetime.datetime(2009, 5, 2, 4, 30) >>> tarr, darr = winddata.get_wind_data_between(t0, t1) ''' f0 = self.db.get(t0) dataarray = {} while True: logging.info('File to be read: %s' % f0) data = self.get_wind_data(f0) time = list(data.keys()) tstart = min(time) logging.debug('tstart = %s' % tstart) if tstart > t1: break for t in time: if t >= t0 and t<=t1: dataarray[t] = data[t] f0 = self.db.nextof(f0) timearray = sorted(dataarray.keys()) dataarray2 = [] for t in timearray: dataarray2.append(dataarray[t]) return timearray, dataarray2
def __readwindmoonfile(self, filename): windmoondata = {} fp = open(filename) for line in fp: winddata = WindMoonData.parse_string(line) windmoondata[winddata.tmoon] = winddata return windmoondata def __parse_folder(self, root): db = irfpy.util.timeseriesdb.DB() for path, dirs, files in os.walk(root): for f in files: if not f.startswith('wind_at_moon_'): continue if not f.endswith('.txt'): continue fullpath = os.path.join(path, f) tt = datetime.datetime(2000+int(f[13:15]), int(f[15:17]), int(f[17:19]), 0, 0, 0) db.append(fullpath, tt) return db
[docs]class WindData: ''' WIND data. >>> str='2009 354 0.00208993 377.5 -0.9312 -1.351 3.646 19.75 -1.000e+31 -377.3 -6.133 -8.901 246.1 -64.36 20.02' >>> data = WindData.parse_string(str) The data is stored as a member in the class. - yr, doy, dayfrac, t - v, ewang, nsang - n - vth - alpha - vx, vy, vz - gsex, gsey, gsez ''' def __str__(self): return self.str
[docs] @classmethod def parse_string(cls, line): vals = line.split() if len(vals) != 15: raise ValueError('No data: %s' % line) winddata = WindData() winddata.str = line.strip() winddata.yr = int(vals[0]) winddata.doy = int(vals[1]) winddata.dayfrac = float(vals[2]) winddata.t = datetime.datetime(winddata.yr, 1, 1, 0) + datetime.timedelta(days=winddata.doy-1) + datetime.timedelta(days=winddata.dayfrac) winddata.v = float(vals[3]) winddata.ewang = float(vals[4]) winddata.nsang = float(vals[5]) winddata.n = float(vals[6]) winddata.vth = float(vals[7]) winddata.alpha = float(vals[8]) winddata.vx = float(vals[9]) winddata.vy = float(vals[10]) winddata.vz = float(vals[11]) winddata.gsex = float(vals[12]) winddata.gsey = float(vals[13]) winddata.gsez = float(vals[14]) return winddata
[docs]class WindMoonData: ''' WIND data at the Moon. >>> str='2009 354 0.00208993 377.5 -0.9312 -1.351 3.646 19.75 -1.000e+31 -377.3 -6.133 -8.901 246.1 -64.36 20.02 2009-01-27 00:15:30 2009-01-27 01:30:44' >>> data = WindMoonData.parse_string(str) The data is stored as a member in the class. - yr, doy, dayfrac, t - tmoon - v, ewang, nsang - n - vth - alpha - vx, vy, vz - gsex, gsey, gsez '''
[docs] def as_array(self): ''' Return the data as numpy.array. Return 1-D array of [n, v, vth, alpha%, vx, vy, vz]. ''' arr = [self.n, self.v, self.vth, self.alpha, self.vx, self.vy, self.vz] return np.array(arr)
[docs] @classmethod def label_array(cls): ''' Return the label of the :meth:`as_array`. :returns: A string array ``['N', 'V', 'Vth', 'Alpha%', 'Vx', 'Vy', 'Vz']`` ''' return ['N', 'V', 'Vth', 'Alpha%', 'Vx', 'Vy', 'Vz']
def __str__(self): return self.str def __repr__(self): return '<WindMoonData instance: ' + str(self.as_array()[:3]) + '>'
[docs] @classmethod def parse_string(cls, line): vals = line.split() if len(vals) != 19: raise ValueError('No data: %s' % line) winddata = WindMoonData() winddata.str = line.strip() winddata.yr = int(vals[0]) winddata.doy = int(vals[1]) winddata.dayfrac = float(vals[2]) winddata.t = datetime.datetime(winddata.yr, 1, 1, 0) + datetime.timedelta(days=winddata.doy-1) + datetime.timedelta(days=winddata.dayfrac) winddata.v = float(vals[3]) winddata.ewang = float(vals[4]) winddata.nsang = float(vals[5]) winddata.n = float(vals[6]) winddata.vth = float(vals[7]) winddata.alpha = float(vals[8]) winddata.vx = float(vals[9]) winddata.vy = float(vals[10]) winddata.vz = float(vals[11]) winddata.gsex = float(vals[12]) winddata.gsey = float(vals[13]) winddata.gsez = float(vals[14]) winddata.tmoon = dateutil.parser.parse(vals[17]+'T'+vals[18]) return winddata
[docs]class Wind2Moon: moonpos = None
[docs] @classmethod def run(cls): ''' Run the WIND time shift to the Moon position. ''' w = WindRawDataTree() t0 = datetime.datetime(2009, 1, 15) t1 = datetime.datetime(2009, 8, 5) dt = datetime.timedelta(days=1) t = t0 db = WindRawDataTree().db alldata = {} while t < t1: filename = db.get(t) fp = open(filename) for line in fp: try: winddata = WindData.parse_string(line) except ValueError as e: continue if cls.moonpos is None: cls.moonpos = irfpy.cy1orb.MoonPos.MoonGse() cls.moonpos.setFromDefaultUri() moon = cls.moonpos.getGse(winddata.t) wind2moon = moon[0] - winddata.gsex * 6378. # x distance in km delt = wind2moon / winddata.vx tmoon = winddata.t + datetime.timedelta(seconds=delt) print(tmoon, winddata.t, str(winddata)) alldata[tmoon] = winddata fp.close() t += dt tlist = sorted(alldata.keys()) fp = None day = None for t in tlist: if day != t.strftime('%F'): day = t.strftime('%F') if fp is not None: fp.close() fp = open('wind_at_moon_%s.txt' % t.strftime('%y%m%d'), 'w') winddata = alldata[t] print(str(winddata), winddata.t, t, file=fp)