Example #1
0
def test_predict_sec_above_below():
    '''
   Test SEC prediction at fixed locations relative to pole of SECS below ground
   '''
    # place SEC at north pole, 0 longitude, and 100 km altitude
    lats = np.array([90, 90])
    lons = np.array([0, 0])
    rads = np.array([6378000. + 100000., 6378000. - 100000.])
    secs_llr = np.array(list(zip(lats, lons, rads)))

    # initialize secs object
    sec_above_below = secs(secs_llr, amps=None, amps_var=None)

    # initialize secsRegressor object
    epsilon = 0.1
    secsR = secsRegressor(sec_above_below, epsilon)

    # predict magnetic disturbance at equator and at pole
    latp = np.array([0, 90])
    lonp = np.array([0, 0])
    radp = np.array([6378000., 6378000.])
    pred_llr = np.array(list(zip(latp, lonp, radp)))

    # set SEC amplitude to 10,000 Amps, and make prediction
    amps = np.array([1e4, -1e4])
    pred = secsR.predict(pred_llr, amps)

    # calculate exact solution using relationships found in Pulkinnen et al.'s
    # 2003 Earth Planets Space article "Separation of the geomagnetic variation
    # field on the ground into external and internal parts using the elementary
    # current system method"
    mu0 = 4 * np.pi * 1e-7  # N / A^2
    Btheta90 = -(mu0 * amps[0]) / (4. * np.pi * radp[0] *
                                np.sin((90-latp[0]) * np.pi/180.)) * \
       (((radp[0]/rads[0]) - np.cos((90-latp[0]) * np.pi/180.)) / \
        np.sqrt(1 - (2. * radp[0] * np.cos((90-latp[0]) * np.pi/180.)) / \
                rads[0] + (radp[0]/rads[0])**2) + \
        np.cos((90-latp[0]) * np.pi/180.) )
    Btheta90 += -(mu0 * amps[1]) / (4. * np.pi * radp[0] *
                                np.sin((90-latp[0]) * np.pi/180.)) * \
       ((radp[0] - rads[1] * np.cos((90-latp[0]) * np.pi/180.)) / \
        np.sqrt(radp[0]**2 -
                (2. * radp[0] * rads[1] * np.cos((90-latp[0]) * np.pi/180.)) + \
                rads[1]**2) - 1.)

    Brad0 = (mu0 * amps[0]) / (4. * np.pi * radp[1]) * \
        (1. / (np.sqrt(1. - 2. * radp[1] * np.cos((90-latp[1]) * np.pi/180.) / \
                       rads[0] + (radp[1] / rads[0])**2) ) - 1. )
    Brad0 += (mu0 * amps[1] * rads[1]) / (4. * np.pi * radp[1]**2) * \
        (1. / (np.sqrt(1. - 2. * rads[1] * np.cos((90-latp[1]) * np.pi/180.) / \
                       radp[1] + (rads[1] / radp[1])**2) ) - 1. )

    assert_approx_equal(pred[0, 0], Btheta90, significant=9)
    assert_approx_equal(pred[1, 2], Brad0, significant=9)
Example #2
0
def test_predict_sec_above_Bphis():
    '''
   Test SEC prediction at fixed locations relative to pole of SECS above ground;
   this test actually checks the phi (longitudinal) vector component
   '''
    # place SEC at equator, 0 longitude, and 100 km altitude
    lats = np.array([0])
    lons = np.array([0])
    rads = np.array([6378000. + 100000.])
    secs_llr = np.array(list(zip(lats, lons, rads)))

    # initialize secs object
    sec_above = secs(secs_llr, amps=None, amps_var=None)

    # initialize secsRegressor object
    epsilon = 0.1
    secsR = secsRegressor(sec_above, epsilon)

    # predict magnetic disturbance at equator, but 90 degrees east and west
    # of pole position; these are where the theta component caculated in the
    # SEC frame will equal the negative of the phi component in geographic
    # coordinates
    latp = np.array([0, 0])
    lonp = np.array([-90, 90])
    radp = np.array([6378000., 6378000.])
    pred_llr = np.array(list(zip(latp, lonp, radp)))

    # set SEC amplitude to 10,000 Amps, and make prediction
    amps = 1e4
    pred = secsR.predict(pred_llr, amps)

    # calculate exact solution using relationships found in Pulkinnen et al.'s
    # 2003 Earth Planets Space article "Separation of the geomagnetic variation
    # field on the ground into external and internal parts using the elementary
    # current system method"
    mu0 = 4 * np.pi * 1e-7  # N / A^2
    Btheta90 = -(mu0 * amps) / (4. * np.pi * radp[0] *
                                np.sin((lonp[0] - lons[0]) * np.pi/180.)) * \
       (((radp[0]/rads[0]) - np.cos((lonp[0] - lons[0]) * np.pi/180.)) / \
        np.sqrt(1 - (2. * radp[0] * np.cos((lonp[0] - lons[0]) * np.pi/180.)) / \
                rads[0] + (radp[0]/rads[0])**2) + \
        np.cos((lonp[0] - lons[0]) * np.pi/180.) )
    Bphi90minus = -Btheta90
    Bphi90plus = Btheta90

    assert_approx_equal(pred[0, 1], Bphi90minus, significant=9)
    assert_approx_equal(pred[1, 1], Bphi90plus, significant=9)
Example #3
0
def test_fit_sec_above_below():
    '''
   Fit uncorrupted B-field predictions generated by known SECs above and below
   the pole
   '''
    # place SEC at north pole, 0 latitude, and 100 km altitude
    lats = np.array([90, 90])
    lons = np.array([0, 0])
    rads = np.array([6378000. + 100000., 6378000. - 100000.])
    secs_llr = np.array(list(zip(lats, lons, rads)))

    # initialize secs object
    sec_above_below = secs(secs_llr, amps=None, amps_var=None)

    # initialize secsRegressor object
    epsilon = 0.1
    secsR = secsRegressor(sec_above_below, epsilon)

    # predict magnetic disturbance at equator and at pole
    latp = np.linspace(90, 0, 901)
    lonp = np.zeros(latp.shape)
    radp = np.zeros(latp.shape) + 6378000.
    pred_llr = np.array(list(zip(latp, lonp, radp)))

    # set SEC amplitude to 10,000 Amps, and make prediction
    amps = np.array([1e4, -1e4])
    pred = secsR.predict(pred_llr, amps)

    # fit the 2 SECs assuming 1nT uncertainty on observations
    secsR.fit(pred_llr, pred, np.ones(pred.shape) * 1e-9)

    assert_approx_equal(secsR.secs_.amps[0], 10000., significant=9)
    assert_approx_equal(secsR.secs_.amps[1], -10000., significant=9)

    assert_approx_equal(np.sqrt(secsR.secs_.amps_var[0]),
                        286.46658513,
                        significant=9)
    assert_approx_equal(np.sqrt(secsR.secs_.amps_var[1]),
                        299.97580929,
                        significant=9)
Example #4
0
def test_regress_construct():
    '''
   Test construction of secs regressor
   '''
    # place SEC at north pole, 0 latitude, and 100 km altitude
    lats = np.array([90])
    lons = np.array([0])
    rads = np.array([6378000 + 100000])
    secs_llr = np.array(list(zip(lats, lons, rads)))

    # initialize secs object
    sec1 = secs(secs_llr, amps=None, amps_var=None)

    # initialize secsRegressor object
    epsilon = 0.1
    secsR = secsRegressor(sec1, epsilon)

    assert_equal(secsR.secs.n_secs, 1)
    assert_equal(secsR.secs.latitude, 90)
    assert_equal(secsR.secs.longitude, 0)
    assert_equal(secsR.secs.radius, 6378000 + 100000)
    assert_equal(secsR.epsilon, 0.1)
Example #5
0
              for good in np.isfinite(dist_Z.data)]])

    # end 'for ob in stations:'

    # necessary to remove these outside the loop due to implicit loop indexing
    for bo in badObs:
        iagaCodes.remove(bo)

    # convert lists to numpy arrays with time varying along axis 0
    obs_lat_lon_r = np.transpose(obs_lat_lon_r, (0, 1))  # time-invariant
    obs_Btheta_Bphi_Br = np.transpose(obs_Btheta_Bphi_Br, (2, 0, 1))
    obs_sigma_Btheta_Bphi_Br = np.transpose(obs_sigma_Btheta_Bphi_Br,
                                            (2, 0, 1))

    # initialize the secs object and secsRegressor
    imp = secsRegressor(secs(secs_lat_lon_r), epsilon)

    # Finally, generate a map for each time step
    X = []
    Y = []
    Z = []
    for tidx in np.arange(len(obs_Btheta_Bphi_Br)):

        # these element-wise comparisons help avoid re-calculation of various
        # imp attributes that would be much more computationally intensive
        if np.array_equal(obs_Btheta_Bphi_Br[tidx], imp.obs_Btheta_Bphi_Br_):
            obs_Bt_Bp_Br = imp.obs_Btheta_Bphi_Br_
        else:
            obs_Bt_Bp_Br = obs_Btheta_Bphi_Br[tidx]
        if np.array_equal(obs_sigma_Btheta_Bphi_Br[tidx],
                          imp.obs_sigma_Btheta_Bphi_Br_):