swim_mominteg
¶
This is a script to calculate the moment by integration in the LSE coordinate system.
#!/usr/bin/env python
''' This is a script to calculate the moment by integration in the LSE coordinate system.
'''
import matplotlib
from math import atan2,acos,sin
from pylab import *
import os,sys
import datetime
import logging
logging.basicConfig(level=logging.INFO)
logger=logging.getLogger(__file__)
logger.setLevel(logging.DEBUG)
import dateutil
import numpy
import irfpy.swim.swim_start
from irfpy.swim.swim_start import filter
from irfpy.util.vector3d import Vector3d
from irfpy.cy1orb.pvat import getlsevec
na = 21 # Division in azimuth angle
nb = 11 # Division in elevation angle
def ___pstring(str, fp=sys.stderr):
''' A helper function to print.
'''
if fp!=None:
print(str, file=fp)
def _swim_observation_table(t0, fp=None):
''' Returns and print a table of the SWIM observation table.
The input is time. The output is a 2-D double array [N,11].
One line consists of one measurement, and the column corresponds to:
0: time (julday)
1: energy step [0-15]
2: direction step [0-15]
3: count rate [0-]
4: energy in eV
5: velocity in km/s
6-8: velocity in LSE frame (x,y,z) in km/s
9: J(E)
10: f(v)
'''
## get the count data
dat=irfpy.swim.swim_start.getdata(t0, filter=[filter.remove_isolated_one_count, filter.remove_background_5numsum])
fv_=irfpy.swim.swim_start.getvdf(t0, filter=[filter.remove_isolated_one_count, filter.remove_background_5numsum]).getData()
je_=irfpy.swim.swim_start.getdeflux(t0, filter=[filter.remove_isolated_one_count, filter.remove_background_5numsum]).getData()
jd = dat.getJd()
dat = dat.getData()
print(jd, file=sys.stderr)
print(dat, file=sys.stderr)
### For nominal energy and velocity table
etbl=irfpy.swim.SwimEnergy.EnergyTable.table().getTable()
vtbl=irfpy.swim.SwimEnergy.eV2kms(etbl)
print(etbl, file=sys.stderr)
print(vtbl, file=sys.stderr)
### For FOV of SWIM
import irfpy.swim.SwimFov
swimfov = irfpy.swim.SwimFov.SwimFov.getInstance(coords='SC')
### SWIM duty time
import irfpy.swim.SwimTime
dt=irfpy.swim.SwimTime.duty_time()
print('DT=', dt, file=sys.stderr)
### SWIM G-factor
import irfpy.swim.SwimGfact
gfact=irfpy.swim.SwimGfact.gfactor()
gf=gfact.getAbsGProtonStart()[0] ### 0 is for 0.5 keV proton
print('GF@0.5keV=', gf, file=sys.stderr)
for ie in range(16):
for id in range(16):
### Here one can get the vector of the flux in SC.
vsc=swimfov.getDirection(id)
vsc.scale(vtbl[ie])
print(id, vsc, file=sys.stderr)
### The SC vector should be converted to LSE.
vlse = getlsevec(jd, vsc)
print(vlse, file=sys.stderr)
### The J(E) and f(V) is calculated
je = je_[ie][id]
fv = fv_[ie][id]
__pstring('%.5f %2d %2d %6d %4d %7.2f %7.2f %7.2f %7.2f %10.3e %10.3e'%(jd.juld(), ie, id, dat[ie,id], etbl[ie], vtbl[ie], vlse.x, vlse.y, vlse.z, je, fv), fp=sys.stdout)
__solids={}
def swim_solid_fov(id):
''' A first attempt of SWIM solid FoV.
Returns the FoV vectors (unit vectors) of the SWIM in the SC frame correpsonding to id.
SWIM FoV is decided by a shifted normal distribution, but here
we assumed a box with sigma in the cal rep.
'''
global __solids
if id in __solids:
return __solids[id]
cent_A=array([-63.1, -54.78, -46.04, -35.46, -27.27, -17.08, -9.74, -1.32, 7.09, 14.43, 24.62, 32.81, 43.40, 52.13, 62.84, 65.41])
sigma_A=array([7.49, 6.66, 5.74, 4.66, 3.92, 3.20, 2.87, 2.70, 2.77, 3.02, 3.62, 4.28, 5.27, 6.12, 7.09, 7.30])
# #The sigma, s, is exp(-t^2/2s^2). If it is converted to HWHM, multiply 2ln(2)
# hwhm_A = sigma_A* 2*log(2)
cent_B = 0.00
sigma_B = 3.25
# hwhm_B = sigma_B * 2 * log(2)
arr_A = arange(na)
# arr_A = (2 * arr_A / (na-1.) -1 )* hwhm_A[id]
arr_A = (2 * arr_A / (na-1.) -1 )* sigma_A[id]
arr_A = arr_A + cent_A[id]
arr_A = arr_A * pi / 180.
arr_B = arange(nb)
# arr_B = (2 * arr_B / (nb-1.) -1 )* hwhm_B
arr_B = (2 * arr_B / (nb-1.) -1 )* sigma_B
arr_B = arr_B + cent_B
arr_B = arr_B * pi / 180.
### Looking direction in the SC frame is
# xsc = -cos(B) * sin(A)
# ysc = sin(B)
# zsc = cos(B) * cos(A)
fovs=[]
for ia in range(na):
for ib in range(nb):
v=Vector3d( -cos(arr_B[ib])*sin(arr_A[ia]), sin(arr_B[ib]), cos(arr_B[ib])*cos(arr_A[ia]))
fovs.append(v)
__solids[id] = fovs
return fovs
def swim_mominteg(t0, t1):
''' Integrate the ion flux over time
'''
# First, prepare the matrixes of the integration for each energy bin
# Assumption is that the s/c ram velocity is ignored.
### Matrix of the reconvolved distribution function: now fixed to be '360x180' x 16
reconfv = []
for ie in range(16):
aarr=[]
for ia in range(360):
barr=[]
for ib in range(180):
barr.append([])
aarr.append(barr)
reconfv.append(aarr)
### Obtain the observation time
import irfpy.swim.swim_start
obstime=irfpy.swim.swim_start.getobstime(timerange=[t0,t1])
### Rotate the time
for t in obstime:
logger.info('T=%s (started at %s)' % (t, datetime.datetime.now()))
### Get the corresponding data (f(v) in MKSA)
fv_=irfpy.swim.swim_start.getvdf(t, filter=[filter.remove_isolated_one_count, filter.remove_background_5numsum]).getData()
### Rotate the deflection step
for id in range(16):
logger.debug('D=%d/16 started at %s' % (id, datetime.datetime.now()))
### Velocity vector of othe observed particles in the SC frame
fov = swim_solid_fov(id)
### Rotate the energy step
for ie in range(16):
### Now we can specify the direction of the coming ion and the energy step
fv = fv_[ie][id]
for vsc in fov:
# Convert SC to LSE
v=getlsevec(t, vsc)
v.normalize()
# theta is measured from z axis
theta = acos(v.z) * 180./pi
# phi is measured from x axis. z-+x plane is 0, z-+y plane is 90
phi = ( atan2(v.y,v.x) * 180./pi + 360 ) % 360
ia = int(phi)
ib = int(theta)
reconfv[ie][ia][ib].append(fv)
# print ie, ia, ib, reconfv[ie][ia][ib]
# Then, integrate over.
# velocity step and its separation
etbl=irfpy.swim.SwimEnergy.EnergyTable.table().getTable()
vtbl=irfpy.swim.SwimEnergy.eV2kms(etbl) * 1000. ### Order in MKSA
dvtbl=zeros(16)
dvtbl[0]=(vtbl[1]-vtbl[0])/2
for i in range(1,15):
dvtbl[i]=(vtbl[i+1]-vtbl[i-1])/2
dvtbl[15]=(vtbl[15]-vtbl[14])/2
## Initialize the density for three methods.
density_by_max=0.
density_by_ave=0.
density_by_med=0.
fv_avelist = zeros([16, 360, 180]) - 1e30
for ia in range(360):
for ib in range(180):
for ie in range(16):
if len(reconfv[ie][ia][ib]) != 0:
# Averaging f(v)
fvarr = array(reconfv[ie][ia][ib])
fv_ave = fvarr.sum()/len(fvarr)
fv_max = max(fvarr)
fv_med = median(fvarr)
partial_ave = vtbl[ie] * vtbl[ie] * fv_ave * dvtbl[ie] * sin(ib*pi/180.) * (pi/180) * (pi/180)
partial_max = vtbl[ie] * vtbl[ie] * fv_max * dvtbl[ie] * sin(ib*pi/180.) * (pi/180) * (pi/180)
partial_med = vtbl[ie] * vtbl[ie] * fv_med * dvtbl[ie] * sin(ib*pi/180.) * (pi/180) * (pi/180)
# logger.debug('%d %d %d %e %e %e %e' % (ia,ib,ie,fv,partial_ave,partial_max, partial_med))
print('%d %d %d %e %e %e %d' % (ie,ia,ib,fv_ave,fv_max,fv_med,len(fvarr)))
density_by_ave=density_by_ave+partial_ave
density_by_max=density_by_max+partial_max
density_by_med=density_by_med+partial_med
fv_avelist[ie, ia, ib] = fv_ave
print('# Density (fv_ave) = %e'% density_by_ave)
print('# Density (fv_max) = %e'% density_by_max)
print('# Density (fv_med) = %e'% density_by_med)
return (density_by_ave, fv_avelist)
if __name__=='__main__':
''' Main routine to investigate the argument.
'''
import getopt
if len(sys.argv) != 3:
print('***\nUSAGE: %s t0 t1\n***' % (sys.argv[0]))
sys.exit(-1)
t0 = dateutil.parser.parse(sys.argv[1])
t1 = dateutil.parser.parse(sys.argv[2])
logger.info('Start %s' % t0)
logger.info('Stop %s' % t1)
# t0 = datetime.datetime(2009,1,25,13,50,0)
# t1 = datetime.datetime(2009,1,25,14,10,0)
# t0 = datetime.datetime(2009,1,25,14,00,0)
# t1 = datetime.datetime(2009,1,25,14,00,10)
# t0 = datetime.datetime(2009,1,25,14,50,0)
# t1 = datetime.datetime(2009,1,25,15,10,0)
import irfpy.swim.swim_start
obstime=irfpy.swim.swim_start.getobstime(timerange=[t0,t1])
# for t in obstime:
# swim_observation_table(t)
swim_mominteg(t0, t1)