Пример #1
0
    def test_integrated_unit_vector_components(self):
        """Test Field-Line Integrated Unit Vectors"""

        p_lats, p_longs, p_alts = gen_plot_grid_fixed_alt(550.)
        # data returned are the locations along each direction
        # the full range of points obtained by iterating over all
        # recasting alts into a more convenient form for later calculation
        p_alts = [p_alts[0]] * len(p_longs)
        zvx = np.zeros((len(p_lats), len(p_longs)))
        zvy = zvx.copy()
        zvz = zvx.copy()
        mx = zvx.copy()
        my = zvx.copy()
        mz = zvx.copy()
        bx = zvx.copy()
        by = zvx.copy()
        bz = zvx.copy()
        date = dt.datetime(2000, 1, 1)

        fcn = OMMBV.heritage.calculate_integrated_mag_drift_unit_vectors_ecef
        for i, p_lat in enumerate(p_lats):
            (tzx, tzy, tzz, tbx, tby, tbz, tmx, tmy,
             tmz) = fcn([p_lat] * len(p_longs),
                        p_longs,
                        p_alts, [date] * len(p_longs),
                        steps=None,
                        max_steps=10000,
                        step_size=10.,
                        ref_height=120.)
            (zvx[i, :], zvy[i, :],
             zvz[i, :]) = OMMBV.vector.ecef_to_enu(tzx, tzy, tzz,
                                                   [p_lat] * len(p_longs),
                                                   p_longs)
            (bx[i, :], by[i, :],
             bz[i, :]) = OMMBV.vector.ecef_to_enu(tbx, tby, tbz,
                                                  [p_lat] * len(p_longs),
                                                  p_longs)
            (mx[i, :], my[i, :],
             mz[i, :]) = OMMBV.vector.ecef_to_enu(tmx, tmy, tmz,
                                                  [p_lat] * len(p_longs),
                                                  p_longs)

        # Zonal generally eastward
        assert np.all(zvx > 0.7)

        # Meridional generally not eastward
        assert np.all(mx < 0.4)

        return
Пример #2
0
    def test_ecef_geodetic_apex_diff_plots(self):
        """Characterize uncertainty of ECEF and Geodetic transformations"""
        import matplotlib.pyplot as plt
        # on_travis = os.environ.get('ONTRAVIS') == 'True'

        p_lats, p_longs, p_alts = gen_plot_grid_fixed_alt(550.)
        # data returned are the locations along each direction
        # the full range of points obtained by iterating over all
        # recasting alts into a more convenient form for later calculation
        p_alts = [p_alts[0]] * len(p_longs)
        # set the date
        date = datetime.datetime(2000, 1, 1)
        # memory for results
        apex_x = np.zeros((len(p_lats), len(p_longs) + 1))
        apex_y = np.zeros((len(p_lats), len(p_longs) + 1))
        apex_z = np.zeros((len(p_lats), len(p_longs) + 1))
        apex_alt = np.zeros((len(p_lats), len(p_longs) + 1))
        norm_alt = np.zeros((len(p_lats), len(p_longs) + 1))

        # set up multi
        if self.dc is not None:
            import itertools
            targets = itertools.cycle(dc.ids)
            pending = []
            for i, p_lat in enumerate(p_lats):
                print (i, p_lat)
                # iterate through target cyclicly and run commands
                dview.targets = next(targets)
                pending.append(dview.apply_async(OMMBV.geodetic_to_ecef, np.array([p_lat] * len(p_longs)), p_longs,
                                                 p_alts))
            for i, p_lat in enumerate(p_lats):
                print ('collecting ', i, p_lat)
                # collect output
                x, y, z = pending.pop(0).get()

                # iterate through target cyclicly and run commands
                dview.targets = next(targets)
                pending.append(dview.apply_async(OMMBV.python_ecef_to_geodetic, x, y, z))

            for i, p_lat in enumerate(p_lats):
                print ('collecting 2', i, p_lat)
                # collect output
                lat2, lon2, alt2 = pending.pop(0).get()

                # iterate through target cyclicly and run commands
                dview.targets = next(targets)
                pending.append(dview.apply_async(OMMBV.apex_location_info, np.array([p_lat] * len(p_longs)), p_longs,
                                                 p_alts, [date] * len(p_longs),
                                                 return_geodetic=True))

                pending.append(dview.apply_async(OMMBV.apex_location_info, lat2, lon2, alt2,
                                                 [date] * len(p_longs),
                                                 return_geodetic=True))

            for i, p_lat in enumerate(p_lats):
                print ('collecting 3', i, p_lat)
                x, y, z, _, _, h = pending.pop(0).get()
                x2, y2, z2, _, _, h2 = pending.pop(0).get()
                norm_alt[i, :-1] = np.abs(h)
                apex_x[i, :-1] = np.abs(x2 - x)
                apex_y[i, :-1] = np.abs(y2 - y)
                apex_z[i, :-1] = np.abs(z2 - z)
                apex_alt[i, :-1] = np.abs(h2 - h)


        else:
            # single processor case
            for i, p_lat in enumerate(p_lats):
                print (i, p_lat)
                x, y, z = OMMBV.geodetic_to_ecef([p_lat] * len(p_longs), p_longs, p_alts)
                lat2, lon2, alt2 = OMMBV.ecef_to_geodetic(x, y, z)
                x2, y2, z2 = OMMBV.geodetic_to_ecef(lat2, lon2, alt2)
                apex_x[i, :-1] = np.abs(x2 - x)
                apex_y[i, :-1] = np.abs(y2 - y)
                apex_z[i, :-1] = np.abs(z2 - z)

        # account for periodicity
        apex_x[:, -1] = apex_x[:, 0]
        apex_y[:, -1] = apex_y[:, 0]
        apex_z[:, -1] = apex_z[:, 0]
        apex_alt[:, -1] = apex_alt[:, 0]
        norm_alt[:, -1] = norm_alt[:, 0]

        ytickarr = np.array([0, 0.25, 0.5, 0.75, 1]) * (len(p_lats) - 1)
        xtickarr = np.array([0, 0.2, 0.4, 0.6, 0.8, 1]) * len(p_longs)
        ytickvals = ['-50', '-25', '0', '25', '50']

        try:
            fig = plt.figure()
            plt.imshow(np.log10(apex_x), origin='lower')
            plt.colorbar()
            plt.yticks(ytickarr, ytickvals)
            plt.xticks(xtickarr, ['0', '72', '144', '216', '288', '360'])
            plt.title('Log ECEF-Geodetic Apex Difference (ECEF-x km)')
            plt.xlabel('Geodetic Longitude (Degrees)')
            plt.ylabel('Geodetic Latitude (Degrees)')
            plt.savefig('ecef_geodetic_apex_diff_x.pdf')
            plt.close()

            fig = plt.figure()
            plt.imshow(np.log10(apex_y), origin='lower')
            plt.colorbar()
            plt.yticks(ytickarr, ytickvals)
            plt.xticks(xtickarr, ['0', '72', '144', '216', '288', '360'])
            plt.title('Log ECEF-Geodetic Apex Difference (ECEF-y km)')
            plt.xlabel('Geodetic Longitude (Degrees)')
            plt.ylabel('Geodetic Latitude (Degrees)')
            plt.savefig('ecef_geodetic_apex_diff_y.pdf')
            plt.close()

            fig = plt.figure()
            plt.imshow(np.log10(apex_z), origin='lower')
            plt.colorbar()
            plt.yticks(ytickarr, ytickvals)
            plt.xticks(xtickarr, ['0', '72', '144', '216', '288', '360'])
            plt.title('Log ECEF-Geodetic Apex Difference (ECEF-z km)')
            plt.xlabel('Geodetic Longitude (Degrees)')
            plt.ylabel('Geodetic Latitude (Degrees)')
            plt.savefig('ecef_geodetic_apex_diff_z.pdf')
            plt.close()

            fig = plt.figure()
            plt.imshow(np.log10(apex_alt), origin='lower')
            plt.colorbar()
            plt.yticks(ytickarr, ytickvals)
            plt.xticks(xtickarr, ['0', '72', '144', '216', '288', '360'])
            plt.title('Log ECEF-Geodetic Apex Altitude Difference (km)')
            plt.xlabel('Geodetic Longitude (Degrees)')
            plt.ylabel('Geodetic Latitude (Degrees)')
            plt.savefig('ecef_geodetic_apex_diff_h.pdf')
            plt.close()

            fig = plt.figure()
            plt.imshow(np.log10(apex_alt / norm_alt), origin='lower')
            plt.colorbar()
            plt.yticks(ytickarr, ytickvals)
            plt.xticks(xtickarr, ['0', '72', '144', '216', '288', '360'])
            plt.title('Log ECEF-Geodetic Apex Normalized Altitude Difference (km)')
            plt.xlabel('Geodetic Longitude (Degrees)')
            plt.ylabel('Geodetic Latitude (Degrees)')
            plt.savefig('ecef_geodetic_apex_norm_diff_h.pdf')
            plt.close()

        except:
            pass
Пример #3
0
    def test_apex_fine_max_step_diff_plots(self):
        """Test apex location info for sensitivity to fine_steps parameters"""
        import matplotlib.pyplot as plt
        # on_travis = os.environ.get('ONTRAVIS') == 'True'

        p_lats, p_longs, p_alts = gen_plot_grid_fixed_alt(550.)
        # data returned are the locations along each direction
        # the full range of points obtained by iterating over all
        # recasting alts into a more convenient form for later calculation
        p_alts = [p_alts[0]] * len(p_longs)
        # set the date
        date = datetime.datetime(2000, 1, 1)
        # memory for results
        apex_lat = np.zeros((len(p_lats), len(p_longs) + 1))
        apex_lon = np.zeros((len(p_lats), len(p_longs) + 1))
        apex_alt = np.zeros((len(p_lats), len(p_longs) + 1))
        apex_z = np.zeros((len(p_lats), len(p_longs) + 1))
        norm_alt = np.zeros((len(p_lats), len(p_longs) + 1))

        # set up multi
        if self.dc is not None:
            import itertools
            targets = itertools.cycle(dc.ids)
            pending = []
            for i, p_lat in enumerate(p_lats):
                print (i, p_lat)
                # iterate through target cyclicly and run commands
                dview.targets = next(targets)
                pending.append(dview.apply_async(OMMBV.apex_location_info, [p_lat] * len(p_longs), p_longs,
                                                 p_alts, [date] * len(p_longs),
                                                 fine_max_steps=5,
                                                 return_geodetic=True))
                pending.append(dview.apply_async(OMMBV.apex_location_info, [p_lat] * len(p_longs), p_longs,
                                                 p_alts, [date] * len(p_longs),
                                                 fine_max_steps=10,
                                                 return_geodetic=True))
            for i, p_lat in enumerate(p_lats):
                print ('collecting ', i, p_lat)
                # collect output
                x, y, z, _, _, h = pending.pop(0).get()
                x2, y2, z2, _, _, h2 = pending.pop(0).get()
                apex_lat[i, :-1] = np.abs(x2 - x)
                apex_lon[i, :-1] = np.abs(y2 - y)
                apex_z[i, :-1] = np.abs(z2 - z)
                apex_alt[i, :-1] = np.abs(h2 - h)

        else:
            # single processor case
            for i, p_lat in enumerate(p_lats):
                print (i, p_lat)
                x, y, z, _, _, h = OMMBV.apex_location_info([p_lat] * len(p_longs), p_longs,
                                                            p_alts, [date] * len(p_longs),
                                                            fine_max_steps=5, return_geodetic=True)
                x2, y2, z2, _, _, h2 = OMMBV.apex_location_info([p_lat] * len(p_longs), p_longs,
                                                                p_alts, [date] * len(p_longs),
                                                                fine_max_steps=10, return_geodetic=True)

                norm_alt[i, :-1] = h
                apex_lat[i, :-1] = np.abs(x2 - x)
                apex_lon[i, :-1] = np.abs(y2 - y)
                apex_z[i, :-1] = np.abs(z2 - z)
                apex_alt[i, :-1] = np.abs(h2 - h)

        # account for periodicity
        apex_lat[:, -1] = apex_lat[:, 0]
        apex_lon[:, -1] = apex_lon[:, 0]
        apex_z[:, -1] = apex_z[:, 0]
        apex_alt[:, -1] = apex_alt[:, 0]
        norm_alt[:, -1] = norm_alt[:, 0]

        idx, idy, = np.where(apex_lat > 10.)
        print('Locations with large apex x (ECEF) location differences.', p_lats[idx], p_longs[idx])

        ytickarr = np.array([0, 0.25, 0.5, 0.75, 1]) * (len(p_lats) - 1)
        xtickarr = np.array([0, 0.2, 0.4, 0.6, 0.8, 1]) * len(p_longs)
        ytickvals = ['-50', '-25', '0', '25', '50']

        try:
            fig = plt.figure()
            plt.imshow(np.log10(apex_lat), origin='lower')
            plt.colorbar()
            plt.yticks(ytickarr, ytickvals)
            plt.xticks(xtickarr, ['0', '72', '144', '216', '288', '360'])
            plt.title('Log Apex Location Difference (ECEF-x km)')
            plt.xlabel('Geodetic Longitude (Degrees)')
            plt.ylabel('Geodetic Latitude (Degrees)')
            plt.savefig('apex_loc_max_steps_diff_x.pdf')
            plt.close()

            fig = plt.figure()
            plt.imshow(np.log10(apex_lon), origin='lower')
            plt.colorbar()
            plt.yticks(ytickarr, ytickvals)
            plt.xticks(xtickarr, ['0', '72', '144', '216', '288', '360'])
            plt.title('Log Apex Location Difference (ECEF-y km)')
            plt.xlabel('Geodetic Longitude (Degrees)')
            plt.ylabel('Geodetic Latitude (Degrees)')
            plt.savefig('apex_loc_max_steps_diff_y.pdf')
            plt.close()

            fig = plt.figure()
            plt.imshow(np.log10(apex_z), origin='lower')
            plt.colorbar()
            plt.yticks(ytickarr, ytickvals)
            plt.xticks(xtickarr, ['0', '72', '144', '216', '288', '360'])
            plt.title('Log Apex Location Difference (ECEF-z km)')
            plt.xlabel('Geodetic Longitude (Degrees)')
            plt.ylabel('Geodetic Latitude (Degrees)')
            plt.savefig('apex_loc_max_steps_diff_z.pdf')
            plt.close()

            fig = plt.figure()
            plt.imshow(np.log10(apex_alt / norm_alt), origin='lower')
            plt.colorbar()
            plt.yticks(ytickarr, ytickvals)
            plt.xticks(xtickarr, ['0', '72', '144', '216', '288', '360'])
            plt.title('Log Apex Altitude Normalized Difference (km)')
            plt.xlabel('Geodetic Longitude (Degrees)')
            plt.ylabel('Geodetic Latitude (Degrees)')
            plt.savefig('apex_norm_loc_max_steps_diff_h.pdf')
            plt.close()

            fig = plt.figure()
            plt.imshow(np.log10(apex_alt), origin='lower')
            plt.colorbar()
            plt.yticks(ytickarr, ytickvals)
            plt.xticks(xtickarr, ['0', '72', '144', '216', '288', '360'])
            plt.title('Log Apex Altitude Normalized Difference (km)')
            plt.xlabel('Geodetic Longitude (Degrees)')
            plt.ylabel('Geodetic Latitude (Degrees)')
            plt.savefig('apex_loc_max_steps_diff_h.pdf')
            plt.close()

        except:
            pass
Пример #4
0
    def test_apex_plots(self):
        """Plot basic apex parameters"""
        import matplotlib.pyplot as plt

        p_lats, p_longs, p_alts = gen_plot_grid_fixed_alt(120.)
        # data returned are the locations along each direction
        # the full range of points obtained by iterating over all
        # recasting alts into a more convenient form for later calculation
        p_alts = [p_alts[0]] * len(p_longs)
        # set the date
        date = datetime.datetime(2000, 1, 1)
        # memory for results
        apex_lat = np.zeros((len(p_lats), len(p_longs) + 1))
        apex_lon = np.zeros((len(p_lats), len(p_longs) + 1))
        apex_alt = np.zeros((len(p_lats), len(p_longs) + 1))

        # set up multi
        if self.dc is not None:
            import itertools
            targets = itertools.cycle(dc.ids)
            pending = []
            for i, p_lat in enumerate(p_lats):
                print (i, p_lat)
                # iterate through target cyclicly and run commands
                dview.targets = next(targets)
                pending.append(dview.apply_async(OMMBV.apex_location_info, [p_lat] * len(p_longs), p_longs,
                                                 p_alts, [date] * len(p_longs),
                                                 return_geodetic=True))
            for i, p_lat in enumerate(p_lats):
                print ('collecting ', i, p_lat)
                # collect output
                x, y, z, olat, olon, oalt = pending.pop(0).get()
                apex_lat[i, :-1] = olat
                apex_lon[i, :-1] = olon
                apex_alt[i, :-1] = oalt

        else:
            # single processor case
            for i, p_lat in enumerate(p_lats):
                print (i, p_lat)
                x, y, z, olat, olon, oalt = OMMBV.apex_location_info([p_lat] * len(p_longs), p_longs,
                                                                     p_alts, [date] * len(p_longs),
                                                                     return_geodetic=True)
                apex_lat[i, :-1] = olat
                apex_lon[i, :-1] = olon
                apex_alt[i, :-1] = oalt

        # calculate difference between apex longitude and original longitude
        # values for apex long are -180 to 180, shift to 0 to 360
        # process degrees a bit to make the degree difference the most meaningful (close to 0)
        idx, idy, = np.where(apex_lon < 0.)
        apex_lon[idx, idy] += 360.
        idx, idy, = np.where(apex_lon >= 360.)
        apex_lon[idx, idy] -= 360.
        apex_lon[:, :-1] -= p_longs
        idx, idy, = np.where(apex_lon > 180.)
        apex_lon[idx, idy] -= 360.
        idx, idy, = np.where(apex_lon <= -180.)
        apex_lon[idx, idy] += 360.

        # account for periodicity
        apex_lat[:, -1] = apex_lat[:, 0]
        apex_lon[:, -1] = apex_lon[:, 0]
        apex_alt[:, -1] = apex_alt[:, 0]

        ytickarr = np.array([0, 0.25, 0.5, 0.75, 1]) * (len(p_lats) - 1)
        xtickarr = np.array([0, 0.2, 0.4, 0.6, 0.8, 1]) * len(p_longs)
        ytickvals = ['-25', '-12.5', '0', '12.5', '25']

        try:
            fig = plt.figure()
            plt.imshow(apex_lat, origin='lower')
            plt.colorbar()
            plt.yticks(ytickarr, ytickvals)
            plt.xticks(xtickarr, ['0', '72', '144', '216', '288', '360'])
            plt.title('Apex Latitude (Degrees) at 120 km')
            plt.xlabel('Geodetic Longitude (Degrees)')
            plt.ylabel('Geodetic Latitude (Degrees)')
            plt.savefig('apex_lat.pdf')
            plt.close()

            fig = plt.figure()
            plt.imshow(apex_lon, origin='lower')
            plt.colorbar()
            plt.yticks(ytickarr, ytickvals)
            plt.xticks(xtickarr, ['0', '72', '144', '216', '288', '360'])
            plt.title('Apex Longitude Difference (Degrees) at 120 km')
            plt.xlabel('Geodetic Longitude (Degrees)')
            plt.ylabel('Geodetic Latitude (Degrees)')
            plt.savefig('apex_lon.pdf')
            plt.close()

            fig = plt.figure()
            plt.imshow(np.log10(apex_alt), origin='lower')
            plt.colorbar()
            plt.yticks(ytickarr, ytickvals)
            plt.xticks(xtickarr, ['0', '72', '144', '216', '288', '360'])
            plt.title('Log Apex Altitude (km) at 120 km')
            plt.xlabel('Geodetic Longitude (Degrees)')
            plt.ylabel('Geodetic Latitude (Degrees)')
            plt.savefig('apex_alt.pdf')
            plt.close()
        except:
            pass
Пример #5
0
    def test_integrated_unit_vector_component_stepsize_sensitivity(self):
        """Test field-line integrated vector sensitivity."""
        p_lats, p_longs, p_alts = gen_plot_grid_fixed_alt(550.)
        # data returned are the locations along each direction
        # the full range of points obtained by iterating over all
        # recasting alts into a more convenient form for later calculation
        p_alts = [p_alts[0]] * len(p_longs)

        # zonal vector components
        # +1 on length of longitude array supports repeating first element
        # shows nice periodicity on the plots
        zvx = np.zeros((len(p_lats), len(p_longs)))
        zvy = zvx.copy()
        zvz = zvx.copy()
        #  meridional vector components
        mx = zvx.copy()
        my = zvx.copy()
        mz = zvx.copy()
        # field aligned, along B
        bx = zvx.copy()
        by = zvx.copy()
        bz = zvx.copy()
        date = dt.datetime(2000, 1, 1)
        fcn = OMMBV.heritage.calculate_integrated_mag_drift_unit_vectors_ecef
        for i, p_lat in enumerate(p_lats):
            (tzx, tzy, tzz, tbx, tby, tbz, tmx, tmy,
             tmz) = fcn([p_lat] * len(p_longs),
                        p_longs,
                        p_alts, [date] * len(p_longs),
                        steps=None,
                        max_steps=10000,
                        step_size=10.,
                        ref_height=120.)
            (zvx[i, :], zvy[i, :],
             zvz[i, :]) = OMMBV.vector.ecef_to_enu(tzx, tzy, tzz,
                                                   [p_lat] * len(p_longs),
                                                   p_longs)
            (bx[i, :], by[i, :],
             bz[i, :]) = OMMBV.vector.ecef_to_enu(tbx, tby, tbz,
                                                  [p_lat] * len(p_longs),
                                                  p_longs)
            (mx[i, :], my[i, :],
             mz[i, :]) = OMMBV.vector.ecef_to_enu(tmx, tmy, tmz,
                                                  [p_lat] * len(p_longs),
                                                  p_longs)

            # second run
            (tzx, tzy, tzz, tbx, tby, tbz, tmx, tmy,
             tmz) = fcn([p_lat] * len(p_longs),
                        p_longs,
                        p_alts, [date] * len(p_longs),
                        steps=None,
                        max_steps=1000,
                        step_size=100.,
                        ref_height=120.)
            _a, _b, _c = OMMBV.vector.ecef_to_enu(tzx, tzy, tzz,
                                                  [p_lat] * len(p_longs),
                                                  p_longs)
            # take difference with first run
            zvx[i, :] = (zvx[i, :] - _a) / zvx[i, :]
            zvy[i, :] = (zvy[i, :] - _b) / zvy[i, :]
            zvz[i, :] = (zvz[i, :] - _c) / zvz[i, :]

            _a, _b, _c = OMMBV.vector.ecef_to_enu(tbx, tby, tbz,
                                                  [p_lat] * len(p_longs),
                                                  p_longs)
            # take difference with first run
            bx[i, :] = (bx[i, :] - _a) / bx[i, :]
            by[i, :] = (by[i, :] - _b) / by[i, :]
            bz[i, :] = (bz[i, :] - _c) / bz[i, :]

            _a, _b, _c = OMMBV.vector.ecef_to_enu(tmx, tmy, tmz,
                                                  [p_lat] * len(p_longs),
                                                  p_longs)
            # take difference with first run
            mx[i, :] = (mx[i, :] - _a) / mx[i, :]
            my[i, :] = (my[i, :] - _b) / my[i, :]
            mz[i, :] = (mz[i, :] - _c) / mz[i, :]

        items = [zvx, zvy, zvz, bx, by, bz, mx, my, mz]
        for item in items:
            assert np.all(item < 1.E-2)

        return
Пример #6
0
 def setup(self):
     """Setup test environment before each function."""
     self.lats, self.longs, self.alts = gen_plot_grid_fixed_alt(550.)
     self.date = dt.datetime(2000, 1, 1)
     return
Пример #7
0
    def test_ecef_geodetic_diff_plots(self):
        """Generate uncertainty plots of ECEF-Geodetic transformations"""
        import matplotlib.pyplot as plt
        import os
        # on_travis = os.environ.get('ONTRAVIS') == 'True'

        p_lats, p_longs, p_alts = gen_plot_grid_fixed_alt(550.)
        # data returned are the locations along each direction
        # the full range of points obtained by iterating over all
        # recasting alts into a more convenient form for later calculation
        p_alts = [p_alts[0]] * len(p_longs)
        # set the date
        date = datetime.datetime(2000, 1, 1)
        # memory for results
        apex_x = np.zeros((len(p_lats), len(p_longs) + 1))
        apex_y = np.zeros((len(p_lats), len(p_longs) + 1))
        apex_z = np.zeros((len(p_lats), len(p_longs) + 1))
        norm_alt = np.zeros((len(p_lats), len(p_longs) + 1))

        # single processor case
        for i, p_lat in enumerate(p_lats):
            print (i, p_lat)
            x, y, z = OMMBV.geodetic_to_ecef([p_lat] * len(p_longs), p_longs, p_alts)
            lat2, lon2, alt2 = OMMBV.ecef_to_geodetic(x, y, z)
            x2, y2, z2 = OMMBV.geodetic_to_ecef(lat2, lon2, alt2)
            apex_x[i, :-1] = np.abs(x2 - x)
            apex_y[i, :-1] = np.abs(y2 - y)
            apex_z[i, :-1] = np.abs(z2 - z)

        # account for periodicity
        apex_x[:, -1] = apex_x[:, 0]
        apex_y[:, -1] = apex_y[:, 0]
        apex_z[:, -1] = apex_z[:, 0]

        ytickarr = np.array([0, 0.25, 0.5, 0.75, 1]) * (len(p_lats) - 1)
        xtickarr = np.array([0, 0.2, 0.4, 0.6, 0.8, 1]) * len(p_longs)
        ytickvals = ['-50', '-25', '0', '25', '50']

        try:
            fig = plt.figure()
            plt.imshow(np.log10(apex_x), origin='lower')
            plt.colorbar()
            plt.yticks(ytickarr, ytickvals)
            plt.xticks(xtickarr, ['0', '72', '144', '216', '288', '360'])
            plt.title('Log ECEF-Geodetic Location Difference (ECEF-x km)')
            plt.xlabel('Geodetic Longitude (Degrees)')
            plt.ylabel('Geodetic Latitude (Degrees)')
            plt.savefig('ecef_geodetic_diff_x.pdf')
            plt.close()

            fig = plt.figure()
            plt.imshow(np.log10(apex_y), origin='lower')
            plt.colorbar()
            plt.yticks(ytickarr, ytickvals)
            plt.xticks(xtickarr, ['0', '72', '144', '216', '288', '360'])
            plt.title('Log ECEF-Geodetic Location Difference (ECEF-y km)')
            plt.xlabel('Geodetic Longitude (Degrees)')
            plt.ylabel('Geodetic Latitude (Degrees)')
            plt.savefig('ecef_geodetic_diff_y.pdf')
            plt.close()

            fig = plt.figure()
            plt.imshow(np.log10(apex_z), origin='lower')
            plt.colorbar()
            plt.yticks(ytickarr, ytickvals)
            plt.xticks(xtickarr, ['0', '72', '144', '216', '288', '360'])
            plt.title('Log ECEF-Geodetic Location Difference (ECEF-z km)')
            plt.xlabel('Geodetic Longitude (Degrees)')
            plt.ylabel('Geodetic Latitude (Degrees)')
            plt.savefig('ecef_geodetic_diff_z.pdf')
            plt.close()

        except:
            pass