apps120811_flux_recalc.mhd_lvalueΒΆ

''' Calculate L-value, dump to a file, and map it on the surface.

The L-value is calculated following the B-field.
The :func:`get_lvalue` returns the L-value, which is defined here
the fartherest point of the magnetic field line.

The data is saved into two files.

* mhd_lvalue.dat
* ganymede_lvalue.dat.gz

The data is also plotted into a figure.

.. image:: ../../../src/scripts/apps120811_flux_recalc/mhd_lvalue.png

.. autofunction:: get_lvalue
'''

import os
import sys
import logging
logging.basicConfig()
logger = logging.getLogger('mhd_lvalue.py')
import datetime
import math
import gzip
import pickle

import matplotlib.pyplot as plt
import numpy as np
import scipy as sp

from pyana.util import streamline
from pyana.pep import mhddata

def get_lvalue(lonr, latr, mf):
    ''' Return the L-value.

    L-value is defined as the "furtherest point along the B-field".

    :param lonr: Longitude in radians.
    :param latr: Latitude in radians.
    :param mf: Magnetic field object.
    :type mf: :class:`pyana.pep.mhddata.MagneticField1201`.
    :returns: L value.
    '''

    ### Bfield function
    def bfield(pos):
        ''' Return the bfield direction in x-z plane
        '''
        bx, by, bz = mf.interpolate3d(pos[0], pos[1], pos[2])
        babs = np.sqrt(bx * bx + by * by + bz * bz)
        return np.array((bx / babs, by / babs, bz / babs))

    l2value = -1

    pos = np.array([np.cos(latr) * np.cos(lonr), np.cos(latr) * np.sin(lonr), np.sin(latr)])

    ### Start tracing.
    tracer = streamline.SimpleTracing(pos, bfield, 0.02)
    for t in range(1000):
        try:
            tracer.step_forward()
            x, y, z = tracer.x, tracer.y, tracer.z
            l2 = x * x + y * y + z * z
            if l2 > l2value:
                l2value = l2
            if l2 < 1:
                break
            
        except IndexError:
            logger.warn('Index error. Stop calculation')
            break

    tracer2 = streamline.SimpleTracing(pos, bfield, -0.02)
    for t in range(1000):
        try:
            tracer2.step_forward()
            x, y, z = tracer2.x, tracer2.y, tracer2.z
            l2 = x * x + y * y + z * z
            if l2 > l2value:
                l2value = l2
            if l2 < 1:
                break
        except IndexError:
            logger.warn('Index error. Stop calculation')
            break

    return np.sqrt(l2value)


def mkdata(filename='mhd_lvalue.dat'):
    '''Main script'''

    mf = mhddata.MagneticField1201()
    mf.set_interpolate_strategy('project')

    ## Start point

    dlat = 1
    dlon = 2

    lats = np.arange(-90, 91, dlat)
    lons = np.arange(0, 361, dlon)
#    lats = np.arange(-40, 41, 10)
#    lons = np.arange(0, 361, 90)

    lvalues = np.zeros([len(lons), len(lats)]) - 1.  # Initialize by -1.

    fp = open(filename, 'w')

    for ilon in range(len(lons)):
        lonr = np.deg2rad(lons[ilon])
        for ilat in range(len(lats)):
            latr = np.deg2rad(lats[ilat])

            lvalues[ilon, ilat] = get_lvalue(lonr, latr, mf)
            print(np.rad2deg(lonr), np.rad2deg(latr), '%.3f' % lvalues[ilon, ilat], file=fp)
            print(np.rad2deg(lonr), np.rad2deg(latr), lvalues[ilon, ilat])

        fp.flush()
    fp.close()

def plotdata(filename='mhd_lvalue.dat'):
    dat = np.loadtxt(filename)   # shape of (N, 3)
    lons = np.unique(dat[:, 0]); lons.sort()
    lats = np.unique(dat[:, 1]); lats.sort()

    lvalues = dat[:, 2].reshape((len(lons), len(lats)))

    lvalues = lvalues.clip(1.1, 8)

    plt.figure()
    cntr = plt.contour(lons, lats, lvalues.T, levels=[1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 3., ])
    plt.clabel(cntr, inline=1, fontsize=10)
#    plt.colorbar(cntr)
    plt.xlabel('Longitude')
    plt.ylabel('Latitude')
    plt.title('L-value')
    plt.gca().yaxis.set_ticks(np.arange(-90, 91, 10))
    plt.grid()
    
    plt.savefig('mhd_lvalue.png')

def pickledata(filename='mhd_lvalue.dat', outfile='ganymede_lvalue.dat.gz'):
    dat = np.loadtxt(filename)
    lons = np.unique(dat[:, 0]); lons.sort()
    lats = np.unique(dat[:, 1]); lats.sort()
    lvalues = dat[:, 2].reshape((len(lons), len(lats)))
    lvalues = np.ma.masked_outside(lvalues, 0, 5)
    lvalues = lvalues.filled(-1)
    f = gzip.open(outfile, 'w')
    pickle.dump(lons, f)
    pickle.dump(lats, f)
    pickle.dump(lvalues, f)
    f.close()
    

if __name__ == "__main__":
    
    if not os.path.exists('mhd_lvalue.dat'):
        mkdata()
    plotdata()
    pickledata()